From 9ee76c20c0d093d5adac2dcc3b275b53b879c369 Mon Sep 17 00:00:00 2001 From: Peter Fors Date: Tue, 28 Oct 2025 17:44:57 +0100 Subject: small optimizations of sprite evaluation in ppu_render_pixel --- mknes_apu.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'mknes_apu.c') 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; } } -- cgit v1.2.3