Core: Implement deterministic event ordering

This commit is contained in:
Jeffrey Pfau 2016-12-18 11:46:45 -08:00
parent 327c3e78c6
commit ad85acab75
13 changed files with 26 additions and 1 deletions

View File

@ -28,9 +28,10 @@ void mTimingSchedule(struct mTiming* timing, struct mTimingEvent* event, int32_t
}
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;

View File

@ -14,6 +14,7 @@ struct mTimingEvent {
void (*callback)(struct mTiming*, void* context, uint32_t);
const char* name;
uint32_t when;
unsigned priority;
struct mTimingEvent* next;
};

View File

@ -68,24 +68,31 @@ void GBAudioInit(struct GBAudio* audio, size_t samples, uint8_t* nr52, enum GBAu
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) {

View File

@ -91,6 +91,7 @@ static void GBInit(void* cpu, struct mCPUComponent* component) {
gb->eiPending.name = "GB EI";
gb->eiPending.callback = _enableInterrupts;
gb->eiPending.context = gb;
gb->eiPending.priority = 0;
}
static void GBDeinit(struct mCPUComponent* component) {

View File

@ -123,9 +123,11 @@ void GBMemoryReset(struct GB* gb) {
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;

View File

@ -16,6 +16,7 @@ void GBSIOInit(struct GBSIO* sio) {
sio->event.context = sio;
sio->event.name = "GB SIO";
sio->event.callback = _GBSIOProcessEvents;
sio->event.priority = 0x30;
}
void GBSIOReset(struct GBSIO* sio) {

View File

@ -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;

View File

@ -55,9 +55,11 @@ void GBVideoInit(struct GBVideo* video) {
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) {

View File

@ -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__

View File

@ -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) {

View File

@ -84,6 +84,7 @@ bool GBASIOLockstepNodeInit(struct GBASIODriver* driver) {
node->event.context = node;
node->event.name = "GBA SIO Lockstep";
node->event.callback = _GBASIOLockstepNodeProcessEvents;
node->event.priority = 0x80;
return true;
}

View File

@ -65,15 +65,19 @@ void GBATimerInit(struct GBA* gba) {
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) {

View File

@ -74,6 +74,7 @@ void GBAVideoInit(struct GBAVideo* video) {
video->event.name = "GBA Video";
video->event.callback = NULL;
video->event.context = video;
video->event.priority = 8;
}
void GBAVideoReset(struct GBAVideo* video) {