Browse Source

Fix sprite priority

v2
Nathaniel Walizer 9 months ago
parent
commit
b0c6feb73f
1 changed files with 36 additions and 58 deletions
  1. +36
    -58
      src/ppu.c

+ 36
- 58
src/ppu.c View File

@@ -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


Loading…
Cancel
Save