Core: Implement deterministic event ordering
Jeffrey Pfau jeffrey@endrift.com
Sun, 18 Dec 2016 11:46:45 -0800
13 files changed,
26 insertions(+),
1 deletions(-)
M
src/core/timing.c
→
src/core/timing.c
@@ -28,9 +28,10 @@ *timing->nextEvent = nextEvent;
} struct mTimingEvent** previous = &timing->root; struct mTimingEvent* next = timing->root; + unsigned priority = event->priority; while (next) { int32_t nextWhen = next->when - timing->masterCycles; - if (nextWhen > when) { + if (nextWhen > when || (nextWhen == when && next->priority > priority)) { break; } previous = &next->next;
M
src/core/timing.h
→
src/core/timing.h
@@ -14,6 +14,7 @@ void* context;
void (*callback)(struct mTiming*, void* context, uint32_t); const char* name; uint32_t when; + unsigned priority; struct mTimingEvent* next; };
M
src/gb/audio.c
→
src/gb/audio.c
@@ -68,24 +68,31 @@
audio->frameEvent.context = audio; audio->frameEvent.name = "GB Audio Frame Sequencer"; audio->frameEvent.callback = _updateFrame; + audio->frameEvent.priority = 0x10; audio->ch1Event.context = audio; audio->ch1Event.name = "GB Audio Channel 1"; audio->ch1Event.callback = _updateChannel1; + audio->ch1Event.priority = 0x11; audio->ch2Event.context = audio; audio->ch2Event.name = "GB Audio Channel 2"; audio->ch2Event.callback = _updateChannel2; + audio->ch2Event.priority = 0x12; audio->ch3Event.context = audio; audio->ch3Event.name = "GB Audio Channel 3"; audio->ch3Event.callback = _updateChannel3; + audio->ch3Event.priority = 0x13; audio->ch3Fade.context = audio; audio->ch3Fade.name = "GB Audio Channel 3 Memory"; audio->ch3Fade.callback = _fadeChannel3; + audio->ch3Fade.priority = 0x14; audio->ch4Event.context = audio; audio->ch4Event.name = "GB Audio Channel 4"; audio->ch4Event.callback = _updateChannel4; + audio->ch4Event.priority = 0x15; audio->sampleEvent.context = audio; audio->sampleEvent.name = "GB Audio Sample"; audio->sampleEvent.callback = _sample; + audio->ch1Event.priority = 0x18; } void GBAudioDeinit(struct GBAudio* audio) {
M
src/gb/gb.c
→
src/gb/gb.c
@@ -91,6 +91,7 @@
gb->eiPending.name = "GB EI"; gb->eiPending.callback = _enableInterrupts; gb->eiPending.context = gb; + gb->eiPending.priority = 0; } static void GBDeinit(struct mCPUComponent* component) {
M
src/gb/memory.c
→
src/gb/memory.c
@@ -123,9 +123,11 @@
gb->memory.dmaEvent.context = gb; gb->memory.dmaEvent.name = "GB DMA"; gb->memory.dmaEvent.callback = _GBMemoryDMAService; + gb->memory.dmaEvent.priority = 0x40; gb->memory.hdmaEvent.context = gb; gb->memory.hdmaEvent.name = "GB HDMA"; gb->memory.hdmaEvent.callback = _GBMemoryHDMAService; + gb->memory.hdmaEvent.priority = 0x41; gb->memory.sramAccess = false; gb->memory.rtcAccess = false;
M
src/gb/sio.c
→
src/gb/sio.c
@@ -16,6 +16,7 @@ sio->pendingSB = 0xFF;
sio->event.context = sio; sio->event.name = "GB SIO"; sio->event.callback = _GBSIOProcessEvents; + sio->event.priority = 0x30; } void GBSIOReset(struct GBSIO* sio) {
M
src/gb/timer.c
→
src/gb/timer.c
@@ -51,9 +51,11 @@ void GBTimerReset(struct GBTimer* timer) {
timer->event.context = timer; timer->event.name = "GB Timer"; timer->event.callback = _GBTimerIncrement; + timer->event.priority = 0x20; timer->irq.context = timer; timer->irq.name = "GB Timer IRQ"; timer->irq.callback = _GBTimerIRQ; + timer->event.priority = 0x21; timer->nextDiv = GB_DMG_DIV_PERIOD; // TODO: GBC differences timer->timaPeriod = 1024 >> 4;
M
src/gb/video.c
→
src/gb/video.c
@@ -55,9 +55,11 @@
video->modeEvent.context = video; video->modeEvent.name = "GB Video Mode"; video->modeEvent.callback = NULL; + video->modeEvent.priority = 8; video->frameEvent.context = video; video->frameEvent.name = "GB Video Frame"; video->frameEvent.callback = _updateFrameCount; + video->frameEvent.priority = 9; } void GBVideoReset(struct GBVideo* video) {
M
src/gba/audio.c
→
src/gba/audio.c
@@ -31,6 +31,7 @@ void GBAAudioInit(struct GBAAudio* audio, size_t samples) {
audio->sampleEvent.context = audio; audio->sampleEvent.name = "GBA Audio Sample"; audio->sampleEvent.callback = _sample; + audio->sampleEvent.priority = 0x18; audio->psg.p = NULL; uint8_t* nr52 = (uint8_t*) &audio->p->memory.io[REG_SOUNDCNT_X >> 1]; #ifdef __BIG_ENDIAN__
M
src/gba/dma.c
→
src/gba/dma.c
@@ -18,6 +18,7 @@ void GBADMAInit(struct GBA* gba) {
gba->memory.dmaEvent.name = "GBA DMA"; gba->memory.dmaEvent.callback = _dmaEvent; gba->memory.dmaEvent.context = gba; + gba->memory.dmaEvent.priority = 0x40; } void GBADMAReset(struct GBA* gba) {
M
src/gba/sio/lockstep.c
→
src/gba/sio/lockstep.c
@@ -84,6 +84,7 @@ mLOG(GBA_SIO, DEBUG, "Lockstep %i: Node init", node->id);
node->event.context = node; node->event.name = "GBA SIO Lockstep"; node->event.callback = _GBASIOLockstepNodeProcessEvents; + node->event.priority = 0x80; return true; }
M
src/gba/timer.c
→
src/gba/timer.c
@@ -65,15 +65,19 @@ memset(gba->timers, 0, sizeof(gba->timers));
gba->timers[0].event.name = "GBA Timer 0"; gba->timers[0].event.callback = GBATimerUpdate0; gba->timers[0].event.context = gba; + gba->timers[0].event.priority = 0x20; gba->timers[1].event.name = "GBA Timer 1"; gba->timers[1].event.callback = GBATimerUpdate1; gba->timers[1].event.context = gba; + gba->timers[1].event.priority = 0x21; gba->timers[2].event.name = "GBA Timer 2"; gba->timers[2].event.callback = GBATimerUpdate2; gba->timers[2].event.context = gba; + gba->timers[2].event.priority = 0x22; gba->timers[3].event.name = "GBA Timer 3"; gba->timers[3].event.callback = GBATimerUpdate3; gba->timers[3].event.context = gba; + gba->timers[3].event.priority = 0x23; } void GBATimerUpdateRegister(struct GBA* gba, int timer) {
M
src/gba/video.c
→
src/gba/video.c
@@ -74,6 +74,7 @@ video->frameskip = 0;
video->event.name = "GBA Video"; video->event.callback = NULL; video->event.context = video; + video->event.priority = 8; } void GBAVideoReset(struct GBAVideo* video) {