aboutsummaryrefslogtreecommitdiff
path: root/src/NDS.cpp
diff options
context:
space:
mode:
authorArisotura <thetotalworm@gmail.com>2023-11-02 21:04:09 +0100
committerArisotura <thetotalworm@gmail.com>2023-11-02 21:04:09 +0100
commit70c6750561b0c130b430e2ec3d076708b3767674 (patch)
treef2cc1b0aad735f9be60e5f837ceca120980ca682 /src/NDS.cpp
parent5ccd3916ff719ea4ed49030077794fadda048cb9 (diff)
better, less hacky, more OOP-friendly scheduler design
Diffstat (limited to 'src/NDS.cpp')
-rw-r--r--src/NDS.cpp202
1 files changed, 64 insertions, 138 deletions
diff --git a/src/NDS.cpp b/src/NDS.cpp
index 832661a..0efd0e9 100644
--- a/src/NDS.cpp
+++ b/src/NDS.cpp
@@ -104,6 +104,14 @@ u64 ARM9Timestamp, ARM9Target;
u64 ARM7Timestamp, ARM7Target;
u64 SysTimestamp;
+struct SchedEvent
+{
+ std::map<u32, EventFunc> Funcs;
+ u64 Timestamp;
+ u32 FuncID;
+ u32 Param;
+};
+
SchedEvent SchedList[Event_MAX];
u32 SchedListMask;
@@ -184,6 +192,9 @@ void SetGBASlotTimings();
bool Init()
{
+ RegisterEventFunc(Event_Div, 0, DivDone);
+ RegisterEventFunc(Event_Sqrt, 0, SqrtDone);
+
ARM9 = new ARMv5();
ARM7 = new ARMv4();
@@ -248,6 +259,9 @@ void DeInit()
DSi::DeInit();
AREngine::DeInit();
+
+ UnregisterEventFunc(Event_Div, 0);
+ UnregisterEventFunc(Event_Sqrt, 0);
}
@@ -608,7 +622,14 @@ void Reset()
for (i = 0; i < 8; i++) DMAs[i]->Reset();
memset(DMA9Fill, 0, 4*4);
- memset(SchedList, 0, sizeof(SchedList));
+ for (i = 0; i < Event_MAX; i++)
+ {
+ SchedEvent& evt = SchedList[i];
+
+ evt.Timestamp = 0;
+ evt.FuncID = 0;
+ evt.Param = 0;
+ }
SchedListMask = 0;
KeyInput = 0x007F03FF;
@@ -699,106 +720,6 @@ void Stop(Platform::StopReason reason)
DSi::Stop();
}
-bool DoSavestate_Scheduler(Savestate* file)
-{
- // this is a bit of a hack
- // but uh, your local coder realized that the scheduler list contains function pointers
- // and that storing those as-is is not a very good idea
- // unless you want it to crash and burn
-
- // this is the solution your local coder came up with.
- // it's gross but I think it's the best solution for this problem.
- // just remember to add here if you add more event callbacks, kay?
- // atleast until we come up with something more elegant.
-
- void (*eventfuncs[])(u32) =
- {
- GPU::StartScanline, GPU::StartHBlank, GPU::FinishFrame,
- SPU::Mix,
- Wifi::USTimer,
- RTC::ClockTimer,
-
- GPU::DisplayFIFO,
- NDSCart::ROMPrepareData, NDSCart::ROMEndTransfer,
- NDSCart::SPITransferDone,
- SPI::TransferDone,
- DivDone,
- SqrtDone,
-
- DSi_SDHost::FinishRX,
- DSi_SDHost::FinishTX,
- DSi_NWifi::MSTimer,
- DSi_CamModule::IRQ,
- DSi_CamModule::TransferScanline,
- DSi_DSP::DSPCatchUpU32,
-
- nullptr
- };
-
- int len = Event_MAX;
- if (file->Saving)
- {
- for (int i = 0; i < len; i++)
- {
- SchedEvent* evt = &SchedList[i];
-
- u32 funcid = 0xFFFFFFFF;
- if (evt->Func)
- {
- for (int j = 0; eventfuncs[j]; j++)
- {
- if (evt->Func == eventfuncs[j])
- {
- funcid = j;
- break;
- }
- }
- if (funcid == 0xFFFFFFFF)
- {
- Log(LogLevel::Error, "savestate: VERY BAD!!!!! FUNCTION POINTER FOR EVENT %d NOT IN HACKY LIST. CANNOT SAVE. SMACK ARISOTURA.\n", i);
- return false;
- }
- }
-
- file->Var32(&funcid);
- file->Var64(&evt->Timestamp);
- file->Var32(&evt->Param);
- }
- }
- else
- {
- for (int i = 0; i < len; i++)
- {
- SchedEvent* evt = &SchedList[i];
-
- u32 funcid;
- file->Var32(&funcid);
-
- if (funcid != 0xFFFFFFFF)
- {
- for (int j = 0; ; j++)
- {
- if (!eventfuncs[j])
- {
- Log(LogLevel::Error, "savestate: VERY BAD!!!!!! EVENT FUNCTION POINTER ID %d IS OUT OF RANGE. HAX?????\n", j);
- return false;
- }
- if (j == funcid) break;
- }
-
- evt->Func = eventfuncs[funcid];
- }
- else
- evt->Func = nullptr;
-
- file->Var64(&evt->Timestamp);
- file->Var32(&evt->Param);
- }
- }
-
- return true;
-}
-
bool DoSavestate(Savestate* file)
{
file->Section("NDSG");
@@ -871,10 +792,13 @@ bool DoSavestate(Savestate* file)
file->VarArray(DMA9Fill, 4*sizeof(u32));
- if (!DoSavestate_Scheduler(file))
+ for (int i = 0; i < Event_MAX; i++)
{
- Platform::Log(Platform::LogLevel::Error, "savestate: failed to %s scheduler state\n", file->Saving ? "save" : "load");
- return false;
+ SchedEvent& evt = SchedList[i];
+
+ file->Var64(&evt.Timestamp);
+ file->Var32(&evt.FuncID);
+ file->Var32(&evt.Param);
}
file->Var32(&SchedListMask);
file->Var64(&ARM9Timestamp);
@@ -1050,10 +974,14 @@ void RunSystem(u64 timestamp)
if (!mask) break;
if (mask & 0x1)
{
- if (SchedList[i].Timestamp <= SysTimestamp)
+ SchedEvent& evt = SchedList[i];
+
+ if (evt.Timestamp <= SysTimestamp)
{
SchedListMask &= ~(1<<i);
- SchedList[i].Func(SchedList[i].Param);
+
+ EventFunc func = evt.Funcs[evt.FuncID];
+ func(evt.Param);
}
}
@@ -1097,7 +1025,9 @@ void RunSystemSleep(u64 timestamp)
{
if (mask & 0x1)
{
- if (SchedList[i].Timestamp <= SysTimestamp)
+ SchedEvent& evt = SchedList[i];
+
+ if (evt.Timestamp <= SysTimestamp)
{
SchedListMask &= ~(1<<i);
@@ -1105,9 +1035,10 @@ void RunSystemSleep(u64 timestamp)
if (i == Event_SPU)
param = 1;
else
- param = SchedList[i].Param;
+ param = evt.Param;
- SchedList[i].Func(param);
+ EventFunc func = evt.Funcs[evt.FuncID];
+ func(param);
}
}
}
@@ -1298,7 +1229,21 @@ void Reschedule(u64 target)
}
}
-void ScheduleEvent(u32 id, bool periodic, s32 delay, void (*func)(u32), u32 param)
+void RegisterEventFunc(u32 id, u32 funcid, EventFunc func)
+{
+ SchedEvent& evt = SchedList[id];
+
+ evt.Funcs[funcid] = func;
+}
+
+void UnregisterEventFunc(u32 id, u32 funcid)
+{
+ SchedEvent& evt = SchedList[id];
+
+ evt.Funcs.erase(funcid);
+}
+
+void ScheduleEvent(u32 id, bool periodic, s32 delay, u32 funcid, u32 param)
{
if (SchedListMask & (1<<id))
{
@@ -1306,43 +1251,24 @@ void ScheduleEvent(u32 id, bool periodic, s32 delay, void (*func)(u32), u32 para
return;
}
- SchedEvent* evt = &SchedList[id];
+ SchedEvent& evt = SchedList[id];
if (periodic)
- evt->Timestamp += delay;
+ evt.Timestamp += delay;
else
{
if (CurCPU == 0)
- evt->Timestamp = (ARM9Timestamp >> ARM9ClockShift) + delay;
+ evt.Timestamp = (ARM9Timestamp >> ARM9ClockShift) + delay;
else
- evt->Timestamp = ARM7Timestamp + delay;
- }
-
- evt->Func = func;
- evt->Param = param;
-
- SchedListMask |= (1<<id);
-
- Reschedule(evt->Timestamp);
-}
-
-void ScheduleEvent(u32 id, u64 timestamp, void (*func)(u32), u32 param)
-{
- if (SchedListMask & (1<<id))
- {
- Log(LogLevel::Debug, "!! EVENT %d ALREADY SCHEDULED\n", id);
- return;
+ evt.Timestamp = ARM7Timestamp + delay;
}
- SchedEvent* evt = &SchedList[id];
-
- evt->Timestamp = timestamp;
- evt->Func = func;
- evt->Param = param;
+ evt.FuncID = funcid;
+ evt.Param = param;
SchedListMask |= (1<<id);
- Reschedule(evt->Timestamp);
+ Reschedule(evt.Timestamp);
}
void CancelEvent(u32 id)
@@ -2096,7 +2022,7 @@ void StartDiv()
{
NDS::CancelEvent(NDS::Event_Div);
DivCnt |= 0x8000;
- NDS::ScheduleEvent(NDS::Event_Div, false, ((DivCnt&0x3)==0) ? 18:34, DivDone, 0);
+ NDS::ScheduleEvent(NDS::Event_Div, false, ((DivCnt&0x3)==0) ? 18:34, 0, 0);
}
// http://stackoverflow.com/questions/1100090/looking-for-an-efficient-integer-square-root-algorithm-for-arm-thumb2
@@ -2144,7 +2070,7 @@ void StartSqrt()
{
NDS::CancelEvent(NDS::Event_Sqrt);
SqrtCnt |= 0x8000;
- NDS::ScheduleEvent(NDS::Event_Sqrt, false, 13, SqrtDone, 0);
+ NDS::ScheduleEvent(NDS::Event_Sqrt, false, 13, 0, 0);
}