From e6b0248c5010492d5d7d33bc52258c16856ad99f Mon Sep 17 00:00:00 2001 From: Nathaniel Walizer Date: Thu, 20 Mar 2025 21:24:25 -0700 Subject: [PATCH] Blargg PPU test fixes --- src/f6502.c | 22 +++++++++++++++++----- src/nes.c | 18 ++++++++++++++++-- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/f6502.c b/src/f6502.c index f5defa1..90800a4 100644 --- a/src/f6502.c +++ b/src/f6502.c @@ -76,14 +76,21 @@ static inline uint8_t f6502_read(nes_Memory* mem, } case ppu_reg_oam_data: - return mem->ppu.oam[mem->ppu.oam_addr++]; + return mem->ppu.oam[mem->ppu.oam_addr]; case ppu_reg_data: { addr = mem->ppu.addr & 0x3FFFU; mem->ppu.addr += mem->ppu.addr_inc; - uint8_t val = mem->ppu.data; - mem->ppu.data = mem->ppu.bank[addr >> 10][addr & 0x3FFU]; - return val; + uint8_t data = mem->ppu.bank[addr >> 10][addr & 0x3FFU]; + if (addr >= 0x3F00) { + addr &= 0x2FFFU; + mem->ppu.data = mem->ppu.bank[addr >> 10][addr & 0x3FFU]; + return data; + } else { + uint8_t val = mem->ppu.data; + mem->ppu.data = data; + return val; + } } } break; @@ -317,7 +324,12 @@ static inline int f6502_write(nes_Memory* mem, break; } if (NULL != src) { - memcpy(mem->ppu.oam, src, NES_PPU_OAM_SIZE); + int top_size = NES_PPU_OAM_SIZE - + mem->ppu.oam_addr; + memcpy(mem->ppu.oam + mem->ppu.oam_addr, + src, top_size); + memcpy(mem->ppu.oam, src + top_size, + mem->ppu.oam_addr); } // TODO: Why does this throw off MMC3? // ret = 513; diff --git a/src/nes.c b/src/nes.c index 36ac1df..3a018c0 100644 --- a/src/nes.c +++ b/src/nes.c @@ -108,16 +108,24 @@ static int nes_hsync(nes* sys, void* plat) { #define mapper_hsync_dot (300U) #define render_dot (256U) +#define vblank_clear_dot (320U) int nes_loop(nes* sys, void* plat) { int status = 0; int dot = 0; bool mapper_hsync = false; + bool vbl_clear = false; while (0 == status) { // TODO: Move to inline PPU function? int target_dot = nes_ppu_scanline_dots; + if ( nes_ppu_frame_end_line - 1 == sys->ppu.scanline && + sys->core.memory.ppu.status & ppu_Status_VBlank) { + target_dot = vblank_clear_dot; + vbl_clear = true; + } + if ( sys->core.memory.mapper.hsync && sys->ppu.scanline > nes_ppu_prerender_line && sys->ppu.scanline < nes_ppu_postrender_line && @@ -139,11 +147,17 @@ int nes_loop(nes* sys, void* plat) { } } - if (target_dot > dot) { - int cpu_cycles = (target_dot - dot + 2) / 3; + int dots_to_run = target_dot - dot; + if (dots_to_run > 0) { + int cpu_cycles = (dots_to_run + 2) / 3; dot += 3 * f6502_step(&sys->core, cpu_cycles); } + if (vbl_clear && dot >= vblank_clear_dot) { + sys->core.memory.ppu.status &= ~ppu_Status_VBlank; + vbl_clear = false; + } + if (mapper_hsync && dot >= mapper_hsync_dot) { nes_Memory* mem = &sys->core.memory; mem->mapper.hsync(&mem->mapper);