summaryrefslogtreecommitdiff
path: root/ppu.c
diff options
context:
space:
mode:
Diffstat (limited to 'ppu.c')
-rw-r--r--ppu.c61
1 files changed, 31 insertions, 30 deletions
diff --git a/ppu.c b/ppu.c
index 1c34381..4246e20 100644
--- a/ppu.c
+++ b/ppu.c
@@ -22,23 +22,27 @@ 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));
-
}
static uint32_t ppu_resolve_ciram(struct nes_state *state, uint32_t addr) {
- // Apply mirroring logic to address in $2000–$2FFF range
addr &= 0x0fff;
switch(state->ines.mirroring) {
- case MIRROR_VERTICAL:
- return (addr & 0x0800) | (addr & 0x03ff); // $2000/$2800 → $0000, $2400/$2C00 → $0400
- case MIRROR_HORIZONTAL:
- return ((addr & 0x0400) >> 1) | (addr & 0x03ff); // $2000/$2400 → $0000, $2800/$2C00 → $0400
- default:
- return addr & 0x07ff; // For now, 4-screen = direct
+ case MIRROR_VERTICAL: {
+ // $2000/$2800 → $0000, $2400/$2C00 → $0400
+ return (addr & 0x0400) | (addr & 0x03ff);
+ }
+ case MIRROR_HORIZONTAL: {
+ // $2000/$2400 → $0000, $2800/$2C00 → $0400
+ return ((addr & 0x0800) >> 1) | (addr & 0x03ff);
+ }
+ default: {
+ return addr & 0x07ff;
+ }
}
}
+
static uint8_t ppu_ciram_read(struct nes_state *state, uint32_t addr) {
return state->ppu.ciram[ppu_resolve_ciram(state, addr)];
}
@@ -47,7 +51,6 @@ static void ppu_ciram_write(struct nes_state *state, uint32_t addr, uint8_t valu
state->ppu.ciram[ppu_resolve_ciram(state, addr)] = value;
}
-
static void ppu_write_2000(struct nes_state *state, uint8_t value) {
struct ppu_state *ppu = &state->ppu;
ppu->reg_ctrl = value;
@@ -96,12 +99,10 @@ static void ppu_write_2006(struct nes_state *state, uint8_t value) {
static void ppu_write_2007(struct nes_state *state, uint8_t value) {
struct ppu_state *ppu = &state->ppu;
uint32_t addr = ppu->vram_addr & 0x3fff;
-
if(addr < 0x2000) {
// CHR-RAM, skip
} else if(addr < 0x3f00) {
- uint32_t mirrored_addr = addr & 0x0fff;
- ppu->ciram[mirrored_addr & 0x7ff] = value;
+ ppu_ciram_write(state, addr, value);
} else if(addr < 0x4000) {
uint32_t pal_addr = addr & 0x1f;
if((pal_addr & 0x13) == 0x10) {
@@ -132,31 +133,24 @@ static uint8_t ppu_read_2007(struct nes_state *state) {
uint32_t addr = ppu->vram_addr & 0x3fff;
uint8_t result = 0;
- // Read from CHR-RAM (CHR-ROM in PPU)
if(addr < 0x2000) {
result = ppu->vram_read_buffer;
ppu->vram_read_buffer = state->chrrom[addr];
} else if(addr < 0x3f00) {
- // Read from CIRAM (internal VRAM)
- uint32_t mirrored_addr = addr & 0x0fff;
- if(state->ines.mirroring == 2) {
- mirrored_addr |= (addr & 0x0800) ? 0x400 : 0x000; // Handle 4-screen mirroring
- }
- result = ppu->ciram[mirrored_addr & 0x7ff];
+ result = ppu_ciram_read(state, addr);
} else if(addr < 0x4000) {
- // Read from palette
uint32_t pal_addr = addr & 0x1f;
if((pal_addr & 0x13) == 0x10) {
- pal_addr &= ~0x10; // Skip over the unused area of the palette
+ pal_addr &= ~0x10;
}
result = ppu->palette[pal_addr];
}
- // Update VRAM address based on control register
ppu->vram_addr += (ppu->reg_ctrl & 0x04) ? 32 : 1;
return result;
}
+
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;
@@ -297,6 +291,7 @@ static void ppu_render_pixel(struct nes_state *state) {
ppu->pixels[y * 256 + x] = final_color;
}
+__attribute__((flatten))
static void ppu_tick(struct nes_state *state) {
struct ppu_state *ppu = &state->ppu;
@@ -322,12 +317,12 @@ static void ppu_tick(struct nes_state *state) {
switch(dot % 8) {
case 1: {
uint32_t nt_addr = 0x2000 | (ppu->vram_addr & 0x0fff);
- ppu->bg_next_tile_id = ppu->ciram[nt_addr & 0x07ff];
+ ppu->bg_next_tile_id = ppu_ciram_read(state, nt_addr);
break;
}
case 3: {
uint32_t attr_addr = 0x23c0 | (ppu->vram_addr & 0x0c00) | ((ppu->vram_addr >> 4) & 0x38) | ((ppu->vram_addr >> 2) & 0x07);
- uint8_t attr = ppu->ciram[attr_addr & 0x07ff];
+ uint8_t attr = ppu_ciram_read(state, attr_addr);
uint8_t shift = ((ppu->vram_addr >> 4) & 4) | (ppu->vram_addr & 2);
ppu->bg_next_tile_attrib = (attr >> shift) & 3;
break;
@@ -356,12 +351,12 @@ static void ppu_tick(struct nes_state *state) {
ppu->bg_shift_attrib_low = (ppu->bg_shift_attrib_low & 0xff00) | ((a & 1) ? 0xff : 0x00);
ppu->bg_shift_attrib_high = (ppu->bg_shift_attrib_high & 0xff00) | ((a & 2) ? 0xff : 0x00);
- if((ppu->vram_addr & 0x001f) == 31) {
- ppu->vram_addr &= ~0x001f;
- ppu->vram_addr ^= 0x0400;
- } else {
- ppu->vram_addr++;
- }
+ if((ppu->vram_addr & 0x001f) == 31) {
+ ppu->vram_addr &= ~0x001f;
+ ppu->vram_addr ^= 0x0400;
+ } else {
+ ppu->vram_addr++;
+ }
break;
}
@@ -395,6 +390,12 @@ 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);
}