summaryrefslogtreecommitdiff
path: root/mknes_apu.c
diff options
context:
space:
mode:
Diffstat (limited to 'mknes_apu.c')
-rw-r--r--mknes_apu.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/mknes_apu.c b/mknes_apu.c
index 98552ed..027b1e5 100644
--- a/mknes_apu.c
+++ b/mknes_apu.c
@@ -35,12 +35,19 @@ static uint8_t apu_read4015(struct nes_state *state) {
}
if(apu->irq_pending) {
result |= 0x40;
- apu->irq_pending = 0;
}
+
+ // Reading $4015 clears the frame IRQ flag
+ apu->irq_pending = 0;
+ // Only clear CPU IRQ if DMC isn't requesting it
+ if(!(apu->dmc_bytes_remaining > 0 && apu->dmc_irq_enable)) {
+ state->cpu.irq_pending = 0;
+ }
+
return result;
}
-// $4010–$4013, $4015 write
+// $4010–$4013, $4015, $4017 write
static void apu_write(struct nes_state *state, uint16_t addr, uint8_t val) {
struct apu_state *apu = &state->apu;
@@ -62,6 +69,26 @@ static void apu_write(struct nes_state *state, uint16_t addr, uint8_t val) {
case 0x4015: {
apu_write4015(state, val);
} break;
+ case 0x4017: {
+ // Frame counter control
+ apu->mode = (val >> 7) & 1;
+ apu->irq_inhibit = (val >> 6) & 1;
+
+ // If IRQ inhibit flag is set, clear the frame IRQ
+ if(apu->irq_inhibit) {
+ apu->irq_pending = 0;
+ // Only clear CPU IRQ if DMC isn't requesting it
+ if(!(apu->dmc_bytes_remaining > 0 && apu->dmc_irq_enable)) {
+ state->cpu.irq_pending = 0;
+ }
+ }
+
+ // Reset frame counter (with delay, but we'll approximate immediately for now)
+ apu->frame_cycle = 0;
+
+ // If 5-step mode, immediately clock half-frame and quarter-frame
+ // (For timing purposes without audio, we can leave this empty)
+ } break;
}
}