diff options
Diffstat (limited to 'ppu.c')
-rw-r--r-- | ppu.c | 62 |
1 files changed, 62 insertions, 0 deletions
@@ -2,6 +2,38 @@ struct ppu ppu = {0}; +static void +vram_addr_inc(void) +{ + ppu.regs.v += (ppu.ctrl.inc_mode) ? 32 : 1; +} + +static uint16_t +vram_addr_mirror(uint16_t addr) +{ + uint8_t nametable; + + addr &= 0x2fff; + addr -= 0x2000; + nametable = addr / 0x400; + + switch (ppu.rom->mirror) { + case M_HORIZONTAL: + if (nametable == 1 || nametable == 2) + return addr - 0x400; + else if (nametable == 3) + return addr - 0x800; + break; + case M_VERTICAL: + if (nametable == 2 || nametable == 3) + return addr - 0x800; + default: + break; + }; + + return addr; +} + void ppu_tick(void) { @@ -17,6 +49,36 @@ ppu_tick(void) uint8_t ppu_read(uint16_t addr) { + uint8_t tmp; + + switch (addr) { + case 0x2002: + tmp = (ppu.status.vblank << 7) + | (ppu.status.sprite0_hit << 6) + | (ppu.status.sprite_overflow << 5); + + ppu.status.vblank = 0; + ppu.regs.w = 0; + + return tmp; + case 0x2004: + return ppu.oam[ppu.oam_addr]; + case 0x2007: + vram_addr_inc(); + + if (addr <= 0x1fff) { + tmp = ppu.last_read; + ppu.last_read = ppu.rom->chr_rom[ppu.regs.v]; + return tmp; + } else if (addr <= 0x2fff) { + tmp = ppu.last_read; + ppu.last_read = ppu.vram[vram_addr_mirror(addr)]; + return tmp; + } + default: + fprintf(stderr, "Invalid PPU read at address $%04\n", addr); + return 0; + } } void |