From 712ee55e7bc153d1803c4de14141fe96ead811ae Mon Sep 17 00:00:00 2001 From: YayIguess Date: Fri, 30 Jan 2026 16:18:01 -0800 Subject: [PATCH] start of mbc3 --- src/addressSpace.hpp | 2 +- src/mbc.cpp | 259 +++++++++++++++++++++++++------------------ 2 files changed, 150 insertions(+), 111 deletions(-) diff --git a/src/addressSpace.hpp b/src/addressSpace.hpp index 44978c3..b55a5ac 100644 --- a/src/addressSpace.hpp +++ b/src/addressSpace.hpp @@ -92,7 +92,7 @@ public: void loadGame(const std::string& filename); void determineMBCInfo(); - static bool testMBCWrite(Word address); + bool MBCWrite(Word address); Byte* MBCRead(Word address); //prevents seg faults when programs with no MBC try to write to ROM Byte dummyVal = 0; diff --git a/src/mbc.cpp b/src/mbc.cpp index 50c3ae3..f0016bf 100644 --- a/src/mbc.cpp +++ b/src/mbc.cpp @@ -1,135 +1,174 @@ #include "addressSpace.hpp" void AddressSpace::determineMBCInfo() { - MBC = static_cast(memoryLayout.romBank0[0x147]); - romSize = 32768 * (1 << memoryLayout.romBank0[0x147]); - romBanks = 1 << (memoryLayout.romBank0[0x147] + 1); + MBC = static_cast(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; - } + 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; - } + if (MBC == MBC2 || MBC == MBC2Battery) { + // only the lower 4 bits are usable + externalRamSize = 512; + } } -bool AddressSpace::testMBCWrite(const Word address) { - if (address <= 0x7FFF) - return true; - return false; +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; - } - 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; - } - return &dummyVal; +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; + } + 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; + } + 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 &= 0x1F; - twoBitBankRegister &= 0x3; + // 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; - } - selectedExternalRamBank = 0; + // 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(); - } - if (MBC == MBC1Ram || MBC == MBC1RamBattery) { - //Selected ROM Bank = (Secondary Bank << 5) + ROM Bank - romBankRegister &= 0x1F; - twoBitBankRegister &= 0x3; + loadRomBank(); + loadRamBank(); + } + 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; - } - loadRomBank(); - loadRamBank(); - } + // 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) { + // 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() { - memoryLayout.romBankSwitch = game.data() + (ROM_BANK_SIZE * selectedRomBank); + memoryLayout.romBankSwitch = game.data() + (ROM_BANK_SIZE * selectedRomBank); } void AddressSpace::createRamBank() { - if (externalRamSize) { - cartridgeRam = new Byte[externalRamSize]; - memoryLayout.externalRam = cartridgeRam; - } + if (externalRamSize) { + cartridgeRam = new Byte[externalRamSize]; + memoryLayout.externalRam = cartridgeRam; + } } void AddressSpace::loadRamBank() { - if (cartridgeRam != nullptr) - memoryLayout.externalRam = cartridgeRam + (RAM_BANK_SIZE * selectedExternalRamBank); + if (cartridgeRam != nullptr) + memoryLayout.externalRam = + cartridgeRam + (RAM_BANK_SIZE * selectedExternalRamBank); } - -