start of mbc3
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
259
src/mbc.cpp
259
src/mbc.cpp
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user