bsnes/higan/fc/ppu/memory.cpp

145 lines
3.1 KiB
C++

auto PPU::readCIRAM(uint11 addr) -> uint8 {
return ciram[addr];
}
auto PPU::writeCIRAM(uint11 addr, uint8 data) -> void {
ciram[addr] = data;
}
auto PPU::readCGRAM(uint5 addr) -> uint8 {
if((addr & 0x13) == 0x10) addr &= ~0x10;
uint8 data = cgram[addr];
if(io.grayscale) data &= 0x30;
return data;
}
auto PPU::writeCGRAM(uint5 addr, uint8 data) -> void {
if((addr & 0x13) == 0x10) addr &= ~0x10;
cgram[addr] = data;
}
auto PPU::readIO(uint16 addr) -> uint8 {
uint8 result = 0x00;
switch(addr.bits(0,2)) {
//PPUSTATUS
case 2:
result |= io.mdr.bits(0,4);
result |= io.spriteOverflow << 5;
result |= io.spriteZeroHit << 6;
result |= io.nmiFlag << 7;
io.v.latch = 0;
io.nmiHold = 0;
cpu.nmiLine(io.nmiFlag = 0);
break;
//OAMDATA
case 4:
result = oam[io.oamAddress];
break;
//PPUDATA
case 7:
if(enable() && (io.ly <= 240 || io.ly == 261)) return 0x00;
addr = (uint14)io.v.address;
if(addr <= 0x1fff) {
result = io.busData;
io.busData = cartridge.readCHR(addr);
} else if(addr <= 0x3eff) {
result = io.busData;
io.busData = cartridge.readCHR(addr);
} else if(addr <= 0x3fff) {
result = readCGRAM(addr);
io.busData = cartridge.readCHR(addr);
}
io.v.address += io.vramIncrement;
break;
}
return result;
}
auto PPU::writeIO(uint16 addr, uint8 data) -> void {
io.mdr = data;
switch(addr.bits(0,2)) {
//PPUCTRL
case 0:
io.t.nametable = data.bits(0,1);
io.vramIncrement = data.bit (2) ? 32 : 1;
io.spriteAddress = data.bit (3) ? 0x1000 : 0x0000;
io.bgAddress = data.bit (4) ? 0x1000 : 0x0000;
io.spriteHeight = data.bit (5) ? 16 : 8;
io.masterSelect = data.bit (6);
io.nmiEnable = data.bit (7);
cpu.nmiLine(io.nmiEnable && io.nmiHold && io.nmiFlag);
break;
//PPUMASK
case 1:
io.grayscale = data.bit (0);
io.bgEdgeEnable = data.bit (1);
io.spriteEdgeEnable = data.bit (2);
io.bgEnable = data.bit (3);
io.spriteEnable = data.bit (4);
io.emphasis = data.bits(5,7);
break;
//PPUSTATUS
case 2:
break;
//OAMADDR
case 3:
io.oamAddress = data;
break;
//OAMDATA
case 4:
if(io.oamAddress.bits(0,1) == 2) data.bits(2,4) = 0; //clear non-existent bits (always read back as 0)
oam[io.oamAddress++] = data;
break;
//PPUSCROLL
case 5:
if(io.v.latch++ == 0) {
io.v.fineX = data.bits(0,2);
io.t.tileX = data.bits(3,7);
} else {
io.t.fineY = data.bits(0,2);
io.t.tileY = data.bits(3,7);
}
break;
//PPUADDR
case 6:
if(io.v.latch++ == 0) {
io.t.addressHi = data.bits(0,5);
} else {
io.t.addressLo = data.bits(0,7);
io.v.address = io.t.address;
}
break;
//PPUDATA
case 7:
if(enable() && (io.ly <= 240 || io.ly == 261)) return;
addr = (uint14)io.v.address;
if(addr <= 0x1fff) {
cartridge.writeCHR(addr, data);
} else if(addr <= 0x3eff) {
cartridge.writeCHR(addr, data);
} else if(addr <= 0x3fff) {
writeCGRAM(addr, data);
}
io.v.address += io.vramIncrement;
break;
}
}