91 lines
1.4 KiB
C
91 lines
1.4 KiB
C
#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;
|
|
}
|