bsnes-mt/bsnes/sfc/coprocessor/sa1/bwram.cpp
2020-06-02 20:53:45 +03:00

121 lines
3.5 KiB
C++

auto SA1::BWRAM::conflict() const -> bool {
if(configuration.hacks.coprocessor.delayedSync) return false;
if((cpu.r.mar & 0x40e000) == 0x006000) return true; //00-3f,80-bf:6000-7fff
if((cpu.r.mar & 0xf00000) == 0x400000) return true; //40-4f:0000-ffff
return false;
}
auto SA1::BWRAM::read(uint address, uint8 data) -> uint8 {
if(!size()) return data;
address = bus.mirror(address, size());
return WritableMemory::read(address, data);
}
auto SA1::BWRAM::write(uint address, uint8 data) -> void {
if(!size()) return;
address = bus.mirror(address, size());
return WritableMemory::write(address, data);
}
//note: addresses are translated prior to invoking this function:
//00-3f,80-bf:6000-7fff size=0x2000 => 00:0000-1fff
//40-4f:0000-ffff => untranslated
auto SA1::BWRAM::readCPU(uint address, uint8 data) -> uint8 {
cpu.synchronizeCoprocessors();
if(address < 0x2000) { //$00-3f,80-bf:6000-7fff
address = sa1.mmio.sbm * 0x2000 + (address & 0x1fff);
}
if(dma) return sa1.dmaCC1Read(address);
return read(address, data);
}
auto SA1::BWRAM::writeCPU(uint address, uint8 data) -> void {
cpu.synchronizeCoprocessors();
if(address < 0x2000) { //$00-3f,80-bf:6000-7fff
address = sa1.mmio.sbm * 0x2000 + (address & 0x1fff);
}
return write(address, data);
}
auto SA1::BWRAM::readSA1(uint address, uint8 data) -> uint8 {
if(sa1.mmio.sw46 == 0) {
//$40-43:0000-ffff x 32 projection
address = (sa1.mmio.cbm & 0x1f) * 0x2000 + (address & 0x1fff);
return readLinear(address, data);
} else {
//$60-6f:0000-ffff x 128 projection
address = sa1.mmio.cbm * 0x2000 + (address & 0x1fff);
return readBitmap(address, data);
}
}
auto SA1::BWRAM::writeSA1(uint address, uint8 data) -> void {
if(sa1.mmio.sw46 == 0) {
//$40-43:0000-ffff x 32 projection
address = (sa1.mmio.cbm & 0x1f) * 0x2000 + (address & 0x1fff);
return writeLinear(address, data);
} else {
//$60-6f:0000-ffff x 128 projection
address = sa1.mmio.cbm * 0x2000 + (address & 0x1fff);
return writeBitmap(address, data);
}
}
auto SA1::BWRAM::readLinear(uint address, uint8 data) -> uint8 {
return read(address, data);
}
auto SA1::BWRAM::writeLinear(uint address, uint8 data) -> void {
return write(address, data);
}
auto SA1::BWRAM::readBitmap(uint20 address, uint8 data) -> uint8 {
if(sa1.mmio.bbf == 0) {
//4bpp
uint shift = address & 1;
address >>= 1;
switch(shift) {
case 0: return read(address) >> 0 & 15;
case 1: return read(address) >> 4 & 15;
}
} else {
//2bpp
uint shift = address & 3;
address >>= 2;
switch(shift) {
case 0: return read(address) >> 0 & 3;
case 1: return read(address) >> 2 & 3;
case 2: return read(address) >> 4 & 3;
case 3: return read(address) >> 6 & 3;
}
}
unreachable;
}
auto SA1::BWRAM::writeBitmap(uint20 address, uint8 data) -> void {
if(sa1.mmio.bbf == 0) {
//4bpp
uint shift = address & 1;
address >>= 1;
switch(shift) {
case 0: data = read(address) & 0xf0 | (data & 0x0f) << 0; break;
case 1: data = read(address) & 0x0f | (data & 0x0f) << 4; break;
}
} else {
//2bpp
uint shift = address & 3;
address >>= 2;
switch(shift) {
case 0: data = read(address) & 0xfc | (data & 0x03) << 0; break;
case 1: data = read(address) & 0xf3 | (data & 0x03) << 2; break;
case 2: data = read(address) & 0xcf | (data & 0x03) << 4; break;
case 3: data = read(address) & 0x3f | (data & 0x03) << 6; break;
}
}
write(address, data);
}