mirror of https://github.com/stella-emu/stella.git
parent
8352a36401
commit
7e2ccf6d99
|
@ -88,7 +88,7 @@ string Cartridge3FWidget::bankState()
|
|||
{
|
||||
ostringstream& buf = buffer();
|
||||
|
||||
buf << "Bank = #" << std::dec << myCart.myCurrentBank << ", hotspot = $3F";
|
||||
buf << "Bank = #" << std::dec << (myCart.myCurrentSegOffset[0] >> myCart.myBankShift) << ", hotspot = $3F";
|
||||
|
||||
return buf.str();
|
||||
}
|
||||
|
|
|
@ -22,177 +22,32 @@
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Cartridge3F::Cartridge3F(const ByteBuffer& image, size_t size,
|
||||
const string& md5, const Settings& settings)
|
||||
: Cartridge(settings, md5),
|
||||
mySize(size)
|
||||
: CartridgeEnhanced(image, size, md5, settings)
|
||||
{
|
||||
// Allocate array for the ROM image
|
||||
myImage = make_unique<uInt8[]>(mySize);
|
||||
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), mySize, myImage.get());
|
||||
createRomAccessArrays(mySize);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Cartridge3F::reset()
|
||||
{
|
||||
initializeStartBank(bankCount() - 1);
|
||||
|
||||
bank(startBank());
|
||||
myBankShift = BANK_SHIFT;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Cartridge3F::install(System& system)
|
||||
{
|
||||
mySystem = &system;
|
||||
CartridgeEnhanced::install(system);
|
||||
|
||||
System::PageAccess access(this, System::PageAccessType::READWRITE);
|
||||
|
||||
// The hotspot ($3F) is in TIA address space, so we claim it here
|
||||
for(uInt16 addr = 0x00; addr < 0x40; addr += System::PAGE_SIZE)
|
||||
mySystem->setPageAccess(addr, access);
|
||||
|
||||
// Setup the second segment to always point to the last ROM slice
|
||||
access.type = System::PageAccessType::READ;
|
||||
for(uInt16 addr = 0x1800; addr < 0x2000; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[(mySize - 2048) + (addr & 0x07FF)];
|
||||
access.romAccessBase = &myRomAccessBase[(mySize - 2048) + (addr & 0x07FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[(mySize - 2048) + (addr & 0x07FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[(mySize - 2048) + (addr & 0x07FF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
bank(startBank());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 Cartridge3F::peek(uInt16 address)
|
||||
bool Cartridge3F::checkSwitchBank(uInt16 address, uInt8 value)
|
||||
{
|
||||
address &= 0x0FFF;
|
||||
|
||||
if(address < 0x0800)
|
||||
return myImage[(address & 0x07FF) + (myCurrentBank << 11)];
|
||||
else
|
||||
return myImage[(address & 0x07FF) + mySize - 2048];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool Cartridge3F::poke(uInt16 address, uInt8 value)
|
||||
{
|
||||
address &= 0x0FFF;
|
||||
|
||||
// Switch banks if necessary
|
||||
if(address <= 0x003F)
|
||||
bank(value);
|
||||
|
||||
// Handle TIA space that we claimed above
|
||||
mySystem->tia().poke(address, value);
|
||||
|
||||
{
|
||||
// Make sure the bank they're asking for is reasonable
|
||||
bank(value % bankCount(), 0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool Cartridge3F::bank(uInt16 bank)
|
||||
{
|
||||
if(bankLocked())
|
||||
return false;
|
||||
|
||||
// Make sure the bank they're asking for is reasonable
|
||||
if((uInt32(bank) << 11) < mySize)
|
||||
{
|
||||
myCurrentBank = bank;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Oops, the bank they're asking for isn't valid so let's wrap it
|
||||
// around to a valid bank number
|
||||
myCurrentBank = bank % (mySize >> 11);
|
||||
}
|
||||
|
||||
uInt32 offset = myCurrentBank << 11;
|
||||
|
||||
// Setup the page access methods for the current bank
|
||||
System::PageAccess access(this, System::PageAccessType::READ);
|
||||
|
||||
// Map ROM image into the system
|
||||
for(uInt16 addr = 0x1000; addr < 0x1800; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[offset + (addr & 0x07FF)];
|
||||
access.romAccessBase = &myRomAccessBase[offset + (addr & 0x07FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[offset + (addr & 0x07FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[offset + (addr & 0x07FF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 Cartridge3F::getBank(uInt16 address) const
|
||||
{
|
||||
if (address & 0x800)
|
||||
return uInt16((mySize >> 11) - 1); // 2K slices, fixed bank
|
||||
else
|
||||
return myCurrentBank;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 Cartridge3F::bankCount() const
|
||||
{
|
||||
return uInt16(mySize >> 11); // 2K slices
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool Cartridge3F::patch(uInt16 address, uInt8 value)
|
||||
{
|
||||
address &= 0x0FFF;
|
||||
|
||||
if(address < 0x0800)
|
||||
myImage[(address & 0x07FF) + (myCurrentBank << 11)] = value;
|
||||
else
|
||||
myImage[(address & 0x07FF) + mySize - 2048] = value;
|
||||
|
||||
return myBankChanged = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const uInt8* Cartridge3F::getImage(size_t& size) const
|
||||
{
|
||||
size = mySize;
|
||||
return myImage.get();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool Cartridge3F::save(Serializer& out) const
|
||||
{
|
||||
try
|
||||
{
|
||||
out.putShort(myCurrentBank);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "ERROR: Cartridge3F::save" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool Cartridge3F::load(Serializer& in)
|
||||
{
|
||||
try
|
||||
{
|
||||
myCurrentBank = in.getShort();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "ERROR: Cartridge3F::load" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now, go to the current bank
|
||||
bank(myCurrentBank);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
class System;
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Cart.hxx"
|
||||
#include "CartEnhanced.hxx"
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
#include "Cart3FWidget.hxx"
|
||||
#endif
|
||||
|
@ -38,7 +38,7 @@ class System;
|
|||
|
||||
@author Bradford W. Mott
|
||||
*/
|
||||
class Cartridge3F : public Cartridge
|
||||
class Cartridge3F : public CartridgeEnhanced
|
||||
{
|
||||
friend class Cartridge3FWidget;
|
||||
|
||||
|
@ -56,11 +56,6 @@ class Cartridge3F : public Cartridge
|
|||
virtual ~Cartridge3F() = 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.
|
||||
|
@ -69,57 +64,6 @@ class Cartridge3F : public Cartridge
|
|||
*/
|
||||
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).
|
||||
|
@ -140,32 +84,12 @@ class Cartridge3F : public Cartridge
|
|||
}
|
||||
#endif
|
||||
|
||||
public:
|
||||
/**
|
||||
Get the byte at the specified address
|
||||
|
||||
@return The byte at the specified address
|
||||
*/
|
||||
uInt8 peek(uInt16 address) override;
|
||||
|
||||
/**
|
||||
Change the byte at the specified address to the given value
|
||||
|
||||
@param address The address where the value should be stored
|
||||
@param value The value to be stored at the address
|
||||
@return True if the poke changed the device address space, else false
|
||||
*/
|
||||
bool poke(uInt16 address, uInt8 value) override;
|
||||
private:
|
||||
bool checkSwitchBank(uInt16 address, uInt8 value) override;
|
||||
|
||||
private:
|
||||
// Pointer to a dynamically allocated ROM image of the cartridge
|
||||
ByteBuffer myImage;
|
||||
|
||||
// Size of the ROM image
|
||||
size_t mySize{0};
|
||||
|
||||
// Indicates which bank is currently active for the first segment
|
||||
uInt16 myCurrentBank{0};
|
||||
// log(ROM bank segment size) / log(2)
|
||||
static constexpr uInt16 BANK_SHIFT = 11; // = 2K = 0x0800
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
|
|
|
@ -42,46 +42,9 @@ void CartridgeE0::reset()
|
|||
bank(5, 1);
|
||||
bank(6, 2);
|
||||
}
|
||||
myCurrentSegOffset[3] = (bankCount() - 1) << myBankShift; // fixed
|
||||
|
||||
myBankChanged = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeE0::install(System& 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);
|
||||
|
||||
// Set the page acessing methods for the first part of the last segment
|
||||
for(uInt16 addr = 0x1C00; addr < static_cast<uInt16>(0x1FE0U & ~System::PAGE_MASK);
|
||||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[0x1C00 + (addr & 0x03FF)];
|
||||
access.romAccessBase = &myRomAccessBase[0x1C00 + (addr & 0x03FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[0x1C00 + (addr & 0x03FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[0x1C00 + (addr & 0x03FF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
// Set the page accessing methods for the hot spots in the last segment
|
||||
access.directPeekBase = nullptr;
|
||||
access.romAccessBase = &myRomAccessBase[0x1FC0];
|
||||
access.romPeekCounter = &myRomAccessCounter[0x1FC0];
|
||||
access.romPokeCounter = &myRomAccessCounter[0x1FC0 + myAccessSize];
|
||||
access.type = System::PageAccessType::READ;
|
||||
for(uInt16 addr = (0x1FE0 & ~System::PAGE_MASK); addr < 0x2000;
|
||||
addr += System::PAGE_SIZE)
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeE0::checkSwitchBank(uInt16 address, uInt8)
|
||||
{
|
||||
|
|
|
@ -64,14 +64,6 @@ class CartridgeE0 : public CartridgeEnhanced
|
|||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
Get a descriptor for the device name (used in error checking).
|
||||
|
||||
|
|
|
@ -79,8 +79,11 @@ void CartridgeEnhanced::install(System& system)
|
|||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
// Install pages for the startup bank
|
||||
bank(startBank());
|
||||
// Install pages for the startup bank (TODO: currently only in first bank segment)
|
||||
bank(startBank(), 0);
|
||||
if(myBankSegs > 1)
|
||||
// Setup the last bank segment to always point to the last ROM segment
|
||||
bank(bankCount() - 1, myBankSegs - 1);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -99,13 +102,13 @@ uInt8 CartridgeEnhanced::peek(uInt16 address)
|
|||
{
|
||||
uInt16 peekAddress = address;
|
||||
|
||||
checkSwitchBank(address & 0x0FFF);
|
||||
if (romHotspot())
|
||||
checkSwitchBank(address & 0x0FFF);
|
||||
address &= myBankMask;
|
||||
|
||||
if(address < myRamSize) // Write port is at 0xF000 - 0xF07F (128 bytes)
|
||||
return peekRAM(myRAM[address], peekAddress);
|
||||
else
|
||||
//return myImage[myBankOffset + address];
|
||||
return myImage[myCurrentSegOffset[(peekAddress & 0xFFF) >> myBankShift] + address];
|
||||
}
|
||||
|
||||
|
@ -113,7 +116,7 @@ uInt8 CartridgeEnhanced::peek(uInt16 address)
|
|||
bool CartridgeEnhanced::poke(uInt16 address, uInt8 value)
|
||||
{
|
||||
// Switch banks if necessary
|
||||
if (checkSwitchBank(address & 0x0FFF))
|
||||
if (checkSwitchBank(address & 0x0FFF, value))
|
||||
return false;
|
||||
|
||||
if(myRamSize)
|
||||
|
@ -149,7 +152,7 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment)
|
|||
uInt16 toAddr = (segmentOffset + 0x1000 + myBankSize) & ~System::PAGE_MASK;
|
||||
|
||||
if(romHotspot)
|
||||
hotSpotAddr = segmentOffset + (romHotspot & ~System::PAGE_MASK);
|
||||
hotSpotAddr = (romHotspot & ~System::PAGE_MASK);
|
||||
else
|
||||
hotSpotAddr = 0xFFFF; // none
|
||||
|
||||
|
|
|
@ -165,6 +165,9 @@ class CartridgeEnhanced : public Cartridge
|
|||
// Pointer to a dynamically allocated RAM area of the cartridge
|
||||
ByteBuffer myRAM{nullptr};
|
||||
|
||||
// The size of the ROM image
|
||||
size_t mySize{0};
|
||||
|
||||
private:
|
||||
// Calculated as: log(ROM bank segment size) / log(2)
|
||||
static constexpr uInt16 BANK_SHIFT = 12; // default = 4K
|
||||
|
@ -172,9 +175,6 @@ class CartridgeEnhanced : public Cartridge
|
|||
// The size of extra RAM in ROM address space
|
||||
static constexpr uInt16 RAM_SIZE = 0; // default = none
|
||||
|
||||
// The size of the ROM image
|
||||
size_t mySize{0};
|
||||
|
||||
protected:
|
||||
/**
|
||||
Check hotspots and switch bank if triggered.
|
||||
|
|
Loading…
Reference in New Issue