add support for multi segment banking into CartEnhanced class

refactor more cart classes
This commit is contained in:
thrust26 2020-04-04 10:53:14 +02:00
parent 244fc3f7d3
commit 05901a2ad8
35 changed files with 183 additions and 1828 deletions

View File

@ -84,7 +84,7 @@ using ByteArray = std::vector<uInt8>;
using ShortArray = std::vector<uInt16>;
using StringList = std::vector<std::string>;
using ByteBuffer = std::unique_ptr<uInt8[]>; // NOLINT
using WordBuffer = std::unique_ptr<uInt16[]>; // NOLINT
using DWordBuffer = std::unique_ptr<uInt32[]>; // NOLINT
// We use KB a lot; let's make a literal for it
constexpr uInt32 operator "" _KB(unsigned long long size)

View File

@ -98,9 +98,9 @@ CartridgeE0Widget::CartridgeE0Widget(
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeE0Widget::loadConfig()
{
mySlice0->setSelectedIndex(myCart.myCurrentBank[0]);
mySlice1->setSelectedIndex(myCart.myCurrentBank[1]);
mySlice2->setSelectedIndex(myCart.myCurrentBank[2]);
mySlice0->setSelectedIndex(myCart.myCurrentSegOffset[0] >> myCart.myBankShift);
mySlice1->setSelectedIndex(myCart.myCurrentSegOffset[1] >> myCart.myBankShift);
mySlice2->setSelectedIndex(myCart.myCurrentSegOffset[2] >> myCart.myBankShift);
CartDebugWidget::loadConfig();
}
@ -136,9 +136,9 @@ string CartridgeE0Widget::bankState()
ostringstream& buf = buffer();
buf << "Slices: " << std::dec
<< seg0[myCart.myCurrentBank[0]] << " / "
<< seg1[myCart.myCurrentBank[1]] << " / "
<< seg2[myCart.myCurrentBank[2]];
<< seg0[myCart.myCurrentSegOffset[0] >> myCart.myBankShift] << " / "
<< seg1[myCart.myCurrentSegOffset[1] >> myCart.myBankShift] << " / "
<< seg2[myCart.myCurrentSegOffset[2] >> myCart.myBankShift];
return buf.str();
}

View File

@ -617,7 +617,7 @@ void DebuggerDialog::addRomArea()
// The 'cart-specific' information tab (optional)
tabID = myRomTab->addTab(" " + instance().console().cartridge().name() + " ", TabWidget::AUTO_WIDTH);
tabID = myRomTab->addTab(" " + instance().console().cartridge().name() + " ", TabWidget::AUTO_WIDTH);
myCartInfo = instance().console().cartridge().infoWidget(
myRomTab, *myLFont, *myNFont, 2, 2, tabWidth - 1,
tabHeight - myRomTab->getTabHeight() - 2);

View File

