GB: Fix HALT

This commit is contained in:
Jeffrey Pfau 2016-01-22 01:09:11 -08:00
parent 6fb8e296d4
commit 862e41ad6b
4 changed files with 40 additions and 24 deletions

View File

@ -106,6 +106,7 @@ void GBInterruptHandlerInit(struct LR35902InterruptHandler* irqh) {
irqh->processEvents = GBProcessEvents;
irqh->setInterrupts = GBSetInterrupts;
irqh->hitStub = GBHitStub;
irqh->halt = GBHalt;
}
void GBReset(struct LR35902Core* cpu) {
@ -133,13 +134,15 @@ void GBReset(struct LR35902Core* cpu) {
}
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,27 +173,33 @@ void GBUpdateIRQs(struct GB* gb) {
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) {
@ -199,6 +208,12 @@ void GBSetInterrupts(struct LR35902Core* cpu, bool 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) {
// TODO
//printf("Hit stub at address %04X\n", cpu->pc);

View File

@ -84,8 +84,8 @@ void GBDestroy(struct GB* gb);
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);

View File

@ -730,7 +730,7 @@ DEFINE_INSTRUCTION_LR35902(RRCA_,
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));

View File

@ -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 @@ struct LR35902Core {
int32_t cycles;
int32_t nextEvent;
enum LR35902ExecutionState executionState;
int halted;
bool halted;
uint8_t bus;
bool condition;