From a4be0841e5a60a4ee690abc172ba678538a27cbe Mon Sep 17 00:00:00 2001 From: MelonSpeedruns Date: Thu, 16 Apr 2026 19:30:37 -0400 Subject: [PATCH 01/11] autosave WIP --- include/f_ap/f_ap_game.h | 10 ++++ src/d/d_s_play.cpp | 3 + src/d/d_save.cpp | 7 +++ src/dusk/imgui/ImGuiConsole.cpp | 6 +- src/dusk/imgui/ImGuiConsole.hpp | 2 + src/f_ap/f_ap_game.cpp | 100 ++++++++++++++++++++++++++++++++ 6 files changed, 127 insertions(+), 1 deletion(-) diff --git a/include/f_ap/f_ap_game.h b/include/f_ap/f_ap_game.h index fca2e70705..5d09d9bc28 100644 --- a/include/f_ap/f_ap_game.h +++ b/include/f_ap/f_ap_game.h @@ -14,6 +14,16 @@ void fapGm_After(); void fapGm_Create(); void fapGm_Execute(); +#if TARGET_PC +void noAutoSave(); +void triggerAutoSave(); +void updateAutoSave(); +void enterAutoSave(); +void autoSaving(); +void waitingForWrite(); +void endAutoSave(); +#endif + class fapGm_HIO_c : public JORReflexible { public: fapGm_HIO_c(); diff --git a/src/d/d_s_play.cpp b/src/d/d_s_play.cpp index 3f3cd073b9..ec8ea8f70a 100644 --- a/src/d/d_s_play.cpp +++ b/src/d/d_s_play.cpp @@ -1499,6 +1499,9 @@ static int phase_4(dScnPly_c* i_this) { } if (preLoadNo < 0) { + #if TARGET_PC + triggerAutoSave(); + #endif return cPhs_COMPLEATE_e; } diff --git a/src/d/d_save.cpp b/src/d/d_save.cpp index 3289a49c64..71f65b61e6 100644 --- a/src/d/d_save.cpp +++ b/src/d/d_save.cpp @@ -25,7 +25,10 @@ #include "lingcod/lingcod.h" #endif +#if TARGET_PC #include "dusk/settings.h" +#include +#endif static u8 dSv_item_rename(u8 i_itemNo) { switch (i_itemNo) { @@ -343,6 +346,10 @@ void dSv_player_item_c::setItem(int i_slotNo, u8 i_itemNo) { dComIfGp_setSelectItem(i); } } + + #if TARGET_PC + triggerAutoSave(); + #endif } u8 dSv_player_item_c::getItem(int i_slotNo, bool i_checkCombo) const { diff --git a/src/dusk/imgui/ImGuiConsole.cpp b/src/dusk/imgui/ImGuiConsole.cpp index eccf9b3c20..d030ca9119 100644 --- a/src/dusk/imgui/ImGuiConsole.cpp +++ b/src/dusk/imgui/ImGuiConsole.cpp @@ -267,7 +267,7 @@ namespace dusk { } if (dusk::IsGameLaunched && !m_isLaunchInitialized) { - m_toasts.emplace_back("Press F1 to toggle menu"s, 2.5f); + ShowToast("Press F1 to toggle menu", 2.5f); m_isLaunchInitialized = true; } @@ -401,6 +401,10 @@ namespace dusk { return false; } + void ImGuiConsole::ShowToast(std::string text, float time) { + m_toasts.emplace_back(text, time); + } + void ImGuiConsole::ShowToasts() { if (m_toasts.empty()) { return; diff --git a/src/dusk/imgui/ImGuiConsole.hpp b/src/dusk/imgui/ImGuiConsole.hpp index 0296dc24cc..9cef53d0e4 100644 --- a/src/dusk/imgui/ImGuiConsole.hpp +++ b/src/dusk/imgui/ImGuiConsole.hpp @@ -21,6 +21,8 @@ public: void PreDraw(); void PostDraw(); + void ShowToast(std::string, float); + static bool CheckMenuViewToggle(ImGuiKey key, bool& active); private: diff --git a/src/f_ap/f_ap_game.cpp b/src/f_ap/f_ap_game.cpp index 93a9148957..2ee6dd5e40 100644 --- a/src/f_ap/f_ap_game.cpp +++ b/src/f_ap/f_ap_game.cpp @@ -22,7 +22,15 @@ #include "f_op/f_op_scene_mng.h" #include "m_Do/m_Do_graphic.h" #include "m_Do/m_Do_main.h" + +#if TARGET_PC #include "tracy/Tracy.hpp" +#include +#include +#include +#include +#endif +#include fapGm_HIO_c::fapGm_HIO_c() { mUsingHostIO = true; @@ -732,6 +740,95 @@ static void fapGm_AfterRecord() { dusk::frame_interp::end_record(); fapGm_After(); } + +u8 mSaveBuffer[QUEST_LOG_SIZE * 3]; +u8 mAutoSaveProc = 0; +int autoSaveWriteState = 0; + +typedef void (*AutoSaveFuncs)(); +static AutoSaveFuncs AutoSaveFuncsProc[] = { + noAutoSave, + enterAutoSave, + autoSaving, + waitingForWrite, + endAutoSave, +}; + +void noAutoSave() {} + +void triggerAutoSave() { + if (mAutoSaveProc == 0 && strcmp(dComIfGp_getStartStageName(), "F_SP102") != 0 && dComIfGp_getStartStageLayer() != 0) + { + mAutoSaveProc = 1; + } +} + +void updateAutoSave() { + (AutoSaveFuncsProc[mAutoSaveProc])(); +} + +void writeAutoSave() { + int stageNo = dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo()); + + dComIfGs_putSave(stageNo); + dComIfGs_setMemoryToCard(mSaveBuffer, dComIfGs_getDataNum()); + mDoMemCdRWm_SetCheckSumGameData(mSaveBuffer, dComIfGs_getDataNum()); + + u8* save = mSaveBuffer; + for (int i = 0; i < 3; i++) { + mDoMemCdRWm_TestCheckSumGameData(save); + save += QUEST_LOG_SIZE; + } + + g_mDoMemCd_control.save(mSaveBuffer, sizeof(mSaveBuffer), 0); +} + +void autoSaving() { + int cardState = g_mDoMemCd_control.LoadSync(mSaveBuffer, sizeof(mSaveBuffer), 0); + if (cardState != 0) { + if (cardState == 2) { + mAutoSaveProc = 1; + } else if (cardState == 1) { + writeAutoSave(); + mAutoSaveProc = 3; + } + } +} + +void enterAutoSave() { + u32 cardStatus = g_mDoMemCd_control.getStatus(0); + + if (cardStatus != 14) { + switch (cardStatus) { + case 2: + g_mDoMemCd_control.load(); + mAutoSaveProc = 2; + break; + case 3: + case 4: + case 5: + break; + default: + mAutoSaveProc = 0; + break; + } + } +} + +void waitingForWrite() { + autoSaveWriteState = g_mDoMemCd_control.SaveSync(); + + if (autoSaveWriteState == 2) { + mAutoSaveProc = 0; + } else if (autoSaveWriteState == 1) { + mAutoSaveProc = 4; + } +} + +void endAutoSave() { + dusk::g_imguiConsole.ShowToast("Saving...", 3.0f); + mAutoSaveProc = 0; +} #endif void fapGm_Execute() { @@ -747,6 +844,8 @@ void fapGm_Execute() { #endif #if TARGET_PC + updateAutoSave(); + if (mDoCPd_c::getHoldR(PAD_1) && mDoCPd_c::getTrigX(PAD_1)) { if (const auto link = g_dComIfG_gameInfo.play.getPlayer(0)) { dynamic_cast(link)->handleWolfHowl(); @@ -775,6 +874,7 @@ void fapGm_Execute() { #else fpcM_ManagementFunc(NULL, fapGm_After); #endif + cCt_Counter(0); } From 39d951d0cb7523c6a7c7d920d24797e74803a374 Mon Sep 17 00:00:00 2001 From: MelonSpeedruns Date: Thu, 16 Apr 2026 19:50:20 -0400 Subject: [PATCH 02/11] scene saving now works --- src/d/d_menu_save.cpp | 3 --- src/d/d_stage.cpp | 4 ++++ src/f_ap/f_ap_game.cpp | 2 -- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/d/d_menu_save.cpp b/src/d/d_menu_save.cpp index 618677866b..cbff78c659 100644 --- a/src/d/d_menu_save.cpp +++ b/src/d/d_menu_save.cpp @@ -1326,9 +1326,6 @@ void dMenu_save_c::memCardDataLoadWait() { } void dMenu_save_c::dataWrite() { - int stageNo = dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo()); - - dComIfGs_putSave(stageNo); dComIfGs_setMemoryToCard(mSaveBuffer, mSelectedFile); mDoMemCdRWm_SetCheckSumGameData(mSaveBuffer, mSelectedFile); diff --git a/src/d/d_stage.cpp b/src/d/d_stage.cpp index f3cdfed17b..c84616873a 100644 --- a/src/d/d_stage.cpp +++ b/src/d/d_stage.cpp @@ -326,6 +326,10 @@ int dStage_roomControl_c::loadRoom(int roomCount, u8* rooms, bool param_2) { if (!r26) { return FALSE; } + + #if TARGET_PC + triggerAutoSave(); + #endif for (int i = 0; i < roomCount; i++) { int roomNo = dStage_roomRead_dt_c_GetLoadRoomIndex(rooms[i]); diff --git a/src/f_ap/f_ap_game.cpp b/src/f_ap/f_ap_game.cpp index 2ee6dd5e40..9aa1763b8a 100644 --- a/src/f_ap/f_ap_game.cpp +++ b/src/f_ap/f_ap_game.cpp @@ -28,9 +28,7 @@ #include #include #include -#include #endif -#include fapGm_HIO_c::fapGm_HIO_c() { mUsingHostIO = true; From 842210e5395adf9371b83b5d0f4eba0601a56072 Mon Sep 17 00:00:00 2001 From: MelonSpeedruns Date: Thu, 16 Apr 2026 19:56:04 -0400 Subject: [PATCH 03/11] remove scene autosave cause that's buggy atm --- src/d/d_s_play.cpp | 3 --- src/d/d_stage.cpp | 4 ---- 2 files changed, 7 deletions(-) diff --git a/src/d/d_s_play.cpp b/src/d/d_s_play.cpp index ec8ea8f70a..3f3cd073b9 100644 --- a/src/d/d_s_play.cpp +++ b/src/d/d_s_play.cpp @@ -1499,9 +1499,6 @@ static int phase_4(dScnPly_c* i_this) { } if (preLoadNo < 0) { - #if TARGET_PC - triggerAutoSave(); - #endif return cPhs_COMPLEATE_e; } diff --git a/src/d/d_stage.cpp b/src/d/d_stage.cpp index c84616873a..f3cdfed17b 100644 --- a/src/d/d_stage.cpp +++ b/src/d/d_stage.cpp @@ -326,10 +326,6 @@ int dStage_roomControl_c::loadRoom(int roomCount, u8* rooms, bool param_2) { if (!r26) { return FALSE; } - - #if TARGET_PC - triggerAutoSave(); - #endif for (int i = 0; i < roomCount; i++) { int roomNo = dStage_roomRead_dt_c_GetLoadRoomIndex(rooms[i]); From 8c5673d9b8dcb87448902183006f791d3cc0f93b Mon Sep 17 00:00:00 2001 From: MelonSpeedruns Date: Fri, 17 Apr 2026 13:12:20 -0400 Subject: [PATCH 04/11] autosave when loading scene --- src/d/d_s_play.cpp | 16 ++++++++++++++++ src/f_ap/f_ap_game.cpp | 3 --- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/d/d_s_play.cpp b/src/d/d_s_play.cpp index 3f3cd073b9..9af875b2f5 100644 --- a/src/d/d_s_play.cpp +++ b/src/d/d_s_play.cpp @@ -700,6 +700,10 @@ static u8 lbl_8074CAE4; static u32 l_sceneChangeStartTick; #endif +#if TARGET_PC +static BOOL shouldAutoSave; +#endif + static int dScnPly_Execute(dScnPly_c* i_this) { #if DEBUG fapGm_HIO_c::startCpuTimer(); @@ -742,6 +746,13 @@ static int dScnPly_Execute(dScnPly_c* i_this) { } } + #if TARGET_PC + if (!fopOvlpM_IsPeek() && !dComIfG_resetToOpening(i_this) && !dComIfGp_isEnableNextStage() && shouldAutoSave == FALSE) { + triggerAutoSave(); + shouldAutoSave = TRUE; + } + #endif + dKy_itudemo_se(); #if DEBUG @@ -1598,6 +1609,11 @@ static int dScnPly_Create(scene_class* i_this) { dScnPly_c* a_this = (dScnPly_c*)i_this; int phase_state = dComLbG_PhaseHandler(&a_this->field_0x1c4, l_method, a_this); + + #if TARGET_PC + shouldAutoSave = FALSE; + #endif + return phase_state; } diff --git a/src/f_ap/f_ap_game.cpp b/src/f_ap/f_ap_game.cpp index 9aa1763b8a..3dc192b665 100644 --- a/src/f_ap/f_ap_game.cpp +++ b/src/f_ap/f_ap_game.cpp @@ -766,9 +766,6 @@ void updateAutoSave() { } void writeAutoSave() { - int stageNo = dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo()); - - dComIfGs_putSave(stageNo); dComIfGs_setMemoryToCard(mSaveBuffer, dComIfGs_getDataNum()); mDoMemCdRWm_SetCheckSumGameData(mSaveBuffer, dComIfGs_getDataNum()); From 8afb1141abd220791159c69aa94fe8af82c3304a Mon Sep 17 00:00:00 2001 From: MelonSpeedruns Date: Fri, 17 Apr 2026 13:41:56 -0400 Subject: [PATCH 05/11] Autosave when changing rooms --- src/d/d_save.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/d/d_save.cpp b/src/d/d_save.cpp index 71f65b61e6..c872cb0f17 100644 --- a/src/d/d_save.cpp +++ b/src/d/d_save.cpp @@ -1482,6 +1482,9 @@ void dSv_restart_c::setRoom(const cXyz& i_position, s16 i_angleY, s8 i_roomNo) { mRoomNo = i_roomNo; mRoomPos = i_position; mRoomAngleY = i_angleY; + #if TARGET_PC + triggerAutoSave(); + #endif } void dSv_turnRestart_c::set(const cXyz& i_position, s16 i_angleY, s8 param_3, u32 i_param) { From c157564da6dd3b45b2738cf721fad9c7c31212ab Mon Sep 17 00:00:00 2001 From: MelonSpeedruns Date: Mon, 20 Apr 2026 13:02:25 -0400 Subject: [PATCH 06/11] dungeon doors now autosave --- src/d/actor/d_a_door_shutter.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/d/actor/d_a_door_shutter.cpp b/src/d/actor/d_a_door_shutter.cpp index a481762132..d416d0b2bc 100644 --- a/src/d/actor/d_a_door_shutter.cpp +++ b/src/d/actor/d_a_door_shutter.cpp @@ -17,6 +17,10 @@ #include #include +#if TARGET_PC +#include +#endif + char* daDoor20_c::getStopBmdName() { switch (door_param2_c::getKind(this)) { case 3: @@ -196,6 +200,7 @@ void daDoor20_c::setEventPrm() { } else { roomNo = FRoomNo; } + if (dComIfGp_roomControl_checkStatusFlag(roomNo, 1)) { if (door_param2_c::getKind(this) == 9) { if (daPy_py_c::checkNowWolf()) { @@ -564,6 +569,11 @@ int daDoor20_c::openEnd(int param_1) { openEnd_1(); break; } + + #if TARGET_PC + triggerAutoSave(); + #endif + return 1; } From 871d18e294168d55f78f46b4cc0e95164dc482af Mon Sep 17 00:00:00 2001 From: MelonSpeedruns Date: Mon, 20 Apr 2026 13:15:37 -0400 Subject: [PATCH 07/11] added experimental setting for autosave --- include/dusk/settings.h | 1 + src/dusk/imgui/ImGuiFirstRunPreset.cpp | 1 + src/dusk/imgui/ImGuiMenuEnhancements.cpp | 12 ++++++++++++ src/dusk/settings.cpp | 22 ++++++++++++---------- src/f_ap/f_ap_game.cpp | 2 +- 5 files changed, 27 insertions(+), 11 deletions(-) diff --git a/include/dusk/settings.h b/include/dusk/settings.h index 03749967c9..31058a7cdd 100644 --- a/include/dusk/settings.h +++ b/include/dusk/settings.h @@ -63,6 +63,7 @@ struct UserSettings { ConfigVar instantSaves; ConfigVar instantText; ConfigVar sunsSong; + ConfigVar autoSave; // Preferences ConfigVar enableMirrorMode; diff --git a/src/dusk/imgui/ImGuiFirstRunPreset.cpp b/src/dusk/imgui/ImGuiFirstRunPreset.cpp index fb2d181562..d3f5441d94 100644 --- a/src/dusk/imgui/ImGuiFirstRunPreset.cpp +++ b/src/dusk/imgui/ImGuiFirstRunPreset.cpp @@ -41,6 +41,7 @@ static void ApplyPresetDusk() { s.game.enableFrameInterpolation.setValue(true); s.game.sunsSong.setValue(true); s.game.bloomMode.setValue(BloomMode::Dusk); + s.game.autoSave.setValue(true); } // ========================================================================= diff --git a/src/dusk/imgui/ImGuiMenuEnhancements.cpp b/src/dusk/imgui/ImGuiMenuEnhancements.cpp index 7d179aa578..e469a830df 100644 --- a/src/dusk/imgui/ImGuiMenuEnhancements.cpp +++ b/src/dusk/imgui/ImGuiMenuEnhancements.cpp @@ -65,6 +65,18 @@ namespace dusk { ImGui::SetTooltip("Skip the delay when writing to the Memory Card."); } + config::ImGuiCheckbox("Autosave", getSettings().game.autoSave); + const bool autoSaveHovered = ImGui::IsItemHovered(); + ImGui::SameLine(); + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.72f, 0.2f, 1.0f)); + ImGui::TextUnformatted("[EXPERIMENTAL]"); + ImGui::PopStyleColor(); + if (autoSaveHovered || ImGui::IsItemHovered()) { + ImGui::SetTooltip( + "Automatically saves the game when going to new areas,\n" + "getting an item, or opening a dungeon door."); + } + config::ImGuiCheckbox("Hold B for Instant Text", getSettings().game.instantText); if (ImGui::IsItemHovered()) { ImGui::SetTooltip("Make text scroll immediately by holding B."); diff --git a/src/dusk/settings.cpp b/src/dusk/settings.cpp index 2bcdbe2185..9e6ae0f5d5 100644 --- a/src/dusk/settings.cpp +++ b/src/dusk/settings.cpp @@ -29,7 +29,7 @@ UserSettings g_userSettings = { .disableRupeeCutscenes {"game.disableRupeeCutscenes", false}, .noSwordRecoil {"game.noSwordRecoil", false}, .damageMultiplier {"game.damageMultiplier", 1}, - .noHeartDrops{"game.noHeartDrops", false}, + .noHeartDrops {"game.noHeartDrops", false}, .instantDeath {"game.instantDeath", false}, .fastClimbing {"game.fastClimbing", false}, .noMissClimbing {"game.noMissClimbing", false}, @@ -37,6 +37,7 @@ UserSettings g_userSettings = { .instantSaves {"game.instantSaves", false}, .instantText {"game.instantText", false}, .sunsSong {"game.sunsSong", false}, + .autoSave {"game.autoSave", false}, // Preferences .enableMirrorMode {"game.enableMirrorMode", false}, @@ -48,7 +49,7 @@ UserSettings g_userSettings = { .bloomMode {"game.bloomMode", BloomMode::Classic}, .bloomMultiplier {"game.bloomMultiplier", 1.0f}, .disableWaterRefraction {"game.disableWaterRefraction", false}, - .enableFrameInterpolation = {"game.enableFrameInterpolation", false}, + .enableFrameInterpolation {"game.enableFrameInterpolation", false}, .internalResolutionScale {"game.internalResolutionScale", 0}, .shadowResolutionMultiplier {"game.shadowResolutionMultiplier", 1}, @@ -69,14 +70,14 @@ UserSettings g_userSettings = { // Cheats .infiniteHearts {"game.infiniteHearts", false}, - .infiniteArrows{"game.infiniteArrows", false}, - .infiniteBombs{"game.infiniteBombs", false}, - .infiniteOil{"game.infiniteOil", false}, - .infiniteOxygen{"game.infiniteOxygen", false}, - .infiniteRupees{"game.infiniteRupees", false}, - .moonJump{"game.moonJump", false}, - .superClawshot{"game.superClawshot", false}, - .alwaysGreatspin{"game.alwaysGreatspin", false}, + .infiniteArrows {"game.infiniteArrows", false}, + .infiniteBombs {"game.infiniteBombs", false}, + .infiniteOil {"game.infiniteOil", false}, + .infiniteOxygen {"game.infiniteOxygen", false}, + .infiniteRupees {"game.infiniteRupees", false}, + .moonJump {"game.moonJump", false}, + .superClawshot {"game.superClawshot", false}, + .alwaysGreatspin {"game.alwaysGreatspin", false}, .enableFastIronBoots {"game.enableFastIronBoots", false}, .canTransformAnywhere {"game.canTransformAnywhere", false}, .fastSpinner {"game.fastSpinner", false}, @@ -134,6 +135,7 @@ void registerSettings() { Register(g_userSettings.game.instantSaves); Register(g_userSettings.game.instantText); Register(g_userSettings.game.sunsSong); + Register(g_userSettings.game.autoSave); Register(g_userSettings.game.enableMirrorMode); Register(g_userSettings.game.invertCameraXAxis); Register(g_userSettings.game.disableMainHUD); diff --git a/src/f_ap/f_ap_game.cpp b/src/f_ap/f_ap_game.cpp index d66c6fbbe1..4a4c37fd7b 100644 --- a/src/f_ap/f_ap_game.cpp +++ b/src/f_ap/f_ap_game.cpp @@ -755,7 +755,7 @@ static AutoSaveFuncs AutoSaveFuncsProc[] = { void noAutoSave() {} void triggerAutoSave() { - if (mAutoSaveProc == 0 && strcmp(dComIfGp_getStartStageName(), "F_SP102") != 0 && dComIfGp_getStartStageLayer() != 0) + if (dusk::getSettings().game.autoSave && mAutoSaveProc == 0 && strcmp(dComIfGp_getStartStageName(), "F_SP102") != 0 && dComIfGp_getStartStageLayer() != 0) { mAutoSaveProc = 1; } From d7dced7ddfb0205aa3003843183eae9e8a71779a Mon Sep 17 00:00:00 2001 From: MelonSpeedruns Date: Sat, 25 Apr 2026 08:25:50 -0400 Subject: [PATCH 08/11] don't autosave if playing a cutscene --- src/d/d_s_play.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/d/d_s_play.cpp b/src/d/d_s_play.cpp index b549bd073d..1bc02029ec 100644 --- a/src/d/d_s_play.cpp +++ b/src/d/d_s_play.cpp @@ -748,7 +748,9 @@ static int dScnPly_Execute(dScnPly_c* i_this) { } #if TARGET_PC - if (!fopOvlpM_IsPeek() && !dComIfG_resetToOpening(i_this) && !dComIfGp_isEnableNextStage() && shouldAutoSave == FALSE) { + if (!dComIfGp_event_runCheck() && !fopOvlpM_IsPeek() && !dComIfG_resetToOpening(i_this) && + !dComIfGp_isEnableNextStage() && shouldAutoSave == FALSE) + { triggerAutoSave(); shouldAutoSave = TRUE; } From d6820c9233fcbeaabd8cac6f9ea38482747d5af2 Mon Sep 17 00:00:00 2001 From: MelonSpeedruns Date: Thu, 30 Apr 2026 14:53:15 -0400 Subject: [PATCH 09/11] fix toast call --- src/dusk/imgui/ImGuiConsole.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dusk/imgui/ImGuiConsole.cpp b/src/dusk/imgui/ImGuiConsole.cpp index cbd3998116..12b4cf87d9 100644 --- a/src/dusk/imgui/ImGuiConsole.cpp +++ b/src/dusk/imgui/ImGuiConsole.cpp @@ -366,9 +366,9 @@ namespace dusk { if (dusk::IsGameLaunched && !m_isLaunchInitialized) { AddToast(ImGui::GetIO().MouseSource == ImGuiMouseSource_TouchScreen ? - "Tap to toggle menu" : - "Press F1 to toggle menu", - 2.5f); + "Tap to toggle menu"s : + "Press F1 to toggle menu"s, + 2.5f); m_isLaunchInitialized = true; if (getSettings().game.liveSplitEnabled) { dusk::speedrun::connectLiveSplit(); From c1ba10fc8b358794a8de318ac81b989c3cdbb3c5 Mon Sep 17 00:00:00 2001 From: MelonSpeedruns Date: Sat, 2 May 2026 10:29:23 -0400 Subject: [PATCH 10/11] fix mistake --- src/d/d_menu_save.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/d/d_menu_save.cpp b/src/d/d_menu_save.cpp index 1f9d11b63c..53dbe37ca4 100644 --- a/src/d/d_menu_save.cpp +++ b/src/d/d_menu_save.cpp @@ -1335,6 +1335,9 @@ void dMenu_save_c::memCardDataLoadWait() { } void dMenu_save_c::dataWrite() { + int stageNo = dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo()); + + dComIfGs_putSave(stageNo); dComIfGs_setMemoryToCard(mSaveBuffer, mSelectedFile); mDoMemCdRWm_SetCheckSumGameData(mSaveBuffer, mSelectedFile); From e3ad41792ad8a83f522f67b3fc7488fe5db6fa2b Mon Sep 17 00:00:00 2001 From: MelonSpeedruns Date: Sat, 2 May 2026 10:42:20 -0400 Subject: [PATCH 11/11] fix respawn stageinfo when autosaving --- src/d/d_s_play.cpp | 8 ++++---- src/dusk/autosave.cpp | 5 ++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/d/d_s_play.cpp b/src/d/d_s_play.cpp index 1bc02029ec..f0e2330a15 100644 --- a/src/d/d_s_play.cpp +++ b/src/d/d_s_play.cpp @@ -702,7 +702,7 @@ static u32 l_sceneChangeStartTick; #endif #if TARGET_PC -static BOOL shouldAutoSave; +static BOOL autoSaved; #endif static int dScnPly_Execute(dScnPly_c* i_this) { @@ -749,10 +749,10 @@ static int dScnPly_Execute(dScnPly_c* i_this) { #if TARGET_PC if (!dComIfGp_event_runCheck() && !fopOvlpM_IsPeek() && !dComIfG_resetToOpening(i_this) && - !dComIfGp_isEnableNextStage() && shouldAutoSave == FALSE) + !dComIfGp_isEnableNextStage() && autoSaved == FALSE) { triggerAutoSave(); - shouldAutoSave = TRUE; + autoSaved = TRUE; } #endif @@ -1609,7 +1609,7 @@ static int dScnPly_Create(scene_class* i_this) { int phase_state = dComLbG_PhaseHandler(&a_this->field_0x1c4, l_method, a_this); #if TARGET_PC - shouldAutoSave = FALSE; + autoSaved = FALSE; #endif return phase_state; diff --git a/src/dusk/autosave.cpp b/src/dusk/autosave.cpp index 23cef619a0..f9b76f4c67 100644 --- a/src/dusk/autosave.cpp +++ b/src/dusk/autosave.cpp @@ -14,7 +14,7 @@ void noAutoSave() {} void triggerAutoSave() { if (dusk::getSettings().game.autoSave && mAutoSaveProc == 0 && - strcmp(dComIfGp_getStartStageName(), "F_SP102") != 0 && dComIfGp_getStartStageLayer() != 0) + strcmp(dComIfGp_getStartStageName(), "F_SP102") != 0) { mAutoSaveProc = 1; } @@ -25,6 +25,9 @@ void updateAutoSave() { } void writeAutoSave() { + int stageNo = dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo()); + + dComIfGs_putSave(stageNo); dComIfGs_setMemoryToCard(mSaveBuffer, dComIfGs_getDataNum()); mDoMemCdRWm_SetCheckSumGameData(mSaveBuffer, dComIfGs_getDataNum());