From 5409798e800b6deb5d5874401a2925d1e18d8bd3 Mon Sep 17 00:00:00 2001 From: Peter Fors Date: Mon, 7 Apr 2025 15:55:23 +0200 Subject: almost back to normal after bytestream excursion --- ppu.c | 169 ++++++------------------------------------------------------------ 1 file changed, 14 insertions(+), 155 deletions(-) (limited to 'ppu.c') diff --git a/ppu.c b/ppu.c index d2772d8..2015b1d 100644 --- a/ppu.c +++ b/ppu.c @@ -10,119 +10,11 @@ static uint8_t __attribute__((aligned(64))) ppu_bitreverse_lut[256] = { #undef R4 #undef R6 -static uint8_t memory_read_dma(struct nes_state *state, uint32_t offset); - static void ppu_reset(struct nes_state *state) { struct ppu_state *ppu = &state->ppu; memset(ppu, 0, sizeof(struct ppu_state)); } -__attribute__((always_inline, hot)) -static inline void ppu_write(struct nes_state *state, uint32_t offset, uint8_t value) { - struct ppu_state *ppu = &state->ppu; - - switch(offset & 7) { - case 0: { // 2000 - ppu->reg_ctrl = value; - ppu->temp_addr = (ppu->temp_addr & 0xf3ff) | ((value & 0x03) << 10); - ppu->open_bus = value; - } break; - - case 1: { // 2001 - ppu->reg_mask = value; - ppu->open_bus = value; - } break; - - case 3: { // 2003 - ppu->oam_addr = value; - } break; - - case 4: { // 2004 - ppu->oam[ppu->oam_addr] = value; - ppu->oam_addr++; - } break; - - case 5: { // 2005 - if(ppu->write_latch == 0) { - ppu->fine_x = value & 0x07; - ppu->temp_addr = (ppu->temp_addr & ~0x001f) | (value >> 3); - ppu->write_latch = 1; - } else { - ppu->temp_addr = (ppu->temp_addr & ~0x73e0) | ((value & 0x07) << 12) | ((value & 0xf8) << 2); - ppu->write_latch = 0; - } - ppu->open_bus = value; - } break; - - case 6: { // 2006 - if(ppu->write_latch == 0) { - ppu->temp_addr = (ppu->temp_addr & 0x00ff) | ((value & 0x3f) << 8); - ppu->write_latch = 1; - } else { - ppu->temp_addr = (ppu->temp_addr & 0xff00) | value; - ppu->vram_addr = ppu->temp_addr; - ppu->write_latch = 0; - } - ppu->open_bus = value; - } break; - - case 7: { // 2007 - uint32_t addr = ppu->vram_addr & 0x3fff; - if(addr < 0x2000) { - state->mapper.chr_write(state, addr, value); - } else if(addr < 0x3f00) { - state->mapper.ciram_write(state, addr, value); - } else if(addr < 0x4000) { - uint32_t pal_addr = addr & 0x1f; - if((pal_addr & 3) == 0) { - pal_addr &= ~0x10; - } - ppu->palette[pal_addr] = value; - } - ppu->vram_addr += (ppu->reg_ctrl & 0x04) ? 32 : 1; - } break; - } -} - -__attribute__((always_inline, hot)) -static inline uint8_t ppu_read(struct nes_state *state, uint32_t offset) { - struct ppu_state *ppu = &state->ppu; - uint8_t result = ppu->open_bus; - - switch(offset & 7) { - case 2: { // 2002 - result = ppu->reg_status; - ppu->reg_status &= ~0x80; - ppu->write_latch = 0; - } break; - - case 4: { // 2004 - result = ppu->oam[ppu->oam_addr]; - } break; - - case 7: { // 2007 - uint32_t addr = ppu->vram_addr & 0x3fff; - result = 0; - - if(addr < 0x2000) { - result = ppu->vram_read_buffer; - ppu->vram_read_buffer = state->mapper.chr_read(state, addr); - } else if(addr < 0x3f00) { - result = state->mapper.ciram_read(state, addr); - } else if(addr < 0x4000) { - uint32_t pal_addr = addr & 0x1f; - if((pal_addr & 0x13) == 0x10) { - pal_addr &= ~0x10; - } - result = ppu->palette[pal_addr]; - } - - ppu->vram_addr += (ppu->reg_ctrl & 0x04) ? 32 : 1; - } break; - } - ppu->open_bus = result; - return result; -} __attribute__((always_inline, hot)) static inline void ppu_evaluate_sprites(struct nes_state *state) { @@ -326,31 +218,27 @@ static void ppu_tick(struct nes_state *state) { case 1: { uint32_t nt_addr = 0x2000 | (ppu->vram_addr & 0x0fff); ppu->bg_next_tile_id = state->mapper.ciram_read(state, nt_addr); - break; - } + } 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 = state->mapper.ciram_read(state, attr_addr & 0x0fff); uint8_t shift = ((ppu->vram_addr >> 4) & 4) | (ppu->vram_addr & 2); ppu->bg_next_tile_attrib = (attr >> shift) & 3; - break; - } + } break; case 5: { uint32_t base = (ppu->reg_ctrl & 0x10) ? 0x1000 : 0x0000; uint32_t tile = ppu->bg_next_tile_id; uint32_t fine_y = (ppu->vram_addr >> 12) & 7; uint32_t addr_lsb = (base + tile * 16 + fine_y) & 0x1fff; ppu->bg_next_tile_lsb = state->mapper.chr_read(state, addr_lsb); - break; - } + } break; case 7: { uint32_t base = (ppu->reg_ctrl & 0x10) ? 0x1000 : 0x0000; uint32_t tile = ppu->bg_next_tile_id; uint32_t fine_y = (ppu->vram_addr >> 12) & 7; uint32_t addr_msb = (base + tile * 16 + fine_y + 8) & 0x1fff; ppu->bg_next_tile_msb = state->mapper.chr_read(state, addr_msb); - break; - } + } break; case 0: { ppu->bg_shift_pattern_low = (ppu->bg_shift_pattern_low & 0xff00) | ppu->bg_next_tile_lsb; ppu->bg_shift_pattern_high = (ppu->bg_shift_pattern_high & 0xff00) | ppu->bg_next_tile_msb; @@ -365,9 +253,7 @@ static void ppu_tick(struct nes_state *state) { } else { ppu->vram_addr++; } - - break; - } + } break; } } break; @@ -427,31 +313,31 @@ static void ppu_tick(struct nes_state *state) { case 1: { uint32_t nt_addr = 0x2000 | (ppu->vram_addr & 0x0fff); ppu->bg_next_tile_id = state->mapper.ciram_read(state, nt_addr); - break; - } + } 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 = state->mapper.ciram_read(state, attr_addr & 0x0fff); uint8_t shift = ((ppu->vram_addr >> 4) & 4) | (ppu->vram_addr & 2); ppu->bg_next_tile_attrib = (attr >> shift) & 3; - break; - } + } break; + case 5: { uint32_t base = (ppu->reg_ctrl & 0x10) ? 0x1000 : 0x0000; uint32_t tile = ppu->bg_next_tile_id; uint32_t fine_y = (ppu->vram_addr >> 12) & 7; uint32_t addr_lsb = (base + tile * 16 + fine_y) & 0x1fff; ppu->bg_next_tile_lsb = state->mapper.chr_read(state, addr_lsb); - break; - } + } break; + case 7: { uint32_t base = (ppu->reg_ctrl & 0x10) ? 0x1000 : 0x0000; uint32_t tile = ppu->bg_next_tile_id; uint32_t fine_y = (ppu->vram_addr >> 12) & 7; uint32_t addr_msb = (base + tile * 16 + fine_y + 8) & 0x1fff; ppu->bg_next_tile_msb = state->mapper.chr_read(state, addr_msb); - break; - } + } break; + case 0: { ppu->bg_shift_pattern_low = (ppu->bg_shift_pattern_low & 0xff00) | ppu->bg_next_tile_lsb; ppu->bg_shift_pattern_high = (ppu->bg_shift_pattern_high & 0xff00) | ppu->bg_next_tile_msb; @@ -467,8 +353,7 @@ static void ppu_tick(struct nes_state *state) { ppu->vram_addr++; } - break; - } + } break; } } break; @@ -521,29 +406,3 @@ static void ppu_tick(struct nes_state *state) { } } -__attribute__((always_inline, hot)) -static inline 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->cycles & 1) ? 1 : 2; - for(uint8_t i = 0; i < idle_cycles; i++) { - state->cycles++; - ppu_tick(state); - } - - for(uint32_t i = 0; i < 256; i++) { - uint32_t addr = base + i; - - state->cycles++; - ppu_tick(state); - uint8_t value = memory_read_dma(state, addr); - - state->cycles++; - ppu_tick(state); - // ppu_write_2004(state, value); - ppu_write(state, 4, value); - } -} - - -- cgit v1.2.3