mirror of https://github.com/stella-emu/stella.git
refactored CartWD
fixed CartEnhanced for multi-segment ROMs with extra RAM improved CartEnhanced by enabling directPoke for extra RAM
This commit is contained in:
parent
0851a445e5
commit
0bf12045d8
|
@ -29,44 +29,17 @@ Cartridge3EPlus::Cartridge3EPlus(const ByteBuffer& image, size_t size,
|
||||||
myRamSize = RAM_SIZE;
|
myRamSize = RAM_SIZE;
|
||||||
myRamBankCount = RAM_BANKS;
|
myRamBankCount = RAM_BANKS;
|
||||||
myRamWpHigh = RAM_HIGH_WP;
|
myRamWpHigh = RAM_HIGH_WP;
|
||||||
|
|
||||||
//// 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 + myRAM.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
//void Cartridge3EPlus::reset()
|
|
||||||
//{
|
|
||||||
// initializeRAM(myRAM.data(), myRAM.size());
|
|
||||||
//
|
|
||||||
// // Remember startup bank (0 per spec, rather than last per 3E scheme).
|
|
||||||
// // Set this to go to 3rd 1K Bank.
|
|
||||||
// initializeStartBank(0);
|
|
||||||
//
|
|
||||||
// // Initialise bank values for all ROM/RAM access
|
|
||||||
// // This is used to reverse-lookup from address to bank location
|
|
||||||
// for(auto& b: bankInUse)
|
|
||||||
// b = BANK_UNDEFINED; // bank is undefined and inaccessible!
|
|
||||||
//
|
|
||||||
// initializeBankState();
|
|
||||||
//
|
|
||||||
// // We'll map the startup banks 0 and 3 from the image into the third 1K bank upon reset
|
|
||||||
// bankROM((0 << BANK_BITS) | 0);
|
|
||||||
// bankROM((3 << BANK_BITS) | 0);
|
|
||||||
//}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Cartridge3EPlus::reset()
|
void Cartridge3EPlus::reset()
|
||||||
{
|
{
|
||||||
CartridgeEnhanced::reset();
|
CartridgeEnhanced::reset();
|
||||||
|
|
||||||
|
// 1st segment in mapped to start bank in CartridgeEnhanced
|
||||||
bank(mySystem->randGenerator().next() % romBankCount(), 1);
|
bank(mySystem->randGenerator().next() % romBankCount(), 1);
|
||||||
bank(mySystem->randGenerator().next() % romBankCount(), 2);
|
bank(mySystem->randGenerator().next() % romBankCount(), 2);
|
||||||
bank(startBank(), 3); // Stella reads the PC vector always from here (TODO?)
|
bank(startBank(), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -68,6 +68,8 @@ void CartridgeEnhanced::install(System& system)
|
||||||
for(uInt16 addr = ROM_OFFSET + myWriteOffset; addr < ROM_OFFSET + 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;
|
uInt16 offset = addr & myRamMask;
|
||||||
|
|
||||||
|
access.directPokeBase = &myRAM[offset];
|
||||||
access.romAccessBase = &myRomAccessBase[myWriteOffset + offset];
|
access.romAccessBase = &myRomAccessBase[myWriteOffset + offset];
|
||||||
access.romPeekCounter = &myRomAccessCounter[myWriteOffset + offset];
|
access.romPeekCounter = &myRomAccessCounter[myWriteOffset + offset];
|
||||||
access.romPokeCounter = &myRomAccessCounter[myWriteOffset + offset + myAccessSize];
|
access.romPokeCounter = &myRomAccessCounter[myWriteOffset + offset + myAccessSize];
|
||||||
|
@ -76,6 +78,7 @@ void CartridgeEnhanced::install(System& system)
|
||||||
|
|
||||||
// Set the page accessing method for the RAM reading pages
|
// Set the page accessing method for the RAM reading pages
|
||||||
access.type = System::PageAccessType::READ;
|
access.type = System::PageAccessType::READ;
|
||||||
|
access.directPokeBase = nullptr;
|
||||||
for(uInt16 addr = ROM_OFFSET + myReadOffset; addr < ROM_OFFSET + 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;
|
uInt16 offset = addr & myRamMask;
|
||||||
|
@ -125,7 +128,7 @@ uInt8 CartridgeEnhanced::peek(uInt16 address)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
address &= myBankMask;
|
address &= ROM_MASK;
|
||||||
|
|
||||||
// Write port is e.g. at 0xF000 - 0xF07F (128 bytes)
|
// Write port is e.g. at 0xF000 - 0xF07F (128 bytes)
|
||||||
if(address < myReadOffset + myRamSize && address >= myReadOffset)
|
if(address < myReadOffset + myRamSize && address >= myReadOffset)
|
||||||
|
@ -133,7 +136,8 @@ uInt8 CartridgeEnhanced::peek(uInt16 address)
|
||||||
// Reading from the write port triggers an unwanted write
|
// Reading from the write port triggers an unwanted write
|
||||||
return peekRAM(myRAM[address], peekAddress);
|
return peekRAM(myRAM[address], peekAddress);
|
||||||
else
|
else
|
||||||
return myImage[myCurrentSegOffset[(peekAddress & ROM_MASK) >> myBankShift] + address];
|
return myImage[myCurrentSegOffset[(peekAddress & ROM_MASK) >> myBankShift]
|
||||||
|
+ (peekAddress & myBankMask)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,7 +210,8 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment)
|
||||||
uInt32 bankOffset = myCurrentSegOffset[segment] = romBank << myBankShift;
|
uInt32 bankOffset = myCurrentSegOffset[segment] = romBank << myBankShift;
|
||||||
uInt16 hotspot = this->hotspot();
|
uInt16 hotspot = this->hotspot();
|
||||||
uInt16 hotSpotAddr;
|
uInt16 hotSpotAddr;
|
||||||
uInt16 fromAddr = (ROM_OFFSET + segmentOffset + myRomOffset) & ~System::PAGE_MASK;
|
// Skip extra RAM; if existing it is only mapped into first segment
|
||||||
|
uInt16 fromAddr = (ROM_OFFSET + segmentOffset + (segment == 0 ? myRomOffset : 0)) & ~System::PAGE_MASK;
|
||||||
// for ROMs < 4_KB, the whole address space will be mapped.
|
// for ROMs < 4_KB, the whole address space will be mapped.
|
||||||
uInt16 toAddr = (ROM_OFFSET + segmentOffset + (mySize < 4_KB ? 4_KB : myBankSize)) & ~System::PAGE_MASK;
|
uInt16 toAddr = (ROM_OFFSET + segmentOffset + (mySize < 4_KB ? 4_KB : myBankSize)) & ~System::PAGE_MASK;
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ class CartridgeEnhanced : public Cartridge
|
||||||
|
|
||||||
@return true, if bank has changed
|
@return true, if bank has changed
|
||||||
*/
|
*/
|
||||||
bool bank(uInt16 bank, uInt16 segment);
|
virtual bool bank(uInt16 bank, uInt16 segment);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Install pages for the specified bank in the system.
|
Install pages for the specified bank in the system.
|
||||||
|
|
|
@ -23,70 +23,46 @@
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
CartridgeWD::CartridgeWD(const ByteBuffer& image, size_t size,
|
CartridgeWD::CartridgeWD(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)
|
||||||
mySize(std::min<size_t>(8_KB + 3, size))
|
|
||||||
{
|
{
|
||||||
// Copy the ROM image into my buffer
|
// Copy the ROM image into my buffer
|
||||||
if (mySize == 8_KB + 3)
|
if (mySize == 8_KB + 3)
|
||||||
{
|
{
|
||||||
// swap slices 2 & 3
|
// swap slices 2 & 3 of bad dump and correct size
|
||||||
std::copy_n(image.get(), 1_KB * 2, myImage.begin());
|
std::copy_n(image.get() + 1_KB * 3, 1_KB * 1, myImage.get() + 1_KB * 2);
|
||||||
std::copy_n(image.get() + 1_KB * 3, 1_KB * 1, myImage.begin() + 1_KB * 2);
|
std::copy_n(image.get() + 1_KB * 2, 1_KB * 1, myImage.get() + 1_KB * 3);
|
||||||
std::copy_n(image.get() + 1_KB * 2, 1_KB * 1, myImage.begin() + 1_KB * 3);
|
mySize = 8_KB;
|
||||||
std::copy_n(image.get() + 1_KB * 4, 1_KB * 4, myImage.begin() + 1_KB * 4);
|
|
||||||
}
|
}
|
||||||
else
|
myDirectPeek = false;
|
||||||
std::copy_n(image.get(), mySize, myImage.begin());
|
|
||||||
createRomAccessArrays(8_KB);
|
myBankShift = BANK_SHIFT;
|
||||||
|
myRamSize = RAM_SIZE;
|
||||||
|
myRamWpHigh = RAM_HIGH_WP;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void CartridgeWD::reset()
|
void CartridgeWD::reset()
|
||||||
{
|
{
|
||||||
initializeRAM(myRAM.data(), myRAM.size());
|
CartridgeEnhanced::reset();
|
||||||
initializeStartBank(0);
|
|
||||||
|
|
||||||
myCyclesAtBankswitchInit = 0;
|
myCyclesAtBankswitchInit = 0;
|
||||||
myPendingBank = 0xF0; // one more than the allowable bank #
|
myPendingBank = 0xF0; // one more than the allowable bank #
|
||||||
|
|
||||||
// Setup segments to some default slices
|
|
||||||
bank(startBank());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void CartridgeWD::install(System& system)
|
void CartridgeWD::install(System& system)
|
||||||
{
|
{
|
||||||
mySystem = &system;
|
CartridgeEnhanced::install(system);
|
||||||
|
|
||||||
// Set the page accessing method for the RAM reading pages
|
System::PageAccess access(this, System::PageAccessType::READ);
|
||||||
System::PageAccess read(this, System::PageAccessType::READ);
|
|
||||||
for(uInt16 addr = 0x1000; addr < 0x1040; addr += System::PAGE_SIZE)
|
|
||||||
{
|
|
||||||
read.directPeekBase = &myRAM[addr & 0x003F];
|
|
||||||
read.romAccessBase = &myRomAccessBase[addr & 0x003F];
|
|
||||||
read.romPeekCounter = &myRomAccessCounter[addr & 0x003F];
|
|
||||||
read.romPokeCounter = &myRomAccessCounter[(addr & 0x003F) + 8_KB];
|
|
||||||
mySystem->setPageAccess(addr, read);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the page accessing method for the RAM writing pages
|
// The hotspots are in TIA address space, so we claim it here
|
||||||
// Map access to this class, since we need to inspect all accesses to
|
for(uInt16 addr = 0x00; addr < 0x40; addr += System::PAGE_SIZE)
|
||||||
// check if RWP happens
|
mySystem->setPageAccess(addr, access);
|
||||||
System::PageAccess write(this, System::PageAccessType::WRITE);
|
|
||||||
for(uInt16 addr = 0x1040; addr < 0x1080; addr += System::PAGE_SIZE)
|
|
||||||
{
|
|
||||||
write.romAccessBase = &myRomAccessBase[addr & 0x003F];
|
|
||||||
write.romPeekCounter = &myRomAccessCounter[addr & 0x003F];
|
|
||||||
write.romPokeCounter = &myRomAccessCounter[(addr & 0x003F) + 8_KB];
|
|
||||||
mySystem->setPageAccess(addr, write);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mirror all access in TIA; by doing so we're taking responsibility
|
// Mirror all access in TIA; by doing so we're taking responsibility
|
||||||
// for that address space in peek and poke below.
|
// for that address space in peek and poke below.
|
||||||
mySystem->tia().installDelegate(system, *this);
|
//mySystem->tia().installDelegate(system, *this);
|
||||||
|
|
||||||
// Setup segments to some default slices
|
|
||||||
bank(startBank());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -113,134 +89,31 @@ uInt8 CartridgeWD::peek(uInt16 address)
|
||||||
return mySystem->tia().peek(address);
|
return mySystem->tia().peek(address);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
return CartridgeEnhanced::peek(address);
|
||||||
uInt16 peekAddress = address;
|
|
||||||
address &= 0x0FFF;
|
|
||||||
|
|
||||||
if(address < 0x0040) // RAM read port
|
|
||||||
return myRAM[address];
|
|
||||||
else if(address < 0x0080) // RAM write port
|
|
||||||
// Reading from the write port @ $1040 - $107F triggers an unwanted write
|
|
||||||
return peekRAM(myRAM[address & 0x003F], peekAddress);
|
|
||||||
else if(address < 0x0400)
|
|
||||||
return myImage[myOffset[0] + (address & 0x03FF)];
|
|
||||||
else if(address < 0x0800)
|
|
||||||
return myImage[myOffset[1] + (address & 0x03FF)];
|
|
||||||
else if(address < 0x0C00)
|
|
||||||
return myImage[myOffset[2] + (address & 0x03FF)];
|
|
||||||
else
|
|
||||||
return mySegment3[address & 0x03FF];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool CartridgeWD::poke(uInt16 address, uInt8 value)
|
bool CartridgeWD::poke(uInt16 address, uInt8 value)
|
||||||
{
|
{
|
||||||
if(!(address & 0x1000)) // TIA addresses
|
if(address < 0x40)
|
||||||
return mySystem->tia().poke(address, value);
|
return mySystem->tia().poke(address, value);
|
||||||
else
|
|
||||||
{
|
|
||||||
if(address & 0x040)
|
|
||||||
{
|
|
||||||
pokeRAM(myRAM[address & 0x003F], 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);
|
return CartridgeEnhanced::poke(address, value);
|
||||||
myRamWriteAccess = address;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool CartridgeWD::bank(uInt16 bank)
|
bool CartridgeWD::bank(uInt16 bank, uInt16)
|
||||||
{
|
{
|
||||||
if(bankLocked() || bank > 15) return false;
|
if(bankLocked()) return false;
|
||||||
|
|
||||||
myCurrentBank = bank;
|
myCurrentBank = bank % romBankCount();
|
||||||
|
|
||||||
segmentZero(ourBankOrg[bank & 0x7].zero);
|
CartridgeEnhanced::bank(ourBankOrg[myCurrentBank].zero, 0);
|
||||||
segmentOne(ourBankOrg[bank & 0x7].one);
|
CartridgeEnhanced::bank(ourBankOrg[myCurrentBank].one, 1);
|
||||||
segmentTwo(ourBankOrg[bank & 0x7].two);
|
CartridgeEnhanced::bank(ourBankOrg[myCurrentBank].two, 2);
|
||||||
segmentThree(ourBankOrg[bank & 0x7].three);
|
CartridgeEnhanced::bank(ourBankOrg[myCurrentBank].three, 3);
|
||||||
|
|
||||||
return myBankChanged = true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void CartridgeWD::segmentZero(uInt8 slice)
|
|
||||||
{
|
|
||||||
uInt16 offset = slice << 10;
|
|
||||||
System::PageAccess access(this, System::PageAccessType::READ);
|
|
||||||
|
|
||||||
// Skip first 128 bytes; it is always RAM
|
|
||||||
for(uInt16 addr = 0x1080; addr < 0x1400; addr += System::PAGE_SIZE)
|
|
||||||
{
|
|
||||||
access.romAccessBase = &myRomAccessBase[offset + (addr & 0x03FF)];
|
|
||||||
access.romPeekCounter = &myRomAccessCounter[offset + (addr & 0x03FF)];
|
|
||||||
access.romPokeCounter = &myRomAccessCounter[offset + (addr & 0x03FF) + 8_KB];
|
|
||||||
mySystem->setPageAccess(addr, access);
|
|
||||||
}
|
|
||||||
myOffset[0] = offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void CartridgeWD::segmentOne(uInt8 slice)
|
|
||||||
{
|
|
||||||
uInt16 offset = slice << 10;
|
|
||||||
System::PageAccess access(this, System::PageAccessType::READ);
|
|
||||||
|
|
||||||
for(uInt16 addr = 0x1400; addr < 0x1800; addr += System::PAGE_SIZE)
|
|
||||||
{
|
|
||||||
access.romAccessBase = &myRomAccessBase[offset + (addr & 0x03FF)];
|
|
||||||
access.romPeekCounter = &myRomAccessCounter[offset + (addr & 0x03FF)];
|
|
||||||
access.romPokeCounter = &myRomAccessCounter[offset + (addr & 0x03FF) + 8_KB];
|
|
||||||
mySystem->setPageAccess(addr, access);
|
|
||||||
}
|
|
||||||
myOffset[1] = offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void CartridgeWD::segmentTwo(uInt8 slice)
|
|
||||||
{
|
|
||||||
uInt16 offset = slice << 10;
|
|
||||||
System::PageAccess access(this, System::PageAccessType::READ);
|
|
||||||
|
|
||||||
for(uInt16 addr = 0x1800; addr < 0x1C00; addr += System::PAGE_SIZE)
|
|
||||||
{
|
|
||||||
access.romAccessBase = &myRomAccessBase[offset + (addr & 0x03FF)];
|
|
||||||
access.romPeekCounter = &myRomAccessCounter[offset + (addr & 0x03FF)];
|
|
||||||
access.romPokeCounter = &myRomAccessCounter[offset + (addr & 0x03FF) + 8_KB];
|
|
||||||
mySystem->setPageAccess(addr, access);
|
|
||||||
}
|
|
||||||
myOffset[2] = offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void CartridgeWD::segmentThree(uInt8 slice)
|
|
||||||
{
|
|
||||||
uInt16 offset = slice << 10;
|
|
||||||
|
|
||||||
// Make a copy of the address space pointed to by the slice
|
|
||||||
// Then overwrite one byte with 0
|
|
||||||
std::copy_n(myImage.begin()+offset, mySegment3.size(), mySegment3.begin());
|
|
||||||
mySegment3[0x3FC] = 0;
|
|
||||||
|
|
||||||
System::PageAccess access(this, System::PageAccessType::READ);
|
|
||||||
|
|
||||||
for(uInt16 addr = 0x1C00; addr < 0x2000; addr += System::PAGE_SIZE)
|
|
||||||
{
|
|
||||||
access.romAccessBase = &myRomAccessBase[offset + (addr & 0x03FF)];
|
|
||||||
access.romPeekCounter = &myRomAccessCounter[offset + (addr & 0x03FF)];
|
|
||||||
access.romPokeCounter = &myRomAccessCounter[offset + (addr & 0x03FF) + 8_KB];
|
|
||||||
mySystem->setPageAccess(addr, access);
|
|
||||||
}
|
|
||||||
myOffset[3] = offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -249,41 +122,13 @@ uInt16 CartridgeWD::getBank(uInt16) const
|
||||||
return myCurrentBank;
|
return myCurrentBank;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
uInt16 CartridgeWD::romBankCount() const
|
|
||||||
{
|
|
||||||
return 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool CartridgeWD::patch(uInt16 address, uInt8 value)
|
|
||||||
{
|
|
||||||
address &= 0x0FFF;
|
|
||||||
|
|
||||||
uInt16 idx = address >> 10;
|
|
||||||
myImage[myOffset[idx] + (address & 0x03FF)] = value;
|
|
||||||
|
|
||||||
// The upper segment is mirrored, so we need to patch its buffer too
|
|
||||||
if(idx == 3)
|
|
||||||
mySegment3[(address & 0x03FF)] = value;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
const uInt8* CartridgeWD::getImage(size_t& size) const
|
|
||||||
{
|
|
||||||
size = mySize;
|
|
||||||
return myImage.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool CartridgeWD::save(Serializer& out) const
|
bool CartridgeWD::save(Serializer& out) const
|
||||||
{
|
{
|
||||||
|
CartridgeEnhanced::save(out);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putShort(myCurrentBank);
|
out.putShort(myCurrentBank);
|
||||||
out.putByteArray(myRAM.data(), myRAM.size());
|
|
||||||
out.putLong(myCyclesAtBankswitchInit);
|
out.putLong(myCyclesAtBankswitchInit);
|
||||||
out.putShort(myPendingBank);
|
out.putShort(myPendingBank);
|
||||||
}
|
}
|
||||||
|
@ -299,10 +144,10 @@ bool CartridgeWD::save(Serializer& out) const
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool CartridgeWD::load(Serializer& in)
|
bool CartridgeWD::load(Serializer& in)
|
||||||
{
|
{
|
||||||
|
CartridgeEnhanced::load(in);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
myCurrentBank = in.getShort();
|
myCurrentBank = in.getShort();
|
||||||
in.getByteArray(myRAM.data(), myRAM.size());
|
|
||||||
myCyclesAtBankswitchInit = in.getLong();
|
myCyclesAtBankswitchInit = in.getLong();
|
||||||
myPendingBank = in.getShort();
|
myPendingBank = in.getShort();
|
||||||
|
|
||||||
|
@ -319,9 +164,9 @@ bool CartridgeWD::load(Serializer& in)
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
const std::array<CartridgeWD::BankOrg, 8> CartridgeWD::ourBankOrg = {{
|
const std::array<CartridgeWD::BankOrg, 8> CartridgeWD::ourBankOrg = {{
|
||||||
// 0 1 2 3 4 5 6 7
|
// 0 1 2 3 4 5 6 7
|
||||||
{ 0, 0, 1, 3 }, // Bank 0, 8 2 1 - 1 - - - -
|
{ 0, 0, 1, 3 }, // Bank 0, 8 2 1 - 1 - - - -
|
||||||
{ 0, 1, 2, 3 }, // Bank 1, 9 1 1 1 1 - - - -
|
{ 0, 1, 2, 3 }, // Bank 1, 9 1 1 1 1 - - - -
|
||||||
{ 4, 5, 6, 7 }, // Bank 2, 10 - - - - 1 1 1 1
|
{ 4, 5, 6, 7 }, // Bank 2, 10 - - - - 1 1 1 1
|
||||||
{ 7, 4, 2, 3 }, // Bank 3, 11 - - 1 1 1 - - 1
|
{ 7, 4, 2, 3 }, // Bank 3, 11 - - 1 1 1 - - 1
|
||||||
{ 0, 0, 6, 7 }, // Bank 4, 12 2 - - - - - 1 1
|
{ 0, 0, 6, 7 }, // Bank 4, 12 2 - - - - - 1 1
|
||||||
|
|
|
@ -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 "CartWDWidget.hxx"
|
#include "CartWDWidget.hxx"
|
||||||
#endif
|
#endif
|
||||||
|
@ -45,15 +45,15 @@ class System;
|
||||||
$0037, $003F: 6,0,5,1
|
$0037, $003F: 6,0,5,1
|
||||||
|
|
||||||
|
|
||||||
In the uppermost (third) segment, the byte at $3FC is overwritten by 0.
|
(Removed: In the uppermost (third) segment, the byte at $3FC is overwritten by 0.)
|
||||||
|
|
||||||
The 64 bytes of RAM are accessible at $1000 - $103F (read port) and
|
The 64 bytes of RAM are accessible at $1000 - $103F (read port) and
|
||||||
$1040 - $107F (write port). Because the RAM takes 128 bytes of address
|
$1040 - $107F (write port). Because the RAM takes 128 bytes of address
|
||||||
space, the range $1000 - $107F of segment 0 ROM will never be available.
|
space, the range $1000 - $107F of segment 0 ROM will never be available.
|
||||||
|
|
||||||
@author Stephen Anthony
|
@author Stephen Anthony, Thomas Jentzsch
|
||||||
*/
|
*/
|
||||||
class CartridgeWD : public Cartridge
|
class CartridgeWD : public CartridgeEnhanced
|
||||||
{
|
{
|
||||||
friend class CartridgeWDWidget;
|
friend class CartridgeWDWidget;
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ class CartridgeWD : 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) override;
|
bool bank(uInt16 bank, uInt16 = 0) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get the current bank.
|
Get the current bank.
|
||||||
|
@ -98,28 +98,6 @@ class CartridgeWD : public Cartridge
|
||||||
*/
|
*/
|
||||||
uInt16 getBank(uInt16 address = 0) const override;
|
uInt16 getBank(uInt16 address = 0) const override;
|
||||||
|
|
||||||
/**
|
|
||||||
Query the number of banks supported by the cartridge.
|
|
||||||
*/
|
|
||||||
uInt16 romBankCount() 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.
|
Save the current state of this cart to the given Serializer.
|
||||||
|
|
||||||
|
@ -173,51 +151,9 @@ class CartridgeWD : public Cartridge
|
||||||
bool poke(uInt16 address, uInt8 value) override;
|
bool poke(uInt16 address, uInt8 value) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
bool checkSwitchBank(uInt16, uInt8 = 0) override { return false; };
|
||||||
Install the specified slice for segment zero.
|
|
||||||
|
|
||||||
@param slice The slice to map into the segment
|
|
||||||
*/
|
|
||||||
void segmentZero(uInt8 slice);
|
|
||||||
|
|
||||||
/**
|
|
||||||
Install the specified slice for segment one.
|
|
||||||
|
|
||||||
@param slice The slice to map into the segment
|
|
||||||
*/
|
|
||||||
void segmentOne(uInt8 slice);
|
|
||||||
|
|
||||||
/**
|
|
||||||
Install the specified slice for segment two.
|
|
||||||
|
|
||||||
@param slice The slice to map into the segment
|
|
||||||
*/
|
|
||||||
void segmentTwo(uInt8 slice);
|
|
||||||
|
|
||||||
/**
|
|
||||||
Install the specified slice for segment three.
|
|
||||||
Note that this method also takes care of setting one byte to 0.
|
|
||||||
|
|
||||||
@param slice The slice to map into the segment
|
|
||||||
*/
|
|
||||||
void segmentThree(uInt8 slice);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The 8K ROM image of the cartridge
|
|
||||||
std::array<uInt8, 8_KB> myImage;
|
|
||||||
|
|
||||||
// Indicates the actual size of the ROM image (either 8K or 8K + 3)
|
|
||||||
size_t mySize{0};
|
|
||||||
|
|
||||||
// The 64 bytes RAM of the cartridge
|
|
||||||
std::array<uInt8, 64> myRAM;
|
|
||||||
|
|
||||||
// The 1K ROM mirror of segment 3 (sometimes contains extra 3 bytes)
|
|
||||||
std::array<uInt8, 1_KB> mySegment3;
|
|
||||||
|
|
||||||
// Indicates the offset for each of the four segments
|
|
||||||
std::array<uInt16, 4> myOffset;
|
|
||||||
|
|
||||||
// Indicates the cycle at which a bankswitch was initiated
|
// Indicates the cycle at which a bankswitch was initiated
|
||||||
uInt64 myCyclesAtBankswitchInit{0};
|
uInt64 myCyclesAtBankswitchInit{0};
|
||||||
|
|
||||||
|
@ -233,6 +169,16 @@ class CartridgeWD : public Cartridge
|
||||||
};
|
};
|
||||||
static const std::array<BankOrg, 8> ourBankOrg;
|
static const std::array<BankOrg, 8> ourBankOrg;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// log(ROM bank segment size) / log(2)
|
||||||
|
static constexpr uInt16 BANK_SHIFT = 10; // = 1K = 0x0400
|
||||||
|
|
||||||
|
// RAM size
|
||||||
|
static constexpr uInt16 RAM_SIZE = 0x40;
|
||||||
|
|
||||||
|
// Write port for extra RAM is at low address by default
|
||||||
|
static constexpr bool RAM_HIGH_WP = true;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
CartridgeWD() = delete;
|
CartridgeWD() = delete;
|
||||||
|
|
Loading…
Reference in New Issue