aboutsummaryrefslogtreecommitdiff
path: root/src
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
parent5ccd3916ff719ea4ed49030077794fadda048cb9 (diff)
better, less hacky, more OOP-friendly scheduler design
Diffstat (limited to 'src')
-rw-r--r--src/DSi_Camera.cpp16
-rw-r--r--src/DSi_DSP.cpp6
-rw-r--r--src/DSi_NWifi.cpp58
-rw-r--r--src/DSi_NWifi.h4
-rw-r--r--src/DSi_SD.cpp42
-rw-r--r--src/DSi_SD.h4
-rw-r--r--src/GPU.cpp27
-rw-r--r--src/NDS.cpp202
-rw-r--r--src/NDS.h14
-rw-r--r--src/NDSCart.cpp22
-rw-r--r--src/RTC.cpp5
-rw-r--r--src/SPI.cpp6
-rw-r--r--src/SPU.cpp8
-rw-r--r--src/Wifi.cpp6
14 files changed, 202 insertions, 218 deletions
diff --git a/src/DSi_Camera.cpp b/src/DSi_Camera.cpp
index 80e578f..2471f8c 100644
--- a/src/DSi_Camera.cpp
+++ b/src/DSi_Camera.cpp
@@ -53,6 +53,9 @@ const u32 kTransferStart = 60000;
bool Init()
{
+ NDS::RegisterEventFunc(NDS::Event_DSi_CamIRQ, 0, IRQ);
+ NDS::RegisterEventFunc(NDS::Event_DSi_CamTransfer, 0, TransferScanline);
+
Camera0 = new Camera(0);
Camera1 = new Camera(1);
@@ -66,6 +69,9 @@ void DeInit()
Camera0 = nullptr;
Camera1 = nullptr;
+
+ NDS::UnregisterEventFunc(NDS::Event_DSi_CamIRQ, 0);
+ NDS::UnregisterEventFunc(NDS::Event_DSi_CamTransfer, 0);
}
void Reset()
@@ -85,7 +91,7 @@ void Reset()
BufferNumLines = 0;
CurCamera = nullptr;
- NDS::ScheduleEvent(NDS::Event_DSi_CamIRQ, false, kIRQInterval, IRQ, 0);
+ NDS::ScheduleEvent(NDS::Event_DSi_CamIRQ, false, kIRQInterval, 0, 0);
}
void Stop()
@@ -132,11 +138,11 @@ void IRQ(u32 param)
BufferWritePos = 0;
BufferNumLines = 0;
CurCamera = activecam;
- NDS::ScheduleEvent(NDS::Event_DSi_CamTransfer, false, kTransferStart, TransferScanline, 0);
+ NDS::ScheduleEvent(NDS::Event_DSi_CamTransfer, false, kTransferStart, 0, 0);
}
}
- NDS::ScheduleEvent(NDS::Event_DSi_CamIRQ, true, kIRQInterval, IRQ, 0);
+ NDS::ScheduleEvent(NDS::Event_DSi_CamIRQ, true, kIRQInterval, 0, 0);
}
void TransferScanline(u32 line)
@@ -162,7 +168,7 @@ void TransferScanline(u32 line)
if (line < ystart || line > yend)
{
if (!CurCamera->TransferDone())
- NDS::ScheduleEvent(NDS::Event_DSi_CamTransfer, false, delay, TransferScanline, line+1);
+ NDS::ScheduleEvent(NDS::Event_DSi_CamTransfer, false, delay, 0, line+1);
return;
}
@@ -242,7 +248,7 @@ void TransferScanline(u32 line)
if (CurCamera->TransferDone())
return;
- NDS::ScheduleEvent(NDS::Event_DSi_CamTransfer, false, delay, TransferScanline, line+1);
+ NDS::ScheduleEvent(NDS::Event_DSi_CamTransfer, false, delay, 0, line+1);
}
diff --git a/src/DSi_DSP.cpp b/src/DSi_DSP.cpp
index eaa80f9..d474763 100644
--- a/src/DSi_DSP.cpp
+++ b/src/DSi_DSP.cpp
@@ -129,6 +129,8 @@ void AudioCb(std::array<s16, 2> frame)
bool Init()
{
+ NDS::RegisterEventFunc(NDS::Event_DSi_DSP, 0, DSPCatchUpU32);
+
TeakraCore = new Teakra::Teakra();
SCFG_RST = false;
@@ -171,6 +173,8 @@ void DeInit()
//PDATAReadFifo = NULL;
//PDATAWriteFifo = NULL;
TeakraCore = NULL;
+
+ NDS::UnregisterEventFunc(NDS::Event_DSi_DSP, 0);
}
void Reset()
@@ -579,7 +583,7 @@ void Run(u32 cycles)
NDS::CancelEvent(NDS::Event_DSi_DSP);
NDS::ScheduleEvent(NDS::Event_DSi_DSP, false,
- 16384/*from citra (TeakraSlice)*/, DSPCatchUpU32, 0);
+ 16384/*from citra (TeakraSlice)*/, 0, 0);
}
void DoSavestate(Savestate* file)
diff --git a/src/DSi_NWifi.cpp b/src/DSi_NWifi.cpp
index 132936a..558cd6f 100644
--- a/src/DSi_NWifi.cpp
+++ b/src/DSi_NWifi.cpp
@@ -116,9 +116,6 @@ const u8 CIS1[256] =
};
-DSi_NWifi* Ctx = nullptr;
-
-
DSi_NWifi::DSi_NWifi(DSi_SDHost* host)
: DSi_SDDevice(host),
Mailbox
@@ -133,16 +130,17 @@ DSi_NWifi::DSi_NWifi(DSi_SDHost* host)
DynamicFIFO<u8>(0x8000)
}
{
+ NDS::RegisterEventFunc(NDS::Event_DSi_NWifi, 0, MemberEventFunc(DSi_NWifi, MSTimer));
+
// this seems to control whether the firmware upload is done
EEPROMReady = 0;
-
- Ctx = this;
}
DSi_NWifi::~DSi_NWifi()
{
NDS::CancelEvent(NDS::Event_DSi_NWifi);
- Ctx = nullptr;
+
+ NDS::UnregisterEventFunc(NDS::Event_DSi_NWifi, 0);
}
void DSi_NWifi::Reset()
@@ -908,7 +906,7 @@ void DSi_NWifi::HTC_Command()
SendWMIEvent(1, 0x1006, regdomain_evt, 4);
BootPhase = 2;
- NDS::ScheduleEvent(NDS::Event_DSi_NWifi, false, 33611, MSTimer, 0);
+ NDS::ScheduleEvent(NDS::Event_DSi_NWifi, false, 33611, 0, 0);
}
break;
@@ -1549,7 +1547,26 @@ void DSi_NWifi::WindowWrite(u32 addr, u32 val)
}
-void DSi_NWifi::_MSTimer()
+void DSi_NWifi::DrainRXBuffer()
+{
+ while (Mailbox[8].Level() >= 6)
+ {
+ u16 len = Mailbox[8].Peek(2) | (Mailbox[8].Peek(3) << 8);
+ u32 totallen = len + 6;
+ u32 required = (totallen + 0x7F) & ~0x7F;
+
+ if (!Mailbox[4].CanFit(required))
+ break;
+
+ u32 i = 0;
+ for (; i < totallen; i++) Mailbox[4].Write(Mailbox[8].Read());
+ for (; i < required; i++) Mailbox[4].Write(0);
+ }
+
+ UpdateIRQ_F1();
+}
+
+void DSi_NWifi::MSTimer(u32 param)
{
BeaconTimer++;
@@ -1587,29 +1604,6 @@ void DSi_NWifi::_MSTimer()
//if (Mailbox[4].IsEmpty())
CheckRX();
}
-}
-
-void DSi_NWifi::DrainRXBuffer()
-{
- while (Mailbox[8].Level() >= 6)
- {
- u16 len = Mailbox[8].Peek(2) | (Mailbox[8].Peek(3) << 8);
- u32 totallen = len + 6;
- u32 required = (totallen + 0x7F) & ~0x7F;
- if (!Mailbox[4].CanFit(required))
- break;
-
- u32 i = 0;
- for (; i < totallen; i++) Mailbox[4].Write(Mailbox[8].Read());
- for (; i < required; i++) Mailbox[4].Write(0);
- }
-
- UpdateIRQ_F1();
-}
-
-void DSi_NWifi::MSTimer(u32 param)
-{
- Ctx->_MSTimer();
- NDS::ScheduleEvent(NDS::Event_DSi_NWifi, true, 33611, MSTimer, 0);
+ NDS::ScheduleEvent(NDS::Event_DSi_NWifi, true, 33611, 0, 0);
}
diff --git a/src/DSi_NWifi.h b/src/DSi_NWifi.h
index ffd5647..a758e96 100644
--- a/src/DSi_NWifi.h
+++ b/src/DSi_NWifi.h
@@ -40,9 +40,7 @@ public:
void SetIRQ_F1_Counter(u32 n);
- void _MSTimer();
-
- static void MSTimer(u32 param);
+ void MSTimer(u32 param);
private:
u32 TransferCmd;
diff --git a/src/DSi_SD.cpp b/src/DSi_SD.cpp
index 158ae1e..5587034 100644
--- a/src/DSi_SD.cpp
+++ b/src/DSi_SD.cpp
@@ -48,11 +48,22 @@ using namespace Platform;
#define SD_DESC Num?"SDIO":"SD/MMC"
+enum
+{
+ Transfer_TX = 0,
+ Transfer_RX,
+};
+
DSi_SDHost::DSi_SDHost(u32 num)
{
Num = num;
+ NDS::RegisterEventFunc(Num ? NDS::Event_DSi_SDIOTransfer : NDS::Event_DSi_SDMMCTransfer,
+ Transfer_TX, MemberEventFunc(DSi_SDHost, FinishTX));
+ NDS::RegisterEventFunc(Num ? NDS::Event_DSi_SDIOTransfer : NDS::Event_DSi_SDMMCTransfer,
+ Transfer_RX, MemberEventFunc(DSi_SDHost, FinishRX));
+
Ports[0] = nullptr;
Ports[1] = nullptr;
}
@@ -61,6 +72,11 @@ DSi_SDHost::~DSi_SDHost()
{
if (Ports[0]) delete Ports[0];
if (Ports[1]) delete Ports[1];
+
+ NDS::UnregisterEventFunc(Num ? NDS::Event_DSi_SDIOTransfer : NDS::Event_DSi_SDMMCTransfer,
+ Transfer_TX);
+ NDS::UnregisterEventFunc(Num ? NDS::Event_DSi_SDIOTransfer : NDS::Event_DSi_SDMMCTransfer,
+ Transfer_RX);
}
void DSi_SDHost::CloseHandles()
@@ -281,14 +297,12 @@ void DSi_SDHost::SendResponse(u32 val, bool last)
void DSi_SDHost::FinishRX(u32 param)
{
- DSi_SDHost* host = (param & 0x1) ? DSi::SDIO : DSi::SDMMC;
-
- host->CheckSwapFIFO();
+ CheckSwapFIFO();
- if (host->DataMode == 1)
- host->UpdateFIFO32();
+ if (DataMode == 1)
+ UpdateFIFO32();
else
- host->SetIRQ(24);
+ SetIRQ(24);
}
u32 DSi_SDHost::DataRX(u8* data, u32 len)
@@ -308,21 +322,19 @@ u32 DSi_SDHost::DataRX(u8* data, u32 len)
// we need a delay because DSi boot2 will send a command and then wait for IRQ0
// but if IRQ24 is thrown instantly, the handler clears IRQ0 before the
// send-command function starts polling IRQ status
- u32 param = Num | (last << 1);
NDS::ScheduleEvent(Num ? NDS::Event_DSi_SDIOTransfer : NDS::Event_DSi_SDMMCTransfer,
- false, 512, FinishRX, param);
+ false, 512, Transfer_RX, 0);
return len;
}
void DSi_SDHost::FinishTX(u32 param)
{
- DSi_SDHost* host = (param & 0x1) ? DSi::SDIO : DSi::SDMMC;
- DSi_SDDevice* dev = host->Ports[host->PortSelect & 0x1];
+ DSi_SDDevice* dev = Ports[PortSelect & 0x1];
- if (host->BlockCountInternal == 0)
+ if (BlockCountInternal == 0)
{
- if (host->StopAction & (1<<8))
+ if (StopAction & (1<<8))
{
if (dev) dev->SendCMD(12, 0);
}
@@ -330,8 +342,8 @@ void DSi_SDHost::FinishTX(u32 param)
// CHECKME: presumably IRQ2 should not trigger here, but rather
// when the data transfer is done
//SetIRQ(0);
- host->SetIRQ(2);
- host->TXReq = false;
+ SetIRQ(2);
+ TXReq = false;
}
else
{
@@ -392,7 +404,7 @@ u32 DSi_SDHost::DataTX(u8* data, u32 len)
BlockCountInternal--;
NDS::ScheduleEvent(Num ? NDS::Event_DSi_SDIOTransfer : NDS::Event_DSi_SDMMCTransfer,
- false, 512, FinishTX, Num);
+ false, 512, Transfer_TX, 0);
return len;
}
diff --git a/src/DSi_SD.h b/src/DSi_SD.h
index 8e53a77..577572c 100644
--- a/src/DSi_SD.h
+++ b/src/DSi_SD.h
@@ -43,8 +43,8 @@ public:
void DoSavestate(Savestate* file);
- static void FinishRX(u32 param);
- static void FinishTX(u32 param);
+ void FinishRX(u32 param);
+ void FinishTX(u32 param);
void SendResponse(u32 val, bool last);
u32 DataRX(u8* data, u32 len);
u32 DataTX(u8* data, u32 len);
diff --git a/src/GPU.cpp b/src/GPU.cpp
index 630e88d..0cbc599 100644
--- a/src/GPU.cpp
+++ b/src/GPU.cpp
@@ -36,6 +36,13 @@ namespace GPU
#define HBLANK_CYCLES (48+(256*6))
#define FRAME_CYCLES (LINE_CYCLES * 263)
+enum
+{
+ LCD_StartHBlank = 0,
+ LCD_StartScanline,
+ LCD_FinishFrame,
+};
+
u16 VCount;
u32 NextVCount;
u16 TotalScanlines;
@@ -151,6 +158,11 @@ std::unique_ptr<GLCompositor> CurGLCompositor = {};
bool Init()
{
+ NDS::RegisterEventFunc(NDS::Event_LCD, LCD_StartHBlank, StartHBlank);
+ NDS::RegisterEventFunc(NDS::Event_LCD, LCD_StartScanline, StartScanline);
+ NDS::RegisterEventFunc(NDS::Event_LCD, LCD_FinishFrame, FinishFrame);
+ NDS::RegisterEventFunc(NDS::Event_DisplayFIFO, 0, DisplayFIFO);
+
GPU2D_Renderer = std::make_unique<GPU2D::SoftRenderer>();
if (!GPU3D::Init()) return false;
@@ -180,6 +192,11 @@ void DeInit()
#ifdef OGLRENDERER_ENABLED
CurGLCompositor = nullptr;
#endif
+
+ NDS::UnregisterEventFunc(NDS::Event_LCD, LCD_StartHBlank);
+ NDS::UnregisterEventFunc(NDS::Event_LCD, LCD_StartScanline);
+ NDS::UnregisterEventFunc(NDS::Event_LCD, LCD_FinishFrame);
+ NDS::UnregisterEventFunc(NDS::Event_DisplayFIFO, 0);
}
void ResetVRAMCache()
@@ -1022,7 +1039,7 @@ void DisplayFIFO(u32 x)
{
// transfer the next 8 pixels
NDS::CheckDMAs(0, 0x04);
- NDS::ScheduleEvent(NDS::Event_DisplayFIFO, true, 6*8, DisplayFIFO, x+8);
+ NDS::ScheduleEvent(NDS::Event_DisplayFIFO, true, 6*8, 0, x+8);
}
else
GPU2D_A.SampleFIFO(253, 3); // sample the remaining pixels
@@ -1077,9 +1094,9 @@ void StartHBlank(u32 line)
if (DispStat[1] & (1<<4)) NDS::SetIRQ(1, NDS::IRQ_HBlank);
if (VCount < 262)
- NDS::ScheduleEvent(NDS::Event_LCD, true, (LINE_CYCLES - HBLANK_CYCLES), StartScanline, line+1);
+ NDS::ScheduleEvent(NDS::Event_LCD, true, (LINE_CYCLES - HBLANK_CYCLES), LCD_StartScanline, line+1);
else
- NDS::ScheduleEvent(NDS::Event_LCD, true, (LINE_CYCLES - HBLANK_CYCLES), FinishFrame, line+1);
+ NDS::ScheduleEvent(NDS::Event_LCD, true, (LINE_CYCLES - HBLANK_CYCLES), LCD_FinishFrame, line+1);
}
void FinishFrame(u32 lines)
@@ -1164,7 +1181,7 @@ void StartScanline(u32 line)
}
if (RunFIFO)
- NDS::ScheduleEvent(NDS::Event_DisplayFIFO, false, 32, DisplayFIFO, 0);
+ NDS::ScheduleEvent(NDS::Event_DisplayFIFO, false, 32, 0, 0);
}
if (VCount == 262)
@@ -1210,7 +1227,7 @@ void StartScanline(u32 line)
}
}
- NDS::ScheduleEvent(NDS::Event_LCD, true, HBLANK_CYCLES, StartHBlank, line);
+ NDS::ScheduleEvent(NDS::Event_LCD, true, HBLANK_CYCLES, LCD_StartHBlank, line);
}
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);
}
diff --git a/src/NDS.h b/src/NDS.h
index de038b2..89ebb1c 100644
--- a/src/NDS.h
+++ b/src/NDS.h
@@ -20,6 +20,7 @@
#define NDS_H
#include <string>
+#include <functional>
#include "Platform.h"
#include "Savestate.h"
@@ -57,12 +58,8 @@ enum
Event_MAX
};
-struct SchedEvent
-{
- void (*Func)(u32 param);
- u64 Timestamp;
- u32 Param;
-};
+typedef std::function<void(u32)> EventFunc;
+#define MemberEventFunc(cls,func) std::bind(&cls::func,this,std::placeholders::_1)
enum
{
@@ -297,8 +294,9 @@ void SetLidClosed(bool closed);
void CamInputFrame(int cam, u32* data, int width, int height, bool rgb);
void MicInputFrame(s16* data, int samples);
-void ScheduleEvent(u32 id, bool periodic, s32 delay, void (*func)(u32), u32 param);
-void ScheduleEvent(u32 id, u64 timestamp, void (*func)(u32), u32 param);
+void RegisterEventFunc(u32 id, u32 funcid, EventFunc func);
+void UnregisterEventFunc(u32 id, u32 funcid);
+void ScheduleEvent(u32 id, bool periodic, s32 delay, u32 funcid, u32 param);
void CancelEvent(u32 id);
void debug(u32 p);
diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp
index 400f7d6..33d7795 100644
--- a/src/NDSCart.cpp
+++ b/src/NDSCart.cpp
@@ -34,6 +34,12 @@ using Platform::LogLevel;
namespace NDSCart
{
+enum
+{
+ ROMTransfer_PrepareData = 0,
+ ROMTransfer_End
+};
+
// SRAM TODO: emulate write delays???
u16 SPICnt;
@@ -1468,6 +1474,10 @@ void CartHomebrew::ReadROM_B7(u32 addr, u32 len, u8* data, u32 offset)
bool Init()
{
+ NDS::RegisterEventFunc(NDS::Event_ROMTransfer, ROMTransfer_PrepareData, ROMPrepareData);
+ NDS::RegisterEventFunc(NDS::Event_ROMTransfer, ROMTransfer_End, ROMEndTransfer);
+ NDS::RegisterEventFunc(NDS::Event_ROMSPITransfer, 0, SPITransferDone);
+
Cart = nullptr;
return true;
@@ -1476,6 +1486,10 @@ bool Init()
void DeInit()
{
Cart = nullptr;
+
+ NDS::UnregisterEventFunc(NDS::Event_ROMTransfer, ROMTransfer_PrepareData);
+ NDS::UnregisterEventFunc(NDS::Event_ROMTransfer, ROMTransfer_End);
+ NDS::UnregisterEventFunc(NDS::Event_ROMSPITransfer, 0);
}
void Reset()
@@ -1967,9 +1981,9 @@ void WriteROMCnt(u32 val)
}
if (datasize == 0)
- NDS::ScheduleEvent(NDS::Event_ROMTransfer, false, xfercycle*cmddelay, ROMEndTransfer, 0);
+ NDS::ScheduleEvent(NDS::Event_ROMTransfer, false, xfercycle*cmddelay, ROMTransfer_End, 0);
else
- NDS::ScheduleEvent(NDS::Event_ROMTransfer, false, xfercycle*(cmddelay+4), ROMPrepareData, 0);
+ NDS::ScheduleEvent(NDS::Event_ROMTransfer, false, xfercycle*(cmddelay+4), ROMTransfer_PrepareData, 0);
}
void AdvanceROMTransfer()
@@ -1986,7 +2000,7 @@ void AdvanceROMTransfer()
delay += ((ROMCnt >> 16) & 0x3F);
}
- NDS::ScheduleEvent(NDS::Event_ROMTransfer, false, xfercycle*delay, ROMPrepareData, 0);
+ NDS::ScheduleEvent(NDS::Event_ROMTransfer, false, xfercycle*delay, ROMTransfer_PrepareData, 0);
}
else
ROMEndTransfer(0);
@@ -2088,7 +2102,7 @@ void WriteSPIData(u8 val)
// SPI transfers one bit per cycle -> 8 cycles per byte
u32 delay = 8 * (8 << (SPICnt & 0x3));
- NDS::ScheduleEvent(NDS::Event_ROMSPITransfer, false, delay, SPITransferDone, 0);
+ NDS::ScheduleEvent(NDS::Event_ROMSPITransfer, false, delay, 0, 0);
}
}
diff --git a/src/RTC.cpp b/src/RTC.cpp
index 3d25226..527b7f4 100644
--- a/src/RTC.cpp
+++ b/src/RTC.cpp
@@ -53,6 +53,8 @@ void WriteDateTime(int num, u8 val);
bool Init()
{
+ NDS::RegisterEventFunc(NDS::Event_RTC, 0, ClockTimer);
+
ResetState();
// indicate the power was off
@@ -64,6 +66,7 @@ bool Init()
void DeInit()
{
+ NDS::UnregisterEventFunc(NDS::Event_RTC, 0);
}
void Reset()
@@ -538,7 +541,7 @@ void ScheduleTimer(bool first)
s32 delay = sysclock >> 15;
TimerError = sysclock & 0x7FFF;
- NDS::ScheduleEvent(NDS::Event_RTC, !first, delay, ClockTimer, 0);
+ NDS::ScheduleEvent(NDS::Event_RTC, !first, delay, 0, 0);
}
void ClockTimer(u32 param)
diff --git a/src/SPI.cpp b/src/SPI.cpp
index a755c44..1a4c12e 100644
--- a/src/SPI.cpp
+++ b/src/SPI.cpp
@@ -612,6 +612,8 @@ u32 CurDevice; // remove me
bool Init()
{
+ NDS::RegisterEventFunc(NDS::Event_SPITransfer, 0, TransferDone);
+
if (!SPI_Firmware::Init()) return false;
if (!SPI_Powerman::Init()) return false;
if (!SPI_TSC::Init()) return false;
@@ -626,6 +628,8 @@ void DeInit()
SPI_Powerman::DeInit();
SPI_TSC::DeInit();
DSi_SPI_TSC::DeInit();
+
+ NDS::UnregisterEventFunc(NDS::Event_SPITransfer, 0);
}
void Reset()
@@ -725,7 +729,7 @@ void WriteData(u8 val)
// SPI transfers one bit per cycle -> 8 cycles per byte
u32 delay = 8 * (8 << (Cnt & 0x3));
- NDS::ScheduleEvent(NDS::Event_SPITransfer, false, delay, TransferDone, 0);
+ NDS::ScheduleEvent(NDS::Event_SPITransfer, false, delay, 0, 0);
}
}
diff --git a/src/SPU.cpp b/src/SPU.cpp
index 76fdd2d..cdfc244 100644
--- a/src/SPU.cpp
+++ b/src/SPU.cpp
@@ -93,6 +93,8 @@ CaptureUnit* Capture[2];
bool Init()
{
+ NDS::RegisterEventFunc(NDS::Event_SPU, 0, Mix);
+
for (int i = 0; i < 16; i++)
Channels[i] = new Channel(i);
@@ -147,6 +149,8 @@ void DeInit()
Platform::Mutex_Free(AudioLock);
AudioLock = nullptr;
+
+ NDS::UnregisterEventFunc(NDS::Event_SPU, 0);
}
void Reset()
@@ -163,7 +167,7 @@ void Reset()
Capture[0]->Reset();
Capture[1]->Reset();
- NDS::ScheduleEvent(NDS::Event_SPU, false, 1024, Mix, 0);
+ NDS::ScheduleEvent(NDS::Event_SPU, false, 1024, 0, 0);
}
void Stop()
@@ -864,7 +868,7 @@ void Mix(u32 dummy)
OutputBackbufferWritePosition += 2;
}
- NDS::ScheduleEvent(NDS::Event_SPU, true, 1024, Mix, 0);
+ NDS::ScheduleEvent(NDS::Event_SPU, true, 1024, 0, 0);
}
void TransferOutput()
diff --git a/src/Wifi.cpp b/src/Wifi.cpp
index d786cd0..c5a67ab 100644
--- a/src/Wifi.cpp
+++ b/src/Wifi.cpp
@@ -150,6 +150,8 @@ u64 RXTimestamp;
bool Init()
{
+ NDS::RegisterEventFunc(NDS::Event_Wifi, 0, USTimer);
+
//MPInited = false;
//LANInited = false;
@@ -172,6 +174,8 @@ void DeInit()
Platform::LAN_DeInit();
WifiAP::DeInit();
+
+ NDS::UnregisterEventFunc(NDS::Event_Wifi, 0);
}
void Reset()
@@ -359,7 +363,7 @@ void ScheduleTimer(bool first)
s32 delay = (cycles + 999999) / 1000000;
TimerError = (delay * 1000000) - cycles;
- NDS::ScheduleEvent(NDS::Event_Wifi, !first, delay, USTimer, 0);
+ NDS::ScheduleEvent(NDS::Event_Wifi, !first, delay, 0, 0);
}
void UpdatePowerOn()