mirror of https://github.com/stella-emu/stella.git
refactor Cart2K and Cart4K(SC)
This commit is contained in:
parent
53387c4b13
commit
edd9cd0147
|
@ -25,7 +25,10 @@ Cartridge2KWidget::Cartridge2KWidget(
|
||||||
: CartDebugWidget(boss, lfont, nfont, x, y, w, h)
|
: CartDebugWidget(boss, lfont, nfont, x, y, w, h)
|
||||||
{
|
{
|
||||||
// Eventually, we should query this from the debugger/disassembler
|
// Eventually, we should query this from the debugger/disassembler
|
||||||
size_t size = cart.mySize;
|
size_t size;
|
||||||
|
|
||||||
|
cart.getImage(size);
|
||||||
|
|
||||||
uInt16 start = (cart.myImage[size-3] << 8) | cart.myImage[size-4];
|
uInt16 start = (cart.myImage[size-3] << 8) | cart.myImage[size-4];
|
||||||
start -= start % size;
|
start -= start % size;
|
||||||
|
|
||||||
|
|
|
@ -21,15 +21,19 @@
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Cartridge2K::Cartridge2K(const ByteBuffer& image, size_t size,
|
Cartridge2K::Cartridge2K(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)
|
||||||
{
|
{
|
||||||
// Size can be a maximum of 2K
|
// Size can be a maximum of 2K
|
||||||
if(size > 2_KB) size = 2_KB;
|
if(size > 2_KB)
|
||||||
|
size = 2_KB;
|
||||||
|
|
||||||
// Set image size to closest power-of-two for the given size
|
// Set image size to closest power-of-two for the given size
|
||||||
mySize = 1;
|
mySize = 1; myBankShift = 0;
|
||||||
while(mySize < size)
|
while(mySize < size)
|
||||||
|
{
|
||||||
mySize <<= 1;
|
mySize <<= 1;
|
||||||
|
myBankShift++;
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize ROM with illegal 6502 opcode that causes a real 6502 to jam
|
// Initialize ROM with illegal 6502 opcode that causes a real 6502 to jam
|
||||||
size_t bufSize = std::max<size_t>(mySize, System::PAGE_SIZE);
|
size_t bufSize = std::max<size_t>(mySize, System::PAGE_SIZE);
|
||||||
|
@ -49,62 +53,12 @@ Cartridge2K::Cartridge2K(const ByteBuffer& image, size_t size,
|
||||||
for(size_t i = 0; i < System::PAGE_SIZE; i += mySize)
|
for(size_t i = 0; i < System::PAGE_SIZE; i += mySize)
|
||||||
std::copy_n(image.get(), mySize, myImage.get() + i);
|
std::copy_n(image.get(), mySize, myImage.get() + i);
|
||||||
mySize = System::PAGE_SIZE;
|
mySize = System::PAGE_SIZE;
|
||||||
|
myBankShift = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update access arrays, bank size and mask based on new size
|
||||||
createRomAccessArrays(mySize);
|
createRomAccessArrays(mySize);
|
||||||
|
|
||||||
// Set mask for accessing the image buffer
|
myBankSize = 1 << myBankShift; // e.g. = 2 ^ 11 = 2048 = 0x0800
|
||||||
// This is guaranteed to work, as mySize is a power of two
|
myBankMask = myBankSize - 1; // e.g. = 0x07FF
|
||||||
myMask = static_cast<uInt16>(mySize) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void Cartridge2K::reset()
|
|
||||||
{
|
|
||||||
myBankChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void Cartridge2K::install(System& system)
|
|
||||||
{
|
|
||||||
mySystem = &system;
|
|
||||||
|
|
||||||
// Map ROM image into the system
|
|
||||||
// Note that we don't need our own peek/poke methods, since the mapping
|
|
||||||
// takes care of the entire address space
|
|
||||||
System::PageAccess access(this, System::PageAccessType::READ);
|
|
||||||
for(uInt16 addr = 0x1000; addr < 0x2000; addr += System::PAGE_SIZE)
|
|
||||||
{
|
|
||||||
access.directPeekBase = &myImage[addr & myMask];
|
|
||||||
access.romAccessBase = &myRomAccessBase[addr & myMask];
|
|
||||||
access.romPeekCounter = &myRomAccessCounter[addr & myMask];
|
|
||||||
access.romPokeCounter = &myRomAccessCounter[(addr & myMask) + myAccessSize];
|
|
||||||
mySystem->setPageAccess(addr, access);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool Cartridge2K::patch(uInt16 address, uInt8 value)
|
|
||||||
{
|
|
||||||
myImage[address & myMask] = value;
|
|
||||||
return myBankChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
const uInt8* Cartridge2K::getImage(size_t& size) const
|
|
||||||
{
|
|
||||||
size = mySize;
|
|
||||||
return myImage.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool Cartridge2K::save(Serializer&) const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool Cartridge2K::load(Serializer&)
|
|
||||||
{
|
|
||||||
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 "Cart2KWidget.hxx"
|
#include "Cart2KWidget.hxx"
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,9 +33,9 @@ class System;
|
||||||
data repeats in intervals based on the size of the ROM (which will
|
data repeats in intervals based on the size of the ROM (which will
|
||||||
always be a power of 2).
|
always be a power of 2).
|
||||||
|
|
||||||
@author Stephen Anthony
|
@author Stephen Anthony, Thomas Jentzsch
|
||||||
*/
|
*/
|
||||||
class Cartridge2K : public Cartridge
|
class Cartridge2K : public CartridgeEnhanced
|
||||||
{
|
{
|
||||||
friend class Cartridge2KWidget;
|
friend class Cartridge2KWidget;
|
||||||
|
|
||||||
|
@ -53,52 +53,6 @@ class Cartridge2K : public Cartridge
|
||||||
virtual ~Cartridge2K() = default;
|
virtual ~Cartridge2K() = default;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
Reset cartridge 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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
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).
|
||||||
|
|
||||||
|
@ -118,22 +72,8 @@ class Cartridge2K : public Cartridge
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
Get the byte at the specified address.
|
|
||||||
|
|
||||||
@return The byte at the specified address
|
|
||||||
*/
|
|
||||||
uInt8 peek(uInt16 address) override { return myImage[address & myMask]; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Pointer to a dynamically allocated ROM image of the cartridge
|
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override { return false; };
|
||||||
ByteBuffer myImage;
|
|
||||||
|
|
||||||
// Size of the ROM image
|
|
||||||
size_t mySize{0};
|
|
||||||
|
|
||||||
// Mask to use for mirroring
|
|
||||||
uInt16 myMask{0};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
|
|
|
@ -21,48 +21,7 @@
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Cartridge4K::Cartridge4K(const ByteBuffer& image, size_t size,
|
Cartridge4K::Cartridge4K(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
|
cerr << "Cartridge4K" << endl;
|
||||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
|
||||||
createRomAccessArrays(myImage.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void Cartridge4K::reset()
|
|
||||||
{
|
|
||||||
myBankChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void Cartridge4K::install(System& system)
|
|
||||||
{
|
|
||||||
mySystem = &system;
|
|
||||||
|
|
||||||
// Map ROM image into the system
|
|
||||||
// Note that we don't need our own peek/poke methods, since the mapping
|
|
||||||
// takes care of the entire address space
|
|
||||||
System::PageAccess access(this, System::PageAccessType::READ);
|
|
||||||
for(uInt16 addr = 0x1000; addr < 0x2000; addr += System::PAGE_SIZE)
|
|
||||||
{
|
|
||||||
access.directPeekBase = &myImage[addr & 0x0FFF];
|
|
||||||
access.romAccessBase = &myRomAccessBase[addr & 0x0FFF];
|
|
||||||
access.romPeekCounter = &myRomAccessCounter[addr & 0x0FFF];
|
|
||||||
access.romPokeCounter = &myRomAccessCounter[(addr & 0x0FFF) + myAccessSize];
|
|
||||||
mySystem->setPageAccess(addr, access);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool Cartridge4K::patch(uInt16 address, uInt8 value)
|
|
||||||
{
|
|
||||||
myImage[address & 0x0FFF] = value;
|
|
||||||
return myBankChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
const uInt8* Cartridge4K::getImage(size_t& size) const
|
|
||||||
{
|
|
||||||
size = myImage.size();
|
|
||||||
return myImage.data();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 "Cart4KWidget.hxx"
|
#include "Cart4KWidget.hxx"
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,9 +30,9 @@ class System;
|
||||||
This is the standard Atari 4K cartridge. These cartridges are
|
This is the standard Atari 4K cartridge. These cartridges are
|
||||||
not bankswitched.
|
not bankswitched.
|
||||||
|
|
||||||
@author Bradford W. Mott
|
@author Bradford W. Mott, Thomas Jentzsch
|
||||||
*/
|
*/
|
||||||
class Cartridge4K : public Cartridge
|
class Cartridge4K : public CartridgeEnhanced
|
||||||
{
|
{
|
||||||
friend class Cartridge4KWidget;
|
friend class Cartridge4KWidget;
|
||||||
|
|
||||||
|
@ -50,52 +50,6 @@ class Cartridge4K : public Cartridge
|
||||||
virtual ~Cartridge4K() = default;
|
virtual ~Cartridge4K() = default;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
Reset cartridge 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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
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 { return true; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
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 { return true; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get a descriptor for the device name (used in error checking).
|
Get a descriptor for the device name (used in error checking).
|
||||||
|
|
||||||
|
@ -115,16 +69,8 @@ class Cartridge4K : public Cartridge
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
Get the byte at the specified address.
|
|
||||||
|
|
||||||
@return The byte at the specified address
|
|
||||||
*/
|
|
||||||
uInt8 peek(uInt16 address) override { return myImage[address & 0x0FFF]; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The 4K ROM image for the cartridge
|
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override { return false; };
|
||||||
std::array<uInt8, 4_KB> myImage;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
|
|
|
@ -21,137 +21,7 @@
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Cartridge4KSC::Cartridge4KSC(const ByteBuffer& image, size_t size,
|
Cartridge4KSC::Cartridge4KSC(const ByteBuffer& image, size_t size,
|
||||||
const string& md5, const Settings& settings)
|
const string& md5, const Settings& settings)
|
||||||
: Cartridge(settings, md5)
|
: Cartridge4K(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 Cartridge4KSC::reset()
|
|
||||||
{
|
|
||||||
initializeRAM(myRAM.data(), myRAM.size());
|
|
||||||
|
|
||||||
myBankChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void Cartridge4KSC::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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map ROM image into the system
|
|
||||||
for(uInt16 addr = 0x1100; addr < 0x2000; addr += System::PAGE_SIZE)
|
|
||||||
{
|
|
||||||
access.directPeekBase = &myImage[addr & 0x0FFF];
|
|
||||||
access.romAccessBase = &myRomAccessBase[addr & 0x0FFF];
|
|
||||||
mySystem->setPageAccess(addr, access);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
uInt8 Cartridge4KSC::peek(uInt16 address)
|
|
||||||
{
|
|
||||||
// The only way we can get to this method is if we attempt to read from
|
|
||||||
// the write port (0xF000 - 0xF07F, 128 bytes), in which case an
|
|
||||||
// unwanted write is potentially triggered
|
|
||||||
return peekRAM(myRAM[address & 0x007F], address);
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool Cartridge4KSC::poke(uInt16 address, uInt8 value)
|
|
||||||
{
|
|
||||||
if (!(address & 0x080))
|
|
||||||
{
|
|
||||||
pokeRAM(myRAM[address & 0x007F], address, value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Writing to the read port should be ignored, but trigger a break if option enabled
|
|
||||||
uInt8 dummy;
|
|
||||||
|
|
||||||
pokeRAM(dummy, address, value);
|
|
||||||
myRamWriteAccess = address;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool Cartridge4KSC::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[address & 0xFFF] = value;
|
|
||||||
|
|
||||||
return myBankChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
const uInt8* Cartridge4KSC::getImage(size_t& size) const
|
|
||||||
{
|
|
||||||
size = myImage.size();
|
|
||||||
return myImage.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool Cartridge4KSC::save(Serializer& out) const
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
out.putByteArray(myRAM.data(), myRAM.size());
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
cerr << "ERROR: Cartridge4KSC::save" << endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool Cartridge4KSC::load(Serializer& in)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
in.getByteArray(myRAM.data(), myRAM.size());
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
cerr << "ERROR: Cartridge4KSC::load" << endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
class System;
|
class System;
|
||||||
|
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "Cart.hxx"
|
#include "Cart4K.hxx"
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
#include "Cart4KSCWidget.hxx"
|
#include "Cart4KSCWidget.hxx"
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,9 +29,11 @@ class System;
|
||||||
/**
|
/**
|
||||||
Cartridge class used for 4K games with 128 bytes of RAM.
|
Cartridge class used for 4K games with 128 bytes of RAM.
|
||||||
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, Thomas Jentzsch
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Cartridge4KSC : public Cartridge
|
class Cartridge4KSC : public Cartridge4K
|
||||||
{
|
{
|
||||||
friend class Cartridge4KSCWidget;
|
friend class Cartridge4KSCWidget;
|
||||||
|
|
||||||
|
@ -49,52 +51,6 @@ class Cartridge4KSC : public Cartridge
|
||||||
virtual ~Cartridge4KSC() = default;
|
virtual ~Cartridge4KSC() = 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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
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).
|
||||||
|
|
||||||
|
@ -114,29 +70,9 @@ class Cartridge4KSC : 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 4K ROM image of the cartridge
|
// RAM size
|
||||||
std::array<uInt8, 4_KB> myImage;
|
static constexpr uInt16 RAM_SIZE = 0x80;
|
||||||
|
|
||||||
// The 128 bytes of RAM
|
|
||||||
std::array<uInt8, 128> myRAM;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
|
|
|
@ -24,19 +24,19 @@ CartridgeEnhanced::CartridgeEnhanced(const ByteBuffer& image, size_t size,
|
||||||
: Cartridge(settings, md5),
|
: Cartridge(settings, md5),
|
||||||
mySize(size)
|
mySize(size)
|
||||||
{
|
{
|
||||||
// Allocate array for the ROM image
|
// Allocate array for the ROM image (at least 64 bytzes)
|
||||||
myImage = make_unique<uInt8[]>(mySize);
|
myImage = make_unique<uInt8[]>(std::max(uInt16(mySize), System::PAGE_SIZE));
|
||||||
|
|
||||||
// Copy the ROM image into my buffer
|
// Copy the ROM image into my buffer
|
||||||
std::copy_n(image.get(), mySize, myImage.get());
|
std::copy_n(image.get(), mySize, myImage.get());
|
||||||
|
|
||||||
// Copy the ROM image into my buffer
|
|
||||||
createRomAccessArrays(mySize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void CartridgeEnhanced::install(System& system)
|
void CartridgeEnhanced::install(System& system)
|
||||||
{
|
{
|
||||||
|
// Copy the ROM image into my buffer
|
||||||
|
createRomAccessArrays(mySize);
|
||||||
|
|
||||||
// calculate bank switching and RAM sizes and masks
|
// calculate bank switching and RAM sizes and masks
|
||||||
myBankSize = 1 << myBankShift; // e.g. = 2 ^ 12 = 4K = 0x1000
|
myBankSize = 1 << myBankShift; // e.g. = 2 ^ 12 = 4K = 0x1000
|
||||||
myBankMask = myBankSize - 1; // e.g. = 0x0FFF
|
myBankMask = myBankSize - 1; // e.g. = 0x0FFF
|
||||||
|
@ -81,7 +81,7 @@ void CartridgeEnhanced::install(System& system)
|
||||||
|
|
||||||
// Install pages for the startup bank (TODO: currently only in first bank segment)
|
// Install pages for the startup bank (TODO: currently only in first bank segment)
|
||||||
bank(startBank(), 0);
|
bank(startBank(), 0);
|
||||||
if(myBankSegs > 1)
|
if(mySize >= 4_KB && myBankSegs > 1)
|
||||||
// Setup the last bank segment to always point to the last ROM segment
|
// Setup the last bank segment to always point to the last ROM segment
|
||||||
bank(bankCount() - 1, myBankSegs - 1);
|
bank(bankCount() - 1, myBankSegs - 1);
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,8 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment)
|
||||||
uInt16 hotspot = this->hotspot();
|
uInt16 hotspot = this->hotspot();
|
||||||
uInt16 hotSpotAddr;
|
uInt16 hotSpotAddr;
|
||||||
uInt16 fromAddr = (segmentOffset + 0x1000 + myRamSize * 2) & ~System::PAGE_MASK;
|
uInt16 fromAddr = (segmentOffset + 0x1000 + myRamSize * 2) & ~System::PAGE_MASK;
|
||||||
uInt16 toAddr = (segmentOffset + 0x1000 + myBankSize) & ~System::PAGE_MASK;
|
// for ROMs < 4_KB, the whole address space will be mapped.
|
||||||
|
uInt16 toAddr = (segmentOffset + 0x1000 + (mySize < 4_KB ? 0x1000 : myBankSize)) & ~System::PAGE_MASK;
|
||||||
|
|
||||||
if(hotspot)
|
if(hotspot)
|
||||||
hotSpotAddr = (hotspot & ~System::PAGE_MASK);
|
hotSpotAddr = (hotspot & ~System::PAGE_MASK);
|
||||||
|
|
|
@ -172,6 +172,9 @@ class CartridgeEnhanced : public Cartridge
|
||||||
// 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};
|
||||||
|
|
||||||
|
// The size of the ROM image
|
||||||
|
size_t mySize{0};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Calculated as: log(ROM bank segment size) / log(2)
|
// Calculated as: log(ROM bank segment size) / log(2)
|
||||||
static constexpr uInt16 BANK_SHIFT = 12; // default = 4K
|
static constexpr uInt16 BANK_SHIFT = 12; // default = 4K
|
||||||
|
@ -179,9 +182,6 @@ class CartridgeEnhanced : public Cartridge
|
||||||
// The size of extra RAM in ROM address space
|
// The size of extra RAM in ROM address space
|
||||||
static constexpr uInt16 RAM_SIZE = 0; // default = none
|
static constexpr uInt16 RAM_SIZE = 0; // default = none
|
||||||
|
|
||||||
// The size of the ROM image
|
|
||||||
size_t mySize{0};
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
Check hotspots and switch bank if triggered.
|
Check hotspots and switch bank if triggered.
|
||||||
|
|
Loading…
Reference in New Issue