From a4be0841e5a60a4ee690abc172ba678538a27cbe Mon Sep 17 00:00:00 2001 From: MelonSpeedruns Date: Thu, 16 Apr 2026 19:30:37 -0400 Subject: [PATCH] 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); }