diff --git a/mm/2s2h/BenGui/BenMenuBar.cpp b/mm/2s2h/BenGui/BenMenuBar.cpp index f9f5b9911..e1a486287 100644 --- a/mm/2s2h/BenGui/BenMenuBar.cpp +++ b/mm/2s2h/BenGui/BenMenuBar.cpp @@ -46,6 +46,12 @@ static std::unordered_map windowBackendsMap = { Ship::WindowBackend::GX2, "GX2" } }; +static const std::unordered_map clockTypeOptions = { + { CLOCK_TYPE_ORIGINAL, "Original" }, + { CLOCK_TYPE_TEXT_BASED, "Text only" }, + { CLOCK_TYPE_HIDDEN, "Hidden" }, +}; + static const std::unordered_map alwaysWinDoggyraceOptions = { { ALWAYS_WIN_DOGGY_RACE_OFF, "Off" }, { ALWAYS_WIN_DOGGY_RACE_MASKOFTRUTH, "When owning Mask of Truth" }, @@ -404,9 +410,11 @@ void DrawEnhancementsMenu() { } if (UIWidgets::BeginMenu("Graphics")) { + ImGui::SeparatorText("Clock"); + UIWidgets::CVarCombobox("Clock Type", "gEnhancements.Graphics.ClockType", clockTypeOptions); + UIWidgets::CVarCheckbox("24 Hours Clock", "gEnhancements.Graphics.24HoursClock"); MotionBlur_RenderMenuOptions(); ImGui::SeparatorText("Other"); - UIWidgets::CVarCheckbox("24 Hours Clock", "gEnhancements.Graphics.24HoursClock"); UIWidgets::CVarCheckbox("Authentic logo", "gEnhancements.Graphics.AuthenticLogo", { .tooltip = "Hide the game version and build details and display the authentic model and texture on the boot logo start screen" }); diff --git a/mm/2s2h/DeveloperTools/SaveEditor.cpp b/mm/2s2h/DeveloperTools/SaveEditor.cpp index 18c3e98d0..61af2b16f 100644 --- a/mm/2s2h/DeveloperTools/SaveEditor.cpp +++ b/mm/2s2h/DeveloperTools/SaveEditor.cpp @@ -167,8 +167,8 @@ void DrawGeneralTab() { std::string minutes = (curMinutes < 10 ? "0" : "") + std::to_string(curMinutes); std::string hours = ""; std::string ampm = ""; - // BENTODO: Switch to CVar if we ever add 24 hour mode display - if (false) { + // Handle 24 or 12 hour time + if (CVarGetInteger("gEnhancements.Graphics.24HoursClock", 0)) { if (curHours < 10) { hours += "0"; } diff --git a/mm/2s2h/Enhancements/Enhancements.cpp b/mm/2s2h/Enhancements/Enhancements.cpp index f761306ec..80a387afe 100644 --- a/mm/2s2h/Enhancements/Enhancements.cpp +++ b/mm/2s2h/Enhancements/Enhancements.cpp @@ -10,6 +10,9 @@ void InitEnhancements() { RegisterMoonJumpOnL(); RegisterUnbreakableRazorSword(); + // Clock + RegisterTextBasedClock(); + // Cycle RegisterEndOfCycleSaveHooks(); diff --git a/mm/2s2h/Enhancements/Enhancements.h b/mm/2s2h/Enhancements/Enhancements.h index 751c1b1a2..4055d2ed2 100644 --- a/mm/2s2h/Enhancements/Enhancements.h +++ b/mm/2s2h/Enhancements/Enhancements.h @@ -5,6 +5,7 @@ #include "Camera/FreeLook.h" #include "Cheats/MoonJump.h" #include "Cheats/Infinite.h" +#include "Graphics/TextBasedClock.h" #include "Cheats/UnbreakableRazorSword.h" #include "Cycle/EndOfCycle.h" #include "Masks/FierceDeityAnywhere.h" @@ -24,6 +25,12 @@ enum AlwaysWinDoggyRaceOptions { ALWAYS_WIN_DOGGY_RACE_ALWAYS, }; +enum ClockTypeOptions { + CLOCK_TYPE_ORIGINAL, + CLOCK_TYPE_TEXT_BASED, + CLOCK_TYPE_HIDDEN, +}; + #ifdef __cplusplus extern "C" { #endif diff --git a/mm/2s2h/Enhancements/GameInteractor/GameInteractor.h b/mm/2s2h/Enhancements/GameInteractor/GameInteractor.h index 9e9545397..bd6bc2bce 100644 --- a/mm/2s2h/Enhancements/GameInteractor/GameInteractor.h +++ b/mm/2s2h/Enhancements/GameInteractor/GameInteractor.h @@ -39,6 +39,7 @@ typedef enum { GI_VB_PATCH_POWER_CROUCH_STAB, GI_VB_PATCH_SIDEROLL, GI_VB_PREVENT_MASK_TRANSFORMATION_CS, + GI_VB_PREVENT_CLOCK_DISPLAY, GI_VB_SONG_AVAILABLE_TO_PLAY, GI_VB_USE_CUSTOM_CAMERA, } GIVanillaBehavior; diff --git a/mm/2s2h/Enhancements/Graphics/TextBasedClock.cpp b/mm/2s2h/Enhancements/Graphics/TextBasedClock.cpp new file mode 100644 index 000000000..a179607ec --- /dev/null +++ b/mm/2s2h/Enhancements/Graphics/TextBasedClock.cpp @@ -0,0 +1,93 @@ +#include +#include "Enhancements/GameInteractor/GameInteractor.h" +#include "2s2h/Enhancements/FrameInterpolation/FrameInterpolation.h" +#include "Enhancements/Enhancements.h" + +extern "C" { +#include +#include +#include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h" + +extern PlayState* gPlayState; +} + +void RegisterTextBasedClock() { + REGISTER_VB_SHOULD(GI_VB_PREVENT_CLOCK_DISPLAY, { + + if (CVarGetInteger("gEnhancements.Graphics.ClockType", CLOCK_TYPE_ORIGINAL) == CLOCK_TYPE_HIDDEN) { + *should = true; + return; + } + + if (CVarGetInteger("gEnhancements.Graphics.ClockType", CLOCK_TYPE_ORIGINAL) == CLOCK_TYPE_TEXT_BASED) { + *should = true; + if ((R_TIME_SPEED != 0) && + ((gPlayState->msgCtx.msgMode == MSGMODE_NONE) || + ((gPlayState->actorCtx.flags & ACTORCTX_FLAG_1) && !Play_InCsMode(gPlayState)) || + (gPlayState->msgCtx.msgMode == MSGMODE_NONE) || + ((gPlayState->msgCtx.currentTextId >= 0x100) && (gPlayState->msgCtx.currentTextId <= 0x200)) || + (gSaveContext.gameMode == GAMEMODE_END_CREDITS)) && + !FrameAdvance_IsEnabled(&gPlayState->state) && !Environment_IsTimeStopped() && (gSaveContext.save.day <= 3)) { + + OPEN_DISPS(gPlayState->state.gfxCtx); + + if ((gPlayState->pauseCtx.state == PAUSE_STATE_OFF) && (gPlayState->pauseCtx.debugEditor == DEBUG_EDITOR_NONE)) { + Gfx_SetupDL39_Overlay(gPlayState->state.gfxCtx); + + u16 curMinutes = (s32)TIME_TO_MINUTES_F(gSaveContext.save.time) % 60; + u16 curHours = (s32)TIME_TO_MINUTES_F(gSaveContext.save.time) / 60; + + u16 timeUntilMoonCrash = (s32)TIME_UNTIL_MOON_CRASH; + u16 timeInMinutes = (s32)TIME_TO_MINUTES_F(timeUntilMoonCrash) % 60; + u16 timeInHours = (s32)TIME_TO_MINUTES_F(timeUntilMoonCrash) / 60; + + char formattedTime[10]; + char formattedCrashTime[10]; + + OPEN_PRINTER(OVERLAY_DISP); + + // Inverted time + if (gSaveContext.save.timeSpeedOffset == -2) { + GfxPrint_SetColor(&printer, 0, 204, 255, 255); + } else { + GfxPrint_SetColor(&printer, 255, 255, 255, 255); + } + + if (CVarGetInteger("gEnhancements.Graphics.24HoursClock", 0)) { + sprintf(formattedTime, "%02d:%02d", curHours, curMinutes); + GfxPrint_SetPos(&printer, 14, 26); + } else { // Format hours and minutes for 12-hour AM/PM clock + char amPm[3] = "am"; + if (curHours >= 12) { + strcpy(amPm, "pm"); + if (curHours > 12) { + curHours -= 12; + } + } + if (curHours == 0) { + curHours = 12; + } + sprintf(formattedTime, "%02d:%02d%s", curHours, curMinutes, amPm); + GfxPrint_SetPos(&printer, 13, 26); + } + + GfxPrint_Printf(&printer, "Day %d: %s", gSaveContext.save.day, formattedTime); + GfxPrint_SetPos(&printer, 13, 27); + + // Crash Countdown + if ((CURRENT_DAY >= 4) || + ((CURRENT_DAY == 3) && (((void)0, gSaveContext.save.time) >= (CLOCK_TIME(0, 0) + 5)) && + (((void)0, gSaveContext.save.time) < CLOCK_TIME(6, 0)))) { + GfxPrint_SetColor(&printer, 255, 0, 0, 255); + sprintf(formattedCrashTime, "%02d:%02d", timeInHours, timeInMinutes); + GfxPrint_Printf(&printer, "Crash in %s", formattedCrashTime); + } + + CLOSE_PRINTER(printer, OVERLAY_DISP); + } + + CLOSE_DISPS(gPlayState->state.gfxCtx); + } + } + }); +} diff --git a/mm/2s2h/Enhancements/Graphics/TextBasedClock.h b/mm/2s2h/Enhancements/Graphics/TextBasedClock.h new file mode 100644 index 000000000..c85ba9450 --- /dev/null +++ b/mm/2s2h/Enhancements/Graphics/TextBasedClock.h @@ -0,0 +1,6 @@ +#ifndef TEXT_BASED_CLOCK_H +#define TEXT_BASED_CLOCK_H + +void RegisterTextBasedClock(); + +#endif // TEXT_BASED_CLOCK_H diff --git a/mm/include/gfxprint.h b/mm/include/gfxprint.h index 6149a5c4a..f6c896c01 100644 --- a/mm/include/gfxprint.h +++ b/mm/include/gfxprint.h @@ -47,4 +47,18 @@ Gfx* GfxPrint_Close(GfxPrint* this); s32 GfxPrint_VPrintf(GfxPrint* this, const char* fmt, va_list args); s32 GfxPrint_Printf(GfxPrint* this, const char* fmt, ...); +// #region 2S2H [Port] Open/Close helper macros for the GfxPrint system +#define OPEN_PRINTER(disp) \ + { \ + GfxPrint printer; \ + GfxPrint_Init(&printer); \ + GfxPrint_Open(&printer, disp) + +#define CLOSE_PRINTER(printer, disp) \ + disp = GfxPrint_Close(&printer); \ + GfxPrint_Destroy(&printer); \ + } \ + (void)0 +// #endregion + #endif diff --git a/mm/src/code/z_parameter.c b/mm/src/code/z_parameter.c index 3ba9f4cfa..6b27c7d96 100644 --- a/mm/src/code/z_parameter.c +++ b/mm/src/code/z_parameter.c @@ -5906,7 +5906,7 @@ void Interface_DrawClock(PlayState* play) { gEmptyTexture, gEmptyTexture, // 2S2H [Port] To account for the vanilla bug detailed later on in this function }; // 2S2H Region [Enhancements] 24 Hours Clock - static TexturePtr sThreeDayClockHourTwentyHourHoursTextures[] = { + static TexturePtr sThreeDayClockHourTwentyFourHoursTextures[] = { gThreeDayClockHour24Tex, gThreeDayClockHour1Tex, gThreeDayClockHour2Tex, gThreeDayClockHour3Tex, gThreeDayClockHour4Tex, gThreeDayClockHour5Tex, gThreeDayClockHour6Tex, gThreeDayClockHour7Tex, gThreeDayClockHour8Tex, gThreeDayClockHour9Tex, gThreeDayClockHour10Tex, gThreeDayClockHour11Tex, @@ -5960,6 +5960,10 @@ void Interface_DrawClock(PlayState* play) { s16 finalHoursClockSlots[8]; s16 index; + if (GameInteractor_Should(GI_VB_PREVENT_CLOCK_DISPLAY, false, NULL)) { + return; + } + OPEN_DISPS(play->state.gfxCtx); if ((R_TIME_SPEED != 0) && @@ -6278,7 +6282,7 @@ void Interface_DrawClock(PlayState* play) { gSPVertex(OVERLAY_DISP++, &interfaceCtx->actionVtx[24], 8, 0); OVERLAY_DISP = CVarGetInteger("gEnhancements.Graphics.24HoursClock", 0) ? - Gfx_DrawTexQuad4b(OVERLAY_DISP, sThreeDayClockHourTwentyHourHoursTextures[sp1C6], 4, 16, 11, 0) : + Gfx_DrawTexQuad4b(OVERLAY_DISP, sThreeDayClockHourTwentyFourHoursTextures[sp1C6], 4, 16, 11, 0) : Gfx_DrawTexQuad4b(OVERLAY_DISP, sThreeDayClockHourTextures[sp1C6], 4, 16, 11, 0); // Colours the Three-Day Clocks's Hour Digit Above the Sun @@ -6304,7 +6308,7 @@ void Interface_DrawClock(PlayState* play) { gSPVertex(OVERLAY_DISP++, &interfaceCtx->actionVtx[32], 8, 0); OVERLAY_DISP = CVarGetInteger("gEnhancements.Graphics.24HoursClock", 0) ? - Gfx_DrawTexQuad4b(OVERLAY_DISP, sThreeDayClockHourTwentyHourHoursTextures[sp1C6], 4, 16, 11, 0) : + Gfx_DrawTexQuad4b(OVERLAY_DISP, sThreeDayClockHourTwentyFourHoursTextures[sp1C6], 4, 16, 11, 0) : Gfx_DrawTexQuad4b(OVERLAY_DISP, sThreeDayClockHourTextures[sp1C6], 4, 16, 11, 0);