@ -21,33 +21,12 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeBF::CartridgeBF(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings)
: Cartridge(settings, md5)
: CartridgeEnhanced(image, size, md5, settings)
{
// Copy the ROM image into my buffer
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
createRomAccessArrays(myImage.size());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeBF::reset()
{
initializeStartBank(1);
// Upon reset we switch to the startup bank
bank(startBank());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeBF::install(System& system)
{
mySystem = &system;
// Install pages for the startup bank
bank(startBank());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeBF::peek(uInt16 address)
bool CartridgeBF::checkSwitchBank(uInt16 address, uInt8)
{
// Due to the way addressing is set up, we will only get here if the
// address is in the hotspot range ($1F80 - $1FFF)
@ -55,111 +34,9 @@ uInt8 CartridgeBF::peek(uInt16 address)
// Switch banks if necessary
if((address >= 0x0F80) && (address <= 0x0FBF))
{
bank(address - 0x0F80);
return myImage[myBankOffset + address];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeBF::poke(uInt16 address, uInt8)
{
// Due to the way addressing is set up, we will only get here if the
// address is in the hotspot range ($1F80 - $1FFF)
address &= 0x0FFF;
// Switch banks if necessary
if((address >= 0x0F80) && (address <= 0x0FBF))
bank(address - 0x0F80);
return true;
}
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeBF::bank(uInt16 bank)
{
if(bankLocked()) return false;
// Remember what bank we're in
myBankOffset = bank << 12;
System::PageAccess access(this, System::PageAccessType::READ);
// Set the page accessing methods for the hot spots
for(uInt16 addr = (0x1F80 & ~System::PAGE_MASK); addr < 0x2000;
addr += System::PAGE_SIZE)
{
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
mySystem->setPageAccess(addr, access);
}
// Setup the page access methods for the current bank
for(uInt16 addr = 0x1000; addr < static_cast<uInt16>(0x1F80U & ~System::PAGE_MASK);
addr += System::PAGE_SIZE)
{
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
mySystem->setPageAccess(addr, access);
}
return myBankChanged = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeBF::getBank(uInt16) const
{
return myBankOffset >> 12;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeBF::bankCount() const
{
return 64;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeBF::patch(uInt16 address, uInt8 value)
{
myImage[myBankOffset + (address & 0x0FFF)] = value;
return myBankChanged = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt8* CartridgeBF::getImage(size_t& size) const
{
size = myImage.size();
return myImage.data();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeBF::save(Serializer& out) const
{
try
{
out.putInt(myBankOffset);
}
catch(...)
{
cerr << "ERROR: CartridgeBF::save" << endl;
return false;
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeBF::load(Serializer& in)
{
try
{
myBankOffset = in.getInt();
}
catch(...)
{
cerr << "ERROR: CartridgeBF::load" << endl;
return false;
}
// Remember what bank we were in
bank(myBankOffset >> 12);
return true;
}

View File

@ -21,7 +21,7 @@
class System;
#include "bspf.hxx"
#include "Cart.hxx"
#include "CartEnhanced.hxx"
#ifdef DEBUGGER_SUPPORT
#include "CartBFWidget.hxx"
#endif
@ -31,9 +31,9 @@ class System;
There are 64 4K banks (total of 256K ROM).
Accessing $1F80 - $1FBF switches to each bank.
@author Mike Saarna
@author Mike Saarna, Thomas Jentzsch
*/
class CartridgeBF : public Cartridge
class CartridgeBF : public CartridgeEnhanced
{
friend class CartridgeBFWidget;
@ -51,71 +51,6 @@ class CartridgeBF : public Cartridge
virtual ~CartridgeBF() = default;
public:
/**
Reset device to its power-on state
*/
void reset() override;
/**
Install cartridge in the specified system. Invoked by the system
when the cartridge is attached to it.
@param system The system the device should install itself in
*/
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;
/**
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).
@ -135,29 +70,12 @@ class CartridgeBF : public Cartridge
}
#endif
public:
/**
Get the byte at the specified address.
@return The byte at the specified address
*/
uInt8 peek(uInt16 address) override;
/**
Change the byte at the specified address to the given value
@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:
// The 256K ROM image of the cartridge
std::array<uInt8, 256_KB> myImage;
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
// Indicates the offset into the ROM image (aligns to current bank)
uInt32 myBankOffset{0};
uInt16 romHotspot() const override { return 0x1F80; }
uInt16 getStartBank() const override { return 1; }
private:
// Following constructors and assignment operators not supported

View File

@ -21,197 +21,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeBFSC::CartridgeBFSC(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings)
: Cartridge(settings, md5)
: CartridgeBF(image, size, md5, settings)
{
// Copy the ROM image into my buffer
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
createRomAccessArrays(myImage.size());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeBFSC::reset()
{
initializeRAM(myRAM.data(), myRAM.size());
initializeStartBank(15);
// Upon reset we switch to the startup bank
bank(startBank());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeBFSC::install(System& system)
{
mySystem = &system;
System::PageAccess access(this, System::PageAccessType::READ);
// Set the page accessing method for the RAM writing pages
// Map access to this class, since we need to inspect all accesses to
// check if RWP happens
access.type = System::PageAccessType::WRITE;
for(uInt16 addr = 0x1000; addr < 0x1080; addr += System::PAGE_SIZE)
{
access.romAccessBase = &myRomAccessBase[addr & 0x007F];
mySystem->setPageAccess(addr, access);
}
// Set the page accessing method for the RAM reading pages
access.type = System::PageAccessType::READ;
for(uInt16 addr = 0x1080; addr < 0x1100; addr += System::PAGE_SIZE)
{
access.directPeekBase = &myRAM[addr & 0x007F];
access.romAccessBase = &myRomAccessBase[0x80 + (addr & 0x007F)];
mySystem->setPageAccess(addr, access);
}
// Install pages for the startup bank
bank(startBank());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeBFSC::peek(uInt16 address)
{
uInt16 peekAddress = address;
address &= 0x0FFF;
// Switch banks if necessary
if((address >= 0x0F80) && (address <= 0x0FBF))
bank(address - 0x0F80);
if(address < 0x0080) // Write port is at 0xF000 - 0xF07F (128 bytes)
return peekRAM(myRAM[address], peekAddress);
else
return myImage[myBankOffset + address];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeBFSC::poke(uInt16 address, uInt8 value)
{
uInt16 pokeAddress = address;
address &= 0x0FFF;
// Switch banks if necessary
if((address >= 0x0F80) && (address <= 0x0FBF))
{
bank(address - 0x0F80);
return false;
}
if (!(address & 0x080))
{
pokeRAM(myRAM[address & 0x007F], 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;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeBFSC::bank(uInt16 bank)
{
if(bankLocked()) return false;
// Remember what bank we're in
myBankOffset = bank << 12;
System::PageAccess access(this, System::PageAccessType::READ);
// Set the page accessing methods for the hot spots
for(uInt16 addr = (0x1F80 & ~System::PAGE_MASK); addr < 0x2000;
addr += System::PAGE_SIZE)
{
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
mySystem->setPageAccess(addr, access);
}
// Setup the page access methods for the current bank
for(uInt16 addr = 0x1100; addr < static_cast<uInt16>(0x1F80U & ~System::PAGE_MASK);
addr += System::PAGE_SIZE)
{
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
mySystem->setPageAccess(addr, access);
}
return myBankChanged = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeBFSC::getBank(uInt16) const
{
return myBankOffset >> 12;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeBFSC::bankCount() const
{
return 64;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeBFSC::patch(uInt16 address, uInt8 value)
{
address &= 0x0FFF;
if(address < 0x0100)
{
// Normally, a write to the read port won't do anything
// However, the patch command is special in that ignores such
// cart restrictions
myRAM[address & 0x007F] = value;
}
else
myImage[myBankOffset + address] = value;
return myBankChanged = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt8* CartridgeBFSC::getImage(size_t& size) const
{
size = myImage.size();
return myImage.data();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeBFSC::save(Serializer& out) const
{
try
{
out.putInt(myBankOffset);
out.putByteArray(myRAM.data(), myRAM.size());
}
catch(...)
{
cerr << "ERROR: CartridgeBFSC::save" << endl;
return false;
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeBFSC::load(Serializer& in)
{
try
{
myBankOffset = in.getInt();
in.getByteArray(myRAM.data(), myRAM.size());
}
catch(...)
{
cerr << "ERROR: CartridgeBFSC::load" << endl;
return false;
}
// Remember what bank we were in
bank(myBankOffset >> 12);
return true;
myRamSize = RAM_SIZE;
}

View File

@ -21,7 +21,7 @@
class System;
#include "bspf.hxx"
#include "Cart.hxx"
#include "CartBF.hxx"
#ifdef DEBUGGER_SUPPORT
#include "CartBFSCWidget.hxx"
#endif
@ -31,9 +31,9 @@ class System;
Accessing $1F80 - $1FBF switches to each bank.
RAM read port is $1080 - $10FF, write port is $1000 - $107F.
@author Stephen Anthony
@author Stephen Anthony, Thomas Jentzsch
*/
class CartridgeBFSC : public Cartridge
class CartridgeBFSC : public CartridgeBF
{
friend class CartridgeBFSCWidget;
@ -50,72 +50,6 @@ class CartridgeBFSC : public Cartridge
const Settings& settings);
virtual ~CartridgeBFSC() = default;
public:
/**
Reset device to its power-on state
*/
void reset() override;
/**
Install cartridge in the specified system. Invoked by the system
when the cartridge is attached to it.
@param system The system the device should install itself in
*/
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;
/**
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).
@ -135,32 +69,12 @@ class CartridgeBFSC : public Cartridge
}
#endif
public:
/**
Get the byte at the specified address.
@return The byte at the specified address
*/
uInt8 peek(uInt16 address) override;
/**
Change the byte at the specified address to the given value
@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:
uInt16 getStartBank() const override { return 15; }
private:
// The 256K ROM image of the cartridge
std::array<uInt8, 256_KB> myImage;
// The 128 bytes of RAM
std::array<uInt8, 128> myRAM;
// Indicates the offset into the ROM image (aligns to current bank)
uInt32 myBankOffset{0};
// RAM size
static constexpr uInt16 RAM_SIZE = 0x80;
private:
// Following constructors and assignment operators not supported

View File

@ -21,145 +21,20 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeDF::CartridgeDF(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings)
: Cartridge(settings, md5)
: CartridgeEnhanced(image, size, md5, settings)
{
// Copy the ROM image into my buffer
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
createRomAccessArrays(myImage.size());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeDF::reset()
{
initializeStartBank(1);
// Upon reset we switch to the startup bank
bank(startBank());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeDF::install(System& system)
{
mySystem = &system;
// Install pages for the startup bank
bank(startBank());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeDF::peek(uInt16 address)
bool CartridgeDF::checkSwitchBank(uInt16 address, uInt8)
{
address &= 0x0FFF;
// Switch banks if necessary
if((address >= 0x0FC0) && (address <= 0x0FDF))
{
bank(address - 0x0FC0);
return myImage[myBankOffset + address];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeDF::poke(uInt16 address, uInt8)
{
address &= 0x0FFF;
// Switch banks if necessary
if((address >= 0x0FC0) && (address <= 0x0FDF))
bank(address - 0x0FC0);
return true;
}
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeDF::bank(uInt16 bank)
{
if(bankLocked()) return false;
// Remember what bank we're in
myBankOffset = bank << 12;
System::PageAccess access(this, System::PageAccessType::READ);
// Set the page accessing methods for the hot spots
for(uInt16 addr = (0x1FC0 & ~System::PAGE_MASK); addr < 0x2000;
addr += System::PAGE_SIZE)
{
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
mySystem->setPageAccess(addr, access);
}
// Setup the page access methods for the current bank
for(uInt16 addr = 0x1000; addr < static_cast<uInt16>(0x1FC0U & ~System::PAGE_MASK);
addr += System::PAGE_SIZE)
{
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
mySystem->setPageAccess(addr, access);
}
return myBankChanged = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeDF::getBank(uInt16) const
{
return myBankOffset >> 12;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeDF::bankCount() const
{
return 32;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeDF::patch(uInt16 address, uInt8 value)
{
myImage[myBankOffset + (address & 0x0FFF)] = value;
return myBankChanged = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt8* CartridgeDF::getImage(size_t& size) const
{
size = myImage.size();
return myImage.data();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeDF::save(Serializer& out) const
{
try
{
out.putInt(myBankOffset);
}
catch(...)
{
cerr << "ERROR: CartridgeDF::save" << endl;
return false;
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeDF::load(Serializer& in)
{
try
{
myBankOffset = in.getInt();
}
catch(...)
{
cerr << "ERROR: CartridgeDF::load" << endl;
return false;
}
// Remember what bank we were in
bank(myBankOffset >> 12);
return true;
}

View File

@ -21,7 +21,7 @@
class System;
#include "bspf.hxx"
#include "Cart.hxx"
#include "CartEnhanced.hxx"
#ifdef DEBUGGER_SUPPORT
#include "CartDFWidget.hxx"
#endif
@ -31,9 +31,9 @@ class System;
There are 32 4K banks (total of 128K ROM).
Accessing $1FC0 - $1FDF switches to each bank.
@author Mike Saarna
@author Mike Saarna, Thomas Jentzsch
*/
class CartridgeDF : public Cartridge
class CartridgeDF : public CartridgeEnhanced
{
friend class CartridgeDFWidget;
@ -51,71 +51,6 @@ class CartridgeDF : public Cartridge
virtual ~CartridgeDF() = default;
public:
/**
Reset device to its power-on state
*/
void reset() override;
/**
Install cartridge in the specified system. Invoked by the system
when the cartridge is attached to it.
@param system The system the device should install itself in
*/
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;
/**
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).
@ -135,29 +70,12 @@ class CartridgeDF : public Cartridge
}
#endif
public:
/**
Get the byte at the specified address.
@return The byte at the specified address
*/
uInt8 peek(uInt16 address) override;
/**
Change the byte at the specified address to the given value
@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:
// The 128K ROM image of the cartridge
std::array<uInt8, 128_KB> myImage;
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
// Indicates the offset into the ROM image (aligns to current bank)
uInt32 myBankOffset{0};
uInt16 romHotspot() const override { return 0x1FC0; }
uInt16 getStartBank() const override { return 15; }
private:
// Following constructors and assignment operators not supported

View File

@ -21,205 +21,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeDFSC::CartridgeDFSC(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings)
: Cartridge(settings, md5)
: CartridgeDF(image, size, md5, settings)
{
// Copy the ROM image into my buffer
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
createRomAccessArrays(myImage.size());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeDFSC::reset()
{
initializeRAM(myRAM.data(), myRAM.size());
initializeStartBank(15);
// Upon reset we switch to the startup bank
bank(startBank());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeDFSC::install(System& system)
{
mySystem = &system;
System::PageAccess access(this, System::PageAccessType::READ);
// Set the page accessing method for the RAM writing pages
// Map access to this class, since we need to inspect all accesses to
// check if RWP happens
access.type = System::PageAccessType::WRITE;
for(uInt16 addr = 0x1000; addr < 0x1080; addr += System::PAGE_SIZE)
{
access.romAccessBase = &myRomAccessBase[addr & 0x007F];
access.romPeekCounter = &myRomAccessCounter[addr & 0x007F];
access.romPokeCounter = &myRomAccessCounter[(addr & 0x007F) + myAccessSize];
mySystem->setPageAccess(addr, access);
}
// Set the page accessing method for the RAM reading pages
access.type = System::PageAccessType::READ;
for(uInt16 addr = 0x1080; addr < 0x1100; addr += System::PAGE_SIZE)
{
access.directPeekBase = &myRAM[addr & 0x007F];
access.romAccessBase = &myRomAccessBase[0x80 + (addr & 0x007F)];
access.romPeekCounter = &myRomAccessCounter[0x80 + (addr & 0x007F)];
access.romPokeCounter = &myRomAccessCounter[0x80 + (addr & 0x007F) + myAccessSize];
mySystem->setPageAccess(addr, access);
}
// Install pages for the startup bank
bank(startBank());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeDFSC::peek(uInt16 address)
{
uInt16 peekAddress = address;
address &= 0x0FFF;
// Switch banks if necessary
if((address >= 0x0FC0) && (address <= 0x0FDF))
bank(address - 0x0FC0);
if(address < 0x0080) // Write port is at 0xF000 - 0xF07F (128 bytes)
return peekRAM(myRAM[address], peekAddress);
else
return myImage[myBankOffset + address];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeDFSC::poke(uInt16 address, uInt8 value)
{
uInt16 pokeAddress = address;
address &= 0x0FFF;
// Switch banks if necessary
if((address >= 0x0FC0) && (address <= 0x0FDF))
{
bank(address - 0x0FC0);
return false;
}
if(!(address & 0x080))
{
pokeRAM(myRAM[address & 0x007F], 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;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeDFSC::bank(uInt16 bank)
{
if(bankLocked()) return false;
// Remember what bank we're in
myBankOffset = bank << 12;
System::PageAccess access(this, System::PageAccessType::READ);
// Set the page accessing methods for the hot spots
for(uInt16 addr = (0x1FC0 & ~System::PAGE_MASK); addr < 0x2000;
addr += System::PAGE_SIZE)
{
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
mySystem->setPageAccess(addr, access);
}
// Setup the page access methods for the current bank
for(uInt16 addr = 0x1100; addr < static_cast<uInt16>(0x1FC0U & ~System::PAGE_MASK);
addr += System::PAGE_SIZE)
{
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
mySystem->setPageAccess(addr, access);
}
return myBankChanged = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeDFSC::getBank(uInt16) const
{
return myBankOffset >> 12;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeDFSC::bankCount() const
{
return 32;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeDFSC::patch(uInt16 address, uInt8 value)
{
address &= 0x0FFF;
if(address < 0x0100)
{
// Normally, a write to the read port won't do anything
// However, the patch command is special in that ignores such
// cart restrictions
myRAM[address & 0x007F] = value;
}
else
myImage[myBankOffset + address] = value;
return myBankChanged = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt8* CartridgeDFSC::getImage(size_t& size) const
{
size = myImage.size();
return myImage.data();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeDFSC::save(Serializer& out) const
{
try
{
out.putInt(myBankOffset);
out.putByteArray(myRAM.data(), myRAM.size());
}
catch(...)
{
cerr << "ERROR: CartridgeDFSC::save" << endl;
return false;
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeDFSC::load(Serializer& in)
{
try
{
myBankOffset = in.getInt();
in.getByteArray(myRAM.data(), myRAM.size());
}
catch(...)
{
cerr << "ERROR: CartridgeDFSC::load" << endl;
return false;
}
// Remember what bank we were in
bank(myBankOffset >> 12);
return true;
myRamSize = RAM_SIZE;
}

View File

@ -21,7 +21,7 @@
class System;
#include "bspf.hxx"
#include "Cart.hxx"
#include "CartDF.hxx"
#ifdef DEBUGGER_SUPPORT
#include "CartDFSCWidget.hxx"
#endif
@ -31,9 +31,9 @@ class System;
Accessing $1FC0 - $1FDF switches to each bank.
RAM read port is $1080 - $10FF, write port is $1000 - $107F.
@author Stephen Anthony
@author Stephen Anthony, Thomas Jentzsch
*/
class CartridgeDFSC : public Cartridge
class CartridgeDFSC : public CartridgeDF
{
friend class CartridgeDFSCWidget;
@ -51,71 +51,6 @@ class CartridgeDFSC : public Cartridge
virtual ~CartridgeDFSC() = default;
public:
/**
Reset device to its power-on state
*/
void reset() override;
/**
Install cartridge in the specified system. Invoked by the system
when the cartridge is attached to it.
@param system The system the device should install itself in
*/
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;
/**
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).
@ -135,34 +70,11 @@ class CartridgeDFSC : public Cartridge
}
#endif
public:
/**
Get the byte at the specified address.
@return The byte at the specified address
*/
uInt8 peek(uInt16 address) override;
/**
Change the byte at the specified address to the given value
@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:
// The 128K ROM image of the cartridge
std::array<uInt8, 128_KB> myImage;
// RAM size
static constexpr uInt16 RAM_SIZE = 0x80;
// The 128 bytes of RAM
std::array<uInt8, 128> myRAM;
// Indicates the offset into the ROM image (aligns to current bank)
uInt32 myBankOffset{0};
private:
private:
// Following constructors and assignment operators not supported
CartridgeDFSC() = delete;
CartridgeDFSC(const CartridgeDFSC&) = delete;

View File

@ -21,11 +21,9 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeE0::CartridgeE0(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings)
: Cartridge(settings, md5)
: CartridgeEnhanced(image, size, md5, settings)
{
// Copy the ROM image into my buffer
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
createRomAccessArrays(myImage.size());
myBankShift = BANK_SHIFT;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -44,7 +42,7 @@ void CartridgeE0::reset()
bank(5, 1);
bank(6, 2);
}
myCurrentBank[3] = bankCount() - 1; // fixed
myCurrentSegOffset[3] = (bankCount() - 1) << myBankShift; // fixed
myBankChanged = true;
}
@ -52,7 +50,13 @@ void CartridgeE0::reset()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeE0::install(System& system)
{
mySystem = &system;
//// Allocate array for the current bank segments slices
//myCurrentSegOffset = make_unique<uInt16[]>(myBankSegs);
//// Setup page access
//mySystem = &system;
CartridgeEnhanced::install(system);
System::PageAccess access(this, System::PageAccessType::READ);
@ -79,127 +83,23 @@ void CartridgeE0::install(System& system)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeE0::getBank(uInt16 address) const
bool CartridgeE0::checkSwitchBank(uInt16 address, uInt8)
{
return myCurrentBank[(address & 0xFFF) >> 10]; // 1K slices
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeE0::bankCount() const
{
return 8;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeE0::peek(uInt16 address)
{
address &= 0x0FFF;
// Switch banks if necessary
if((address >= 0x0FE0) && (address <= 0x0FE7))
{
bank(address & 0x0007, 0);
}
else if((address >= 0x0FE8) && (address <= 0x0FEF))
{
bank(address & 0x0007, 1);
}
else if((address >= 0x0FF0) && (address <= 0x0FF7))
{
bank(address & 0x0007, 2);
}
return myImage[(myCurrentBank[address >> 10] << 10) + (address & 0x03FF)];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeE0::poke(uInt16 address, uInt8)
{
address &= 0x0FFF;
// Switch banks if necessary
if((address >= 0x0FE0) && (address <= 0x0FE7))
{
bank(address & 0x0007, 0);
return true;
}
else if((address >= 0x0FE8) && (address <= 0x0FEF))
{
bank(address & 0x0007, 1);
return true;
}
else if((address >= 0x0FF0) && (address <= 0x0FF7))
{
bank(address & 0x0007, 2);
return true;
}
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeE0::bank(uInt16 bank, uInt16 slice)
{
if(bankLocked()) return;
// Remember the new slice
myCurrentBank[slice] = bank;
uInt16 sliceOffset = slice * (1 << 10);
uInt16 bankOffset = bank << 10;
// Setup the page access methods for the current bank
System::PageAccess access(this, System::PageAccessType::READ);
for(uInt16 addr = 0x1000 + sliceOffset; addr < 0x1000 + sliceOffset + 0x400; addr += System::PAGE_SIZE)
{
access.directPeekBase = &myImage[bankOffset + (addr & 0x03FF)];
access.romAccessBase = &myRomAccessBase[bankOffset + (addr & 0x03FF)];
access.romPeekCounter = &myRomAccessCounter[bankOffset + (addr & 0x03FF)];
access.romPokeCounter = &myRomAccessCounter[bankOffset + (addr & 0x03FF) + myAccessSize];
mySystem->setPageAccess(addr, access);
}
myBankChanged = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeE0::patch(uInt16 address, uInt8 value)
{
address &= 0x0FFF;
myImage[(myCurrentBank[address >> 10] << 10) + (address & 0x03FF)] = value;
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt8* CartridgeE0::getImage(size_t& size) const
{
size = myImage.size();
return myImage.data();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeE0::save(Serializer& out) const
{
try
{
out.putShortArray(myCurrentBank.data(), myCurrentBank.size());
}
catch(...)
{
cerr << "ERROR: CartridgeE0::save" << endl;
return false;
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeE0::load(Serializer& in)
{
try
{
in.getShortArray(myCurrentBank.data(), myCurrentBank.size());
}
catch(...)
{
cerr << "ERROR: CartridgeE0::load" << endl;
return false;
}
return true;
}

View File

@ -21,7 +21,7 @@
class System;
#include "bspf.hxx"
#include "Cart.hxx"
#include "CartEnhanced.hxx"
#ifdef DEBUGGER_SUPPORT
#include "CartE0Widget.hxx"
#endif
@ -39,9 +39,9 @@ class System;
only one actual bank, in which pieces of it can be swapped out in
many different ways.
@author Bradford W. Mott
@author Bradford W. Mott, Thomas Jentzsch
*/
class CartridgeE0 : public Cartridge
class CartridgeE0 : public CartridgeEnhanced
{
friend class CartridgeE0Widget;
@ -72,52 +72,6 @@ class CartridgeE0 : public Cartridge
*/
void install(System& system) 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;
/**
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).
@ -137,37 +91,14 @@ class CartridgeE0 : public Cartridge
}
#endif
public:
/**
Get the byte at the specified address.
private:
bool checkSwitchBank(uInt16 address, uInt8 = 0) override;
@return The byte at the specified address
*/
uInt8 peek(uInt16 address) override;
/**
Change the byte at the specified address to the given value
@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;
uInt16 romHotspot() const override { return 0x1FE0; }
private:
/**
Install the specified slice for segment (bank) 0..2
@param slice The slice to map into the segment
*/
void bank(uInt16 bank, uInt16 slice);
private:
// The 8K ROM image of the cartridge
std::array<uInt8, 8_KB> myImage;
// Indicates the slice mapped into each of the four segments
std::array<uInt16, 4> myCurrentBank;
// log(ROM bank segment size) / log(2)
static constexpr uInt16 BANK_SHIFT = 10; // = 1K = 0x0400
private:
// Following constructors and assignment operators not supported

View File

@ -21,145 +21,20 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeEF::CartridgeEF(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings)
: Cartridge(settings, md5)
: CartridgeEnhanced(image, size, md5, settings)
{
// Copy the ROM image into my buffer
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
createRomAccessArrays(myImage.size());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeEF::reset()
{
initializeStartBank(1);
// Upon reset we switch to the startup bank
bank(startBank());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeEF::install(System& system)
{
mySystem = &system;
// Install pages for the startup bank
bank(startBank());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeEF::peek(uInt16 address)
bool CartridgeEF::checkSwitchBank(uInt16 address, uInt8)
{
address &= 0x0FFF;
// Switch banks if necessary
if((address >= 0x0FE0) && (address <= 0x0FEF))
{
bank(address - 0x0FE0);
return myImage[myBankOffset + address];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeEF::poke(uInt16 address, uInt8)
{
address &= 0x0FFF;
// Switch banks if necessary
if((address >= 0x0FE0) && (address <= 0x0FEF))
bank(address - 0x0FE0);
return true;
}
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeEF::bank(uInt16 bank)
{
if(bankLocked()) return false;
// Remember what bank we're in
myBankOffset = bank << 12;
System::PageAccess access(this, System::PageAccessType::READ);
// Set the page accessing methods for the hot spots
for(uInt16 addr = (0x1FE0 & ~System::PAGE_MASK); addr < 0x2000;
addr += System::PAGE_SIZE)
{
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
mySystem->setPageAccess(addr, access);
}
// Setup the page access methods for the current bank
for(uInt16 addr = 0x1000; addr < static_cast<uInt16>(0x1FE0U & ~System::PAGE_MASK);
addr += System::PAGE_SIZE)
{
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
mySystem->setPageAccess(addr, access);
}
return myBankChanged = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeEF::getBank(uInt16) const
{
return myBankOffset >> 12;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeEF::bankCount() const
{
return 16;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeEF::patch(uInt16 address, uInt8 value)
{
myImage[myBankOffset + (address & 0x0FFF)] = value;
return myBankChanged = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt8* CartridgeEF::getImage(size_t& size) const
{
size = myImage.size();
return myImage.data();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeEF::save(Serializer& out) const
{
try
{
out.putShort(myBankOffset);
}
catch(...)
{
cerr << "ERROR: CartridgeEF::save" << endl;
return false;
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeEF::load(Serializer& in)
{
try
{
myBankOffset = in.getShort();
}
catch(...)
{
cerr << "ERROR: CartridgeEF::load" << endl;
return false;
}
// Remember what bank we were in
bank(myBankOffset >> 12);
return true;
}

View File

@ -21,7 +21,7 @@
class System;
#include "bspf.hxx"
#include "Cart.hxx"
#include "CartEnhanced.hxx"
#ifdef DEBUGGER_SUPPORT
#include "CartEFWidget.hxx"
#endif
@ -31,9 +31,9 @@ class System;
There are 16 4K banks (total of 64K ROM).
Accessing $1FE0 - $1FEF switches to each bank.
@author Stephen Anthony
@author Stephen Anthony, Thomas Jentzsch
*/
class CartridgeEF : public Cartridge
class CartridgeEF : public CartridgeEnhanced
{
friend class CartridgeEFWidget;
@ -51,71 +51,6 @@ class CartridgeEF : public Cartridge
virtual ~CartridgeEF() = default;
public:
/**
Reset device to its power-on state
*/
void reset() override;
/**
Install cartridge in the specified system. Invoked by the system
when the cartridge is attached to it.
@param system The system the device should install itself in
*/
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;
/**
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).
@ -135,29 +70,12 @@ class CartridgeEF : public Cartridge
}
#endif
public:
/**
Get the byte at the specified address.
@return The byte at the specified address
*/
uInt8 peek(uInt16 address) override;
/**
Change the byte at the specified address to the given value
@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:
// The 64K ROM image of the cartridge
std::array<uInt8, 64_KB> myImage;
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
// Indicates the offset into the ROM image (aligns to current bank)
uInt16 myBankOffset{0};
uInt16 romHotspot() const override { return 0x1FE0; }
uInt16 getStartBank() const override { return 1; }
private:
// Following constructors and assignment operators not supported

View File

@ -21,205 +21,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeEFSC::CartridgeEFSC(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings)
: Cartridge(settings, md5)
: CartridgeEF(image, size, md5, settings)
{
// Copy the ROM image into my buffer
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
createRomAccessArrays(myImage.size());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeEFSC::reset()
{
initializeRAM(myRAM.data(), myRAM.size());
initializeStartBank(15);
// Upon reset we switch to the startup bank
bank(startBank());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeEFSC::install(System& system)
{
mySystem = &system;
System::PageAccess access(this, System::PageAccessType::READ);
// Set the page accessing method for the RAM writing pages
// Map access to this class, since we need to inspect all accesses to
// check if RWP happens
access.type = System::PageAccessType::WRITE;
for(uInt16 addr = 0x1000; addr < 0x1080; addr += System::PAGE_SIZE)
{
access.romAccessBase = &myRomAccessBase[addr & 0x007F];
access.romPeekCounter = &myRomAccessCounter[addr & 0x007F];
access.romPokeCounter = &myRomAccessCounter[(addr & 0x007F) + myAccessSize];
mySystem->setPageAccess(addr, access);
}
// Set the page accessing method for the RAM reading pages
access.type = System::PageAccessType::READ;
for(uInt16 addr = 0x1080; addr < 0x1100; addr += System::PAGE_SIZE)
{
access.directPeekBase = &myRAM[addr & 0x007F];
access.romAccessBase = &myRomAccessBase[0x80 + (addr & 0x007F)];
access.romPeekCounter = &myRomAccessCounter[0x80 + (addr & 0x007F)];
access.romPokeCounter = &myRomAccessCounter[0x80 + (addr & 0x007F) + myAccessSize];
mySystem->setPageAccess(addr, access);
}
// Install pages for the startup bank
bank(startBank());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeEFSC::peek(uInt16 address)
{
uInt16 peekAddress = address;
address &= 0x0FFF;
// Switch banks if necessary
if((address >= 0x0FE0) && (address <= 0x0FEF))
bank(address - 0x0FE0);
if(address < 0x0080) // Write port is at 0xF000 - 0xF07F (128 bytes)
return peekRAM(myRAM[address], peekAddress);
else
return myImage[myBankOffset + address];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeEFSC::poke(uInt16 address, uInt8 value)
{
uInt16 pokeAddress = address;
address &= 0x0FFF;
// Switch banks if necessary
if((address >= 0x0FE0) && (address <= 0x0FEF))
{
bank(address - 0x0FE0);
return false;
}
if (!(address & 0x080))
{
pokeRAM(myRAM[address & 0x007F], 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;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeEFSC::bank(uInt16 bank)
{
if(bankLocked()) return false;
// Remember what bank we're in
myBankOffset = bank << 12;
System::PageAccess access(this, System::PageAccessType::READ);
// Set the page accessing methods for the hot spots
for(uInt16 addr = (0x1FE0 & ~System::PAGE_MASK); addr < 0x2000;
addr += System::PAGE_SIZE)
{
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
mySystem->setPageAccess(addr, access);
}
// Setup the page access methods for the current bank
for(uInt16 addr = 0x1100; addr < static_cast<uInt16>(0x1FE0U & ~System::PAGE_MASK);
addr += System::PAGE_SIZE)
{
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
mySystem->setPageAccess(addr, access);
}
return myBankChanged = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeEFSC::getBank(uInt16) const
{
return myBankOffset >> 12;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeEFSC::bankCount() const
{
return 16;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeEFSC::patch(uInt16 address, uInt8 value)
{
address &= 0x0FFF;
if(address < 0x0100)
{
// Normally, a write to the read port won't do anything
// However, the patch command is special in that ignores such
// cart restrictions
myRAM[address & 0x007F] = value;
}
else
myImage[myBankOffset + address] = value;
return myBankChanged = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt8* CartridgeEFSC::getImage(size_t& size) const
{
size = myImage.size();
return myImage.data();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeEFSC::save(Serializer& out) const
{
try
{
out.putShort(myBankOffset);
out.putByteArray(myRAM.data(), myRAM.size());
}
catch(...)
{
cerr << "ERROR: CartridgeEFSC::save" << endl;
return false;
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeEFSC::load(Serializer& in)
{
try
{
myBankOffset = in.getShort();
in.getByteArray(myRAM.data(), myRAM.size());
}
catch(...)
{
cerr << "ERROR: CartridgeEFSC::load" << endl;
return false;
}
// Remember what bank we were in
bank(myBankOffset >> 12);
return true;
myRamSize = RAM_SIZE;
}

View File

@ -21,7 +21,7 @@
class System;
#include "bspf.hxx"
#include "Cart.hxx"
#include "CartEF.hxx"
#ifdef DEBUGGER_SUPPORT
#include "CartEFSCWidget.hxx"
#endif
@ -32,9 +32,9 @@ class System;
Accessing $1FE0 - $1FEF switches to each bank.
RAM read port is $1080 - $10FF, write port is $1000 - $107F.
@author Stephen Anthony
@author Stephen Anthony, Thomas Jentzsch
*/
class CartridgeEFSC : public Cartridge
class CartridgeEFSC : public CartridgeEF
{
friend class CartridgeEFSCWidget;
@ -52,71 +52,6 @@ class CartridgeEFSC : public Cartridge
virtual ~CartridgeEFSC() = default;
public:
/**
Reset device to its power-on state
*/
void reset() override;
/**
Install cartridge in the specified system. Invoked by the system
when the cartridge is attached to it.
@param system The system the device should install itself in
*/
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;
/**
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).
@ -136,32 +71,12 @@ class CartridgeEFSC : public Cartridge
}
#endif
public:
/**
Get the byte at the specified address.
@return The byte at the specified address
*/
uInt8 peek(uInt16 address) override;
/**
Change the byte at the specified address to the given value
@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:
uInt16 getStartBank() const override { return 15; }
private:
// The 64K ROM image of the cartridge
std::array<uInt8, 64_KB> myImage;
// The 128 bytes of RAM
std::array<uInt8, 128> myRAM;
// Indicates the offset into the ROM image (aligns to current bank)
uInt16 myBankOffset{0};
// RAM size
static constexpr uInt16 RAM_SIZE = 0x80;
private:
// Following constructors and assignment operators not supported

View File

@ -37,9 +37,14 @@ CartridgeEnhanced::CartridgeEnhanced(const ByteBuffer& image, size_t size,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeEnhanced::install(System& system)
{
// calculate bank switching and RAM sizes and masks
myBankSize = 1 << myBankShift; // e.g. = 2 ^ 12 = 4K = 0x1000
myBankMask = myBankSize - 1; // e.g. = 0x0FFF
myBankSegs = 1 << (12 - myBankShift); // e.g. = 1
myRamMask = myRamSize - 1; // e.g. = 0xFFFF (doesn't matter for RAM size 0)
// Allocate array for the current bank segments slices
myCurrentBankOffset = make_unique<uInt16[]>(BANK_SEGS);
std::fill_n(myCurrentBankOffset.get(), BANK_SEGS, 0);
myCurrentSegOffset = make_unique<uInt32[]>(myBankSegs);
// Allocate array for the RAM area
myRAM = make_unique<uInt8[]>(myRamSize);
@ -93,24 +98,22 @@ void CartridgeEnhanced::reset()
uInt8 CartridgeEnhanced::peek(uInt16 address)
{
uInt16 peekAddress = address;
address &= myBankMask;
checkSwitchBank(address);
checkSwitchBank(address & 0x0FFF);
address &= myBankMask;
if(address < myRamSize) // Write port is at 0xF000 - 0xF07F (128 bytes)
return peekRAM(myRAM[address], peekAddress);
else
return myImage[myBankOffset + address];
return myImage[myCurrentBankOffset[address >> BANK_SHIFT] + (address & BANK_MASK)];
//return myImage[myBankOffset + address];
return myImage[myCurrentSegOffset[(peekAddress & 0xFFF) >> myBankShift] + address];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeEnhanced::poke(uInt16 address, uInt8 value)
{
address &= myBankMask;
// Switch banks if necessary
if (checkSwitchBank(address & myBankMask))
if (checkSwitchBank(address & 0x0FFF))
return false;
if(myRamSize)
@ -133,45 +136,34 @@ bool CartridgeEnhanced::poke(uInt16 address, uInt8 value)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeEnhanced::bank(uInt16 bank, uInt16 slice)
bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment)
{
if(bankLocked()) return false;
// Remember what bank we're in
myBankOffset = bank << myBankShift;
// Remember what bank is in which segment
uInt32 bankOffset = myCurrentSegOffset[segment] = bank << myBankShift;
uInt16 segmentOffset = segment << myBankShift;
uInt16 romHotspot = this->romHotspot();
uInt16 fromAddr = 0x1000 + myRamSize * 2;
uInt16 toAddr;
uInt16 hotSpotAddr;
uInt16 fromAddr = (segmentOffset + 0x1000 + myRamSize * 2) & ~System::PAGE_MASK;
uInt16 toAddr = (segmentOffset + 0x1000 + myBankSize) & ~System::PAGE_MASK;
if(romHotspot)
{
System::PageAccess access(this, System::PageAccessType::READ);
// Set the page accessing methods for the hot spots
for(uInt16 addr = (romHotspot & ~System::PAGE_MASK); addr < 0x1000 + myBankSize;
addr += System::PAGE_SIZE)
{
uInt16 offset = myBankOffset + (addr & myBankMask);
access.romAccessBase = &myRomAccessBase[offset];
access.romPeekCounter = &myRomAccessCounter[offset];
access.romPokeCounter = &myRomAccessCounter[offset + myAccessSize];
mySystem->setPageAccess(addr, access);
}
toAddr = romHotspot;
}
hotSpotAddr = segmentOffset + (romHotspot & ~System::PAGE_MASK);
else
toAddr = 0x1000 + myBankSize;
hotSpotAddr = 0xFFFF; // none
System::PageAccess access(this, System::PageAccessType::READ);
// Setup the page access methods for the current bank
for(uInt16 addr = (fromAddr & ~System::PAGE_MASK); addr < (toAddr & ~System::PAGE_MASK);
addr += System::PAGE_SIZE)
for(uInt16 addr = fromAddr; addr < toAddr; addr += System::PAGE_SIZE)
{
uInt16 offset = myBankOffset + (addr & myBankMask);
if(myDirectPeek)
uInt32 offset = bankOffset + (addr & myBankMask);
if(myDirectPeek && addr != hotSpotAddr)
access.directPeekBase = &myImage[offset];
else
access.directPeekBase = nullptr;
access.romAccessBase = &myRomAccessBase[offset];
access.romPeekCounter = &myRomAccessCounter[offset];
access.romPokeCounter = &myRomAccessCounter[offset + myAccessSize];
@ -182,9 +174,9 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 slice)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeEnhanced::getBank(uInt16) const
uInt16 CartridgeEnhanced::getBank(uInt16 address) const
{
return myBankOffset >> myBankShift;
return myCurrentSegOffset[(address & 0xFFF) >> myBankShift] >> myBankShift;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -196,9 +188,7 @@ uInt16 CartridgeEnhanced::bankCount() const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeEnhanced::patch(uInt16 address, uInt8 value)
{
address &= myBankMask;
if(address < myRamSize * 2)
if((address & myBankMask) < myRamSize * 2)
{
// Normally, a write to the read port won't do anything
// However, the patch command is special in that ignores such
@ -206,7 +196,7 @@ bool CartridgeEnhanced::patch(uInt16 address, uInt8 value)
myRAM[address & myRamMask] = value;
}
else
myImage[myBankOffset + address] = value;
myImage[myCurrentSegOffset[(address & 0xFFF) >> myBankShift] + (address & myBankMask)] = value;
return myBankChanged = true;
}
@ -223,7 +213,7 @@ bool CartridgeEnhanced::save(Serializer& out) const
{
try
{
out.putShort(myBankOffset);
out.putIntArray(myCurrentSegOffset.get(), myBankSegs);
if(myRamSize)
out.putByteArray(myRAM.get(), myRamSize);
@ -242,7 +232,7 @@ bool CartridgeEnhanced::load(Serializer& in)
{
try
{
myBankOffset = in.getShort();
in.getIntArray(myCurrentSegOffset.get(), myBankSegs);
if(myRamSize)
in.getByteArray(myRAM.get(), myRamSize);
}
@ -251,9 +241,5 @@ bool CartridgeEnhanced::load(Serializer& in)
cerr << "ERROR: " << name() << "::load" << endl;
return false;
}
// Remember what bank we were in
bank(myBankOffset >> myBankShift);
return true;
}

View File

@ -63,7 +63,7 @@ class CartridgeEnhanced : public Cartridge
@param bank The bank that should be installed in the system
*/
bool bank(uInt16 bank, uInt16 slice);
bool bank(uInt16 bank, uInt16 segment);
/**
Install pages for the specified bank in the system.
@ -135,62 +135,71 @@ class CartridgeEnhanced : public Cartridge
bool poke(uInt16 address, uInt8 value) override;
protected:
// The '2 ^ N = bank segment size' exponent
uInt16 myBankShift{BANK_SHIFT}; // default 12 (-> one 4K segment)
// The size of a bank's segment
uInt16 myBankSize{0};
// The mask for a bank segment
uInt16 myBankMask{0};
// The number of segments a bank is split into
uInt16 myBankSegs{0};
// The extra RAM size
uInt16 myRamSize{RAM_SIZE}; // default 0
// The mask for the extra RAM
uInt16 myRamMask{0}; // RAM_SIZE - 1, but doesn't matter when RAM_SIZE is 0
// Pointer to a dynamically allocated ROM image of the cartridge
ByteBuffer myImage{nullptr};
// Contains the offset into the ROM image for each of the bank segments
DWordBuffer myCurrentSegOffset{nullptr};
// Indicates whether to use direct ROM peeks or not
bool myDirectPeek{true};
// Pointer to a dynamically allocated RAM area of the cartridge
ByteBuffer myRAM{nullptr};
uInt16 myBankShift{BANK_SHIFT};
uInt16 myBankSize{BANK_SIZE};
uInt16 myBankMask{BANK_MASK};
uInt16 myRamSize{RAM_SIZE};
uInt16 myRamMask{RAM_MASK};
bool myDirectPeek{true};
// Indicates the offset into the ROM image (aligns to current bank)
uInt16 myBankOffset{0};
// Indicates the slice mapped into each of the bank segments
WordBuffer myCurrentBankOffset{nullptr};
private:
// log(ROM bank size) / log(2)
static constexpr uInt16 BANK_SHIFT = 12;
// Calculated as: log(ROM bank segment size) / log(2)
static constexpr uInt16 BANK_SHIFT = 12; // default = 4K
// bank size
static constexpr uInt16 BANK_SIZE = 1 << BANK_SHIFT; // 2 ^ 12 = 4K
// The size of extra RAM in ROM address space
static constexpr uInt16 RAM_SIZE = 0; // default = none
// bank mask
static constexpr uInt16 BANK_MASK = BANK_SIZE - 1;
// bank segments
static constexpr uInt16 BANK_SEGS = 1;
// RAM size
static constexpr uInt16 RAM_SIZE = 0;
// RAM mask
static constexpr uInt16 RAM_MASK = 0;
// Size of the ROM image
// The size of the ROM image
size_t mySize{0};
protected:
/**
Check hotspots and switch bank if triggered.
@param address The address to check
@param value The optional value used to determine the bank switched to
@return True if a bank switch happened.
*/
virtual bool checkSwitchBank(uInt16 address, uInt8 value = 0) = 0;
private:
/**
Get the ROM's startup bank.
@return The bank the ROM will start in
*/
virtual uInt16 getStartBank() const { return 0; }
/**
Get the hotspot in ROM address space.
@return The first hotspot address in ROM space or 0
*/
virtual uInt16 romHotspot() const { return 0; }
// TODO: handle cases where there the hotspots cover multiple pages
private:
// Following constructors and assignment operators not supported

View File

@ -67,12 +67,11 @@ class CartridgeF0 : public CartridgeEnhanced
}
#endif
protected:
private:
bool checkSwitchBank(uInt16 address, uInt8 value = 0);
uInt16 romHotspot() const override { return 0x1FF0; }
private:
uInt16 getStartBank() const override { return 15; }
private:

View File

@ -66,7 +66,7 @@ class CartridgeF4 : public CartridgeEnhanced
}
#endif
protected:
private:
bool checkSwitchBank(uInt16 address, uInt8 value = 0);
uInt16 romHotspot() const override { return 0x1FF4; }

View File

@ -23,5 +23,5 @@ CartridgeF4SC::CartridgeF4SC(const ByteBuffer& image, size_t size,
: CartridgeF4(image, size, md5, settings)
{
myRamSize = RAM_SIZE;
myRamMask = RAM_MASK;
myRamMask = RAM_SIZE - 1;
}

View File

@ -66,7 +66,7 @@ class CartridgeF6 : public CartridgeEnhanced
}
#endif
protected:
private:
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
uInt16 romHotspot() const override { return 0x1FF6; }

View File

@ -23,5 +23,5 @@ CartridgeF6SC::CartridgeF6SC(const ByteBuffer& image, size_t size,
: CartridgeF6(image, size, md5, settings)
{
myRamSize = RAM_SIZE;
myRamMask = RAM_MASK;
myRamMask = RAM_SIZE - 1;
}

View File

@ -66,12 +66,11 @@ class CartridgeF8 : public CartridgeEnhanced
}
#endif
protected:
private:
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
uInt16 romHotspot() const override { return 0x1FF8; }
private:
uInt16 getStartBank() const override { return 1; }
private:

View File

@ -23,5 +23,4 @@ CartridgeF8SC::CartridgeF8SC(const ByteBuffer& image, size_t size,
: CartridgeF8(image, size, md5, settings)
{
myRamSize = RAM_SIZE;
myRamMask = RAM_MASK;
}

View File

@ -71,9 +71,6 @@ class CartridgeF8SC : public CartridgeF8
// RAM size
static constexpr uInt16 RAM_SIZE = 0x80;
// RAM mask
static constexpr uInt16 RAM_MASK = RAM_SIZE - 1;
private:
// Following constructors and assignment operators not supported
CartridgeF8SC() = delete;

View File

@ -87,12 +87,11 @@ class CartridgeFC : public CartridgeEnhanced
*/
bool poke(uInt16 address, uInt8 value) override;
protected:
private:
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
uInt16 romHotspot() const override { return 0x1FF8; }
private:
// Target bank defined by writing to $1FF8/9
uInt16 myTargetBank{0};

View File

@ -37,7 +37,7 @@ void CartridgeFE::reset()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeFE::install(System& system)
{
mySystem = &system;
CartridgeEnhanced::install(system);
// The hotspot $01FE is in a mirror of zero-page RAM
// We need to claim access to it here, and deal with it in peek/poke below
@ -63,7 +63,7 @@ bool CartridgeFE::checkSwitchBank(uInt16 address, uInt8 value)
uInt8 CartridgeFE::peek(uInt16 address)
{
uInt8 value = (address < 0x200) ? mySystem->m6532().peek(address) :
myImage[myBankOffset + (address & myBankMask)];
myImage[myCurrentSegOffset[(address & 0xFFF) >> myBankShift] + (address & myBankMask)];
// Check if we hit hotspot
checkSwitchBank(address, value);

View File

@ -72,8 +72,8 @@ class System;
particular *why* the address $01FE will be placed on the address
bus after both the JSR and RTS opcodes.
@author Stephen Anthony; with ideas/research from Christian Speckner and
alex_79 and TomSon (of AtariAge)
@author Stephen Anthony, Thomas Jentzsch; with ideas/research from Christian
Speckner and alex_79 and TomSon (of AtariAge)
*/
class CartridgeFE : public CartridgeEnhanced
{

View File

@ -30,7 +30,7 @@ CartridgeUA::CartridgeUA(const ByteBuffer& image, size_t size,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeUA::install(System& system)
{
mySystem = &system;
CartridgeEnhanced::install(system);
// Get the page accessing methods for the hot spots since they overlap
// areas within the TIA we'll need to forward requests to the TIA

View File

@ -97,7 +97,7 @@ class CartridgeUA : public CartridgeEnhanced
bool poke(uInt16 address, uInt8 value) override;
protected:
private:
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
private:

Binary file not shown.