Core: Add callback when game resets/loads state

This commit is contained in:
zilmar 2022-03-14 21:07:06 +10:30
parent d33725bda5
commit d7e732a7eb
5 changed files with 130 additions and 8 deletions

View File

@ -1,5 +1,6 @@
#include "stdafx.h"
#include "VideoInterfaceHandler.h"
#include <Project64-core\N64System\N64System.h>
#include <Project64-core\N64System\Mips\MemoryVirtualMem.h>
#include <Project64-core\N64System\Mips\SystemTiming.h>
#include <Project64-core\N64System\Mips\Register.h>
@ -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)
@ -214,3 +224,17 @@ void VideoInterfaceHandler::UpdateHalfLine()
VI_V_CURRENT_LINE_REG = m_HalfLine;
m_HalfLineCheck = NextViTimer;
}
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();
}

View File

@ -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;

View File

@ -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),

View File

@ -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);

View File

@ -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> SETTING_CHANGED_CB_LIST;
typedef std::map<CN64SystemCB, SETTING_CHANGED_CB_LIST> 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;