From 1fb16b3bfd2f0fbc8fcbcbfc8c2cf21213d47ed5 Mon Sep 17 00:00:00 2001 From: Demon Date: Sun, 3 Dec 2023 13:18:27 +0800 Subject: [PATCH 01/55] Update README.md, add the minimal required gcc and sdl2 version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9c5e7de14..5ad82c0c2 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ Controls can be rebound in `pd.ini`. Default control scheme is as follows: ### Linux -1. Ensure you have gcc, g++ and 32-bit versions of SDL2, libGL and ZLib installed on your system. +1. Ensure you have gcc, g++ (both >=10) and 32-bit versions of SDL2 (>=2.0.14), libGL and ZLib installed on your system. * On a 64-bit system you also need to have `gcc-multilib` and `g++-multilib` (or your distro's analogues) installed. 2. Run the following command in the `perfect_dark` directory: * On a 64-bit system: ```make -f Makefile.port TARGET_PLATFORM=i686-linux``` From 39d5b57ccb2419776545528f3c66374028a2bc46 Mon Sep 17 00:00:00 2001 From: Demon Date: Tue, 5 Dec 2023 23:00:56 +0800 Subject: [PATCH 02/55] Update README.md, change minimal SDL2 version to 2.0.12 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5ad82c0c2..46cf7b737 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ Controls can be rebound in `pd.ini`. Default control scheme is as follows: ### Linux -1. Ensure you have gcc, g++ (both >=10) and 32-bit versions of SDL2 (>=2.0.14), libGL and ZLib installed on your system. +1. Ensure you have gcc, g++ (both >=10) and 32-bit versions of SDL2 (>=2.0.12), libGL and ZLib installed on your system. * On a 64-bit system you also need to have `gcc-multilib` and `g++-multilib` (or your distro's analogues) installed. 2. Run the following command in the `perfect_dark` directory: * On a 64-bit system: ```make -f Makefile.port TARGET_PLATFORM=i686-linux``` From f46359b30724b806ee97414d66a9447520979822 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Tue, 5 Dec 2023 16:27:09 +0100 Subject: [PATCH 03/55] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 46cf7b737..11912dbd9 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ Controls can be rebound in `pd.ini`. Default control scheme is as follows: ### Linux -1. Ensure you have gcc, g++ (both >=10) and 32-bit versions of SDL2 (>=2.0.12), libGL and ZLib installed on your system. +1. Ensure you have gcc, g++ (version 10.0+) and 32-bit versions of SDL2 (version 2.0.12+), libGL and ZLib installed on your system. * On a 64-bit system you also need to have `gcc-multilib` and `g++-multilib` (or your distro's analogues) installed. 2. Run the following command in the `perfect_dark` directory: * On a 64-bit system: ```make -f Makefile.port TARGET_PLATFORM=i686-linux``` From 3118d01921ceaf1c563f630d67ab07692fc7344e Mon Sep 17 00:00:00 2001 From: fgsfds Date: Wed, 6 Dec 2023 14:57:21 +0100 Subject: [PATCH 04/55] port: don't render garbage in the first blur frame (fixes #287) --- port/src/pdsched.c | 5 +++++ src/game/bondview.c | 18 ++++++++++++++++-- src/game/texreset.c | 3 +++ src/include/data.h | 1 + 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/port/src/pdsched.c b/port/src/pdsched.c index 4501b15a5..1f8800565 100644 --- a/port/src/pdsched.c +++ b/port/src/pdsched.c @@ -104,6 +104,7 @@ bool g_SchedIsFirstTask = true; s32 g_PrevFrameFb = -1; s32 g_BlurFb = -1; s32 g_BlurFbCapTimer = -1; +bool g_BlurFbDirty = true; void schedSetCrashEnable1(bool enable) { @@ -390,8 +391,12 @@ void schedConsiderScreenshot(void) if (g_BlurFbCapTimer == 0) { videoCopyFramebuffer(g_BlurFb, 0, -1, -1); g_BlurFbCapTimer = -1; + g_BlurFbDirty = false; } else if (g_BlurFbCapTimer > 0) { --g_BlurFbCapTimer; + } else if (g_BlurFbCapTimer < 0) { + // no blur requested this frame, mark blur fb dirty + g_BlurFbDirty = true; } if (g_MenuData.screenshottimer >= 2) { diff --git a/src/game/bondview.c b/src/game/bondview.c index 2a086c614..af101fa37 100644 --- a/src/game/bondview.c +++ b/src/game/bondview.c @@ -289,6 +289,14 @@ Gfx *bviewDrawMotionBlur(Gfx *gdl, u32 colour, u32 alpha) if (!videoFramebuffersSupported()) { return gdl; } + + // capture fb at the end of this frame + g_BlurFbCapTimer = 0; + + // don't render first blur frame as we haven't captured the fb yet + if (g_BlurFbDirty) { + return gdl; + } #endif mainOverrideVariable("sfxxx", &sfxxx); @@ -312,7 +320,6 @@ Gfx *bviewDrawMotionBlur(Gfx *gdl, u32 colour, u32 alpha) viewleft << 2, viewtop << 2, viewleft, viewtop, (viewleft + viewwidth) << 2, (viewtop + viewheight) << 2, viewleft + viewwidth, viewtop + viewheight, 0, videoGetNativeWidth(), videoGetNativeHeight()); - g_BlurFbCapTimer = 0; #endif return gdl; @@ -521,6 +528,14 @@ Gfx *bviewDrawZoomBlur(Gfx *gdl, u32 colour, s32 alpha, f32 arg3, f32 arg4) if (!videoFramebuffersSupported()) { return gdl; } + + // capture fb at the end of this frame + g_BlurFbCapTimer = 0; + + // don't render first blur frame as we haven't captured the fb yet + if (g_BlurFbDirty) { + return gdl; + } #endif strcpy(var800a41c0, "stretchBlurGfx"); @@ -550,7 +565,6 @@ Gfx *bviewDrawZoomBlur(Gfx *gdl, u32 colour, s32 alpha, f32 arg3, f32 arg4) left << 2, top << 2, viewleft, viewtop, right << 2, bottom << 2, viewleft + viewwidth, viewtop + viewheight, 0, videoGetNativeWidth(), videoGetNativeHeight()); - g_BlurFbCapTimer = 0; #endif return gdl; diff --git a/src/game/texreset.c b/src/game/texreset.c index 4bf444113..1daf8c737 100644 --- a/src/game/texreset.c +++ b/src/game/texreset.c @@ -139,6 +139,9 @@ void texReset(void) // get backend texture settings g_TexFilter2D = videoGetTextureFilter2D() ? G_TF_BILERP : G_TF_POINT; + + // notify blur code that the blur framebuffer is probably full of garbage + g_BlurFbDirty = true; #endif g_TexWords = mempAlloc(ALIGN16(g_TexNumConfigs * 4), MEMPOOL_STAGE); diff --git a/src/include/data.h b/src/include/data.h index 0b93a521f..2f0afbe88 100644 --- a/src/include/data.h +++ b/src/include/data.h @@ -545,6 +545,7 @@ extern u32 g_HudAlignModeR; extern s32 g_PrevFrameFb; extern s32 g_BlurFb; extern s32 g_BlurFbCapTimer; +extern bool g_BlurFbDirty; extern s32 g_TickRateDiv; extern s32 g_MusicDisableMpDeath; From 42af4d4604af0f6d0c46bf5efb7f55eae68284ed Mon Sep 17 00:00:00 2001 From: fgsfds Date: Wed, 6 Dec 2023 16:53:46 +0100 Subject: [PATCH 05/55] port: approximately normalize eyespy bob --- src/game/bondeyespy.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/game/bondeyespy.c b/src/game/bondeyespy.c index 1250f1f0a..cd15f48e3 100644 --- a/src/game/bondeyespy.c +++ b/src/game/bondeyespy.c @@ -1098,7 +1098,13 @@ void eyespyProcessInput(bool allowbuttons) if (g_Vars.currentplayer->eyespy->bobactive || ABS(g_Vars.currentplayer->eyespy->vel.y) < 0.1f) { g_Vars.currentplayer->eyespy->bobactive = true; g_Vars.currentplayer->eyespy->bobtimer += g_Vars.lvupdate60; +#ifdef PLATFORM_N64 g_Vars.currentplayer->eyespy->vel.y += 0.025f * g_Vars.currentplayer->eyespy->bobdir; +#else + // HACK: how do I scale this properly? + const f32 scale = (g_Vars.lvupdate60freal <= 1.1f) ? 0.0055f : 0.0125f; + g_Vars.currentplayer->eyespy->vel.y += scale * g_Vars.lvupdate60freal * g_Vars.currentplayer->eyespy->bobdir; +#endif if (g_Vars.currentplayer->eyespy->bobtimer > TICKS(120)) { g_Vars.currentplayer->eyespy->bobtimer = 0; From 3a313287bb5bf2dcdc841bdb29ff62a0f63f87c2 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Wed, 6 Dec 2023 17:10:48 +0100 Subject: [PATCH 06/55] port: fix config ints not clamping properly --- port/src/config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/port/src/config.c b/port/src/config.c index 5bce419e1..b10c5e5df 100644 --- a/port/src/config.c +++ b/port/src/config.c @@ -133,7 +133,7 @@ static void configSetFromString(const char *key, const char *val) 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); + tmp_s32 = configClampInt(tmp_s32, cfg->min_s32, cfg->max_s32); } *(s32 *)cfg->ptr = tmp_s32; break; From 7647062619228de43625f3a292dde1011ba7abec Mon Sep 17 00:00:00 2001 From: fgsfds Date: Wed, 6 Dec 2023 17:11:21 +0100 Subject: [PATCH 07/55] port: hard cap FPS to 200 for now --- port/fast3d/gfx_sdl2.cpp | 12 ++++++++---- port/fast3d/gfx_window_manager_api.h | 2 +- port/include/video.h | 3 +++ port/src/video.c | 12 ++++++++++-- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/port/fast3d/gfx_sdl2.cpp b/port/fast3d/gfx_sdl2.cpp index 274bf1230..07128bfcf 100644 --- a/port/fast3d/gfx_sdl2.cpp +++ b/port/fast3d/gfx_sdl2.cpp @@ -291,7 +291,7 @@ static void gfx_sdl_set_target_fps(int fps) { } static bool gfx_sdl_can_disable_vsync(void) { - return false; + return true; } static void *gfx_sdl_get_window_handle(void) { @@ -302,9 +302,13 @@ static void gfx_sdl_set_window_title(const char *title) { SDL_SetWindowTitle(wnd, title); } -static void gfx_sdl_set_swap_interval(int interval) { - SDL_GL_SetSwapInterval(interval); - vsync_enabled = (interval != 0); +static bool gfx_sdl_set_swap_interval(int interval) { + const bool success = SDL_GL_SetSwapInterval(interval) >= 0; + vsync_enabled = success && (interval != 0); + if (!success) { + sysLogPrintf(LOG_WARNING, "SDL: failed to set vsync %d: %s", interval, SDL_GetError()); + } + return success; } struct GfxWindowManagerAPI gfx_sdl = { diff --git a/port/fast3d/gfx_window_manager_api.h b/port/fast3d/gfx_window_manager_api.h index f4070f782..71886547e 100644 --- a/port/fast3d/gfx_window_manager_api.h +++ b/port/fast3d/gfx_window_manager_api.h @@ -22,7 +22,7 @@ struct GfxWindowManagerAPI { bool (*can_disable_vsync)(void); void *(*get_window_handle)(void); void (*set_window_title)(const char *); - void (*set_swap_interval)(int); + bool (*set_swap_interval)(int); }; #endif diff --git a/port/include/video.h b/port/include/video.h index ffd2c6728..2ebeda21e 100644 --- a/port/include/video.h +++ b/port/include/video.h @@ -4,6 +4,9 @@ #include #include +// maximum framerate; if the game runs faster than this, things will break +#define VIDEO_MAX_FPS 200 + s32 videoInit(void); void videoStartFrame(void); void videoSubmitCommands(Gfx *cmds); diff --git a/port/src/video.c b/port/src/video.c index 075546218..c0c2fb642 100644 --- a/port/src/video.c +++ b/port/src/video.c @@ -46,7 +46,15 @@ s32 videoInit(void) gfx_init(wmAPI, renderingAPI, "PD", vidFullscreen, vidWidth, vidHeight, 100, 100); - wmAPI->set_swap_interval(vidVsync); + if (!wmAPI->set_swap_interval(vidVsync)) { + vidVsync = 0; + } + + if (vidVsync == 0 && vidFramerateLimit == 0) { + // cap FPS if there's no vsync to prevent the game from exploding + vidFramerateLimit = VIDEO_MAX_FPS; + } + wmAPI->set_target_fps(vidFramerateLimit); // disabled because vsync is on renderingAPI->set_texture_filter((enum FilteringMode)texFilter); @@ -228,7 +236,7 @@ PD_CONSTRUCTOR static void videoConfigInit(void) 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.FramerateLimit", &vidFramerateLimit, 0, VIDEO_MAX_FPS); configRegisterInt("Video.MSAA", &vidMSAA, 1, 16); configRegisterInt("Video.TextureFilter", &texFilter, 0, 2); configRegisterInt("Video.TextureFilter2D", &texFilter2D, 0, 1); From 26da2aa5e6f0d3a76454c419ad9211792818863a Mon Sep 17 00:00:00 2001 From: fgsfds Date: Wed, 6 Dec 2023 17:12:13 +0100 Subject: [PATCH 08/55] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 11912dbd9..3b61708a4 100644 --- a/README.md +++ b/README.md @@ -30,9 +30,9 @@ There are minor graphics- and gameplay-related issues, and possibly occasional c * fixes for a couple original bugs and crashes; * basic mod support, currently enough to load a few custom levels; * slightly expanded memory heap size; -* experimental uncapped framerate support: +* experimental high framerate support (up to 200 FPS): * set `Game.TickRateDivisor` to `0` in `pd.ini` to activate; - * in practice the game will have issues running faster than ~150 FPS, so use VSync or `Video.FramerateLimit` to cap it. + * in practice the game will have issues running faster than ~165 FPS, so use VSync or `Video.FramerateLimit` to cap it. Currently only 32-bit platforms are supported, namely x86 Windows and Linux. Note that 32-bit binaries will still work on 64-bit versions of those platforms, From aeb68516068a9f02360a65ffc95ac51294b64da7 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Wed, 6 Dec 2023 17:16:34 +0100 Subject: [PATCH 09/55] port: change FPS hard cap to 240 on NTSC, 200 on PAL --- README.md | 2 +- port/include/video.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3b61708a4..d54b38e18 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ There are minor graphics- and gameplay-related issues, and possibly occasional c * fixes for a couple original bugs and crashes; * basic mod support, currently enough to load a few custom levels; * slightly expanded memory heap size; -* experimental high framerate support (up to 200 FPS): +* experimental high framerate support (up to 240 FPS): * set `Game.TickRateDivisor` to `0` in `pd.ini` to activate; * in practice the game will have issues running faster than ~165 FPS, so use VSync or `Video.FramerateLimit` to cap it. diff --git a/port/include/video.h b/port/include/video.h index 2ebeda21e..ab7e34575 100644 --- a/port/include/video.h +++ b/port/include/video.h @@ -5,7 +5,11 @@ #include // maximum framerate; if the game runs faster than this, things will break +#if PAL #define VIDEO_MAX_FPS 200 +#else +#define VIDEO_MAX_FPS 240 +#endif s32 videoInit(void); void videoStartFrame(void); From 03324c082374cfe95454aeb695378b711765aa44 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Thu, 7 Dec 2023 16:46:32 +0100 Subject: [PATCH 10/55] port: use correct aspect instead of 4:3 when scaling crosshair --- src/game/sight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/sight.c b/src/game/sight.c index 8bf2f4e6c..6dc76bd64 100644 --- a/src/game/sight.c +++ b/src/game/sight.c @@ -25,7 +25,7 @@ static inline f32 sightGetScaleX(void) { - return (videoGetAspect() / (4.f / 3.f)); + return (videoGetAspect() / SCREEN_ASPECT); } static inline s32 sightGetAdjustedX(const f32 x) From 0a7faf240939697cd4d24dd5ada3e2bceb2c583f Mon Sep 17 00:00:00 2001 From: fgsfds Date: Thu, 7 Dec 2023 17:20:04 +0100 Subject: [PATCH 11/55] port: add file patching system; add patch for #286 patch submitted by Ryan Dwyer --- port/src/romdata.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/port/src/romdata.c b/port/src/romdata.c index 08629ecf4..effc67e65 100644 --- a/port/src/romdata.c +++ b/port/src/romdata.c @@ -64,6 +64,13 @@ enum loadsource { SRC_EXTERNAL }; +struct romfilepatch { + u32 ofs; + u32 len; + const char *src; + const char *dst; +}; + struct romfile { u8 **segstart; u8 **segend; @@ -73,9 +80,21 @@ struct romfile { preprocessfunc preprocess; s32 source; // enum loadsource s32 preprocessed; + const struct romfilepatch *patches; + u32 numpatches; }; -static struct romfile fileSlots[ROMDATA_MAX_FILES]; +/* patches for individual files; applied on file load, before preprocFuncs, but */ +/* after unzip; only applied when loading from a ROM file */ +static const struct romfilepatch filePatches[] = { + /* FILE_USETUPLUE: fixes Jon's double "if what" in Infiltration outro */ + { 0x92a2, 1, "\x6c", "\x99" }, + { 0x92b0, 1, "\x6c", "\x99" }, +}; + +static struct romfile fileSlots[ROMDATA_MAX_FILES] = { + [FILE_USETUPLUE] = { .patches = &filePatches[0], .numpatches = 2 }, +}; #define ROMSEG_START(n) _ ## n ## SegmentRomStart #define ROMSEG_END(n) _ ## n ## SegmentRomEnd @@ -409,6 +428,8 @@ u8 *romdataFileLoad(s32 fileNum, u32 *outSize) fileSlots[fileNum].data = out; fileSlots[fileNum].size = size; fileSlots[fileNum].source = SRC_EXTERNAL; + // external file; do not apply patches to this + fileSlots[fileNum].numpatches = 0; } } // tried and failed, fall back to ROM @@ -435,6 +456,15 @@ void romdataFilePreprocess(s32 fileNum, s32 loadType, u8 *data, u32 size) if (data && size /* && !fileSlots[fileNum].preprocessed*/) { if (loadType && loadType < (u32)ARRAYCOUNT(filePreprocFuncs) && filePreprocFuncs[loadType]) { + // apply patches + for (u32 i = 0; i < fileSlots[fileNum].numpatches; ++i) { + const struct romfilepatch *p = &fileSlots[fileNum].patches[i]; + if (!memcmp(data + p->ofs, p->src, p->len)) { + memcpy(data + p->ofs, p->dst, p->len); + sysLogPrintf(LOG_NOTE, "file %d (%s) patched at offset 0x%x", fileNum, fileSlots[fileNum].name, p->ofs); + } + } + // then preprocess filePreprocFuncs[loadType](data, size); // fileSlots[fileNum].preprocessed = 1; } From cabd40f8984986d52046bda4116fd40e5c385e56 Mon Sep 17 00:00:00 2001 From: J Date: Mon, 11 Dec 2023 00:49:09 +0000 Subject: [PATCH 12/55] GE Muzzle flash addition --- src/game/bondgun.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/game/bondgun.c b/src/game/bondgun.c index b63ab0d2c..c17f39bd0 100644 --- a/src/game/bondgun.c +++ b/src/game/bondgun.c @@ -1911,7 +1911,13 @@ void bgun0f09a6f8(struct handweaponinfo *info, s32 handnum, struct hand *hand, s if (func->flags & FUNCFLAG_NOMUZZLEFLASH) { hand->flashon = false; } else { - hand->flashon = true; + if ( func->type != INVENTORYFUNCTYPE_SHOOT_SINGLE) { + if (hand->shotstotake % 2 == 1) { + hand->flashon = true; + } + } else { + hand->flashon = true; + } } bgunStartSlide(handnum); From 342e186f794d83c6832be5f621dc3b3b913e8d9d Mon Sep 17 00:00:00 2001 From: Bobby Lovell Date: Wed, 13 Dec 2023 13:06:48 -0500 Subject: [PATCH 13/55] Add option to change crosshair alpha, and could provide fully custom colors. Proof of concept. --- port/src/main.c | 2 ++ port/src/optionsmenu.c | 35 +++++++++++++++++++++++++ src/game/mplayer/mplayer.c | 3 ++- src/game/sight.c | 52 ++++++++++++++++++++++++++++++++++++++ src/include/types.h | 2 ++ 5 files changed, 93 insertions(+), 1 deletion(-) diff --git a/port/src/main.c b/port/src/main.c index 38d4da332..fbad0859c 100644 --- a/port/src/main.c +++ b/port/src/main.c @@ -166,5 +166,7 @@ PD_CONSTRUCTOR static void gameConfigInit(void) configRegisterFloat(strFmt("Game.Player%d.CrosshairSway", i), &g_PlayerExtCfg[j].crosshairsway, 0.f, 10.f); configRegisterInt(strFmt("Game.Player%d.CrouchMode", i), &g_PlayerExtCfg[j].crouchmode, 0, CROUCHMODE_TOGGLE_ANALOG); configRegisterInt(strFmt("Game.Player%d.ExtendedControls", i), &g_PlayerExtCfg[j].extcontrols, 0, 1); + configRegisterInt(strFmt("Game.Player%d.CrosshairAlpha", i), &g_PlayerExtCfg[j].crosshairalpha, 0, 255); + } } diff --git a/port/src/optionsmenu.c b/port/src/optionsmenu.c index e77e95322..24f353383 100644 --- a/port/src/optionsmenu.c +++ b/port/src/optionsmenu.c @@ -903,6 +903,33 @@ static MenuItemHandlerResult menuhandlerCrosshairSway(s32 operation, struct menu return 0; } +#define SIGHT_COLOUR_R 0; +#define SIGHT_COLOUR_G 255; +#define SIGHT_COLOUR_B 0; + +static u32 RGBAToINT(u32 r, u32 g, u32 b, u32 a) +{ + return (((r) & 0xff) << 24 | ((g) & 0xff) << 16 | ((b) & 0xff) << 8 | ((a) & 0xff)); +} + +static MenuItemHandlerResult menuhandlerCrosshairAlpha(s32 operation, struct menuitem* item, union handlerdata* data) +{ + switch (operation) { + case MENUOP_GETSLIDER: + data->slider.value = g_PlayerExtCfg[g_ExtMenuPlayer].crosshairalpha; + break; + case MENUOP_SET: + g_PlayerExtCfg[g_ExtMenuPlayer].crosshairalpha = data->slider.value; + + g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour = RGBAToINT(SIGHT_COLOUR_R, SIGHT_COLOUR_G, SIGHT_COLOUR_B, g_PlayerExtCfg[g_ExtMenuPlayer].crosshairalpha); + + break; + } + + return 0; +} + + struct menuitem g_ExtendedGameMenuItems[] = { { MENUITEMTYPE_DROPDOWN, @@ -928,6 +955,14 @@ struct menuitem g_ExtendedGameMenuItems[] = { 20, menuhandlerCrosshairSway, }, + { + MENUITEMTYPE_SLIDER, + 0, + MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE, + (uintptr_t)"Crosshair Alpha", + 255, + menuhandlerCrosshairAlpha, + }, { MENUITEMTYPE_SEPARATOR, 0, diff --git a/src/game/mplayer/mplayer.c b/src/game/mplayer/mplayer.c index d91f60a4e..5dd2584ce 100644 --- a/src/game/mplayer/mplayer.c +++ b/src/game/mplayer/mplayer.c @@ -121,7 +121,8 @@ struct mpweapon g_MpWeapons[NUM_MPWEAPONS] = { .radialmenuspeed = 4.f, \ .crosshairsway = 1.f, \ .crouchmode = CROUCHMODE_TOGGLE_ANALOG, \ - .extcontrols = true, \ + .crosshairalpha = 40, \ + .crosshaircolour = 0x00ff0028, \ } struct extplayerconfig g_PlayerExtCfg[MAX_PLAYERS] = { diff --git a/src/game/sight.c b/src/game/sight.c index 6dc76bd64..1206cac7d 100644 --- a/src/game/sight.c +++ b/src/game/sight.c @@ -459,7 +459,11 @@ Gfx *sightDrawAimer(Gfx *gdl, s32 x, s32 y, s32 radius, s32 cornergap, u32 colou s32 viewright = viewleft + viewwidth - 1; s32 viewbottom = viewtop + viewheight - 1; +#ifndef PLATFORM_N64 + gdl = textSetPrimColour(gdl, PLAYER_EXTCFG().crosshaircolour); +#else gdl = textSetPrimColour(gdl, 0x00ff0028); +#endif #ifndef PLATFORM_N64 x = sightGetAdjustedX(x); @@ -619,7 +623,11 @@ Gfx *sightDrawDelayedAimer(Gfx *gdl, s32 x, s32 y, s32 radius, s32 cornergap, u3 boxx = xpos; boxy = ypos; +#ifndef PLATFORM_N64 + gdl = textSetPrimColour(gdl, PLAYER_EXTCFG().crosshaircolour); +#else gdl = textSetPrimColour(gdl, 0x00ff0028); +#endif // Fill a 3x3 box at the live crosshair gDPHudRectangle(gdl++, x - 1, y - 1, x + 1, y - 1); @@ -677,7 +685,13 @@ Gfx *sightDrawDefault(Gfx *gdl, bool sighton) // SIGHTTRACKTYPE_NONE is used for unarmed, but this appears to be // unreachable. The aimer is never drawn when unarmed. if (sighton) { + +#ifndef PLATFORM_N64 + colour = PLAYER_EXTCFG().crosshaircolour; +#else colour = 0x00ff0028; +#endif + radius = 8; cornergap = 5; gdl = sightDrawAimer(gdl, x, y, radius, cornergap, colour); @@ -687,7 +701,13 @@ Gfx *sightDrawDefault(Gfx *gdl, bool sighton) // For most guns, render the aimer if holding R if (sighton) { if (g_Vars.currentplayer->lookingatprop.prop == NULL) { + +#ifndef PLATFORM_N64 + colour = PLAYER_EXTCFG().crosshaircolour; +#else colour = 0x00ff0028; +#endif + radius = 8; cornergap = 5; } else { @@ -716,7 +736,13 @@ Gfx *sightDrawDefault(Gfx *gdl, bool sighton) s32 texty; if (g_Vars.currentplayer->lookingatprop.prop == NULL) { + +#ifndef PLATFORM_N64 + colour = PLAYER_EXTCFG().crosshaircolour; +#else colour = 0x00ff0028; +#endif + radius = 8; cornergap = 5; } else { @@ -761,7 +787,13 @@ Gfx *sightDrawDefault(Gfx *gdl, bool sighton) if (sighton) { if (g_Vars.currentplayer->lookingatprop.prop == NULL) { + +#ifndef PLATFORM_N64 + colour = PLAYER_EXTCFG().crosshaircolour; +#else colour = 0x00ff0028; +#endif + radius = 8; cornergap = 5; } else { @@ -832,7 +864,13 @@ Gfx *sightDrawDefault(Gfx *gdl, bool sighton) if (sighton) { if (g_Vars.currentplayer->lookingatprop.prop == NULL) { + +#ifndef PLATFORM_N64 + colour = PLAYER_EXTCFG().crosshaircolour; +#else colour = 0x00ff0028; +#endif + radius = 8; cornergap = 5; } else { @@ -1252,7 +1290,12 @@ Gfx *sightDrawZoom(Gfx *gdl, bool sighton) if (showzoomrange) { gdl = text0f153628(gdl); + +#ifndef PLATFORM_N64 + gdl = textSetPrimColour(gdl, PLAYER_EXTCFG().crosshaircolour); +#else gdl = textSetPrimColour(gdl, 0x00ff0028); +#endif if (frac < 0.2f) { cornerwidth *= 0.2f; @@ -1436,7 +1479,12 @@ Gfx *sightDrawMaian(Gfx *gdl, bool sighton) gSPTri4(gdl++, 0, 4, 5, 5, 3, 6, 7, 6, 1, 4, 7, 2); gdl = func0f0d49c8(gdl); + +#ifndef PLATFORM_N64 + gdl = textSetPrimColour(gdl, PLAYER_EXTCFG().crosshaircolour); +#else gdl = textSetPrimColour(gdl, 0x00ff0028); +#endif // Draw border over inner points gDPHudRectangle(gdl++, x - 4, y - 4, x - 4, y + 4); // left @@ -1464,7 +1512,11 @@ Gfx *sightDrawTarget(Gfx *gdl) mainOverrideVariable("sout", &var80070f9c); mainOverrideVariable("sin", &var80070fa0); +#ifndef PLATFORM_N64 + gdl = textSetPrimColour(gdl, PLAYER_EXTCFG().crosshaircolour); +#else gdl = textSetPrimColour(gdl, 0x00ff0028); +#endif #ifndef PLATFORM_N64 gSPSetExtraGeometryModeEXT(gdl++, G_ASPECT_CENTER_EXT); diff --git a/src/include/types.h b/src/include/types.h index 67a8eddaf..4737f178b 100644 --- a/src/include/types.h +++ b/src/include/types.h @@ -6139,6 +6139,8 @@ struct extplayerconfig { f32 radialmenuspeed; f32 crosshairsway; s32 extcontrols; + u32 crosshairalpha; + u32 crosshaircolour; }; #endif From 2a6625278ab6c79d3568de80cad8380cddd9c539 Mon Sep 17 00:00:00 2001 From: Bobby Lovell Date: Wed, 13 Dec 2023 13:48:06 -0500 Subject: [PATCH 14/55] - Fix RGB defines - Just store the colour and parse RGBA values when modifying. --- port/src/main.c | 3 +-- port/src/optionsmenu.c | 12 ++++++------ src/game/mplayer/mplayer.c | 1 - src/include/types.h | 1 - 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/port/src/main.c b/port/src/main.c index fbad0859c..3b53d781c 100644 --- a/port/src/main.c +++ b/port/src/main.c @@ -166,7 +166,6 @@ PD_CONSTRUCTOR static void gameConfigInit(void) configRegisterFloat(strFmt("Game.Player%d.CrosshairSway", i), &g_PlayerExtCfg[j].crosshairsway, 0.f, 10.f); configRegisterInt(strFmt("Game.Player%d.CrouchMode", i), &g_PlayerExtCfg[j].crouchmode, 0, CROUCHMODE_TOGGLE_ANALOG); configRegisterInt(strFmt("Game.Player%d.ExtendedControls", i), &g_PlayerExtCfg[j].extcontrols, 0, 1); - configRegisterInt(strFmt("Game.Player%d.CrosshairAlpha", i), &g_PlayerExtCfg[j].crosshairalpha, 0, 255); - + configRegisterInt(strFmt("Game.Player%d.CrosshairColour", i), &g_PlayerExtCfg[j].crosshaircolour, 0, 0xFFFFFFFF); } } diff --git a/port/src/optionsmenu.c b/port/src/optionsmenu.c index 24f353383..34a28e74b 100644 --- a/port/src/optionsmenu.c +++ b/port/src/optionsmenu.c @@ -903,9 +903,10 @@ static MenuItemHandlerResult menuhandlerCrosshairSway(s32 operation, struct menu return 0; } -#define SIGHT_COLOUR_R 0; -#define SIGHT_COLOUR_G 255; -#define SIGHT_COLOUR_B 0; +// Stock sight RGB. +#define SIGHT_COLOUR_R 0 +#define SIGHT_COLOUR_G 255 +#define SIGHT_COLOUR_B 0 static u32 RGBAToINT(u32 r, u32 g, u32 b, u32 a) { @@ -916,12 +917,11 @@ static MenuItemHandlerResult menuhandlerCrosshairAlpha(s32 operation, struct men { switch (operation) { case MENUOP_GETSLIDER: - data->slider.value = g_PlayerExtCfg[g_ExtMenuPlayer].crosshairalpha; + data->slider.value = g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour & 0xFF; break; case MENUOP_SET: - g_PlayerExtCfg[g_ExtMenuPlayer].crosshairalpha = data->slider.value; - g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour = RGBAToINT(SIGHT_COLOUR_R, SIGHT_COLOUR_G, SIGHT_COLOUR_B, g_PlayerExtCfg[g_ExtMenuPlayer].crosshairalpha); + g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour = RGBAToINT(SIGHT_COLOUR_R, SIGHT_COLOUR_G, SIGHT_COLOUR_B, data->slider.value); break; } diff --git a/src/game/mplayer/mplayer.c b/src/game/mplayer/mplayer.c index 5dd2584ce..825d62a33 100644 --- a/src/game/mplayer/mplayer.c +++ b/src/game/mplayer/mplayer.c @@ -121,7 +121,6 @@ struct mpweapon g_MpWeapons[NUM_MPWEAPONS] = { .radialmenuspeed = 4.f, \ .crosshairsway = 1.f, \ .crouchmode = CROUCHMODE_TOGGLE_ANALOG, \ - .crosshairalpha = 40, \ .crosshaircolour = 0x00ff0028, \ } diff --git a/src/include/types.h b/src/include/types.h index 4737f178b..81b71ca6d 100644 --- a/src/include/types.h +++ b/src/include/types.h @@ -6139,7 +6139,6 @@ struct extplayerconfig { f32 radialmenuspeed; f32 crosshairsway; s32 extcontrols; - u32 crosshairalpha; u32 crosshaircolour; }; From fb05725c34c6ea278c9d99423a0dda51111b0c06 Mon Sep 17 00:00:00 2001 From: Bobby Lovell Date: Thu, 14 Dec 2023 10:13:27 -0500 Subject: [PATCH 15/55] - Implement RGBA. - Add preview label. --- port/src/optionsmenu.c | 164 ++++++++++++++++++++++++++++++++----- src/game/mplayer/mplayer.c | 2 +- 2 files changed, 145 insertions(+), 21 deletions(-) diff --git a/port/src/optionsmenu.c b/port/src/optionsmenu.c index 34a28e74b..81dbbb6db 100644 --- a/port/src/optionsmenu.c +++ b/port/src/optionsmenu.c @@ -903,32 +903,156 @@ static MenuItemHandlerResult menuhandlerCrosshairSway(s32 operation, struct menu return 0; } -// Stock sight RGB. -#define SIGHT_COLOUR_R 0 -#define SIGHT_COLOUR_G 255 -#define SIGHT_COLOUR_B 0 - -static u32 RGBAToINT(u32 r, u32 g, u32 b, u32 a) -{ - return (((r) & 0xff) << 24 | ((g) & 0xff) << 16 | ((b) & 0xff) << 8 | ((a) & 0xff)); -} - -static MenuItemHandlerResult menuhandlerCrosshairAlpha(s32 operation, struct menuitem* item, union handlerdata* data) +static MenuItemHandlerResult menuhandlerCrosshair_R(s32 operation, struct menuitem* item, union handlerdata* data) { switch (operation) { case MENUOP_GETSLIDER: - data->slider.value = g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour & 0xFF; + data->slider.value = (g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour >> 24) & 0xFF; break; + case MENUOP_SET: - - g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour = RGBAToINT(SIGHT_COLOUR_R, SIGHT_COLOUR_G, SIGHT_COLOUR_B, data->slider.value); - + u32 newColor = g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour & 0xFFFFFF | data->slider.value << 24; + g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour = newColor; break; } return 0; } +static MenuItemHandlerResult menuhandlerCrosshair_G(s32 operation, struct menuitem* item, union handlerdata* data) +{ + switch (operation) { + case MENUOP_GETSLIDER: + data->slider.value = (g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour >> 16) & 0xFF; + break; + + case MENUOP_SET: + u32 newColor = g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour & 0xFF00FFFF | data->slider.value << 16; + g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour = newColor; + break; + } + + return 0; +} + +static MenuItemHandlerResult menuhandlerCrosshair_B(s32 operation, struct menuitem* item, union handlerdata* data) +{ + switch (operation) { + case MENUOP_GETSLIDER: + data->slider.value = (g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour >> 8) & 0xFF; + break; + + case MENUOP_SET: + u32 newColor = g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour & 0xFFFF00FF | data->slider.value << 8; + g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour = newColor; + break; + } + + return 0; +} + +static MenuItemHandlerResult menuhandlerCrosshair_A(s32 operation, struct menuitem* item, union handlerdata* data) +{ + switch (operation) { + case MENUOP_GETSLIDER: + data->slider.value = g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour & 0xFF; + break; + + case MENUOP_SET: + u32 newColor = g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour & 0xFFFFFF00 | data->slider.value; + g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour = newColor; + break; + } + + return 0; +} + +static MenuItemHandlerResult menuhandlerCrosshairColorPreview(s32 operation, struct menuitem* item, union handlerdata* data) +{ + if (operation == MENUOP_GETCOLOUR) { + data->label.colour1 = g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour; + data->label.colour2 = g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour; + } + + return 0; +} + +struct menuitem g_ExtendedGameCrosshairColourMenuItems[] = { + { + MENUITEMTYPE_SLIDER, + 0, + MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE, + (uintptr_t)"R", + 255, + menuhandlerCrosshair_R, + }, + { + MENUITEMTYPE_SLIDER, + 0, + MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE, + (uintptr_t)"G", + 255, + menuhandlerCrosshair_G, + }, + { + MENUITEMTYPE_SLIDER, + 0, + MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE, + (uintptr_t)"B", + 255, + menuhandlerCrosshair_B, + }, + { + MENUITEMTYPE_SLIDER, + 0, + MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE, + (uintptr_t)"Alpha", + 255, + menuhandlerCrosshair_A, + }, + { + MENUITEMTYPE_SEPARATOR, + 0, + 0, + 0, + 0, + NULL, + }, + { + MENUITEMTYPE_LABEL, + 0, + MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_LABEL_CUSTOMCOLOUR, + (uintptr_t)"PREVIEW\n", + 0, + menuhandlerCrosshairColorPreview, + }, + { + MENUITEMTYPE_SEPARATOR, + 0, + 0, + 0, + 0, + NULL, + }, + { + MENUITEMTYPE_SELECTABLE, + 0, + MENUITEMFLAG_SELECTABLE_CLOSESDIALOG, + L_OPTIONS_213, // "Back" + 0, + NULL, + }, + { MENUITEMTYPE_END }, +}; + +struct menudialogdef g_ExtendedGameCrosshairColourMenuDialog = { + MENUDIALOGTYPE_DEFAULT, + (uintptr_t)"Crosshair Colour", + g_ExtendedGameCrosshairColourMenuItems, + NULL, + MENUDIALOGFLAG_LITERAL_TEXT, + NULL, +}; struct menuitem g_ExtendedGameMenuItems[] = { { @@ -956,12 +1080,12 @@ struct menuitem g_ExtendedGameMenuItems[] = { menuhandlerCrosshairSway, }, { - MENUITEMTYPE_SLIDER, + MENUITEMTYPE_SELECTABLE, 0, - MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE, - (uintptr_t)"Crosshair Alpha", - 255, - menuhandlerCrosshairAlpha, + MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SELECTABLE_OPENSDIALOG, + (uintptr_t)"Crosshair Colour\n", + 0, + (void*)&g_ExtendedGameCrosshairColourMenuDialog, }, { MENUITEMTYPE_SEPARATOR, diff --git a/src/game/mplayer/mplayer.c b/src/game/mplayer/mplayer.c index 825d62a33..b83d21d01 100644 --- a/src/game/mplayer/mplayer.c +++ b/src/game/mplayer/mplayer.c @@ -121,7 +121,7 @@ struct mpweapon g_MpWeapons[NUM_MPWEAPONS] = { .radialmenuspeed = 4.f, \ .crosshairsway = 1.f, \ .crouchmode = CROUCHMODE_TOGGLE_ANALOG, \ - .crosshaircolour = 0x00ff0028, \ + .crosshaircolour = 0x00ff0028, \ // Stock green color. } struct extplayerconfig g_PlayerExtCfg[MAX_PLAYERS] = { From 894ea53b291c968501c2959d8482056ba9dec8d4 Mon Sep 17 00:00:00 2001 From: Bobby Lovell Date: Thu, 14 Dec 2023 10:18:43 -0500 Subject: [PATCH 16/55] Spell out colors... --- port/src/optionsmenu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/port/src/optionsmenu.c b/port/src/optionsmenu.c index 81dbbb6db..931c95923 100644 --- a/port/src/optionsmenu.c +++ b/port/src/optionsmenu.c @@ -982,7 +982,7 @@ struct menuitem g_ExtendedGameCrosshairColourMenuItems[] = { MENUITEMTYPE_SLIDER, 0, MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE, - (uintptr_t)"R", + (uintptr_t)"Red", 255, menuhandlerCrosshair_R, }, @@ -990,7 +990,7 @@ struct menuitem g_ExtendedGameCrosshairColourMenuItems[] = { MENUITEMTYPE_SLIDER, 0, MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE, - (uintptr_t)"G", + (uintptr_t)"Green", 255, menuhandlerCrosshair_G, }, @@ -998,7 +998,7 @@ struct menuitem g_ExtendedGameCrosshairColourMenuItems[] = { MENUITEMTYPE_SLIDER, 0, MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE, - (uintptr_t)"B", + (uintptr_t)"Blue", 255, menuhandlerCrosshair_B, }, From 8421140e3fbbde18f6d4f4afc4470c3ee3398455 Mon Sep 17 00:00:00 2001 From: Bobby Lovell Date: Thu, 14 Dec 2023 10:31:47 -0500 Subject: [PATCH 17/55] Remove comment. --- src/game/mplayer/mplayer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/mplayer/mplayer.c b/src/game/mplayer/mplayer.c index b83d21d01..825d62a33 100644 --- a/src/game/mplayer/mplayer.c +++ b/src/game/mplayer/mplayer.c @@ -121,7 +121,7 @@ struct mpweapon g_MpWeapons[NUM_MPWEAPONS] = { .radialmenuspeed = 4.f, \ .crosshairsway = 1.f, \ .crouchmode = CROUCHMODE_TOGGLE_ANALOG, \ - .crosshaircolour = 0x00ff0028, \ // Stock green color. + .crosshaircolour = 0x00ff0028, \ } struct extplayerconfig g_PlayerExtCfg[MAX_PLAYERS] = { From 519bd95a7516ca6798caae5fa6e35baa3667dc47 Mon Sep 17 00:00:00 2001 From: Bobby Lovell Date: Thu, 14 Dec 2023 14:49:13 -0500 Subject: [PATCH 18/55] Center preview text. --- port/src/optionsmenu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/port/src/optionsmenu.c b/port/src/optionsmenu.c index 931c95923..c700b8dcb 100644 --- a/port/src/optionsmenu.c +++ b/port/src/optionsmenu.c @@ -1021,7 +1021,7 @@ struct menuitem g_ExtendedGameCrosshairColourMenuItems[] = { { MENUITEMTYPE_LABEL, 0, - MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_LABEL_CUSTOMCOLOUR, + MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_LABEL_CUSTOMCOLOUR | MENUITEMFLAG_SELECTABLE_CENTRE, (uintptr_t)"PREVIEW\n", 0, menuhandlerCrosshairColorPreview, From 79fb976bcfd12b1767279c0e9a2818c083eb1491 Mon Sep 17 00:00:00 2001 From: Bobby Lovell Date: Thu, 14 Dec 2023 16:03:29 -0500 Subject: [PATCH 19/55] Implement a simple colored box menu item type and use that for the preview. --- port/src/optionsmenu.c | 7 +++---- src/game/menu.c | 3 +++ src/game/menuitem.c | 31 +++++++++++++++++++++++++++++++ src/include/constants.h | 4 ++++ src/include/game/menuitem.h | 4 ++++ 5 files changed, 45 insertions(+), 4 deletions(-) diff --git a/port/src/optionsmenu.c b/port/src/optionsmenu.c index c700b8dcb..b3f80e207 100644 --- a/port/src/optionsmenu.c +++ b/port/src/optionsmenu.c @@ -971,7 +971,6 @@ static MenuItemHandlerResult menuhandlerCrosshairColorPreview(s32 operation, str { if (operation == MENUOP_GETCOLOUR) { data->label.colour1 = g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour; - data->label.colour2 = g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour; } return 0; @@ -1019,10 +1018,10 @@ struct menuitem g_ExtendedGameCrosshairColourMenuItems[] = { NULL, }, { - MENUITEMTYPE_LABEL, + MENUITEMTYPE_COLORBOX, + 0, + 0, 0, - MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_LABEL_CUSTOMCOLOUR | MENUITEMFLAG_SELECTABLE_CENTRE, - (uintptr_t)"PREVIEW\n", 0, menuhandlerCrosshairColorPreview, }, diff --git a/src/game/menu.c b/src/game/menu.c index b63ad6315..46e743aca 100644 --- a/src/game/menu.c +++ b/src/game/menu.c @@ -1178,6 +1178,9 @@ bool menuIsItemFocusable(struct menuitem *item, struct menudialog *dialog, s32 a case MENUITEMTYPE_METER: case MENUITEMTYPE_MARQUEE: case MENUITEMTYPE_CONTROLLER: +#ifndef PLATFORM_N64 + case MENUITEMTYPE_COLORBOX: +#endif return false; case MENUITEMTYPE_10: case MENUITEMTYPE_14: diff --git a/src/game/menuitem.c b/src/game/menuitem.c index 11e53274d..d780e74ab 100644 --- a/src/game/menuitem.c +++ b/src/game/menuitem.c @@ -2109,6 +2109,36 @@ Gfx *menuitemMeterRender(Gfx *gdl, struct menurendercontext *context) return gdl; } +#ifndef PLATFORM_N64 + +// Draws a colored box which fills the background of the menu item. +Gfx* menuitemColorBoxRender(Gfx *gdl, struct menurendercontext *context) +{ + u32 width = context->width; + u32 height = context->height; + u32 colour1; + s32 x1; + s32 x2; + + x1 = context->x; + x2 = x1 + width; + + union handlerdata data; + if (context->item->handlervoid) { + context->item->handlervoid(MENUOP_GETCOLOUR, context->item, &data); + } + + colour1 = data.label.colour1; + + gdl = textSetPrimColour(gdl, colour1); + gDPFillRectangleScaled(gdl++, x1, context->y, x2, context->y + height); + gdl = text0f153838(gdl); + + return gdl; +} + +#endif + Gfx *menuitemSelectableRender(Gfx *gdl, struct menurendercontext *context) { u32 leftcolour; @@ -4349,6 +4379,7 @@ Gfx *menuitemRender(Gfx *gdl, struct menurendercontext *context) case MENUITEMTYPE_CAROUSEL: return menuitemCarouselRender(gdl, context); case MENUITEMTYPE_MODEL: return menuitemModelRender(gdl, context); case MENUITEMTYPE_CONTROLLER: return menuitemControllerRender(gdl, context); + case MENUITEMTYPE_COLORBOX: return menuitemColorBoxRender(gdl, context); } return gdl; diff --git a/src/include/constants.h b/src/include/constants.h index 943f172d3..8b39686d4 100644 --- a/src/include/constants.h +++ b/src/include/constants.h @@ -1692,6 +1692,10 @@ #define MENUITEMTYPE_CONTROLLER 0x19 #define MENUITEMTYPE_END 0x1a +#ifndef PLATFORM_N64 +#define MENUITEMTYPE_COLORBOX 0x1b +#endif + #define MENUMODELFLAG_HASSCALE 0x01 #define MENUMODELFLAG_HASPOSITION 0x02 #define MENUMODELFLAG_HASROTATION 0x04 diff --git a/src/include/game/menuitem.h b/src/include/game/menuitem.h index 27747bf71..79b868989 100644 --- a/src/include/game/menuitem.h +++ b/src/include/game/menuitem.h @@ -32,6 +32,10 @@ Gfx *menuitemLabelRender(Gfx *gdl, struct menurendercontext *context); Gfx *menuitemMeterRender(Gfx *gdl, struct menurendercontext *context); +#ifndef PLATFORM_N64 +Gfx *menuitemColorBoxRender(Gfx *gdl, struct menurendercontext *context); +#endif + Gfx *menuitemSelectableRender(Gfx *gdl, struct menurendercontext *context); bool menuitemSelectableTick(struct menuitem *item, struct menuinputs *inputs, u32 tickflags); From e84d83e404bc5abf4e7eefaaf136e3512aeae35e Mon Sep 17 00:00:00 2001 From: Bobby Lovell Date: Thu, 14 Dec 2023 16:08:53 -0500 Subject: [PATCH 20/55] Add missing ndef. --- src/game/menuitem.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/game/menuitem.c b/src/game/menuitem.c index d780e74ab..0f5d68b6b 100644 --- a/src/game/menuitem.c +++ b/src/game/menuitem.c @@ -4379,7 +4379,11 @@ Gfx *menuitemRender(Gfx *gdl, struct menurendercontext *context) case MENUITEMTYPE_CAROUSEL: return menuitemCarouselRender(gdl, context); case MENUITEMTYPE_MODEL: return menuitemModelRender(gdl, context); case MENUITEMTYPE_CONTROLLER: return menuitemControllerRender(gdl, context); + +#ifndef PLATFORM_N64 case MENUITEMTYPE_COLORBOX: return menuitemColorBoxRender(gdl, context); +#endif + } return gdl; From 880a7a0971b07afbceb02c6cc4039e9716d963e4 Mon Sep 17 00:00:00 2001 From: Bobby Lovell Date: Fri, 15 Dec 2023 08:10:31 -0500 Subject: [PATCH 21/55] Add back line inadvertently removed in 342e186f794d83c6832be5f621dc3b3b913e8d9d --- src/game/mplayer/mplayer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/game/mplayer/mplayer.c b/src/game/mplayer/mplayer.c index 825d62a33..409d6c246 100644 --- a/src/game/mplayer/mplayer.c +++ b/src/game/mplayer/mplayer.c @@ -121,6 +121,7 @@ struct mpweapon g_MpWeapons[NUM_MPWEAPONS] = { .radialmenuspeed = 4.f, \ .crosshairsway = 1.f, \ .crouchmode = CROUCHMODE_TOGGLE_ANALOG, \ + .extcontrols = true, \ .crosshaircolour = 0x00ff0028, \ } From 5aa799718a770a2e92414ccb654be842ed8029e2 Mon Sep 17 00:00:00 2001 From: Bobby Lovell Date: Fri, 15 Dec 2023 10:17:15 -0500 Subject: [PATCH 22/55] Add support for unsigned integers. --- port/src/config.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/port/src/config.c b/port/src/config.c index b10c5e5df..5f9f7289e 100644 --- a/port/src/config.c +++ b/port/src/config.c @@ -16,6 +16,7 @@ typedef enum { CFG_NONE, CFG_S32, CFG_F32, + CFG_U32, CFG_STR } configtype; @@ -27,6 +28,7 @@ struct configentry { union { struct { f32 min_f32, max_f32; }; struct { s32 min_s32, max_s32; }; + struct { u32 min_u32, max_u32; }; u32 max_str; }; } settings[CONFIG_MAX_SETTINGS]; @@ -38,6 +40,11 @@ static inline s32 configClampInt(s32 val, s32 min, s32 max) return (val < min) ? min : ((val > max) ? max : val); } +static inline u32 configClampUInt(u32 val, u32 min, u32 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); @@ -101,6 +108,17 @@ void configRegisterInt(const char *key, s32 *var, s32 min, s32 max) } } +void configRegisterUInt(const char* key, u32* var, u32 min, u32 max) +{ + struct configentry* cfg = configFindOrAddEntry(key); + if (cfg) { + cfg->type = CFG_U32; + cfg->ptr = var; + cfg->min_u32 = min; + cfg->max_u32 = max; + } +} + void configRegisterFloat(const char *key, f32 *var, f32 min, f32 max) { struct configentry *cfg = configFindOrAddEntry(key); @@ -129,6 +147,7 @@ static void configSetFromString(const char *key, const char *val) s32 tmp_s32; f32 tmp_f32; + u32 tmp_u32; switch (cfg->type) { case CFG_S32: tmp_s32 = atoi(val); @@ -144,6 +163,13 @@ static void configSetFromString(const char *key, const char *val) } *(f32 *)cfg->ptr = tmp_f32; break; + case CFG_U32: + tmp_u32 = atoll(val); + if (cfg->min_u32 < cfg->max_u32) { + tmp_u32 = configClampUInt(tmp_u32, cfg->min_u32, cfg->max_u32); + } + *(u32*)cfg->ptr = tmp_u32; + break; case CFG_STR: strncpy(cfg->ptr, val, cfg->max_str ? cfg->max_str - 1 : 4096); break; @@ -167,6 +193,12 @@ static void configSaveEntry(struct configentry *cfg, FILE *f) } fprintf(f, "%s=%f\n", cfg->key + cfg->seclen + 1, *(f32 *)cfg->ptr); break; + case CFG_U32: + if (cfg->min_u32 < cfg->max_u32) { + *(u32*)cfg->ptr = configClampUInt(*(u32*)cfg->ptr, cfg->min_u32, cfg->max_u32); + } + fprintf(f, "%s=%u\n", cfg->key + cfg->seclen + 1, *(u32*)cfg->ptr); + break; case CFG_STR: fprintf(f, "%s=%s\n", cfg->key + cfg->seclen + 1, (char *)cfg->ptr); break; From 8c509db8888a6b4895939d35b373a4288a070475 Mon Sep 17 00:00:00 2001 From: Dominic Della Valle Date: Sat, 16 Dec 2023 07:04:52 -0500 Subject: [PATCH 23/55] port: add start window maximized flag to config --- port/fast3d/gfx_api.h | 2 +- port/fast3d/gfx_pc.cpp | 4 ++-- port/fast3d/gfx_sdl2.cpp | 8 ++++++-- port/fast3d/gfx_window_manager_api.h | 2 +- port/src/video.c | 4 +++- 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/port/fast3d/gfx_api.h b/port/fast3d/gfx_api.h index 1f53f0ed4..3bf8427ad 100644 --- a/port/fast3d/gfx_api.h +++ b/port/fast3d/gfx_api.h @@ -31,7 +31,7 @@ extern float gfx_current_native_aspect; // The aspect ratio of the above mode extern bool gfx_framebuffers_enabled; void gfx_init(struct GfxWindowManagerAPI* wapi, struct GfxRenderingAPI* rapi, const char* game_name, - bool start_in_fullscreen, uint32_t width, uint32_t height, + bool start_in_fullscreen, bool start_maximized, uint32_t width, uint32_t height, uint32_t posX, uint32_t posY); void gfx_destroy(void); struct GfxRenderingAPI* gfx_get_current_rendering_api(void); diff --git a/port/fast3d/gfx_pc.cpp b/port/fast3d/gfx_pc.cpp index a5c997a31..cdd0d3e3c 100644 --- a/port/fast3d/gfx_pc.cpp +++ b/port/fast3d/gfx_pc.cpp @@ -2699,10 +2699,10 @@ extern "C" void gfx_get_dimensions(uint32_t* width, uint32_t* height, int32_t* p } extern "C" void gfx_init(struct GfxWindowManagerAPI* wapi, struct GfxRenderingAPI* rapi, const char* game_name, - bool start_in_fullscreen, uint32_t width, uint32_t height, uint32_t posX, uint32_t posY) { + bool start_in_fullscreen, bool start_maximized, uint32_t width, uint32_t height, uint32_t posX, uint32_t posY) { gfx_wapi = wapi; gfx_rapi = rapi; - gfx_wapi->init(game_name, rapi->get_name(), start_in_fullscreen, width, height, posX, posY); + gfx_wapi->init(game_name, rapi->get_name(), start_in_fullscreen, start_maximized, width, height, posX, posY); gfx_rapi->init(); gfx_rapi->update_framebuffer_parameters(0, width, height, 1, false, true, true, true); gfx_current_dimensions.internal_mul = 1; diff --git a/port/fast3d/gfx_sdl2.cpp b/port/fast3d/gfx_sdl2.cpp index 07128bfcf..778232eb8 100644 --- a/port/fast3d/gfx_sdl2.cpp +++ b/port/fast3d/gfx_sdl2.cpp @@ -84,7 +84,7 @@ static void gfx_sdl_get_active_window_refresh_rate(uint32_t* refresh_rate) { *refresh_rate = mode.refresh_rate; } -static void gfx_sdl_init(const char* game_name, const char* gfx_api_name, bool start_in_fullscreen, uint32_t width, +static void gfx_sdl_init(const char* game_name, const char* gfx_api_name, bool start_in_fullscreen, bool start_maximized, uint32_t width, uint32_t height, int32_t posX, int32_t posY) { window_width = width; window_height = height; @@ -110,7 +110,11 @@ static void gfx_sdl_init(const char* game_name, const char* gfx_api_name, bool s posY = 100; } - const Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_OPENGL; + Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_OPENGL; + if (start_maximized) { + flags |= SDL_WINDOW_MAXIMIZED; + } + wnd = SDL_CreateWindow(title, posX, posY, window_width, window_height, flags); if (!wnd) { sysFatalError("Could not open SDL window:\n%s", SDL_GetError()); diff --git a/port/fast3d/gfx_window_manager_api.h b/port/fast3d/gfx_window_manager_api.h index 71886547e..cc8893ace 100644 --- a/port/fast3d/gfx_window_manager_api.h +++ b/port/fast3d/gfx_window_manager_api.h @@ -5,7 +5,7 @@ #include struct GfxWindowManagerAPI { - void (*init)(const char* game_name, const char* gfx_api_name, bool start_in_fullscreen, uint32_t width, + void (*init)(const char* game_name, const char* gfx_api_name, bool start_in_fullscreen, bool start_maximized, uint32_t width, uint32_t height, int32_t posX, int32_t posY); void (*close)(void); void (*set_fullscreen_changed_callback)(void (*on_fullscreen_changed)(bool is_now_fullscreen)); diff --git a/port/src/video.c b/port/src/video.c index c0c2fb642..d645522bd 100644 --- a/port/src/video.c +++ b/port/src/video.c @@ -21,6 +21,7 @@ static s32 vidWidth = 640; static s32 vidHeight = 480; static s32 vidFramebuffers = true; static s32 vidFullscreen = false; +static s32 vidMaximize = false; static s32 vidVsync = 1; static s32 vidMSAA = 1; static s32 vidFramerateLimit = 0; @@ -44,7 +45,7 @@ s32 videoInit(void) gfx_framebuffers_enabled = (bool)vidFramebuffers; gfx_msaa_level = vidMSAA; - gfx_init(wmAPI, renderingAPI, "PD", vidFullscreen, vidWidth, vidHeight, 100, 100); + gfx_init(wmAPI, renderingAPI, "PD", vidFullscreen, vidMaximize, vidWidth, vidHeight, 100, 100); if (!wmAPI->set_swap_interval(vidVsync)) { vidVsync = 0; @@ -232,6 +233,7 @@ void videoFreeCachedTexture(const void *texptr) PD_CONSTRUCTOR static void videoConfigInit(void) { configRegisterInt("Video.DefaultFullscreen", &vidFullscreen, 0, 1); + configRegisterInt("Video.DefaultMaximize", &vidMaximize, 0, 1); configRegisterInt("Video.DefaultWidth", &vidWidth, 0, 32767); configRegisterInt("Video.DefaultHeight", &vidHeight, 0, 32767); configRegisterInt("Video.VSync", &vidVsync, -1, 10); From cdd7d6edacf2bfbdad9c56d40dea057fcfda3757 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sat, 16 Dec 2023 15:08:14 +0100 Subject: [PATCH 24/55] port: use strto* when parsing config instead of ato* allows hex values --- port/src/config.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/port/src/config.c b/port/src/config.c index 5f9f7289e..b37c2e955 100644 --- a/port/src/config.c +++ b/port/src/config.c @@ -50,7 +50,6 @@ 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) { @@ -150,21 +149,21 @@ static void configSetFromString(const char *key, const char *val) u32 tmp_u32; switch (cfg->type) { case CFG_S32: - tmp_s32 = atoi(val); + tmp_s32 = strtol(val, NULL, 0); if (cfg->min_s32 < cfg->max_s32) { tmp_s32 = configClampInt(tmp_s32, cfg->min_s32, cfg->max_s32); } *(s32 *)cfg->ptr = tmp_s32; break; case CFG_F32: - tmp_f32 = atof(val); + tmp_f32 = strtof(val, NULL); 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_U32: - tmp_u32 = atoll(val); + tmp_u32 = strtoul(val, NULL, 0); if (cfg->min_u32 < cfg->max_u32) { tmp_u32 = configClampUInt(tmp_u32, cfg->min_u32, cfg->max_u32); } @@ -197,7 +196,7 @@ static void configSaveEntry(struct configentry *cfg, FILE *f) if (cfg->min_u32 < cfg->max_u32) { *(u32*)cfg->ptr = configClampUInt(*(u32*)cfg->ptr, cfg->min_u32, cfg->max_u32); } - fprintf(f, "%s=%u\n", cfg->key + cfg->seclen + 1, *(u32*)cfg->ptr); + fprintf(f, "%s=%u\n", cfg->key + cfg->seclen + 1, *(u32 *)cfg->ptr); break; case CFG_STR: fprintf(f, "%s=%s\n", cfg->key + cfg->seclen + 1, (char *)cfg->ptr); From 28218b26c284abf94188be0b326a35b8fb18bfad Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sat, 16 Dec 2023 15:22:23 +0100 Subject: [PATCH 25/55] port: add setting for GE muzzle flashes and disable it by default --- port/src/main.c | 1 + port/src/optionsmenu.c | 21 +++++++++++++++++++++ src/game/bondgun.c | 12 ++++++++++-- src/include/data.h | 1 + 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/port/src/main.c b/port/src/main.c index 38d4da332..e8a71c479 100644 --- a/port/src/main.c +++ b/port/src/main.c @@ -155,6 +155,7 @@ PD_CONSTRUCTOR static void gameConfigInit(void) configRegisterInt("Game.TickRateDivisor", &g_TickRateDiv, 0, 10); configRegisterInt("Game.SkipIntro", &g_SkipIntro, 0, 1); configRegisterInt("Game.DisableMpDeathMusic", &g_MusicDisableMpDeath, 0, 1); + configRegisterInt("Game.GEMuzzleFlashes", &g_BgunGeMuzzleFlashes, 0, 1); for (s32 j = 0; j < MAX_PLAYERS; ++j) { const s32 i = j + 1; configRegisterFloat(strFmt("Game.Player%d.FovY", i), &g_PlayerExtCfg[j].fovy, 5.f, 175.f); diff --git a/port/src/optionsmenu.c b/port/src/optionsmenu.c index e77e95322..0c6b2a9d3 100644 --- a/port/src/optionsmenu.c +++ b/port/src/optionsmenu.c @@ -678,6 +678,19 @@ static MenuItemHandlerResult menuhandlerTexFilter2D(s32 operation, struct menuit return 0; } +static MenuItemHandlerResult menuhandlerGeMuzzleFlashes(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GET: + return g_BgunGeMuzzleFlashes; + case MENUOP_SET: + g_BgunGeMuzzleFlashes = data->checkbox.value; + break; + } + + return 0; +} + static MenuItemHandlerResult menuhandlerCenterHUD(s32 operation, struct menuitem *item, union handlerdata *data) { static const char *opts[] = { @@ -751,6 +764,14 @@ struct menuitem g_ExtendedVideoMenuItems[] = { 0, menuhandlerTexFilter2D, }, + { + MENUITEMTYPE_CHECKBOX, + 0, + MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"GE64-style Muzzle Flashes", + 0, + menuhandlerGeMuzzleFlashes, + }, { MENUITEMTYPE_DROPDOWN, 0, diff --git a/src/game/bondgun.c b/src/game/bondgun.c index c17f39bd0..cb891c8c9 100644 --- a/src/game/bondgun.c +++ b/src/game/bondgun.c @@ -190,6 +190,10 @@ char var800700bc[][10] = { { 'x','x','x' }, // "xxx" }; +#ifndef PLATFORM_N64 +s32 g_BgunGeMuzzleFlashes = false; +#endif + #if !MATCHING || VERSION >= VERSION_NTSC_1_0 void bgunRumble(s32 handnum, s32 weaponnum) { @@ -1911,13 +1915,17 @@ void bgun0f09a6f8(struct handweaponinfo *info, s32 handnum, struct hand *hand, s if (func->flags & FUNCFLAG_NOMUZZLEFLASH) { hand->flashon = false; } else { - if ( func->type != INVENTORYFUNCTYPE_SHOOT_SINGLE) { - if (hand->shotstotake % 2 == 1) { +#ifdef PLATFORM_N64 + hand->flashon = true; +#else + if (g_BgunGeMuzzleFlashes) { + if (func->type != INVENTORYFUNCTYPE_SHOOT_SINGLE && (hand->shotstotake & 1)) { hand->flashon = true; } } else { hand->flashon = true; } +#endif } bgunStartSlide(handnum); diff --git a/src/include/data.h b/src/include/data.h index 2f0afbe88..315c8bb17 100644 --- a/src/include/data.h +++ b/src/include/data.h @@ -548,6 +548,7 @@ extern s32 g_BlurFbCapTimer; extern bool g_BlurFbDirty; extern s32 g_TickRateDiv; extern s32 g_MusicDisableMpDeath; +extern s32 g_BgunGeMuzzleFlashes; #define PLAYER_EXTCFG() g_PlayerExtCfg[g_Vars.currentplayerstats->mpindex & 3] #define PLAYER_DEFAULT_FOV (PLAYER_EXTCFG().fovy) From 1698f53728d254c36b588cbae8af4fa13927fa46 Mon Sep 17 00:00:00 2001 From: Bobby Lovell Date: Sat, 16 Dec 2023 10:20:32 -0500 Subject: [PATCH 26/55] Update main.c to use new UInt config for crosshair color --- port/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/port/src/main.c b/port/src/main.c index 743b8a699..8f8ec2af8 100644 --- a/port/src/main.c +++ b/port/src/main.c @@ -167,6 +167,6 @@ PD_CONSTRUCTOR static void gameConfigInit(void) configRegisterFloat(strFmt("Game.Player%d.CrosshairSway", i), &g_PlayerExtCfg[j].crosshairsway, 0.f, 10.f); configRegisterInt(strFmt("Game.Player%d.CrouchMode", i), &g_PlayerExtCfg[j].crouchmode, 0, CROUCHMODE_TOGGLE_ANALOG); configRegisterInt(strFmt("Game.Player%d.ExtendedControls", i), &g_PlayerExtCfg[j].extcontrols, 0, 1); - configRegisterInt(strFmt("Game.Player%d.CrosshairColour", i), &g_PlayerExtCfg[j].crosshaircolour, 0, 0xFFFFFFFF); + configRegisterUInt(strFmt("Game.Player%d.CrosshairColour", i), &g_PlayerExtCfg[j].crosshaircolour, 0, 0xFFFFFFFF); } } From 022183969954bc8c44db1bfda69acc92ecb4db86 Mon Sep 17 00:00:00 2001 From: Dominic Della Valle Date: Sat, 16 Dec 2023 09:14:38 -0500 Subject: [PATCH 27/55] port: add maximize window option to extended menu --- port/fast3d/gfx_sdl2.cpp | 24 ++++++++++++++++++++---- port/fast3d/gfx_window_manager_api.h | 1 + port/src/optionsmenu.c | 21 +++++++++++++++++++++ port/src/video.c | 13 +++++++++++++ 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/port/fast3d/gfx_sdl2.cpp b/port/fast3d/gfx_sdl2.cpp index 778232eb8..8e9dcfaf7 100644 --- a/port/fast3d/gfx_sdl2.cpp +++ b/port/fast3d/gfx_sdl2.cpp @@ -36,6 +36,7 @@ static bool vsync_enabled = true; static int window_width = DESIRED_SCREEN_WIDTH; static int window_height = DESIRED_SCREEN_HEIGHT; static bool fullscreen_state; +static bool maximized_state; static bool is_running = true; static void (*on_fullscreen_changed_callback)(bool is_now_fullscreen); @@ -76,6 +77,18 @@ static void set_fullscreen(bool on, bool call_callback) { } } +static void set_maximize_window(bool on) { + if (maximized_state == on) { + return; + } + maximized_state = on; + if (on) { + SDL_MaximizeWindow(wnd); + } else { + SDL_RestoreWindow (wnd); + } +} + static void gfx_sdl_get_active_window_refresh_rate(uint32_t* refresh_rate) { int display_in_use = SDL_GetWindowDisplayIndex(wnd); @@ -110,10 +123,7 @@ static void gfx_sdl_init(const char* game_name, const char* gfx_api_name, bool s posY = 100; } - Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_OPENGL; - if (start_maximized) { - flags |= SDL_WINDOW_MAXIMIZED; - } + const Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_OPENGL; wnd = SDL_CreateWindow(title, posX, posY, window_width, window_height, flags); if (!wnd) { @@ -185,6 +195,7 @@ static void gfx_sdl_init(const char* game_name, const char* gfx_api_name, bool s } #endif + set_maximize_window(start_maximized); set_fullscreen(start_in_fullscreen, false); } @@ -200,6 +211,10 @@ static void gfx_sdl_set_fullscreen(bool enable) { set_fullscreen(enable, true); } +static void gfx_sdl_set_maximize_window(bool enable) { + set_maximize_window(enable); +} + static void gfx_sdl_set_cursor_visibility(bool visible) { if (visible) { SDL_ShowCursor(SDL_ENABLE); @@ -320,6 +335,7 @@ struct GfxWindowManagerAPI gfx_sdl = { gfx_sdl_close, gfx_sdl_set_fullscreen_changed_callback, gfx_sdl_set_fullscreen, + gfx_sdl_set_maximize_window, gfx_sdl_get_active_window_refresh_rate, gfx_sdl_set_cursor_visibility, gfx_sdl_get_dimensions, diff --git a/port/fast3d/gfx_window_manager_api.h b/port/fast3d/gfx_window_manager_api.h index cc8893ace..44eda4160 100644 --- a/port/fast3d/gfx_window_manager_api.h +++ b/port/fast3d/gfx_window_manager_api.h @@ -10,6 +10,7 @@ struct GfxWindowManagerAPI { void (*close)(void); void (*set_fullscreen_changed_callback)(void (*on_fullscreen_changed)(bool is_now_fullscreen)); void (*set_fullscreen)(bool enable); + void (*set_maximize)(bool enable); void (*get_active_window_refresh_rate)(uint32_t* refresh_rate); void (*set_cursor_visibility)(bool visible); void (*get_dimensions)(uint32_t* width, uint32_t* height, int32_t* posX, int32_t* posY); diff --git a/port/src/optionsmenu.c b/port/src/optionsmenu.c index 0c6b2a9d3..3a22069b9 100644 --- a/port/src/optionsmenu.c +++ b/port/src/optionsmenu.c @@ -652,6 +652,19 @@ static MenuItemHandlerResult menuhandlerFullScreen(s32 operation, struct menuite return 0; } +static MenuItemHandlerResult menuhandlerMaximizeWindow(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GET: + return videoGetMaximizeWindow(); + case MENUOP_SET: + videoSetMaximizeWindow(data->checkbox.value); + break; + } + + return 0; +} + static MenuItemHandlerResult menuhandlerTexFilter(s32 operation, struct menuitem *item, union handlerdata *data) { switch (operation) { @@ -748,6 +761,14 @@ struct menuitem g_ExtendedVideoMenuItems[] = { 0, menuhandlerFullScreen, }, + { + MENUITEMTYPE_CHECKBOX, + 0, + MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Maximize Window", + 0, + menuhandlerMaximizeWindow, + }, { MENUITEMTYPE_CHECKBOX, 0, diff --git a/port/src/video.c b/port/src/video.c index d645522bd..18da94fc0 100644 --- a/port/src/video.c +++ b/port/src/video.c @@ -148,6 +148,11 @@ s32 videoGetFullscreen(void) return vidFullscreen; } +s32 videoGetMaximizeWindow(void) +{ + return vidMaximize; +} + f32 videoGetAspect(void) { return gfx_current_dimensions.aspect_ratio; @@ -177,6 +182,14 @@ void videoSetFullscreen(s32 fs) } } +void videoSetMaximizeWindow(s32 fs) +{ + if (fs != vidMaximize) { + vidMaximize = !!fs; + wmAPI->set_maximize(vidMaximize); + } +} + void videoSetTextureFilter(u32 filter) { if (filter > FILTER_THREE_POINT) filter = FILTER_THREE_POINT; From f2545b4e53be0f9652b7e3bd5511a6accb14510d Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sun, 17 Dec 2023 12:28:47 +0100 Subject: [PATCH 28/55] port: fix GE muzzleflashes on single-shot guns --- src/game/bondgun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/bondgun.c b/src/game/bondgun.c index cb891c8c9..7107d7f53 100644 --- a/src/game/bondgun.c +++ b/src/game/bondgun.c @@ -1919,7 +1919,7 @@ void bgun0f09a6f8(struct handweaponinfo *info, s32 handnum, struct hand *hand, s hand->flashon = true; #else if (g_BgunGeMuzzleFlashes) { - if (func->type != INVENTORYFUNCTYPE_SHOOT_SINGLE && (hand->shotstotake & 1)) { + if (func->type == INVENTORYFUNCTYPE_SHOOT_SINGLE || (hand->shotstotake & 1)) { hand->flashon = true; } } else { From 92c66c93dcfefb833ac7bd4eab5e5d4a44e303b4 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sun, 17 Dec 2023 12:51:53 +0100 Subject: [PATCH 29/55] port: correct HUD aspect in horizontal 2-player splitscreen too --- src/game/activemenu.c | 3 ++- src/game/bondgun.c | 6 +++--- src/game/hudmsg.c | 7 ++++--- src/game/mplayer/scenarios/holdthebriefcase.inc | 3 ++- src/game/mplayer/scenarios/kingofthehill.inc | 3 ++- src/game/mplayer/scenarios/popacap.inc | 3 ++- src/game/propobj.c | 2 +- src/game/radar.c | 5 +++++ 8 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/game/activemenu.c b/src/game/activemenu.c index 917504112..bba991a14 100644 --- a/src/game/activemenu.c +++ b/src/game/activemenu.c @@ -1275,7 +1275,8 @@ Gfx *amRender(Gfx *gdl) #endif #ifndef PLATFORM_N64 - if (PLAYERCOUNT() == 1) { + const s32 playercount = PLAYERCOUNT(); + if (playercount < 2 || (playercount == 2 && optionsGetScreenSplit() == SCREENSPLIT_HORIZONTAL)) { gSPSetExtraGeometryModeEXT(gdl++, G_ASPECT_CENTER_EXT); } #endif diff --git a/src/game/bondgun.c b/src/game/bondgun.c index 7107d7f53..67825c973 100644 --- a/src/game/bondgun.c +++ b/src/game/bondgun.c @@ -12797,7 +12797,7 @@ Gfx *bgunDrawHud(Gfx *gdl) gdl = text0f153628(gdl); #ifndef PLATFORM_N64 - if (playercount < 2) { + if (playercount < 2 || (playercount == 2 && optionsGetScreenSplit() == SCREENSPLIT_HORIZONTAL)) { gSPExtraGeometryModeEXT(gdl++, G_ASPECT_MODE_EXT, g_HudAlignModeR); } #endif @@ -13051,7 +13051,7 @@ Gfx *bgunDrawHud(Gfx *gdl) } #ifndef PLATFORM_N64 - if (playercount < 2) { + if (playercount < 2 || (playercount == 2 && optionsGetScreenSplit() == SCREENSPLIT_HORIZONTAL)) { gSPExtraGeometryModeEXT(gdl++, G_ASPECT_MODE_EXT, g_HudAlignModeL); } #endif @@ -13091,7 +13091,7 @@ Gfx *bgunDrawHud(Gfx *gdl) } #ifndef PLATFORM_N64 - if (playercount < 2) { + if (playercount < 2 || (playercount == 2 && optionsGetScreenSplit() == SCREENSPLIT_HORIZONTAL)) { gSPExtraGeometryModeEXT(gdl++, G_ASPECT_MODE_EXT, g_HudAlignModeR); } #endif diff --git a/src/game/hudmsg.c b/src/game/hudmsg.c index 650906509..6cbf73408 100644 --- a/src/game/hudmsg.c +++ b/src/game/hudmsg.c @@ -190,7 +190,7 @@ Gfx *hudmsgRenderMissionTimer(Gfx *gdl, u32 alpha) y = timery; #ifndef PLATFORM_N64 - if (PLAYERCOUNT() < 2) { + if (playercount < 2 || (playercount == 2 && optionsGetScreenSplit() == SCREENSPLIT_HORIZONTAL)) { gSPExtraGeometryModeEXT(gdl++, G_ASPECT_MODE_EXT, g_HudAlignModeL); } #endif @@ -282,7 +282,7 @@ Gfx *hudmsgRenderZoomRange(Gfx *gdl, u32 alpha) y2 = y + textheight; #ifndef PLATFORM_N64 - if (playercount == 1) { + if (playercount < 2 || (playercount == 2 && optionsGetScreenSplit() == SCREENSPLIT_HORIZONTAL)) { gSPSetExtraGeometryModeEXT(gdl++, G_ASPECT_CENTER_EXT); } #endif @@ -1450,7 +1450,8 @@ Gfx *hudmsgsRender(Gfx *gdl) } #ifndef PLATFORM_N64 - if (playercount < 2 && msg->state >= HUDMSGSTATE_FADINGIN) { + const bool doaspectfix = (playercount < 2) || (playercount == 2 && optionsGetScreenSplit() == SCREENSPLIT_HORIZONTAL); + if (doaspectfix && msg->state >= HUDMSGSTATE_FADINGIN) { if (msg->alignh == HUDMSGALIGN_SCREENLEFT || msg->alignh == HUDMSGALIGN_LEFT) { gSPExtraGeometryModeEXT(gdl++, G_ASPECT_MODE_EXT, g_HudAlignModeL); } else if (msg->alignh == HUDMSGALIGN_RIGHT) { diff --git a/src/game/mplayer/scenarios/holdthebriefcase.inc b/src/game/mplayer/scenarios/holdthebriefcase.inc index 53de09f69..4441a6050 100644 --- a/src/game/mplayer/scenarios/holdthebriefcase.inc +++ b/src/game/mplayer/scenarios/holdthebriefcase.inc @@ -417,7 +417,8 @@ Gfx *htbRenderHud(Gfx *gdl) #endif #ifndef PLATFORM_N64 - if (PLAYERCOUNT() == 1) { + const s32 playercount = PLAYERCOUNT(); + if (playercount < 2 || (playercount == 2 && optionsGetScreenSplit() == SCREENSPLIT_HORIZONTAL)) { gSPSetExtraGeometryModeEXT(gdl++, G_ASPECT_CENTER_EXT); } #endif diff --git a/src/game/mplayer/scenarios/kingofthehill.inc b/src/game/mplayer/scenarios/kingofthehill.inc index ed53d37f8..050ff36b7 100644 --- a/src/game/mplayer/scenarios/kingofthehill.inc +++ b/src/game/mplayer/scenarios/kingofthehill.inc @@ -583,7 +583,8 @@ Gfx *kohRenderHud(Gfx *gdl) } #ifndef PLATFORM_N64 - if (PLAYERCOUNT() == 1) { + const s32 playercount = PLAYERCOUNT(); + if (playercount < 2 || (playercount == 2 && optionsGetScreenSplit() == SCREENSPLIT_HORIZONTAL)) { gSPSetExtraGeometryModeEXT(gdl++, G_ASPECT_CENTER_EXT); } #endif diff --git a/src/game/mplayer/scenarios/popacap.inc b/src/game/mplayer/scenarios/popacap.inc index 4e499c87e..d0cc31933 100644 --- a/src/game/mplayer/scenarios/popacap.inc +++ b/src/game/mplayer/scenarios/popacap.inc @@ -312,7 +312,8 @@ Gfx *pacRenderHud(Gfx *gdl) sprintf(text, "%d:%02d", mins, secs); #ifndef PLATFORM_N64 - if (PLAYERCOUNT() == 1) { + const s32 playercount = PLAYERCOUNT(); + if (playercount < 2 || (playercount == 2 && optionsGetScreenSplit() == SCREENSPLIT_HORIZONTAL)) { gSPSetExtraGeometryModeEXT(gdl++, G_ASPECT_CENTER_EXT); } #endif diff --git a/src/game/propobj.c b/src/game/propobj.c index 3ba8b6dab..99c405475 100644 --- a/src/game/propobj.c +++ b/src/game/propobj.c @@ -20979,7 +20979,7 @@ Gfx *countdownTimerRender(Gfx *gdl) ms = (s32)floorf(value60 * 1.6666666269302f) - mins * 6000 - secs * 100; #ifndef PLATFORM_N64 - if (playercount == 1) { + if (playercount < 2 || (playercount == 2 && optionsGetScreenSplit() == SCREENSPLIT_HORIZONTAL)) { gSPSetExtraGeometryModeEXT(gdl++, G_ASPECT_CENTER_EXT); } #endif diff --git a/src/game/radar.c b/src/game/radar.c index e963747ba..a98ae6764 100644 --- a/src/game/radar.c +++ b/src/game/radar.c @@ -312,6 +312,11 @@ Gfx *radarRender(Gfx *gdl) } else if (optionsGetScreenSplit() != SCREENSPLIT_VERTICAL && playernum == 1) { g_RadarY -= 8; } +#ifndef PLATFORM_N64 + if (optionsGetScreenSplit() == SCREENSPLIT_HORIZONTAL) { + gSPExtraGeometryModeEXT(gdl++, G_ASPECT_MODE_EXT, g_HudAlignModeR); + } +#endif } else if (playercount >= 3) { if (playernum >= 2) { g_RadarY -= 8; From db1d00a9b02f5972b0da7e1a2b95f151a73d049e Mon Sep 17 00:00:00 2001 From: Richard M Date: Sun, 17 Dec 2023 11:50:16 -0700 Subject: [PATCH 30/55] port: add "Skedar Leader" track Add the "Skedar Leader" track to the Combat Simulator Soundtrack selection menu as "Skedar Warrior" as we do not currently have the ability to use the official track name --- src/game/mplayer/mplayer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/game/mplayer/mplayer.c b/src/game/mplayer/mplayer.c index d91f60a4e..c184298b0 100644 --- a/src/game/mplayer/mplayer.c +++ b/src/game/mplayer/mplayer.c @@ -2717,6 +2717,7 @@ struct mptrack g_MpTracks[] = { /*0x27*/ { MUSIC_SKEDARRUINS, 120, L_MISC_163, SOLOSTAGEINDEX_SKEDARRUINS }, // "Skedar Ruins" /*0x28*/ { MUSIC_SKEDARRUINS_X, 120, L_MISC_164, SOLOSTAGEINDEX_SKEDARRUINS }, // "Skedar Ruins X" /*0x29*/ { MUSIC_CREDITS, 120, L_MISC_165, SOLOSTAGEINDEX_SKEDARRUINS }, // "End Credits" + /*0x30*/ { MUSIC_SKEDARRUINS_KING,120, L_MISC_261, SOLOSTAGEINDEX_SKEDARRUINS }, // "Skedar Warrior" (Skedar Leader) }; bool mpIsTrackUnlocked(s32 tracknum) From a7ab358b435864f9c1838eaa33c9509c6978a9df Mon Sep 17 00:00:00 2001 From: fgsfds Date: Fri, 22 Dec 2023 12:32:13 +0100 Subject: [PATCH 31/55] port: simplify sight color code a bit --- src/game/sight.c | 75 +++++++++--------------------------------------- 1 file changed, 13 insertions(+), 62 deletions(-) diff --git a/src/game/sight.c b/src/game/sight.c index 1206cac7d..8e7ed749b 100644 --- a/src/game/sight.c +++ b/src/game/sight.c @@ -23,6 +23,8 @@ #include #include "video.h" +#define SIGHT_COLOUR PLAYER_EXTCFG().crosshaircolour + static inline f32 sightGetScaleX(void) { return (videoGetAspect() / SCREEN_ASPECT); @@ -36,6 +38,7 @@ static inline s32 sightGetAdjustedX(const f32 x) #else +#define SIGHT_COLOUR 0x00ff0028 #define sightGetScaleX() 1.f #define sightGetAdjustedX(x) (x) @@ -459,11 +462,7 @@ Gfx *sightDrawAimer(Gfx *gdl, s32 x, s32 y, s32 radius, s32 cornergap, u32 colou s32 viewright = viewleft + viewwidth - 1; s32 viewbottom = viewtop + viewheight - 1; -#ifndef PLATFORM_N64 - gdl = textSetPrimColour(gdl, PLAYER_EXTCFG().crosshaircolour); -#else - gdl = textSetPrimColour(gdl, 0x00ff0028); -#endif + gdl = textSetPrimColour(gdl, SIGHT_COLOUR); #ifndef PLATFORM_N64 x = sightGetAdjustedX(x); @@ -623,11 +622,7 @@ Gfx *sightDrawDelayedAimer(Gfx *gdl, s32 x, s32 y, s32 radius, s32 cornergap, u3 boxx = xpos; boxy = ypos; -#ifndef PLATFORM_N64 - gdl = textSetPrimColour(gdl, PLAYER_EXTCFG().crosshaircolour); -#else - gdl = textSetPrimColour(gdl, 0x00ff0028); -#endif + gdl = textSetPrimColour(gdl, SIGHT_COLOUR); // Fill a 3x3 box at the live crosshair gDPHudRectangle(gdl++, x - 1, y - 1, x + 1, y - 1); @@ -685,13 +680,7 @@ Gfx *sightDrawDefault(Gfx *gdl, bool sighton) // SIGHTTRACKTYPE_NONE is used for unarmed, but this appears to be // unreachable. The aimer is never drawn when unarmed. if (sighton) { - -#ifndef PLATFORM_N64 - colour = PLAYER_EXTCFG().crosshaircolour; -#else - colour = 0x00ff0028; -#endif - + colour = SIGHT_COLOUR; radius = 8; cornergap = 5; gdl = sightDrawAimer(gdl, x, y, radius, cornergap, colour); @@ -701,13 +690,7 @@ Gfx *sightDrawDefault(Gfx *gdl, bool sighton) // For most guns, render the aimer if holding R if (sighton) { if (g_Vars.currentplayer->lookingatprop.prop == NULL) { - -#ifndef PLATFORM_N64 - colour = PLAYER_EXTCFG().crosshaircolour; -#else - colour = 0x00ff0028; -#endif - + colour = SIGHT_COLOUR; radius = 8; cornergap = 5; } else { @@ -736,13 +719,7 @@ Gfx *sightDrawDefault(Gfx *gdl, bool sighton) s32 texty; if (g_Vars.currentplayer->lookingatprop.prop == NULL) { - -#ifndef PLATFORM_N64 - colour = PLAYER_EXTCFG().crosshaircolour; -#else - colour = 0x00ff0028; -#endif - + colour = SIGHT_COLOUR; radius = 8; cornergap = 5; } else { @@ -787,13 +764,7 @@ Gfx *sightDrawDefault(Gfx *gdl, bool sighton) if (sighton) { if (g_Vars.currentplayer->lookingatprop.prop == NULL) { - -#ifndef PLATFORM_N64 - colour = PLAYER_EXTCFG().crosshaircolour; -#else - colour = 0x00ff0028; -#endif - + colour = SIGHT_COLOUR; radius = 8; cornergap = 5; } else { @@ -864,13 +835,7 @@ Gfx *sightDrawDefault(Gfx *gdl, bool sighton) if (sighton) { if (g_Vars.currentplayer->lookingatprop.prop == NULL) { - -#ifndef PLATFORM_N64 - colour = PLAYER_EXTCFG().crosshaircolour; -#else - colour = 0x00ff0028; -#endif - + colour = SIGHT_COLOUR; radius = 8; cornergap = 5; } else { @@ -1290,12 +1255,7 @@ Gfx *sightDrawZoom(Gfx *gdl, bool sighton) if (showzoomrange) { gdl = text0f153628(gdl); - -#ifndef PLATFORM_N64 - gdl = textSetPrimColour(gdl, PLAYER_EXTCFG().crosshaircolour); -#else - gdl = textSetPrimColour(gdl, 0x00ff0028); -#endif + gdl = textSetPrimColour(gdl, SIGHT_COLOUR); if (frac < 0.2f) { cornerwidth *= 0.2f; @@ -1479,12 +1439,7 @@ Gfx *sightDrawMaian(Gfx *gdl, bool sighton) gSPTri4(gdl++, 0, 4, 5, 5, 3, 6, 7, 6, 1, 4, 7, 2); gdl = func0f0d49c8(gdl); - -#ifndef PLATFORM_N64 - gdl = textSetPrimColour(gdl, PLAYER_EXTCFG().crosshaircolour); -#else - gdl = textSetPrimColour(gdl, 0x00ff0028); -#endif + gdl = textSetPrimColour(gdl, SIGHT_COLOUR); // Draw border over inner points gDPHudRectangle(gdl++, x - 4, y - 4, x - 4, y + 4); // left @@ -1512,11 +1467,7 @@ Gfx *sightDrawTarget(Gfx *gdl) mainOverrideVariable("sout", &var80070f9c); mainOverrideVariable("sin", &var80070fa0); -#ifndef PLATFORM_N64 - gdl = textSetPrimColour(gdl, PLAYER_EXTCFG().crosshaircolour); -#else - gdl = textSetPrimColour(gdl, 0x00ff0028); -#endif + gdl = textSetPrimColour(gdl, SIGHT_COLOUR); #ifndef PLATFORM_N64 gSPSetExtraGeometryModeEXT(gdl++, G_ASPECT_CENTER_EXT); From f2a2458795e74e173d9b9dc0f1311f65b969d2c6 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Fri, 22 Dec 2023 12:33:34 +0100 Subject: [PATCH 32/55] port: fix typo --- src/game/mplayer/mplayer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/mplayer/mplayer.c b/src/game/mplayer/mplayer.c index 5c4bb3580..dc3e4cbb6 100644 --- a/src/game/mplayer/mplayer.c +++ b/src/game/mplayer/mplayer.c @@ -2718,7 +2718,7 @@ struct mptrack g_MpTracks[] = { /*0x27*/ { MUSIC_SKEDARRUINS, 120, L_MISC_163, SOLOSTAGEINDEX_SKEDARRUINS }, // "Skedar Ruins" /*0x28*/ { MUSIC_SKEDARRUINS_X, 120, L_MISC_164, SOLOSTAGEINDEX_SKEDARRUINS }, // "Skedar Ruins X" /*0x29*/ { MUSIC_CREDITS, 120, L_MISC_165, SOLOSTAGEINDEX_SKEDARRUINS }, // "End Credits" - /*0x30*/ { MUSIC_SKEDARRUINS_KING,120, L_MISC_261, SOLOSTAGEINDEX_SKEDARRUINS }, // "Skedar Warrior" (Skedar Leader) + /*0x2a*/ { MUSIC_SKEDARRUINS_KING,120, L_MISC_261, SOLOSTAGEINDEX_SKEDARRUINS }, // "Skedar Warrior" (Skedar Leader) }; bool mpIsTrackUnlocked(s32 tracknum) From 3c62a967a299c56a62be670723ea6ff5d2e93039 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Tue, 26 Dec 2023 22:58:08 +0100 Subject: [PATCH 33/55] port: display branch name in legal screen --- Makefile.port | 9 +++++++++ src/game/title.c | 2 ++ 2 files changed, 11 insertions(+) diff --git a/Makefile.port b/Makefile.port index db1d2bbd9..0a53f3d33 100644 --- a/Makefile.port +++ b/Makefile.port @@ -116,14 +116,23 @@ else endif VERSION_HASH := $(shell git rev-parse --short HEAD) +VERSION_BRANCH := $(shell git rev-parse --abbrev-ref HEAD) VERSION_TARGET := $(TARGET_PLATFORM) VERSION_ROMID := $(ROMID) +ifeq ($(VERSION_BRANCH),) + VERSION_BRANCH := port-custom +endif +ifeq ($(VERSION_BRANCH),HEAD) + VERSION_BRANCH := port-custom +endif + DEFINES := \ VERSION=$(VERSION) \ VERSION_HASH=\"$(VERSION_HASH)\" \ VERSION_TARGET=\"$(VERSION_TARGET)\" \ VERSION_ROMID=\"$(VERSION_ROMID)\" \ + VERSION_BRANCH=\"$(VERSION_BRANCH)\" \ MATCHING=0 \ PAL=$(IS_PAL) \ PIRACYCHECKS=0 \ diff --git a/src/game/title.c b/src/game/title.c index 23f48290f..db1a78531 100644 --- a/src/game/title.c +++ b/src/game/title.c @@ -372,6 +372,8 @@ Gfx *titleRenderLegal(Gfx *gdl) elem->textptr = VERSION_HASH " (" VERSION_TARGET ")"; } else if (elem->textid == L_OPTIONS_083) { elem->textptr = VERSION_ROMID; + } else if (elem->textid == L_OPTIONS_082) { + elem->textptr = "Perfect Dark (" VERSION_BRANCH ")"; } #endif break; From 787758c0385a9047240c238bebef89325e0b8cdb Mon Sep 17 00:00:00 2001 From: fgsfds Date: Thu, 28 Dec 2023 21:41:20 +0100 Subject: [PATCH 34/55] port: log branch name --- port/src/system.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/port/src/system.c b/port/src/system.c index d01e88060..5261f05cd 100644 --- a/port/src/system.c +++ b/port/src/system.c @@ -46,7 +46,7 @@ void sysInit(void) } #ifdef VERSION_HASH - sysLogPrintf(LOG_NOTE, "version: " VERSION_HASH " (" VERSION_TARGET ")"); + sysLogPrintf(LOG_NOTE, "version: " VERSION_BRANCH " " VERSION_HASH " (" VERSION_TARGET ")"); #endif char timestr[256]; From 49f607dd798f5c902c2abfb11732f19d3cfd9cf8 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sat, 30 Dec 2023 12:19:36 +0100 Subject: [PATCH 35/55] port: fix pal and jpn builds --- src/game/mplayer/mplayer.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/game/mplayer/mplayer.c b/src/game/mplayer/mplayer.c index dc3e4cbb6..efb63bfc0 100644 --- a/src/game/mplayer/mplayer.c +++ b/src/game/mplayer/mplayer.c @@ -2718,7 +2718,11 @@ struct mptrack g_MpTracks[] = { /*0x27*/ { MUSIC_SKEDARRUINS, 120, L_MISC_163, SOLOSTAGEINDEX_SKEDARRUINS }, // "Skedar Ruins" /*0x28*/ { MUSIC_SKEDARRUINS_X, 120, L_MISC_164, SOLOSTAGEINDEX_SKEDARRUINS }, // "Skedar Ruins X" /*0x29*/ { MUSIC_CREDITS, 120, L_MISC_165, SOLOSTAGEINDEX_SKEDARRUINS }, // "End Credits" +#if VERSION < VERSION_PAL_BETA /*0x2a*/ { MUSIC_SKEDARRUINS_KING,120, L_MISC_261, SOLOSTAGEINDEX_SKEDARRUINS }, // "Skedar Warrior" (Skedar Leader) +#else + /*0x2a*/ { MUSIC_SKEDARRUINS_KING,120, L_MISC_041, SOLOSTAGEINDEX_SKEDARRUINS }, // "E R R O R" (can't find a good approximation for Skedar Leader) +#endif }; bool mpIsTrackUnlocked(s32 tracknum) From c487e423b107c51fedf0b1f78a4378b77f8ec29f Mon Sep 17 00:00:00 2001 From: fgsfds Date: Wed, 3 Jan 2024 21:55:07 +0100 Subject: [PATCH 36/55] port: fix blur-related crash on Intel GPUs --- port/fast3d/gfx_opengl.cpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/port/fast3d/gfx_opengl.cpp b/port/fast3d/gfx_opengl.cpp index d446f111f..44c420e10 100644 --- a/port/fast3d/gfx_opengl.cpp +++ b/port/fast3d/gfx_opengl.cpp @@ -396,25 +396,22 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad if (cc_features.opt_blur) { // blur filter, used for menu backgrounds + // used to be two for loops from 0 to 4, but apparently intel drivers crashed trying to unroll it append_line(fs_buf, &fs_len, R"( - const vec4 blurOffsets = vec4(-1.5, -0.5, +0.5, +1.5); - const mat4 blurWeights = mat4( + const lowp float blurWeights[16] = float[16]( 0.009947, 0.009641, 0.008778, 0.007509, 0.009641, 0.009345, 0.008508, 0.007278, 0.008778, 0.008508, 0.007747, 0.006626, 0.007509, 0.007278, 0.006626, 0.005668 ); - lowp vec4 hookTexture2D(in sampler2D tex, in vec2 texCoord, in vec2 texSize) { - lowp vec4 color = vec4(0.0); - lowp float wacc = 0.0; - for (int y = 0; y < 4; ++y) { - for (int x = 0; x < 4; ++x) { - vec2 ofs = vec2(blurOffsets[x], blurOffsets[y]) / texSize; - wacc += blurWeights[x][y]; - color += texture2D(tex, texCoord + ofs) * blurWeights[x][y]; - } + lowp vec4 hookTexture2D(in sampler2D t, in vec2 uv, in vec2 tsize) { + lowp vec4 cw = vec4(0.0); + for (int i = 0; i < 16; ++i) { + vec2 xy = vec2(float(i & 3), float(i >> 2)); + vec2 ofs = (vec2(-1.5) + xy) / tsize; + cw += vec4(texture2D(t, uv + ofs).rgb * blurWeights[i], blurWeights[i]); } - return vec4(color.rgb / wacc, 1.0); + return vec4(cw.rgb / cw.a, 1.0); })" ); } else if (current_filter_mode == FILTER_THREE_POINT) { From b1b17e21c18f4e748598d961adeded28348b9b3c Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sun, 7 Jan 2024 15:40:30 +0100 Subject: [PATCH 37/55] port: write crash info to log file even without --log --- port/include/system.h | 1 + port/src/crash.c | 3 +++ port/src/system.c | 40 +++++++++++++++++++++++++++------------- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/port/include/system.h b/port/include/system.h index 005dbaf48..e6b75ac3d 100644 --- a/port/include/system.h +++ b/port/include/system.h @@ -24,6 +24,7 @@ u64 sysGetMicroseconds(void); void sysFatalError(const char *fmt, ...) __attribute__((noreturn)); +void sysLogStartCrash(void); void sysLogPrintf(s32 level, const char *fmt, ...); void sysGetExecutablePath(char *outPath, const u32 outLen); diff --git a/port/src/crash.c b/port/src/crash.c index 77a8228ed..1ea2ea557 100644 --- a/port/src/crash.c +++ b/port/src/crash.c @@ -128,6 +128,9 @@ static long __stdcall crashHandler(PEXCEPTION_POINTERS exinfo) return EXCEPTION_CONTINUE_EXECUTION; } + // start writing to a crash log file + sysLogStartCrash(); + sysLogPrintf(LOG_ERROR, "FATAL: Crashed: PC=%p CODE=0x%08lx", exinfo->ExceptionRecord->ExceptionAddress, exinfo->ExceptionRecord->ExceptionCode); fflush(stderr); diff --git a/port/src/system.c b/port/src/system.c index 5261f05cd..fb24addd0 100644 --- a/port/src/system.c +++ b/port/src/system.c @@ -11,6 +11,7 @@ #include "system.h" #define LOG_FNAME "pd.log" +#define CRASHLOG_FNAME "pd.crash.log" #define USEC_IN_SEC 1000000ULL static u64 startTick = 0; @@ -19,6 +20,24 @@ static char logPath[2048]; static s32 sysArgc; static const char **sysArgv; +static inline void sysLogSetPath(const char *fname) +{ + // figure out where the log is and clear it + // try working dir first + snprintf(logPath, sizeof(logPath), "./%s", fname); + FILE *f = fopen(logPath, "wb"); + if (!f) { + // try home dir + sysGetHomePath(logPath, sizeof(logPath) - 1); + strncat(logPath, "/", sizeof(logPath) - 1); + strncat(logPath, fname, sizeof(logPath) - 1); + f = fopen(logPath, "wb"); + } + if (f) { + fclose(f); + } +} + void sysInitArgs(s32 argc, const char **argv) { sysArgc = argc; @@ -30,19 +49,7 @@ void sysInit(void) startTick = sysGetMicroseconds(); if (sysArgCheck("--log")) { - // figure out where the log is and clear it - // try working dir first - snprintf(logPath, sizeof(logPath), "./%s", LOG_FNAME); - FILE *f = fopen(logPath, "wb"); - if (!f) { - // try home dir - sysGetHomePath(logPath, sizeof(logPath) - 1); - strncat(logPath, "/" LOG_FNAME, sizeof(logPath) - 1); - f = fopen(logPath, "wb"); - } - if (f) { - fclose(f); - } + sysLogSetPath(LOG_FNAME); } #ifdef VERSION_HASH @@ -96,6 +103,13 @@ u64 sysGetMicroseconds(void) return ((u64)tv.tv_sec * USEC_IN_SEC + (u64)tv.tv_usec) - startTick; } +void sysLogStartCrash(void) +{ + if (!logPath[0]) { + sysLogSetPath(CRASHLOG_FNAME); + } +} + void sysLogPrintf(s32 level, const char *fmt, ...) { static const char *prefix[3] = { From 06f22831804128bf33b16851eb5b9f8aa049748f Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sun, 7 Jan 2024 16:09:04 +0100 Subject: [PATCH 38/55] port: use cv2pdb on windows executables if present --- Makefile.port | 10 ++++++++++ port/src/crash.c | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Makefile.port b/Makefile.port index 0a53f3d33..e7a266855 100644 --- a/Makefile.port +++ b/Makefile.port @@ -154,6 +154,13 @@ ifneq (,$(findstring windows,$(TARGET_PLATFORM))) TARGET_LDFLAGS := $(shell pkg-config sdl2 --libs) -lz -lopengl32 -static-libstdc++ -ldbghelp # on windows/mingw we need this to be built with a 32-bit compiler so it finds the correct libs TOOLCHAIN ?= i686-w64-mingw32- + # check if cv2pdb is present + ifeq ($(CV2PDB),) + CV2PDB := cv2pdb + ifeq (,$(shell which cv2pdb 2>/dev/null)) + CV2PDB := + endif + endif else # assume *nix TARGET_CFLAGS := $(shell pkg-config sdl2 --cflags-only-I) TARGET_LDFLAGS := $(shell pkg-config sdl2 --libs) -lGL -lz -ldl @@ -305,6 +312,9 @@ $(G_DIR)/tiles/%.h: $(A_DIR)/tiles/%.json $(BIN): $(O_FILES) $(LD) $(COMMON_CFLAGS) $(OPT_LVL) -o $(BIN) $^ $(LDFLAGS) +ifneq ($(CV2PDB),) + $(CV2PDB) $(BIN) +endif $(B_DIR)/%.o: %.c @mkdir -p $(dir $@) diff --git a/port/src/crash.c b/port/src/crash.c index 1ea2ea557..47c24101b 100644 --- a/port/src/crash.c +++ b/port/src/crash.c @@ -10,7 +10,7 @@ #include "system.h" #include "platform.h" -#define CRASH_MAX_MSG 4096 +#define CRASH_MAX_MSG 8192 #define CRASH_MAX_SYM 256 #define CRASH_MAX_FRAMES 32 #define CRASH_MSG(...) \ From d1d288b96a92ea5e359e23cc73fa14be82eb38ae Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sun, 7 Jan 2024 16:43:02 +0100 Subject: [PATCH 39/55] port: don't use cv2pdb by default if it exists --- Makefile.port | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Makefile.port b/Makefile.port index e7a266855..b8ebadb12 100644 --- a/Makefile.port +++ b/Makefile.port @@ -154,13 +154,6 @@ ifneq (,$(findstring windows,$(TARGET_PLATFORM))) TARGET_LDFLAGS := $(shell pkg-config sdl2 --libs) -lz -lopengl32 -static-libstdc++ -ldbghelp # on windows/mingw we need this to be built with a 32-bit compiler so it finds the correct libs TOOLCHAIN ?= i686-w64-mingw32- - # check if cv2pdb is present - ifeq ($(CV2PDB),) - CV2PDB := cv2pdb - ifeq (,$(shell which cv2pdb 2>/dev/null)) - CV2PDB := - endif - endif else # assume *nix TARGET_CFLAGS := $(shell pkg-config sdl2 --cflags-only-I) TARGET_LDFLAGS := $(shell pkg-config sdl2 --libs) -lGL -lz -ldl From ba52580e0c70b9f2b35ce76831fa3d59e64dd75a Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sun, 7 Jan 2024 16:43:20 +0100 Subject: [PATCH 40/55] port: display module offsets in the windows crashlog --- port/src/crash.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/port/src/crash.c b/port/src/crash.c index 47c24101b..e2b6be079 100644 --- a/port/src/crash.c +++ b/port/src/crash.c @@ -79,8 +79,8 @@ static void crashStackTrace(char *msg, PEXCEPTION_POINTERS exinfo) if (SymGetLineFromAddr64(process, (uintptr_t)exinfo->ExceptionRecord->ExceptionAddress, &disp, &line)) { CRASH_MSG(": %s:%lu+%lu", line.FileName, line.LineNumber, disp); } - CRASH_MSG("\nMODULE: %p\n", crashGetModuleBase(exinfo->ExceptionRecord->ExceptionAddress)); - CRASH_MSG("MAIN MODULE: %p\n", crashGetModuleBase(crashInit)); + CRASH_MSG("\nMODULE: [%p]\n", crashGetModuleBase(exinfo->ExceptionRecord->ExceptionAddress)); + CRASH_MSG("MAIN MODULE: [%p]\n", crashGetModuleBase(crashInit)); CRASH_MSG("\nBACKTRACE:\n"); char symbuf[sizeof(SYMBOL_INFO) + CRASH_MAX_SYM * sizeof(TCHAR)]; @@ -99,6 +99,10 @@ static void crashStackTrace(char *msg, PEXCEPTION_POINTERS exinfo) if (SymFromAddr(process, stackframe.AddrPC.Offset, &disp64, sym)) { CRASH_MSG(": %s+%llu", sym->Name, disp64); + } else if (process, stackframe.AddrPC.Offset) { + const uintptr_t modbase = (uintptr_t)crashGetModuleBase((void *)(uintptr_t)stackframe.AddrPC.Offset); + const uintptr_t modofs = (uintptr_t)stackframe.AddrPC.Offset - modbase; + CRASH_MSG(": [%p]+%p", (void *)modbase, (void *)modofs); } if(SymGetLineFromAddr64(process, stackframe.AddrPC.Offset, &disp, &line)) { From 8645d0a82a5c89650e834b898b7b4deb3108c4fb Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sun, 7 Jan 2024 17:07:12 +0100 Subject: [PATCH 41/55] port: don't use the existing log system in crashlog in case it crashes --- port/include/system.h | 2 +- port/src/crash.c | 13 ++++++++++--- port/src/system.c | 6 ++---- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/port/include/system.h b/port/include/system.h index e6b75ac3d..94158802a 100644 --- a/port/include/system.h +++ b/port/include/system.h @@ -24,7 +24,7 @@ u64 sysGetMicroseconds(void); void sysFatalError(const char *fmt, ...) __attribute__((noreturn)); -void sysLogStartCrash(void); +s32 sysLogIsOpen(void); void sysLogPrintf(s32 level, const char *fmt, ...); void sysGetExecutablePath(char *outPath, const u32 outLen); diff --git a/port/src/crash.c b/port/src/crash.c index e2b6be079..dc0536589 100644 --- a/port/src/crash.c +++ b/port/src/crash.c @@ -10,6 +10,7 @@ #include "system.h" #include "platform.h" +#define CRASH_LOG_FNAME "pd.crash.log" #define CRASH_MAX_MSG 8192 #define CRASH_MAX_SYM 256 #define CRASH_MAX_FRAMES 32 @@ -132,9 +133,6 @@ static long __stdcall crashHandler(PEXCEPTION_POINTERS exinfo) return EXCEPTION_CONTINUE_EXECUTION; } - // start writing to a crash log file - sysLogStartCrash(); - sysLogPrintf(LOG_ERROR, "FATAL: Crashed: PC=%p CODE=0x%08lx", exinfo->ExceptionRecord->ExceptionAddress, exinfo->ExceptionRecord->ExceptionCode); fflush(stderr); @@ -142,6 +140,15 @@ static long __stdcall crashHandler(PEXCEPTION_POINTERS exinfo) crashStackTrace(msg, exinfo); + // open log file for the crash dump if one hasn't been opened yet + if (!sysLogIsOpen()) { + FILE *f = fopen(CRASH_LOG_FNAME, "wb"); + if (f) { + fprintf(f, "Crash!\n\n%s", msg); + fclose(f); + } + } + sysFatalError("Crash!\n\n%s", msg); return EXCEPTION_CONTINUE_EXECUTION; diff --git a/port/src/system.c b/port/src/system.c index fb24addd0..538dd1e87 100644 --- a/port/src/system.c +++ b/port/src/system.c @@ -103,11 +103,9 @@ u64 sysGetMicroseconds(void) return ((u64)tv.tv_sec * USEC_IN_SEC + (u64)tv.tv_usec) - startTick; } -void sysLogStartCrash(void) +s32 sysLogIsOpen(void) { - if (!logPath[0]) { - sysLogSetPath(CRASHLOG_FNAME); - } + return (logPath[0] != '\0'); } void sysLogPrintf(s32 level, const char *fmt, ...) From 6bd3597ff6b91a361644512d08061f4b1629806d Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sun, 7 Jan 2024 18:40:32 +0100 Subject: [PATCH 42/55] port: fix optionsmenu.c warnings --- port/include/video.h | 2 ++ port/src/optionsmenu.c | 32 ++++++++++++++++++++------------ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/port/include/video.h b/port/include/video.h index ab7e34575..105f78699 100644 --- a/port/include/video.h +++ b/port/include/video.h @@ -27,6 +27,8 @@ s32 videoGetWidth(void); s32 videoGetHeight(void); f32 videoGetAspect(void); s32 videoGetFullscreen(void); +s32 videoGetMaximizeWindow(void); +void videoSetMaximizeWindow(s32 fs); u32 videoGetTextureFilter(void); u32 videoGetTextureFilter2D(void); diff --git a/port/src/optionsmenu.c b/port/src/optionsmenu.c index 9f3898cae..53da2571f 100644 --- a/port/src/optionsmenu.c +++ b/port/src/optionsmenu.c @@ -945,15 +945,17 @@ static MenuItemHandlerResult menuhandlerCrosshairSway(s32 operation, struct menu return 0; } -static MenuItemHandlerResult menuhandlerCrosshair_R(s32 operation, struct menuitem* item, union handlerdata* data) +static MenuItemHandlerResult menuhandlerCrosshairR(s32 operation, struct menuitem* item, union handlerdata* data) { + u32 newColor; + switch (operation) { case MENUOP_GETSLIDER: data->slider.value = (g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour >> 24) & 0xFF; break; case MENUOP_SET: - u32 newColor = g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour & 0xFFFFFF | data->slider.value << 24; + newColor = (g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour & 0xFFFFFF) | data->slider.value << 24; g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour = newColor; break; } @@ -961,15 +963,17 @@ static MenuItemHandlerResult menuhandlerCrosshair_R(s32 operation, struct menuit return 0; } -static MenuItemHandlerResult menuhandlerCrosshair_G(s32 operation, struct menuitem* item, union handlerdata* data) +static MenuItemHandlerResult menuhandlerCrosshairG(s32 operation, struct menuitem* item, union handlerdata* data) { + u32 newColor; + switch (operation) { case MENUOP_GETSLIDER: data->slider.value = (g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour >> 16) & 0xFF; break; case MENUOP_SET: - u32 newColor = g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour & 0xFF00FFFF | data->slider.value << 16; + newColor = (g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour & 0xFF00FFFF) | data->slider.value << 16; g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour = newColor; break; } @@ -977,15 +981,17 @@ static MenuItemHandlerResult menuhandlerCrosshair_G(s32 operation, struct menuit return 0; } -static MenuItemHandlerResult menuhandlerCrosshair_B(s32 operation, struct menuitem* item, union handlerdata* data) +static MenuItemHandlerResult menuhandlerCrosshairB(s32 operation, struct menuitem* item, union handlerdata* data) { + u32 newColor; + switch (operation) { case MENUOP_GETSLIDER: data->slider.value = (g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour >> 8) & 0xFF; break; case MENUOP_SET: - u32 newColor = g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour & 0xFFFF00FF | data->slider.value << 8; + newColor = (g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour & 0xFFFF00FF) | data->slider.value << 8; g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour = newColor; break; } @@ -993,15 +999,17 @@ static MenuItemHandlerResult menuhandlerCrosshair_B(s32 operation, struct menuit return 0; } -static MenuItemHandlerResult menuhandlerCrosshair_A(s32 operation, struct menuitem* item, union handlerdata* data) +static MenuItemHandlerResult menuhandlerCrosshairA(s32 operation, struct menuitem* item, union handlerdata* data) { + u32 newColor; + switch (operation) { case MENUOP_GETSLIDER: data->slider.value = g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour & 0xFF; break; case MENUOP_SET: - u32 newColor = g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour & 0xFFFFFF00 | data->slider.value; + newColor = (g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour & 0xFFFFFF00) | data->slider.value; g_PlayerExtCfg[g_ExtMenuPlayer].crosshaircolour = newColor; break; } @@ -1025,7 +1033,7 @@ struct menuitem g_ExtendedGameCrosshairColourMenuItems[] = { MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE, (uintptr_t)"Red", 255, - menuhandlerCrosshair_R, + menuhandlerCrosshairR, }, { MENUITEMTYPE_SLIDER, @@ -1033,7 +1041,7 @@ struct menuitem g_ExtendedGameCrosshairColourMenuItems[] = { MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE, (uintptr_t)"Green", 255, - menuhandlerCrosshair_G, + menuhandlerCrosshairG, }, { MENUITEMTYPE_SLIDER, @@ -1041,7 +1049,7 @@ struct menuitem g_ExtendedGameCrosshairColourMenuItems[] = { MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE, (uintptr_t)"Blue", 255, - menuhandlerCrosshair_B, + menuhandlerCrosshairB, }, { MENUITEMTYPE_SLIDER, @@ -1049,7 +1057,7 @@ struct menuitem g_ExtendedGameCrosshairColourMenuItems[] = { MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE, (uintptr_t)"Alpha", 255, - menuhandlerCrosshair_A, + menuhandlerCrosshairA, }, { MENUITEMTYPE_SEPARATOR, From b9db86f89b0c15129467fac5dbced7634404616d Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sun, 7 Jan 2024 22:05:31 +0100 Subject: [PATCH 43/55] port: add command line parameter to select player file --- port/src/main.c | 7 +++++++ src/game/filemgr.c | 10 ++++++++++ src/include/data.h | 1 + 3 files changed, 18 insertions(+) diff --git a/port/src/main.c b/port/src/main.c index 8f8ec2af8..006353cf7 100644 --- a/port/src/main.c +++ b/port/src/main.c @@ -39,6 +39,8 @@ s32 g_TickRateDiv = 1; s32 g_SkipIntro = false; +s32 g_FileAutoSelect = -1; + extern s32 g_StageNum; s32 bootGetMemSize(void) @@ -142,6 +144,11 @@ int main(int argc, const char **argv) sysLogPrintf(LOG_NOTE, "boot stage set to 0x%02x", g_StageNum); } + g_FileAutoSelect = sysArgGetInt("--profile", -1); + if (g_FileAutoSelect >= 0) { + sysLogPrintf(LOG_NOTE, "player profile set to %d", g_FileAutoSelect); + } + mainProc(); return 0; diff --git a/src/game/filemgr.c b/src/game/filemgr.c index 6d7184cf1..aac819ad1 100644 --- a/src/game/filemgr.c +++ b/src/game/filemgr.c @@ -2592,6 +2592,16 @@ MenuItemHandlerResult filemgrChooseAgentListMenuHandler(s32 operation, struct me } } } + +#ifndef PLATFORM_N64 + if (g_FileAutoSelect >= 0 && g_FileLists[0] && g_FileLists[0]->numfiles > 0) { + const u32 tmp = data->list.value; + data->list.value = g_FileAutoSelect; + g_FileAutoSelect = -1; + filemgrChooseAgentListMenuHandler(MENUOP_SET, item, data); + data->list.value = tmp; + } +#endif break; case MENUOP_GETOPTIONCOUNT: data->list.value = g_FileLists[0]->numfiles + 1; diff --git a/src/include/data.h b/src/include/data.h index 315c8bb17..e513c6f10 100644 --- a/src/include/data.h +++ b/src/include/data.h @@ -549,6 +549,7 @@ extern bool g_BlurFbDirty; extern s32 g_TickRateDiv; extern s32 g_MusicDisableMpDeath; extern s32 g_BgunGeMuzzleFlashes; +extern s32 g_FileAutoSelect; #define PLAYER_EXTCFG() g_PlayerExtCfg[g_Vars.currentplayerstats->mpindex & 3] #define PLAYER_DEFAULT_FOV (PLAYER_EXTCFG().fovy) From d9cb8508487a6026077c718f4fcca47e5e41a777 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sun, 14 Jan 2024 20:49:20 +0100 Subject: [PATCH 44/55] Merge pull request #333 from AXDOOMER/port Always use high detail weapon models --- src/game/game_0b0fd0.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/game/game_0b0fd0.c b/src/game/game_0b0fd0.c index 8c7953ccf..719959461 100644 --- a/src/game/game_0b0fd0.c +++ b/src/game/game_0b0fd0.c @@ -398,9 +398,11 @@ u16 weaponGetFileNum(s32 weaponnum) } if (weapon) { +#ifdef PLATFORM_N64 if (PLAYERCOUNT() >= 2) { return weapon->lo_model; } +#endif return weapon->hi_model; } From cf5588478b0c65a394731537cfe7d4ddf30f7156 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sun, 14 Jan 2024 21:11:58 +0100 Subject: [PATCH 45/55] Merge pull request #332 from Calinou/add-crosshair-size-option Add a crosshair size option --- port/src/main.c | 1 + port/src/optionsmenu.c | 22 ++++++++++++++++++++++ src/game/mplayer/mplayer.c | 1 + src/game/sight.c | 23 +++++++++++++++-------- src/include/types.h | 1 + 5 files changed, 40 insertions(+), 8 deletions(-) diff --git a/port/src/main.c b/port/src/main.c index 006353cf7..10150f7ae 100644 --- a/port/src/main.c +++ b/port/src/main.c @@ -175,5 +175,6 @@ PD_CONSTRUCTOR static void gameConfigInit(void) configRegisterInt(strFmt("Game.Player%d.CrouchMode", i), &g_PlayerExtCfg[j].crouchmode, 0, CROUCHMODE_TOGGLE_ANALOG); configRegisterInt(strFmt("Game.Player%d.ExtendedControls", i), &g_PlayerExtCfg[j].extcontrols, 0, 1); configRegisterUInt(strFmt("Game.Player%d.CrosshairColour", i), &g_PlayerExtCfg[j].crosshaircolour, 0, 0xFFFFFFFF); + configRegisterUInt(strFmt("Game.Player%d.CrosshairSize", i), &g_PlayerExtCfg[j].crosshairsize, 0, 4); } } diff --git a/port/src/optionsmenu.c b/port/src/optionsmenu.c index 53da2571f..dd999bee4 100644 --- a/port/src/optionsmenu.c +++ b/port/src/optionsmenu.c @@ -1026,6 +1026,20 @@ static MenuItemHandlerResult menuhandlerCrosshairColorPreview(s32 operation, str return 0; } +static MenuItemHandlerResult menuhandlerCrosshairSize(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GETSLIDER: + data->slider.value = g_PlayerExtCfg[g_ExtMenuPlayer].crosshairsize; + break; + case MENUOP_SET: + g_PlayerExtCfg[g_ExtMenuPlayer].crosshairsize = data->slider.value; + break; + } + + return 0; +} + struct menuitem g_ExtendedGameCrosshairColourMenuItems[] = { { MENUITEMTYPE_SLIDER, @@ -1128,6 +1142,14 @@ struct menuitem g_ExtendedGameMenuItems[] = { 20, menuhandlerCrosshairSway, }, + { + MENUITEMTYPE_SLIDER, + 0, + MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE, + (uintptr_t)"Crosshair Size", + 4, + menuhandlerCrosshairSize, + }, { MENUITEMTYPE_SELECTABLE, 0, diff --git a/src/game/mplayer/mplayer.c b/src/game/mplayer/mplayer.c index efb63bfc0..7246a418b 100644 --- a/src/game/mplayer/mplayer.c +++ b/src/game/mplayer/mplayer.c @@ -123,6 +123,7 @@ struct mpweapon g_MpWeapons[NUM_MPWEAPONS] = { .crouchmode = CROUCHMODE_TOGGLE_ANALOG, \ .extcontrols = true, \ .crosshaircolour = 0x00ff0028, \ + .crosshairsize = 2, \ } struct extplayerconfig g_PlayerExtCfg[MAX_PLAYERS] = { diff --git a/src/game/sight.c b/src/game/sight.c index 8e7ed749b..fa2155d4d 100644 --- a/src/game/sight.c +++ b/src/game/sight.c @@ -1473,14 +1473,21 @@ Gfx *sightDrawTarget(Gfx *gdl) gSPSetExtraGeometryModeEXT(gdl++, G_ASPECT_CENTER_EXT); #endif - gDPHudRectangle(gdl++, x + 2, y + 0, x + 6, y + 0); - gDPHudRectangle(gdl++, x + 2, y + 0, x + 4, y + 0); - gDPHudRectangle(gdl++, x - 6, y + 0, x - 2, y + 0); - gDPHudRectangle(gdl++, x - 4, y + 0, x - 2, y + 0); - gDPHudRectangle(gdl++, x + 0, y + 2, x + 0, y + 6); - gDPHudRectangle(gdl++, x + 0, y + 2, x + 0, y + 4); - gDPHudRectangle(gdl++, x + 0, y - 6, x + 0, y - 2); - gDPHudRectangle(gdl++, x + 0, y - 4, x + 0, y - 2); +#define SIGHT_SCALE PLAYER_EXTCFG().crosshairsize + + if (SIGHT_SCALE == 0) { + // Draw single rectangle to preserve intended opacity + gDPHudRectangle(gdl++, x, y, x, y); + } else { + gDPHudRectangle(gdl++, x + 1 * SIGHT_SCALE, y + 0 * SIGHT_SCALE, x + 3 * SIGHT_SCALE, y + 0 * SIGHT_SCALE); + gDPHudRectangle(gdl++, x + 1 * SIGHT_SCALE, y + 0 * SIGHT_SCALE, x + 2 * SIGHT_SCALE, y + 0 * SIGHT_SCALE); + gDPHudRectangle(gdl++, x - 3 * SIGHT_SCALE, y + 0 * SIGHT_SCALE, x - 1 * SIGHT_SCALE, y + 0 * SIGHT_SCALE); + gDPHudRectangle(gdl++, x - 2 * SIGHT_SCALE, y + 0 * SIGHT_SCALE, x - 1 * SIGHT_SCALE, y + 0 * SIGHT_SCALE); + gDPHudRectangle(gdl++, x + 0 * SIGHT_SCALE, y + 1 * SIGHT_SCALE, x + 0 * SIGHT_SCALE, y + 3 * SIGHT_SCALE); + gDPHudRectangle(gdl++, x + 0 * SIGHT_SCALE, y + 1 * SIGHT_SCALE, x + 0 * SIGHT_SCALE, y + 2 * SIGHT_SCALE); + gDPHudRectangle(gdl++, x + 0 * SIGHT_SCALE, y - 3 * SIGHT_SCALE, x + 0 * SIGHT_SCALE, y - 1 * SIGHT_SCALE); + gDPHudRectangle(gdl++, x + 0 * SIGHT_SCALE, y - 2 * SIGHT_SCALE, x + 0 * SIGHT_SCALE, y - 1 * SIGHT_SCALE); + } #ifndef PLATFORM_N64 gSPClearExtraGeometryModeEXT(gdl++, G_ASPECT_CENTER_EXT); diff --git a/src/include/types.h b/src/include/types.h index 81b71ca6d..2a0491896 100644 --- a/src/include/types.h +++ b/src/include/types.h @@ -6140,6 +6140,7 @@ struct extplayerconfig { f32 crosshairsway; s32 extcontrols; u32 crosshaircolour; + u32 crosshairsize; }; #endif From 81313f0c4e73510198819db922caee4460d58947 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sun, 14 Jan 2024 21:13:31 +0100 Subject: [PATCH 46/55] port: ifdef around sight scale changes --- src/game/sight.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/game/sight.c b/src/game/sight.c index fa2155d4d..fb5f255ae 100644 --- a/src/game/sight.c +++ b/src/game/sight.c @@ -24,6 +24,7 @@ #include "video.h" #define SIGHT_COLOUR PLAYER_EXTCFG().crosshaircolour +#define SIGHT_SCALE PLAYER_EXTCFG().crosshairsize static inline f32 sightGetScaleX(void) { @@ -39,6 +40,7 @@ static inline s32 sightGetAdjustedX(const f32 x) #else #define SIGHT_COLOUR 0x00ff0028 +#define SIGHT_SCALE 2 #define sightGetScaleX() 1.f #define sightGetAdjustedX(x) (x) @@ -1471,14 +1473,12 @@ Gfx *sightDrawTarget(Gfx *gdl) #ifndef PLATFORM_N64 gSPSetExtraGeometryModeEXT(gdl++, G_ASPECT_CENTER_EXT); -#endif - -#define SIGHT_SCALE PLAYER_EXTCFG().crosshairsize - if (SIGHT_SCALE == 0) { // Draw single rectangle to preserve intended opacity gDPHudRectangle(gdl++, x, y, x, y); - } else { + } else +#endif + { gDPHudRectangle(gdl++, x + 1 * SIGHT_SCALE, y + 0 * SIGHT_SCALE, x + 3 * SIGHT_SCALE, y + 0 * SIGHT_SCALE); gDPHudRectangle(gdl++, x + 1 * SIGHT_SCALE, y + 0 * SIGHT_SCALE, x + 2 * SIGHT_SCALE, y + 0 * SIGHT_SCALE); gDPHudRectangle(gdl++, x - 3 * SIGHT_SCALE, y + 0 * SIGHT_SCALE, x - 1 * SIGHT_SCALE, y + 0 * SIGHT_SCALE); From e53f26f3ebf2ae34b685104237224dc4f8bac0fa Mon Sep 17 00:00:00 2001 From: fgsfds Date: Mon, 15 Jan 2024 09:45:56 +0100 Subject: [PATCH 47/55] port: fix #347 patch submitted by Ryan Dwyer The patch allows all humans/bots to be selected regardless of team. It also adds a check to make sure a bot is not given a command to attack itself. --- src/game/activemenu.c | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/src/game/activemenu.c b/src/game/activemenu.c index bba991a14..bc984de99 100644 --- a/src/game/activemenu.c +++ b/src/game/activemenu.c @@ -90,19 +90,8 @@ MenuItemHandlerResult amPickTargetMenuList(s32 operation, struct menuitem *item, switch (operation) { case MENUOP_GETOPTIONCOUNT: if (g_AmMenus[g_AmIndex].prevallbots) { - // All bots: num bot opponents + all human players - s32 count = 0; - s32 i; - struct chrdata *playerchr = g_Vars.currentplayer->prop->chr; - - for (i = PLAYERCOUNT(); i < g_MpNumChrs; i++) { - if (g_MpAllChrPtrs[i]->team != playerchr->team) { - count++; - } - } - - count += PLAYERCOUNT(); - data->list.value = count; + // All bots + data->list.value = g_MpNumChrs; } else { // Single bot: All except the bot itself data->list.value = g_MpNumChrs - 1; @@ -125,9 +114,7 @@ MenuItemHandlerResult amPickTargetMenuList(s32 operation, struct menuitem *item, chrindex++; if (g_AmMenus[g_AmIndex].prevallbots) { - if (playerchr == g_MpAllChrPtrs[chrindex] || playerchr->team != g_MpAllChrPtrs[chrindex]->team) { - numremaining--; - } + numremaining--; } else { if (botchr != g_MpAllChrPtrs[chrindex]) { numremaining--; @@ -139,7 +126,9 @@ MenuItemHandlerResult amPickTargetMenuList(s32 operation, struct menuitem *item, g_AmMenus[g_AmIndex].prevallbots = false; for (i = 0; i < g_Vars.currentplayer->numaibuddies; i++) { - botApplyAttack(g_MpAllChrPtrs[g_Vars.currentplayer->aibuddynums[i]], g_MpAllChrPtrs[chrindex]->prop); + if (g_Vars.currentplayer->aibuddynums[i] != chrindex) { + botApplyAttack(g_MpAllChrPtrs[g_Vars.currentplayer->aibuddynums[i]], g_MpAllChrPtrs[chrindex]->prop); + } } } else { botApplyAttack(botchr, g_MpAllChrPtrs[chrindex]->prop); @@ -167,9 +156,7 @@ MenuItemHandlerResult amPickTargetMenuList(s32 operation, struct menuitem *item, chrindex++; if (g_AmMenus[g_AmIndex].prevallbots) { - if (playerchr == g_MpAllChrPtrs[chrindex] || playerchr->team != g_MpAllChrPtrs[chrindex]->team) { - numremaining--; - } + numremaining--; } else { if (botchr != g_MpAllChrPtrs[chrindex]) { numremaining--; From 9cde121b52bc93c41cb37083422fc61bda9c6503 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Mon, 15 Jan 2024 12:58:00 +0100 Subject: [PATCH 48/55] port: don't call rumble function if rumble strength is 0 --- port/src/input.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/port/src/input.c b/port/src/input.c index a4b14d0e5..96438e3f6 100644 --- a/port/src/input.c +++ b/port/src/input.c @@ -838,6 +838,10 @@ void inputRumble(s32 idx, f32 strength, f32 time) return; } + if (padsCfg[idx].rumbleScale <= 0.f) { + return; + } + if (padsCfg[idx].rumbleOn) { strength *= padsCfg[idx].rumbleScale; if (strength <= 0.f) { From 474a6df3d4c39719e5ea74d0008bbd34813723d7 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Tue, 16 Jan 2024 01:56:30 +0100 Subject: [PATCH 49/55] port: add spawn with weapon mp option unfortunately it does not fit in the save buffer and won't save --- src/game/bot.c | 11 +++++++++++ src/game/mplayer/scenarios/capturethecase.inc | 10 ++++++++++ src/game/mplayer/scenarios/combat.inc | 10 ++++++++++ src/game/mplayer/scenarios/hackthatmac.inc | 10 ++++++++++ src/game/mplayer/scenarios/holdthebriefcase.inc | 10 ++++++++++ src/game/mplayer/scenarios/kingofthehill.inc | 10 ++++++++++ src/game/mplayer/scenarios/popacap.inc | 10 ++++++++++ src/game/player.c | 17 +++++++++++++++-- src/include/constants.h | 1 + 9 files changed, 87 insertions(+), 2 deletions(-) diff --git a/src/game/bot.c b/src/game/bot.c index 0658a1ce3..826bc2a51 100644 --- a/src/game/bot.c +++ b/src/game/bot.c @@ -260,6 +260,17 @@ void botSpawn(struct chrdata *chr, u8 respawning) chr->aibot->moveratex = 0; chr->aibot->moveratey = 0; func0f02e9a0(chr, 0); + +#ifndef PLATFORM_N64 + if ((g_MpSetup.options & MPOPTION_SPAWNWITHWEAPON) + && g_MpSetup.weapons[0] != MPWEAPON_NONE + && g_MpSetup.weapons[0] != MPWEAPON_DISABLED) { + struct mpweapon *mpweapon = &g_MpWeapons[g_MpSetup.weapons[0]]; + botinvGiveSingleWeapon(chr, mpweapon->weaponnum); + botactGiveAmmoByType(aibot, mpweapon->priammotype - 1, mpweapon->priammoqty / 2); + botinvSwitchToWeapon(chr, mpweapon->weaponnum, FUNC_PRIMARY); + } +#endif } } diff --git a/src/game/mplayer/scenarios/capturethecase.inc b/src/game/mplayer/scenarios/capturethecase.inc index b701a69c2..0e82d542a 100644 --- a/src/game/mplayer/scenarios/capturethecase.inc +++ b/src/game/mplayer/scenarios/capturethecase.inc @@ -60,6 +60,16 @@ struct menuitem g_CtcOptionsMenuItems[] = { MPOPTION_NOAUTOAIM, menuhandlerMpCheckboxOption, }, +#ifndef PLATFORM_N64 + { + MENUITEMTYPE_CHECKBOX, + 0, + MENUITEMFLAG_LOCKABLEMINOR | MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Spawn With Weapon", + MPOPTION_SPAWNWITHWEAPON, + menuhandlerMpCheckboxOption, + }, +#endif { MENUITEMTYPE_CHECKBOX, 0, diff --git a/src/game/mplayer/scenarios/combat.inc b/src/game/mplayer/scenarios/combat.inc index 74f4c6ad3..7d096a55c 100644 --- a/src/game/mplayer/scenarios/combat.inc +++ b/src/game/mplayer/scenarios/combat.inc @@ -55,6 +55,16 @@ struct menuitem g_MpCombatOptionsMenuItems[] = { MPOPTION_NOAUTOAIM, menuhandlerMpCheckboxOption, }, +#ifndef PLATFORM_N64 + { + MENUITEMTYPE_CHECKBOX, + 0, + MENUITEMFLAG_LOCKABLEMINOR | MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Spawn With Weapon", + MPOPTION_SPAWNWITHWEAPON, + menuhandlerMpCheckboxOption, + }, +#endif { MENUITEMTYPE_SEPARATOR, 0, diff --git a/src/game/mplayer/scenarios/hackthatmac.inc b/src/game/mplayer/scenarios/hackthatmac.inc index d065929ec..1ca58458a 100644 --- a/src/game/mplayer/scenarios/hackthatmac.inc +++ b/src/game/mplayer/scenarios/hackthatmac.inc @@ -58,6 +58,16 @@ struct menuitem g_HtmOptionsMenuItems[] = { MPOPTION_NOAUTOAIM, menuhandlerMpCheckboxOption, }, +#ifndef PLATFORM_N64 + { + MENUITEMTYPE_CHECKBOX, + 0, + MENUITEMFLAG_LOCKABLEMINOR | MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Spawn With Weapon", + MPOPTION_SPAWNWITHWEAPON, + menuhandlerMpCheckboxOption, + }, +#endif { MENUITEMTYPE_CHECKBOX, 0, diff --git a/src/game/mplayer/scenarios/holdthebriefcase.inc b/src/game/mplayer/scenarios/holdthebriefcase.inc index 4441a6050..fe9cc0bd6 100644 --- a/src/game/mplayer/scenarios/holdthebriefcase.inc +++ b/src/game/mplayer/scenarios/holdthebriefcase.inc @@ -58,6 +58,16 @@ struct menuitem g_HtbOptionsMenuItems[] = { MPOPTION_NOAUTOAIM, menuhandlerMpCheckboxOption, }, +#ifndef PLATFORM_N64 + { + MENUITEMTYPE_CHECKBOX, + 0, + MENUITEMFLAG_LOCKABLEMINOR | MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Spawn With Weapon", + MPOPTION_SPAWNWITHWEAPON, + menuhandlerMpCheckboxOption, + }, +#endif { MENUITEMTYPE_CHECKBOX, 0, diff --git a/src/game/mplayer/scenarios/kingofthehill.inc b/src/game/mplayer/scenarios/kingofthehill.inc index 050ff36b7..120024f19 100644 --- a/src/game/mplayer/scenarios/kingofthehill.inc +++ b/src/game/mplayer/scenarios/kingofthehill.inc @@ -79,6 +79,16 @@ struct menuitem g_KohOptionsMenuItems[] = { MPOPTION_NOAUTOAIM, menuhandlerMpCheckboxOption, }, +#ifndef PLATFORM_N64 + { + MENUITEMTYPE_CHECKBOX, + 0, + MENUITEMFLAG_LOCKABLEMINOR | MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Spawn With Weapon", + MPOPTION_SPAWNWITHWEAPON, + menuhandlerMpCheckboxOption, + }, +#endif { MENUITEMTYPE_CHECKBOX, 0, diff --git a/src/game/mplayer/scenarios/popacap.inc b/src/game/mplayer/scenarios/popacap.inc index d0cc31933..7da8ed521 100644 --- a/src/game/mplayer/scenarios/popacap.inc +++ b/src/game/mplayer/scenarios/popacap.inc @@ -56,6 +56,16 @@ struct menuitem g_PacOptionsMenuItems[] = { MPOPTION_NOAUTOAIM, menuhandlerMpCheckboxOption, }, +#ifndef PLATFORM_N64 + { + MENUITEMTYPE_CHECKBOX, + 0, + MENUITEMFLAG_LOCKABLEMINOR | MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Spawn With Weapon", + MPOPTION_SPAWNWITHWEAPON, + menuhandlerMpCheckboxOption, + }, +#endif { MENUITEMTYPE_CHECKBOX, 0, diff --git a/src/game/player.c b/src/game/player.c index 3ae336630..bb26bd28e 100644 --- a/src/game/player.c +++ b/src/game/player.c @@ -1099,8 +1099,21 @@ void playerSpawn(void) g_Vars.currentplayer->prop->chr->blurnumtimesdied = 0; } } else { - bgunEquipWeapon2(HAND_LEFT, g_DefaultWeapons[HAND_LEFT]); - bgunEquipWeapon2(HAND_RIGHT, g_DefaultWeapons[HAND_RIGHT]); +#ifndef PLATFORM_N64 + if ((g_MpSetup.options & MPOPTION_SPAWNWITHWEAPON) + && g_MpSetup.weapons[0] != MPWEAPON_NONE + && g_MpSetup.weapons[0] != MPWEAPON_DISABLED) { + struct mpweapon *mpweapon = &g_MpWeapons[g_MpSetup.weapons[0]]; + invGiveSingleWeapon(mpweapon->weaponnum); + bgunEquipWeapon2(HAND_LEFT, WEAPON_NONE); + bgunEquipWeapon2(HAND_RIGHT, mpweapon->weaponnum); + bgunSetAmmoQuantity(mpweapon->priammotype, mpweapon->priammoqty / 2); + } else +#endif + { + bgunEquipWeapon2(HAND_LEFT, g_DefaultWeapons[HAND_LEFT]); + bgunEquipWeapon2(HAND_RIGHT, g_DefaultWeapons[HAND_RIGHT]); + } #if VERSION >= VERSION_NTSC_1_0 if (g_Vars.currentplayer->model00d4 == NULL diff --git a/src/include/constants.h b/src/include/constants.h index 8b39686d4..4c3705b7f 100644 --- a/src/include/constants.h +++ b/src/include/constants.h @@ -2889,6 +2889,7 @@ #define MPOPTION_HTM_SHOWONRADAR 0x00040000 #define MPOPTION_PAC_HIGHLIGHTTARGET 0x00080000 #define MPOPTION_PAC_SHOWONRADAR 0x00100000 +#define MPOPTION_SPAWNWITHWEAPON 0x00200000 #define MPPAUSEMODE_UNPAUSED 0 #define MPPAUSEMODE_PAUSED 1 From 1f4d9c8cdca4b9a29af0191b8764d7787a4c1abe Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Sat, 27 Jan 2024 02:51:34 +0100 Subject: [PATCH 50/55] Always hide crosshair when dead Previously, the crosshair would show up during the death animation if Always Show Target is enabled or if aiming just before dying. --- src/game/sight.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/game/sight.c b/src/game/sight.c index fb5f255ae..d8fb87007 100644 --- a/src/game/sight.c +++ b/src/game/sight.c @@ -1536,6 +1536,13 @@ Gfx *sightDraw(Gfx *gdl, bool sighton, s32 sight) sight = SIGHT_DEFAULT; } +#ifndef PLATFORM_N64 + if (g_Vars.currentplayer->bondhealth <= 0.0f) { + // Hide crosshair during death animation + sight = SIGHT_NONE; + } +#endif + sightTick(sighton); switch (sight) { From 02d7efb87fd1e88d0a164a03ea662f8799ce0284 Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Sat, 27 Jan 2024 02:32:09 +0100 Subject: [PATCH 51/55] Add an option to color crosshair according to player health + shield Shield is taken into account and is added to health for the calculation, as the vast majority of damage types are fully blocked by a shield. 3 modes are available: - Off (default) - On (Green): Goes through a red-yellow-green-cyan gradient, closer to vanilla. - On (White): Goes through a red-yellow-white-green gradient, closer to games like Xonotic. When set to either of the On modes, the crosshair color setting is ignored but the crosshair alpha setting is still used. --- port/src/main.c | 1 + port/src/optionsmenu.c | 32 +++++++++++++++++++++++++ src/game/mplayer/mplayer.c | 1 + src/game/sight.c | 48 +++++++++++++++++++++++++++++++++++++- src/include/constants.h | 4 ++++ src/include/types.h | 1 + 6 files changed, 86 insertions(+), 1 deletion(-) diff --git a/port/src/main.c b/port/src/main.c index 10150f7ae..901d2eef4 100644 --- a/port/src/main.c +++ b/port/src/main.c @@ -176,5 +176,6 @@ PD_CONSTRUCTOR static void gameConfigInit(void) configRegisterInt(strFmt("Game.Player%d.ExtendedControls", i), &g_PlayerExtCfg[j].extcontrols, 0, 1); configRegisterUInt(strFmt("Game.Player%d.CrosshairColour", i), &g_PlayerExtCfg[j].crosshaircolour, 0, 0xFFFFFFFF); configRegisterUInt(strFmt("Game.Player%d.CrosshairSize", i), &g_PlayerExtCfg[j].crosshairsize, 0, 4); + configRegisterInt(strFmt("Game.Player%d.CrosshairHealth", i), &g_PlayerExtCfg[j].crosshairhealth, 0, CROSSHAIR_HEALTH_ON_WHITE); } } diff --git a/port/src/optionsmenu.c b/port/src/optionsmenu.c index dd999bee4..e8085b564 100644 --- a/port/src/optionsmenu.c +++ b/port/src/optionsmenu.c @@ -1040,6 +1040,30 @@ static MenuItemHandlerResult menuhandlerCrosshairSize(s32 operation, struct menu return 0; } +static MenuItemHandlerResult menuhandlerCrosshairHealth(s32 operation, struct menuitem *item, union handlerdata *data) +{ + static const char *opts[] = { + "Off", + "On (Green)", + "On (White)" + }; + + switch (operation) { + case MENUOP_GETOPTIONCOUNT: + data->dropdown.value = ARRAYCOUNT(opts); + break; + case MENUOP_GETOPTIONTEXT: + return (intptr_t)opts[data->dropdown.value]; + case MENUOP_SET: + g_PlayerExtCfg[g_ExtMenuPlayer].crosshairhealth = data->dropdown.value; + break; + case MENUOP_GETSELECTEDINDEX: + data->dropdown.value = g_PlayerExtCfg[g_ExtMenuPlayer].crosshairhealth; + } + + return 0; +} + struct menuitem g_ExtendedGameCrosshairColourMenuItems[] = { { MENUITEMTYPE_SLIDER, @@ -1158,6 +1182,14 @@ struct menuitem g_ExtendedGameMenuItems[] = { 0, (void*)&g_ExtendedGameCrosshairColourMenuDialog, }, + { + MENUITEMTYPE_DROPDOWN, + 0, + MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Crosshair Colour by Health", + 0, + menuhandlerCrosshairHealth, + }, { MENUITEMTYPE_SEPARATOR, 0, diff --git a/src/game/mplayer/mplayer.c b/src/game/mplayer/mplayer.c index 7246a418b..9aca1a2a2 100644 --- a/src/game/mplayer/mplayer.c +++ b/src/game/mplayer/mplayer.c @@ -124,6 +124,7 @@ struct mpweapon g_MpWeapons[NUM_MPWEAPONS] = { .extcontrols = true, \ .crosshaircolour = 0x00ff0028, \ .crosshairsize = 2, \ + .crosshairhealth = CROSSHAIR_HEALTH_OFF, \ } struct extplayerconfig g_PlayerExtCfg[MAX_PLAYERS] = { diff --git a/src/game/sight.c b/src/game/sight.c index fb5f255ae..34d6dac52 100644 --- a/src/game/sight.c +++ b/src/game/sight.c @@ -23,9 +23,55 @@ #include #include "video.h" -#define SIGHT_COLOUR PLAYER_EXTCFG().crosshaircolour +#define SIGHT_COLOUR ((PLAYER_EXTCFG().crosshairhealth >= CROSSHAIR_HEALTH_ON_GREEN) ? sightGetCrosshairHealthColor(g_Vars.currentplayer->bondhealth, g_Vars.currentplayer->prop->chr->cshield * 0.125f) : PLAYER_EXTCFG().crosshaircolour) #define SIGHT_SCALE PLAYER_EXTCFG().crosshairsize +static u32 sightGetCrosshairHealthColor(float health, float shield) +{ + const float ratio = MAX(0.0f, MIN(health + shield, 2.0f)); + + int red = 0; + int green = 0; + int blue = 0; + if (ratio < 0.2f) { + // Red (critical health level) + red = 255; + green = 0; + blue = 0; + } else if (ratio < 0.6f) { + // Red-yellow + red = 255; + green = 255 * ((ratio - 0.2f) / 0.4f); + blue = 0; + } else if (ratio < 1.0f) { + if (PLAYER_EXTCFG().crosshairhealth == CROSSHAIR_HEALTH_ON_GREEN) { + // Yellow-green + red = 255 * ((ratio - 0.6f) / 0.4f); + green = 255; + blue = 0; + } else { + // Yellow-white + red = 255; + green = 255; + blue = 255 * ((ratio - 0.6f) / 0.4f); + } + } else { + if (PLAYER_EXTCFG().crosshairhealth == CROSSHAIR_HEALTH_ON_GREEN) { + // Green-cyan (overheal via shield) + red = 0; + green = 255; + blue = 255 * (ratio - 1.0f); + } else { + // White-green (overheal via shield) + red = 255 * (2.0f - ratio); + green = 255; + blue = 255 * (2.0f - ratio); + } + } + + return (red << 24) + (green << 16) + (blue << 8) + (PLAYER_EXTCFG().crosshaircolour & 0xff); +} + static inline f32 sightGetScaleX(void) { return (videoGetAspect() / SCREEN_ASPECT); diff --git a/src/include/constants.h b/src/include/constants.h index 4c3705b7f..612138bcf 100644 --- a/src/include/constants.h +++ b/src/include/constants.h @@ -4718,6 +4718,10 @@ enum weaponnum { #define CROUCHMODE_TOGGLE 2 // press the crouch buttons to toggle stance #define CROUCHMODE_TOGGLE_ANALOG (CROUCHMODE_ANALOG | CROUCHMODE_TOGGLE) +#define CROSSHAIR_HEALTH_OFF 0 +#define CROSSHAIR_HEALTH_ON_GREEN 1 +#define CROSSHAIR_HEALTH_ON_WHITE 2 + #endif #endif diff --git a/src/include/types.h b/src/include/types.h index 2a0491896..0d772d798 100644 --- a/src/include/types.h +++ b/src/include/types.h @@ -6141,6 +6141,7 @@ struct extplayerconfig { s32 extcontrols; u32 crosshaircolour; u32 crosshairsize; + s32 crosshairhealth; }; #endif From 815c75c6a8dbc0e69553cc1d1a76b1fc70728a27 Mon Sep 17 00:00:00 2001 From: Adriano Bini Date: Mon, 29 Jan 2024 17:08:27 -0300 Subject: [PATCH 52/55] Add port-net/netplay build links to default README Some people are not being able to properly download/play because of Github's always defaulting to master's README.MD. This includes netplay links in the master branchg README as well. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index d54b38e18..6636217c6 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,9 @@ though you might have to install some additional libraries. Latest [automatic builds](https://github.com/fgsfdsfgs/perfect_dark/actions) for supported platforms: * [i686-windows](https://nightly.link/fgsfdsfgs/perfect_dark/workflows/c-cpp/port/pd-i686-windows.zip) +* [i686-windows (port-net/netplay)](https://nightly.link/fgsfdsfgs/perfect_dark/workflows/c-cpp/port-net/pd-i686-windows.zip) * [i686-linux](https://nightly.link/fgsfdsfgs/perfect_dark/workflows/c-cpp/port/pd-i686-linux.zip) +* [i686-linux (port-net/netplay)](https://nightly.link/fgsfdsfgs/perfect_dark/workflows/c-cpp/port-net/pd-i686-linux.zip) ## Running From 36f8494ebfac04ccbf04ee7a8e7c89e0e600d2dc Mon Sep 17 00:00:00 2001 From: fgsfds Date: Mon, 29 Jan 2024 22:11:34 +0100 Subject: [PATCH 53/55] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6636217c6..3451264ff 100644 --- a/README.md +++ b/README.md @@ -42,9 +42,9 @@ though you might have to install some additional libraries. Latest [automatic builds](https://github.com/fgsfdsfgs/perfect_dark/actions) for supported platforms: * [i686-windows](https://nightly.link/fgsfdsfgs/perfect_dark/workflows/c-cpp/port/pd-i686-windows.zip) -* [i686-windows (port-net/netplay)](https://nightly.link/fgsfdsfgs/perfect_dark/workflows/c-cpp/port-net/pd-i686-windows.zip) * [i686-linux](https://nightly.link/fgsfdsfgs/perfect_dark/workflows/c-cpp/port/pd-i686-linux.zip) -* [i686-linux (port-net/netplay)](https://nightly.link/fgsfdsfgs/perfect_dark/workflows/c-cpp/port-net/pd-i686-linux.zip) + +If you are looking for netplay builds (the `port-net` branch), see [this link](https://github.com/fgsfdsfgs/perfect_dark/blob/port-net/README.md#download). ## Running From 935cd1faa9ab428f5e50dbe9090d06c32922ede8 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sat, 10 Feb 2024 14:07:20 +0100 Subject: [PATCH 54/55] port: gl: dump shader source when compilation fails --- port/fast3d/gfx_opengl.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/port/fast3d/gfx_opengl.cpp b/port/fast3d/gfx_opengl.cpp index 44c420e10..f8569a370 100644 --- a/port/fast3d/gfx_opengl.cpp +++ b/port/fast3d/gfx_opengl.cpp @@ -586,6 +586,7 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad glGetShaderiv(vertex_shader, GL_INFO_LOG_LENGTH, &max_length); char error_log[1024]; glGetShaderInfoLog(vertex_shader, max_length, &max_length, &error_log[0]); + sysLogPrintf(LOG_ERROR, "Failed to compile this vertex shader (ID %llx, %x):\n%s", shader_id0, shader_id1, vs_buf); sysFatalError("Vertex shader compilation failed:\n%s", error_log); } @@ -598,6 +599,7 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad glGetShaderiv(fragment_shader, GL_INFO_LOG_LENGTH, &max_length); char error_log[1024]; glGetShaderInfoLog(fragment_shader, max_length, &max_length, &error_log[0]); + sysLogPrintf(LOG_ERROR, "Failed to compile this fragment shader (ID %llx, %x):\n%s", shader_id0, shader_id1, fs_buf); sysFatalError("Fragment shader compilation failed:\n%s", error_log); } From fe0d9b3cfdd7acf3e7bfc615d4277f8ddd633c20 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sat, 10 Feb 2024 16:56:54 +0100 Subject: [PATCH 55/55] port: fix blur shader on some older cards --- port/fast3d/gfx_opengl.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/port/fast3d/gfx_opengl.cpp b/port/fast3d/gfx_opengl.cpp index f8569a370..86efd96bc 100644 --- a/port/fast3d/gfx_opengl.cpp +++ b/port/fast3d/gfx_opengl.cpp @@ -397,19 +397,14 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad if (cc_features.opt_blur) { // blur filter, used for menu backgrounds // used to be two for loops from 0 to 4, but apparently intel drivers crashed trying to unroll it + // used to have a const weight array, but apparently drivers for the GT620 don't like const array initializers append_line(fs_buf, &fs_len, R"( - const lowp float blurWeights[16] = float[16]( - 0.009947, 0.009641, 0.008778, 0.007509, - 0.009641, 0.009345, 0.008508, 0.007278, - 0.008778, 0.008508, 0.007747, 0.006626, - 0.007509, 0.007278, 0.006626, 0.005668 - ); lowp vec4 hookTexture2D(in sampler2D t, in vec2 uv, in vec2 tsize) { lowp vec4 cw = vec4(0.0); for (int i = 0; i < 16; ++i) { vec2 xy = vec2(float(i & 3), float(i >> 2)); - vec2 ofs = (vec2(-1.5) + xy) / tsize; - cw += vec4(texture2D(t, uv + ofs).rgb * blurWeights[i], blurWeights[i]); + lowp float w = 0.009947 - length(xy) * 0.001; + cw += vec4(texture2D(t, uv + (vec2(-1.5) + xy) / tsize).rgb * w, w); } return vec4(cw.rgb / cw.a, 1.0); })"