diff options
Diffstat (limited to 'mknes_ppu.c')
| -rw-r--r-- | mknes_ppu.c | 149 |
1 files changed, 45 insertions, 104 deletions
diff --git a/mknes_ppu.c b/mknes_ppu.c index 64d6821..92b22fc 100644 --- a/mknes_ppu.c +++ b/mknes_ppu.c @@ -25,7 +25,7 @@ static void ppu_reset(struct nes_state *state) { } __attribute__((hot, flatten)) -static inline void ppu_evaluate_sprites(struct nes_state *state) { +static inline void ppu_evaluate_sprites(struct nes_state *state, uint32_t scanline) { struct ppu_state *restrict ppu = &state->ppu; uint8_t sprite_height = (ppu->reg_ctrl & 0x20) ? 16 : 8; uint8_t n = 0; @@ -36,7 +36,7 @@ static inline void ppu_evaluate_sprites(struct nes_state *state) { for(uint8_t i = 0; i < 64; i++, src += 4) { uint8_t y = src[0]; - int32_t row = (int32_t)ppu->scanline - y; + int32_t row = (int32_t)scanline - y; if(row >= 0 && row < sprite_height) { if(n < 8) { @@ -63,7 +63,7 @@ static inline void ppu_evaluate_sprites(struct nes_state *state) { } __attribute__((hot)) -static inline void ppu_fetch_sprite_patterns(struct nes_state *state, uint32_t scanline) { +static inline void ppu_fetch_sprite_patterns(struct nes_state * restrict state, uint32_t scanline) { struct ppu_state *restrict ppu = &state->ppu; uint8_t * restrict sec_oam = ppu->secondary_oam; @@ -110,8 +110,8 @@ static inline void ppu_fetch_sprite_patterns(struct nes_state *state, uint32_t s } -__attribute__((always_inline, hot)) -static inline void ppu_render_pixel(struct nes_state *state, uint32_t x, uint32_t y) { +__attribute__((always_inline, hot, optimize("no-jump-tables"))) +static inline void ppu_render_pixel(struct nes_state * restrict state, uint32_t x, uint32_t y) { struct ppu_state *restrict ppu = &state->ppu; uint16_t bit = 0x8000 >> ppu->fine_x; @@ -138,100 +138,42 @@ static inline void ppu_render_pixel(struct nes_state *state, uint32_t x, uint32_ uint8_t bg_pixel = ((p1 << 1) | p0) & bg_mask; uint8_t bg_palette = ((a1 << 1) | a0) & bg_mask; - // Sprite - - if(sp_mask && ppu->sprite_count) { - switch(ppu->sprite_count) { - case 8: { - if(!ppu->sprites[7].position) { - sp_pixel = (((ppu->sprites[7].shift_hi & 0x80) >> 6) | ((ppu->sprites[7].shift_lo & 0x80) >> 7)); - if(sp_pixel) { - sp_prio = ppu->sprites[7].priority; - sp_palette = ppu->sprites[7].palette; - break; - } - } - } __attribute__((fallthrough)); - - case 7: { - if(!ppu->sprites[6].position) { - sp_pixel = (((ppu->sprites[6].shift_hi & 0x80) >> 6) | ((ppu->sprites[6].shift_lo & 0x80) >> 7)); - if(sp_pixel) { - sp_prio = ppu->sprites[6].priority; - sp_palette = ppu->sprites[6].palette; - break; - } - } - } __attribute__((fallthrough)); - - case 6: { - if(!ppu->sprites[5].position) { - sp_pixel = (((ppu->sprites[5].shift_hi & 0x80) >> 6) | ((ppu->sprites[5].shift_lo & 0x80) >> 7)); - if(sp_pixel) { - sp_prio = ppu->sprites[5].priority; - sp_palette = ppu->sprites[5].palette; - break; - } - } - } __attribute__((fallthrough)); - - case 5: { - if(!ppu->sprites[4].position) { - sp_pixel = (((ppu->sprites[4].shift_hi & 0x80) >> 6) | ((ppu->sprites[4].shift_lo & 0x80) >> 7)); - if(sp_pixel) { - sp_prio = ppu->sprites[4].priority; - sp_palette = ppu->sprites[4].palette; - break; - } - } - } __attribute__((fallthrough)); - - case 4: { - if(!ppu->sprites[3].position) { - sp_pixel = (((ppu->sprites[3].shift_hi & 0x80) >> 6) | ((ppu->sprites[3].shift_lo & 0x80) >> 7)); - if(sp_pixel) { - sp_prio = ppu->sprites[3].priority; - sp_palette = ppu->sprites[3].palette; - break; - } - } - } __attribute__((fallthrough)); - - case 3: { - if(!ppu->sprites[2].position) { - sp_pixel = (((ppu->sprites[2].shift_hi & 0x80) >> 6) | ((ppu->sprites[2].shift_lo & 0x80) >> 7)); - if(sp_pixel) { - sp_prio = ppu->sprites[2].priority; - sp_palette = ppu->sprites[2].palette; - break; - } - } - } __attribute__((fallthrough)); - - case 2: { - if(!ppu->sprites[1].position) { - sp_pixel = (((ppu->sprites[1].shift_hi & 0x80) >> 6) | ((ppu->sprites[1].shift_lo & 0x80) >> 7)); - if(sp_pixel) { - sp_prio = ppu->sprites[1].priority; - sp_palette = ppu->sprites[1].palette; - break; - } - } - } __attribute__((fallthrough)); - - case 1: { - if(!ppu->sprites[0].position) { - sp_pixel = (((ppu->sprites[0].shift_hi & 0x80) >> 6) | ((ppu->sprites[0].shift_lo & 0x80) >> 7)); - if(sp_pixel) { - sp_prio = ppu->sprites[0].priority; - sp_palette = ppu->sprites[0].palette; - sp_zero = ppu->sprite_zero_in_range; // Only slot 0 can be sprite 0 - break; - } - } - } - } + // Sprites +#define SPRITE_STEP(N) do { \ + if(!ppu->sprites[(N)].position) { \ + sp_pixel = (((ppu->sprites[(N)].shift_hi & 0x80) >> 6) | ((ppu->sprites[(N)].shift_lo & 0x80) >> 7)); \ + if(sp_pixel) { \ + sp_prio = ppu->sprites[(N)].priority; \ + sp_palette = ppu->sprites[(N)].palette; \ + if((N) == 0) { \ + sp_zero = ppu->sprite_zero_in_range; \ + } \ + goto sprite_done; \ + } \ + } \ +} while (0) + + if(sp_mask && ppu->sprite_count > 0) { + if(ppu->sprite_count == 1) goto sprite_1; + if(ppu->sprite_count == 2) goto sprite_2; + if(ppu->sprite_count == 3) goto sprite_3; + if(ppu->sprite_count == 4) goto sprite_4; + if(ppu->sprite_count == 5) goto sprite_5; + if(ppu->sprite_count == 6) goto sprite_6; + if(ppu->sprite_count == 7) goto sprite_7; + if(ppu->sprite_count == 8) goto sprite_8; + +sprite_8: SPRITE_STEP(7); +sprite_7: SPRITE_STEP(6); +sprite_6: SPRITE_STEP(5); +sprite_5: SPRITE_STEP(4); +sprite_4: SPRITE_STEP(3); +sprite_3: SPRITE_STEP(2); +sprite_2: SPRITE_STEP(1); +sprite_1: SPRITE_STEP(0); } +sprite_done:; + // Final pixel composition uint8_t bg_index = (bg_palette << 2) + bg_pixel; @@ -266,7 +208,7 @@ static void ppu_tick(struct nes_state *state) { if(scanline <= 239) { if(dot == 65) { - ppu_evaluate_sprites(state); // Evaluate sprites early, sets overflow immediately + ppu_evaluate_sprites(state, scanline); // Evaluate sprites early, sets overflow immediately } if(dot >= 1 && dot <= 256) { @@ -371,7 +313,7 @@ stupid: if(ppu->reg_mask & 0x10) { if(scanline == 261) { if(dot == 65) { - ppu_evaluate_sprites(state); // Evaluate sprites early + ppu_evaluate_sprites(state, scanline); // Evaluate sprites early } if(dot >= 1 && dot <= 256) { @@ -424,6 +366,7 @@ stupid2: if(ppu->reg_mask & 0x10) { ppu->bg_shift_attrib_low <<= 1; ppu->bg_shift_attrib_high <<= 1; + switch(dot % 8) { case 1: { uint32_t nt_addr = 0x2000 | (ppu->vram_addr & 0x0fff); @@ -512,9 +455,7 @@ stupid2: if(ppu->reg_mask & 0x10) { if(state->mapper_function.tick) { state->mapper_function.tick(state); } - - ppu->dot = dot; - ppu->scanline = scanline; - } + ppu->dot = dot; + ppu->scanline = scanline; } |
