diff options
author | Arisotura <thetotalworm@gmail.com> | 2023-11-02 21:04:09 +0100 |
---|---|---|
committer | Arisotura <thetotalworm@gmail.com> | 2023-11-02 21:04:09 +0100 |
commit | 70c6750561b0c130b430e2ec3d076708b3767674 (patch) | |
tree | f2cc1b0aad735f9be60e5f837ceca120980ca682 /src/NDS.cpp | |
parent | 5ccd3916ff719ea4ed49030077794fadda048cb9 (diff) |
better, less hacky, more OOP-friendly scheduler design
Diffstat (limited to 'src/NDS.cpp')
-rw-r--r-- | src/NDS.cpp | 202 |
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); } |