summaryrefslogtreecommitdiff
path: root/mknes_ppu.c
diff options
context:
space:
mode:
Diffstat (limited to 'mknes_ppu.c')
-rw-r--r--mknes_ppu.c149
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;
}