mirror of https://github.com/stella-emu/stella.git
parent
9d12378cff
commit
646f2a1daa
|
@ -64,7 +64,7 @@ bool Cartridge3E::checkSwitchBank(uInt16 address, uInt8 value)
|
|||
uInt8 Cartridge3E::peek(uInt16 address)
|
||||
{
|
||||
uInt16 peekAddress = address;
|
||||
address &= 0x0FFF;
|
||||
address &= ROM_MASK;
|
||||
|
||||
if(address < 0x0040) // TIA access
|
||||
return mySystem->tia().peek(address);
|
||||
|
|
|
@ -103,7 +103,7 @@ bool Cartridge3EPlus::checkSwitchBank(uInt16 address, uInt8 value)
|
|||
uInt8 Cartridge3EPlus::peek(uInt16 address)
|
||||
{
|
||||
uInt16 peekAddress = address;
|
||||
address &= 0x0FFF;
|
||||
address &= ROM_MASK;
|
||||
|
||||
if(address < 0x0040) // TIA peek
|
||||
return mySystem->tia().peek(address);
|
||||
|
|
|
@ -30,7 +30,7 @@ bool CartridgeBF::checkSwitchBank(uInt16 address, uInt8)
|
|||
{
|
||||
// Due to the way addressing is set up, we will only get here if the
|
||||
// address is in the hotspot range ($1F80 - $1FFF)
|
||||
address &= 0x0FFF;
|
||||
address &= ROM_MASK;
|
||||
|
||||
// Switch banks if necessary
|
||||
if((address >= 0x0F80) && (address <= 0x0FBF))
|
||||
|
|
|
@ -28,7 +28,7 @@ CartridgeDF::CartridgeDF(const ByteBuffer& image, size_t size,
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeDF::checkSwitchBank(uInt16 address, uInt8)
|
||||
{
|
||||
address &= 0x0FFF;
|
||||
address &= ROM_MASK;
|
||||
|
||||
// Switch banks if necessary
|
||||
if((address >= 0x0FC0) && (address <= 0x0FDF))
|
||||
|
|
|
@ -28,7 +28,7 @@ CartridgeEF::CartridgeEF(const ByteBuffer& image, size_t size,
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeEF::checkSwitchBank(uInt16 address, uInt8)
|
||||
{
|
||||
address &= 0x0FFF;
|
||||
address &= ROM_MASK;
|
||||
|
||||
// Switch banks if necessary
|
||||
if((address >= 0x0FE0) && (address <= 0x0FEF))
|
||||
|
|
|
@ -35,18 +35,18 @@ CartridgeEnhanced::CartridgeEnhanced(const ByteBuffer& image, size_t size,
|
|||
void CartridgeEnhanced::install(System& system)
|
||||
{
|
||||
// limit banked RAM size to the size of one RAM bank
|
||||
uInt16 ramSize = myRamBankCount ? 1 << (myBankShift - 1) : myRamSize;
|
||||
uInt16 ramSize = myRamBankCount > 0 ? 1 << (myBankShift - 1) : myRamSize;
|
||||
|
||||
// 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
|
||||
myRomOffset = myRamBankCount ? 0 : myRamSize * 2;
|
||||
myRamMask = ramSize - 1; // e.g. = 0xFFFF (doesn't matter for RAM size 0)
|
||||
myWriteOffset = myRamWpHigh ? ramSize : 0;
|
||||
myReadOffset = myRamWpHigh ? 0 : ramSize;
|
||||
myBankSize = 1 << myBankShift; // e.g. = 2 ^ 12 = 4K = 0x1000
|
||||
myBankMask = myBankSize - 1; // e.g. = 0x0FFF
|
||||
myBankSegs = 1 << (MAX_BANK_SHIFT - myBankShift); // e.g. = 1
|
||||
myRomOffset = myRamBankCount > 0 ? 0 : myRamSize * 2;
|
||||
myRamMask = ramSize - 1; // e.g. = 0xFFFF (doesn't matter for RAM size 0)
|
||||
myWriteOffset = myRamWpHigh ? ramSize : 0; // e.g. = 0x0000
|
||||
myReadOffset = myRamWpHigh ? 0 : ramSize; // e.g. = 0x0080
|
||||
|
||||
createRomAccessArrays(mySize + (myRomOffset ? 0 : myRamSize));
|
||||
createRomAccessArrays(mySize + (myRomOffset > 0 ? 0 : myRamSize));
|
||||
|
||||
// Allocate array for the current bank segments slices
|
||||
myCurrentSegOffset = make_unique<uInt32[]>(myBankSegs);
|
||||
|
@ -56,7 +56,7 @@ void CartridgeEnhanced::install(System& system)
|
|||
|
||||
mySystem = &system;
|
||||
|
||||
if(myRomOffset)
|
||||
if(myRomOffset > 0)
|
||||
{
|
||||
// Setup page access for extended RAM; banked RAM will be setup in bank()
|
||||
System::PageAccess access(this, System::PageAccessType::READ);
|
||||
|
@ -65,7 +65,7 @@ void CartridgeEnhanced::install(System& system)
|
|||
// 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 + myWriteOffset; addr < 0x1000 + myWriteOffset + myRamSize; addr += System::PAGE_SIZE)
|
||||
for(uInt16 addr = ROM_OFFSET + myWriteOffset; addr < ROM_OFFSET + myWriteOffset + myRamSize; addr += System::PAGE_SIZE)
|
||||
{
|
||||
uInt16 offset = addr & myRamMask;
|
||||
access.romAccessBase = &myRomAccessBase[myWriteOffset + offset];
|
||||
|
@ -76,7 +76,7 @@ void CartridgeEnhanced::install(System& system)
|
|||
|
||||
// Set the page accessing method for the RAM reading pages
|
||||
access.type = System::PageAccessType::READ;
|
||||
for(uInt16 addr = 0x1000 + myReadOffset; addr < 0x1000 + myReadOffset + myRamSize; addr += System::PAGE_SIZE)
|
||||
for(uInt16 addr = ROM_OFFSET + myReadOffset; addr < ROM_OFFSET + myReadOffset + myRamSize; addr += System::PAGE_SIZE)
|
||||
{
|
||||
uInt16 offset = addr & myRamMask;
|
||||
access.directPeekBase = &myRAM[offset];
|
||||
|
@ -110,8 +110,8 @@ uInt8 CartridgeEnhanced::peek(uInt16 address)
|
|||
{
|
||||
uInt16 peekAddress = address;
|
||||
|
||||
if (hotspot())
|
||||
checkSwitchBank(address & 0x0FFF);
|
||||
if (hotspot() != 0)
|
||||
checkSwitchBank(address & ROM_MASK);
|
||||
|
||||
if(isRamBank(address))
|
||||
{
|
||||
|
@ -120,7 +120,7 @@ uInt8 CartridgeEnhanced::peek(uInt16 address)
|
|||
// This is a read access to a write port!
|
||||
// Reading from the write port triggers an unwanted write
|
||||
// The RAM banks follow the ROM banks and are half the size of a ROM bank
|
||||
return peekRAM(myRAM[((myCurrentSegOffset[(peekAddress & 0xFFF) >> myBankShift] - mySize) >> 1) + address],
|
||||
return peekRAM(myRAM[((myCurrentSegOffset[(peekAddress & ROM_MASK) >> myBankShift] - mySize) >> 1) + address],
|
||||
peekAddress);
|
||||
}
|
||||
else
|
||||
|
@ -133,7 +133,7 @@ uInt8 CartridgeEnhanced::peek(uInt16 address)
|
|||
// Reading from the write port triggers an unwanted write
|
||||
return peekRAM(myRAM[address], peekAddress);
|
||||
else
|
||||
return myImage[myCurrentSegOffset[(peekAddress & 0xFFF) >> myBankShift] + address];
|
||||
return myImage[myCurrentSegOffset[(peekAddress & ROM_MASK) >> myBankShift] + address];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,10 +144,10 @@ bool CartridgeEnhanced::poke(uInt16 address, uInt8 value)
|
|||
// Note: (TODO?)
|
||||
// The checkSwitchBank() call makes no difference between ROM and e.g TIA space
|
||||
// Writing to e.g. 0xf0xx might triger a bankswitch, is (and was!) this a bug???
|
||||
if (checkSwitchBank(address & 0x0FFF, value))
|
||||
if (checkSwitchBank(address & ROM_MASK, value))
|
||||
return false;
|
||||
|
||||
if(myRamSize)
|
||||
if(myRamSize > 0)
|
||||
{
|
||||
uInt16 pokeAddress = address;
|
||||
|
||||
|
@ -157,7 +157,7 @@ bool CartridgeEnhanced::poke(uInt16 address, uInt8 value)
|
|||
{
|
||||
address &= myRamMask;
|
||||
// The RAM banks follow the ROM banks and are half the size of a ROM bank
|
||||
pokeRAM(myRAM[((myCurrentSegOffset[(pokeAddress & 0xFFF) >> myBankShift] - mySize) >> 1) + address],
|
||||
pokeRAM(myRAM[((myCurrentSegOffset[(pokeAddress & ROM_MASK) >> myBankShift] - mySize) >> 1) + address],
|
||||
pokeAddress, value);
|
||||
return true;
|
||||
}
|
||||
|
@ -198,7 +198,7 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment)
|
|||
|
||||
uInt16 segmentOffset = segment << myBankShift;
|
||||
|
||||
if(!myRamBankCount || bank < romBankCount())
|
||||
if(myRamBankCount == 0 || bank < romBankCount())
|
||||
{
|
||||
// Setup ROM bank
|
||||
uInt16 romBank = bank % romBankCount();
|
||||
|
@ -206,11 +206,11 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment)
|
|||
uInt32 bankOffset = myCurrentSegOffset[segment] = romBank << myBankShift;
|
||||
uInt16 hotspot = this->hotspot();
|
||||
uInt16 hotSpotAddr;
|
||||
uInt16 fromAddr = (0x1000 + segmentOffset + myRomOffset) & ~System::PAGE_MASK;
|
||||
uInt16 fromAddr = (ROM_OFFSET + segmentOffset + myRomOffset) & ~System::PAGE_MASK;
|
||||
// for ROMs < 4_KB, the whole address space will be mapped.
|
||||
uInt16 toAddr = (0x1000 + segmentOffset + (mySize < 4_KB ? 0x1000 : myBankSize)) & ~System::PAGE_MASK;
|
||||
uInt16 toAddr = (ROM_OFFSET + segmentOffset + (mySize < 4_KB ? 4_KB : myBankSize)) & ~System::PAGE_MASK;
|
||||
|
||||
if(hotspot)
|
||||
if(hotspot != 0)
|
||||
hotSpotAddr = (hotspot & ~System::PAGE_MASK);
|
||||
else
|
||||
hotSpotAddr = 0xFFFF; // none
|
||||
|
@ -242,8 +242,8 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment)
|
|||
myCurrentSegOffset[segment] = bank << myBankShift;
|
||||
|
||||
// Set the page accessing method for the RAM writing pages
|
||||
uInt16 fromAddr = (0x1000 + segmentOffset + myWriteOffset) & ~System::PAGE_MASK;
|
||||
uInt16 toAddr = (0x1000 + segmentOffset + myWriteOffset + (myBankSize >> 1)) & ~System::PAGE_MASK;
|
||||
uInt16 fromAddr = (ROM_OFFSET + segmentOffset + myWriteOffset) & ~System::PAGE_MASK;
|
||||
uInt16 toAddr = (ROM_OFFSET + segmentOffset + myWriteOffset + (myBankSize >> 1)) & ~System::PAGE_MASK;
|
||||
System::PageAccess access(this, System::PageAccessType::WRITE);
|
||||
|
||||
for(uInt16 addr = fromAddr; addr < toAddr; addr += System::PAGE_SIZE)
|
||||
|
@ -257,8 +257,8 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment)
|
|||
}
|
||||
|
||||
// Set the page accessing method for the RAM reading pages
|
||||
fromAddr = (0x1000 + segmentOffset + myReadOffset) & ~System::PAGE_MASK;
|
||||
toAddr = (0x1000 + segmentOffset + myReadOffset + (myBankSize >> 1)) & ~System::PAGE_MASK;
|
||||
fromAddr = (ROM_OFFSET + segmentOffset + myReadOffset) & ~System::PAGE_MASK;
|
||||
toAddr = (ROM_OFFSET + segmentOffset + myReadOffset + (myBankSize >> 1)) & ~System::PAGE_MASK;
|
||||
access.type = System::PageAccessType::READ;
|
||||
|
||||
for(uInt16 addr = fromAddr; addr < toAddr; addr += System::PAGE_SIZE)
|
||||
|
@ -278,7 +278,7 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 CartridgeEnhanced::getBank(uInt16 address) const
|
||||
{
|
||||
return myCurrentSegOffset[(address & 0xFFF) >> myBankShift] >> myBankShift;
|
||||
return myCurrentSegOffset[(address & ROM_MASK) >> myBankShift] >> myBankShift;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -302,7 +302,7 @@ uInt16 CartridgeEnhanced::ramBankCount() const
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeEnhanced::isRamBank(uInt16 address) const
|
||||
{
|
||||
return myRamBankCount ? getBank(address) >= romBankCount() : false;
|
||||
return myRamBankCount > 0 ? getBank(address) >= romBankCount() : false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -310,7 +310,7 @@ bool CartridgeEnhanced::patch(uInt16 address, uInt8 value)
|
|||
{
|
||||
if(isRamBank(address))
|
||||
{
|
||||
myRAM[((myCurrentSegOffset[(address & 0xFFF) >> myBankShift] - mySize) >> 1) + (address & myRamMask)] = value;
|
||||
myRAM[((myCurrentSegOffset[(address & ROM_MASK) >> myBankShift] - mySize) >> 1) + (address & myRamMask)] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -322,7 +322,7 @@ bool CartridgeEnhanced::patch(uInt16 address, uInt8 value)
|
|||
myRAM[address & myRamMask] = value;
|
||||
}
|
||||
else
|
||||
myImage[myCurrentSegOffset[(address & 0xFFF) >> myBankShift] + (address & myBankMask)] = value;
|
||||
myImage[myCurrentSegOffset[(address & ROM_MASK) >> myBankShift] + (address & myBankMask)] = value;
|
||||
}
|
||||
|
||||
return myBankChanged = true;
|
||||
|
@ -341,7 +341,7 @@ bool CartridgeEnhanced::save(Serializer& out) const
|
|||
try
|
||||
{
|
||||
out.putIntArray(myCurrentSegOffset.get(), myBankSegs);
|
||||
if(myRamSize)
|
||||
if(myRamSize > 0)
|
||||
out.putByteArray(myRAM.get(), myRamSize);
|
||||
}
|
||||
catch(...)
|
||||
|
@ -359,7 +359,7 @@ bool CartridgeEnhanced::load(Serializer& in)
|
|||
try
|
||||
{
|
||||
in.getIntArray(myCurrentSegOffset.get(), myBankSegs);
|
||||
if(myRamSize)
|
||||
if(myRamSize > 0)
|
||||
in.getByteArray(myRAM.get(), myRamSize);
|
||||
}
|
||||
catch(...)
|
||||
|
|
|
@ -218,6 +218,13 @@ class CartridgeEnhanced : public Cartridge
|
|||
// The size of the ROM image
|
||||
size_t mySize{0};
|
||||
|
||||
protected:
|
||||
// The offset into address space for accessing ROM
|
||||
static constexpr uInt16 ROM_OFFSET = 0x1000;
|
||||
|
||||
// The mask for ROM address space
|
||||
static constexpr uInt16 ROM_MASK = 0x0FFF;
|
||||
|
||||
private:
|
||||
// Calculated as: log(ROM bank segment size) / log(2)
|
||||
static constexpr uInt16 BANK_SHIFT = 12; // default = 4K
|
||||
|
@ -231,6 +238,9 @@ class CartridgeEnhanced : public Cartridge
|
|||
// Write port for extra RAM is at low address by default
|
||||
static constexpr bool RAM_HIGH_WP = false;
|
||||
|
||||
// The maximum shift (for a 4K bank size)
|
||||
static constexpr uInt16 MAX_BANK_SHIFT = 12; ; // -> 4K
|
||||
|
||||
protected:
|
||||
/**
|
||||
Check hotspots and switch bank if triggered.
|
||||
|
|
|
@ -35,7 +35,7 @@ CartridgeFA2::CartridgeFA2(const ByteBuffer& image, size_t size,
|
|||
myImage = make_unique<uInt8[]>(mySize);
|
||||
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), mySize, myImage.get());
|
||||
std::copy_n(img_ptr, mySize, myImage.get());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -53,7 +53,7 @@ bool CartridgeFA2::checkSwitchBank(uInt16 address, uInt8)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 CartridgeFA2::peek(uInt16 address)
|
||||
{
|
||||
if((address & 0x0FFF) == 0x0FF4)
|
||||
if((address & ROM_MASK) == 0x0FF4)
|
||||
{
|
||||
// Load/save RAM to/from Harmony cart flash
|
||||
if(mySize == 28_KB && !bankLocked())
|
||||
|
@ -66,7 +66,7 @@ uInt8 CartridgeFA2::peek(uInt16 address)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeFA2::poke(uInt16 address, uInt8 value)
|
||||
{
|
||||
if((address & 0x0FFF) == 0x0FF4)
|
||||
if((address & ROM_MASK) == 0x0FF4)
|
||||
{
|
||||
// Load/save RAM to/from Harmony cart flash
|
||||
if(mySize == 28_KB && !bankLocked())
|
||||
|
|
|
@ -63,7 +63,7 @@ bool CartridgeFE::checkSwitchBank(uInt16 address, uInt8 value)
|
|||
uInt8 CartridgeFE::peek(uInt16 address)
|
||||
{
|
||||
uInt8 value = (address < 0x200) ? mySystem->m6532().peek(address) :
|
||||
myImage[myCurrentSegOffset[(address & 0xFFF) >> myBankShift] + (address & myBankMask)];
|
||||
myImage[myCurrentSegOffset[(address & myBankMask) >> myBankShift] + (address & myBankMask)];
|
||||
|
||||
// Check if we hit hotspot
|
||||
checkSwitchBank(address, value);
|
||||
|
|
|
@ -54,13 +54,12 @@ bool CartridgeSB::checkSwitchBank(uInt16 address, uInt8)
|
|||
// Switch banks if necessary
|
||||
if((address & 0x1800) == 0x0800)
|
||||
{
|
||||
bank(address & startBank());
|
||||
bank(address & (romBankCount() - 1));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 CartridgeSB::peek(uInt16 address)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue