GB: Fix HALT
Jeffrey Pfau jeffrey@endrift.com
Fri, 22 Jan 2016 01:09:11 -0800
4 files changed,
40 insertions(+),
24 deletions(-)
M
src/gb/gb.c
→
src/gb/gb.c
@@ -106,6 +106,7 @@ irqh->reset = GBReset;
irqh->processEvents = GBProcessEvents; irqh->setInterrupts = GBSetInterrupts; irqh->hitStub = GBHitStub; + irqh->halt = GBHalt; } void GBReset(struct LR35902Core* cpu) {@@ -133,13 +134,15 @@ GBIOReset(gb);
} void GBUpdateIRQs(struct GB* gb) { - if (!gb->memory.ime) { - return; - } int irqs = gb->memory.ie & gb->memory.io[REG_IF]; if (!irqs) { return; } + gb->cpu->halted = false; + + if (!gb->memory.ime) { + return; + } gb->cpu->irqh.setInterrupts(gb->cpu, false); if (irqs & (1 << GB_IRQ_VBLANK)) {@@ -170,33 +173,45 @@ }
void GBProcessEvents(struct LR35902Core* cpu) { struct GB* gb = (struct GB*) cpu->master; - int32_t cycles = cpu->nextEvent; - int32_t nextEvent = INT_MAX; - int32_t testEvent; + do { + int32_t cycles = cpu->nextEvent; + int32_t nextEvent = INT_MAX; + int32_t testEvent; - testEvent = GBVideoProcessEvents(&gb->video, cycles); - if (testEvent < nextEvent) { - nextEvent = testEvent; - } + testEvent = GBVideoProcessEvents(&gb->video, cycles); + if (testEvent < nextEvent) { + nextEvent = testEvent; + } + + testEvent = GBTimerProcessEvents(&gb->timer, cycles); + if (testEvent < nextEvent) { + nextEvent = testEvent; + } - testEvent = GBTimerProcessEvents(&gb->timer, cycles); - if (testEvent < nextEvent) { - nextEvent = testEvent; - } + testEvent = GBMemoryProcessEvents(gb, cycles); + if (testEvent < nextEvent) { + nextEvent = testEvent; + } - testEvent = GBMemoryProcessEvents(gb, cycles); - if (testEvent < nextEvent) { - nextEvent = testEvent; - } + cpu->cycles -= cycles; + cpu->nextEvent = nextEvent; - cpu->cycles -= cycles; - cpu->nextEvent = nextEvent; + if (cpu->halted) { + cpu->cycles = cpu->nextEvent; + } + } while (cpu->cycles >= cpu->nextEvent); } void GBSetInterrupts(struct LR35902Core* cpu, bool enable) { struct GB* gb = (struct GB*) cpu->master; gb->memory.ime = enable; GBUpdateIRQs(gb); +} + +void GBHalt(struct LR35902Core* cpu) { + struct GB* gb = (struct GB*) cpu->master; + cpu->cycles = cpu->nextEvent; + cpu->halted = true; } void GBHitStub(struct LR35902Core* cpu) {
M
src/gb/gb.h
→
src/gb/gb.h
@@ -84,8 +84,8 @@
void GBReset(struct LR35902Core* cpu); void GBUpdateIRQs(struct GB* gb); -void GBHalt(struct GB* gb); -void GBStop(struct GB* gb); +void GBHalt(struct LR35902Core* cpu); +void GBStop(struct LR35902Core* cpu); struct VFile; bool GBLoadROM(struct GB* gb, struct VFile* vf, struct VFile* sav, const char* fname);
M
src/lr35902/isa-lr35902.c
→
src/lr35902/isa-lr35902.c
@@ -730,7 +730,7 @@ cpu->f.c = low;)
DEFINE_INSTRUCTION_LR35902(DI, cpu->irqh.setInterrupts(cpu, false)); DEFINE_INSTRUCTION_LR35902(EI, cpu->irqh.setInterrupts(cpu, true)); -DEFINE_INSTRUCTION_LR35902(HALT, cpu->cycles = cpu->nextEvent); +DEFINE_INSTRUCTION_LR35902(HALT, cpu->irqh.halt(cpu)); DEFINE_INSTRUCTION_LR35902(RST00, LR35902RaiseIRQ(cpu, 0x00)); DEFINE_INSTRUCTION_LR35902(RST08, LR35902RaiseIRQ(cpu, 0x08));
M
src/lr35902/lr35902.h
→
src/lr35902/lr35902.h
@@ -63,6 +63,7 @@ struct LR35902InterruptHandler {
void (*reset)(struct LR35902Core* cpu); void (*processEvents)(struct LR35902Core* cpu); void (*setInterrupts)(struct LR35902Core* cpu, bool enable); + void (*halt)(struct LR35902Core* cpu); void (*hitStub)(struct LR35902Core* cpu); };@@ -113,7 +114,7 @@
int32_t cycles; int32_t nextEvent; enum LR35902ExecutionState executionState; - int halted; + bool halted; uint8_t bus; bool condition;