#include "ppu.h" 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) { ppu.cycles++; if (ppu.cycles >= 341) { ppu.cycles -= 341; ppu.scanlines++; } if (ppu.scanlines >= 262) ppu.scanlines -= 262; } 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 ppu_write(uint16_t addr, uint8_t byte) { static uint8_t prev; prev = byte; }