diff options
author | Paul Duncan <pabs@pablotron.org> | 2018-06-16 20:50:18 -0400 |
---|---|---|
committer | Paul Duncan <pabs@pablotron.org> | 2018-06-16 20:50:18 -0400 |
commit | 9dd61937a48467e7949eb456380a00e69a8ed813 (patch) | |
tree | d45eba9a153b79d6e00942373a70a842ea59c86b | |
parent | 67bdc96a4341b329cda87396879cfee75be4b227 (diff) | |
download | gb-c-9dd61937a48467e7949eb456380a00e69a8ed813.tar.bz2 gb-c-9dd61937a48467e7949eb456380a00e69a8ed813.zip |
add gb_handle_interrupts()
-rw-r--r-- | ops.yaml | 59 |
1 files changed, 50 insertions, 9 deletions
@@ -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: |