add RAM bank support to CartEnhanced

refactor Cart3E
differentiate between ROM and RAM banks (TODO: check debugger)
This commit is contained in:
thrust26 2020-04-15 14:53:05 +02:00
parent ca5b6a6fe7
commit 00e67f1a51
42 changed files with 313 additions and 504 deletions

View File

@ -72,12 +72,18 @@ CartDebug::CartDebug(Debugger& dbg, Console& console, const OSystem& osystem)
// Create bank information for each potential bank, and an extra one for ZP RAM // Create bank information for each potential bank, and an extra one for ZP RAM
BankInfo info; BankInfo info;
for(uInt32 i = 0; i < myConsole.cartridge().bankCount(); ++i) for(uInt32 i = 0; i < myConsole.cartridge().romBankCount(); ++i)
{ {
info.size = myConsole.cartridge().bankSize(i); info.size = myConsole.cartridge().bankSize(i);
myBankInfo.push_back(info); myBankInfo.push_back(info);
} }
for(uInt32 i = 0; i < myConsole.cartridge().ramBankCount(); ++i)
{
info.size = myConsole.cartridge().bankSize(i) >> 1;
myBankInfo.push_back(info);
}
info.size = 128; // ZP RAM info.size = 128; // ZP RAM
myBankInfo.push_back(info); myBankInfo.push_back(info);
@ -235,9 +241,10 @@ string CartDebug::toString()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDebug::disassemble(bool force) bool CartDebug::disassemblePC(bool force)
{ {
uInt16 PC = myDebugger.cpuDebug().pc(); uInt16 PC = myDebugger.cpuDebug().pc();
// ROM/RAM bank or ZP-RAM?
int bank = (PC & 0x1000) ? getBank(PC) : int(myBankInfo.size()) - 1; int bank = (PC & 0x1000) ? getBank(PC) : int(myBankInfo.size()) - 1;
return disassemble(bank, PC, force); return disassemble(bank, PC, force);
@ -414,7 +421,7 @@ bool CartDebug::addDirective(Device::AccessType type,
bank = (myDebugger.cpuDebug().pc() & 0x1000) ? bank = (myDebugger.cpuDebug().pc() & 0x1000) ?
getBank(myDebugger.cpuDebug().pc()) : int(myBankInfo.size())-1; getBank(myDebugger.cpuDebug().pc()) : int(myBankInfo.size())-1;
bank = std::min(bank, bankCount()); bank = std::min(bank, romBankCount());
BankInfo& info = myBankInfo[bank]; BankInfo& info = myBankInfo[bank];
DirectiveList& list = info.directiveList; DirectiveList& list = info.directiveList;
@ -546,9 +553,9 @@ int CartDebug::getPCBank()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int CartDebug::bankCount() const int CartDebug::romBankCount() const
{ {
return myConsole.cartridge().bankCount(); return myConsole.cartridge().romBankCount();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -955,7 +962,7 @@ string CartDebug::loadConfigFile()
myDebugger.rom().invalidate(); myDebugger.rom().invalidate();
stringstream retVal; stringstream retVal;
if(myConsole.cartridge().bankCount() > 1) if(myConsole.cartridge().romBankCount() > 1)
retVal << DebuggerParser::red("config file for multi-bank ROM not fully supported\n"); retVal << DebuggerParser::red("config file for multi-bank ROM not fully supported\n");
retVal << "config file '" << node.getShortPath() << "' loaded OK"; retVal << "config file '" << node.getShortPath() << "' loaded OK";
return retVal.str(); return retVal.str();
@ -990,14 +997,14 @@ string CartDebug::saveConfigFile()
out << "// Stella.pro: \"" << name << "\"" << endl out << "// Stella.pro: \"" << name << "\"" << endl
<< "// MD5: " << md5 << endl << "// MD5: " << md5 << endl
<< endl; << endl;
for(uInt32 b = 0; b < myConsole.cartridge().bankCount(); ++b) for(uInt32 b = 0; b < myConsole.cartridge().romBankCount(); ++b)
{ {
out << "[" << b << "]" << endl; out << "[" << b << "]" << endl;
getBankDirectives(out, myBankInfo[b]); getBankDirectives(out, myBankInfo[b]);
} }
stringstream retVal; stringstream retVal;
if(myConsole.cartridge().bankCount() > 1) if(myConsole.cartridge().romBankCount() > 1)
retVal << DebuggerParser::red("config file for multi-bank ROM not fully supported\n"); retVal << DebuggerParser::red("config file for multi-bank ROM not fully supported\n");
retVal << "config file '" << cfg.getShortPath() << "' saved OK"; retVal << "config file '" << cfg.getShortPath() << "' saved OK";
return retVal.str(); return retVal.str();
@ -1058,14 +1065,14 @@ string CartDebug::saveDisassembly()
Disassembly disasm; Disassembly disasm;
disasm.list.reserve(2048); disasm.list.reserve(2048);
uInt16 bankCount = myConsole.cartridge().bankCount(); uInt16 romBankCount = myConsole.cartridge().romBankCount();
uInt16 oldBank = myConsole.cartridge().getBank(); uInt16 oldBank = myConsole.cartridge().getBank();
// prepare for switching banks // prepare for switching banks
myConsole.cartridge().unlockBank(); myConsole.cartridge().unlockBank();
uInt32 origin = 0; uInt32 origin = 0;
for(int bank = 0; bank < bankCount; ++bank) for(int bank = 0; bank < romBankCount; ++bank)
{ {
// TODO: not every CartDebugWidget does it like that, we need a method // TODO: not every CartDebugWidget does it like that, we need a method
myConsole.cartridge().unlockBank(); myConsole.cartridge().unlockBank();
@ -1082,8 +1089,8 @@ string CartDebug::saveDisassembly()
buf << "\n\n;***********************************************************\n" buf << "\n\n;***********************************************************\n"
<< "; Bank " << bank; << "; Bank " << bank;
if (bankCount > 1) if (romBankCount > 1)
buf << " / 0.." << bankCount - 1; buf << " / 0.." << romBankCount - 1;
buf << "\n;***********************************************************\n\n"; buf << "\n;***********************************************************\n\n";
@ -1097,7 +1104,7 @@ string CartDebug::saveDisassembly()
buf << " SEG CODE\n"; buf << " SEG CODE\n";
if(bankCount == 1) if(romBankCount == 1)
buf << " ORG $" << Base::HEX4 << info.offset << "\n\n"; buf << " ORG $" << Base::HEX4 << info.offset << "\n\n";
else else
buf << " ORG $" << Base::HEX4 << origin << "\n" buf << " ORG $" << Base::HEX4 << origin << "\n"
@ -1327,7 +1334,7 @@ string CartDebug::saveDisassembly()
out << buf.str(); out << buf.str();
stringstream retVal; stringstream retVal;
if(myConsole.cartridge().bankCount() > 1) if(myConsole.cartridge().romBankCount() > 1)
retVal << DebuggerParser::red("disassembly for multi-bank ROM not fully supported\n"); retVal << DebuggerParser::red("disassembly for multi-bank ROM not fully supported\n");
retVal << "saved " << node.getShortPath() << " OK"; retVal << "saved " << node.getShortPath() << " OK";
return retVal.str(); return retVal.str();
@ -1367,8 +1374,8 @@ string CartDebug::saveAccessFile()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string CartDebug::listConfig(int bank) string CartDebug::listConfig(int bank)
{ {
uInt32 startbank = 0, endbank = bankCount(); uInt32 startbank = 0, endbank = romBankCount();
if(bank >= 0 && bank < bankCount()) if(bank >= 0 && bank < romBankCount())
{ {
startbank = bank; startbank = bank;
endbank = startbank + 1; endbank = startbank + 1;
@ -1392,7 +1399,7 @@ string CartDebug::listConfig(int bank)
getBankDirectives(buf, info); getBankDirectives(buf, info);
} }
if(myConsole.cartridge().bankCount() > 1) if(myConsole.cartridge().romBankCount() > 1)
buf << DebuggerParser::red("config file for multi-bank ROM not fully supported") << endl; buf << DebuggerParser::red("config file for multi-bank ROM not fully supported") << endl;
return buf.str(); return buf.str();
@ -1401,8 +1408,8 @@ string CartDebug::listConfig(int bank)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string CartDebug::clearConfig(int bank) string CartDebug::clearConfig(int bank)
{ {
uInt32 startbank = 0, endbank = bankCount(); uInt32 startbank = 0, endbank = romBankCount();
if(bank >= 0 && bank < bankCount()) if(bank >= 0 && bank < romBankCount())
{ {
startbank = bank; startbank = bank;
endbank = startbank + 1; endbank = startbank + 1;

View File

@ -95,7 +95,7 @@ class CartDebug : public DebuggerSystem
int lastWriteBaseAddress(); int lastWriteBaseAddress();
// TODO // TODO
bool disassemble(bool force = false); bool disassemblePC(bool force = false);
bool disassembleBank(int bank); bool disassembleBank(int bank);
// First, a call is made to disassemble(), which updates the disassembly // First, a call is made to disassemble(), which updates the disassembly
@ -159,7 +159,7 @@ class CartDebug : public DebuggerSystem
/** /**
Get the total number of banks supported by the cartridge. Get the total number of banks supported by the cartridge.
*/ */
int bankCount() const; int romBankCount() const;
/** /**
Add a label and associated address. Add a label and associated address.

View File

@ -763,7 +763,7 @@ void DebuggerParser::executeBreak()
{ {
uInt16 addr; uInt16 addr;
uInt8 bank; uInt8 bank;
uInt32 bankCount = debugger.cartDebug().bankCount(); uInt32 romBankCount = debugger.cartDebug().romBankCount();
if(argCount == 0) if(argCount == 0)
addr = debugger.cpuDebug().pc(); addr = debugger.cpuDebug().pc();
@ -775,7 +775,7 @@ void DebuggerParser::executeBreak()
else else
{ {
bank = args[1]; bank = args[1];
if(bank >= bankCount && bank != 0xff) if(bank >= romBankCount && bank != 0xff)
{ {
commandResult << red("invalid bank"); commandResult << red("invalid bank");
return; return;
@ -791,12 +791,12 @@ void DebuggerParser::executeBreak()
commandResult << "cleared"; commandResult << "cleared";
commandResult << " breakpoint at $" << Base::HEX4 << addr << " + mirrors"; commandResult << " breakpoint at $" << Base::HEX4 << addr << " + mirrors";
if(bankCount > 1) if(romBankCount > 1)
commandResult << " in bank #" << std::dec << int(bank); commandResult << " in bank #" << std::dec << int(bank);
} }
else else
{ {
for(int i = 0; i < debugger.cartDebug().bankCount(); ++i) for(int i = 0; i < debugger.cartDebug().romBankCount(); ++i)
{ {
bool set = debugger.toggleBreakPoint(addr, i); bool set = debugger.toggleBreakPoint(addr, i);
@ -809,7 +809,7 @@ void DebuggerParser::executeBreak()
commandResult << "cleared"; commandResult << "cleared";
commandResult << " breakpoint at $" << Base::HEX4 << addr << " + mirrors"; commandResult << " breakpoint at $" << Base::HEX4 << addr << " + mirrors";
if(bankCount > 1) if(romBankCount > 1)
commandResult << " in bank #" << std::dec << int(bank); commandResult << " in bank #" << std::dec << int(bank);
} }
} }
@ -1459,11 +1459,11 @@ void DebuggerParser::executeListbreaks()
{ {
stringstream buf; stringstream buf;
int count = 0; int count = 0;
uInt32 bankCount = debugger.cartDebug().bankCount(); uInt32 romBankCount = debugger.cartDebug().romBankCount();
for(const auto& bp : debugger.breakPoints().getBreakpoints()) for(const auto& bp : debugger.breakPoints().getBreakpoints())
{ {
if(bankCount == 1) if(romBankCount == 1)
{ {
buf << debugger.cartDebug().getLabel(bp.addr, true, 4) << " "; buf << debugger.cartDebug().getLabel(bp.addr, true, 4) << " ";
if(!(++count % 8)) buf << endl; if(!(++count % 8)) buf << endl;

View File

@ -25,8 +25,8 @@ Cartridge3EWidget::Cartridge3EWidget(
int x, int y, int w, int h, Cartridge3E& cart) int x, int y, int w, int h, Cartridge3E& cart)
: CartDebugWidget(boss, lfont, nfont, x, y, w, h), : CartDebugWidget(boss, lfont, nfont, x, y, w, h),
myCart(cart), myCart(cart),
myNumRomBanks(uInt32(cart.mySize >> 11)), myNumRomBanks(myCart.romBankCount()),
myNumRamBanks(32) myNumRamBanks(myCart.ramBankCount())
{ {
size_t size = cart.mySize; size_t size = cart.mySize;
@ -93,21 +93,21 @@ void Cartridge3EWidget::saveOldState()
for(uInt32 i = 0; i < internalRamSize(); ++i) for(uInt32 i = 0; i < internalRamSize(); ++i)
myOldState.internalram.push_back(myCart.myRAM[i]); myOldState.internalram.push_back(myCart.myRAM[i]);
myOldState.bank = myCart.myCurrentBank; myOldState.bank = myCart.getBank();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Cartridge3EWidget::loadConfig() void Cartridge3EWidget::loadConfig()
{ {
if(myCart.myCurrentBank < 256) if(myCart.getBank() < myCart.romBankCount())
{ {
myROMBank->setSelectedIndex(myCart.myCurrentBank % myNumRomBanks, myOldState.bank != myCart.myCurrentBank); myROMBank->setSelectedIndex(myCart.getBank() % myNumRomBanks, myOldState.bank != myCart.getBank());
myRAMBank->setSelectedMax(myOldState.bank >= 256); myRAMBank->setSelectedMax(myOldState.bank >= myCart.romBankCount());
} }
else else
{ {
myROMBank->setSelectedMax(myOldState.bank < 256); myROMBank->setSelectedMax(myOldState.bank < myCart.romBankCount());
myRAMBank->setSelectedIndex(myCart.myCurrentBank - 256, myOldState.bank != myCart.myCurrentBank); myRAMBank->setSelectedIndex(myCart.getBank() - myCart.romBankCount(), myOldState.bank != myCart.getBank());
} }
CartDebugWidget::loadConfig(); CartDebugWidget::loadConfig();
@ -128,7 +128,7 @@ void Cartridge3EWidget::handleCommand(CommandSender* sender,
} }
else else
{ {
bank = 256; // default to first RAM bank bank = myCart.romBankCount(); // default to first RAM bank
myRAMBank->setSelectedIndex(0); myRAMBank->setSelectedIndex(0);
} }
} }
@ -137,7 +137,7 @@ void Cartridge3EWidget::handleCommand(CommandSender* sender,
if(myRAMBank->getSelected() < int(myNumRamBanks)) if(myRAMBank->getSelected() < int(myNumRamBanks))
{ {
myROMBank->setSelectedMax(); myROMBank->setSelectedMax();
bank = myRAMBank->getSelected() + 256; bank = myRAMBank->getSelected() + myCart.romBankCount();
} }
else else
{ {
@ -157,8 +157,8 @@ string Cartridge3EWidget::bankState()
{ {
ostringstream& buf = buffer(); ostringstream& buf = buffer();
uInt16& bank = myCart.myCurrentBank; uInt16 bank = myCart.getBank();
if(bank < 256) if(bank < myCart.romBankCount())
buf << "ROM bank #" << std::dec << bank % myNumRomBanks << ", RAM inactive"; buf << "ROM bank #" << std::dec << bank % myNumRomBanks << ", RAM inactive";
else else
buf << "ROM inactive, RAM bank #" << std::dec << bank % myNumRomBanks; buf << "ROM inactive, RAM bank #" << std::dec << bank % myNumRomBanks;

View File

@ -44,7 +44,7 @@ Cartridge3FWidget::Cartridge3FWidget(
ypos = addBaseInformation(size, "TigerVision", info.str()) + myLineHeight; ypos = addBaseInformation(size, "TigerVision", info.str()) + myLineHeight;
VariantList items; VariantList items;
for(uInt16 i = 0; i < cart.bankCount(); ++i) for(uInt16 i = 0; i < cart.romBankCount(); ++i)
VarList::push_back(items, Variant(i).toString() + " ($3F)"); VarList::push_back(items, Variant(i).toString() + " ($3F)");
ostringstream label; ostringstream label;

View File

@ -38,7 +38,7 @@ CartridgeFA2Widget::CartridgeFA2Widget(
<< "Startup bank = " << cart.startBank() << " or undetermined\n"; << "Startup bank = " << cart.startBank() << " or undetermined\n";
// Eventually, we should query this from the debugger/disassembler // Eventually, we should query this from the debugger/disassembler
for(uInt32 i = 0, offset = 0xFFC, spot = 0xFF5; i < cart.bankCount(); for(uInt32 i = 0, offset = 0xFFC, spot = 0xFF5; i < cart.romBankCount();
++i, offset += 0x1000) ++i, offset += 0x1000)
{ {
uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset]; uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset];
@ -58,7 +58,7 @@ CartridgeFA2Widget::CartridgeFA2Widget(
VarList::push_back(items, "3 ($FFF8)"); VarList::push_back(items, "3 ($FFF8)");
VarList::push_back(items, "4 ($FFF9)"); VarList::push_back(items, "4 ($FFF9)");
VarList::push_back(items, "5 ($FFFA)"); VarList::push_back(items, "5 ($FFFA)");
if(cart.bankCount() == 7) if(cart.romBankCount() == 7)
VarList::push_back(items, "6 ($FFFB)"); VarList::push_back(items, "6 ($FFFB)");
myBank = myBank =

View File

@ -26,7 +26,7 @@ CartridgeFCWidget::CartridgeFCWidget(
: CartDebugWidget(boss, lfont, nfont, x, y, w, h), : CartDebugWidget(boss, lfont, nfont, x, y, w, h),
myCart(cart) myCart(cart)
{ {
uInt16 size = cart.bankCount() * 4096; uInt16 size = cart.romBankCount() * 4096;
ostringstream info; ostringstream info;
info << "FC cartridge, up to eight 4K banks\n" info << "FC cartridge, up to eight 4K banks\n"
@ -42,7 +42,7 @@ CartridgeFCWidget::CartridgeFCWidget(
ypos = addBaseInformation(size, "Amiga Corp.", info.str()) + myLineHeight; ypos = addBaseInformation(size, "Amiga Corp.", info.str()) + myLineHeight;
VariantList items; VariantList items;
for (uInt16 i = 0; i < cart.bankCount(); ++i) for (uInt16 i = 0; i < cart.romBankCount(); ++i)
VarList::push_back(items, Variant(i).toString() + VarList::push_back(items, Variant(i).toString() +
" ($FFF8 = " + Variant(i & 0b11).toString() + " ($FFF8 = " + Variant(i & 0b11).toString() +
"/$FFF9 = " + Variant(i >> 2).toString() +")"); "/$FFF9 = " + Variant(i >> 2).toString() +")");

View File

@ -40,7 +40,7 @@ CartridgeMDMWidget::CartridgeMDMWidget(
ypos = addBaseInformation(size, "Edwin Blink", info.str(), 15) + myLineHeight; ypos = addBaseInformation(size, "Edwin Blink", info.str(), 15) + myLineHeight;
VariantList items; VariantList items;
for(uInt32 i = 0x800; i < (0x800U + myCart.bankCount()); ++i) for(uInt32 i = 0x800; i < (0x800U + myCart.romBankCount()); ++i)
{ {
info.str(""); info.str("");
info << std::dec << (i & 0xFF) << " ($" << Common::Base::HEX4 << i << ")"; info << std::dec << (i & 0xFF) << " ($" << Common::Base::HEX4 << i << ")";

View File

@ -35,14 +35,14 @@ CartridgeMNetworkWidget::CartridgeMNetworkWidget(
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeMNetworkWidget::initialize(GuiObject* boss, CartridgeMNetwork& cart, ostringstream& info) void CartridgeMNetworkWidget::initialize(GuiObject* boss, CartridgeMNetwork& cart, ostringstream& info)
{ {
uInt32 size = cart.bankCount() * cart.BANK_SIZE; uInt32 size = cart.romBankCount() * cart.BANK_SIZE;
int xpos = 2, int xpos = 2,
ypos = addBaseInformation(size, "M-Network", info.str(), 15) + ypos = addBaseInformation(size, "M-Network", info.str(), 15) +
myLineHeight; myLineHeight;
VariantList items0, items1; VariantList items0, items1;
for(int i = 0; i < cart.bankCount(); ++i) for(int i = 0; i < cart.romBankCount(); ++i)
VarList::push_back(items0, getSpotLower(i)); VarList::push_back(items0, getSpotLower(i));
for(int i = 0; i < 4; ++i) for(int i = 0; i < 4; ++i)
VarList::push_back(items1, getSpotUpper(i)); VarList::push_back(items1, getSpotUpper(i));

View File

@ -33,12 +33,12 @@ CartridgeSBWidget::CartridgeSBWidget(
myCart.getImage(size); myCart.getImage(size);
info << "SB SUPERbanking, 32 or 64 4K banks\n" info << "SB SUPERbanking, 32 or 64 4K banks\n"
<< "Hotspots are from $800 to $" << "Hotspots are from $800 to $"
<< Common::Base::HEX2 << (0x800 + myCart.bankCount() - 1) << ", including\n" << Common::Base::HEX2 << (0x800 + myCart.romBankCount() - 1) << ", including\n"
<< "mirrors ($900, $A00, $B00, ...)\n" << "mirrors ($900, $A00, $B00, ...)\n"
<< "Startup bank = " << std::dec << cart.startBank() << "\n"; << "Startup bank = " << std::dec << cart.startBank() << "\n";
// Eventually, we should query this from the debugger/disassembler // Eventually, we should query this from the debugger/disassembler
for(uInt32 i = 0, offset = 0xFFC, spot = 0x800; i < myCart.bankCount(); for(uInt32 i = 0, offset = 0xFFC, spot = 0x800; i < myCart.romBankCount();
++i, offset += 0x1000, ++spot) ++i, offset += 0x1000, ++spot)
{ {
uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset]; uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset];

View File

@ -68,7 +68,7 @@ void RomWidget::loadConfig()
const CartState& oldstate = static_cast<const CartState&>(cart.getOldState()); const CartState& oldstate = static_cast<const CartState&>(cart.getOldState());
// Fill romlist the current bank of source or disassembly // Fill romlist the current bank of source or disassembly
myListIsDirty |= cart.disassemble(myListIsDirty); myListIsDirty |= cart.disassemblePC(myListIsDirty);
if(myListIsDirty) if(myListIsDirty)
{ {
myRomList->setList(cart.disassembly()); myRomList->setList(cart.disassembly());

View File

@ -83,7 +83,7 @@ uInt16 Cartridge::bankSize(uInt16 bank) const
getImage(size); getImage(size);
return std::min(uInt32(size) / bankCount(), 4_KB); // assuming that each bank has the same size return std::min(uInt32(size) / romBankCount(), 4_KB); // assuming that each bank has the same size
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -145,13 +145,13 @@ string Cartridge::getAccessCounters() const
ostringstream out; ostringstream out;
uInt32 offset = 0; uInt32 offset = 0;
for(uInt16 bank = 0; bank < bankCount(); ++bank) for(uInt16 bank = 0; bank < romBankCount(); ++bank)
{ {
uInt16 origin = bankOrigin(bank); uInt16 origin = bankOrigin(bank);
uInt16 bankSize = this->bankSize(bank); uInt16 bankSize = this->bankSize(bank);
out << "Bank " << Common::Base::toString(bank, Common::Base::Fmt::_10_8) << " / 0.." out << "Bank " << Common::Base::toString(bank, Common::Base::Fmt::_10_8) << " / 0.."
<< Common::Base::toString(bankCount() - 1, Common::Base::Fmt::_10_8) << " reads:\n"; << Common::Base::toString(romBankCount() - 1, Common::Base::Fmt::_10_8) << " reads:\n";
for(uInt16 addr = 0; addr < bankSize; ++addr) for(uInt16 addr = 0; addr < bankSize; ++addr)
{ {
out << Common::Base::HEX4 << (addr | origin) << "," out << Common::Base::HEX4 << (addr | origin) << ","
@ -159,7 +159,7 @@ string Cartridge::getAccessCounters() const
} }
out << "\n"; out << "\n";
out << "Bank " << Common::Base::toString(bank, Common::Base::Fmt::_10_8) << " / 0.." out << "Bank " << Common::Base::toString(bank, Common::Base::Fmt::_10_8) << " / 0.."
<< Common::Base::toString(bankCount() - 1, Common::Base::Fmt::_10_8) << " writes:\n"; << Common::Base::toString(romBankCount() - 1, Common::Base::Fmt::_10_8) << " writes:\n";
for(uInt16 addr = 0; addr < bankSize; ++addr) for(uInt16 addr = 0; addr < bankSize; ++addr)
{ {
out << Common::Base::HEX4 << (addr | origin) << "," out << Common::Base::HEX4 << (addr | origin) << ","
@ -230,11 +230,11 @@ uInt16 Cartridge::initializeStartBank(uInt16 defaultBank)
int propsBank = myStartBankFromPropsFunc(); int propsBank = myStartBankFromPropsFunc();
if(randomStartBank()) if(randomStartBank())
return myStartBank = mySystem->randGenerator().next() % bankCount(); return myStartBank = mySystem->randGenerator().next() % romBankCount();
else if(propsBank >= 0) else if(propsBank >= 0)
return myStartBank = BSPF::clamp(propsBank, 0, bankCount() - 1); return myStartBank = BSPF::clamp(propsBank, 0, romBankCount() - 1);
else else
return myStartBank = BSPF::clamp(int(defaultBank), 0, bankCount() - 1); return myStartBank = BSPF::clamp(int(defaultBank), 0, romBankCount() - 1);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -180,7 +180,7 @@ class Cartridge : public Device
virtual uInt16 getBank(uInt16 address = 0) const { return 0; } virtual uInt16 getBank(uInt16 address = 0) const { return 0; }
/** /**
Query the number of 'banks' supported by the cartridge. Note that Query the number of ROM 'banks' supported by the cartridge. Note that
this information is cart-specific, where each cart basically defines this information is cart-specific, where each cart basically defines
what a 'bank' is. what a 'bank' is.
@ -192,7 +192,15 @@ class Cartridge : public Device
RAM slices at multiple access points) is so complicated that the RAM slices at multiple access points) is so complicated that the
cart will report having only one 'virtual' bank. cart will report having only one 'virtual' bank.
*/ */
virtual uInt16 bankCount() const { return 1; } virtual uInt16 romBankCount() const { return 1; }
/**
Query the number of RAM 'banks' supported by the cartridge. Note that
this information is cart-specific, where each cart basically defines
what a 'bank' is.
*/
virtual uInt16 ramBankCount() const { return 0; }
/** /**
Get the size of a bank. Get the size of a bank.

View File

@ -22,52 +22,42 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge3E::Cartridge3E(const ByteBuffer& image, size_t size, Cartridge3E::Cartridge3E(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: Cartridge(settings, md5), : CartridgeEnhanced(image, size, md5, settings)
mySize(size),
myRomBanks(256/*uInt16(size) >> 11*/)
{ {
// Allocate array for the ROM image myBankShift = BANK_SHIFT;
myImage = make_unique<uInt8[]>(mySize); myRamSize = RAM_SIZE;
myRamBankCount = RAM_BANKS;
// Copy the ROM image into my buffer myRamWpHigh = RAM_HIGH_WP;
std::copy_n(image.get(), mySize, myImage.get());
createRomAccessArrays(mySize + myRAM.size());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Cartridge3E::reset()
{
initializeRAM(myRAM.data(), myRAM.size());
initializeStartBank(0);
// We'll map the startup bank into the first segment upon reset
bank(startBank());
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Cartridge3E::install(System& system) void Cartridge3E::install(System& system)
{ {
mySystem = &system; CartridgeEnhanced::install(system);
System::PageAccess access(this, System::PageAccessType::READWRITE); System::PageAccess access(this, System::PageAccessType::READWRITE);
// The hotspots ($3E and $3F) are in TIA address space, so we claim it here // The hotspots ($3E and $3F) are in TIA address space, so we claim it here
for(uInt16 addr = 0x00; addr < 0x40; addr += System::PAGE_SIZE) for(uInt16 addr = 0x00; addr < 0x40; addr += System::PAGE_SIZE)
mySystem->setPageAccess(addr, access); mySystem->setPageAccess(addr, access);
}
// Setup the second segment to always point to the last ROM slice // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
access.type = System::PageAccessType::READ; bool Cartridge3E::checkSwitchBank(uInt16 address, uInt8 value)
for(uInt16 addr = 0x1800; addr < 0x2000; addr += System::PAGE_SIZE) {
{ // Switch banks if necessary
access.directPeekBase = &myImage[(mySize - 2048) + (addr & 0x07FF)]; if(address == 0x003F) {
access.romAccessBase = &myRomAccessBase[(mySize - 2048) + (addr & 0x07FF)]; // Switch ROM bank into segment 0
access.romPeekCounter = &myRomAccessCounter[(mySize - 2048) + (addr & 0x07FF)]; bank(value);
access.romPokeCounter = &myRomAccessCounter[(mySize - 2048) + (addr & 0x07FF) + myAccessSize]; return true;
mySystem->setPageAccess(addr, access);
} }
else if(address == 0x003E)
// Install pages for the startup bank into the first segment {
bank(startBank()); // Switch RAM bank into segment 0
bank(value + romBankCount());
return true;
}
return false;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -76,215 +66,8 @@ uInt8 Cartridge3E::peek(uInt16 address)
uInt16 peekAddress = address; uInt16 peekAddress = address;
address &= 0x0FFF; address &= 0x0FFF;
// Due to the way paging is set up, the only way to get here is a TIA read or
// attempting to read from the RAM write port
if(address < 0x0040) // TIA access if(address < 0x0040) // TIA access
return mySystem->tia().peek(address); return mySystem->tia().peek(address);
else if(myCurrentBank >= myRomBanks)
{
// Reading from the write port triggers an unwanted write
return peekRAM(myRAM[(address & 0x03FF) + ((myCurrentBank - myRomBanks) << 10)], peekAddress);
}
// Make compiler happy; should never get here return CartridgeEnhanced::peek(peekAddress);
return myImage[(address & 0x07FF) + mySize - 2048];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Cartridge3E::poke(uInt16 address, uInt8 value)
{
uInt16 pokeAddress = address;
address &= 0x0FFF;
// Switch banks if necessary. Armin (Kroko) says there are no mirrored
// hotspots.
if(address < 0x0040)
{
if(address == 0x003F)
bank(value);
else if(address == 0x003E)
bank(value + myRomBanks);
return mySystem->tia().poke(address, value);
}
else if(myCurrentBank >= myRomBanks)
{
if(address & 0x0400)
{
pokeRAM(myRAM[(address & 0x03FF) + ((myCurrentBank - myRomBanks) << 10)],
pokeAddress, value);
return true;
}
else
{
// Writing to the read port should be ignored, but trigger a break if option enabled
uInt8 dummy;
pokeRAM(dummy, pokeAddress, value);
myRamWriteAccess = pokeAddress;
return false;
}
}
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Cartridge3E::bank(uInt16 bank)
{
if(bankLocked()) return false;
if(bank < myRomBanks)
{
// Make sure the bank they're asking for is reasonable
if((uInt32(bank) << 11) < mySize)
{
myCurrentBank = bank;
}
else
{
// Oops, the bank they're asking for isn't valid so let's wrap it
// around to a valid bank number
myCurrentBank = bank % (mySize >> 11);
}
uInt32 offset = myCurrentBank << 11;
// Setup the page access methods for the current bank
System::PageAccess access(this, System::PageAccessType::READ);
// Map ROM image into the system
for(uInt16 addr = 0x1000; addr < 0x1800; addr += System::PAGE_SIZE)
{
access.directPeekBase = &myImage[offset + (addr & 0x07FF)];
access.romAccessBase = &myRomAccessBase[offset + (addr & 0x07FF)];
access.romPeekCounter = &myRomAccessCounter[offset + (addr & 0x07FF)];
access.romPokeCounter = &myRomAccessCounter[offset + (addr & 0x07FF) + myAccessSize];
mySystem->setPageAccess(addr, access);
}
}
else
{
bank -= myRomBanks;
bank %= myRamBanks;
myCurrentBank = bank + myRomBanks;
uInt32 offset = bank << 10;
// Setup the page access methods for the current bank
System::PageAccess access(this, System::PageAccessType::READ);
// Map read-port RAM image into the system
// Writes are mapped to poke(), to check for write to the read port
for(uInt16 addr = 0x1000; addr < 0x1400; addr += System::PAGE_SIZE)
{
access.directPeekBase = &myRAM[offset + (addr & 0x03FF)];
access.romAccessBase = &myRomAccessBase[mySize + offset + (addr & 0x03FF)];
access.romPeekCounter = &myRomAccessCounter[mySize + offset + (addr & 0x03FF)];
access.romPokeCounter = &myRomAccessCounter[mySize + offset + (addr & 0x03FF) + myAccessSize];
mySystem->setPageAccess(addr, access);
}
access.directPeekBase = nullptr;
access.type = System::PageAccessType::WRITE;
// Map write-port RAM image into the system
// Reads are mapped to peek(), to check for read from write port
for(uInt16 addr = 0x1400; addr < 0x1800; addr += System::PAGE_SIZE)
{
access.romAccessBase = &myRomAccessBase[mySize + offset + (addr & 0x03FF)];
access.romPeekCounter = &myRomAccessCounter[mySize + offset + (addr & 0x03FF)];
access.romPokeCounter = &myRomAccessCounter[mySize + offset + (addr & 0x03FF) + myAccessSize];
mySystem->setPageAccess(addr, access);
}
}
return myBankChanged = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 Cartridge3E::getBank(uInt16 address) const
{
if (address & 0x800)
return myRomBanks - 1; // 2K slices, fixed bank
else
return myCurrentBank;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 Cartridge3E::bankCount() const
{
// Because the RAM banks always start at 256 and above, we require the
// number of ROM banks to be 256
// If the RAM banks were simply appended to the number of actual
// ROM banks, bank numbers would be ambiguous (ie, would bank 128 be
// the last bank of ROM, or one of the banks of RAM?)
return myRomBanks + myRamBanks;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 Cartridge3E::bankSize(uInt16 bank) const
{
return 2_KB; // we cannot use bankCount() here, because it delivers wrong numbers
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Cartridge3E::patch(uInt16 address, uInt8 value)
{
address &= 0x0FFF;
if(address < 0x0800)
{
if(myCurrentBank < myRomBanks)
myImage[(address & 0x07FF) + (myCurrentBank << 11)] = value;
else
myRAM[(address & 0x03FF) + ((myCurrentBank - myRomBanks) << 10)] = value;
}
else
myImage[(address & 0x07FF) + mySize - 2048] = value;
return myBankChanged = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt8* Cartridge3E::getImage(size_t& size) const
{
size = mySize;
return myImage.get();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Cartridge3E::save(Serializer& out) const
{
try
{
out.putShort(myCurrentBank);
out.putByteArray(myRAM.data(), myRAM.size());
}
catch(...)
{
cerr << "ERROR: Cartridge3E::save" << endl;
return false;
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Cartridge3E::load(Serializer& in)
{
try
{
myCurrentBank = in.getShort();
in.getByteArray(myRAM.data(), myRAM.size());
}
catch(...)
{
cerr << "ERROR: Cartridge3E::load" << endl;
return false;
}
// Now, go to the current bank
bank(myCurrentBank);
return true;
} }

View File

@ -21,7 +21,7 @@
class System; class System;
#include "bspf.hxx" #include "bspf.hxx"
#include "Cart.hxx" #include "CartEnhanced.hxx"
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
#include "Cart3EWidget.hxx" #include "Cart3EWidget.hxx"
#endif #endif
@ -47,10 +47,8 @@ class System;
by storing its value into $3F. To map RAM in the first 2K segment by storing its value into $3F. To map RAM in the first 2K segment
instead, store the RAM bank number into $3E. instead, store the RAM bank number into $3E.
This implementation of 3E bankswitching numbers the ROM banks 0 to This implementation of 3E bankswitching numbers the RAM banks (up to 32)
255, and the RAM banks 256 to 287. This is done because the public after the ROM banks (up to 256).
bankswitching interface requires us to use one bank number, not one
bank number plus the knowledge of whether it's RAM or ROM.
All 32K of potential RAM is available to a game using this class, even All 32K of potential RAM is available to a game using this class, even
though real cartridges might not have the full 32K: We have no way to though real cartridges might not have the full 32K: We have no way to
@ -58,10 +56,10 @@ class System;
may add a stella.pro property for this), but for now it shouldn't cause may add a stella.pro property for this), but for now it shouldn't cause
any problems. (Famous last words...) any problems. (Famous last words...)
@author B. Watson @author B. Watson, Thomas Jentzsch
*/ */
class Cartridge3E : public Cartridge class Cartridge3E : public CartridgeEnhanced
{ {
friend class Cartridge3EWidget; friend class Cartridge3EWidget;
@ -79,10 +77,6 @@ class Cartridge3E : public Cartridge
virtual ~Cartridge3E() = default; virtual ~Cartridge3E() = default;
public: public:
/**
Reset device to its power-on state
*/
void reset() override;
/** /**
Install cartridge in the specified system. Invoked by the system Install cartridge in the specified system. Invoked by the system
@ -92,66 +86,6 @@ class Cartridge3E : public Cartridge
*/ */
void install(System& system) override; void install(System& system) override;
/**
Install pages for the specified bank in the system.
@param bank The bank that should be installed in the system
*/
bool bank(uInt16 bank) override;
/**
Get the current bank.
@param address The address to use when querying the bank
*/
uInt16 getBank(uInt16 address = 0) const override;
/**
Query the number of banks supported by the cartridge.
*/
uInt16 bankCount() const override;
/**
Get the size of a bank.
@param bank The bank to get the size for
@return The bank's size
*/
virtual uInt16 bankSize(uInt16 bank = 0) const;
/**
Patch the cartridge ROM.
@param address The ROM address to patch
@param value The value to place into the address
@return Success or failure of the patch operation
*/
bool patch(uInt16 address, uInt8 value) override;
/**
Access the internal ROM image for this cartridge.
@param size Set to the size of the internal ROM image data
@return A pointer to the internal ROM image data
*/
const uInt8* getImage(size_t& size) const override;
/**
Save the current state of this cart to the given Serializer.
@param out The Serializer object to use
@return False on any errors, else true
*/
bool save(Serializer& out) const override;
/**
Load the current state of this cart from the given Serializer.
@param in The Serializer object to use
@return False on any errors, else true
*/
bool load(Serializer& in) override;
/** /**
Get a descriptor for the device name (used in error checking). Get a descriptor for the device name (used in error checking).
@ -179,33 +113,21 @@ class Cartridge3E : public Cartridge
*/ */
uInt8 peek(uInt16 address) override; uInt8 peek(uInt16 address) override;
/** private:
Change the byte at the specified address to the given value bool checkSwitchBank(uInt16 address, uInt8 value) override;
@param address The address where the value should be stored
@param value The value to be stored at the address
@return True if the poke changed the device address space, else false
*/
bool poke(uInt16 address, uInt8 value) override;
private: private:
// Pointer to a dynamically allocated ROM image of the cartridge // log(ROM bank segment size) / log(2)
ByteBuffer myImage; static constexpr uInt16 BANK_SHIFT = 11; // = 2K = 0x0800
// RAM contents. For now every ROM gets all 32K of potential RAM // The size of extra RAM in ROM address space
std::array<uInt8, 32_KB> myRAM; static constexpr uInt16 RAM_BANKS = 32;
// Size of the ROM image // RAM size
size_t mySize{0}; static constexpr uInt16 RAM_SIZE = RAM_BANKS << (BANK_SHIFT - 1); // = 32K = 0x4000;
// Size of the ROM image // Write port for extra RAM is at high address
uInt16 myRomBanks{0}; static constexpr bool RAM_HIGH_WP = true;
// Size of the ROM image
uInt16 myRamBanks{32};
// Indicates which bank is currently active for the first segment
uInt16 myCurrentBank{0};
private: private:
// Following constructors and assignment operators not supported // Following constructors and assignment operators not supported

View File

@ -85,7 +85,7 @@ uInt16 Cartridge3EPlus::getBank(uInt16 address) const
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 Cartridge3EPlus::bankCount() const uInt16 Cartridge3EPlus::romBankCount() const
{ {
return uInt16(mySize >> 10); // 1K slices return uInt16(mySize >> 10); // 1K slices
} }

View File

@ -80,7 +80,7 @@ class Cartridge3EPlus: public Cartridge
/** /**
Query the number of banks supported by the cartridge. Query the number of banks supported by the cartridge.
*/ */
uInt16 bankCount() const override; uInt16 romBankCount() const override;
/** /**
Patch the cartridge ROM. Patch the cartridge ROM.

View File

@ -46,7 +46,7 @@ bool Cartridge3F::checkSwitchBank(uInt16 address, uInt8 value)
if(address <= 0x003F) if(address <= 0x003F)
{ {
// Make sure the bank they're asking for is reasonable // Make sure the bank they're asking for is reasonable
bank(value % bankCount(), 0); bank(value % romBankCount(), 0);
return true; return true;
} }
return false; return false;

View File

@ -406,7 +406,7 @@ uInt16 CartridgeAR::getBank(uInt16) const
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeAR::bankCount() const uInt16 CartridgeAR::romBankCount() const
{ {
return 32; return 32;
} }

View File

@ -87,7 +87,7 @@ class CartridgeAR : public Cartridge
/** /**
Query the number of banks supported by the cartridge. Query the number of banks supported by the cartridge.
*/ */
uInt16 bankCount() const override; uInt16 romBankCount() const override;
/** /**
Patch the cartridge ROM. Patch the cartridge ROM.

View File

@ -457,7 +457,7 @@ uInt16 CartridgeBUS::getBank(uInt16) const
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeBUS::bankCount() const uInt16 CartridgeBUS::romBankCount() const
{ {
return 7; return 7;
} }

View File

@ -98,7 +98,7 @@ class CartridgeBUS : public Cartridge
/** /**
Query the number of banks supported by the cartridge. Query the number of banks supported by the cartridge.
*/ */
uInt16 bankCount() const override; uInt16 romBankCount() const override;
/** /**
Patch the cartridge ROM. Patch the cartridge ROM.

View File

@ -430,7 +430,7 @@ uInt16 CartridgeCDF::getBank(uInt16) const
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeCDF::bankCount() const uInt16 CartridgeCDF::romBankCount() const
{ {
return 7; return 7;
} }

View File

@ -104,7 +104,7 @@ class CartridgeCDF : public Cartridge
/** /**
Query the number of banks supported by the cartridge. Query the number of banks supported by the cartridge.
*/ */
uInt16 bankCount() const override; uInt16 romBankCount() const override;
/** /**
Patch the cartridge ROM. Patch the cartridge ROM.

View File

@ -163,7 +163,7 @@ uInt16 CartridgeCM::getBank(uInt16) const
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeCM::bankCount() const uInt16 CartridgeCM::romBankCount() const
{ {
// We report 4 banks (of ROM), even though RAM can overlap the upper 2K // We report 4 banks (of ROM), even though RAM can overlap the upper 2K
// of cart address space at some times // of cart address space at some times

View File

@ -155,7 +155,7 @@ class CartridgeCM : public Cartridge
/** /**
Query the number of banks supported by the cartridge. Query the number of banks supported by the cartridge.
*/ */
uInt16 bankCount() const override; uInt16 romBankCount() const override;
/** /**
Patch the cartridge ROM. Patch the cartridge ROM.

View File

@ -255,7 +255,7 @@ uInt16 CartridgeCTY::getBank(uInt16) const
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeCTY::bankCount() const uInt16 CartridgeCTY::romBankCount() const
{ {
return 8; return 8;
} }

View File

@ -153,7 +153,7 @@ class CartridgeCTY : public Cartridge
/** /**
Query the number of banks supported by the cartridge. Query the number of banks supported by the cartridge.
*/ */
uInt16 bankCount() const override; uInt16 romBankCount() const override;
/** /**
Patch the cartridge ROM. Patch the cartridge ROM.

View File

@ -399,7 +399,7 @@ uInt16 CartridgeDPC::getBank(uInt16) const
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeDPC::bankCount() const uInt16 CartridgeDPC::romBankCount() const
{ {
return 2; return 2;
} }

View File

@ -85,7 +85,7 @@ class CartridgeDPC : public Cartridge
/** /**
Query the number of banks supported by the cartridge. Query the number of banks supported by the cartridge.
*/ */
uInt16 bankCount() const override; uInt16 romBankCount() const override;
/** /**
Patch the cartridge ROM. Patch the cartridge ROM.

View File

@ -619,7 +619,7 @@ uInt16 CartridgeDPCPlus::getBank(uInt16) const
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeDPCPlus::bankCount() const uInt16 CartridgeDPCPlus::romBankCount() const
{ {
return 6; return 6;
} }

View File

@ -100,7 +100,7 @@ class CartridgeDPCPlus : public Cartridge
/** /**
Query the number of banks supported by the cartridge. Query the number of banks supported by the cartridge.
*/ */
uInt16 bankCount() const override; uInt16 romBankCount() const override;
/** /**
Patch the cartridge ROM. Patch the cartridge ROM.

View File

@ -34,16 +34,19 @@ CartridgeEnhanced::CartridgeEnhanced(const ByteBuffer& image, size_t size,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeEnhanced::install(System& system) void CartridgeEnhanced::install(System& system)
{ {
// Copy the ROM image into my buffer // limit banked RAM size to the size of one RAM bank
createRomAccessArrays(mySize); uInt16 ramSize = myRamBankCount ? 1 << (myBankShift - 1) : myRamSize;
// calculate bank switching and RAM sizes and masks // calculate bank switching and RAM sizes and masks
myBankSize = 1 << myBankShift; // e.g. = 2 ^ 12 = 4K = 0x1000 myBankSize = 1 << myBankShift; // e.g. = 2 ^ 12 = 4K = 0x1000
myBankMask = myBankSize - 1; // e.g. = 0x0FFF myBankMask = myBankSize - 1; // e.g. = 0x0FFF
myBankSegs = 1 << (12 - myBankShift); // e.g. = 1 myBankSegs = 1 << (12 - myBankShift); // e.g. = 1
myRamMask = myRamSize - 1; // e.g. = 0xFFFF (doesn't matter for RAM size 0) myRomOffset = myRamBankCount ? 0 : myRamSize * 2;
myWriteOffset = myRamWpHigh ? myRamSize : 0; myRamMask = ramSize - 1; // e.g. = 0xFFFF (doesn't matter for RAM size 0)
myReadOffset = myRamWpHigh ? 0 : myRamSize; myWriteOffset = myRamWpHigh ? ramSize : 0;
myReadOffset = myRamWpHigh ? 0 : ramSize;
createRomAccessArrays(mySize + (myRomOffset ? 0 : myRamSize));
// Allocate array for the current bank segments slices // Allocate array for the current bank segments slices
myCurrentSegOffset = make_unique<uInt32[]>(myBankSegs); myCurrentSegOffset = make_unique<uInt32[]>(myBankSegs);
@ -51,9 +54,11 @@ void CartridgeEnhanced::install(System& system)
// Allocate array for the RAM area // Allocate array for the RAM area
myRAM = make_unique<uInt8[]>(myRamSize); myRAM = make_unique<uInt8[]>(myRamSize);
// Setup page access
mySystem = &system; mySystem = &system;
if(myRomOffset)
{
// Setup page access for extended RAM; banked RAM will be setup in bank()
System::PageAccess access(this, System::PageAccessType::READ); System::PageAccess access(this, System::PageAccessType::READ);
// Set the page accessing method for the RAM writing pages // Set the page accessing method for the RAM writing pages
@ -80,12 +85,13 @@ void CartridgeEnhanced::install(System& system)
access.romPokeCounter = &myRomAccessCounter[myReadOffset + offset + myAccessSize]; access.romPokeCounter = &myRomAccessCounter[myReadOffset + offset + myAccessSize];
mySystem->setPageAccess(addr, access); mySystem->setPageAccess(addr, access);
} }
}
// Install pages for the startup bank (TODO: currently only in first bank segment) // Install pages for the startup bank (TODO: currently only in first bank segment)
bank(startBank(), 0); bank(startBank(), 0);
if(mySize >= 4_KB && myBankSegs > 1) if(mySize >= 4_KB && myBankSegs > 1)
// Setup the last bank segment to always point to the last ROM segment // Setup the last bank segment to always point to the last ROM segment
bank(bankCount() - 1, myBankSegs - 1); bank(romBankCount() - 1, myBankSegs - 1);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -106,28 +112,67 @@ uInt8 CartridgeEnhanced::peek(uInt16 address)
if (hotspot()) if (hotspot())
checkSwitchBank(address & 0x0FFF); checkSwitchBank(address & 0x0FFF);
if(isRamBank(address))
{
address &= myRamMask;
// This is a read access to a write port!
// Reading from the write port triggers an unwanted write
// The RAM banks follow the ROM banks and are half the size of a ROM bank
return peekRAM(myRAM[((myCurrentSegOffset[(peekAddress & 0xFFF) >> myBankShift] - mySize) >> 1) + address],
peekAddress);
}
else
{
address &= myBankMask; address &= myBankMask;
// Write port is e.g. at 0xF000 - 0xF07F (128 bytes) // Write port is e.g. at 0xF000 - 0xF07F (128 bytes)
if(address < myReadOffset + myRamSize && address >= myReadOffset) if(address < myReadOffset + myRamSize && address >= myReadOffset)
// This is a read access to a write port! // This is a read access to a write port!
// Reading from the write port triggers an unwanted write
return peekRAM(myRAM[address], peekAddress); return peekRAM(myRAM[address], peekAddress);
else else
return myImage[myCurrentSegOffset[(peekAddress & 0xFFF) >> myBankShift] + address]; return myImage[myCurrentSegOffset[(peekAddress & 0xFFF) >> myBankShift] + address];
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeEnhanced::poke(uInt16 address, uInt8 value) bool CartridgeEnhanced::poke(uInt16 address, uInt8 value)
{ {
uInt16 pokeAddress = address;
// Switch banks if necessary // Switch banks if necessary
// Note: (TODO?)
// The checkSwitchBank() call makes no difference between ROM and e.g TIA space
// Writing to e.g. 0xf0xx might triger a bankswitch, is (and was!) this a bug???
if (checkSwitchBank(address & 0x0FFF, value)) if (checkSwitchBank(address & 0x0FFF, value))
return false; return false;
address &= myBankMask;
if(myRamSize) if(myRamSize)
{ {
uInt16 pokeAddress = address;
if(isRamBank(address))
{
if(bool(address & (myBankSize >> 1)) == myRamWpHigh)
{
address &= myRamMask;
// The RAM banks follow the ROM banks and are half the size of a ROM bank
pokeRAM(myRAM[((myCurrentSegOffset[(pokeAddress & 0xFFF) >> myBankShift] - mySize) >> 1) + address],
pokeAddress, value);
return true;
}
else
{
// Writing to the read port should be ignored, but trigger a break if option enabled
uInt8 dummy;
pokeRAM(dummy, pokeAddress, value);
myRamWriteAccess = pokeAddress;
}
}
else
{
//address &= myBankMask;
if(bool(address & myRamSize) == myRamWpHigh) if(bool(address & myRamSize) == myRamWpHigh)
{ {
pokeRAM(myRAM[address & myRamMask], pokeAddress, value); pokeRAM(myRAM[address & myRamMask], pokeAddress, value);
@ -142,27 +187,28 @@ bool CartridgeEnhanced::poke(uInt16 address, uInt8 value)
myRamWriteAccess = pokeAddress; myRamWriteAccess = pokeAddress;
} }
} }
}
return false; return false;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment, bool isRAM) bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment)
{ {
if(bankLocked()) return false; if(bankLocked()) return false;
uInt16 segmentOffset = segment << myBankShift; uInt16 segmentOffset = segment << myBankShift;
if(!isRAM) if(!myRamBankCount || bank < romBankCount())
{ {
// Setup ROM bank // Setup ROM bank
// Remember what bank is in which segment uInt16 romBank = bank % romBankCount();
uInt32 bankOffset = myCurrentSegOffset[segment] = bank << myBankShift; // Remember what bank is in this segment
uInt32 bankOffset = myCurrentSegOffset[segment] = romBank << myBankShift;
uInt16 hotspot = this->hotspot(); uInt16 hotspot = this->hotspot();
uInt16 hotSpotAddr; uInt16 hotSpotAddr;
uInt16 fromAddr = (segmentOffset + 0x1000 + myRamSize * 2) & ~System::PAGE_MASK; uInt16 fromAddr = (0x1000 + segmentOffset + myRomOffset) & ~System::PAGE_MASK;
// for ROMs < 4_KB, the whole address space will be mapped. // for ROMs < 4_KB, the whole address space will be mapped.
uInt16 toAddr = (segmentOffset + 0x1000 + (mySize < 4_KB ? 0x1000 : myBankSize)) & ~System::PAGE_MASK; uInt16 toAddr = (0x1000 + segmentOffset + (mySize < 4_KB ? 0x1000 : myBankSize)) & ~System::PAGE_MASK;
if(hotspot) if(hotspot)
hotSpotAddr = (hotspot & ~System::PAGE_MASK); hotSpotAddr = (hotspot & ~System::PAGE_MASK);
@ -185,24 +231,24 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment, bool isRAM)
mySystem->setPageAccess(addr, access); mySystem->setPageAccess(addr, access);
} }
} }
/*else else
{ {
// Setup RAM bank // Setup RAM bank
// TODO: define offsets on init uInt16 ramBank = (bank - romBankCount()) % myRamBankCount;
uInt16 myWriteBankOffset = myBankSize >> 1; // The RAM banks follow the ROM banks and are half the size of a ROM bank
uInt16 myReadBankOffset = 0; uInt32 bankOffset = uInt32(mySize) + (ramBank << (myBankShift - 1));
// Remember what bank is in which segment // Remember what bank is in this segment
uInt32 bankOffset = myCurrentSegOffset[segment] = bank << myBankShift; myCurrentSegOffset[segment] = bank << myBankShift;
// Set the page accessing method for the RAM writing pages // Set the page accessing method for the RAM writing pages
uInt16 fromAddr = (segmentOffset + myWriteBankOffset + 0x1000) & ~System::PAGE_MASK; uInt16 fromAddr = (0x1000 + segmentOffset + myWriteOffset) & ~System::PAGE_MASK;
uInt16 toAddr = (segmentOffset + myWriteBankOffset + 0x1000 + myBankSize >> 1) & ~System::PAGE_MASK; uInt16 toAddr = (0x1000 + segmentOffset + myWriteOffset + (myBankSize >> 1)) & ~System::PAGE_MASK;
System::PageAccess access(this, System::PageAccessType::WRITE); System::PageAccess access(this, System::PageAccessType::WRITE);
for(uInt16 addr = fromAddr; addr < toAddr; addr += System::PAGE_SIZE) for(uInt16 addr = fromAddr; addr < toAddr; addr += System::PAGE_SIZE)
{ {
uInt32 offset = bankOffset + (addr & myBankMask); uInt32 offset = bankOffset + (addr & myRamMask);
access.romAccessBase = &myRomAccessBase[offset]; access.romAccessBase = &myRomAccessBase[offset];
access.romPeekCounter = &myRomAccessCounter[offset]; access.romPeekCounter = &myRomAccessCounter[offset];
@ -211,25 +257,23 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment, bool isRAM)
} }
// Set the page accessing method for the RAM reading pages // Set the page accessing method for the RAM reading pages
fromAddr = (segmentOffset + myReadBankOffset + 0x1000) & ~System::PAGE_MASK; fromAddr = (0x1000 + segmentOffset + myReadOffset) & ~System::PAGE_MASK;
toAddr = (segmentOffset + myReadBankOffset + 0x1000 + myBankSize >> 1) & ~System::PAGE_MASK; toAddr = (0x1000 + segmentOffset + myReadOffset + (myBankSize >> 1)) & ~System::PAGE_MASK;
access.type = System::PageAccessType::READ; access.type = System::PageAccessType::READ;
for(uInt16 addr = fromAddr; addr < toAddr; addr += System::PAGE_SIZE) for(uInt16 addr = fromAddr; addr < toAddr; addr += System::PAGE_SIZE)
{ {
uInt32 offset = bankOffset + (addr & myBankMask); uInt32 offset = bankOffset + (addr & myRamMask);
access.directPeekBase = &myRAM[offset - mySize];
uInt16 offset = addr & myRamMask;
access.directPeekBase = &myBankRAM[offset];
access.romAccessBase = &myRomAccessBase[offset]; access.romAccessBase = &myRomAccessBase[offset];
access.romPeekCounter = &myRomAccessCounter[offset]; access.romPeekCounter = &myRomAccessCounter[offset];
access.romPokeCounter = &myRomAccessCounter[offset + myAccessSize]; access.romPokeCounter = &myRomAccessCounter[offset + myAccessSize];
mySystem->setPageAccess(addr, access); mySystem->setPageAccess(addr, access);
} }
}*/
}
return myBankChanged = true; return myBankChanged = true;
} }
@ -246,14 +290,32 @@ uInt16 CartridgeEnhanced::getSegmentBank(uInt16 segment) const
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeEnhanced::bankCount() const uInt16 CartridgeEnhanced::romBankCount() const
{ {
return uInt16(mySize >> myBankShift); return uInt16(mySize >> myBankShift);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeEnhanced::ramBankCount() const
{
return myRamBankCount;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeEnhanced::isRamBank(uInt16 address) const
{
return myRamBankCount ? getBank(address) >= romBankCount() : false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeEnhanced::patch(uInt16 address, uInt8 value) bool CartridgeEnhanced::patch(uInt16 address, uInt8 value)
{ {
if(isRamBank(address))
{
myRAM[((myCurrentSegOffset[(address & 0xFFF) >> myBankShift] - mySize) >> 1) + (address & myRamMask)] = value;
}
else
{
if((address & myBankMask) < myRamSize * 2) if((address & myBankMask) < myRamSize * 2)
{ {
// Normally, a write to the read port won't do anything // Normally, a write to the read port won't do anything
@ -263,6 +325,7 @@ bool CartridgeEnhanced::patch(uInt16 address, uInt8 value)
} }
else else
myImage[myCurrentSegOffset[(address & 0xFFF) >> myBankShift] + (address & myBankMask)] = value; myImage[myCurrentSegOffset[(address & 0xFFF) >> myBankShift] + (address & myBankMask)] = value;
}
return myBankChanged = true; return myBankChanged = true;
} }

View File

@ -62,11 +62,10 @@ class CartridgeEnhanced : public Cartridge
@param bank The bank that should be installed in the system @param bank The bank that should be installed in the system
@param segment The segment the bank should be using @param segment The segment the bank should be using
@param isRAM True if the bank is a RAM bank
@return true, if bank has changed @return true, if bank has changed
*/ */
bool bank(uInt16 bank, uInt16 segment, bool isRAM = false); bool bank(uInt16 bank, uInt16 segment);
/** /**
Install pages for the specified bank in the system. Install pages for the specified bank in the system.
@ -94,7 +93,21 @@ class CartridgeEnhanced : public Cartridge
/** /**
Query the number of banks supported by the cartridge. Query the number of banks supported by the cartridge.
*/ */
uInt16 bankCount() const override; uInt16 romBankCount() const override;
/**
Query the number of RAM 'banks' supported by the cartridge.
*/
uInt16 ramBankCount() const override;
/**
Check if the segment at that address contains a RAM bank
@param address The address which defines the segment
@return true, if the segment is currently mapped to a RAM bank
*/
bool isRamBank(uInt16 address) const;
/** /**
Patch the cartridge ROM. Patch the cartridge ROM.
@ -162,9 +175,19 @@ class CartridgeEnhanced : public Cartridge
// The extra RAM size // The extra RAM size
uInt16 myRamSize{RAM_SIZE}; // default 0 uInt16 myRamSize{RAM_SIZE}; // default 0
// The number of RAM banks
uInt16 myRamBankCount{RAM_BANKS}; // default 0
// The mask for the extra RAM // The mask for the extra RAM
uInt16 myRamMask{0}; // RAM_SIZE - 1, but doesn't matter when RAM_SIZE is 0 uInt16 myRamMask{0}; // RAM_SIZE - 1, but doesn't matter when RAM_SIZE is 0
// The offset into ROM space for reading from ROM
// This is zero for types without RAM and with banked RAM
// - xxSC = 0x0100
// - FA(2) = 0x0200
// - CV = 0x0800
uInt16 myRomOffset{0};
// The offset into ROM space for writing to RAM // The offset into ROM space for writing to RAM
// - xxSC = 0x0000 // - xxSC = 0x0000
// - FA(2) = 0x0000 // - FA(2) = 0x0000
@ -202,6 +225,9 @@ class CartridgeEnhanced : public Cartridge
// The size of extra RAM in ROM address space // The size of extra RAM in ROM address space
static constexpr uInt16 RAM_SIZE = 0; // default = none static constexpr uInt16 RAM_SIZE = 0; // default = none
// The size of extra RAM in ROM address space
static constexpr uInt16 RAM_BANKS = 0;
// Write port for extra RAM is at low address by default // Write port for extra RAM is at low address by default
static constexpr bool RAM_HIGH_WP = false; static constexpr bool RAM_HIGH_WP = false;

View File

@ -61,14 +61,14 @@ bool CartridgeFC::poke(uInt16 address, uInt8 value)
case 0x0FF9: case 0x0FF9:
// Set the high bits of target 4k bank // Set the high bits of target 4k bank
if (value << 2 < bankCount()) if (value << 2 < romBankCount())
{ {
myTargetBank += value << 2; myTargetBank += value << 2;
myTargetBank %= bankCount(); myTargetBank %= romBankCount();
} }
else else
// special handling when both values are identical (e.g. 4/4 or 5/5) // special handling when both values are identical (e.g. 4/4 or 5/5)
myTargetBank = value % bankCount(); myTargetBank = value % romBankCount();
break; break;
default: default:

View File

@ -36,7 +36,7 @@ void CartridgeMNetwork::initialize(const ByteBuffer& image, size_t size)
std::copy_n(image.get(), std::min<size_t>(romSize(), size), myImage.get()); std::copy_n(image.get(), std::min<size_t>(romSize(), size), myImage.get());
createRomAccessArrays(romSize() + myRAM.size()); createRomAccessArrays(romSize() + myRAM.size());
myRAMSlice = bankCount() - 1; myRAMSlice = romBankCount() - 1;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -265,7 +265,7 @@ bool CartridgeMNetwork::patch(uInt16 address, uInt8 value)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt8* CartridgeMNetwork::getImage(size_t& size) const const uInt8* CartridgeMNetwork::getImage(size_t& size) const
{ {
size = bankCount() * BANK_SIZE; size = romBankCount() * BANK_SIZE;
return myImage.get(); return myImage.get();
} }
@ -310,7 +310,7 @@ bool CartridgeMNetwork::load(Serializer& in)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeMNetwork::bankCount() const uInt16 CartridgeMNetwork::romBankCount() const
{ {
return uInt16(mySize >> 11); return uInt16(mySize >> 11);
} }
@ -318,5 +318,5 @@ uInt16 CartridgeMNetwork::bankCount() const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeMNetwork::romSize() const uInt16 CartridgeMNetwork::romSize() const
{ {
return bankCount() * BANK_SIZE; return romBankCount() * BANK_SIZE;
} }

View File

@ -108,7 +108,7 @@ class CartridgeMNetwork : public Cartridge
/** /**
Query the number of banks supported by the cartridge. Query the number of banks supported by the cartridge.
*/ */
uInt16 bankCount() const override; uInt16 romBankCount() const override;
/** /**
Patch the cartridge ROM. Patch the cartridge ROM.

View File

@ -64,7 +64,7 @@ bool CartridgeSB::checkSwitchBank(uInt16 address, uInt8)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeSB::peek(uInt16 address) uInt8 CartridgeSB::peek(uInt16 address)
{ {
address &= (0x17FF + bankCount()); address &= (0x17FF + romBankCount());
checkSwitchBank(address); checkSwitchBank(address);
@ -82,7 +82,7 @@ uInt8 CartridgeSB::peek(uInt16 address)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeSB::poke(uInt16 address, uInt8 value) bool CartridgeSB::poke(uInt16 address, uInt8 value)
{ {
address &= (0x17FF + bankCount()); address &= (0x17FF + romBankCount());
checkSwitchBank(address); checkSwitchBank(address);

View File

@ -100,7 +100,7 @@ class CartridgeSB : public CartridgeEnhanced
uInt16 hotspot() const override { return 0x0840; } uInt16 hotspot() const override { return 0x0840; }
uInt16 getStartBank() const override { return bankCount() - 1; } uInt16 getStartBank() const override { return romBankCount() - 1; }
private: private:
// Previous Device's page access // Previous Device's page access

View File

@ -250,7 +250,7 @@ uInt16 CartridgeWD::getBank(uInt16) const
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeWD::bankCount() const uInt16 CartridgeWD::romBankCount() const
{ {
return 16; return 16;
} }

View File

@ -101,7 +101,7 @@ class CartridgeWD : public Cartridge
/** /**
Query the number of banks supported by the cartridge. Query the number of banks supported by the cartridge.
*/ */
uInt16 bankCount() const override; uInt16 romBankCount() const override;
/** /**
Patch the cartridge ROM. Patch the cartridge ROM.

View File

@ -445,7 +445,7 @@ void GameInfoDialog::loadEmulationProperties(const Properties& props)
VarList::push_back(items, "Auto", "AUTO"); VarList::push_back(items, "Auto", "AUTO");
if(instance().hasConsole()) if(instance().hasConsole())
{ {
uInt16 numBanks = instance().console().cartridge().bankCount(); uInt16 numBanks = instance().console().cartridge().romBankCount();
for(uInt16 i = 0; i < numBanks; ++i) for(uInt16 i = 0; i < numBanks; ++i)
VarList::push_back(items, i, i); VarList::push_back(items, i, i);