From 1ede50c1a541e8843773a68e0d29e9d244e68957 Mon Sep 17 00:00:00 2001 From: Alex Burnett Date: Mon, 18 May 2020 03:34:27 -0700 Subject: [PATCH 01/15] Fix text being wrapped in fullscreen --- bin/segment2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/segment2.c b/bin/segment2.c index d7e807fd..5d5398aa 100644 --- a/bin/segment2.c +++ b/bin/segment2.c @@ -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(), }; From 2bd840a299ec0298e8eef57c0485eaaca57233ad Mon Sep 17 00:00:00 2001 From: fgsfds Date: Mon, 18 May 2020 23:03:04 +0300 Subject: [PATCH 02/15] (hopefully) fix the timing crap; add vsync option --- include/text_strings.h.in | 2 ++ src/game/options_menu.c | 27 ++++++++++++++------ src/pc/configfile.c | 4 ++- src/pc/configfile.h | 3 ++- src/pc/gfx/gfx_sdl2.c | 53 ++++++++++++--------------------------- 5 files changed, 43 insertions(+), 46 deletions(-) diff --git a/include/text_strings.h.in b/include/text_strings.h.in index 06173692..b77a51ca 100644 --- a/include/text_strings.h.in +++ b/include/text_strings.h.in @@ -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") diff --git a/src/game/options_menu.c b/src/game/options_menu.c index b9033bee..7b8d9f74 100644 --- a/src/game/options_menu.c +++ b/src/game/options_menu.c @@ -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] = { @@ -112,6 +114,12 @@ static const u8 *filterChoices[] = { optsVideoStr[3], }; +static const u8 *vsyncChoices[] = { + toggleStr[0], + toggleStr[1], + optsVideoStr[6], +}; + enum OptType { OPT_INVALID = 0, OPT_TOGGLE, @@ -178,8 +186,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 */ @@ -217,8 +229,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[] = { @@ -230,8 +243,8 @@ 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[4], &Cheats.SuperSpeed ), + DEF_OPT_TOGGLE( optsCheatsStr[5], &Cheats.Responsive ), }; @@ -243,7 +256,7 @@ static struct SubMenu menuCamera = DEF_SUBMENU( menuStr[4], optsCamera ); static struct SubMenu menuControls = DEF_SUBMENU( menuStr[5], optsControls ); static struct SubMenu menuVideo = DEF_SUBMENU( menuStr[6], optsVideo ); static struct SubMenu menuAudio = DEF_SUBMENU( menuStr[7], optsAudio ); -static struct SubMenu menuCheats = DEF_SUBMENU( menuStr[9], optsCheats ); +static struct SubMenu menuCheats = DEF_SUBMENU( menuStr[9], optsCheats ); /* main options menu definition */ diff --git a/src/pc/configfile.c b/src/pc/configfile.c index 0b6fe370..ce9a08ad 100644 --- a/src/pc/configfile.c +++ b/src/pc/configfile.c @@ -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}, diff --git a/src/pc/configfile.h b/src/pc/configfile.h index 4343ebdc..5238b17c 100644 --- a/src/pc/configfile.h +++ b/src/pc/configfile.h @@ -9,10 +9,11 @@ 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; diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c index 363d9209..cc660d79 100644 --- a/src/pc/gfx/gfx_sdl2.c +++ b/src/pc/gfx/gfx_sdl2.c @@ -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; } @@ -275,23 +258,19 @@ 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; + Uint32 elapsed = SDL_GetTicks() - frame_start; if (elapsed < FRAME_TIME) SDL_Delay(FRAME_TIME - elapsed); - - last_time = SDL_GetTicks(); } static void gfx_sdl_swap_buffers_begin(void) { - if (!configWindow.vsync) + // if vsync is set to 2, depend only on SwapInterval to sync + if (configWindow.vsync <= 1) sync_framerate_with_timer(); SDL_GL_SwapWindow(wnd); } From 952495ae085d900213f3f88d4bf7209733d06ab5 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Mon, 18 May 2020 23:31:19 +0300 Subject: [PATCH 03/15] clean up cliopts --- src/pc/cliopts.c | 93 +++++++++++++++++++++------------------------ src/pc/cliopts.h | 14 ++++--- src/pc/configfile.h | 2 + 3 files changed, 54 insertions(+), 55 deletions(-) diff --git a/src/pc/cliopts.c b/src/pc/cliopts.c index ee9bc13e..234660b2 100644 --- a/src/pc/cliopts.c +++ b/src/pc/cliopts.c @@ -1,4 +1,7 @@ #include "cliopts.h" +#include "configfile.h" +#include "pc_main.h" + #include #include #include @@ -6,53 +9,45 @@ 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 - { - 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); - } - - if (strncmp(argv[i], "--configfile", strlen("--configfile")) == 0) - { - if (i+1 < argc) - { - if (strlen(argv[i]) > 30) { - 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'; - } - } - } - } - } +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"); +} + +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; + + // Print help + else if (strcmp(argv[i], "--help") == 0) { + print_help(); + game_exit(); + } + + 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 { + strncpy(gCLIOpts.ConfigFile, argv[i+1], arglen); + gCLIOpts.ConfigFile[arglen] = '\0'; + } + } + } + } } diff --git a/src/pc/cliopts.h b/src/pc/cliopts.h index 1844c44c..d20dcb4f 100644 --- a/src/pc/cliopts.h +++ b/src/pc/cliopts.h @@ -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 diff --git a/src/pc/configfile.h b/src/pc/configfile.h index 5238b17c..cafd272f 100644 --- a/src/pc/configfile.h +++ b/src/pc/configfile.h @@ -3,6 +3,8 @@ #include +#define CONFIGFILE_DEFAULT "sm64config.txt" + #define MAX_BINDS 3 #define MAX_VOLUME 127 #define VOLUME_SHIFT 7 From 36cef2ef5d26b4738d9607cfff1c71ecf19ac565 Mon Sep 17 00:00:00 2001 From: Leon422 Date: Mon, 18 May 2020 22:10:37 +0100 Subject: [PATCH 04/15] Added the cheats menu to the list of features --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 1ba69773..dadc0b7e 100644 --- a/README.md +++ b/README.md @@ -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, accessible from the "Options" menu. 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). From 7ad1b1f12bd7bbb914385c9accb703fce8452962 Mon Sep 17 00:00:00 2001 From: Leon422 Date: Mon, 18 May 2020 22:13:00 +0100 Subject: [PATCH 05/15] *commits in Spanish* --- README_es_ES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README_es_ES.md b/README_es_ES.md index 7426486c..02ac0b47 100644 --- a/README_es_ES.md +++ b/README_es_ES.md @@ -13,6 +13,7 @@ Ejecuta `./extract_assets.py --clean && make clean` o `make distclean` para borr * 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`. + * Menú de trucos, al cual se accede a través del menú "Options". 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.** From 1d9398abb399c46814d7873a9df03a17ff6c7d4d Mon Sep 17 00:00:00 2001 From: Leon422 Date: Mon, 18 May 2020 22:15:06 +0100 Subject: [PATCH 06/15] *commits in Spanish again* Added the cheats menu to the feature list, and updated the feature list in general to match the English version. --- README_es_ES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README_es_ES.md b/README_es_ES.md index 02ac0b47..fa7ba3ca 100644 --- a/README_es_ES.md +++ b/README_es_ES.md @@ -11,8 +11,8 @@ 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, al cual se accede a través del menú "Options". 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 From c3c2451c6a9d8417e1e7f83ddac3a85e34949b28 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Mon, 18 May 2020 23:03:04 +0300 Subject: [PATCH 07/15] Revert "(hopefully) fix the timing crap; add vsync option" This reverts commit 2bd840a299ec0298e8eef57c0485eaaca57233ad. --- include/text_strings.h.in | 2 -- src/game/options_menu.c | 27 ++++++-------------- src/pc/configfile.c | 4 +-- src/pc/configfile.h | 3 +-- src/pc/gfx/gfx_sdl2.c | 53 +++++++++++++++++++++++++++------------ 5 files changed, 46 insertions(+), 43 deletions(-) diff --git a/include/text_strings.h.in b/include/text_strings.h.in index b77a51ca..06173692 100644 --- a/include/text_strings.h.in +++ b/include/text_strings.h.in @@ -27,8 +27,6 @@ #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") diff --git a/src/game/options_menu.c b/src/game/options_menu.c index 7b8d9f74..b9033bee 100644 --- a/src/game/options_menu.c +++ b/src/game/options_menu.c @@ -72,9 +72,7 @@ static const u8 optsVideoStr[][32] = { { TEXT_OPT_TEXFILTER }, { TEXT_OPT_NEAREST }, { TEXT_OPT_LINEAR }, - { TEXT_RESET_WINDOW }, - { TEXT_OPT_VSYNC }, - { TEXT_OPT_DOUBLE }, + { TEXT_RESET_WINDOW } }; static const u8 optsAudioStr[][32] = { @@ -114,12 +112,6 @@ static const u8 *filterChoices[] = { optsVideoStr[3], }; -static const u8 *vsyncChoices[] = { - toggleStr[0], - toggleStr[1], - optsVideoStr[6], -}; - enum OptType { OPT_INVALID = 0, OPT_TOGGLE, @@ -186,12 +178,8 @@ 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 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; - } +static void optvide_reset_window(UNUSED struct Option *self, s32 arg) { + if (!arg) configWindow.reset = true;; // Restrict reset to A press and not directions } /* submenu option lists */ @@ -229,9 +217,8 @@ 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], optvideo_reset_window ), + DEF_OPT_BUTTON( optsVideoStr[4], optvide_reset_window ), }; static struct Option optsAudio[] = { @@ -243,8 +230,8 @@ 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[4], &Cheats.SuperSpeed), + DEF_OPT_TOGGLE( optsCheatsStr[5], &Cheats.Responsive), }; @@ -256,7 +243,7 @@ static struct SubMenu menuCamera = DEF_SUBMENU( menuStr[4], optsCamera ); static struct SubMenu menuControls = DEF_SUBMENU( menuStr[5], optsControls ); static struct SubMenu menuVideo = DEF_SUBMENU( menuStr[6], optsVideo ); static struct SubMenu menuAudio = DEF_SUBMENU( menuStr[7], optsAudio ); -static struct SubMenu menuCheats = DEF_SUBMENU( menuStr[9], optsCheats ); +static struct SubMenu menuCheats = DEF_SUBMENU( menuStr[9], optsCheats ); /* main options menu definition */ diff --git a/src/pc/configfile.c b/src/pc/configfile.c index ce9a08ad..0b6fe370 100644 --- a/src/pc/configfile.c +++ b/src/pc/configfile.c @@ -40,11 +40,10 @@ 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 @@ -85,7 +84,6 @@ 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}, diff --git a/src/pc/configfile.h b/src/pc/configfile.h index cafd272f..01d657c2 100644 --- a/src/pc/configfile.h +++ b/src/pc/configfile.h @@ -11,11 +11,10 @@ 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; diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c index cc660d79..363d9209 100644 --- a/src/pc/gfx/gfx_sdl2.c +++ b/src/pc/gfx/gfx_sdl2.c @@ -39,12 +39,9 @@ # 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[] = { @@ -113,9 +110,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; @@ -126,14 +123,29 @@ static void gfx_sdl_reset_dimension_and_pos() { configWindow.fullscreen = false; return; } - } else if (!configWindow.settings_changed) { + } else return; - } - configWindow.settings_changed = false; SDL_SetWindowSize(wnd, configWindow.w, configWindow.h); SDL_SetWindowPosition(wnd, configWindow.x, configWindow.y); - SDL_GL_SetSwapInterval(configWindow.vsync); // in case vsync changed +} + +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); } static void gfx_sdl_init(void) { @@ -153,9 +165,11 @@ static void gfx_sdl_init(void) { if (gCLIOpts.FullScreen == 1) configWindow.fullscreen = true; - else if (gCLIOpts.FullScreen == 2) + + if (gCLIOpts.FullScreen == 2) configWindow.fullscreen = false; + const char* window_title = #ifndef USE_GLES "Super Mario 64 PC port (OpenGL)"; @@ -169,11 +183,14 @@ static void gfx_sdl_init(void) { SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE ); ctx = SDL_GL_CreateContext(wnd); - - SDL_GL_SetSwapInterval(configWindow.vsync); + SDL_GL_SetSwapInterval(2); 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; } @@ -258,19 +275,23 @@ 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) { - Uint32 elapsed = SDL_GetTicks() - frame_start; + // 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 vsync is set to 2, depend only on SwapInterval to sync - if (configWindow.vsync <= 1) + if (!configWindow.vsync) sync_framerate_with_timer(); SDL_GL_SwapWindow(wnd); } From c6961b8606d63d33c8ffebf001b932b0ddb3ff16 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Mon, 18 May 2020 23:03:04 +0300 Subject: [PATCH 08/15] Revert "(hopefully) fix the timing crap; add vsync option" This reverts commit 2bd840a299ec0298e8eef57c0485eaaca57233ad. --- include/text_strings.h.in | 2 -- src/game/options_menu.c | 27 ++++++-------------- src/pc/configfile.c | 4 +-- src/pc/configfile.h | 3 +-- src/pc/gfx/gfx_sdl2.c | 53 +++++++++++++++++++++++++++------------ 5 files changed, 46 insertions(+), 43 deletions(-) diff --git a/include/text_strings.h.in b/include/text_strings.h.in index b77a51ca..06173692 100644 --- a/include/text_strings.h.in +++ b/include/text_strings.h.in @@ -27,8 +27,6 @@ #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") diff --git a/src/game/options_menu.c b/src/game/options_menu.c index 7b8d9f74..b9033bee 100644 --- a/src/game/options_menu.c +++ b/src/game/options_menu.c @@ -72,9 +72,7 @@ static const u8 optsVideoStr[][32] = { { TEXT_OPT_TEXFILTER }, { TEXT_OPT_NEAREST }, { TEXT_OPT_LINEAR }, - { TEXT_RESET_WINDOW }, - { TEXT_OPT_VSYNC }, - { TEXT_OPT_DOUBLE }, + { TEXT_RESET_WINDOW } }; static const u8 optsAudioStr[][32] = { @@ -114,12 +112,6 @@ static const u8 *filterChoices[] = { optsVideoStr[3], }; -static const u8 *vsyncChoices[] = { - toggleStr[0], - toggleStr[1], - optsVideoStr[6], -}; - enum OptType { OPT_INVALID = 0, OPT_TOGGLE, @@ -186,12 +178,8 @@ 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 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; - } +static void optvide_reset_window(UNUSED struct Option *self, s32 arg) { + if (!arg) configWindow.reset = true;; // Restrict reset to A press and not directions } /* submenu option lists */ @@ -229,9 +217,8 @@ 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], optvideo_reset_window ), + DEF_OPT_BUTTON( optsVideoStr[4], optvide_reset_window ), }; static struct Option optsAudio[] = { @@ -243,8 +230,8 @@ 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[4], &Cheats.SuperSpeed), + DEF_OPT_TOGGLE( optsCheatsStr[5], &Cheats.Responsive), }; @@ -256,7 +243,7 @@ static struct SubMenu menuCamera = DEF_SUBMENU( menuStr[4], optsCamera ); static struct SubMenu menuControls = DEF_SUBMENU( menuStr[5], optsControls ); static struct SubMenu menuVideo = DEF_SUBMENU( menuStr[6], optsVideo ); static struct SubMenu menuAudio = DEF_SUBMENU( menuStr[7], optsAudio ); -static struct SubMenu menuCheats = DEF_SUBMENU( menuStr[9], optsCheats ); +static struct SubMenu menuCheats = DEF_SUBMENU( menuStr[9], optsCheats ); /* main options menu definition */ diff --git a/src/pc/configfile.c b/src/pc/configfile.c index ce9a08ad..0b6fe370 100644 --- a/src/pc/configfile.c +++ b/src/pc/configfile.c @@ -40,11 +40,10 @@ 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 @@ -85,7 +84,6 @@ 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}, diff --git a/src/pc/configfile.h b/src/pc/configfile.h index cafd272f..01d657c2 100644 --- a/src/pc/configfile.h +++ b/src/pc/configfile.h @@ -11,11 +11,10 @@ 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; diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c index cc660d79..363d9209 100644 --- a/src/pc/gfx/gfx_sdl2.c +++ b/src/pc/gfx/gfx_sdl2.c @@ -39,12 +39,9 @@ # 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[] = { @@ -113,9 +110,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; @@ -126,14 +123,29 @@ static void gfx_sdl_reset_dimension_and_pos() { configWindow.fullscreen = false; return; } - } else if (!configWindow.settings_changed) { + } else return; - } - configWindow.settings_changed = false; SDL_SetWindowSize(wnd, configWindow.w, configWindow.h); SDL_SetWindowPosition(wnd, configWindow.x, configWindow.y); - SDL_GL_SetSwapInterval(configWindow.vsync); // in case vsync changed +} + +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); } static void gfx_sdl_init(void) { @@ -153,9 +165,11 @@ static void gfx_sdl_init(void) { if (gCLIOpts.FullScreen == 1) configWindow.fullscreen = true; - else if (gCLIOpts.FullScreen == 2) + + if (gCLIOpts.FullScreen == 2) configWindow.fullscreen = false; + const char* window_title = #ifndef USE_GLES "Super Mario 64 PC port (OpenGL)"; @@ -169,11 +183,14 @@ static void gfx_sdl_init(void) { SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE ); ctx = SDL_GL_CreateContext(wnd); - - SDL_GL_SetSwapInterval(configWindow.vsync); + SDL_GL_SetSwapInterval(2); 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; } @@ -258,19 +275,23 @@ 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) { - Uint32 elapsed = SDL_GetTicks() - frame_start; + // 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 vsync is set to 2, depend only on SwapInterval to sync - if (configWindow.vsync <= 1) + if (!configWindow.vsync) sync_framerate_with_timer(); SDL_GL_SwapWindow(wnd); } From 59913a9beb3d902d277377663610a4813167ef26 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Tue, 19 May 2020 01:25:59 +0300 Subject: [PATCH 09/15] Revert "Revert "(hopefully) fix the timing crap; add vsync option"" This reverts commit c6961b8606d63d33c8ffebf001b932b0ddb3ff16. --- include/text_strings.h.in | 2 ++ src/game/options_menu.c | 27 ++++++++++++++------ src/pc/configfile.c | 4 ++- src/pc/configfile.h | 3 ++- src/pc/gfx/gfx_sdl2.c | 53 ++++++++++++--------------------------- 5 files changed, 43 insertions(+), 46 deletions(-) diff --git a/include/text_strings.h.in b/include/text_strings.h.in index 06173692..b77a51ca 100644 --- a/include/text_strings.h.in +++ b/include/text_strings.h.in @@ -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") diff --git a/src/game/options_menu.c b/src/game/options_menu.c index b9033bee..7b8d9f74 100644 --- a/src/game/options_menu.c +++ b/src/game/options_menu.c @@ -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] = { @@ -112,6 +114,12 @@ static const u8 *filterChoices[] = { optsVideoStr[3], }; +static const u8 *vsyncChoices[] = { + toggleStr[0], + toggleStr[1], + optsVideoStr[6], +}; + enum OptType { OPT_INVALID = 0, OPT_TOGGLE, @@ -178,8 +186,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 */ @@ -217,8 +229,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[] = { @@ -230,8 +243,8 @@ 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[4], &Cheats.SuperSpeed ), + DEF_OPT_TOGGLE( optsCheatsStr[5], &Cheats.Responsive ), }; @@ -243,7 +256,7 @@ static struct SubMenu menuCamera = DEF_SUBMENU( menuStr[4], optsCamera ); static struct SubMenu menuControls = DEF_SUBMENU( menuStr[5], optsControls ); static struct SubMenu menuVideo = DEF_SUBMENU( menuStr[6], optsVideo ); static struct SubMenu menuAudio = DEF_SUBMENU( menuStr[7], optsAudio ); -static struct SubMenu menuCheats = DEF_SUBMENU( menuStr[9], optsCheats ); +static struct SubMenu menuCheats = DEF_SUBMENU( menuStr[9], optsCheats ); /* main options menu definition */ diff --git a/src/pc/configfile.c b/src/pc/configfile.c index 0b6fe370..ce9a08ad 100644 --- a/src/pc/configfile.c +++ b/src/pc/configfile.c @@ -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}, diff --git a/src/pc/configfile.h b/src/pc/configfile.h index 01d657c2..cafd272f 100644 --- a/src/pc/configfile.h +++ b/src/pc/configfile.h @@ -11,10 +11,11 @@ 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; diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c index 363d9209..cc660d79 100644 --- a/src/pc/gfx/gfx_sdl2.c +++ b/src/pc/gfx/gfx_sdl2.c @@ -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; } @@ -275,23 +258,19 @@ 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; + Uint32 elapsed = SDL_GetTicks() - frame_start; if (elapsed < FRAME_TIME) SDL_Delay(FRAME_TIME - elapsed); - - last_time = SDL_GetTicks(); } static void gfx_sdl_swap_buffers_begin(void) { - if (!configWindow.vsync) + // if vsync is set to 2, depend only on SwapInterval to sync + if (configWindow.vsync <= 1) sync_framerate_with_timer(); SDL_GL_SwapWindow(wnd); } From 6a79a9af99748b6caad82377a3eb1929205c3df6 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Tue, 19 May 2020 01:32:49 +0300 Subject: [PATCH 10/15] bring back the old frame timing method (if vsync != 2) --- src/pc/gfx/gfx_sdl2.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c index cc660d79..e86a100c 100644 --- a/src/pc/gfx/gfx_sdl2.c +++ b/src/pc/gfx/gfx_sdl2.c @@ -189,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) { @@ -262,16 +268,7 @@ static bool gfx_sdl_start_frame(void) { return true; } -static void sync_framerate_with_timer(void) { - Uint32 elapsed = SDL_GetTicks() - frame_start; - if (elapsed < FRAME_TIME) - SDL_Delay(FRAME_TIME - elapsed); -} - static void gfx_sdl_swap_buffers_begin(void) { - // if vsync is set to 2, depend only on SwapInterval to sync - if (configWindow.vsync <= 1) - sync_framerate_with_timer(); SDL_GL_SwapWindow(wnd); } From 26705aed7a3b83103606a1e0e847055aba065d8a Mon Sep 17 00:00:00 2001 From: fgsfds Date: Tue, 19 May 2020 01:59:29 +0300 Subject: [PATCH 11/15] disable cheats by default; use --cheats CLI option to enable for now --- src/game/options_menu.c | 15 +++++++++++++-- src/pc/cheats.c | 1 + src/pc/cheats.h | 10 +++++++--- src/pc/cliopts.c | 4 ++++ 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/game/options_menu.c b/src/game/options_menu.c index 7b8d9f74..d23223b0 100644 --- a/src/game/options_menu.c +++ b/src/game/options_menu.c @@ -268,8 +268,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 ); @@ -459,6 +459,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 { diff --git a/src/pc/cheats.c b/src/pc/cheats.c index 5663d777..adcc4efe 100644 --- a/src/pc/cheats.c +++ b/src/pc/cheats.c @@ -1,2 +1,3 @@ #include "cheats.h" + struct CheatList Cheats; diff --git a/src/pc/cheats.h b/src/pc/cheats.h index 01a7264b..531c392f 100644 --- a/src/pc/cheats.h +++ b/src/pc/cheats.h @@ -1,9 +1,11 @@ +#ifndef _CHEATS_H +#define _CHEATS_H + #include -struct CheatList -{ +struct CheatList { bool EnableCheats; - bool MoonJump; + bool MoonJump; bool GodMode; bool InfiniteLives; bool SuperSpeed; @@ -11,3 +13,5 @@ struct CheatList }; extern struct CheatList Cheats; + +#endif // _CHEATS_H diff --git a/src/pc/cliopts.c b/src/pc/cliopts.c index 234660b2..727de38b 100644 --- a/src/pc/cliopts.c +++ b/src/pc/cliopts.c @@ -1,5 +1,6 @@ #include "cliopts.h" #include "configfile.h" +#include "cheats.h" #include "pc_main.h" #include @@ -32,6 +33,9 @@ void parse_cli_opts(int argc, char* argv[]) { 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(); From 8e60f9960ea6452011bd33cc833ee309adc91700 Mon Sep 17 00:00:00 2001 From: Leon422 Date: Tue, 19 May 2020 00:02:03 +0100 Subject: [PATCH 12/15] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dadc0b7e..0e28a0b2 100644 --- a/README.md +++ b/README.md @@ -18,7 +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, accessible from the "Options" menu. 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. + * 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). From 18c197dbff6c3932688ec6f56d81cf8f1fbe1ca7 Mon Sep 17 00:00:00 2001 From: Leon422 Date: Tue, 19 May 2020 00:04:07 +0100 Subject: [PATCH 13/15] Update README_es_ES.md --- README_es_ES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_es_ES.md b/README_es_ES.md index fa7ba3ca..44a34a1c 100644 --- a/README_es_ES.md +++ b/README_es_ES.md @@ -13,7 +13,7 @@ Ejecuta `./extract_assets.py --clean && make clean` o `make distclean` para borr * Opción para desactivar el límite de distancia de renderizado. (Se activa con `make NODRAWINGDISTANCE=1`.) * 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, al cual se accede a través del menú "Options". 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. + * 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.** From c18e70f44eaf628f5795002c29166bbfc4835238 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Tue, 19 May 2020 02:38:59 +0300 Subject: [PATCH 14/15] Revert "Merge branch 'nightly' into master" This reverts commit 2e8a821fa3c48df20223312df815d4d41b34b1c9, reversing changes made to d499f5540291020e2eeed6053a9e06f7d80e960c. --- bin/segment2.c | 4 ++-- include/text_strings.h.in | 2 ++ src/game/options_menu.c | 27 ++++++++++++++++++------- src/pc/configfile.c | 4 +++- src/pc/configfile.h | 3 ++- src/pc/gfx/gfx_sdl2.c | 42 ++++++++++++--------------------------- 6 files changed, 42 insertions(+), 40 deletions(-) diff --git a/bin/segment2.c b/bin/segment2.c index 5d5398aa..d7e807fd 100644 --- a/bin/segment2.c +++ b/bin/segment2.c @@ -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_CLAMP, 4, G_TX_NOLOD, G_TX_CLAMP, 4, G_TX_NOLOD), + 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), 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_CLAMP, 4, G_TX_NOLOD, G_TX_CLAMP, 4, G_TX_NOLOD), + 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), gsDPSetTileSize(0, 0, 0, (16 - 1) << G_TEXTURE_IMAGE_FRAC, (16 - 1) << G_TEXTURE_IMAGE_FRAC), gsSPEndDisplayList(), }; diff --git a/include/text_strings.h.in b/include/text_strings.h.in index 06173692..b77a51ca 100644 --- a/include/text_strings.h.in +++ b/include/text_strings.h.in @@ -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") diff --git a/src/game/options_menu.c b/src/game/options_menu.c index 58b7d05c..d23223b0 100644 --- a/src/game/options_menu.c +++ b/src/game/options_menu.c @@ -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] = { @@ -112,6 +114,12 @@ static const u8 *filterChoices[] = { optsVideoStr[3], }; +static const u8 *vsyncChoices[] = { + toggleStr[0], + toggleStr[1], + optsVideoStr[6], +}; + enum OptType { OPT_INVALID = 0, OPT_TOGGLE, @@ -178,8 +186,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 */ @@ -217,8 +229,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[] = { @@ -230,8 +243,8 @@ 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[4], &Cheats.SuperSpeed ), + DEF_OPT_TOGGLE( optsCheatsStr[5], &Cheats.Responsive ), }; @@ -243,7 +256,7 @@ static struct SubMenu menuCamera = DEF_SUBMENU( menuStr[4], optsCamera ); static struct SubMenu menuControls = DEF_SUBMENU( menuStr[5], optsControls ); static struct SubMenu menuVideo = DEF_SUBMENU( menuStr[6], optsVideo ); static struct SubMenu menuAudio = DEF_SUBMENU( menuStr[7], optsAudio ); -static struct SubMenu menuCheats = DEF_SUBMENU( menuStr[9], optsCheats ); +static struct SubMenu menuCheats = DEF_SUBMENU( menuStr[9], optsCheats ); /* main options menu definition */ diff --git a/src/pc/configfile.c b/src/pc/configfile.c index 0b6fe370..ce9a08ad 100644 --- a/src/pc/configfile.c +++ b/src/pc/configfile.c @@ -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}, diff --git a/src/pc/configfile.h b/src/pc/configfile.h index 01d657c2..cafd272f 100644 --- a/src/pc/configfile.h +++ b/src/pc/configfile.h @@ -11,10 +11,11 @@ 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; diff --git a/src/pc/gfx/gfx_sdl2.c b/src/pc/gfx/gfx_sdl2.c index 6ff6906d..e86a100c 100644 --- a/src/pc/gfx/gfx_sdl2.c +++ b/src/pc/gfx/gfx_sdl2.c @@ -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; } @@ -281,6 +264,7 @@ static void gfx_sdl_handle_events(void) { } static bool gfx_sdl_start_frame(void) { + frame_start = SDL_GetTicks(); return true; } From 1046cc1301314a029c44edf6902bff7166f36e1b Mon Sep 17 00:00:00 2001 From: fgsfds Date: Mon, 18 May 2020 22:38:19 +0300 Subject: [PATCH 15/15] Merge pull request #179 from dernett/fix-fullscreen-text Fix fullscreen text --- bin/segment2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/segment2.c b/bin/segment2.c index d7e807fd..5d5398aa 100644 --- a/bin/segment2.c +++ b/bin/segment2.c @@ -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(), };