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 ShortArray = std::vector<uInt16>;
|
||||||
using StringList = std::vector<std::string>;
|
using StringList = std::vector<std::string>;
|
||||||
using ByteBuffer = std::unique_ptr<uInt8[]>; // NOLINT
|
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
|
// We use KB a lot; let's make a literal for it
|
||||||
constexpr uInt32 operator "" _KB(unsigned long long size)
|
constexpr uInt32 operator "" _KB(unsigned long long size)
|
||||||
|
|
|
@ -98,9 +98,9 @@ CartridgeE0Widget::CartridgeE0Widget(
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void CartridgeE0Widget::loadConfig()
|
void CartridgeE0Widget::loadConfig()
|
||||||
{
|
{
|
||||||
mySlice0->setSelectedIndex(myCart.myCurrentBank[0]);
|
mySlice0->setSelectedIndex(myCart.myCurrentSegOffset[0] >> myCart.myBankShift);
|
||||||
mySlice1->setSelectedIndex(myCart.myCurrentBank[1]);
|
mySlice1->setSelectedIndex(myCart.myCurrentSegOffset[1] >> myCart.myBankShift);
|
||||||
mySlice2->setSelectedIndex(myCart.myCurrentBank[2]);
|
mySlice2->setSelectedIndex(myCart.myCurrentSegOffset[2] >> myCart.myBankShift);
|
||||||
|
|
||||||
CartDebugWidget::loadConfig();
|
CartDebugWidget::loadConfig();
|
||||||
}
|
}
|
||||||
|
@ -136,9 +136,9 @@ string CartridgeE0Widget::bankState()
|
||||||
ostringstream& buf = buffer();
|
ostringstream& buf = buffer();
|
||||||
|
|
||||||
buf << "Slices: " << std::dec
|
buf << "Slices: " << std::dec
|
||||||
<< seg0[myCart.myCurrentBank[0]] << " / "
|
<< seg0[myCart.myCurrentSegOffset[0] >> myCart.myBankShift] << " / "
|
||||||
<< seg1[myCart.myCurrentBank[1]] << " / "
|
<< seg1[myCart.myCurrentSegOffset[1] >> myCart.myBankShift] << " / "
|
||||||
<< seg2[myCart.myCurrentBank[2]];
|
<< seg2[myCart.myCurrentSegOffset[2] >> myCart.myBankShift];
|
||||||
|
|
||||||
return buf.str();
|
return buf.str();
|
||||||
}
|
}
|
||||||
|
|
|
@ -617,7 +617,7 @@ void DebuggerDialog::addRomArea()
|
||||||
|
|
||||||
// The 'cart-specific' information tab (optional)
|
// 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(
|
myCartInfo = instance().console().cartridge().infoWidget(
|
||||||
myRomTab, *myLFont, *myNFont, 2, 2, tabWidth - 1,
|
myRomTab, *myLFont, *myNFont, 2, 2, tabWidth - 1,
|
||||||
tabHeight - myRomTab->getTabHeight() - 2);
|
tabHeight - myRomTab->getTabHeight() - 2);
|
||||||
|
|
|
@ -21,33 +21,12 @@
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
CartridgeBF::CartridgeBF(const ByteBuffer& image, size_t size,
|
CartridgeBF::CartridgeBF(const ByteBuffer& image, size_t size,
|
||||||
const string& md5, const Settings& settings)
|
const string& md5, const Settings& settings)
|
||||||
: Cartridge(settings, md5)
|
: CartridgeEnhanced(image, size, md5, settings)
|
||||||
{
|
{
|
||||||
// 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()
|
bool CartridgeBF::checkSwitchBank(uInt16 address, uInt8)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
// Due to the way addressing is set up, we will only get here if the
|
// Due to the way addressing is set up, we will only get here if the
|
||||||
// address is in the hotspot range ($1F80 - $1FFF)
|
// address is in the hotspot range ($1F80 - $1FFF)
|
||||||
|
@ -55,111 +34,9 @@ uInt8 CartridgeBF::peek(uInt16 address)
|
||||||
|
|
||||||
// Switch banks if necessary
|
// Switch banks if necessary
|
||||||
if((address >= 0x0F80) && (address <= 0x0FBF))
|
if((address >= 0x0F80) && (address <= 0x0FBF))
|
||||||
|
{
|
||||||
bank(address - 0x0F80);
|
bank(address - 0x0F80);
|
||||||
|
return true;
|
||||||
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 false;
|
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;
|
class System;
|
||||||
|
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "Cart.hxx"
|
#include "CartEnhanced.hxx"
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
#include "CartBFWidget.hxx"
|
#include "CartBFWidget.hxx"
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,9 +31,9 @@ class System;
|
||||||
There are 64 4K banks (total of 256K ROM).
|
There are 64 4K banks (total of 256K ROM).
|
||||||
Accessing $1F80 - $1FBF switches to each bank.
|
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;
|
friend class CartridgeBFWidget;
|
||||||
|
|
||||||
|
@ -51,71 +51,6 @@ class CartridgeBF : public Cartridge
|
||||||
virtual ~CartridgeBF() = default;
|
virtual ~CartridgeBF() = default;
|
||||||
|
|
||||||
public:
|
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).
|
Get a descriptor for the device name (used in error checking).
|
||||||
|
|
||||||
|
@ -135,29 +70,12 @@ class CartridgeBF : public Cartridge
|
||||||
}
|
}
|
||||||
#endif
|
#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:
|
private:
|
||||||
// The 256K ROM image of the cartridge
|
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
|
||||||
std::array<uInt8, 256_KB> myImage;
|
|
||||||
|
|
||||||
// Indicates the offset into the ROM image (aligns to current bank)
|
uInt16 romHotspot() const override { return 0x1F80; }
|
||||||
uInt32 myBankOffset{0};
|
|
||||||
|
uInt16 getStartBank() const override { return 1; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
|
|
|
@ -21,197 +21,7 @@
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
CartridgeBFSC::CartridgeBFSC(const ByteBuffer& image, size_t size,
|
CartridgeBFSC::CartridgeBFSC(const ByteBuffer& image, size_t size,
|
||||||
const string& md5, const Settings& settings)
|
const string& md5, const Settings& settings)
|
||||||
: Cartridge(settings, md5)
|
: CartridgeBF(image, size, md5, settings)
|
||||||
{
|
{
|
||||||
// Copy the ROM image into my buffer
|
myRamSize = RAM_SIZE;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
class System;
|
class System;
|
||||||
|
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "Cart.hxx"
|
#include "CartBF.hxx"
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
#include "CartBFSCWidget.hxx"
|
#include "CartBFSCWidget.hxx"
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,9 +31,9 @@ class System;
|
||||||
Accessing $1F80 - $1FBF switches to each bank.
|
Accessing $1F80 - $1FBF switches to each bank.
|
||||||
RAM read port is $1080 - $10FF, write port is $1000 - $107F.
|
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;
|
friend class CartridgeBFSCWidget;
|
||||||
|
|
||||||
|
@ -50,72 +50,6 @@ class CartridgeBFSC : public Cartridge
|
||||||
const Settings& settings);
|
const Settings& settings);
|
||||||
virtual ~CartridgeBFSC() = default;
|
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).
|
Get a descriptor for the device name (used in error checking).
|
||||||
|
|
||||||
|
@ -135,32 +69,12 @@ class CartridgeBFSC : public Cartridge
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
private:
|
||||||
/**
|
uInt16 getStartBank() const override { return 15; }
|
||||||
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:
|
private:
|
||||||
// The 256K ROM image of the cartridge
|
// RAM size
|
||||||
std::array<uInt8, 256_KB> myImage;
|
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
|
// Following constructors and assignment operators not supported
|
||||||
|
|
|
@ -21,145 +21,20 @@
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
CartridgeDF::CartridgeDF(const ByteBuffer& image, size_t size,
|
CartridgeDF::CartridgeDF(const ByteBuffer& image, size_t size,
|
||||||
const string& md5, const Settings& settings)
|
const string& md5, const Settings& settings)
|
||||||
: Cartridge(settings, md5)
|
: CartridgeEnhanced(image, size, md5, settings)
|
||||||
{
|
{
|
||||||
// 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()
|
bool CartridgeDF::checkSwitchBank(uInt16 address, uInt8)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
address &= 0x0FFF;
|
address &= 0x0FFF;
|
||||||
|
|
||||||
// Switch banks if necessary
|
// Switch banks if necessary
|
||||||
if((address >= 0x0FC0) && (address <= 0x0FDF))
|
if((address >= 0x0FC0) && (address <= 0x0FDF))
|
||||||
|
{
|
||||||
bank(address - 0x0FC0);
|
bank(address - 0x0FC0);
|
||||||
|
return true;
|
||||||
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 false;
|
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;
|
class System;
|
||||||
|
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "Cart.hxx"
|
#include "CartEnhanced.hxx"
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
#include "CartDFWidget.hxx"
|
#include "CartDFWidget.hxx"
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,9 +31,9 @@ class System;
|
||||||
There are 32 4K banks (total of 128K ROM).
|
There are 32 4K banks (total of 128K ROM).
|
||||||
Accessing $1FC0 - $1FDF switches to each bank.
|
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;
|
friend class CartridgeDFWidget;
|
||||||
|
|
||||||
|
@ -51,71 +51,6 @@ class CartridgeDF : public Cartridge
|
||||||
virtual ~CartridgeDF() = default;
|
virtual ~CartridgeDF() = default;
|
||||||
|
|
||||||
public:
|
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).
|
Get a descriptor for the device name (used in error checking).
|
||||||
|
|
||||||
|
@ -135,29 +70,12 @@ class CartridgeDF : public Cartridge
|
||||||
}
|
}
|
||||||
#endif
|
#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:
|
private:
|
||||||
// The 128K ROM image of the cartridge
|
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
|
||||||
std::array<uInt8, 128_KB> myImage;
|
|
||||||
|
|
||||||
// Indicates the offset into the ROM image (aligns to current bank)
|
uInt16 romHotspot() const override { return 0x1FC0; }
|
||||||
uInt32 myBankOffset{0};
|
|
||||||
|
uInt16 getStartBank() const override { return 15; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
|
|
|
@ -21,205 +21,7 @@
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
CartridgeDFSC::CartridgeDFSC(const ByteBuffer& image, size_t size,
|
CartridgeDFSC::CartridgeDFSC(const ByteBuffer& image, size_t size,
|
||||||
const string& md5, const Settings& settings)
|
const string& md5, const Settings& settings)
|
||||||
: Cartridge(settings, md5)
|
: CartridgeDF(image, size, md5, settings)
|
||||||
{
|
{
|
||||||
// Copy the ROM image into my buffer
|
myRamSize = RAM_SIZE;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
class System;
|
class System;
|
||||||
|
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "Cart.hxx"
|
#include "CartDF.hxx"
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
#include "CartDFSCWidget.hxx"
|
#include "CartDFSCWidget.hxx"
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,9 +31,9 @@ class System;
|
||||||
Accessing $1FC0 - $1FDF switches to each bank.
|
Accessing $1FC0 - $1FDF switches to each bank.
|
||||||
RAM read port is $1080 - $10FF, write port is $1000 - $107F.
|
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;
|
friend class CartridgeDFSCWidget;
|
||||||
|
|
||||||
|
@ -51,71 +51,6 @@ class CartridgeDFSC : public Cartridge
|
||||||
virtual ~CartridgeDFSC() = default;
|
virtual ~CartridgeDFSC() = default;
|
||||||
|
|
||||||
public:
|
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).
|
Get a descriptor for the device name (used in error checking).
|
||||||
|
|
||||||
|
@ -135,34 +70,11 @@ class CartridgeDFSC : public Cartridge
|
||||||
}
|
}
|
||||||
#endif
|
#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:
|
private:
|
||||||
// The 128K ROM image of the cartridge
|
// RAM size
|
||||||
std::array<uInt8, 128_KB> myImage;
|
static constexpr uInt16 RAM_SIZE = 0x80;
|
||||||
|
|
||||||
// The 128 bytes of RAM
|
private:
|
||||||
std::array<uInt8, 128> myRAM;
|
|
||||||
|
|
||||||
// Indicates the offset into the ROM image (aligns to current bank)
|
|
||||||
uInt32 myBankOffset{0};
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
CartridgeDFSC() = delete;
|
CartridgeDFSC() = delete;
|
||||||
CartridgeDFSC(const CartridgeDFSC&) = delete;
|
CartridgeDFSC(const CartridgeDFSC&) = delete;
|
||||||
|
|
|
@ -21,11 +21,9 @@
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
CartridgeE0::CartridgeE0(const ByteBuffer& image, size_t size,
|
CartridgeE0::CartridgeE0(const ByteBuffer& image, size_t size,
|
||||||
const string& md5, const Settings& settings)
|
const string& md5, const Settings& settings)
|
||||||
: Cartridge(settings, md5)
|
: CartridgeEnhanced(image, size, md5, settings)
|
||||||
{
|
{
|
||||||
// Copy the ROM image into my buffer
|
myBankShift = BANK_SHIFT;
|
||||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
|
||||||
createRomAccessArrays(myImage.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -44,7 +42,7 @@ void CartridgeE0::reset()
|
||||||
bank(5, 1);
|
bank(5, 1);
|
||||||
bank(6, 2);
|
bank(6, 2);
|
||||||
}
|
}
|
||||||
myCurrentBank[3] = bankCount() - 1; // fixed
|
myCurrentSegOffset[3] = (bankCount() - 1) << myBankShift; // fixed
|
||||||
|
|
||||||
myBankChanged = true;
|
myBankChanged = true;
|
||||||
}
|
}
|
||||||
|
@ -52,7 +50,13 @@ void CartridgeE0::reset()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void CartridgeE0::install(System& system)
|
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);
|
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
|
// Switch banks if necessary
|
||||||
if((address >= 0x0FE0) && (address <= 0x0FE7))
|
if((address >= 0x0FE0) && (address <= 0x0FE7))
|
||||||
{
|
{
|
||||||
bank(address & 0x0007, 0);
|
bank(address & 0x0007, 0);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
else if((address >= 0x0FE8) && (address <= 0x0FEF))
|
else if((address >= 0x0FE8) && (address <= 0x0FEF))
|
||||||
{
|
{
|
||||||
bank(address & 0x0007, 1);
|
bank(address & 0x0007, 1);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
else if((address >= 0x0FF0) && (address <= 0x0FF7))
|
else if((address >= 0x0FF0) && (address <= 0x0FF7))
|
||||||
{
|
{
|
||||||
bank(address & 0x0007, 2);
|
bank(address & 0x0007, 2);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
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;
|
class System;
|
||||||
|
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "Cart.hxx"
|
#include "CartEnhanced.hxx"
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
#include "CartE0Widget.hxx"
|
#include "CartE0Widget.hxx"
|
||||||
#endif
|
#endif
|
||||||
|
@ -39,9 +39,9 @@ class System;
|
||||||
only one actual bank, in which pieces of it can be swapped out in
|
only one actual bank, in which pieces of it can be swapped out in
|
||||||
many different ways.
|
many different ways.
|
||||||
|
|
||||||
@author Bradford W. Mott
|
@author Bradford W. Mott, Thomas Jentzsch
|
||||||
*/
|
*/
|
||||||
class CartridgeE0 : public Cartridge
|
class CartridgeE0 : public CartridgeEnhanced
|
||||||
{
|
{
|
||||||
friend class CartridgeE0Widget;
|
friend class CartridgeE0Widget;
|
||||||
|
|
||||||
|
@ -72,52 +72,6 @@ class CartridgeE0 : public Cartridge
|
||||||
*/
|
*/
|
||||||
void install(System& system) override;
|
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).
|
Get a descriptor for the device name (used in error checking).
|
||||||
|
|
||||||
|
@ -137,37 +91,14 @@ class CartridgeE0 : public Cartridge
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
private:
|
||||||
/**
|
bool checkSwitchBank(uInt16 address, uInt8 = 0) override;
|
||||||
Get the byte at the specified address.
|
|
||||||
|
|
||||||
@return The byte at the specified address
|
uInt16 romHotspot() const override { return 0x1FE0; }
|
||||||
*/
|
|
||||||
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:
|
private:
|
||||||
/**
|
// log(ROM bank segment size) / log(2)
|
||||||
Install the specified slice for segment (bank) 0..2
|
static constexpr uInt16 BANK_SHIFT = 10; // = 1K = 0x0400
|
||||||
|
|
||||||
@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;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
|
|
|
@ -21,145 +21,20 @@
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
CartridgeEF::CartridgeEF(const ByteBuffer& image, size_t size,
|
CartridgeEF::CartridgeEF(const ByteBuffer& image, size_t size,
|
||||||
const string& md5, const Settings& settings)
|
const string& md5, const Settings& settings)
|
||||||
: Cartridge(settings, md5)
|
: CartridgeEnhanced(image, size, md5, settings)
|
||||||
{
|
{
|
||||||
// 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()
|
bool CartridgeEF::checkSwitchBank(uInt16 address, uInt8)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
address &= 0x0FFF;
|
address &= 0x0FFF;
|
||||||
|
|
||||||
// Switch banks if necessary
|
// Switch banks if necessary
|
||||||
if((address >= 0x0FE0) && (address <= 0x0FEF))
|
if((address >= 0x0FE0) && (address <= 0x0FEF))
|
||||||
|
{
|
||||||
bank(address - 0x0FE0);
|
bank(address - 0x0FE0);
|
||||||
|
return true;
|
||||||
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 false;
|
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;
|
class System;
|
||||||
|
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "Cart.hxx"
|
#include "CartEnhanced.hxx"
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
#include "CartEFWidget.hxx"
|
#include "CartEFWidget.hxx"
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,9 +31,9 @@ class System;
|
||||||
There are 16 4K banks (total of 64K ROM).
|
There are 16 4K banks (total of 64K ROM).
|
||||||
Accessing $1FE0 - $1FEF switches to each bank.
|
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;
|
friend class CartridgeEFWidget;
|
||||||
|
|
||||||
|
@ -51,71 +51,6 @@ class CartridgeEF : public Cartridge
|
||||||
virtual ~CartridgeEF() = default;
|
virtual ~CartridgeEF() = default;
|
||||||
|
|
||||||
public:
|
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).
|
Get a descriptor for the device name (used in error checking).
|
||||||
|
|
||||||
|
@ -135,29 +70,12 @@ class CartridgeEF : public Cartridge
|
||||||
}
|
}
|
||||||
#endif
|
#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:
|
private:
|
||||||
// The 64K ROM image of the cartridge
|
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
|
||||||
std::array<uInt8, 64_KB> myImage;
|
|
||||||
|
|
||||||
// Indicates the offset into the ROM image (aligns to current bank)
|
uInt16 romHotspot() const override { return 0x1FE0; }
|
||||||
uInt16 myBankOffset{0};
|
|
||||||
|
uInt16 getStartBank() const override { return 1; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
|
|
|
@ -21,205 +21,7 @@
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
CartridgeEFSC::CartridgeEFSC(const ByteBuffer& image, size_t size,
|
CartridgeEFSC::CartridgeEFSC(const ByteBuffer& image, size_t size,
|
||||||
const string& md5, const Settings& settings)
|
const string& md5, const Settings& settings)
|
||||||
: Cartridge(settings, md5)
|
: CartridgeEF(image, size, md5, settings)
|
||||||
{
|
{
|
||||||
// Copy the ROM image into my buffer
|
myRamSize = RAM_SIZE;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
class System;
|
class System;
|
||||||
|
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "Cart.hxx"
|
#include "CartEF.hxx"
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
#include "CartEFSCWidget.hxx"
|
#include "CartEFSCWidget.hxx"
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,9 +32,9 @@ class System;
|
||||||
Accessing $1FE0 - $1FEF switches to each bank.
|
Accessing $1FE0 - $1FEF switches to each bank.
|
||||||
RAM read port is $1080 - $10FF, write port is $1000 - $107F.
|
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;
|
friend class CartridgeEFSCWidget;
|
||||||
|
|
||||||
|
@ -52,71 +52,6 @@ class CartridgeEFSC : public Cartridge
|
||||||
virtual ~CartridgeEFSC() = default;
|
virtual ~CartridgeEFSC() = default;
|
||||||
|
|
||||||
public:
|
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).
|
Get a descriptor for the device name (used in error checking).
|
||||||
|
|
||||||
|
@ -136,32 +71,12 @@ class CartridgeEFSC : public Cartridge
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
private:
|
||||||
/**
|
uInt16 getStartBank() const override { return 15; }
|
||||||
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:
|
private:
|
||||||
// The 64K ROM image of the cartridge
|
// RAM size
|
||||||
std::array<uInt8, 64_KB> myImage;
|
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)
|
|
||||||
uInt16 myBankOffset{0};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
|
|
|
@ -37,9 +37,14 @@ CartridgeEnhanced::CartridgeEnhanced(const ByteBuffer& image, size_t size,
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void CartridgeEnhanced::install(System& system)
|
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
|
// Allocate array for the current bank segments slices
|
||||||
myCurrentBankOffset = make_unique<uInt16[]>(BANK_SEGS);
|
myCurrentSegOffset = make_unique<uInt32[]>(myBankSegs);
|
||||||
std::fill_n(myCurrentBankOffset.get(), BANK_SEGS, 0);
|
|
||||||
|
|
||||||
// Allocate array for the RAM area
|
// Allocate array for the RAM area
|
||||||
myRAM = make_unique<uInt8[]>(myRamSize);
|
myRAM = make_unique<uInt8[]>(myRamSize);
|
||||||
|
@ -93,24 +98,22 @@ void CartridgeEnhanced::reset()
|
||||||
uInt8 CartridgeEnhanced::peek(uInt16 address)
|
uInt8 CartridgeEnhanced::peek(uInt16 address)
|
||||||
{
|
{
|
||||||
uInt16 peekAddress = address;
|
uInt16 peekAddress = address;
|
||||||
address &= myBankMask;
|
|
||||||
|
|
||||||
checkSwitchBank(address);
|
checkSwitchBank(address & 0x0FFF);
|
||||||
|
address &= myBankMask;
|
||||||
|
|
||||||
if(address < myRamSize) // Write port is at 0xF000 - 0xF07F (128 bytes)
|
if(address < myRamSize) // Write port is at 0xF000 - 0xF07F (128 bytes)
|
||||||
return peekRAM(myRAM[address], peekAddress);
|
return peekRAM(myRAM[address], peekAddress);
|
||||||
else
|
else
|
||||||
return myImage[myBankOffset + address];
|
//return myImage[myBankOffset + address];
|
||||||
return myImage[myCurrentBankOffset[address >> BANK_SHIFT] + (address & BANK_MASK)];
|
return myImage[myCurrentSegOffset[(peekAddress & 0xFFF) >> myBankShift] + address];
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool CartridgeEnhanced::poke(uInt16 address, uInt8 value)
|
bool CartridgeEnhanced::poke(uInt16 address, uInt8 value)
|
||||||
{
|
{
|
||||||
address &= myBankMask;
|
|
||||||
|
|
||||||
// Switch banks if necessary
|
// Switch banks if necessary
|
||||||
if (checkSwitchBank(address & myBankMask))
|
if (checkSwitchBank(address & 0x0FFF))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(myRamSize)
|
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;
|
if(bankLocked()) return false;
|
||||||
|
|
||||||
// Remember what bank we're in
|
// Remember what bank is in which segment
|
||||||
myBankOffset = bank << myBankShift;
|
uInt32 bankOffset = myCurrentSegOffset[segment] = bank << myBankShift;
|
||||||
|
uInt16 segmentOffset = segment << myBankShift;
|
||||||
uInt16 romHotspot = this->romHotspot();
|
uInt16 romHotspot = this->romHotspot();
|
||||||
uInt16 fromAddr = 0x1000 + myRamSize * 2;
|
uInt16 hotSpotAddr;
|
||||||
uInt16 toAddr;
|
uInt16 fromAddr = (segmentOffset + 0x1000 + myRamSize * 2) & ~System::PAGE_MASK;
|
||||||
|
uInt16 toAddr = (segmentOffset + 0x1000 + myBankSize) & ~System::PAGE_MASK;
|
||||||
|
|
||||||
if(romHotspot)
|
if(romHotspot)
|
||||||
{
|
hotSpotAddr = segmentOffset + (romHotspot & ~System::PAGE_MASK);
|
||||||
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;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
toAddr = 0x1000 + myBankSize;
|
hotSpotAddr = 0xFFFF; // none
|
||||||
|
|
||||||
System::PageAccess access(this, System::PageAccessType::READ);
|
System::PageAccess access(this, System::PageAccessType::READ);
|
||||||
|
|
||||||
// Setup the page access methods for the current bank
|
// Setup the page access methods for the current bank
|
||||||
for(uInt16 addr = (fromAddr & ~System::PAGE_MASK); addr < (toAddr & ~System::PAGE_MASK);
|
for(uInt16 addr = fromAddr; addr < toAddr; addr += System::PAGE_SIZE)
|
||||||
addr += System::PAGE_SIZE)
|
|
||||||
{
|
{
|
||||||
uInt16 offset = myBankOffset + (addr & myBankMask);
|
uInt32 offset = bankOffset + (addr & myBankMask);
|
||||||
if(myDirectPeek)
|
|
||||||
|
if(myDirectPeek && addr != hotSpotAddr)
|
||||||
access.directPeekBase = &myImage[offset];
|
access.directPeekBase = &myImage[offset];
|
||||||
|
else
|
||||||
|
access.directPeekBase = nullptr;
|
||||||
access.romAccessBase = &myRomAccessBase[offset];
|
access.romAccessBase = &myRomAccessBase[offset];
|
||||||
access.romPeekCounter = &myRomAccessCounter[offset];
|
access.romPeekCounter = &myRomAccessCounter[offset];
|
||||||
access.romPokeCounter = &myRomAccessCounter[offset + myAccessSize];
|
access.romPokeCounter = &myRomAccessCounter[offset + myAccessSize];
|
||||||
|
@ -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)
|
bool CartridgeEnhanced::patch(uInt16 address, uInt8 value)
|
||||||
{
|
{
|
||||||
address &= myBankMask;
|
if((address & myBankMask) < myRamSize * 2)
|
||||||
|
|
||||||
if(address < myRamSize * 2)
|
|
||||||
{
|
{
|
||||||
// Normally, a write to the read port won't do anything
|
// Normally, a write to the read port won't do anything
|
||||||
// However, the patch command is special in that ignores such
|
// 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;
|
myRAM[address & myRamMask] = value;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
myImage[myBankOffset + address] = value;
|
myImage[myCurrentSegOffset[(address & 0xFFF) >> myBankShift] + (address & myBankMask)] = value;
|
||||||
|
|
||||||
return myBankChanged = true;
|
return myBankChanged = true;
|
||||||
}
|
}
|
||||||
|
@ -223,7 +213,7 @@ bool CartridgeEnhanced::save(Serializer& out) const
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putShort(myBankOffset);
|
out.putIntArray(myCurrentSegOffset.get(), myBankSegs);
|
||||||
if(myRamSize)
|
if(myRamSize)
|
||||||
out.putByteArray(myRAM.get(), myRamSize);
|
out.putByteArray(myRAM.get(), myRamSize);
|
||||||
|
|
||||||
|
@ -242,7 +232,7 @@ bool CartridgeEnhanced::load(Serializer& in)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
myBankOffset = in.getShort();
|
in.getIntArray(myCurrentSegOffset.get(), myBankSegs);
|
||||||
if(myRamSize)
|
if(myRamSize)
|
||||||
in.getByteArray(myRAM.get(), myRamSize);
|
in.getByteArray(myRAM.get(), myRamSize);
|
||||||
}
|
}
|
||||||
|
@ -251,9 +241,5 @@ bool CartridgeEnhanced::load(Serializer& in)
|
||||||
cerr << "ERROR: " << name() << "::load" << endl;
|
cerr << "ERROR: " << name() << "::load" << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remember what bank we were in
|
|
||||||
bank(myBankOffset >> myBankShift);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ class CartridgeEnhanced : public Cartridge
|
||||||
|
|
||||||
@param bank The bank that should be installed in the system
|
@param bank The bank that should be installed in the system
|
||||||
*/
|
*/
|
||||||
bool bank(uInt16 bank, uInt16 slice);
|
bool bank(uInt16 bank, uInt16 segment);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Install pages for the specified bank in the system.
|
Install pages for the specified bank in the system.
|
||||||
|
@ -135,62 +135,71 @@ class CartridgeEnhanced : public Cartridge
|
||||||
bool poke(uInt16 address, uInt8 value) override;
|
bool poke(uInt16 address, uInt8 value) override;
|
||||||
|
|
||||||
protected:
|
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
|
// Pointer to a dynamically allocated ROM image of the cartridge
|
||||||
ByteBuffer myImage{nullptr};
|
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
|
// Pointer to a dynamically allocated RAM area of the cartridge
|
||||||
ByteBuffer myRAM{nullptr};
|
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:
|
private:
|
||||||
// log(ROM bank size) / log(2)
|
// Calculated as: log(ROM bank segment size) / log(2)
|
||||||
static constexpr uInt16 BANK_SHIFT = 12;
|
static constexpr uInt16 BANK_SHIFT = 12; // default = 4K
|
||||||
|
|
||||||
// bank size
|
// The size of extra RAM in ROM address space
|
||||||
static constexpr uInt16 BANK_SIZE = 1 << BANK_SHIFT; // 2 ^ 12 = 4K
|
static constexpr uInt16 RAM_SIZE = 0; // default = none
|
||||||
|
|
||||||
// bank mask
|
// The size of the ROM image
|
||||||
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
|
|
||||||
size_t mySize{0};
|
size_t mySize{0};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
Check hotspots and switch bank if triggered.
|
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;
|
virtual bool checkSwitchBank(uInt16 address, uInt8 value = 0) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/**
|
||||||
|
Get the ROM's startup bank.
|
||||||
|
|
||||||
|
@return The bank the ROM will start in
|
||||||
|
*/
|
||||||
virtual uInt16 getStartBank() const { return 0; }
|
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; }
|
virtual uInt16 romHotspot() const { return 0; }
|
||||||
|
// TODO: handle cases where there the hotspots cover multiple pages
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
|
|
|
@ -67,12 +67,11 @@ class CartridgeF0 : public CartridgeEnhanced
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
bool checkSwitchBank(uInt16 address, uInt8 value = 0);
|
bool checkSwitchBank(uInt16 address, uInt8 value = 0);
|
||||||
|
|
||||||
uInt16 romHotspot() const override { return 0x1FF0; }
|
uInt16 romHotspot() const override { return 0x1FF0; }
|
||||||
|
|
||||||
private:
|
|
||||||
uInt16 getStartBank() const override { return 15; }
|
uInt16 getStartBank() const override { return 15; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -66,7 +66,7 @@ class CartridgeF4 : public CartridgeEnhanced
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
bool checkSwitchBank(uInt16 address, uInt8 value = 0);
|
bool checkSwitchBank(uInt16 address, uInt8 value = 0);
|
||||||
|
|
||||||
uInt16 romHotspot() const override { return 0x1FF4; }
|
uInt16 romHotspot() const override { return 0x1FF4; }
|
||||||
|
|
|
@ -23,5 +23,5 @@ CartridgeF4SC::CartridgeF4SC(const ByteBuffer& image, size_t size,
|
||||||
: CartridgeF4(image, size, md5, settings)
|
: CartridgeF4(image, size, md5, settings)
|
||||||
{
|
{
|
||||||
myRamSize = RAM_SIZE;
|
myRamSize = RAM_SIZE;
|
||||||
myRamMask = RAM_MASK;
|
myRamMask = RAM_SIZE - 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ class CartridgeF6 : public CartridgeEnhanced
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
|
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
|
||||||
|
|
||||||
uInt16 romHotspot() const override { return 0x1FF6; }
|
uInt16 romHotspot() const override { return 0x1FF6; }
|
||||||
|
|
|
@ -23,5 +23,5 @@ CartridgeF6SC::CartridgeF6SC(const ByteBuffer& image, size_t size,
|
||||||
: CartridgeF6(image, size, md5, settings)
|
: CartridgeF6(image, size, md5, settings)
|
||||||
{
|
{
|
||||||
myRamSize = RAM_SIZE;
|
myRamSize = RAM_SIZE;
|
||||||
myRamMask = RAM_MASK;
|
myRamMask = RAM_SIZE - 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,12 +66,11 @@ class CartridgeF8 : public CartridgeEnhanced
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
|
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
|
||||||
|
|
||||||
uInt16 romHotspot() const override { return 0x1FF8; }
|
uInt16 romHotspot() const override { return 0x1FF8; }
|
||||||
|
|
||||||
private:
|
|
||||||
uInt16 getStartBank() const override { return 1; }
|
uInt16 getStartBank() const override { return 1; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -23,5 +23,4 @@ CartridgeF8SC::CartridgeF8SC(const ByteBuffer& image, size_t size,
|
||||||
: CartridgeF8(image, size, md5, settings)
|
: CartridgeF8(image, size, md5, settings)
|
||||||
{
|
{
|
||||||
myRamSize = RAM_SIZE;
|
myRamSize = RAM_SIZE;
|
||||||
myRamMask = RAM_MASK;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,9 +71,6 @@ class CartridgeF8SC : public CartridgeF8
|
||||||
// RAM size
|
// RAM size
|
||||||
static constexpr uInt16 RAM_SIZE = 0x80;
|
static constexpr uInt16 RAM_SIZE = 0x80;
|
||||||
|
|
||||||
// RAM mask
|
|
||||||
static constexpr uInt16 RAM_MASK = RAM_SIZE - 1;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
CartridgeF8SC() = delete;
|
CartridgeF8SC() = delete;
|
||||||
|
|
|
@ -87,12 +87,11 @@ class CartridgeFC : public CartridgeEnhanced
|
||||||
*/
|
*/
|
||||||
bool poke(uInt16 address, uInt8 value) override;
|
bool poke(uInt16 address, uInt8 value) override;
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
|
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
|
||||||
|
|
||||||
uInt16 romHotspot() const override { return 0x1FF8; }
|
uInt16 romHotspot() const override { return 0x1FF8; }
|
||||||
|
|
||||||
private:
|
|
||||||
// Target bank defined by writing to $1FF8/9
|
// Target bank defined by writing to $1FF8/9
|
||||||
uInt16 myTargetBank{0};
|
uInt16 myTargetBank{0};
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ void CartridgeFE::reset()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void CartridgeFE::install(System& system)
|
void CartridgeFE::install(System& system)
|
||||||
{
|
{
|
||||||
mySystem = &system;
|
CartridgeEnhanced::install(system);
|
||||||
|
|
||||||
// The hotspot $01FE is in a mirror of zero-page RAM
|
// 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
|
// 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 CartridgeFE::peek(uInt16 address)
|
||||||
{
|
{
|
||||||
uInt8 value = (address < 0x200) ? mySystem->m6532().peek(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
|
// Check if we hit hotspot
|
||||||
checkSwitchBank(address, value);
|
checkSwitchBank(address, value);
|
||||||
|
|
|
@ -72,8 +72,8 @@ class System;
|
||||||
particular *why* the address $01FE will be placed on the address
|
particular *why* the address $01FE will be placed on the address
|
||||||
bus after both the JSR and RTS opcodes.
|
bus after both the JSR and RTS opcodes.
|
||||||
|
|
||||||
@author Stephen Anthony; with ideas/research from Christian Speckner and
|
@author Stephen Anthony, Thomas Jentzsch; with ideas/research from Christian
|
||||||
alex_79 and TomSon (of AtariAge)
|
Speckner and alex_79 and TomSon (of AtariAge)
|
||||||
*/
|
*/
|
||||||
class CartridgeFE : public CartridgeEnhanced
|
class CartridgeFE : public CartridgeEnhanced
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,7 +30,7 @@ CartridgeUA::CartridgeUA(const ByteBuffer& image, size_t size,
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void CartridgeUA::install(System& system)
|
void CartridgeUA::install(System& system)
|
||||||
{
|
{
|
||||||
mySystem = &system;
|
CartridgeEnhanced::install(system);
|
||||||
|
|
||||||
// Get the page accessing methods for the hot spots since they overlap
|
// 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
|
// 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;
|
bool poke(uInt16 address, uInt8 value) override;
|
||||||
|
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
|
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue