start of mbc3

This commit is contained in:
2026-01-30 16:18:01 -08:00
parent ab258d177e
commit 712ee55e7b
2 changed files with 150 additions and 111 deletions

View File

@@ -92,7 +92,7 @@ public:
void loadGame(const std::string& filename); void loadGame(const std::string& filename);
void determineMBCInfo(); void determineMBCInfo();
static bool testMBCWrite(Word address); bool MBCWrite(Word address);
Byte* MBCRead(Word address); Byte* MBCRead(Word address);
//prevents seg faults when programs with no MBC try to write to ROM //prevents seg faults when programs with no MBC try to write to ROM
Byte dummyVal = 0; Byte dummyVal = 0;

View File

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