mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2024-11-14 13:27:41 -07:00
better, less hacky, more OOP-friendly scheduler design
This commit is contained in:
parent
5ccd3916ff
commit
70c6750561
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
CheckSwapFIFO();
|
||||
|
||||
host->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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
27
src/GPU.cpp
27
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);
|
||||
}
|
||||
|
||||
|
||||
|
202
src/NDS.cpp
202
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.Timestamp = ARM7Timestamp + delay;
|
||||
}
|
||||
|
||||
evt->Func = func;
|
||||
evt->Param = param;
|
||||
evt.FuncID = funcid;
|
||||
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;
|
||||
}
|
||||
|
||||
SchedEvent* evt = &SchedList[id];
|
||||
|
||||
evt->Timestamp = timestamp;
|
||||
evt->Func = func;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
14
src/NDS.h
14
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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user