From fbae610a3b6a25c079f0cacca96c2bbee09e084e Mon Sep 17 00:00:00 2001 From: fgsfds Date: Fri, 3 Nov 2023 16:24:10 +0100 Subject: [PATCH] port: rework config system a bit --- port/include/config.h | 20 ++--- port/include/input.h | 2 +- port/include/video.h | 2 - port/src/audio.c | 15 +++- port/src/config.c | 179 ++++++++++++++++++++--------------------- port/src/input.c | 139 +++++++++++++++----------------- port/src/main.c | 52 ++++++------ port/src/optionsmenu.c | 5 +- port/src/video.c | 66 ++++++++------- src/game/game_1531a0.c | 1 + src/include/data.h | 1 + src/include/platform.h | 9 ++- 12 files changed, 238 insertions(+), 253 deletions(-) diff --git a/port/include/config.h b/port/include/config.h index c48550345..5bc12cf11 100644 --- a/port/include/config.h +++ b/port/include/config.h @@ -13,18 +13,8 @@ s32 configLoad(const char *fname); // saves config to file (path extensions such as ! apply) s32 configSave(const char *fname); -// get value of a config variable or create a new one with specified default -// key is a string of the form "SECTION.KEY" -s32 configGetInt(const char *key, s32 defval); -f32 configGetFloat(const char *key, f32 defval); -const char *configGetString(const char *key, const char *defval); - -// get value as above and clamp it in between minval, maxval -s32 configGetIntClamped(const char *key, s32 defval, s32 minval, s32 maxval); -f32 configGetFloatClamped(const char *key, f32 defval, f32 minval, f32 maxval); - -// set value of a config variable, will create it if it doesn't exist -// key is a string of the form "SECTION.KEY" -void configSetInt(const char *key, s32 val); -void configSetFloat(const char *key, f32 val); -void configSetString(const char *key, const char *val); +// registers a variable in the config file +// this should be done before configInit() is called, preferably in a module constructor +void configRegisterInt(const char *key, s32 *var, s32 min, s32 max); +void configRegisterFloat(const char *key, f32 *var, f32 min, f32 max); +void configRegisterString(const char *key, char *var, u32 maxstr); diff --git a/port/include/input.h b/port/include/input.h index 9a91005bb..fb6c410f1 100644 --- a/port/include/input.h +++ b/port/include/input.h @@ -167,7 +167,7 @@ void inputMouseEnable(s32 enabled); void inputUpdate(void); // call this before configSave() -void inputSaveConfig(void); +void inputSaveBinds(void); void inputSetDefaultKeyBinds(void); diff --git a/port/include/video.h b/port/include/video.h index a68ac75d3..ffd2c6728 100644 --- a/port/include/video.h +++ b/port/include/video.h @@ -38,6 +38,4 @@ s32 videoFramebuffersSupported(void); void videoResetTextureCache(void); void videoFreeCachedTexture(const void *texptr); -void videoSaveConfig(void); - #endif diff --git a/port/src/audio.c b/port/src/audio.c index 8c673a851..c66cf5912 100644 --- a/port/src/audio.c +++ b/port/src/audio.c @@ -1,6 +1,7 @@ #include #include #include +#include "platform.h" #include "config.h" #include "audio.h" #include "system.h" @@ -8,7 +9,9 @@ static SDL_AudioDeviceID dev; static const s16 *nextBuf; static u32 nextSize = 0; -static u32 queueLimit = 8192; + +static s32 bufferSize = 512; +static s32 queueLimit = 8192; s32 audioInit(void) { @@ -22,7 +25,7 @@ s32 audioInit(void) want.freq = 22020; // TODO: this might cause trouble for some platforms want.format = AUDIO_S16SYS; want.channels = 2; - want.samples = configGetInt("Audio.BufferSize", 512); + want.samples = bufferSize; want.callback = NULL; nextBuf = NULL; @@ -33,8 +36,6 @@ s32 audioInit(void) return -1; } - queueLimit = configGetInt("Audio.QueueLimit", 8192); - SDL_PauseAudioDevice(dev, 0); return 0; @@ -66,3 +67,9 @@ void audioEndFrame(void) nextSize = 0; } } + +PD_CONSTRUCTOR static void audioConfigInit(void) +{ + configRegisterInt("Audio.BufferSize", &bufferSize, 0, 1 * 1024 * 1024); + configRegisterInt("Audio.QueueLimit", &queueLimit, 0, 1 * 1024 * 1024); +} diff --git a/port/src/config.c b/port/src/config.c index ced137d55..4d2383276 100644 --- a/port/src/config.c +++ b/port/src/config.c @@ -8,20 +8,42 @@ #include "system.h" #include "utils.h" -#define CONFIG_MAX_STR 512 #define CONFIG_MAX_SECNAME 128 #define CONFIG_MAX_KEYNAME 256 #define CONFIG_MAX_SETTINGS 256 +typedef enum { + CFG_NONE, + CFG_S32, + CFG_F32, + CFG_STR +} configtype; + struct configentry { char key[CONFIG_MAX_KEYNAME + 1]; - char strval[CONFIG_MAX_STR + 1]; - s32 s32val; - f32 f32val; s32 seclen; -} settings[CONFIG_MAX_SETTINGS + 1]; + configtype type; + void *ptr; + union { + struct { f32 min_f32, max_f32; }; + struct { s32 min_s32, max_s32; }; + u32 max_str; + }; +} settings[CONFIG_MAX_SETTINGS]; + static s32 numSettings = 0; +static inline s32 configClampInt(s32 val, s32 min, s32 max) +{ + return (val < min) ? min : ((val > max) ? max : val); +} + +static inline f32 configClampFloat(f32 val, f32 min, f32 max) +{ + return (val < min) ? min : ((val > max) ? max : val); +} + + static inline struct configentry *configFindEntry(const char *key) { for (s32 i = 0; i < numSettings; ++i) { @@ -68,115 +90,89 @@ static inline const char *configGetSection(char *sec, const struct configentry * return sec; } -void configSetInt(const char *key, s32 val) +void configRegisterInt(const char *key, s32 *var, s32 min, s32 max) { struct configentry *cfg = configFindOrAddEntry(key); if (cfg) { - cfg->s32val = val; - snprintf(cfg->strval, CONFIG_MAX_STR, "%d", val); + cfg->type = CFG_S32; + cfg->ptr = var; + cfg->min_s32 = min; + cfg->max_s32 = max; } } -void configSetFloat(const char *key, f32 val) +void configRegisterFloat(const char *key, f32 *var, f32 min, f32 max) { struct configentry *cfg = configFindOrAddEntry(key); if (cfg) { - cfg->f32val = val; - snprintf(cfg->strval, CONFIG_MAX_STR, "%f", val); + cfg->type = CFG_F32; + cfg->ptr = var; + cfg->min_f32 = min; + cfg->max_f32 = max; } } -void configSetString(const char *key, const char *val) +void configRegisterString(const char *key, char *var, u32 maxstr) { struct configentry *cfg = configFindOrAddEntry(key); if (cfg) { - strncpy(cfg->strval, val, CONFIG_MAX_STR); + cfg->type = CFG_STR; + cfg->ptr = var; + cfg->max_str = maxstr; } } -void configSetFromString(const char *key, const char *val) +static void configSetFromString(const char *key, const char *val) { struct configentry *cfg = configFindOrAddEntry(key); - if (cfg) { - strncpy(cfg->strval, val, CONFIG_MAX_STR); - cfg->f32val = atof(val); - cfg->s32val = atoi(val); + if (!cfg) return; + + s32 tmp_s32; + f32 tmp_f32; + switch (cfg->type) { + case CFG_S32: + tmp_s32 = atoi(val); + if (cfg->min_s32 < cfg->max_s32) { + tmp_f32 = configClampInt(tmp_s32, cfg->min_s32, cfg->max_s32); + } + *(s32 *)cfg->ptr = tmp_s32; + break; + case CFG_F32: + tmp_f32 = atof(val); + if (cfg->min_f32 < cfg->max_f32) { + tmp_f32 = configClampFloat(tmp_f32, cfg->min_f32, cfg->max_f32); + } + *(f32 *)cfg->ptr = tmp_f32; + break; + case CFG_STR: + strncpy(cfg->ptr, val, cfg->max_str ? cfg->max_str - 1 : 4096); + break; + default: + break; } } -s32 configGetInt(const char *key, s32 defval) +static void configSaveEntry(struct configentry *cfg, FILE *f) { - struct configentry *cfg = configFindEntry(key); - if (cfg) { - return cfg->s32val; + switch (cfg->type) { + case CFG_S32: + if (cfg->min_s32 < cfg->max_s32) { + *(s32 *)cfg->ptr = configClampInt(*(s32 *)cfg->ptr, cfg->min_s32, cfg->max_s32); + } + fprintf(f, "%s=%d\n", cfg->key + cfg->seclen + 1, *(s32 *)cfg->ptr); + break; + case CFG_F32: + if (cfg->min_f32 < cfg->max_f32) { + *(f32 *)cfg->ptr = configClampFloat(*(f32 *)cfg->ptr, cfg->min_f32, cfg->max_f32); + } + fprintf(f, "%s=%f\n", cfg->key + cfg->seclen + 1, *(f32 *)cfg->ptr); + break; + case CFG_STR: + fprintf(f, "%s=%s\n", cfg->key + cfg->seclen + 1, (char *)cfg->ptr); + break; + default: + break; } - - cfg = configAddEntry(key); - if (cfg) { - cfg->s32val = defval; - snprintf(cfg->strval, CONFIG_MAX_STR, "%d", defval); - } - - return defval; -} - -f32 configGetFloat(const char *key, f32 defval) -{ - struct configentry *cfg = configFindEntry(key); - if (cfg) { - return cfg->f32val; - } - - cfg = configAddEntry(key); - if (cfg) { - cfg->f32val = defval; - snprintf(cfg->strval, CONFIG_MAX_STR, "%f", defval); - } - - return defval; -} - -const char *configGetString(const char *key, const char *defval) -{ - struct configentry *cfg = configFindEntry(key); - if (cfg) { - return cfg->strval; - } - - cfg = configAddEntry(key); - if (cfg) { - strncpy(cfg->strval, defval, CONFIG_MAX_STR); - } - - return defval; -} - -s32 configGetIntClamped(const char *key, s32 defval, s32 minval, s32 maxval) -{ - const s32 ret = configGetInt(key, defval); - return (ret < minval) ? minval : ((ret > maxval) ? maxval : ret); -} - -f32 configGetFloatClamped(const char *key, f32 defval, f32 minval, f32 maxval) -{ - const f32 ret = configGetFloat(key, defval); - return (ret < minval) ? minval : ((ret > maxval) ? maxval : ret); -} - -static s32 configCmp(const struct configentry *a, const struct configentry *b) { - char tmpa[CONFIG_MAX_SECNAME + 1]; - char tmpb[CONFIG_MAX_SECNAME + 1]; - configGetSection(tmpa, a); - configGetSection(tmpb, b); - - // compare section names first - const s32 seccmp = strncmp(tmpa, tmpb, CONFIG_MAX_SECNAME); - if (seccmp) { - return seccmp; - } - - // same section; sort keys by first letter - return a->key[a->seclen + 1] - b->key[b->seclen + 1]; } s32 configSave(const char *fname) @@ -186,9 +182,6 @@ s32 configSave(const char *fname) return 0; } - // sort the config so that the sections appear in order - qsort(settings, numSettings, sizeof(*settings), (void *)configCmp); - char tmpSec[CONFIG_MAX_SECNAME + 1] = { 0 }; char curSec[CONFIG_MAX_SECNAME + 1] = { 0 }; configGetSection(curSec, &settings[0]); @@ -201,7 +194,7 @@ s32 configSave(const char *fname) fprintf(f, "\n[%s]\n", tmpSec); strncpy(curSec, tmpSec, CONFIG_MAX_SECNAME); } - fprintf(f, "%s=%s\n", cfg->key + cfg->seclen + 1, cfg->strval); + configSaveEntry(cfg, f); } fsFileClose(f); diff --git a/port/src/input.c b/port/src/input.c index 5ae433f3d..deeb9cf0f 100644 --- a/port/src/input.c +++ b/port/src/input.c @@ -10,6 +10,8 @@ #include "config.h" #include "system.h" +#define MAX_BIND_STR 256 + #define TRIG_THRESHOLD (30 * 256) #define DEFAULT_DEADZONE 4096 #define DEFAULT_DEADZONE_RY 6144 @@ -21,7 +23,10 @@ static SDL_GameController *pads[INPUT_MAX_CONTROLLERS]; static s32 rumbleSupported[INPUT_MAX_CONTROLLERS]; static u32 binds[MAXCONTROLLERS][CK_TOTAL_COUNT][INPUT_MAX_BINDS]; // [i][CK_][b] = [VK_] +static char bindStrs[MAXCONTROLLERS][CK_TOTAL_COUNT][MAX_BIND_STR]; +static s32 fakeControllers = 0; +static s32 firstController = 0; static s32 connectedMask = 0; static s32 mouseEnabled = 1; @@ -57,6 +62,7 @@ static s32 deadzone[4] = { }; static s32 stickCButtons = 1; +static s32 swapSticks = 1; static const char *ckNames[CK_TOTAL_COUNT] = { "R_CBUTTONS", @@ -253,7 +259,7 @@ static int inputEventFilter(void *data, SDL_Event *event) { switch (event->type) { case SDL_CONTROLLERDEVICEADDED: - for (s32 i = 0; i < INPUT_MAX_CONTROLLERS; ++i) { + for (s32 i = firstController; i < INPUT_MAX_CONTROLLERS; ++i) { if (!pads[i]) { pads[i] = SDL_GameControllerOpen(event->cdevice.which); if (pads[i]) { @@ -387,34 +393,36 @@ static inline void inputInitKeyNames(void) } } -static inline void inputSaveBinds(void) +void inputSaveBinds(void) { - char bindstr[256]; - char keyname[256]; - char secname[] = "Input.Player1.Binds"; - - bindstr[sizeof(bindstr) - 1] = '\0'; + char *bindstr; for (s32 i = 0; i < MAXCONTROLLERS; ++i) { - secname[12] = '1' + i; for (u32 ck = 0; ck < CK_TOTAL_COUNT; ++ck) { - snprintf(keyname, sizeof(keyname), "%s.%s", secname, inputGetContKeyName(ck)); + bindstr = bindStrs[i][ck]; bindstr[0] = '\0'; for (s32 b = 0; b < INPUT_MAX_BINDS; ++b) { if (binds[i][ck][b]) { if (b) { - strncat(bindstr, ", ", sizeof(bindstr) - 1); + strncat(bindstr, ", ", MAX_BIND_STR - 1); } - strncat(bindstr, inputGetKeyName(binds[i][ck][b]), sizeof(bindstr) - 1); + strncat(bindstr, inputGetKeyName(binds[i][ck][b]), MAX_BIND_STR - 1); } } - configSetString(keyname, bindstr[0] ? bindstr : "NONE"); + if (!bindstr[0]) { + strcpy(bindstr, "NONE"); + } } } } static inline void inputParseBindString(const s32 ctrl, const u32 ck, char *bindstr) { + if (!bindstr[0]) { + // empty string, keep defaults + return; + } + // unbind all first memset(binds[ctrl][ck], 0, sizeof(binds[ctrl][ck])); @@ -437,50 +445,13 @@ static inline void inputParseBindString(const s32 ctrl, const u32 ck, char *bind static inline void inputLoadBinds(void) { - char secname[] = "Input.Player1.Binds"; - char keyname[256]; - char bindstr[256]; - for (s32 i = 0; i < MAXCONTROLLERS; ++i) { - secname[12] = '1' + i; for (u32 ck = 0; ck < CK_TOTAL_COUNT; ++ck) { - snprintf(keyname, sizeof(keyname), "%s.%s", secname, inputGetContKeyName(ck)); - const char *cfgstr = configGetString(keyname, ""); - if (cfgstr[0]) { - strncpy(bindstr, cfgstr, sizeof(bindstr) - 1); - bindstr[sizeof(bindstr) - 1] = '\0'; - inputParseBindString(i, ck, bindstr); - } + inputParseBindString(i, ck, bindStrs[i][ck]); } } } -void inputSaveConfig(void) -{ - inputSaveBinds(); - - configSetInt("Input.MouseEnabled", mouseEnabled); - configSetInt("Input.MouseDefaultLocked", mouseDefaultLocked); - configSetFloat("Input.MouseSpeedX", mouseSensX); - configSetFloat("Input.MouseSpeedY", mouseSensY); - - configSetInt("Input.LStickDeadzoneX", deadzone[0]); - configSetInt("Input.LStickDeadzoneY", deadzone[1]); - configSetInt("Input.RStickDeadzoneX", deadzone[2]); - configSetInt("Input.RStickDeadzoneY", deadzone[3]); - - configSetFloat("Input.LStickScaleX", stickSens[0]); - configSetFloat("Input.LStickScaleY", stickSens[1]); - configSetFloat("Input.RStickScaleX", stickSens[2]); - configSetFloat("Input.RStickScaleY", stickSens[3]); - - configSetFloat("Input.RumbleScale", rumbleScale); - - configSetInt("Input.StickCButtons", stickCButtons); - - configGetInt("Input.SwapSticks", axisMap[0][0] == SDL_CONTROLLER_AXIS_RIGHTX); -} - s32 inputInit(void) { if (!SDL_WasInit(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC)) { @@ -493,11 +464,9 @@ s32 inputInit(void) connectedMask = 1; // always report first controller as connected - // if this is set to 1, keyboard will count as a separate controller on its own, + // if firstController is set to 1, keyboard will count as a separate controller on its own, // so the first connected gamepad will go to player 2 instead of player 1 - const s32 cstart = configGetInt("Input.FirstGamepadNum", 0); - - for (s32 jidx = 0, cidx = cstart; jidx < numJoys && cidx < INPUT_MAX_CONTROLLERS; ++jidx) { + for (s32 jidx = 0, cidx = firstController; jidx < numJoys && cidx < INPUT_MAX_CONTROLLERS; ++jidx) { if (SDL_IsGameController(jidx)) { pads[cidx] = SDL_GameControllerOpen(jidx); if (pads[cidx]) { @@ -514,27 +483,9 @@ s32 inputInit(void) inputSetDefaultKeyBinds(); - mouseEnabled = configGetInt("Input.MouseEnabled", 1); - mouseDefaultLocked = configGetInt("Input.MouseDefaultLocked", 0); inputLockMouse(mouseDefaultLocked); - mouseSensX = configGetFloat("Input.MouseSpeedX", 1.5f); - mouseSensY = configGetFloat("Input.MouseSpeedY", 1.5f); - rumbleScale = configGetFloat("Input.RumbleScale", 0.5f); - - deadzone[0] = configGetInt("Input.LStickDeadzoneX", DEFAULT_DEADZONE); - deadzone[1] = configGetInt("Input.LStickDeadzoneY", DEFAULT_DEADZONE); - deadzone[2] = configGetInt("Input.RStickDeadzoneX", DEFAULT_DEADZONE); - deadzone[3] = configGetInt("Input.RStickDeadzoneY", DEFAULT_DEADZONE_RY); - - stickSens[0] = configGetFloat("Input.LStickScaleX", 1.f); - stickSens[1] = configGetFloat("Input.LStickScaleY", 1.f); - stickSens[2] = configGetFloat("Input.RStickScaleX", 1.f); - stickSens[3] = configGetFloat("Input.RStickScaleY", 1.f); - - stickCButtons = configGetInt("Input.StickCButtons", 0); - - if (configGetInt("Input.SwapSticks", 1)) { + if (swapSticks) { // invert axis map axisMap[0][0] = SDL_CONTROLLER_AXIS_RIGHTX; axisMap[0][1] = SDL_CONTROLLER_AXIS_RIGHTY; @@ -542,7 +493,7 @@ s32 inputInit(void) axisMap[1][1] = SDL_CONTROLLER_AXIS_LEFTY; } - const s32 overrideMask = (1 << configGetInt("Input.FakeGamepads", 0)) - 1; + const s32 overrideMask = (1 << fakeControllers) - 1; if (overrideMask) { connectedMask = overrideMask; } @@ -737,11 +688,12 @@ s32 inputControllerMask(void) s32 inputControllerGetSticksSwapped(void) { - return (axisMap[0][0] == SDL_CONTROLLER_AXIS_RIGHTX); + return swapSticks; } void inputControllerSetSticksSwapped(s32 swapped) { + swapSticks = swapped; if (swapped) { axisMap[0][0] = SDL_CONTROLLER_AXIS_RIGHTX; axisMap[0][1] = SDL_CONTROLLER_AXIS_RIGHTY; @@ -791,7 +743,6 @@ void inputKeyBind(s32 idx, u32 ck, s32 bind, u32 vk) return; } - if (bind < 0) { for (s32 i = 0; i < INPUT_MAX_BINDS; ++i) { if (binds[idx][ck][i] == 0) { @@ -1019,3 +970,39 @@ s32 inputGetLastKey(void) { return lastKey; } + +PD_CONSTRUCTOR static void inputConfigInit(void) +{ + configRegisterInt("Input.MouseEnabled", &mouseEnabled, 0, 1); + configRegisterInt("Input.MouseDefaultLocked", &mouseDefaultLocked, 0, 1); + configRegisterFloat("Input.MouseSpeedX", &mouseSensX, -10.f, 10.f); + configRegisterFloat("Input.MouseSpeedY", &mouseSensY, -10.f, 10.f); + + configRegisterFloat("Input.RumbleScale", &rumbleScale, 0.f, 1.f); + + configRegisterInt("Input.LStickDeadzoneX", &deadzone[0], 0, 32767); + configRegisterInt("Input.LStickDeadzoneY", &deadzone[1], 0, 32767); + configRegisterInt("Input.RStickDeadzoneX", &deadzone[2], 0, 32767); + configRegisterInt("Input.RStickDeadzoneY", &deadzone[3], 0, 32767); + + configRegisterFloat("Input.LStickScaleX", &stickSens[0], -10.f, 10.f); + configRegisterFloat("Input.LStickScaleY", &stickSens[1], -10.f, 10.f); + configRegisterFloat("Input.RStickScaleX", &stickSens[2], -10.f, 10.f); + configRegisterFloat("Input.RStickScaleY", &stickSens[3], -10.f, 10.f); + + configRegisterInt("Input.StickCButtons", &stickCButtons, 0, 1); + configRegisterInt("Input.SwapSticks", &swapSticks, 0, 1); + + configRegisterInt("Input.FakeGamepads", &fakeControllers, 0, 4); + configRegisterInt("Input.FirstGamepadNum", &firstController, 0, 3); + + char secname[] = "Input.Player1.Binds"; + char keyname[256] = { 0 }; + for (s32 c = 0; c < MAXCONTROLLERS; ++c) { + secname[12] = '1' + c; + for (u32 ck = 0; ck < CK_TOTAL_COUNT; ++ck) { + snprintf(keyname, sizeof(keyname), "%s.%s", secname, inputGetContKeyName(ck)); + configRegisterString(keyname, bindStrs[c][ck], MAX_BIND_STR); + } + } +} diff --git a/port/src/main.c b/port/src/main.c index 8db10b5fe..9e850c02a 100644 --- a/port/src/main.c +++ b/port/src/main.c @@ -18,6 +18,7 @@ #include "system.h" u32 g_OsMemSize = 0; +s32 g_OsMemSizeMb = 16; u8 g_Is4Mb = 0; s8 g_Resetting = false; OSSched g_Sched; @@ -58,43 +59,18 @@ void bootCreateSched(void) static void gameLoadConfig(void) { - osMemSize = configGetIntClamped("Game.MemorySize", 16, 4, 2048) * 1024 * 1024; - g_PlayerCrosshairSway = configGetFloatClamped("Game.CrosshairSway", g_PlayerCrosshairSway, 0.f, 10.f); - g_PlayerDefaultFovY = configGetFloatClamped("Game.FovY", g_PlayerDefaultFovY, 5.f, 175.f); - g_PlayerMouseAimMode = configGetIntClamped("Game.MouseAimMode", g_PlayerMouseAimMode, 0, 1); - g_PlayerMouseAimSpeedX = configGetFloatClamped("Game.MouseAimSpeedX", g_PlayerMouseAimSpeedX, 0.f, 10.f); - g_PlayerMouseAimSpeedY = configGetFloatClamped("Game.MouseAimSpeedY", g_PlayerMouseAimSpeedY, 0.f, 10.f); - g_PlayerRadialMenuSpeed = configGetFloatClamped("Game.RadialMenuSpeed", g_PlayerRadialMenuSpeed, 0.f, 10.f); - g_PlayerFovAffectsZoom = configGetIntClamped("Game.FovAffectsZoom", g_PlayerFovAffectsZoom, 0, 1); + osMemSize = g_OsMemSizeMb * 1024 * 1024; g_PlayerFovZoomMultiplier = g_PlayerFovAffectsZoom ? g_PlayerDefaultFovY / 60.0f : 1.0f; - g_PlayerClassicCrouch = configGetIntClamped("Game.ClassicCrouch", 0, 0, 1); - g_ViShakeIntensityMult = configGetFloatClamped("Game.ScreenShakeIntensity", 1.f, 0.f, 100.f); - const s32 center = configGetIntClamped("Game.CenterHUD", 0, 0, 1); - if (center) { + if (g_HudCenter) { g_HudAlignModeL = G_ASPECT_CENTER_EXT; g_HudAlignModeR = G_ASPECT_CENTER_EXT; } } -static void gameSaveConfig(void) -{ - configSetFloat("Game.FovY", g_PlayerDefaultFovY); - configSetInt("Game.CenterHUD", g_HudAlignModeL == G_ASPECT_CENTER_EXT); - configSetInt("Game.ClassicCrouch", g_PlayerClassicCrouch); - configSetInt("Game.MouseAimMode", g_PlayerMouseAimMode); - configSetFloat("Game.MouseAimSpeedX", g_PlayerMouseAimSpeedX); - configSetFloat("Game.MouseAimSpeedY", g_PlayerMouseAimSpeedY); - configSetFloat("Game.RadialMenuSpeed", g_PlayerRadialMenuSpeed); - configSetFloat("Game.CrosshairSway", g_PlayerCrosshairSway); - configSetFloat("Game.ScreenShakeIntensity", g_ViShakeIntensityMult); -} - static void cleanup(void) { sysLogPrintf(LOG_NOTE, "shutdown"); - inputSaveConfig(); - videoSaveConfig(); - gameSaveConfig(); + inputSaveBinds(); configSave(CONFIG_PATH); crashShutdown(); // TODO: actually shut down all subsystems @@ -147,3 +123,23 @@ int main(int argc, const char **argv) return 0; } + +PD_CONSTRUCTOR static void gameConfigInit(void) +{ + configRegisterInt("Game.MemorySize", &g_OsMemSizeMb, 4, 2048); + + configRegisterFloat("Game.FovY", &g_PlayerDefaultFovY, 5.f, 175.f); + configRegisterInt("Game.FovAffectsZoom", &g_PlayerFovAffectsZoom, 0, 1); + + configRegisterInt("Game.MouseAimMode", &g_PlayerMouseAimMode, 0, 1); + configRegisterFloat("Game.MouseAimSpeedX", &g_PlayerMouseAimSpeedX, 0.f, 10.f); + configRegisterFloat("Game.MouseAimSpeedY", &g_PlayerMouseAimSpeedY, 0.f, 10.f); + + configRegisterFloat("Game.RadialMenuSpeed", &g_PlayerRadialMenuSpeed, 0.f, 10.f); + configRegisterFloat("Game.CrosshairSway", &g_PlayerCrosshairSway, 0.f, 10.f); + configRegisterFloat("Game.ScreenShakeIntensity", &g_ViShakeIntensityMult, 0.f, 10.f); + + configRegisterInt("Game.ClassicCrouch", &g_PlayerClassicCrouch, 0, 1); + + configRegisterInt("Game.CenterHUD", &g_HudCenter, 0, 1); +} diff --git a/port/src/optionsmenu.c b/port/src/optionsmenu.c index dcd656a3b..250388f5c 100644 --- a/port/src/optionsmenu.c +++ b/port/src/optionsmenu.c @@ -549,9 +549,10 @@ static MenuItemHandlerResult menuhandlerCenterHUD(s32 operation, struct menuitem { switch (operation) { case MENUOP_GET: - return g_HudAlignModeL == G_ASPECT_CENTER_EXT; + return g_HudCenter; case MENUOP_SET: - if (data->checkbox.value) { + g_HudCenter = data->checkbox.value; + if (g_HudCenter) { g_HudAlignModeL = G_ASPECT_CENTER_EXT; g_HudAlignModeR = G_ASPECT_CENTER_EXT; } else { diff --git a/port/src/video.c b/port/src/video.c index 778303100..afe485f5b 100644 --- a/port/src/video.c +++ b/port/src/video.c @@ -4,6 +4,7 @@ #include #include #include +#include "platform.h" #include "config.h" #include "video.h" @@ -15,42 +16,38 @@ static struct GfxWindowManagerAPI *wmAPI; static struct GfxRenderingAPI *renderingAPI; static bool initDone = false; -static bool isFullscreen = false; + +static s32 vidWidth = 640; +static s32 vidHeight = 480; +static s32 vidFramebuffers = true; +static s32 vidFullscreen = false; +static s32 vidVsync = 1; +static s32 vidMSAA = 1; +static s32 vidFramerateLimit = 0; + +static s32 texFilter = FILTER_LINEAR; +static s32 texFilter2D = true; static u32 dlcount = 0; static u32 frames = 0; static u32 framesPerSec = 0; static f64 startTime, endTime, fpsTime; -static u32 texFilter2D = 1; s32 videoInit(void) { wmAPI = &gfx_sdl; renderingAPI = &gfx_opengl_api; + gfx_current_native_viewport.width = 320; gfx_current_native_viewport.height = 240; + gfx_framebuffers_enabled = (bool)vidFramebuffers; + gfx_msaa_level = vidMSAA; - const s32 w = configGetInt("Video.DefaultWidth", 640); - const s32 h = configGetInt("Video.DefaultHeight", 480); - isFullscreen = configGetInt("Video.DefaultFullscreen", false); + gfx_init(wmAPI, renderingAPI, "PD", vidFullscreen, vidWidth, vidHeight, 100, 100); - gfx_framebuffers_enabled = (bool)configGetIntClamped("Video.FramebufferEffects", 1, 0, 1); - - gfx_msaa_level = configGetInt("Video.MSAA", 0); - if (gfx_msaa_level < 1 || gfx_msaa_level > 16) { - gfx_msaa_level = 1; - } - - gfx_init(wmAPI, renderingAPI, "PD", isFullscreen, w, h, 100, 100); - - wmAPI->set_swap_interval(configGetInt("Video.VSync", 1)); - wmAPI->set_target_fps(configGetInt("Video.FramerateLimit", 0)); // disabled because vsync is on - - u32 filter = configGetInt("Video.TextureFilter", FILTER_LINEAR); - if (filter > FILTER_THREE_POINT) filter = FILTER_THREE_POINT; - renderingAPI->set_texture_filter((enum FilteringMode)filter); - - texFilter2D = configGetIntClamped("Video.TextureFilter2D", 1, 0, 1); + wmAPI->set_swap_interval(vidVsync); + wmAPI->set_target_fps(vidFramerateLimit); // disabled because vsync is on + renderingAPI->set_texture_filter((enum FilteringMode)texFilter); initDone = true; return 0; @@ -137,7 +134,7 @@ s32 videoGetHeight(void) s32 videoGetFullscreen(void) { - return isFullscreen; + return vidFullscreen; } f32 videoGetAspect(void) @@ -152,7 +149,7 @@ u32 videoGetTextureFilter2D(void) u32 videoGetTextureFilter(void) { - return renderingAPI->get_texture_filter(); + return texFilter; } void videoSetWindowOffset(s32 x, s32 y) @@ -163,15 +160,16 @@ void videoSetWindowOffset(s32 x, s32 y) void videoSetFullscreen(s32 fs) { - if (fs != isFullscreen) { - isFullscreen = !!fs; - wmAPI->set_fullscreen(isFullscreen); + if (fs != vidFullscreen) { + vidFullscreen = !!fs; + wmAPI->set_fullscreen(vidFullscreen); } } void videoSetTextureFilter(u32 filter) { if (filter > FILTER_THREE_POINT) filter = FILTER_THREE_POINT; + texFilter = filter; renderingAPI->set_texture_filter((enum FilteringMode)filter); } @@ -221,9 +219,15 @@ void videoFreeCachedTexture(const void *texptr) gfx_texture_cache_delete(texptr); } -void videoSaveConfig(void) +PD_CONSTRUCTOR static void videoConfigInit(void) { - configSetInt("Video.DefaultFullscreen", isFullscreen); - configSetInt("Video.TextureFilter", (u32)renderingAPI->get_texture_filter()); - configSetInt("Video.TextureFilter2D", texFilter2D); + configRegisterInt("Video.DefaultFullscreen", &vidFullscreen, 0, 1); + configRegisterInt("Video.DefaultWidth", &vidWidth, 0, 32767); + configRegisterInt("Video.DefaultHeight", &vidHeight, 0, 32767); + configRegisterInt("Video.VSync", &vidVsync, -1, 10); + configRegisterInt("Video.FramebufferEffects", &vidFramebuffers, 0, 1); + configRegisterInt("Video.FramerateLimit", &vidFramerateLimit, 0, 10000); + configRegisterInt("Video.MSAA", &vidMSAA, 1, 16); + configRegisterInt("Video.TextureFilter", &texFilter, 0, 2); + configRegisterInt("Video.TextureFilter2D", &texFilter2D, 0, 1); } diff --git a/src/game/game_1531a0.c b/src/game/game_1531a0.c index a28ff87ee..3bc8e225a 100644 --- a/src/game/game_1531a0.c +++ b/src/game/game_1531a0.c @@ -143,6 +143,7 @@ u32 var8007fbc0 = 0x44444400; u32 var8007fbc4 = 0xffffff00; #ifndef PLATFORM_N64 +s32 g_HudCenter = false; u32 g_HudAlignModeL = G_ASPECT_LEFT_EXT; u32 g_HudAlignModeR = G_ASPECT_RIGHT_EXT; #endif diff --git a/src/include/data.h b/src/include/data.h index f36ffbeef..e6598f3f6 100644 --- a/src/include/data.h +++ b/src/include/data.h @@ -546,6 +546,7 @@ extern f32 g_PlayerFovZoomMultiplier; extern s32 g_PlayerClassicCrouch; extern f32 g_ViShakeIntensityMult; extern u32 g_TexFilter2D; +extern s32 g_HudCenter; extern u32 g_HudAlignModeL; extern u32 g_HudAlignModeR; extern s32 g_PrevFrameFb; diff --git a/src/include/platform.h b/src/include/platform.h index 7542a6815..30615f750 100644 --- a/src/include/platform.h +++ b/src/include/platform.h @@ -49,7 +49,7 @@ // byteswap macros -#ifdef __GNUC__ +#if defined(__GNUC__) || defined(__clang__) #define PD_BSWAP16(x) __builtin_bswap16(x) #define PD_BSWAP32(x) __builtin_bswap32(x) #define PD_BSWAP64(x) __builtin_bswap64(x) @@ -82,4 +82,11 @@ #define PD_LEPTR(x) PD_LE32(x) #endif +// module constructor function attribute +#if defined(__GNUC__) || defined(__clang__) + #define PD_CONSTRUCTOR __attribute__((constructor)) +#else + #error "Implement PD_CONSTRUCTOR macro for your compiler." +#endif + #endif