summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Duncan <pabs@pablotron.org>2018-06-16 20:50:18 -0400
committerPaul Duncan <pabs@pablotron.org>2018-06-16 20:50:18 -0400
commit9dd61937a48467e7949eb456380a00e69a8ed813 (patch)
treed45eba9a153b79d6e00942373a70a842ea59c86b
parent67bdc96a4341b329cda87396879cfee75be4b227 (diff)
downloadgb-c-9dd61937a48467e7949eb456380a00e69a8ed813.tar.bz2
gb-c-9dd61937a48467e7949eb456380a00e69a8ed813.zip
add gb_handle_interrupts()
-rw-r--r--ops.yaml59
1 files 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: