From 9dd61937a48467e7949eb456380a00e69a8ed813 Mon Sep 17 00:00:00 2001 From: Paul Duncan Date: Sat, 16 Jun 2018 20:50:18 -0400 Subject: add gb_handle_interrupts() --- ops.yaml | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/ops.yaml b/ops.yaml index 08c8d8c..965b9d7 100644 --- a/ops.yaml +++ b/ops.yaml @@ -7582,6 +7582,9 @@ templates: uint8_t *rom; uint32_t rom_size; + // interrupt enable flags (0xFFFF) + uint8_t ei; + // external ram (optional, 8k) uint8_t *eram; } mmu; @@ -7600,8 +7603,6 @@ templates: // interrupt master enable bool ime; - uint32_t iev; - uint32_t ivs; // FIXME: uint8_t? } cpu; } gb_t; @@ -7677,7 +7678,9 @@ templates: break; case 0x0F00: - if (addr < 0xFF80) { + if (addr == 0xFFFF) { + return ctx->mmu.ei; + } else if (addr < 0xFF80) { // TODO: io ports return 0; } else { @@ -7690,6 +7693,7 @@ templates: // working ram (shadow) return ctx->mmu.ram[addr & 0x1FFF]; } + break; default: // never reached @@ -7766,7 +7770,9 @@ templates: break; case 0x0F00: - if (addr < 0xFF80) { + if (addr == 0xFFFF) { + ctx->mmu.ei = val; + } else if (addr < 0xFF80) { // TODO: io ports } else { // zero page @@ -8747,10 +8753,11 @@ templates: // process next scanline ctx->gpu.mode = GPU_MODE_OAM; } else { - // go to vblank - ctx->gpu.mode = GPU_MODE_VBLANK; + // trigger vblank interrupt + mmu_wb(ctx, 0xFF0F, mmu_rb(ctx, 0xFF0F) | 1); - // TODO: trigger vblank interrupt + // set gpu mode + ctx->gpu.mode = GPU_MODE_VBLANK; } } @@ -8770,15 +8777,49 @@ templates: } } + static void + gb_handle_interrupts( + gb_t * const ctx + ) { + // handle interrupts + if (ctx->cpu.ime) { + // get interrupt vector (masked against enabled interrupts) + const uint8_t iv = mmu_rb(ctx, 0xFFFF) & mmu_rb(ctx, 0xFF0F); + + for (uint8_t i = 0; i < 5; i++) { + const uint8_t m = (i ? (1 << i) : 1); + + // has this interrupt been triggered? + if (iv & m) { + // disable ime + ctx->cpu.ime = false; + + // clear interrupt flag + mmu_wb(ctx, 0xFF0F, mmu_rb(ctx, 0xFF0F) ^ m); + + + // trigger interrupt + rst(ctx, 0x0040 + (8 * i)); + + // break out of for loop + break; + } + } + } + } + void gb_step( gb_t * const ctx ) { + // handle pending interrupts + gb_handle_interrupts(ctx); + + // get pc, and current op const uint16_t old_pc = cpu_rw(ctx, RW_PC), op = mmu_rb(ctx, old_pc); - // TODO: handle interrupts - + // exec op switch (op) { <%= switches['main'] %> case 0xCB: -- cgit v1.2.3