summaryrefslogtreecommitdiff
path: root/ppu.c
diff options
context:
space:
mode:
authorPeter Fors <peter.fors@mindkiller.com>2025-06-08 17:32:05 +0200
committerPeter Fors <peter.fors@mindkiller.com>2025-06-08 17:32:05 +0200
commit412b2ef851516c1de8ba5006ddd284192cbcaf9b (patch)
treee8b68d60125bf89e375ec9acc4e7833825abbfaa /ppu.c
parent6dd73982c514445c4d2a4787c37666d0812a3dad (diff)
tests
Diffstat (limited to 'ppu.c')
-rw-r--r--ppu.c75
1 files changed, 39 insertions, 36 deletions
diff --git a/ppu.c b/ppu.c
index e0fce44..3b6200e 100644
--- a/ppu.c
+++ b/ppu.c
@@ -60,20 +60,23 @@ static inline void ppu_evaluate_sprites(struct nes_state *state) {
__attribute__((hot))
static inline void ppu_fetch_sprite_patterns(struct nes_state *state) {
struct ppu_state *restrict ppu = &state->ppu;
- uint32_t addr;
- uint32_t bank;
- uint8_t lsb;
- uint8_t msb;
uint8_t * restrict s = ppu->secondary_oam;
uint8_t height = (ppu->reg_ctrl & 0x20) ? 16 : 8;
+ uint8_t ctrl = ppu->reg_ctrl;
+ uint8_t scanline = ppu->scanline;
+ uint32_t sprite_pattern_table_base = (ctrl & 0x08) << 9;
for(uint8_t i = 0; i < ppu->sprite_count; i++) {
- uint8_t y = s[0], tile = s[1], attr = s[2], x = s[3];
- uint8_t row = ppu->scanline - y;
+ uint8_t y = s[0];
+ uint8_t tile = s[1];
+ uint8_t attr = s[2];
+ uint8_t x = s[3];
+ uint8_t row = scanline - y;
row = (attr & 0x80) ? height - 1 - row : row;
+ uint32_t bank, addr;
if(height == 16) {
bank = (tile & 1) << 12;
tile &= 0xfe;
@@ -81,29 +84,29 @@ static inline void ppu_fetch_sprite_patterns(struct nes_state *state) {
tile++;
row -= 8;
}
- } else {
- bank = (ppu->reg_ctrl & 0x08) << 9;
- }
- addr = bank + tile * 16 + row;
+ addr = bank + tile * 16 + row;
- if(attr & 0x40) {
- lsb = ppu_bitreverse_lut[state->mapper_function.chr_read(state, addr)];
- msb = ppu_bitreverse_lut[state->mapper_function.chr_read(state, addr + 8)];
} else {
- lsb = state->mapper_function.chr_read(state, addr);
- msb = state->mapper_function.chr_read(state, addr + 8);
+ addr = sprite_pattern_table_base + tile * 16 + row;
}
+ uint8_t val_lo = state->mapper_function.chr_read(state, addr);
+ uint8_t val_hi = state->mapper_function.chr_read(state, addr + 8);
+
+ uint8_t rev = -(!!(attr & 0x40));
+ uint8_t lsb = (rev & ppu_bitreverse_lut[val_lo]) | (~rev & val_lo);
+ uint8_t msb = (rev & ppu_bitreverse_lut[val_hi]) | (~rev & val_hi);
+
ppu->sprite_shift_lo[i] = lsb;
ppu->sprite_shift_hi[i] = msb;
-
ppu->sprite_positions[i] = x;
ppu->sprite_priorities[i] = attr & 0x20;
+
s += 4;
}
}
-__attribute__((always_inline, hot, flatten))
+__attribute__((always_inline, hot))
static inline void ppu_render_pixel(struct nes_state *state) {
struct ppu_state *restrict ppu = &state->ppu;
@@ -112,8 +115,6 @@ static inline void ppu_render_pixel(struct nes_state *state) {
uint16_t bit = 0x8000 >> ppu->fine_x;
- uint8_t bg_pixel = 0;
- uint8_t bg_palette = 0;
uint8_t sp_pixel = 0;
uint8_t sp_palette = 0;
uint8_t sp_prio = 0;
@@ -133,23 +134,25 @@ static inline void ppu_render_pixel(struct nes_state *state) {
uint8_t a0 = !!(ppu->bg_shift_attrib_low & bit);
uint8_t a1 = !!(ppu->bg_shift_attrib_high & bit);
- bg_pixel = ((p1 << 1) | p0) & bg_mask;
- bg_palette = ((a1 << 1) | a0) & bg_mask;
+ uint8_t bg_pixel = ((p1 << 1) | p0) & bg_mask;
+ uint8_t bg_palette = ((a1 << 1) | a0) & bg_mask;
// Sprite
- for(uint8_t i = 0; i < ppu->sprite_count; i++) {
- if(ppu->sprite_positions[i]) continue;
+ if(sp_mask) {
+ for(uint8_t i = 0; i < ppu->sprite_count; i++) {
+ if(ppu->sprite_positions[i]) continue;
- uint8_t lo = ppu->sprite_shift_lo[i];
- uint8_t hi = ppu->sprite_shift_hi[i];
- sp_pixel = (((hi & 0x80) >> 6) | ((lo & 0x80) >> 7)) & sp_mask;
+ uint8_t lo = ppu->sprite_shift_lo[i];
+ uint8_t hi = ppu->sprite_shift_hi[i];
+ sp_pixel = (((hi & 0x80) >> 6) | ((lo & 0x80) >> 7));
- if(!sp_pixel) continue;
+ if(!sp_pixel) continue;
- sp_palette = ppu->secondary_oam[i * 4 + 2] & 3;
- sp_prio = ppu->sprite_priorities[i];
- sp_zero = (ppu->sprite_indexes[i] == 0);
- break;
+ sp_palette = ppu->secondary_oam[i * 4 + 2] & 3;
+ sp_prio = ppu->sprite_priorities[i];
+ sp_zero = (ppu->sprite_indexes[i] == 0);
+ break;
+ }
}
// Final pixel composition
@@ -170,8 +173,8 @@ static inline void ppu_render_pixel(struct nes_state *state) {
state->pixels[y * 256 + x] = ppu->palette[palette_index]; // NOTE(peter): Add color_emphasis bits (expand palette to 8x).
}
-__attribute__((hot, flatten))
-__attribute__((optimize("no-jump-tables")))
+
+__attribute__((hot, optimize("no-jump-tables")))
static inline void ppu_tick(struct nes_state *state) {
struct ppu_state *restrict ppu = &state->ppu;
@@ -208,10 +211,10 @@ static inline void ppu_tick(struct nes_state *state) {
case 1 ... 255: // fallthrough: this is 1->256
ppu_render_pixel(state);
- __attribute__((fallthrough));
+ __attribute__((fallthrough)); // fallthrough: the code below has to run 1->256 + 321->336
+
+ case 321 ... 336: { // Rendering and tile fetch;
- case 321 ... 336: { // fallthrough: the code below has to run 1->256 + 321->336
- // Rendering and tile fetch goes here
if(ppu->reg_mask & 0x10) {
for(uint32_t i = 0; i < ppu->sprite_count; i++) {
if(ppu->sprite_positions[i] > 0) {