mirror of https://github.com/bsnes-emu/bsnes.git
204 lines
4.7 KiB
C++
204 lines
4.7 KiB
C++
auto CPU::read(uint8 bank, uint13 addr) -> uint8 {
|
|
auto data = read_(bank, addr);
|
|
if(auto result = cheat.find(bank << 13 | addr, data)) data = result();
|
|
return data;
|
|
}
|
|
|
|
auto CPU::read_(uint8 bank, uint13 addr) -> uint8 {
|
|
//$00-7f HuCard
|
|
if(!bank.bit(7)) {
|
|
return cartridge.read(bank << 13 | addr);
|
|
}
|
|
|
|
//$f7 BRAM
|
|
if(bank == 0xf7) {
|
|
return bram[addr.bits(0,10)];
|
|
}
|
|
|
|
//$f8-fb RAM
|
|
if(bank >= 0xf8 && bank <= 0xfb) {
|
|
if(Model::PCEngine()) return ram[addr];
|
|
if(Model::SuperGrafx()) return ram[bank.bits(0,1) << 13 | addr];
|
|
}
|
|
|
|
//$ff Hardware
|
|
if(bank == 0xff) {
|
|
//$0000-03ff VDC or VPC
|
|
if((addr & 0x1c00) == 0x0000) {
|
|
HuC6280::io(); //penalty cycle
|
|
if(Model::PCEngine()) return vdc0.read(addr);
|
|
if(Model::SuperGrafx()) return vpc.read(addr);
|
|
}
|
|
|
|
//$0400-07ff VCE
|
|
if((addr & 0x1c00) == 0x0400) {
|
|
HuC6280::io(); //penalty cycle
|
|
return vce.read(addr);
|
|
}
|
|
|
|
//$0800-0bff PSG
|
|
if((addr & 0x1c00) == 0x0800) {
|
|
return io.mdr;
|
|
}
|
|
|
|
//$0c00-0fff Timer
|
|
if((addr & 0x1c00) == 0x0c00) {
|
|
return (io.mdr & 0x80) | timer.value;
|
|
}
|
|
|
|
//$1000-13ff I/O
|
|
if((addr & 0x1c00) == 0x1000) {
|
|
//note 1: Turbografx-16 games check this bit for region protection.
|
|
//yet PC Engine games do not. since we cannot tell the games apart,
|
|
//it's more compatible to always identify as a Turbografx-16 system.
|
|
//note 2: we state that the CD-ROM drive is present.
|
|
//this is so games can use its backup RAM for save data.
|
|
return (
|
|
controllerPort.device->readData() << 0
|
|
| 1 << 4
|
|
| 1 << 5
|
|
| 0 << 6 //device (0 = Turbografx-16; 1 = PC Engine)
|
|
| 0 << 7 //add-on (0 = CD-ROM; 1 = nothing)
|
|
);
|
|
}
|
|
|
|
//$1400-17ff IRQ
|
|
if((addr & 0x1c00) == 0x1400) {
|
|
if(addr.bits(0,1) == 0) {
|
|
return io.mdr;
|
|
}
|
|
|
|
if(addr.bits(0,1) == 1) {
|
|
return io.mdr;
|
|
}
|
|
|
|
if(addr.bits(0,1) == 2) {
|
|
return (
|
|
irq.disableExternal << 0
|
|
| irq.disableVDC << 1
|
|
| irq.disableTimer << 2
|
|
| (io.mdr & 0xf8)
|
|
);
|
|
}
|
|
|
|
if(addr.bits(0,1) == 3) {
|
|
bool pendingExternal = 0;
|
|
bool pendingVDC = vdc0.irqLine() | vdc1.irqLine();
|
|
bool pendingTimer = timer.irqLine();
|
|
return (
|
|
pendingExternal << 0
|
|
| pendingVDC << 1
|
|
| pendingTimer << 2
|
|
| (io.mdr & 0xf8)
|
|
);
|
|
}
|
|
}
|
|
|
|
//$1800-1bff CD-ROM
|
|
if((addr & 0x1c00) == 0x1800) {
|
|
return 0xff;
|
|
}
|
|
|
|
//$1c00-1fff unmapped
|
|
if((addr & 0x1c00) == 0x1c00) {
|
|
return 0xff;
|
|
}
|
|
}
|
|
|
|
return 0xff;
|
|
}
|
|
|
|
auto CPU::write(uint8 bank, uint13 addr, uint8 data) -> void {
|
|
//$00-7f HuCard
|
|
if(!bank.bit(7)) {
|
|
return cartridge.write(bank << 13 | addr, data);
|
|
}
|
|
|
|
//$f7 BRAM
|
|
if(bank == 0xf7) {
|
|
bram[addr.bits(0,10)] = data;
|
|
return;
|
|
}
|
|
|
|
//$f8-fb RAM
|
|
if(bank >= 0xf8 && bank <= 0xfb) {
|
|
if(Model::PCEngine()) ram[addr] = data;
|
|
if(Model::SuperGrafx()) ram[bank.bits(0,1) << 13 | addr] = data;
|
|
return;
|
|
}
|
|
|
|
//$1fe000-1fffff Hardware
|
|
if(bank == 0xff) {
|
|
//$0000-03ff VDC or VPC
|
|
if((addr & 0x1c00) == 0x0000) {
|
|
HuC6280::io(); //penalty cycle
|
|
if(Model::PCEngine()) return vdc0.write(addr, data);
|
|
if(Model::SuperGrafx()) return vpc.write(addr, data);
|
|
}
|
|
|
|
//$0400-07ff VCE
|
|
if((addr & 0x1c00) == 0x0400) {
|
|
HuC6280::io(); //penalty cycle
|
|
return vce.write(addr, data);
|
|
}
|
|
|
|
//$0800-0bff PSG
|
|
if((addr & 0x1c00) == 0x0800) {
|
|
return psg.write(addr, io.mdr = data);
|
|
}
|
|
|
|
//$0c00-0fff Timer
|
|
if((addr & 0x1c00) == 0x0c00) {
|
|
io.mdr = data;
|
|
if(!addr.bit(0)) {
|
|
timer.latch = data.bits(0,6);
|
|
} else {
|
|
timer.enable = data.bit(0);
|
|
if(timer.enable) timer.start();
|
|
}
|
|
return;
|
|
}
|
|
|
|
//$1000-13ff I/O
|
|
if((addr & 0x1c00) == 0x1000) {
|
|
io.mdr = data;
|
|
controllerPort.device->writeData(data.bits(0,1));
|
|
return;
|
|
}
|
|
|
|
//$1400-17ff IRQ
|
|
if((addr & 0x1c00) == 0x1400) {
|
|
io.mdr = data;
|
|
if(addr.bits(0,1) == 2) {
|
|
irq.disableExternal = data.bit(0);
|
|
irq.disableVDC = data.bit(1);
|
|
irq.disableTimer = data.bit(2);
|
|
return;
|
|
}
|
|
|
|
if(addr.bits(0,1) == 3) {
|
|
timer.line = 0;
|
|
return;
|
|
}
|
|
}
|
|
|
|
//$1800-1bff CD-ROM
|
|
if((addr & 0x1c00) == 0x1800) {
|
|
return;
|
|
}
|
|
|
|
//$1c00-1fff unmapped
|
|
if((addr & 0x1c00) == 0x1c00) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
//ST0, ST1, ST2
|
|
auto CPU::store(uint2 addr, uint8 data) -> void {
|
|
HuC6280::io(); //penalty cycle
|
|
if(addr) addr++; //0,1,2 => 0,2,3
|
|
if(Model::PCEngine()) vdc0.write(addr, data);
|
|
if(Model::SuperGrafx()) vpc.store(addr, data);
|
|
}
|