186 lines
5.1 KiB
C++
186 lines
5.1 KiB
C++
#include "addressSpace.hpp"
|
|
|
|
void AddressSpace::determineMBCInfo() {
|
|
MBC = static_cast<MBCType>(memoryLayout.romBank0[0x147]);
|
|
romSize = 32768 * (1 << memoryLayout.romBank0[0x147]);
|
|
romBanks = 1 << (memoryLayout.romBank0[0x147] + 1);
|
|
|
|
const Byte ramSize = memoryLayout.romBank0[0x0149];
|
|
switch (ramSize) {
|
|
case 0x02:
|
|
externalRamSize = 8196;
|
|
externalRamBanks = 1;
|
|
break;
|
|
case 0x03:
|
|
externalRamSize = 32768;
|
|
externalRamBanks = 4;
|
|
break;
|
|
case 0x04:
|
|
externalRamSize = 131072;
|
|
externalRamBanks = 16;
|
|
break;
|
|
case 0x05:
|
|
externalRamSize = 65536;
|
|
externalRamBanks = 8;
|
|
break;
|
|
default:
|
|
externalRamSize = 0;
|
|
externalRamBanks = 0;
|
|
break;
|
|
}
|
|
|
|
if (MBC == MBC2 || MBC == MBC2Battery) {
|
|
// only the lower 4 bits are usable
|
|
externalRamSize = 512;
|
|
}
|
|
}
|
|
|
|
bool AddressSpace::MBCWrite(const Word address) {
|
|
if (address <= 0x7FFF)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
Byte *AddressSpace::MBCRead(const Word address) {
|
|
if (MBC == MBC1) {
|
|
if (address <= 0x1FFF)
|
|
return &ramEnable;
|
|
if (address <= 0x3FFF)
|
|
return &romBankRegister;
|
|
if (address <= 0x5FFF)
|
|
return &twoBitBankRegister;
|
|
if (address <= 0x7FFF)
|
|
return &romRamSelect;
|
|
} else if (MBC == MBC1Ram || MBC == MBC1RamBattery) {
|
|
if (address <= 0x1FFF)
|
|
return &ramEnable;
|
|
// bits 0-4
|
|
if (address <= 0x3FFF)
|
|
return &romBankRegister;
|
|
if (address <= 0x5FFF) {
|
|
return &twoBitBankRegister;
|
|
}
|
|
if (address <= 0x7FFF)
|
|
return &romRamSelect;
|
|
} else if (MBC == MBC2 || MBC == MBC2Battery) {
|
|
if (address <= 0x3FFF) {
|
|
if (address & 0x0100)
|
|
return &romBankRegister;
|
|
else
|
|
return &ramEnable;
|
|
}
|
|
} else if (MBC == MBC3 || MBC == MBC3TimerBattery) {
|
|
} else if (MBC == MBC3Ram || MBC == MBC3RamBattery ||
|
|
MBC == MBC3TimerRamBattery) {
|
|
}
|
|
return &dummyVal;
|
|
}
|
|
|
|
void AddressSpace::MBCUpdate() {
|
|
// TODO: multicart roms need to be able to switch the first rom bank as well
|
|
// see: https://gbdev.io/pandocs/MBC1.html
|
|
if (MBC == MBC1) {
|
|
// Selected ROM Bank = (Secondary Bank << 5) + ROM Bank
|
|
romBankRegister &= 0b11111;
|
|
twoBitBankRegister &= 0b11;
|
|
|
|
// 512 KiB can only have 8KiB of ram
|
|
if (romSize >= 524288) {
|
|
if (romBankRegister == 0)
|
|
selectedRomBank = (twoBitBankRegister << 5) + 1;
|
|
selectedRomBank = (twoBitBankRegister << 5) + romBankRegister;
|
|
} else {
|
|
if (romBankRegister == 0)
|
|
selectedRomBank = 1;
|
|
else
|
|
selectedRomBank = romBankRegister;
|
|
}
|
|
if (romBankRegister == 0x20 || romBankRegister == 0x40 ||
|
|
romBankRegister == 0x60)
|
|
romBankRegister += 1;
|
|
selectedExternalRamBank = 0;
|
|
|
|
loadRomBank();
|
|
loadRamBank();
|
|
} else if (MBC == MBC1Ram || MBC == MBC1RamBattery) {
|
|
// Selected ROM Bank = (Secondary Bank << 5) + ROM Bank
|
|
romBankRegister &= 0b11111;
|
|
twoBitBankRegister &= 0b11;
|
|
|
|
// 512 KiB can only have 8KiB of ram
|
|
if (romSize >= 524288) {
|
|
if (romBankRegister == 0)
|
|
selectedRomBank = (twoBitBankRegister << 5) + 1;
|
|
selectedRomBank = (twoBitBankRegister << 5) + romBankRegister;
|
|
selectedExternalRamBank = 0;
|
|
} else {
|
|
if (romBankRegister == 0)
|
|
selectedRomBank = 1;
|
|
else
|
|
selectedRomBank = romBankRegister;
|
|
selectedExternalRamBank = twoBitBankRegister;
|
|
}
|
|
if (romBankRegister == 0x20 || romBankRegister == 0x40 ||
|
|
romBankRegister == 0x60)
|
|
romBankRegister += 1;
|
|
|
|
loadRomBank();
|
|
loadRamBank();
|
|
} else if (MBC == MBC2 || MBC == MBC2Battery) {
|
|
selectedRomBank = romBankRegister & 0x0F;
|
|
loadRomBank();
|
|
loadRamBank();
|
|
} else if (MBC == MBC3 || MBC == MBC3TimerBattery) {
|
|
romBankRegister &= 0b11111;
|
|
twoBitBankRegister &= 0b11;
|
|
|
|
// 512 KiB can only have 8KiB of ram
|
|
if (romSize >= 524288) {
|
|
if (romBankRegister == 0)
|
|
selectedRomBank = (twoBitBankRegister << 5) + 1;
|
|
selectedRomBank = (twoBitBankRegister << 5) + romBankRegister;
|
|
} else {
|
|
if (romBankRegister == 0)
|
|
selectedRomBank = 1;
|
|
else
|
|
selectedRomBank = romBankRegister;
|
|
}
|
|
} else if (MBC == MBC3Ram || MBC == MBC3RamBattery ||
|
|
MBC == MBC3TimerRamBattery) {
|
|
romBankRegister &= 0b11111;
|
|
twoBitBankRegister &= 0b11;
|
|
|
|
// 512 KiB can only have 8KiB of ram
|
|
if (romSize >= 524288) {
|
|
if (romBankRegister == 0)
|
|
selectedRomBank = (twoBitBankRegister << 5) + 1;
|
|
selectedRomBank = (twoBitBankRegister << 5) + romBankRegister;
|
|
selectedExternalRamBank = 0;
|
|
} else {
|
|
if (romBankRegister == 0)
|
|
selectedRomBank = 1;
|
|
else
|
|
selectedRomBank = romBankRegister;
|
|
selectedExternalRamBank = twoBitBankRegister;
|
|
}
|
|
}
|
|
}
|
|
|
|
void AddressSpace::loadRomBank() {
|
|
memoryLayout.romBankSwitch = game.data() + (ROM_BANK_SIZE * selectedRomBank);
|
|
}
|
|
|
|
void AddressSpace::createRamBank() {
|
|
if (externalRamSize) {
|
|
cartridgeRam = new Byte[externalRamSize];
|
|
memoryLayout.externalRam = cartridgeRam;
|
|
}
|
|
}
|
|
|
|
void AddressSpace::loadRamBank() {
|
|
if (cartridgeRam != nullptr) {
|
|
memoryLayout.externalRam =
|
|
cartridgeRam + (RAM_BANK_SIZE * selectedExternalRamBank);
|
|
}
|
|
}
|