Skip to content

Commit

Permalink
Core: Add callback when game resets/loads state
Browse files Browse the repository at this point in the history
  • Loading branch information
project64 committed Mar 14, 2022
1 parent d33725b commit d7e732a
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -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>
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -213,4 +223,18 @@ void VideoInterfaceHandler::UpdateHalfLine()
m_HalfLine |= m_FieldSerration;
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();
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class CMipsMemoryVM;
class CPlugins;
class CRegisters;
class CSystemTimer;
class CN64System;

class VideoInterfaceHandler :
public MemoryHandler,
Expand All @@ -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);
Expand All @@ -65,8 +67,14 @@ class VideoInterfaceHandler :
VideoInterfaceHandler(const VideoInterfaceHandler &);
VideoInterfaceHandler & operator=(const VideoInterfaceHandler &);

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;
Expand Down
2 changes: 1 addition & 1 deletion Source/Project64-core/N64System/Mips/MemoryVirtualMem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
66 changes: 66 additions & 0 deletions Source/Project64-core/N64System/N64System.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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");
Expand All @@ -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);
Expand Down
24 changes: 24 additions & 0 deletions Source/Project64-core/N64System/N64System.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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);

Expand All @@ -55,6 +64,9 @@ class CN64System :
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);
Expand Down Expand Up @@ -93,6 +105,14 @@ class CN64System :
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;
Expand All @@ -108,6 +128,8 @@ class CN64System :
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);
Expand All @@ -120,6 +142,7 @@ class CN64System :
bool SetActiveSystem(bool bActive = true);
void InitRegisters(bool bPostPif, CMipsMemoryVM & MMU);
void DisplayRSPListCount();
void NotifyCallback(CN64SystemCB Type);

// CPU methods
void ExecuteRecompiler();
Expand All @@ -134,6 +157,7 @@ class CN64System :
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;
Expand Down

0 comments on commit d7e732a

Please sign in to comment.