mirror of https://github.com/sm64pc/sm64pc.git
Merge branch 'nightly' into master
This commit is contained in:
commit
29bfb1b9b8
|
@ -18,6 +18,7 @@ Please contribute **first** to the [nightly branch](https://github.com/sm64pc/sm
|
|||
* An option to disable drawing distances. (Activate with `make NODRAWINGDISTANCE=1`.)
|
||||
* In-game control binding, currently available on the `testing` branch.
|
||||
* Skip introductory Peach & Lakitu cutscenes with the `--skip-intro` CLI option
|
||||
* Cheats menu in Options. (Activate with `--cheats`) Please note that if a cheat asks you to press "L" it's referring to the N64 button. Check your bindings and make sure you have the "L" button mapped to a button in your controller.
|
||||
|
||||
## Building
|
||||
For building instructions, please refer to the [wiki](https://github.com/sm64pc/sm64pc/wiki).
|
||||
|
|
|
@ -11,8 +11,9 @@ Ejecuta `./extract_assets.py --clean && make clean` o `make distclean` para borr
|
|||
* Soporte nativo para mandos XInput. En Linux, se ha confirmado que el DualShock 4 funciona sin más.
|
||||
* Cámara analógica y cámara controlada con el ratón. (Se activa con `make BETTERCAMERA=1`.)
|
||||
* Opción para desactivar el límite de distancia de renderizado. (Se activa con `make NODRAWINGDISTANCE=1`.)
|
||||
* Configurar los controles desde el juego, actualmente solo en la rama `testing`.
|
||||
* Posibilidad de saltarte la intro con la opción de línea de comandos `--skip-intro`, actualmente solo en las ramas `testing` y `skip-intro`.
|
||||
* Configurar los controles desde el juego.
|
||||
* Posibilidad de saltarte la intro con la opción de línea de comandos `--skip-intro`
|
||||
* Menú de trucos (_cheats_) en _options_. (Se activa con la opción de línea de comandos `--cheats`) Ten en cuenta que si un cheat te pide pulsar el botón "L", se refiere al botón de N64, el cual tendrá que estar asignado a un botón de tu mando. Ve a los ajustes de control y asegúrate de que tienes "L" mapeado a un botón de tu mando.
|
||||
|
||||
## Compilar en Windows
|
||||
**No intentes compilar ejecutables para Windows bajo Linux usando `WINDOWS_BUILD=1`. No va a funcionar. Sigue la guía.**
|
||||
|
|
|
@ -2107,7 +2107,7 @@ const Gfx dl_hud_img_load_tex_block[] = {
|
|||
gsDPSetTile(G_IM_FMT_RGBA, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, G_TX_WRAP | G_TX_NOMIRROR, 4, G_TX_NOLOD, G_TX_WRAP | G_TX_NOMIRROR, 4, G_TX_NOLOD),
|
||||
gsDPLoadSync(),
|
||||
gsDPLoadBlock(G_TX_LOADTILE, 0, 0, 16 * 16 - 1, CALC_DXT(16, G_IM_SIZ_16b_BYTES)),
|
||||
gsDPSetTile(G_IM_FMT_RGBA, G_IM_SIZ_16b, 4, 0, G_TX_RENDERTILE, 0, G_TX_WRAP | G_TX_NOMIRROR, 4, G_TX_NOLOD, G_TX_WRAP | G_TX_NOMIRROR, 4, G_TX_NOLOD),
|
||||
gsDPSetTile(G_IM_FMT_RGBA, G_IM_SIZ_16b, 4, 0, G_TX_RENDERTILE, 0, G_TX_CLAMP, 4, G_TX_NOLOD, G_TX_CLAMP, 4, G_TX_NOLOD),
|
||||
gsDPSetTileSize(0, 0, 0, (16 - 1) << G_TEXTURE_IMAGE_FRAC, (16 - 1) << G_TEXTURE_IMAGE_FRAC),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
@ -2144,7 +2144,7 @@ const Gfx dl_rgba16_load_tex_block[] = {
|
|||
gsDPSetTile(G_IM_FMT_RGBA, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, G_TX_WRAP | G_TX_NOMIRROR, 4, G_TX_NOLOD, G_TX_WRAP | G_TX_NOMIRROR, 4, G_TX_NOLOD),
|
||||
gsDPLoadSync(),
|
||||
gsDPLoadBlock(G_TX_LOADTILE, 0, 0, 16 * 16 - 1, CALC_DXT(16, G_IM_SIZ_16b_BYTES)),
|
||||
gsDPSetTile(G_IM_FMT_RGBA, G_IM_SIZ_16b, 4, 0, G_TX_RENDERTILE, 0, G_TX_WRAP | G_TX_NOMIRROR, 4, G_TX_NOLOD, G_TX_WRAP | G_TX_NOMIRROR, 4, G_TX_NOLOD),
|
||||
gsDPSetTile(G_IM_FMT_RGBA, G_IM_SIZ_16b, 4, 0, G_TX_RENDERTILE, 0, G_TX_CLAMP, 4, G_TX_NOLOD, G_TX_CLAMP, 4, G_TX_NOLOD),
|
||||
gsDPSetTileSize(0, 0, 0, (16 - 1) << G_TEXTURE_IMAGE_FRAC, (16 - 1) << G_TEXTURE_IMAGE_FRAC),
|
||||
gsSPEndDisplayList(),
|
||||
};
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#define TEXT_OPT_NEAREST _("Nearest")
|
||||
#define TEXT_OPT_LINEAR _("Linear")
|
||||
#define TEXT_OPT_MVOLUME _("Master Volume")
|
||||
#define TEXT_OPT_VSYNC _("Vertical Sync")
|
||||
#define TEXT_OPT_DOUBLE _("Double")
|
||||
#define TEXT_RESET_WINDOW _("Reset Window")
|
||||
|
||||
#define TEXT_OPT_UNBOUND _("NONE")
|
||||
|
|
|
@ -72,7 +72,9 @@ static const u8 optsVideoStr[][32] = {
|
|||
{ TEXT_OPT_TEXFILTER },
|
||||
{ TEXT_OPT_NEAREST },
|
||||
{ TEXT_OPT_LINEAR },
|
||||
{ TEXT_RESET_WINDOW }
|
||||
{ TEXT_RESET_WINDOW },
|
||||
{ TEXT_OPT_VSYNC },
|
||||
{ TEXT_OPT_DOUBLE },
|
||||
};
|
||||
|
||||
static const u8 optsAudioStr[][32] = {
|
||||
|
@ -115,6 +117,12 @@ static const u8 *filterChoices[] = {
|
|||
optsVideoStr[3],
|
||||
};
|
||||
|
||||
static const u8 *vsyncChoices[] = {
|
||||
toggleStr[0],
|
||||
toggleStr[1],
|
||||
optsVideoStr[6],
|
||||
};
|
||||
|
||||
enum OptType {
|
||||
OPT_INVALID = 0,
|
||||
OPT_TOGGLE,
|
||||
|
@ -181,8 +189,12 @@ static void optmenu_act_exit(UNUSED struct Option *self, s32 arg) {
|
|||
if (!arg) game_exit(); // only exit on A press and not directions
|
||||
}
|
||||
|
||||
static void optvide_reset_window(UNUSED struct Option *self, s32 arg) {
|
||||
if (!arg) configWindow.reset = true;; // Restrict reset to A press and not directions
|
||||
static void optvideo_reset_window(UNUSED struct Option *self, s32 arg) {
|
||||
if (!arg) {
|
||||
// Restrict reset to A press and not directions
|
||||
configWindow.reset = true;
|
||||
configWindow.settings_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* submenu option lists */
|
||||
|
@ -220,8 +232,9 @@ static struct Option optsControls[] = {
|
|||
|
||||
static struct Option optsVideo[] = {
|
||||
DEF_OPT_TOGGLE( optsVideoStr[0], &configWindow.fullscreen ),
|
||||
DEF_OPT_CHOICE( optsVideoStr[5], &configWindow.vsync, vsyncChoices ),
|
||||
DEF_OPT_CHOICE( optsVideoStr[1], &configFiltering, filterChoices ),
|
||||
DEF_OPT_BUTTON( optsVideoStr[4], optvide_reset_window ),
|
||||
DEF_OPT_BUTTON( optsVideoStr[4], optvideo_reset_window ),
|
||||
};
|
||||
|
||||
static struct Option optsAudio[] = {
|
||||
|
@ -233,11 +246,11 @@ static struct Option optsCheats[] = {
|
|||
DEF_OPT_TOGGLE( optsCheatsStr[1], &Cheats.MoonJump ),
|
||||
DEF_OPT_TOGGLE( optsCheatsStr[2], &Cheats.GodMode ),
|
||||
DEF_OPT_TOGGLE( optsCheatsStr[3], &Cheats.InfiniteLives ),
|
||||
DEF_OPT_TOGGLE( optsCheatsStr[4], &Cheats.SuperSpeed),
|
||||
DEF_OPT_TOGGLE( optsCheatsStr[5], &Cheats.Responsive),
|
||||
DEF_OPT_TOGGLE( optsCheatsStr[6], &Cheats.ExitAnywhere),
|
||||
DEF_OPT_TOGGLE( optsCheatsStr[7], &Cheats.HugeMario),
|
||||
DEF_OPT_TOGGLE( optsCheatsStr[8], &Cheats.TinyMario),
|
||||
DEF_OPT_TOGGLE( optsCheatsStr[4], &Cheats.SuperSpeed ),
|
||||
DEF_OPT_TOGGLE( optsCheatsStr[5], &Cheats.Responsive ),
|
||||
DEF_OPT_TOGGLE( optsCheatsStr[6], &Cheats.ExitAnywhere ),
|
||||
DEF_OPT_TOGGLE( optsCheatsStr[7], &Cheats.HugeMario ),
|
||||
DEF_OPT_TOGGLE( optsCheatsStr[8], &Cheats.TinyMario ),
|
||||
|
||||
};
|
||||
|
||||
|
@ -261,8 +274,8 @@ static struct Option optsMain[] = {
|
|||
DEF_OPT_SUBMENU( menuStr[6], &menuVideo ),
|
||||
DEF_OPT_SUBMENU( menuStr[7], &menuAudio ),
|
||||
DEF_OPT_BUTTON ( menuStr[8], optmenu_act_exit ),
|
||||
DEF_OPT_SUBMENU( menuStr[9], &menuCheats ),
|
||||
|
||||
// NOTE: always keep cheats the last option here because of the half-assed way I toggle them
|
||||
DEF_OPT_SUBMENU( menuStr[9], &menuCheats )
|
||||
};
|
||||
|
||||
static struct SubMenu menuMain = DEF_SUBMENU( menuStr[3], optsMain );
|
||||
|
@ -452,6 +465,17 @@ void optmenu_toggle(void) {
|
|||
#ifndef nosound
|
||||
play_sound(SOUND_MENU_CHANGE_SELECT, gDefaultSoundArgs);
|
||||
#endif
|
||||
|
||||
// HACK: hide the last option in main if cheats are disabled
|
||||
menuMain.numOpts = sizeof(optsMain) / sizeof(optsMain[0]);
|
||||
if (!Cheats.EnableCheats) {
|
||||
menuMain.numOpts--;
|
||||
if (menuMain.select >= menuMain.numOpts) {
|
||||
menuMain.select = 0; // don't bother
|
||||
menuMain.scroll = 0;
|
||||
}
|
||||
}
|
||||
|
||||
currentMenu = &menuMain;
|
||||
optmenu_open = 1;
|
||||
} else {
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
#include "cheats.h"
|
||||
|
||||
struct CheatList Cheats;
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#ifndef _CHEATS_H
|
||||
#define _CHEATS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct CheatList
|
||||
{
|
||||
struct CheatList {
|
||||
bool EnableCheats;
|
||||
bool MoonJump;
|
||||
bool GodMode;
|
||||
|
@ -14,3 +16,5 @@ struct CheatList
|
|||
};
|
||||
|
||||
extern struct CheatList Cheats;
|
||||
|
||||
#endif // _CHEATS_H
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
#include "cliopts.h"
|
||||
#include "configfile.h"
|
||||
#include "cheats.h"
|
||||
#include "pc_main.h"
|
||||
|
||||
#include <strings.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
@ -6,51 +10,46 @@
|
|||
|
||||
struct PCCLIOptions gCLIOpts;
|
||||
|
||||
void parse_cli_opts(int argc, char* argv[])
|
||||
{
|
||||
// Initialize options with false values.
|
||||
gCLIOpts.SkipIntro = 0;
|
||||
gCLIOpts.FullScreen = 0;
|
||||
gCLIOpts.ConfigFile = malloc(31);
|
||||
strncpy(gCLIOpts.ConfigFile, "sm64config.txt", strlen("sm64config.txt"));
|
||||
gCLIOpts.ConfigFile[strlen("sm64config.txt")] = '\0';
|
||||
|
||||
// Scan arguments for options
|
||||
if (argc > 1)
|
||||
{
|
||||
int i;
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (strcmp(argv[i], "--skip-intro") == 0) // Skip Peach Intro
|
||||
gCLIOpts.SkipIntro = 1;
|
||||
|
||||
if (strcmp(argv[i], "--fullscreen") == 0) // Open game in fullscreen
|
||||
gCLIOpts.FullScreen = 1;
|
||||
|
||||
if (strcmp(argv[i], "--windowed") == 0) // Open game in windowed mode
|
||||
gCLIOpts.FullScreen = 2;
|
||||
|
||||
if (strcmp(argv[i], "--help") == 0) // Print help
|
||||
{
|
||||
static void print_help(void) {
|
||||
printf("Super Mario 64 PC Port\n");
|
||||
printf("%-20s\tSkips the Peach and Castle intro when starting a new game.\n", "--skip-intro");
|
||||
printf("%-20s\tStarts the game in full screen mode.\n", "--fullscreen");
|
||||
printf("%-20s\tStarts the game in windowed mode.\n", "--windowed");
|
||||
printf("%-20s\tSaves the configuration file as CONFIGNAME.\n", "--configfile CONFIGNAME");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void parse_cli_opts(int argc, char* argv[]) {
|
||||
// Initialize options with false values.
|
||||
memset(&gCLIOpts, 0, sizeof(gCLIOpts));
|
||||
strncpy(gCLIOpts.ConfigFile, CONFIGFILE_DEFAULT, sizeof(gCLIOpts.ConfigFile));
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "--skip-intro") == 0) // Skip Peach Intro
|
||||
gCLIOpts.SkipIntro = 1;
|
||||
|
||||
else if (strcmp(argv[i], "--fullscreen") == 0) // Open game in fullscreen
|
||||
gCLIOpts.FullScreen = 1;
|
||||
|
||||
else if (strcmp(argv[i], "--windowed") == 0) // Open game in windowed mode
|
||||
gCLIOpts.FullScreen = 2;
|
||||
|
||||
else if (strcmp(argv[i], "--cheats") == 0) // Enable cheats menu
|
||||
Cheats.EnableCheats = true;
|
||||
|
||||
// Print help
|
||||
else if (strcmp(argv[i], "--help") == 0) {
|
||||
print_help();
|
||||
game_exit();
|
||||
}
|
||||
|
||||
if (strncmp(argv[i], "--configfile", strlen("--configfile")) == 0)
|
||||
{
|
||||
if (i+1 < argc)
|
||||
{
|
||||
if (strlen(argv[i]) > 30) {
|
||||
else if (strcmp(argv[i], "--configfile") == 0) {
|
||||
if (i+1 < argc) {
|
||||
const unsigned int arglen = strlen(argv[i+1]);
|
||||
if (arglen >= sizeof(gCLIOpts.ConfigFile)) {
|
||||
fprintf(stderr, "Configuration file supplied has a name too long.\n");
|
||||
} else {
|
||||
memset(gCLIOpts.ConfigFile, 0, 30);
|
||||
strncpy(gCLIOpts.ConfigFile, argv[i+1], strlen(argv[i+1]));
|
||||
gCLIOpts.ConfigFile[strlen(argv[i+1])] = '\0';
|
||||
}
|
||||
strncpy(gCLIOpts.ConfigFile, argv[i+1], arglen);
|
||||
gCLIOpts.ConfigFile[arglen] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
#include "sm64.h"
|
||||
#ifndef _CLIOPTS_H
|
||||
#define _CLIOPTS_H
|
||||
|
||||
struct PCCLIOptions
|
||||
{
|
||||
u8 SkipIntro;
|
||||
u8 FullScreen;
|
||||
char * ConfigFile;
|
||||
struct PCCLIOptions {
|
||||
unsigned int SkipIntro;
|
||||
unsigned int FullScreen;
|
||||
char ConfigFile[1024];
|
||||
};
|
||||
|
||||
extern struct PCCLIOptions gCLIOpts;
|
||||
|
||||
void parse_cli_opts(int argc, char* argv[]);
|
||||
|
||||
#endif // _CLIOPTS_H
|
||||
|
|
|
@ -40,10 +40,11 @@ ConfigWindow configWindow = {
|
|||
.y = SDL_WINDOWPOS_CENTERED,
|
||||
.w = DESIRED_SCREEN_WIDTH,
|
||||
.h = DESIRED_SCREEN_HEIGHT,
|
||||
.vsync = 1,
|
||||
.reset = false,
|
||||
.vsync = false,
|
||||
.fullscreen = false,
|
||||
.exiting_fullscreen = false,
|
||||
.settings_changed = false,
|
||||
};
|
||||
unsigned int configFiltering = 1; // 0=force nearest, 1=linear, (TODO) 2=three-point
|
||||
unsigned int configMasterVolume = MAX_VOLUME; // 0 - MAX_VOLUME
|
||||
|
@ -84,6 +85,7 @@ static const struct ConfigOption options[] = {
|
|||
{.name = "window_y", .type = CONFIG_TYPE_UINT, .uintValue = &configWindow.y},
|
||||
{.name = "window_w", .type = CONFIG_TYPE_UINT, .uintValue = &configWindow.w},
|
||||
{.name = "window_h", .type = CONFIG_TYPE_UINT, .uintValue = &configWindow.h},
|
||||
{.name = "vsync", .type = CONFIG_TYPE_UINT, .uintValue = &configWindow.vsync},
|
||||
{.name = "texture_filtering", .type = CONFIG_TYPE_UINT, .uintValue = &configFiltering},
|
||||
{.name = "master_volume", .type = CONFIG_TYPE_UINT, .uintValue = &configMasterVolume},
|
||||
{.name = "key_a", .type = CONFIG_TYPE_BIND, .uintValue = configKeyA},
|
||||
|
|
|
@ -3,16 +3,19 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define CONFIGFILE_DEFAULT "sm64config.txt"
|
||||
|
||||
#define MAX_BINDS 3
|
||||
#define MAX_VOLUME 127
|
||||
#define VOLUME_SHIFT 7
|
||||
|
||||
typedef struct {
|
||||
unsigned int x, y, w, h;
|
||||
unsigned int vsync;
|
||||
bool reset;
|
||||
bool vsync;
|
||||
bool fullscreen;
|
||||
bool exiting_fullscreen;
|
||||
bool settings_changed;
|
||||
} ConfigWindow;
|
||||
|
||||
extern ConfigWindow configWindow;
|
||||
|
|
|
@ -39,9 +39,12 @@
|
|||
# define FRAMERATE 30
|
||||
#endif
|
||||
|
||||
static const Uint32 FRAME_TIME = 1000 / FRAMERATE;
|
||||
|
||||
static SDL_Window *wnd;
|
||||
static SDL_GLContext ctx = NULL;
|
||||
static int inverted_scancode_table[512];
|
||||
static Uint32 frame_start = 0;
|
||||
|
||||
const SDL_Scancode windows_scancode_table[] =
|
||||
{
|
||||
|
@ -110,9 +113,9 @@ static void gfx_sdl_set_fullscreen() {
|
|||
}
|
||||
|
||||
static void gfx_sdl_reset_dimension_and_pos() {
|
||||
if (configWindow.exiting_fullscreen)
|
||||
if (configWindow.exiting_fullscreen) {
|
||||
configWindow.exiting_fullscreen = false;
|
||||
else if (configWindow.reset) {
|
||||
} else if (configWindow.reset) {
|
||||
configWindow.x = SDL_WINDOWPOS_CENTERED;
|
||||
configWindow.y = SDL_WINDOWPOS_CENTERED;
|
||||
configWindow.w = DESIRED_SCREEN_WIDTH;
|
||||
|
@ -123,29 +126,14 @@ static void gfx_sdl_reset_dimension_and_pos() {
|
|||
configWindow.fullscreen = false;
|
||||
return;
|
||||
}
|
||||
} else
|
||||
} else if (!configWindow.settings_changed) {
|
||||
return;
|
||||
}
|
||||
|
||||
configWindow.settings_changed = false;
|
||||
SDL_SetWindowSize(wnd, configWindow.w, configWindow.h);
|
||||
SDL_SetWindowPosition(wnd, configWindow.x, configWindow.y);
|
||||
}
|
||||
|
||||
static bool test_vsync(void) {
|
||||
// Even if SDL_GL_SetSwapInterval succeeds, it doesn't mean that VSync actually works.
|
||||
// A 60 Hz monitor should have a swap interval of 16.67 milliseconds.
|
||||
// If it takes less than 12 milliseconds, assume that VSync is not working.
|
||||
// SDL_GetTicks() probably does not offer enough precision for this kind of shit.
|
||||
Uint32 start, end;
|
||||
|
||||
// do an extra swap, sometimes the first one takes longer (maybe creates buffers?)
|
||||
SDL_GL_SwapWindow(wnd);
|
||||
|
||||
SDL_GL_SwapWindow(wnd);
|
||||
start = SDL_GetTicks();
|
||||
SDL_GL_SwapWindow(wnd);
|
||||
end = SDL_GetTicks();
|
||||
|
||||
return (end - start >= 12);
|
||||
SDL_GL_SetSwapInterval(configWindow.vsync); // in case vsync changed
|
||||
}
|
||||
|
||||
static void gfx_sdl_init(void) {
|
||||
|
@ -165,11 +153,9 @@ static void gfx_sdl_init(void) {
|
|||
|
||||
if (gCLIOpts.FullScreen == 1)
|
||||
configWindow.fullscreen = true;
|
||||
|
||||
if (gCLIOpts.FullScreen == 2)
|
||||
else if (gCLIOpts.FullScreen == 2)
|
||||
configWindow.fullscreen = false;
|
||||
|
||||
|
||||
const char* window_title =
|
||||
#ifndef USE_GLES
|
||||
"Super Mario 64 PC port (OpenGL)";
|
||||
|
@ -183,14 +169,11 @@ static void gfx_sdl_init(void) {
|
|||
SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE
|
||||
);
|
||||
ctx = SDL_GL_CreateContext(wnd);
|
||||
SDL_GL_SetSwapInterval(2);
|
||||
|
||||
SDL_GL_SetSwapInterval(configWindow.vsync);
|
||||
|
||||
gfx_sdl_set_fullscreen();
|
||||
|
||||
configWindow.vsync = test_vsync();
|
||||
if (!configWindow.vsync)
|
||||
printf("Warning: VSync is not enabled or not working. Falling back to timer for synchronization\n");
|
||||
|
||||
for (size_t i = 0; i < sizeof(windows_scancode_table) / sizeof(SDL_Scancode); i++) {
|
||||
inverted_scancode_table[windows_scancode_table[i]] = i;
|
||||
}
|
||||
|
@ -206,8 +189,14 @@ static void gfx_sdl_init(void) {
|
|||
}
|
||||
|
||||
static void gfx_sdl_main_loop(void (*run_one_game_iter)(void)) {
|
||||
while (1)
|
||||
Uint32 t;
|
||||
while (1) {
|
||||
t = SDL_GetTicks();
|
||||
run_one_game_iter();
|
||||
t = SDL_GetTicks() - t;
|
||||
if (t < FRAME_TIME && configWindow.vsync <= 1)
|
||||
SDL_Delay(FRAME_TIME - t);
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_sdl_get_dimensions(uint32_t *width, uint32_t *height) {
|
||||
|
@ -275,24 +264,11 @@ static void gfx_sdl_handle_events(void) {
|
|||
}
|
||||
|
||||
static bool gfx_sdl_start_frame(void) {
|
||||
frame_start = SDL_GetTicks();
|
||||
return true;
|
||||
}
|
||||
|
||||
static void sync_framerate_with_timer(void) {
|
||||
// Number of milliseconds a frame should take (30 fps)
|
||||
const Uint32 FRAME_TIME = 1000 / FRAMERATE;
|
||||
static Uint32 last_time;
|
||||
|
||||
Uint32 elapsed = SDL_GetTicks() - last_time;
|
||||
if (elapsed < FRAME_TIME)
|
||||
SDL_Delay(FRAME_TIME - elapsed);
|
||||
|
||||
last_time = SDL_GetTicks();
|
||||
}
|
||||
|
||||
static void gfx_sdl_swap_buffers_begin(void) {
|
||||
if (!configWindow.vsync)
|
||||
sync_framerate_with_timer();
|
||||
SDL_GL_SwapWindow(wnd);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue