From 6f63478cf43d4c0b77cabe3f76710f2b9f0c912e Mon Sep 17 00:00:00 2001 From: Peter Fors Date: Wed, 2 Apr 2025 12:19:38 +0200 Subject: Itsa twerking. --- ppu.c | 61 +++++++++++++++++++++++++++++++------------------------------ 1 file changed, 31 insertions(+), 30 deletions(-) (limited to 'ppu.c') 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); } -- cgit v1.2.3