refactored Cart3EWidget (also supports 3EX)

added RAM bank support to CartEnhancedWidget
This commit is contained in:
thrust26 2020-04-22 19:58:40 +02:00
parent 579f73d1ea
commit a67ea71dca
7 changed files with 157 additions and 210 deletions

View File

@ -80,16 +80,11 @@ void PhysicalKeyboardHandler::setDefaultKey(EventMapping map, Event::Type event,
if (updateDefaults)
{
if (map.event == Event::ToggleSAPortOrder)
int i = 0;
// if there is no existing mapping for the event and
// the default mapping for the event is unused, set default key for event
if (myKeyMap.getEventMapping(map.event, mode).size() == 0 &&
!myKeyMap.check(mode, map.key, map.mod))
{
if (map.event == Event::ConsoleReset)
int i = 0;
addMapping(map.event, mode, map.key, StellaMod(map.mod));
}
}

View File

@ -23,129 +23,134 @@
Cartridge3EWidget::Cartridge3EWidget(
GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont,
int x, int y, int w, int h, Cartridge3E& cart)
: CartDebugWidget(boss, lfont, nfont, x, y, w, h),
myCart(cart),
myNumRomBanks(myCart.romBankCount()),
myNumRamBanks(myCart.ramBankCount())
: CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart)
{
size_t size = cart.mySize;
ostringstream info;
info << "3E cartridge - (3F + RAM)\n"
<< " 2-256 2K ROM (currently " << myNumRomBanks << "), 32 1K RAM\n"
<< "First 2K (ROM) selected by writing to $3F\n"
"First 2K (RAM) selected by writing to $3E\n"
" $F000 - $F3FF (R), $F400 - $F7FF (W)\n"
"Last 2K always points to last 2K of ROM\n";
if(cart.startBank() < myNumRomBanks)
info << "Startup bank = " << cart.startBank() << " (ROM)\n";
else
info << "Startup bank = " << (cart.startBank()-myNumRomBanks) << " (RAM)\n";
// Eventually, we should query this from the debugger/disassembler
uInt16 start = (cart.myImage[size-3] << 8) | cart.myImage[size-4];
start -= start % 0x1000;
info << "Bank RORG" << " = $" << Common::Base::HEX4 << start << "\n";
int xpos = 2,
ypos = addBaseInformation(size, "TigerVision", info.str()) + myLineHeight;
VariantList romitems;
for(uInt32 i = 0; i < myNumRomBanks; ++i)
VarList::push_back(romitems, i);
VarList::push_back(romitems, "Inactive", "");
VariantList ramitems;
for(uInt32 i = 0; i < myNumRamBanks; ++i)
VarList::push_back(ramitems, i);
VarList::push_back(ramitems, "Inactive", "");
ostringstream label;
label << "Set bank ($" << Common::Base::HEX4 << start << " - $"
<< (start+0x7FF) << "): ";
new StaticTextWidget(_boss, _font, xpos, ypos, _font.getStringWidth(label.str()),
myFontHeight, label.str(), TextAlign::Left);
ypos += myLineHeight + 8;
xpos += 40;
myROMBank =
new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("0 ($3E) "),
myLineHeight, romitems, "ROM ($3F) ",
_font.getStringWidth("ROM ($3F) "), kROMBankChanged);
myROMBank->setTarget(this);
addFocusWidget(myROMBank);
xpos += myROMBank->getWidth() + 20;
myRAMBank =
new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("0 ($3E) "),
myLineHeight, ramitems, "RAM ($3E) ",
_font.getStringWidth("RAM ($3E) "), kRAMBankChanged);
myRAMBank->setTarget(this);
addFocusWidget(myRAMBank);
initialize();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Cartridge3EWidget::saveOldState()
string Cartridge3EWidget::description()
{
myOldState.internalram.clear();
ostringstream info;
size_t size;
const uInt8* image = myCart.getImage(size);
uInt16 numRomBanks = myCart.romBankCount();
uInt16 numRamBanks = myCart.ramBankCount();
for(uInt32 i = 0; i < internalRamSize(); ++i)
myOldState.internalram.push_back(myCart.myRAM[i]);
myOldState.bank = myCart.getBank();
info << "3E cartridge (3F + RAM),\n"
<< " " << numRomBanks << " 2K ROM banks, " << numRamBanks << " 1K RAM banks\n"
<< "First 2K (ROM) selected by writing to $3F\n"
"First 2K (RAM) selected by writing to $3E\n";
info << CartridgeEnhancedWidget::ramDescription();
info << "Last 2K always points to last 2K of ROM\n";
if(myCart.startBank() < numRomBanks)
info << "Startup bank = " << myCart.startBank() << " (ROM)\n";
else
info << "Startup bank = " << (myCart.startBank() - numRomBanks) << " (RAM)\n";
// Eventually, we should query this from the debugger/disassembler
uInt16 start = (image[size-3] << 8) | image[size-4];
start -= start % 0x1000;
info << "Bank RORG" << " = $" << Common::Base::HEX4 << start << "\n";
return info.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Cartridge3EWidget::bankList(uInt16 bankCount, int seg, VariantList& items, int& width)
{
CartridgeEnhancedWidget::bankList(bankCount, seg, items, width);
VarList::push_back(items, "Inactive", "");
width = _font.getStringWidth("Inactive");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Cartridge3EWidget::bankSelect(int& ypos)
{
int xpos = 2;
VariantList items;
int pw;
myBankWidgets = make_unique<PopUpWidget* []>(2);
bankList(myCart.romBankCount(), 0, items, pw);
myBankWidgets[0] =
new PopUpWidget(_boss, _font, xpos, ypos - 2, pw,
myLineHeight, items, "Set bank ",
_font.getStringWidth("Set bank "), kBankChanged);
myBankWidgets[0]->setTarget(this);
myBankWidgets[0]->setID(0);
addFocusWidget(myBankWidgets[0]);
StaticTextWidget* t = new StaticTextWidget(_boss, _font, myBankWidgets[0]->getRight(), ypos - 1, " (ROM)");
xpos = t->getRight() + 20;
items.clear();
bankList(myCart.ramBankCount(), 0, items, pw);
myBankWidgets[1] =
new PopUpWidget(_boss, _font, xpos, ypos - 2, pw,
myLineHeight, items, "", 0, kRAMBankChanged);
myBankWidgets[1]->setTarget(this);
myBankWidgets[1]->setID(1);
addFocusWidget(myBankWidgets[1]);
new StaticTextWidget(_boss, _font, myBankWidgets[1]->getRight(), ypos - 1, " (RAM)");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Cartridge3EWidget::loadConfig()
{
uInt16 oldBank = myOldState.banks[0];
uInt16 bank = myCart.getBank();
if(myCart.getBank() < myCart.romBankCount())
{
myROMBank->setSelectedIndex(myCart.getBank() % myNumRomBanks, myOldState.bank != myCart.getBank());
myRAMBank->setSelectedMax(myOldState.bank >= myCart.romBankCount());
myBankWidgets[0]->setSelectedIndex(bank, oldBank != bank);
myBankWidgets[1]->setSelectedMax(oldBank >= myCart.romBankCount());
}
else
{
myROMBank->setSelectedMax(myOldState.bank < myCart.romBankCount());
myRAMBank->setSelectedIndex(myCart.getBank() - myCart.romBankCount(), myOldState.bank != myCart.getBank());
myBankWidgets[0]->setSelectedMax(oldBank < myCart.romBankCount());
myBankWidgets[1]->setSelectedIndex(bank - myCart.romBankCount(), oldBank != bank);
}
CartDebugWidget::loadConfig();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Cartridge3EWidget::handleCommand(CommandSender* sender,
int cmd, int data, int id)
void Cartridge3EWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
{
uInt16 bank = 0;
if(cmd == kROMBankChanged)
if(cmd == kBankChanged)
{
if(myROMBank->getSelected() < int(myNumRomBanks))
if(myBankWidgets[0]->getSelected() < myCart.romBankCount())
{
bank = myROMBank->getSelected();
myRAMBank->setSelectedMax();
bank = myBankWidgets[0]->getSelected();
myBankWidgets[1]->setSelectedMax();
}
else
{
bank = myCart.romBankCount(); // default to first RAM bank
myRAMBank->setSelectedIndex(0);
myBankWidgets[1]->setSelectedIndex(0);
}
}
else if(cmd == kRAMBankChanged)
{
if(myRAMBank->getSelected() < int(myNumRamBanks))
if(myBankWidgets[1]->getSelected() < myCart.ramBankCount())
{
myROMBank->setSelectedMax();
bank = myRAMBank->getSelected() + myCart.romBankCount();
myBankWidgets[0]->setSelectedMax();
bank = myBankWidgets[1]->getSelected() + myCart.romBankCount();
}
else
{
bank = 0; // default to first ROM bank
myROMBank->setSelectedIndex(0);
myBankWidgets[0]->setSelectedIndex(0);
}
}
myCart.unlockBank();
myCart.bank(bank);
myCart.lockBank();
@ -156,65 +161,13 @@ void Cartridge3EWidget::handleCommand(CommandSender* sender,
string Cartridge3EWidget::bankState()
{
ostringstream& buf = buffer();
uInt16 bank = myCart.getBank();
if(bank < myCart.romBankCount())
buf << "ROM bank #" << std::dec << bank % myNumRomBanks << ", RAM inactive";
buf << "ROM bank #" << std::dec << bank % myCart.romBankCount() << ", RAM inactive";
else
buf << "ROM inactive, RAM bank #" << std::dec << bank % myNumRamBanks;
buf << "ROM inactive, RAM bank #"
<< std::dec << (bank - myCart.romBankCount()) % myCart.ramBankCount();
return buf.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 Cartridge3EWidget::internalRamSize()
{
return uInt32(myCart.myRamSize);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 Cartridge3EWidget::internalRamRPort(int start)
{
return 0x0000 + start;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string Cartridge3EWidget::internalRamDescription()
{
ostringstream desc;
desc << "Accessible 1K at a time via:\n"
<< " $F000 - $F3FF used for Read Access\n"
<< " $F400 - $F7FF used for Write Access";
return desc.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const ByteArray& Cartridge3EWidget::internalRamOld(int start, int count)
{
myRamOld.clear();
for(int i = 0; i < count; i++)
myRamOld.push_back(myOldState.internalram[start + i]);
return myRamOld;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const ByteArray& Cartridge3EWidget::internalRamCurrent(int start, int count)
{
myRamCurrent.clear();
for(int i = 0; i < count; i++)
myRamCurrent.push_back(myCart.myRAM[start + i]);
return myRamCurrent;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Cartridge3EWidget::internalRamSetValue(int addr, uInt8 value)
{
myCart.myRAM[addr] = value;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 Cartridge3EWidget::internalRamGetValue(int addr)
{
return myCart.myRAM[addr];
}

View File

@ -19,11 +19,12 @@
#define CARTRIDGE3E_WIDGET_HXX
class Cartridge3E;
class PopUpWidget;
#include "CartDebugWidget.hxx"
#include "CartEnhancedWidget.hxx"
class Cartridge3EWidget : public CartDebugWidget
// Note: This class supports 3EX too
class Cartridge3EWidget : public CartridgeEnhancedWidget
{
public:
Cartridge3EWidget(GuiObject* boss, const GUI::Font& lfont,
@ -33,39 +34,28 @@ class Cartridge3EWidget : public CartDebugWidget
virtual ~Cartridge3EWidget() = default;
private:
Cartridge3E& myCart;
const uInt32 myNumRomBanks{0};
const uInt32 myNumRamBanks{0};
PopUpWidget *myROMBank{nullptr}, *myRAMBank{nullptr};
struct CartState {
ByteArray internalram;
uInt16 bank;
};
CartState myOldState;
enum {
kROMBankChanged = 'rmCH',
kRAMBankChanged = 'raCH'
};
private:
void saveOldState() override;
string manufacturer() override { return "Andrew Davie & Thomas Jentzsch"; }
string description() override;
void bankList(uInt16 bankCount, int seg, VariantList& items, int& width) override;
void bankSelect(int& ypos) override;
int bankSegs() override { return 1; }
void loadConfig() override;
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
string bankState() override;
// start of functions for Cartridge RAM tab
uInt32 internalRamSize() override;
uInt32 internalRamRPort(int start) override;
string internalRamDescription() override;
const ByteArray& internalRamOld(int start, int count) override;
const ByteArray& internalRamCurrent(int start, int count) override;
void internalRamSetValue(int addr, uInt8 value) override;
uInt8 internalRamGetValue(int addr) override;
// end of functions for Cartridge RAM tab
private:
// Following constructors and assignment operators not supported
Cartridge3EWidget() = delete;
Cartridge3EWidget(const Cartridge3EWidget&) = delete;

View File

@ -74,13 +74,15 @@ string CartridgeEnhancedWidget::ramDescription()
{
ostringstream info;
info << myCart.myRamSize << " bytes RAM @ "
<< "$" << Common::Base::HEX4 << ADDR_BASE << " - "
<< "$" << (ADDR_BASE | (myCart.myRamSize * 2 - 1)) << "\n"
<< " $" << (ADDR_BASE | myCart.myReadOffset)
<< " - $" << (ADDR_BASE | (myCart.myReadOffset + myCart.myRamSize - 1)) << " (R)"
if(myCart.ramBankCount() == 0)
info << myCart.myRamSize << " bytes RAM @ "
<< "$" << Common::Base::HEX4 << ADDR_BASE << " - "
<< "$" << (ADDR_BASE | (myCart.myRamSize * 2 - 1)) << "\n";
info << " $" << Common::Base::HEX4 << (ADDR_BASE | myCart.myReadOffset)
<< " - $" << (ADDR_BASE | (myCart.myReadOffset + myCart.myRamMask)) << " (R)"
<< ", $" << (ADDR_BASE | myCart.myWriteOffset)
<< " - $" << (ADDR_BASE | (myCart.myWriteOffset + myCart.myRamSize - 1)) << " (W)\n";
<< " - $" << (ADDR_BASE | (myCart.myWriteOffset + myCart.myRamMask)) << " (W)\n";
return info.str();
}
@ -133,6 +135,23 @@ string CartridgeEnhancedWidget::romDescription()
return info.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeEnhancedWidget::bankList(uInt16 bankCount, int seg, VariantList& items, int& width)
{
width = 0;
for(int bank = 0; bank < bankCount; ++bank)
{
ostringstream buf;
buf << std::setw(bank < 10 ? 2 : 1) << "#" << std::dec << bank;
if(myCart.hotspot() != 0 && myHotspotDelta > 0)
buf << " " << hotspotStr(bank, seg);
VarList::push_back(items, buf.str());
width = std::max(width, _font.getStringWidth(buf.str()));
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeEnhancedWidget::bankSelect(int& ypos)
{
@ -148,17 +167,7 @@ void CartridgeEnhancedWidget::bankSelect(int& ypos)
VariantList items;
int pw = 0;
for(int bank = 0; bank < myCart.romBankCount(); ++bank)
{
ostringstream buf;
buf << std::setw(bank < 10 ? 2 : 1) << "#" << std::dec << bank;
//if(myCart.hotspot() >= 0x100 && myHotspotDelta > 0)
if(myCart.hotspot() != 0 && myHotspotDelta > 0)
buf << " " << hotspotStr(bank, seg);
VarList::push_back(items, buf.str());
pw = std::max(pw, _font.getStringWidth(buf.str()));
}
bankList(myCart.romBankCount(), seg, items, pw);
// create widgets
ostringstream buf;
@ -282,7 +291,7 @@ void CartridgeEnhancedWidget::loadConfig()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeEnhancedWidget::handleCommand(CommandSender* sender,
int cmd, int data, int id)
int cmd, int data, int id)
{
if(cmd == kBankChanged)
{
@ -302,31 +311,45 @@ uInt32 CartridgeEnhancedWidget::internalRamSize()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 CartridgeEnhancedWidget::internalRamRPort(int start)
{
return ADDR_BASE + myCart.myReadOffset + start;
if(myCart.ramBankCount() == 0)
return ADDR_BASE + myCart.myReadOffset + start;
else
return start;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string CartridgeEnhancedWidget::internalRamDescription()
{
ostringstream desc;
string indent = "";
if(myCart.ramBankCount())
{
desc << "Accessible ";
if (myCart.bankSize() >> 1 >= 1024)
desc << ((myCart.bankSize() >> 1) / 1024) << "K";
else
desc << (myCart.bankSize() >> 1) << " bytes";
desc << " at a time via:\n";
indent = " ";
}
// order RW by addresses
if(myCart.myReadOffset <= myCart.myWriteOffset)
{
desc << "$" << Common::Base::HEX4 << (ADDR_BASE | myCart.myReadOffset)
<< " - $" << (ADDR_BASE | (myCart.myReadOffset + myCart.myRamSize - 1))
desc << indent << "$" << Common::Base::HEX4 << (ADDR_BASE | myCart.myReadOffset)
<< " - $" << (ADDR_BASE | (myCart.myReadOffset + myCart.myRamMask))
<< " used for Read Access\n";
}
desc
<< "$" << Common::Base::HEX4 << (ADDR_BASE | myCart.myWriteOffset)
<< " - $" << (ADDR_BASE | (myCart.myWriteOffset + myCart.myRamSize - 1))
desc << indent << "$" << Common::Base::HEX4 << (ADDR_BASE | myCart.myWriteOffset)
<< " - $" << (ADDR_BASE | (myCart.myWriteOffset + myCart.myRamMask))
<< " used for Write Access";
if(myCart.myReadOffset > myCart.myWriteOffset)
{
desc << "\n$" << Common::Base::HEX4 << (ADDR_BASE | myCart.myReadOffset)
<< " - $" << (ADDR_BASE | (myCart.myReadOffset + myCart.myRamSize - 1))
desc << indent << "\n$" << Common::Base::HEX4 << (ADDR_BASE | myCart.myReadOffset)
<< " - $" << (ADDR_BASE | (myCart.myReadOffset + myCart.myRamMask))
<< " used for Read Access";
}

View File

@ -51,6 +51,8 @@ class CartridgeEnhancedWidget : public CartDebugWidget
virtual string romDescription();
virtual void bankList(uInt16 bankCount, int seg, VariantList& items, int& width);
virtual void bankSelect(int& ypos);
virtual string hotspotStr(int bank = 0, int segment = 0, bool prefix = false);

View File

@ -22,7 +22,7 @@ Cartridge3EX::Cartridge3EX(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings)
: Cartridge3E(image, size, md5, settings)
{
myRamSize = RAM_SIZE;
// 0xFFFA contains RAM bank count - 1;
myRamBankCount = image[size - 6] + 1;
myRamSize = (myBankSize >> 1) * myRamBankCount;
}

View File

@ -21,9 +21,6 @@
class System;
#include "Cart3E.hxx"
#ifdef DEBUGGER_SUPPORT
//#include "Cart3EXWidget.hxx"
#endif
/**
This is an enhanced version of 3E which supports up to 256KB RAM.
@ -33,7 +30,6 @@ class System;
class Cartridge3EX : public Cartridge3E
{
//friend class Cartridge3EXWidget;
public:
/**
@ -56,18 +52,6 @@ public:
*/
string name() const override { return "Cartridge3EX"; }
#ifdef DEBUGGER_SUPPORT
///**
// Get debugger widget responsible for accessing the inner workings
// of the cart.
//*/
//CartDebugWidget* debugWidget(GuiObject* boss, const GUI::Font& lfont,
// const GUI::Font& nfont, int x, int y, int w, int h) override
//{
// return new Cartridge3EXWidget(boss, lfont, nfont, x, y, w, h, *this);
//}
#endif
private:
// RAM size
static constexpr size_t RAM_SIZE = RAM_BANKS << (BANK_SHIFT - 1); // = 256K = 0x40000;