From b0c6feb73ff2b97960f537396362811ce4ec9c00 Mon Sep 17 00:00:00 2001 From: Nathaniel Walizer Date: Tue, 18 Mar 2025 18:45:55 -0700 Subject: [PATCH] Fix sprite priority --- src/ppu.c | 94 +++++++++++++++++++++---------------------------------- 1 file changed, 36 insertions(+), 58 deletions(-) diff --git a/src/ppu.c b/src/ppu.c index ec5c697..6079195 100644 --- a/src/ppu.c +++ b/src/ppu.c @@ -232,6 +232,9 @@ void nes_ppu_render_line(nes_PPU* ppu, nes_PPU_Memory* mem) { int sprite_bank = !!(mem->ctrl & ppu_Control_Sprite_Bank) << 2; + uint8_t foreground[nes_ppu_render_w]; + memset(foreground, 0xFFU, nes_ppu_render_w); + int n_sprites = 0; const oam_sprite* sprites = (oam_sprite*)mem->oam; const oam_sprite* sprite = sprites + @@ -265,7 +268,10 @@ void nes_ppu_render_line(nes_PPU* ppu, nes_PPU_Memory* mem) { int pat1 = ((pl0 >> 1) & 0x55) | (pl1 & 0xAA); const uint8_t* pal = &mem->palette[0x10 + ((sprite->attr & oam_Attr_Pal_Mask) << 2)]; - uint8_t* dst = scanline_ptr + sprite->x; + const uint8_t* back = + (sprite->attr & oam_Attr_Background) ? + (scanline_ptr + sprite->x) : NULL; + uint8_t* dst = foreground + sprite->x; const int over_x = ((int)sprite->x + 8) - nes_ppu_render_w; @@ -275,73 +281,31 @@ void nes_ppu_render_line(nes_PPU* ppu, nes_PPU_Memory* mem) { pat1 = sprite_rev[tmp]; } - // TODO: Handle column 0 sprite mask +#define do_sprite(idx, pi, shift) \ + if (back && back[idx] != 0xFFU) { \ + dst[idx] = back[idx]; \ + } else { \ + int pal_idx = (pat##pi >> shift) & 3; \ + if (pal_idx) dst[idx] = pal[pal_idx]; \ + } switch (over_x) { default: - { int pal_idx = (pat0 >> 0) & 3; - if ( ( !(sprite->attr & oam_Attr_Background) || - dst[7] == 0xFFU) - && pal_idx) { - dst[7] = pal[pal_idx]; - } - } + do_sprite(7, 0, 0); case 1: - { int pal_idx = (pat1 >> 0) & 3; - if ( ( !(sprite->attr & oam_Attr_Background) || - dst[6] == 0xFFU) - && pal_idx) { - dst[6] = pal[pal_idx]; - } - } + do_sprite(6, 1, 0); case 2: - { int pal_idx = (pat0 >> 2) & 3; - if ( ( !(sprite->attr & oam_Attr_Background) || - dst[5] == 0xFFU) - && pal_idx) { - dst[5] = pal[pal_idx]; - } - } + do_sprite(5, 0, 2); case 3: - { int pal_idx = (pat1 >> 2) & 3; - if ( ( !(sprite->attr & oam_Attr_Background) || - dst[4] == 0xFFU) - && pal_idx) { - dst[4] = pal[pal_idx]; - } - } + do_sprite(4, 1, 2); case 4: - { int pal_idx = (pat0 >> 4) & 3; - if ( ( !(sprite->attr & oam_Attr_Background) || - dst[3] == 0xFFU) - && pal_idx) { - dst[3] = pal[pal_idx]; - } - } + do_sprite(3, 0, 4); case 5: - { int pal_idx = (pat1 >> 4) & 3; - if ( ( !(sprite->attr & oam_Attr_Background) || - dst[2] == 0xFFU) - && pal_idx) { - dst[2] = pal[pal_idx]; - } - } + do_sprite(2, 1, 4); case 6: - { int pal_idx = (pat0 >> 6) & 3; - if ( ( !(sprite->attr & oam_Attr_Background) || - dst[1] == 0xFFU) - && pal_idx) { - dst[1] = pal[pal_idx]; - } - } + do_sprite(1, 0, 6); case 7: - { int pal_idx = (pat1 >> 6) & 3; - if ( ( !(sprite->attr & oam_Attr_Background) || - dst[0] == 0xFFU) - && pal_idx) { - dst[0] = pal[pal_idx]; - } - } + do_sprite(0, 1, 6); } ++n_sprites; @@ -352,6 +316,20 @@ void nes_ppu_render_line(nes_PPU* ppu, nes_PPU_Memory* mem) { } else { mem->status &= ~ppu_Status_Overflow; } + + // Mask column 0? + if (!(mem->mask & ppu_Mask_Left_Sprite)) { + memset(foreground, 0xFFU, 8); + } + + // Overlay the sprites + const uint8_t* fg = foreground; + uint8_t* dst = scanline_ptr; + for (int i = 0; i < nes_ppu_render_w; ++i) { + if (*fg != 0xFFU) *dst = *fg; + ++fg; + ++dst; + } } // Increment internal registers