|
|
|
@@ -195,13 +195,18 @@ static void sdl_render_done(nes_Renderer* rend) { |
|
|
|
|
|
|
|
static inline void render_sprite_line( |
|
|
|
const nes_ppu* ppu, int index, int y, const uint8_t* pal, |
|
|
|
uint8_t* dst, int start, int end) { |
|
|
|
uint8_t* dst, int start, int end, const uint8_t* back) { |
|
|
|
uint8_t* sprite = chr_mem(ppu, index * 16U); |
|
|
|
uint8_t lo = sprite[0U + y] << start; |
|
|
|
uint8_t hi = sprite[8U + y] << start; |
|
|
|
for (int x = start; x < end; ++x) { |
|
|
|
int pal_idx = (((hi & 0x80) >> 6) | ((lo & 0x80) >> 7)); |
|
|
|
if (pal_idx) *dst = pal[pal_idx]; |
|
|
|
if (back && *back != 0xFFU) { |
|
|
|
*dst = *back; |
|
|
|
} else { |
|
|
|
int pal_idx = (((hi & 0x80) >> 6) | ((lo & 0x80) >> 7)); |
|
|
|
if (pal_idx) *dst = pal[pal_idx]; |
|
|
|
} |
|
|
|
if (back) ++back; |
|
|
|
dst++; |
|
|
|
hi <<= 1; |
|
|
|
lo <<= 1; |
|
|
|
@@ -210,13 +215,18 @@ static inline void render_sprite_line( |
|
|
|
|
|
|
|
static inline void render_sprite_line_flip( |
|
|
|
const nes_ppu* ppu, int index, int y, const uint8_t* pal, |
|
|
|
uint8_t* dst, int start, int end) { |
|
|
|
uint8_t* dst, int start, int end, const uint8_t* back) { |
|
|
|
uint8_t* sprite = chr_mem(ppu, index * 16U); |
|
|
|
uint8_t lo = sprite[0U + y] >> start; |
|
|
|
uint8_t hi = sprite[8U + y] >> start; |
|
|
|
for (int x = start; x < end; ++x) { |
|
|
|
int pal_idx = (((hi & 1) << 1) | (lo & 1)); |
|
|
|
if (pal_idx) *dst = pal[pal_idx]; |
|
|
|
if (back && *back != 0xFFU) { |
|
|
|
*dst = *back; |
|
|
|
} else { |
|
|
|
int pal_idx = (((hi & 1) << 1) | (lo & 1)); |
|
|
|
if (pal_idx) *dst = pal[pal_idx]; |
|
|
|
} |
|
|
|
if (back) ++back; |
|
|
|
dst++; |
|
|
|
hi >>= 1; |
|
|
|
lo >>= 1; |
|
|
|
@@ -413,16 +423,12 @@ static void render_sprite(nes_ppu* ppu, int index, |
|
|
|
*/ |
|
|
|
|
|
|
|
static void render_line_sprites(nes_ppu* ppu, uint8_t* dst_line, |
|
|
|
int scanline, int background, |
|
|
|
int scanline, const uint8_t* back, |
|
|
|
const oam_sprite* sprites, |
|
|
|
int n_sprites) { |
|
|
|
for (int i_sprite = n_sprites - 1; i_sprite >= 0; --i_sprite) { |
|
|
|
const oam_sprite* sprite = &sprites[i_sprite]; |
|
|
|
|
|
|
|
if ((sprite->attr & oam_Attr_Background) ^ background) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
int index = sprite->index; |
|
|
|
int bank = (ppu->control & ppu_Control_Sprite_Bank) ? |
|
|
|
0x100 : 0; |
|
|
|
@@ -455,13 +461,19 @@ static void render_line_sprites(nes_ppu* ppu, uint8_t* dst_line, |
|
|
|
start = 8 - sprite->x; |
|
|
|
} |
|
|
|
if (sprite->attr & oam_Attr_Flip_X) { |
|
|
|
render_sprite_line_flip(ppu, index, y, pal, |
|
|
|
dst_line + sprite->x + start, |
|
|
|
start, end); |
|
|
|
render_sprite_line_flip( |
|
|
|
ppu, index, y, pal, |
|
|
|
dst_line + sprite->x + start, start, end, |
|
|
|
(sprite->attr & oam_Attr_Background) ? |
|
|
|
(back + sprite->x + start) : NULL |
|
|
|
); |
|
|
|
} else { |
|
|
|
render_sprite_line(ppu, index, y, pal, |
|
|
|
dst_line + sprite->x + start, |
|
|
|
start, end); |
|
|
|
render_sprite_line( |
|
|
|
ppu, index, y, pal, |
|
|
|
dst_line + sprite->x + start, start, end, |
|
|
|
(sprite->attr & oam_Attr_Background) ? |
|
|
|
(back + sprite->x + start) : NULL |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@@ -734,6 +746,16 @@ static int select_line_sprites(const nes_ppu* ppu, int scanline, |
|
|
|
return n_sprites; |
|
|
|
} |
|
|
|
|
|
|
|
static void dump_line_sprites(const nes_ppu* ppu, int line, |
|
|
|
const oam_sprite* sprites, int n) { |
|
|
|
while (n-- > 0) { |
|
|
|
PPU_LOG("PPU: Line %3d: Sprite $%02x @ %3d, %3d (%02x)\n", |
|
|
|
line, sprites->index, sprites->x, sprites->y, |
|
|
|
sprites->attr); |
|
|
|
++sprites; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static void render_scanline(nes_ppu* ppu, int line, |
|
|
|
sdl_render_data* data) { |
|
|
|
|
|
|
|
@@ -769,27 +791,18 @@ static void render_scanline(nes_ppu* ppu, int line, |
|
|
|
uint8_t* foreground = data->foreground->pixels; |
|
|
|
uint8_t* background = data->background->pixels; |
|
|
|
|
|
|
|
|
|
|
|
// We check for hits if EITHER layer is enabled. |
|
|
|
render_bg_scanline(ppu, background); |
|
|
|
if (ppu->hit_line <= 0) { |
|
|
|
update_scanline_hit(ppu, background, line); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (line >= 0) { |
|
|
|
oam_sprite line_sprites[8] = {0}; |
|
|
|
int n_sprites = select_line_sprites(ppu, line, |
|
|
|
line_sprites, 8); |
|
|
|
|
|
|
|
if (ppu->mask & ppu_Mask_Sprite) { |
|
|
|
memset(foreground, 0xFFU, nes_ppu_render_w); |
|
|
|
render_line_sprites(ppu, foreground, line, |
|
|
|
oam_Attr_Background, |
|
|
|
line_sprites, n_sprites); |
|
|
|
SDL_BlitSurface(data->foreground, &src_rect, |
|
|
|
data->target, &dst_rect); |
|
|
|
} |
|
|
|
dump_line_sprites(ppu, line, line_sprites, n_sprites); |
|
|
|
|
|
|
|
if (ppu->mask & ppu_Mask_Back) { |
|
|
|
SDL_BlitSurface(data->background, &src_rect, |
|
|
|
@@ -798,7 +811,7 @@ static void render_scanline(nes_ppu* ppu, int line, |
|
|
|
|
|
|
|
if (ppu->mask & ppu_Mask_Sprite) { |
|
|
|
memset(foreground, 0xFFU, nes_ppu_render_w); |
|
|
|
render_line_sprites(ppu, foreground, line, 0, |
|
|
|
render_line_sprites(ppu, foreground, line, background, |
|
|
|
line_sprites, n_sprites); |
|
|
|
SDL_BlitSurface(data->foreground, &src_rect, |
|
|
|
data->target, &dst_rect); |
|
|
|
|