summaryrefslogtreecommitdiff
path: root/ppu.c
diff options
context:
space:
mode:
authorPeter Fors <peter.fors@mindkiller.com>2025-04-03 20:02:00 +0200
committerPeter Fors <peter.fors@mindkiller.com>2025-04-03 20:02:00 +0200
commit6274071e3857c1640cc5aef804cb86509ab312f9 (patch)
tree1a4e56b3c3b4bfb4d8f0d2f588487d6e227c3b27 /ppu.c
parent971e51eebbf088f1ac590da1fc57e803eb1ee8cf (diff)
Move to glfw
Diffstat (limited to 'ppu.c')
-rw-r--r--ppu.c70
1 files changed, 46 insertions, 24 deletions
diff --git a/ppu.c b/ppu.c
index 4246e20..2c993c9 100644
--- a/ppu.c
+++ b/ppu.c
@@ -18,7 +18,6 @@ static void ppu_sprite_shift(struct nes_state *state) {
}
}
-
static void ppu_reset(struct nes_state *state) {
struct ppu_state *ppu = &state->ppu;
memset(ppu, 0, sizeof(struct ppu_state));
@@ -44,11 +43,11 @@ static uint32_t ppu_resolve_ciram(struct nes_state *state, uint32_t addr) {
static uint8_t ppu_ciram_read(struct nes_state *state, uint32_t addr) {
- return state->ppu.ciram[ppu_resolve_ciram(state, addr)];
+ return state->ciram[ppu_resolve_ciram(state, addr)];
}
static void ppu_ciram_write(struct nes_state *state, uint32_t addr, uint8_t value) {
- state->ppu.ciram[ppu_resolve_ciram(state, addr)] = value;
+ state->ciram[ppu_resolve_ciram(state, addr)] = value;
}
static void ppu_write_2000(struct nes_state *state, uint8_t value) {
@@ -150,7 +149,41 @@ static uint8_t ppu_read_2007(struct nes_state *state) {
return result;
}
+#if 1
+static void ppu_evaluate_sprites(struct nes_state *state) {
+ struct ppu_state *ppu = &state->ppu;
+ uint8_t sprite_height = (ppu->reg_ctrl & 0x20) ? 16 : 8;
+ uint8_t n = 0;
+
+ uint8_t *src = ppu->oam;
+ uint8_t *dst = ppu->secondary_oam;
+ for(uint8_t i = 0; i < 64; i++) {
+ uint8_t y = src[0];
+ int32_t row = (int32_t)ppu->scanline - y;
+
+ if(row >= 0 && row < sprite_height) {
+ if(n < 8) {
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ dst[3] = src[3];
+ ppu->sprite_indexes[n] = i;
+ ppu->sprite_zero_hit_possible |= (i == 0) ? 1 : 0;
+
+ dst += 4;
+ n++;
+ } else {
+ ppu->reg_status |= 0x20;
+ break;
+ }
+ }
+ src += 4;
+ }
+
+ ppu->sprite_count = n;
+}
+#else
static void ppu_evaluate_sprites(struct nes_state *state) {
struct ppu_state *ppu = &state->ppu;
uint8_t sprite_height = (ppu->reg_ctrl & 0x20) ? 16 : 8;
@@ -182,6 +215,7 @@ static void ppu_evaluate_sprites(struct nes_state *state) {
ppu->sprite_count = n;
}
+#endif
static void ppu_fetch_sprite_patterns(struct nes_state *state) {
struct ppu_state *ppu = &state->ppu;
@@ -238,9 +272,9 @@ static void ppu_render_pixel(struct nes_state *state) {
uint32_t x = ppu->dot - 1;
uint32_t y = ppu->scanline;
- if(x >= 256 || y >= 240) {
- return;
- }
+ // if(x >= 256 || y >= 240) {
+ // return;
+ // }
uint32_t bit = 0x8000 >> ppu->fine_x;
@@ -287,11 +321,10 @@ static void ppu_render_pixel(struct nes_state *state) {
final_color = ppu->palette[(bg_palette << 2) | bg_pixel];
}
}
- assert(y*256+x <= 256*240);
ppu->pixels[y * 256 + x] = final_color;
}
-__attribute__((flatten))
+__attribute__((hot, flatten))
static void ppu_tick(struct nes_state *state) {
struct ppu_state *ppu = &state->ppu;
@@ -390,12 +423,6 @@ static void ppu_tick(struct nes_state *state) {
ppu->vram_addr = (ppu->vram_addr & ~0x7be0) | (ppu->temp_addr & 0x7be0);
}
-// if(scanline == 261 && dot >= 280 && dot <= 304) {
-// printf("Scroll Copy (V): SL:%d DOT:%d vram_addr=%04x temp_addr=%04x\n", scanline, dot, ppu->vram_addr, ppu->temp_addr);
-// ppu->vram_addr = (ppu->vram_addr & 0x041f) | (ppu->temp_addr & 0x7be0);
-// }
-
-
if(dot == 257 && scanline < 240) {
ppu_evaluate_sprites(state);
}
@@ -437,26 +464,21 @@ static void ppu_dma_4014(struct nes_state *state, uint8_t page) {
uint32_t base = page << 8;
// Add 1 or 2 idle cycles depending on current CPU cycle
- uint8_t idle_cycles = (state->cycle & 1) ? 1 : 2;
+ uint8_t idle_cycles = (state->cycles & 1) ? 1 : 2;
for(uint8_t i = 0; i < idle_cycles; i++) {
- state->cycle++;
+ state->cycles++;
ppu_tick(state); ppu_tick(state); ppu_tick(state);
}
for(uint32_t i = 0; i < 256; i++) {
uint32_t addr = base + i;
- // First CPU cycle (read, ticks only)
- state->cycle++;
+ state->cycles++;
ppu_tick(state); ppu_tick(state); ppu_tick(state);
-
- // Perform read
uint8_t value = memory_read_dma(state, addr);
- // Second CPU cycle (write)
- ppu_write_2004(state, value);
-
- state->cycle++;
+ state->cycles++;
ppu_tick(state); ppu_tick(state); ppu_tick(state);
+ ppu_write_2004(state, value);
}
} \ No newline at end of file