diff --git a/source/CCustomOpcodeSystem.cpp b/source/CCustomOpcodeSystem.cpp index 58ecbe4e..2c544945 100644 --- a/source/CCustomOpcodeSystem.cpp +++ b/source/CCustomOpcodeSystem.cpp @@ -25,6 +25,7 @@ namespace CLEO OpcodeResult __stdcall opcode_004E(CRunningScript* thread); // terminate_this_script OpcodeResult __stdcall opcode_0051(CRunningScript * thread); // GOSUB return + OpcodeResult __stdcall opcode_03D9(CRunningScript* thread); // has_save_game_finished OpcodeResult __stdcall opcode_0417(CRunningScript* thread); // load_and_launch_mission_internal OpcodeResult __stdcall opcode_0A92(CRunningScript* thread); // stream_custom_script @@ -235,6 +236,7 @@ namespace CLEO CLEO_RegisterOpcode(0x004E, opcode_004E); CLEO_RegisterOpcode(0x0051, opcode_0051); + CLEO_RegisterOpcode(0x03D9, opcode_03D9); CLEO_RegisterOpcode(0x0417, opcode_0417); CLEO_RegisterOpcode(0x0A92, opcode_0A92); CLEO_RegisterOpcode(0x0A93, opcode_0A93); @@ -823,6 +825,20 @@ namespace CLEO return originalOpcodeHandlers[tableIdx](thread, 0x0051); // call game's original } + OpcodeResult __stdcall CCustomOpcodeSystem::opcode_03D9(CRunningScript* thread) // has_save_game_finished + { + if (thread->IsCustom()) + { + bool saveProcessing = (GetInstance().GameState() == GameSessionState::Initial) && (GetInstance().saveSlot) != -1; + + OPCODE_CONDITION_RESULT(!saveProcessing); + return OR_CONTINUE; + } + + size_t tableIdx = 0x03D9 / 100; // 100 opcodes peer handler table + return originalOpcodeHandlers[tableIdx](thread, 0x03D9); // call game's original + } + OpcodeResult __stdcall CCustomOpcodeSystem::opcode_0417(CRunningScript* thread) // load_and_launch_mission_internal { MissionIndex = CLEO_PeekIntOpcodeParam(thread); diff --git a/source/CCustomOpcodeSystem.h b/source/CCustomOpcodeSystem.h index 6bd50410..724f8139 100644 --- a/source/CCustomOpcodeSystem.h +++ b/source/CCustomOpcodeSystem.h @@ -46,6 +46,7 @@ namespace CLEO static OpcodeResult __stdcall opcode_004E(CRunningScript* thread); // terminate_this_script static OpcodeResult __stdcall opcode_0051(CRunningScript* thread); // GOSUB's return + static OpcodeResult __stdcall opcode_03D9(CRunningScript* thread); // has_save_game_finished static OpcodeResult __stdcall opcode_0417(CRunningScript* thread); // load_and_launch_mission_internal private: diff --git a/source/CleoBase.cpp b/source/CleoBase.cpp index fefc469a..4b31f5ba 100644 --- a/source/CleoBase.cpp +++ b/source/CleoBase.cpp @@ -12,13 +12,13 @@ namespace CLEO Stop(); } - void __declspec(naked) CCleoInstance::OnUpdateGameLogics() + void __cdecl CCleoInstance::OnUpdateGameLogics() { CleoInstance.CallCallbacks(eCallbackId::GameProcess); // execute registered callbacks - static DWORD dwFunc; - dwFunc = (DWORD)(CleoInstance.UpdateGameLogics); - _asm jmp dwFunc + CleoInstance.UpdateGameLogics(); // call original function + + CleoInstance.m_gameState = GameSessionState::InProgress; } HWND CCleoInstance::OnCreateMainWnd(HINSTANCE hinst) @@ -121,7 +121,7 @@ namespace CLEO { if (stage > InitStage::Done) return; // invalid argument - auto nextStage = InitStage(m_initStage + 1); + auto nextStage = InitStage((size_t)m_initStage + 1); if (stage != nextStage) return; if (stage == InitStage::Initial) @@ -183,8 +183,8 @@ namespace CLEO void CCleoInstance::GameBegin() { - if (m_bGameInProgress) return; - m_bGameInProgress = true; + if (m_gameState != GameSessionState::None) return; + m_gameState = GameSessionState::Initial; saveSlot = MenuManager->m_bWantToLoad ? MenuManager->m_nSelectedSaveGame : -1; @@ -197,8 +197,8 @@ namespace CLEO void CCleoInstance::GameEnd() { - if (!m_bGameInProgress) return; - m_bGameInProgress = false; + if (m_gameState == GameSessionState::None) return; + m_gameState = GameSessionState::None; TRACE(""); // separator TRACE("Ending current game"); diff --git a/source/CleoBase.h b/source/CleoBase.h index 4423c548..9fe0ac56 100644 --- a/source/CleoBase.h +++ b/source/CleoBase.h @@ -15,10 +15,17 @@ namespace CLEO { + enum class GameSessionState : size_t + { + None, + Initial, + InProgress + }; + class CCleoInstance { public: - enum InitStage : size_t + enum class InitStage : size_t { None, Initial, @@ -47,6 +54,7 @@ namespace CLEO void GameBegin(); void GameEnd(); + GameSessionState GameState() const { return m_gameState; } bool IsStarted() const { return m_initStage != InitStage::None; } @@ -95,7 +103,7 @@ namespace CLEO private: InitStage m_initStage = InitStage::None; - bool m_bGameInProgress; + GameSessionState m_gameState = GameSessionState::None; std::map> m_callbacks; };