Path: blob/master/libsnes/bsnes/snes/alt/ppu-compatibility/memory/memory.cpp
2 views
#ifdef PPU_CPP12void PPU::latch_counters() {3regs.hcounter = cpu.hdot();4regs.vcounter = cpu.vcounter();5regs.counters_latched = true;6}78uint16 PPU::get_vram_address() {9uint16 addr = regs.vram_addr;10switch(regs.vram_mapping) {11case 0: break; //direct mapping12case 1: addr = (addr & 0xff00) | ((addr & 0x001f) << 3) | ((addr >> 5) & 7); break;13case 2: addr = (addr & 0xfe00) | ((addr & 0x003f) << 3) | ((addr >> 6) & 7); break;14case 3: addr = (addr & 0xfc00) | ((addr & 0x007f) << 3) | ((addr >> 7) & 7); break;15}16return (addr << 1);17}1819//NOTE: all VRAM writes during active display are invalid. Unlike OAM and CGRAM, they will20//not be written anywhere at all. The below address ranges for where writes are invalid have21//been validated on hardware, as has the edge case where the S-CPU MDR can be written if the22//write occurs during the very last clock cycle of vblank.2324uint8 PPU::vram_mmio_read(uint16 addr) {25uint8 data;2627if(regs.display_disabled == true) {28data = vram[addr];29} else {30uint16 v = cpu.vcounter();31uint16 h = cpu.hcounter();32uint16 ls = ((system.region() == System::Region::NTSC ? 525 : 625) >> 1) - 1;33if(interlace() && !cpu.field()) ls++;3435if(v == ls && h == 1362) {36data = 0x00;37} else if(v < (!overscan() ? 224 : 239)) {38data = 0x00;39} else if(v == (!overscan() ? 224 : 239)) {40if(h == 1362) {41data = vram[addr];42} else {43data = 0x00;44}45} else {46data = vram[addr];47}48}4950return data;51}5253void PPU::vram_mmio_write(uint16 addr, uint8 data) {54if(regs.display_disabled == true) {55vram[addr] = data;56} else {57uint16 v = cpu.vcounter();58uint16 h = cpu.hcounter();59if(v == 0) {60if(h <= 4) {61vram[addr] = data;62} else if(h == 6) {63vram[addr] = cpu.regs.mdr;64} else {65//no write66}67} else if(v < (!overscan() ? 225 : 240)) {68//no write69} else if(v == (!overscan() ? 225 : 240)) {70if(h <= 4) {71//no write72} else {73vram[addr] = data;74}75} else {76vram[addr] = data;77}78}79}8081uint8 PPU::oam_mmio_read(uint16 addr) {82addr &= 0x03ff;83if(addr & 0x0200) addr &= 0x021f;84uint8 data;8586if(regs.display_disabled == true) {87data = oam[addr];88} else {89if(cpu.vcounter() < (!overscan() ? 225 : 240)) {90data = oam[regs.ioamaddr];91} else {92data = oam[addr];93}94}9596return data;97}9899void PPU::oam_mmio_write(uint16 addr, uint8 data) {100addr &= 0x03ff;101if(addr & 0x0200) addr &= 0x021f;102103sprite_list_valid = false;104105if(regs.display_disabled == true) {106oam[addr] = data;107update_sprite_list(addr, data);108} else {109if(cpu.vcounter() < (!overscan() ? 225 : 240)) {110oam[regs.ioamaddr] = data;111update_sprite_list(regs.ioamaddr, data);112} else {113oam[addr] = data;114update_sprite_list(addr, data);115}116}117}118119uint8 PPU::cgram_mmio_read(uint16 addr) {120addr &= 0x01ff;121uint8 data;122123if(1 || regs.display_disabled == true) {124data = cgram[addr];125} else {126uint16 v = cpu.vcounter();127uint16 h = cpu.hcounter();128if(v < (!overscan() ? 225 : 240) && h >= 128 && h < 1096) {129data = cgram[regs.icgramaddr] & 0x7f;130} else {131data = cgram[addr];132}133}134135if(addr & 1) data &= 0x7f;136return data;137}138139void PPU::cgram_mmio_write(uint16 addr, uint8 data) {140addr &= 0x01ff;141if(addr & 1) data &= 0x7f;142143if(1 || regs.display_disabled == true) {144cgram[addr] = data;145} else {146uint16 v = cpu.vcounter();147uint16 h = cpu.hcounter();148if(v < (!overscan() ? 225 : 240) && h >= 128 && h < 1096) {149cgram[regs.icgramaddr] = data & 0x7f;150} else {151cgram[addr] = data;152}153}154}155156#endif157158159