diff --git a/port/include/input.h b/port/include/input.h index 49c94de0e..85b14641b 100644 --- a/port/include/input.h +++ b/port/include/input.h @@ -93,6 +93,12 @@ s32 inputControllerConnected(s32 idx); // returns bitmask of connected controllers s32 inputControllerMask(void); +s32 inputControllerGetSticksSwapped(void); +void inputControllerSetSticksSwapped(s32 swapped); + +s32 inputControllerGetDualAnalog(void); +void inputControllerSetDualAnalog(s32 enable); + // vk is a value from the virtkey enum above s32 inputKeyPressed(u32 vk); @@ -118,6 +124,9 @@ const char *inputGetContKeyName(u32 ck); // strength is 0 .. 1; 0 strength turns it off void inputRumble(s32 idx, f32 strength, f32 time); +f32 inputRumbleGetStrength(void); +void inputRumbleSetStrength(f32 val); + // locks the mouse cursor in the window and makes it invisible if argument is true void inputLockMouse(s32 lock); @@ -138,6 +147,12 @@ void inputMouseGetScaledDelta(f32 *dx, f32 *dy); // returns 0, 0 when the mouse is not locked into the window void inputMouseGetAbsScaledDelta(f32 *dx, f32 *dy); +void inputMouseGetSpeed(f32 *x, f32 *y); +void inputMouseSetSpeed(f32 x, f32 y); + +s32 inputMouseIsEnabled(void); +void inputMouseEnable(s32 enabled); + // call this every frame void inputUpdate(void); diff --git a/port/include/video.h b/port/include/video.h index b067ecbc3..a68ac75d3 100644 --- a/port/include/video.h +++ b/port/include/video.h @@ -19,9 +19,14 @@ s32 videoGetNativeHeight(void); s32 videoGetWidth(void); s32 videoGetHeight(void); f32 videoGetAspect(void); +s32 videoGetFullscreen(void); +u32 videoGetTextureFilter(void); u32 videoGetTextureFilter2D(void); void videoSetWindowOffset(s32 x, s32 y); +void videoSetFullscreen(s32 fs); +void videoSetTextureFilter(u32 filter); +void videoSetTextureFilter2D(u32 filter); s32 videoCreateFramebuffer(u32 w, u32 h, s32 upscale, s32 autoresize); void videoSetFramebuffer(s32 target); @@ -33,4 +38,6 @@ s32 videoFramebuffersSupported(void); void videoResetTextureCache(void); void videoFreeCachedTexture(const void *texptr); +void videoSaveConfig(void); + #endif diff --git a/port/src/input.c b/port/src/input.c index 06a7566ff..2a1b291af 100644 --- a/port/src/input.c +++ b/port/src/input.c @@ -407,6 +407,9 @@ static inline void inputLoadBinds(void) void inputSaveConfig(void) { inputSaveBinds(); + + configSetFloat("Input.MouseSpeedX", mouseSensX); + configSetFloat("Input.MouseSpeedY", mouseSensY); } s32 inputInit(void) @@ -646,11 +649,51 @@ void inputRumble(s32 idx, f32 strength, f32 time) } } +f32 inputRumbleGetStrength(void) +{ + return rumbleScale; +} + +void inputRumbleSetStrength(f32 val) +{ + rumbleScale = val; +} + s32 inputControllerMask(void) { return connectedMask; } +s32 inputControllerGetSticksSwapped(void) +{ + return (axisMap[0][0] == SDL_CONTROLLER_AXIS_RIGHTX); +} + +void inputControllerSetSticksSwapped(s32 swapped) +{ + if (swapped) { + axisMap[0][0] = SDL_CONTROLLER_AXIS_RIGHTX; + axisMap[0][1] = SDL_CONTROLLER_AXIS_RIGHTY; + axisMap[1][0] = SDL_CONTROLLER_AXIS_LEFTX; + axisMap[1][1] = SDL_CONTROLLER_AXIS_LEFTY; + } else { + axisMap[0][0] = SDL_CONTROLLER_AXIS_LEFTX; + axisMap[0][1] = SDL_CONTROLLER_AXIS_LEFTY; + axisMap[1][0] = SDL_CONTROLLER_AXIS_RIGHTX; + axisMap[1][1] = SDL_CONTROLLER_AXIS_RIGHTY; + } +} + +s32 inputControllerGetDualAnalog(void) +{ + return !stickCButtons; +} + +void inputControllerSetDualAnalog(s32 enable) +{ + stickCButtons = !enable; +} + void inputKeyBind(s32 idx, u32 ck, s32 bind, u32 vk) { if (idx < 0 || idx >= INPUT_MAX_CONTROLLERS || bind >= MAX_BINDS || ck >= CK_TOTAL_COUNT) { @@ -766,6 +809,32 @@ void inputMouseGetAbsScaledDelta(f32 *dx, f32 *dy) if (dy) *dy = mdy; } +void inputMouseGetSpeed(f32 *x, f32 *y) +{ + *x = mouseSensX; + *y = mouseSensY; +} + +void inputMouseSetSpeed(f32 x, f32 y) +{ + mouseSensX = x; + mouseSensY = y; +} + +s32 inputMouseIsEnabled(void) +{ + return mouseEnabled; +} + +void inputMouseEnable(s32 enabled) +{ + mouseEnabled = !!enabled; + if (!mouseEnabled && mouseLocked) { + inputLockMouse(0); + } +} + + const char *inputGetContKeyName(u32 ck) { if (ck >= CK_TOTAL_COUNT) { diff --git a/port/src/main.c b/port/src/main.c index 74a3205a6..056a489a8 100644 --- a/port/src/main.c +++ b/port/src/main.c @@ -56,15 +56,6 @@ void bootCreateSched(void) } } -static void cleanup(void) -{ - sysLogPrintf(LOG_NOTE, "shutdown"); - inputSaveConfig(); - configSave(CONFIG_PATH); - crashShutdown(); - // TODO: actually shut down all subsystems -} - static void gameLoadConfig(void) { osMemSize = configGetIntClamped("Game.MemorySize", 16, 4, 2048) * 1024 * 1024; @@ -84,6 +75,29 @@ static void gameLoadConfig(void) } } +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.CrosshairSway", g_PlayerCrosshairSway); + configSetFloat("Game.ScreenShakeIntensity", g_ViShakeIntensityMult); +} + +static void cleanup(void) +{ + sysLogPrintf(LOG_NOTE, "shutdown"); + inputSaveConfig(); + videoSaveConfig(); + gameSaveConfig(); + configSave(CONFIG_PATH); + crashShutdown(); + // TODO: actually shut down all subsystems +} + int main(int argc, const char **argv) { sysInitArgs(argc, argv); diff --git a/port/src/optionsmenu.c b/port/src/optionsmenu.c new file mode 100644 index 000000000..3c2715d6c --- /dev/null +++ b/port/src/optionsmenu.c @@ -0,0 +1,597 @@ +#include +#include +#include +#include +#include "platform.h" +#include "data.h" +#include "types.h" +#include "game/mainmenu.h" +#include "game/menu.h" +#include "video.h" +#include "input.h" +#include "config.h" + +static MenuItemHandlerResult menuhandlerMouseEnabled(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GET: + return inputMouseIsEnabled(); + case MENUOP_SET: + inputMouseEnable(data->checkbox.value); + break; + } + + return 0; +} + +static MenuItemHandlerResult menuhandlerMouseAimLock(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GET: + return g_PlayerMouseAimMode; + case MENUOP_SET: + g_PlayerMouseAimMode = data->checkbox.value; + break; + } + + return 0; +} + +static MenuItemHandlerResult menuhandlerMouseSpeedX(s32 operation, struct menuitem *item, union handlerdata *data) +{ + f32 x, y; + + switch (operation) { + case MENUOP_GETSLIDER: + inputMouseGetSpeed(&x, &y); + if (x < 0.f) { + data->slider.value = 0; + } else if (x > 10.f) { + data->slider.value = 100; + } else { + data->slider.value = x * 10.f + 0.5f; + } + break; + case MENUOP_SET: + inputMouseGetSpeed(&x, &y); + inputMouseSetSpeed((f32)data->slider.value / 10.f, y); + break; + } + + return 0; +} + +static MenuItemHandlerResult menuhandlerMouseSpeedY(s32 operation, struct menuitem *item, union handlerdata *data) +{ + f32 x, y; + + switch (operation) { + case MENUOP_GETSLIDER: + inputMouseGetSpeed(&x, &y); + if (y < 0.f) { + data->slider.value = 0; + } else if (y > 10.f) { + data->slider.value = 100; + } else { + data->slider.value = y * 10.f + 0.5f; + } + break; + case MENUOP_SET: + inputMouseGetSpeed(&x, &y); + inputMouseSetSpeed(x, (f32)data->slider.value / 10.f); + break; + } + + return 0; +} + +static MenuItemHandlerResult menuhandlerMouseAimSpeedX(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GETSLIDER: + if (g_PlayerMouseAimSpeedX < 0.f) { + data->slider.value = 0; + } else if (g_PlayerMouseAimSpeedX > 10.f) { + data->slider.value = 100; + } else { + data->slider.value = g_PlayerMouseAimSpeedX * 10.f + 0.5f; + } + break; + case MENUOP_SET: + g_PlayerMouseAimSpeedX = (f32)data->slider.value / 10.f; + break; + } + + return 0; +} + +static MenuItemHandlerResult menuhandlerMouseAimSpeedY(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GETSLIDER: + if (g_PlayerMouseAimSpeedY < 0.f) { + data->slider.value = 0; + } else if (g_PlayerMouseAimSpeedY > 10.f) { + data->slider.value = 100; + } else { + data->slider.value = g_PlayerMouseAimSpeedY * 10.f + 0.5f; + } + break; + case MENUOP_SET: + g_PlayerMouseAimSpeedY = (f32)data->slider.value / 10.f; + break; + } + + return 0; +} + +struct menuitem g_ExtendedMouseMenuItems[] = { + { + MENUITEMTYPE_CHECKBOX, + 0, + MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Mouse Enabled", + 0, + menuhandlerMouseEnabled, + }, + { + MENUITEMTYPE_CHECKBOX, + 0, + MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Mouse Aim Lock", + 0, + menuhandlerMouseAimLock, + }, + { + MENUITEMTYPE_SLIDER, + 0, + MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_ALTSIZE, + (uintptr_t)"Mouse Speed X", + 100, + menuhandlerMouseSpeedX, + }, + { + MENUITEMTYPE_SLIDER, + 0, + MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_ALTSIZE, + (uintptr_t)"Mouse Speed Y", + 100, + menuhandlerMouseSpeedY, + }, + { + MENUITEMTYPE_SLIDER, + 0, + MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_ALTSIZE, + (uintptr_t)"Crosshair Speed X", + 100, + menuhandlerMouseAimSpeedX, + }, + { + MENUITEMTYPE_SLIDER, + 0, + MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_ALTSIZE, + (uintptr_t)"Crosshair Speed Y", + 100, + menuhandlerMouseAimSpeedY, + }, + { + MENUITEMTYPE_SEPARATOR, + 0, + 0, + 0, + 0, + NULL, + }, + { + MENUITEMTYPE_SELECTABLE, + 0, + MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, + L_OPTIONS_213, // "Back" + 0, + NULL, + }, + { MENUITEMTYPE_END }, +}; + +struct menudialogdef g_ExtendedMouseMenuDialog = { + MENUDIALOGTYPE_DEFAULT, + (uintptr_t)"Extended Mouse Options", + g_ExtendedMouseMenuItems, + NULL, + MENUDIALOGFLAG_LITERAL_TEXT, + NULL, +}; + +static MenuItemHandlerResult menuhandlerVibration(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GETSLIDER: + data->slider.value = inputRumbleGetStrength() * 100.f + 0.5f; + break; + case MENUOP_SET: + inputRumbleSetStrength((f32)data->slider.value / 100.f); + break; + } + + return 0; +} + +static MenuItemHandlerResult menuhandlerAnalogMovement(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GET: + return inputControllerGetDualAnalog(); + case MENUOP_SET: + inputControllerSetDualAnalog(data->checkbox.value); + break; + } + + return 0; +} + +static MenuItemHandlerResult menuhandlerSwapSticks(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GET: + return inputControllerGetSticksSwapped(); + case MENUOP_SET: + inputControllerSetSticksSwapped(data->checkbox.value); + break; + } + + return 0; +} + +struct menuitem g_ExtendedControllerMenuItems[] = { + { + MENUITEMTYPE_CHECKBOX, + 0, + MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Analog Movement", + 0, + menuhandlerAnalogMovement, + }, + { + MENUITEMTYPE_CHECKBOX, + 0, + MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Swap Sticks", + 0, + menuhandlerSwapSticks, + }, + { + MENUITEMTYPE_SLIDER, + 0, + MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Vibration", + 100, + menuhandlerVibration, + }, + { + MENUITEMTYPE_SEPARATOR, + 0, + 0, + 0, + 0, + NULL, + }, + { + MENUITEMTYPE_SELECTABLE, + 0, + MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, + L_OPTIONS_213, // "Back" + 0, + NULL, + }, + { MENUITEMTYPE_END }, +}; + +struct menudialogdef g_ExtendedControllerMenuDialog = { + MENUDIALOGTYPE_DEFAULT, + (uintptr_t)"Extended Controller Options", + g_ExtendedControllerMenuItems, + NULL, + MENUDIALOGFLAG_LITERAL_TEXT, + NULL, +}; + +static MenuItemHandlerResult menuhandlerFullScreen(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GET: + return videoGetFullscreen(); + case MENUOP_SET: + videoSetFullscreen(data->checkbox.value); + break; + } + + return 0; +} + +static MenuItemHandlerResult menuhandlerTexFilter(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GET: + return (videoGetTextureFilter() != 0); + case MENUOP_SET: + videoSetTextureFilter(data->checkbox.value); + break; + } + + return 0; +} + +static MenuItemHandlerResult menuhandlerTexFilter2D(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GET: + return videoGetTextureFilter2D(); + case MENUOP_SET: + videoSetTextureFilter2D(data->checkbox.value); + break; + } + + return 0; +} + +static MenuItemHandlerResult menuhandlerCenterHUD(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GET: + return g_HudAlignModeL == G_ASPECT_CENTER_EXT; + case MENUOP_SET: + if (data->checkbox.value) { + g_HudAlignModeL = G_ASPECT_CENTER_EXT; + g_HudAlignModeR = G_ASPECT_CENTER_EXT; + } else { + g_HudAlignModeL = G_ASPECT_LEFT_EXT; + g_HudAlignModeR = G_ASPECT_RIGHT_EXT; + } + break; + } + + return 0; +} + +static MenuItemHandlerResult menuhandlerFieldOfView(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GETSLIDER: + data->slider.value = g_PlayerDefaultFovY + 0.5f; + break; + case MENUOP_SET: + if (data->slider.value >= 15) { + g_PlayerDefaultFovY = data->slider.value; + if (g_PlayerFovAffectsZoom) { + g_PlayerFovZoomMultiplier = g_PlayerDefaultFovY / 60.0f; + } + } + break; + } + + return 0; +} + +struct menuitem g_ExtendedDisplayMenuItems[] = { + { + MENUITEMTYPE_CHECKBOX, + 0, + MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Full Screen", + 0, + menuhandlerFullScreen, + }, + { + MENUITEMTYPE_CHECKBOX, + 0, + MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Texture Filtering", + 0, + menuhandlerTexFilter, + }, + { + MENUITEMTYPE_CHECKBOX, + 0, + MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"GUI Texture Filtering", + 0, + menuhandlerTexFilter2D, + }, + { + MENUITEMTYPE_CHECKBOX, + 0, + MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Center HUD", + 0, + menuhandlerCenterHUD, + }, + { + MENUITEMTYPE_SLIDER, + 0, + MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Vert FOV", + 170, + menuhandlerFieldOfView, + }, + { + MENUITEMTYPE_SEPARATOR, + 0, + 0, + 0, + 0, + NULL, + }, + { + MENUITEMTYPE_SELECTABLE, + 0, + MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, + L_OPTIONS_213, // "Back" + 0, + NULL, + }, + { MENUITEMTYPE_END }, +}; + +struct menudialogdef g_ExtendedDisplayMenuDialog = { + MENUDIALOGTYPE_DEFAULT, + (uintptr_t)"Extended Display Options", + g_ExtendedDisplayMenuItems, + NULL, + MENUDIALOGFLAG_LITERAL_TEXT, + NULL, +}; + +static MenuItemHandlerResult menuhandlerClassicCrouch(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GET: + return g_PlayerClassicCrouch; + case MENUOP_SET: + g_PlayerClassicCrouch = data->checkbox.value; + break; + } + + return 0; +} + +static MenuItemHandlerResult menuhandlerCrosshairSway(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GETSLIDER: + data->slider.value = g_PlayerCrosshairSway * 10.f; + break; + case MENUOP_SET: + g_PlayerCrosshairSway = data->slider.value / 10.f; + break; + } + + return 0; +} + +static MenuItemHandlerResult menuhandlerScreenShake(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GETSLIDER: + data->slider.value = g_ViShakeIntensityMult * 10.f; + break; + case MENUOP_SET: + g_ViShakeIntensityMult = data->slider.value / 10.f; + break; + } + + return 0; +} + +struct menuitem g_ExtendedGameMenuItems[] = { + { + MENUITEMTYPE_CHECKBOX, + 0, + MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Allow Classic Crouch", + 0, + menuhandlerClassicCrouch, + }, + { + MENUITEMTYPE_SLIDER, + 0, + MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_ALTSIZE, + (uintptr_t)"Crosshair Sway", + 20, + menuhandlerCrosshairSway, + }, + { + MENUITEMTYPE_SLIDER, + 0, + MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_ALTSIZE, + (uintptr_t)"Explosion Shake", + 20, + menuhandlerScreenShake, + }, + { + MENUITEMTYPE_SEPARATOR, + 0, + 0, + 0, + 0, + NULL, + }, + { + MENUITEMTYPE_SELECTABLE, + 0, + MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, + L_OPTIONS_213, // "Back" + 0, + NULL, + }, + { MENUITEMTYPE_END }, +}; + +struct menudialogdef g_ExtendedGameMenuDialog = { + MENUDIALOGTYPE_DEFAULT, + (uintptr_t)"Extended Game Options", + g_ExtendedGameMenuItems, + NULL, + MENUDIALOGFLAG_LITERAL_TEXT, + NULL, +}; + +struct menuitem g_ExtendedMenuItems[] = { + { + MENUITEMTYPE_SELECTABLE, + 0, + MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Display\n", + 0, + (void *)&g_ExtendedDisplayMenuDialog, + }, + { + MENUITEMTYPE_SELECTABLE, + 0, + MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Mouse\n", + 0, + (void *)&g_ExtendedMouseMenuDialog, + }, + { + MENUITEMTYPE_SELECTABLE, + 0, + MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Controller\n", + 0, + (void *)&g_ExtendedControllerMenuDialog, + }, + { + MENUITEMTYPE_SELECTABLE, + 0, + MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Game\n", + 0, + (void *)&g_ExtendedGameMenuDialog, + }, + { + MENUITEMTYPE_SEPARATOR, + 0, + 0, + 0, + 0, + NULL, + }, + { + MENUITEMTYPE_SELECTABLE, + 0, + MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, + L_OPTIONS_213, // "Back" + 0, + NULL, + }, + { MENUITEMTYPE_END }, +}; + +struct menudialogdef g_ExtendedMenuDialog = { + MENUDIALOGTYPE_DEFAULT, + (uintptr_t)"Extended Options", + g_ExtendedMenuItems, + NULL, + MENUDIALOGFLAG_LITERAL_TEXT, + NULL, +}; diff --git a/port/src/video.c b/port/src/video.c index 48fbd4821..778303100 100644 --- a/port/src/video.c +++ b/port/src/video.c @@ -15,6 +15,7 @@ static struct GfxWindowManagerAPI *wmAPI; static struct GfxRenderingAPI *renderingAPI; static bool initDone = false; +static bool isFullscreen = false; static u32 dlcount = 0; static u32 frames = 0; @@ -31,7 +32,7 @@ s32 videoInit(void) const s32 w = configGetInt("Video.DefaultWidth", 640); const s32 h = configGetInt("Video.DefaultHeight", 480); - const bool fs = configGetInt("Video.DefaultFullscreen", false); + isFullscreen = configGetInt("Video.DefaultFullscreen", false); gfx_framebuffers_enabled = (bool)configGetIntClamped("Video.FramebufferEffects", 1, 0, 1); @@ -40,7 +41,7 @@ s32 videoInit(void) gfx_msaa_level = 1; } - gfx_init(wmAPI, renderingAPI, "PD", fs, w, h, 100, 100); + 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 @@ -134,6 +135,11 @@ s32 videoGetHeight(void) return gfx_current_dimensions.height; } +s32 videoGetFullscreen(void) +{ + return isFullscreen; +} + f32 videoGetAspect(void) { return gfx_current_dimensions.aspect_ratio; @@ -144,12 +150,36 @@ u32 videoGetTextureFilter2D(void) return texFilter2D; } +u32 videoGetTextureFilter(void) +{ + return renderingAPI->get_texture_filter(); +} + void videoSetWindowOffset(s32 x, s32 y) { gfx_current_game_window_viewport.x = x; gfx_current_game_window_viewport.y = y; } +void videoSetFullscreen(s32 fs) +{ + if (fs != isFullscreen) { + isFullscreen = !!fs; + wmAPI->set_fullscreen(isFullscreen); + } +} + +void videoSetTextureFilter(u32 filter) +{ + if (filter > FILTER_THREE_POINT) filter = FILTER_THREE_POINT; + renderingAPI->set_texture_filter((enum FilteringMode)filter); +} + +void videoSetTextureFilter2D(u32 filter) +{ + texFilter2D = !!filter; +} + s32 videoCreateFramebuffer(u32 w, u32 h, s32 upscale, s32 autoresize) { return gfx_create_framebuffer(w, h, upscale, autoresize); @@ -190,3 +220,10 @@ void videoFreeCachedTexture(const void *texptr) { gfx_texture_cache_delete(texptr); } + +void videoSaveConfig(void) +{ + configSetInt("Video.DefaultFullscreen", isFullscreen); + configSetInt("Video.TextureFilter", (u32)renderingAPI->get_texture_filter()); + configSetInt("Video.TextureFilter2D", texFilter2D); +} diff --git a/src/game/bondwalk.c b/src/game/bondwalk.c index ae9ab2263..edbfeaba4 100644 --- a/src/game/bondwalk.c +++ b/src/game/bondwalk.c @@ -26,6 +26,9 @@ #include "lib/collision.h" #include "data.h" #include "types.h" +#ifndef PLATFORM_N64 +extern f32 fabsf(f32); +#endif void bwalkInit(void) { diff --git a/src/game/mainmenu.c b/src/game/mainmenu.c index 5a0710ca9..29ab9fab0 100644 --- a/src/game/mainmenu.c +++ b/src/game/mainmenu.c @@ -39,6 +39,9 @@ u8 g_InventoryWeapon; struct menudialogdef g_2PMissionControlStyleMenuDialog; struct menudialogdef g_CiControlPlayer2MenuDialog; struct menudialogdef g_CinemaMenuDialog; +#ifndef PLATFORM_N64 +extern struct menudialogdef g_ExtendedMenuDialog; +#endif char *menuTextCurrentStageName(struct menuitem *item) { @@ -3429,15 +3432,23 @@ struct menuitem g_ExitGameMenuItems[] = { { MENUITEMTYPE_LABEL, 0, - MENUITEMFLAG_00000002 | MENUITEMFLAG_LESSLEFTPADDING, - L_OPTIONS_110, // "Exit" + MENUITEMFLAG_SELECTABLE_CENTRE | MENUITEMFLAG_LESSHEIGHT | MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Are you sure you want to exit?\n", + 0, + NULL, + }, + { + MENUITEMTYPE_SEPARATOR, + 0, + 0, + 0x00000082, 0, NULL, }, { MENUITEMTYPE_SELECTABLE, 0, - 0, + MENUITEMFLAG_SELECTABLE_CENTRE, L_OPTIONS_190, // "Yes" 0, menuhandlerExitGame, @@ -3445,7 +3456,7 @@ struct menuitem g_ExitGameMenuItems[] = { { MENUITEMTYPE_SELECTABLE, 0, - MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, + MENUITEMFLAG_SELECTABLE_CENTRE | MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, L_OPTIONS_191, // "No" 0, NULL, @@ -3497,6 +3508,16 @@ struct menuitem g_SoloMissionOptionsMenuItems[] = { 0, (void *)&g_MissionDisplayOptionsMenuDialog, }, +#ifndef PLATFORM_N64 + { + MENUITEMTYPE_SELECTABLE, + 0, + MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_BIGFONT | MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Extended", + 0, + (void *)&g_ExtendedMenuDialog, + }, +#endif { MENUITEMTYPE_END }, }; @@ -3533,6 +3554,16 @@ struct menuitem g_2PMissionOptionsHMenuItems[] = { 0, (void *)&g_MissionDisplayOptionsMenuDialog, }, +#ifndef PLATFORM_N64 + { + MENUITEMTYPE_SELECTABLE, + 0, + MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Extended", + 0, + (void *)&g_ExtendedMenuDialog, + }, +#endif { MENUITEMTYPE_SEPARATOR, 0, @@ -3589,6 +3620,16 @@ struct menuitem g_2PMissionOptionsVMenuItems[] = { 0, (void *)&g_2PMissionDisplayOptionsVMenuDialog, }, +#ifndef PLATFORM_N64 + { + MENUITEMTYPE_SELECTABLE, + 0, + MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Extended", + 0, + (void *)&g_ExtendedMenuDialog, + }, +#endif { MENUITEMTYPE_SEPARATOR, 0, @@ -3657,6 +3698,16 @@ struct menuitem g_CiOptionsMenuItems[] = { 6, (void *)&g_CinemaMenuDialog, }, +#ifndef PLATFORM_N64 + { + MENUITEMTYPE_SELECTABLE, + 0, + MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_BIGFONT | MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Extended", + 7, + (void *)&g_ExtendedMenuDialog, + }, +#endif { MENUITEMTYPE_END }, }; @@ -4886,8 +4937,8 @@ struct menuitem g_MainMenuMenuItems[] = { { MENUITEMTYPE_SELECTABLE, 0, - MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_BIGFONT, - L_OPTIONS_110, // "Exit Game" + MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_BIGFONT | MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Exit Game", 0x00000007, (void *)&g_ExitGameMenuDialog, }, diff --git a/src/game/menu.c b/src/game/menu.c index 507dacc09..fa29c900d 100644 --- a/src/game/menu.c +++ b/src/game/menu.c @@ -488,11 +488,21 @@ char *menuResolveText(uintptr_t thing, void *dialogoritem) char *menuResolveParam2Text(struct menuitem *item) { +#ifndef PLATFORM_N64 + if (item->flags & MENUITEMFLAG_LITERAL_TEXT) { + return (const char *)item->param2; + } +#endif return menuResolveText(item->param2, item); } char *menuResolveDialogTitle(struct menudialogdef *dialogdef) { +#ifndef PLATFORM_N64 + if (dialogdef->flags & MENUDIALOGFLAG_LITERAL_TEXT) { + return (const char *)dialogdef->title; + } +#endif return menuResolveText(dialogdef->title, dialogdef); } @@ -746,6 +756,11 @@ void menuCalculateItemSize(struct menuitem *item, s16 *width, s16 *height, struc #endif if ((item->flags & (MENUITEMFLAG_LABEL_HASRIGHTTEXT | MENUITEMFLAG_BIGFONT)) == 0) { +#ifndef PLATFORM_N64 + if (item->flags & MENUITEMFLAG_LITERAL_TEXT) { + text = (const char *)item->param3; + } else +#endif text = menuResolveText(item->param3, item); // @bug: This is not how you check for an empty string diff --git a/src/game/player.c b/src/game/player.c index 351e6a7b8..2ecffb6a2 100644 --- a/src/game/player.c +++ b/src/game/player.c @@ -206,8 +206,8 @@ s32 g_NumDeathAnimations = 0; f32 g_PlayerDefaultFovY = 60.f; f32 g_PlayerCrosshairSway = 1.f; s32 g_PlayerMouseAimMode = MOUSEAIM_CLASSIC; -f32 g_PlayerMouseAimSpeedX = 0.75f; -f32 g_PlayerMouseAimSpeedY = 0.75f; +f32 g_PlayerMouseAimSpeedX = 0.7f; +f32 g_PlayerMouseAimSpeedY = 0.7f; s32 g_PlayerFovAffectsZoom = 1; f32 g_PlayerFovZoomMultiplier = 1.0f; s32 g_PlayerClassicCrouch = true; diff --git a/src/include/constants.h b/src/include/constants.h index 14a1bc83b..e2751bdcf 100644 --- a/src/include/constants.h +++ b/src/include/constants.h @@ -1618,6 +1618,9 @@ #define MENUDIALOGFLAG_0400 0x0400 #define MENUDIALOGFLAG_DROPOUTONCLOSE 0x0800 #define MENUDIALOGFLAG_1000 0x1000 +#ifndef PLATFORM_N64 +#define MENUDIALOGFLAG_LITERAL_TEXT 0x2000 +#endif #define MENUDIALOGSTATE_PREOPEN 0 #define MENUDIALOGSTATE_OPENING 1 @@ -1658,6 +1661,7 @@ #define MENUITEMFLAG_LABEL_CUSTOMCOLOUR 0x01000000 #define MENUITEMFLAG_LESSHEIGHT 0x02000000 #define MENUITEMFLAG_CAROUSEL_04000000 0x04000000 +#define MENUITEMFLAG_LITERAL_TEXT 0x08000000 #define MENUITEMTYPE_LABEL 0x01 #define MENUITEMTYPE_LIST 0x02