mirror of https://github.com/stella-emu/stella.git
add support for multi segment banking into CartEnhanced class
refactor more cart classes
This commit is contained in:
parent
244fc3f7d3
commit
05901a2ad8
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -66,7 +66,7 @@ class CartridgeF4 : public CartridgeEnhanced
|
|||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
private:
|
||||
bool checkSwitchBank(uInt16 address, uInt8 value = 0);
|
||||
|
||||
uInt16 romHotspot() const override { return 0x1FF4; }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -23,5 +23,4 @@ CartridgeF8SC::CartridgeF8SC(const ByteBuffer& image, size_t size,
|
|||
: CartridgeF8(image, size, md5, settings)
|
||||
{
|
||||
myRamSize = RAM_SIZE;
|
||||
myRamMask = RAM_MASK;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
Binary file not shown.
Loading…
Reference in New Issue