From d7e732a7eb1454dac300698080aecef73ab675c0 Mon Sep 17 00:00:00 2001 From: zilmar Date: Mon, 14 Mar 2022 21:07:06 +1030 Subject: [PATCH] Core: Add callback when game resets/loads state --- .../MemoryHandler/VideoInterfaceHandler.cpp | 34 ++++++++-- .../MemoryHandler/VideoInterfaceHandler.h | 12 +++- .../N64System/Mips/MemoryVirtualMem.cpp | 2 +- Source/Project64-core/N64System/N64System.cpp | 66 +++++++++++++++++++ Source/Project64-core/N64System/N64System.h | 24 +++++++ 5 files changed, 130 insertions(+), 8 deletions(-) diff --git a/Source/Project64-core/N64System/MemoryHandler/VideoInterfaceHandler.cpp b/Source/Project64-core/N64System/MemoryHandler/VideoInterfaceHandler.cpp index 6667c9c38..dfd5db588 100644 --- a/Source/Project64-core/N64System/MemoryHandler/VideoInterfaceHandler.cpp +++ b/Source/Project64-core/N64System/MemoryHandler/VideoInterfaceHandler.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "VideoInterfaceHandler.h" +#include #include #include #include @@ -33,18 +34,27 @@ VideoInterfaceReg::VideoInterfaceReg(uint32_t * VideoInterface) : { } -VideoInterfaceHandler::VideoInterfaceHandler(CMipsMemoryVM & MMU, CPlugins * Plugins, CRegisters & Reg, CSystemTimer & SystemTimer, int32_t & NextTimer) : +VideoInterfaceHandler::VideoInterfaceHandler(CN64System & System, CMipsMemoryVM & MMU, CRegisters & Reg) : VideoInterfaceReg(Reg.m_Video_Interface), + m_System(System), m_MMU(MMU), - m_Plugins(Plugins), + m_Plugins(System.GetPlugins()), m_Reg(Reg), - m_SystemTimer(SystemTimer), - m_NextTimer(NextTimer), + m_SystemTimer(System.m_SystemTimer), + m_NextTimer(System.m_NextTimer), m_PC(Reg.m_PROGRAM_COUNTER), m_FieldSerration(0), m_HalfLine(0), m_HalfLineCheck(false) { + System.RegisterCallBack(CN64SystemCB_Reset, this, (CN64System::CallBackFunction)stSystemReset); + System.RegisterCallBack(CN64SystemCB_LoadedGameState, this, (CN64System::CallBackFunction)stLoadedGameState); +} + +VideoInterfaceHandler::~VideoInterfaceHandler() +{ + m_System.UnregisterCallBack(CN64SystemCB_Reset, this, (CN64System::CallBackFunction)stSystemReset); + m_System.UnregisterCallBack(CN64SystemCB_LoadedGameState, this, (CN64System::CallBackFunction)stLoadedGameState); } bool VideoInterfaceHandler::Read32(uint32_t Address, uint32_t & Value) @@ -213,4 +223,18 @@ void VideoInterfaceHandler::UpdateHalfLine() m_HalfLine |= m_FieldSerration; VI_V_CURRENT_LINE_REG = m_HalfLine; m_HalfLineCheck = NextViTimer; -} \ No newline at end of file +} + +void VideoInterfaceHandler::LoadedGameState(void) +{ + SystemReset(); +} + +void VideoInterfaceHandler::SystemReset(void) +{ + m_FieldSerration = 0; + m_HalfLine = 0; + m_HalfLineCheck = false; + UpdateFieldSerration((VI_STATUS_REG & 0x40) != 0); + UpdateHalfLine(); +} diff --git a/Source/Project64-core/N64System/MemoryHandler/VideoInterfaceHandler.h b/Source/Project64-core/N64System/MemoryHandler/VideoInterfaceHandler.h index 75609ecba..3823e5a2b 100644 --- a/Source/Project64-core/N64System/MemoryHandler/VideoInterfaceHandler.h +++ b/Source/Project64-core/N64System/MemoryHandler/VideoInterfaceHandler.h @@ -45,6 +45,7 @@ class CMipsMemoryVM; class CPlugins; class CRegisters; class CSystemTimer; +class CN64System; class VideoInterfaceHandler : public MemoryHandler, @@ -54,7 +55,8 @@ class VideoInterfaceHandler : private CLogging { public: - VideoInterfaceHandler(CMipsMemoryVM & MMU, CPlugins * Plugins, CRegisters & Reg, CSystemTimer & SystemTimer, int32_t & NextTimer); + VideoInterfaceHandler(CN64System & System, CMipsMemoryVM & MMU, CRegisters & Reg); + ~VideoInterfaceHandler(); void UpdateFieldSerration(uint32_t interlaced); bool Read32(uint32_t Address, uint32_t & Value); @@ -65,8 +67,14 @@ private: VideoInterfaceHandler(const VideoInterfaceHandler &); VideoInterfaceHandler & operator=(const VideoInterfaceHandler &); - void UpdateHalfLine(); + static void stSystemReset(VideoInterfaceHandler * _this) { _this->SystemReset(); } + static void stLoadedGameState(VideoInterfaceHandler * _this) { _this->LoadedGameState(); } + void UpdateHalfLine(); + void LoadedGameState(void); + void SystemReset(void); + + CN64System & m_System; uint32_t m_FieldSerration; uint32_t m_HalfLine; uint32_t m_HalfLineCheck; diff --git a/Source/Project64-core/N64System/Mips/MemoryVirtualMem.cpp b/Source/Project64-core/N64System/Mips/MemoryVirtualMem.cpp index 9a055e25e..010d7c114 100755 --- a/Source/Project64-core/N64System/Mips/MemoryVirtualMem.cpp +++ b/Source/Project64-core/N64System/Mips/MemoryVirtualMem.cpp @@ -34,7 +34,7 @@ CMipsMemoryVM::CMipsMemoryVM(CN64System & System, CRegisters & Reg, bool SavesRe m_PeripheralInterfaceHandler(*this, Reg), m_RDRAMInterfaceHandler(Reg), m_SPRegistersHandler(System, *this, Reg), - m_VideoInterfaceHandler(*this, System.GetPlugins(), Reg, System.m_SystemTimer, System.m_NextTimer), + m_VideoInterfaceHandler(System, *this, Reg), m_Rom(nullptr), m_RomSize(0), m_RomWrittenTo(false), diff --git a/Source/Project64-core/N64System/N64System.cpp b/Source/Project64-core/N64System/N64System.cpp index 4ecaaca47..a8897c8f9 100644 --- a/Source/Project64-core/N64System/N64System.cpp +++ b/Source/Project64-core/N64System/N64System.cpp @@ -152,6 +152,56 @@ CN64System::~CN64System() } } +void CN64System::RegisterCallBack(CN64SystemCB Type, void * Data, CallBackFunction Func) +{ + SETTING_CHANGED_CB Item; + Item.Data = Data; + Item.Func = Func; + + SETTING_CALLBACK::iterator Callback = m_Callback.find(Type); + if (Callback != m_Callback.end()) + { + SETTING_CHANGED_CB_LIST & List = Callback->second; + bool found = false; + for (SETTING_CHANGED_CB_LIST::const_iterator itr = List.begin(); itr != List.end(); itr++) + { + if (itr->Data == Data && itr->Func == Func) + { + found = true; + break; + } + } + if (!found) + { + Callback->second.push_back(Item); + } + } + else + { + SETTING_CHANGED_CB_LIST List; + List.push_back(Item); + m_Callback.insert(SETTING_CALLBACK::value_type(Type, List)); + } +} + +void CN64System::UnregisterCallBack(CN64SystemCB Type, void * Data, CallBackFunction Func) +{ + SETTING_CALLBACK::iterator Callback = m_Callback.find(Type); + if (Callback != m_Callback.end()) + { + SETTING_CHANGED_CB_LIST & List = Callback->second; + bool found = false; + for (SETTING_CHANGED_CB_LIST::const_iterator itr = List.begin(); itr != List.end(); itr++) + { + if (itr->Data == Data && itr->Func == Func) + { + List.erase(itr); + return; + } + } + } +} + void CN64System::ExternalEvent(SystemEvent action) { WriteTrace(TraceN64System, TraceDebug, "Action: %s", SystemEventName(action)); @@ -898,6 +948,7 @@ void CN64System::Reset(bool bInitReg, bool ClearMenory) { m_SyncCPU->Reset(bInitReg, ClearMenory); } + NotifyCallback(CN64SystemCB_Reset); g_Settings->SaveBool(GameRunning_InReset, false); WriteTrace(TraceN64System, TraceDebug, "Done"); @@ -1184,6 +1235,7 @@ void CN64System::ExecuteCPU() g_Notify->DisplayMessage(2, MSG_EMULATION_STARTED); m_EndEmulation = false; + NotifyCallback(CN64SystemCB_LoadedGameState); m_Plugins->RomOpened(); if (m_SyncCPU) @@ -2253,6 +2305,7 @@ bool CN64System::LoadState(const char * FileName) SyncCPU(m_SyncCPU); } } + NotifyCallback(CN64SystemCB_LoadedGameState); std::string LoadMsg = g_Lang->GetString(MSG_LOADED_STATE); g_Notify->DisplayMessage(3, stdstr_f("%s %s", LoadMsg.c_str(), stdstr(SaveFile.GetNameExtension()).c_str()).c_str()); WriteTrace(TraceN64System, TraceDebug, "Done"); @@ -2277,6 +2330,19 @@ void CN64System::DisplayRSPListCount() g_Notify->DisplayMessage(0, stdstr_f("Dlist: %d Alist: %d Unknown: %d", m_DlistCount, m_AlistCount, m_UnknownCount).c_str()); } +void CN64System::NotifyCallback(CN64SystemCB Type) +{ + SETTING_CALLBACK::iterator Callback = m_Callback.find(Type); + if (Callback != m_Callback.end()) + { + SETTING_CHANGED_CB_LIST & List = Callback->second; + for (SETTING_CHANGED_CB_LIST::const_iterator itr = List.begin(); itr != List.end(); itr++) + { + itr->Func(itr->Data); + } + } +} + void CN64System::RunRSP() { WriteTrace(TraceRSP, TraceDebug, "Start (SP Status %X)", m_Reg.SP_STATUS_REG); diff --git a/Source/Project64-core/N64System/N64System.h b/Source/Project64-core/N64System/N64System.h index f91bb5f0e..7c6afa174 100644 --- a/Source/Project64-core/N64System/N64System.h +++ b/Source/Project64-core/N64System/N64System.h @@ -27,7 +27,14 @@ class CPlugins; class CRSP_Plugin; class CRecompiler; +class VideoInterfaceHandler; + //#define TEST_SP_TRACKING // Track the SP to make sure all ops pick it up fine +enum CN64SystemCB +{ + CN64SystemCB_Reset, + CN64SystemCB_LoadedGameState, +}; class CN64System : public CLogging, @@ -38,6 +45,8 @@ class CN64System : protected CDebugSettings { public: + typedef void(*CallBackFunction)(void *); + CN64System(CPlugins * Plugins, uint32_t randomizer_seed, bool SavesReadOnly, bool SyncSystem); virtual ~CN64System(void); @@ -55,6 +64,9 @@ public: static void RunLoadedImage(void); static void CloseSystem(void); + void RegisterCallBack(CN64SystemCB Type, void * Data, CallBackFunction Func); + void UnregisterCallBack(CN64SystemCB Type, void * Data, CallBackFunction Func); + void CloseCpu(); void ExternalEvent(SystemEvent action); // Covers GUI interactions and timers etc. void StartEmulation(bool NewThread); @@ -93,6 +105,14 @@ public: uint32_t JumpToLocation() const { return m_JumpToLocation; } private: + struct SETTING_CHANGED_CB + { + void * Data; + CallBackFunction Func; + }; + typedef std::vector SETTING_CHANGED_CB_LIST; + typedef std::map SETTING_CALLBACK; + // Make sure plugins can directly access this information friend class CGfxPlugin; friend class CAudioPlugin; @@ -108,6 +128,8 @@ private: friend class R4300iOp32; friend class R4300iOp; + friend class VideoInterfaceHandler; + // Used for loading and potentially executing the CPU in its own thread static void StartEmulationThread(CThread * thread); static bool EmulationStarting(CThread * thread); @@ -120,6 +142,7 @@ private: bool SetActiveSystem(bool bActive = true); void InitRegisters(bool bPostPif, CMipsMemoryVM & MMU); void DisplayRSPListCount(); + void NotifyCallback(CN64SystemCB Type); // CPU methods void ExecuteRecompiler(); @@ -134,6 +157,7 @@ private: void TLB_Unmaped(uint32_t VAddr, uint32_t Len); void TLB_Changed(); + SETTING_CALLBACK m_Callback; CPlugins * const m_Plugins; // The plugin container CPlugins * m_SyncPlugins; CN64System * m_SyncCPU;