mirror of https://github.com/stella-emu/stella.git
initial commit
This commit is contained in:
parent
3f5453e9d4
commit
244fc3f7d3
|
@ -84,6 +84,7 @@ using ByteArray = std::vector<uInt8>;
|
|||
using ShortArray = std::vector<uInt16>;
|
||||
using StringList = std::vector<std::string>;
|
||||
using ByteBuffer = std::unique_ptr<uInt8[]>; // NOLINT
|
||||
using WordBuffer = std::unique_ptr<uInt16[]>; // NOLINT
|
||||
|
||||
// We use KB a lot; let's make a literal for it
|
||||
constexpr uInt32 operator "" _KB(unsigned long long size)
|
||||
|
|
|
@ -98,9 +98,9 @@ CartridgeE0Widget::CartridgeE0Widget(
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeE0Widget::loadConfig()
|
||||
{
|
||||
mySlice0->setSelectedIndex(myCart.myCurrentSlice[0]);
|
||||
mySlice1->setSelectedIndex(myCart.myCurrentSlice[1]);
|
||||
mySlice2->setSelectedIndex(myCart.myCurrentSlice[2]);
|
||||
mySlice0->setSelectedIndex(myCart.myCurrentBank[0]);
|
||||
mySlice1->setSelectedIndex(myCart.myCurrentBank[1]);
|
||||
mySlice2->setSelectedIndex(myCart.myCurrentBank[2]);
|
||||
|
||||
CartDebugWidget::loadConfig();
|
||||
}
|
||||
|
@ -114,13 +114,13 @@ void CartridgeE0Widget::handleCommand(CommandSender* sender,
|
|||
switch(cmd)
|
||||
{
|
||||
case kSlice0Changed:
|
||||
myCart.segmentZero(mySlice0->getSelected());
|
||||
myCart.bank(mySlice0->getSelected(), 0);
|
||||
break;
|
||||
case kSlice1Changed:
|
||||
myCart.segmentOne(mySlice1->getSelected());
|
||||
myCart.bank(mySlice1->getSelected(), 1);
|
||||
break;
|
||||
case kSlice2Changed:
|
||||
myCart.segmentTwo(mySlice2->getSelected());
|
||||
myCart.bank(mySlice2->getSelected(), 2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -136,9 +136,9 @@ string CartridgeE0Widget::bankState()
|
|||
ostringstream& buf = buffer();
|
||||
|
||||
buf << "Slices: " << std::dec
|
||||
<< seg0[myCart.myCurrentSlice[0]] << " / "
|
||||
<< seg1[myCart.myCurrentSlice[1]] << " / "
|
||||
<< seg2[myCart.myCurrentSlice[2]];
|
||||
<< seg0[myCart.myCurrentBank[0]] << " / "
|
||||
<< seg1[myCart.myCurrentBank[1]] << " / "
|
||||
<< seg2[myCart.myCurrentBank[2]];
|
||||
|
||||
return buf.str();
|
||||
}
|
||||
|
|
|
@ -34,17 +34,17 @@ void CartridgeE0::reset()
|
|||
// Setup segments to some default slices
|
||||
if(randomStartBank())
|
||||
{
|
||||
segmentZero(mySystem->randGenerator().next() % 8);
|
||||
segmentOne(mySystem->randGenerator().next() % 8);
|
||||
segmentTwo(mySystem->randGenerator().next() % 8);
|
||||
bank(mySystem->randGenerator().next() % 8, 0);
|
||||
bank(mySystem->randGenerator().next() % 8, 1);
|
||||
bank(mySystem->randGenerator().next() % 8, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
segmentZero(4);
|
||||
segmentOne(5);
|
||||
segmentTwo(6);
|
||||
bank(4, 0);
|
||||
bank(5, 1);
|
||||
bank(6, 2);
|
||||
}
|
||||
myCurrentSlice[3] = 7; // fixed
|
||||
myCurrentBank[3] = bankCount() - 1; // fixed
|
||||
|
||||
myBankChanged = true;
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ void CartridgeE0::install(System& system)
|
|||
|
||||
// Set the page accessing methods for the hot spots in the last segment
|
||||
access.directPeekBase = nullptr;
|
||||
access.romAccessBase = &myRomAccessBase[0x1FC0]; // TJ: is this the correct address (or 0x1FE0)?
|
||||
access.romAccessBase = &myRomAccessBase[0x1FC0];
|
||||
access.romPeekCounter = &myRomAccessCounter[0x1FC0];
|
||||
access.romPokeCounter = &myRomAccessCounter[0x1FC0 + myAccessSize];
|
||||
access.type = System::PageAccessType::READ;
|
||||
|
@ -81,7 +81,7 @@ void CartridgeE0::install(System& system)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 CartridgeE0::getBank(uInt16 address) const
|
||||
{
|
||||
return myCurrentSlice[(address & 0xFFF) >> 10]; // 1K slices
|
||||
return myCurrentBank[(address & 0xFFF) >> 10]; // 1K slices
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -98,18 +98,18 @@ uInt8 CartridgeE0::peek(uInt16 address)
|
|||
// Switch banks if necessary
|
||||
if((address >= 0x0FE0) && (address <= 0x0FE7))
|
||||
{
|
||||
segmentZero(address & 0x0007);
|
||||
bank(address & 0x0007, 0);
|
||||
}
|
||||
else if((address >= 0x0FE8) && (address <= 0x0FEF))
|
||||
{
|
||||
segmentOne(address & 0x0007);
|
||||
bank(address & 0x0007, 1);
|
||||
}
|
||||
else if((address >= 0x0FF0) && (address <= 0x0FF7))
|
||||
{
|
||||
segmentTwo(address & 0x0007);
|
||||
bank(address & 0x0007, 2);
|
||||
}
|
||||
|
||||
return myImage[(myCurrentSlice[address >> 10] << 10) + (address & 0x03FF)];
|
||||
return myImage[(myCurrentBank[address >> 10] << 10) + (address & 0x03FF)];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -120,83 +120,38 @@ bool CartridgeE0::poke(uInt16 address, uInt8)
|
|||
// Switch banks if necessary
|
||||
if((address >= 0x0FE0) && (address <= 0x0FE7))
|
||||
{
|
||||
segmentZero(address & 0x0007);
|
||||
bank(address & 0x0007, 0);
|
||||
}
|
||||
else if((address >= 0x0FE8) && (address <= 0x0FEF))
|
||||
{
|
||||
segmentOne(address & 0x0007);
|
||||
bank(address & 0x0007, 1);
|
||||
}
|
||||
else if((address >= 0x0FF0) && (address <= 0x0FF7))
|
||||
{
|
||||
segmentTwo(address & 0x0007);
|
||||
bank(address & 0x0007, 2);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeE0::segmentZero(uInt16 slice)
|
||||
void CartridgeE0::bank(uInt16 bank, uInt16 slice)
|
||||
{
|
||||
if(bankLocked()) return;
|
||||
|
||||
// Remember the new slice
|
||||
myCurrentSlice[0] = slice;
|
||||
uInt16 offset = slice << 10;
|
||||
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; addr < 0x1400; addr += System::PAGE_SIZE)
|
||||
for(uInt16 addr = 0x1000 + sliceOffset; addr < 0x1000 + sliceOffset + 0x400; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[offset + (addr & 0x03FF)];
|
||||
access.romAccessBase = &myRomAccessBase[offset + (addr & 0x03FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[offset + (addr & 0x03FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[offset + (addr & 0x03FF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
myBankChanged = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeE0::segmentOne(uInt16 slice)
|
||||
{
|
||||
if(bankLocked()) return;
|
||||
|
||||
// Remember the new slice
|
||||
myCurrentSlice[1] = slice;
|
||||
uInt16 offset = slice << 10;
|
||||
|
||||
// Setup the page access methods for the current bank
|
||||
System::PageAccess access(this, System::PageAccessType::READ);
|
||||
|
||||
for(uInt16 addr = 0x1400; addr < 0x1800; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[offset + (addr & 0x03FF)];
|
||||
access.romAccessBase = &myRomAccessBase[offset + (addr & 0x03FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[offset + (addr & 0x03FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[offset + (addr & 0x03FF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
myBankChanged = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeE0::segmentTwo(uInt16 slice)
|
||||
{
|
||||
if(bankLocked()) return;
|
||||
|
||||
// Remember the new slice
|
||||
myCurrentSlice[2] = slice;
|
||||
uInt16 offset = slice << 10;
|
||||
|
||||
// Setup the page access methods for the current bank
|
||||
System::PageAccess access(this, System::PageAccessType::READ);
|
||||
|
||||
for(uInt16 addr = 0x1800; addr < 0x1C00; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[offset + (addr & 0x03FF)];
|
||||
access.romAccessBase = &myRomAccessBase[offset + (addr & 0x03FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[offset + (addr & 0x03FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[offset + (addr & 0x03FF) + myAccessSize];
|
||||
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;
|
||||
|
@ -206,7 +161,7 @@ void CartridgeE0::segmentTwo(uInt16 slice)
|
|||
bool CartridgeE0::patch(uInt16 address, uInt8 value)
|
||||
{
|
||||
address &= 0x0FFF;
|
||||
myImage[(myCurrentSlice[address >> 10] << 10) + (address & 0x03FF)] = value;
|
||||
myImage[(myCurrentBank[address >> 10] << 10) + (address & 0x03FF)] = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -222,7 +177,7 @@ bool CartridgeE0::save(Serializer& out) const
|
|||
{
|
||||
try
|
||||
{
|
||||
out.putShortArray(myCurrentSlice.data(), myCurrentSlice.size());
|
||||
out.putShortArray(myCurrentBank.data(), myCurrentBank.size());
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
@ -238,7 +193,7 @@ bool CartridgeE0::load(Serializer& in)
|
|||
{
|
||||
try
|
||||
{
|
||||
in.getShortArray(myCurrentSlice.data(), myCurrentSlice.size());
|
||||
in.getShortArray(myCurrentBank.data(), myCurrentBank.size());
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
|
|
@ -156,32 +156,18 @@ class CartridgeE0 : public Cartridge
|
|||
|
||||
private:
|
||||
/**
|
||||
Install the specified slice for segment zero
|
||||
Install the specified slice for segment (bank) 0..2
|
||||
|
||||
@param slice The slice to map into the segment
|
||||
*/
|
||||
void segmentZero(uInt16 slice);
|
||||
|
||||
/**
|
||||
Install the specified slice for segment one
|
||||
|
||||
@param slice The slice to map into the segment
|
||||
*/
|
||||
void segmentOne(uInt16 slice);
|
||||
|
||||
/**
|
||||
Install the specified slice for segment two
|
||||
|
||||
@param slice The slice to map into the segment
|
||||
*/
|
||||
void segmentTwo(uInt16 slice);
|
||||
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> myCurrentSlice;
|
||||
std::array<uInt16, 4> myCurrentBank;
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
|
|
|
@ -0,0 +1,259 @@
|
|||
//============================================================================
|
||||
//
|
||||
// SSSS tt lll lll
|
||||
// SS SS tt ll ll
|
||||
// SS tttttt eeee ll ll aaaa
|
||||
// SSSS tt ee ee ll ll aa
|
||||
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#include "System.hxx"
|
||||
#include "CartEnhanced.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
CartridgeEnhanced::CartridgeEnhanced(const ByteBuffer& image, size_t size,
|
||||
const string& md5, const Settings& settings)
|
||||
: Cartridge(settings, md5),
|
||||
mySize(size)
|
||||
{
|
||||
// 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());
|
||||
|
||||
// Copy the ROM image into my buffer
|
||||
createRomAccessArrays(mySize);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeEnhanced::install(System& system)
|
||||
{
|
||||
// Allocate array for the current bank segments slices
|
||||
myCurrentBankOffset = make_unique<uInt16[]>(BANK_SEGS);
|
||||
std::fill_n(myCurrentBankOffset.get(), BANK_SEGS, 0);
|
||||
|
||||
// Allocate array for the RAM area
|
||||
myRAM = make_unique<uInt8[]>(myRamSize);
|
||||
|
||||
// Setup page access
|
||||
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 < 0x1000 + myRamSize; addr += System::PAGE_SIZE)
|
||||
{
|
||||
uInt16 offset = addr & myRamMask;
|
||||
access.romAccessBase = &myRomAccessBase[offset];
|
||||
access.romPeekCounter = &myRomAccessCounter[offset];
|
||||
access.romPokeCounter = &myRomAccessCounter[offset + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
// Set the page accessing method for the RAM reading pages
|
||||
access.type = System::PageAccessType::READ;
|
||||
for(uInt16 addr = 0x1000 + myRamSize; addr < 0x1000 + myRamSize * 2; addr += System::PAGE_SIZE)
|
||||
{
|
||||
uInt16 offset = addr & myRamMask;
|
||||
access.directPeekBase = &myRAM[offset];
|
||||
access.romAccessBase = &myRomAccessBase[myRamSize + offset];
|
||||
access.romPeekCounter = &myRomAccessCounter[myRamSize + offset];
|
||||
access.romPokeCounter = &myRomAccessCounter[myRamSize + offset + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
// Install pages for the startup bank
|
||||
bank(startBank());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeEnhanced::reset()
|
||||
{
|
||||
initializeRAM(myRAM.get(), myRamSize);
|
||||
|
||||
initializeStartBank(getStartBank());
|
||||
|
||||
// Upon reset we switch to the reset bank
|
||||
bank(startBank());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 CartridgeEnhanced::peek(uInt16 address)
|
||||
{
|
||||
uInt16 peekAddress = address;
|
||||
address &= myBankMask;
|
||||
|
||||
checkSwitchBank(address);
|
||||
|
||||
if(address < myRamSize) // Write port is at 0xF000 - 0xF07F (128 bytes)
|
||||
return peekRAM(myRAM[address], peekAddress);
|
||||
else
|
||||
return myImage[myBankOffset + address];
|
||||
return myImage[myCurrentBankOffset[address >> BANK_SHIFT] + (address & BANK_MASK)];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeEnhanced::poke(uInt16 address, uInt8 value)
|
||||
{
|
||||
address &= myBankMask;
|
||||
|
||||
// Switch banks if necessary
|
||||
if (checkSwitchBank(address & myBankMask))
|
||||
return false;
|
||||
|
||||
if(myRamSize)
|
||||
{
|
||||
if(!(address & myRamSize))
|
||||
{
|
||||
pokeRAM(myRAM[address & myRamMask], 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 CartridgeEnhanced::bank(uInt16 bank, uInt16 slice)
|
||||
{
|
||||
if(bankLocked()) return false;
|
||||
|
||||
// Remember what bank we're in
|
||||
myBankOffset = bank << myBankShift;
|
||||
|
||||
uInt16 romHotspot = this->romHotspot();
|
||||
uInt16 fromAddr = 0x1000 + myRamSize * 2;
|
||||
uInt16 toAddr;
|
||||
|
||||
if(romHotspot)
|
||||
{
|
||||
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
|
||||
toAddr = 0x1000 + myBankSize;
|
||||
|
||||
System::PageAccess access(this, System::PageAccessType::READ);
|
||||
|
||||
// Setup the page access methods for the current bank
|
||||
for(uInt16 addr = (fromAddr & ~System::PAGE_MASK); addr < (toAddr & ~System::PAGE_MASK);
|
||||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
uInt16 offset = myBankOffset + (addr & myBankMask);
|
||||
if(myDirectPeek)
|
||||
access.directPeekBase = &myImage[offset];
|
||||
access.romAccessBase = &myRomAccessBase[offset];
|
||||
access.romPeekCounter = &myRomAccessCounter[offset];
|
||||
access.romPokeCounter = &myRomAccessCounter[offset + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
return myBankChanged = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 CartridgeEnhanced::getBank(uInt16) const
|
||||
{
|
||||
return myBankOffset >> myBankShift;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 CartridgeEnhanced::bankCount() const
|
||||
{
|
||||
return uInt16(mySize >> myBankShift);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeEnhanced::patch(uInt16 address, uInt8 value)
|
||||
{
|
||||
address &= myBankMask;
|
||||
|
||||
if(address < myRamSize * 2)
|
||||
{
|
||||
// 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 & myRamMask] = value;
|
||||
}
|
||||
else
|
||||
myImage[myBankOffset + address] = value;
|
||||
|
||||
return myBankChanged = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const uInt8* CartridgeEnhanced::getImage(size_t& size) const
|
||||
{
|
||||
size = mySize;
|
||||
return myImage.get();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeEnhanced::save(Serializer& out) const
|
||||
{
|
||||
try
|
||||
{
|
||||
out.putShort(myBankOffset);
|
||||
if(myRamSize)
|
||||
out.putByteArray(myRAM.get(), myRamSize);
|
||||
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "ERROR: << " << name() << "::save" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeEnhanced::load(Serializer& in)
|
||||
{
|
||||
try
|
||||
{
|
||||
myBankOffset = in.getShort();
|
||||
if(myRamSize)
|
||||
in.getByteArray(myRAM.get(), myRamSize);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "ERROR: " << name() << "::load" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remember what bank we were in
|
||||
bank(myBankOffset >> myBankShift);
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,204 @@
|
|||
//============================================================================
|
||||
//
|
||||
// SSSS tt lll lll
|
||||
// SS SS tt ll ll
|
||||
// SS tttttt eeee ll ll aaaa
|
||||
// SSSS tt ee ee ll ll aa
|
||||
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#ifndef CARTRIDGEENHANCED_HXX
|
||||
#define CARTRIDGEENHANCED_HXX
|
||||
|
||||
class System;
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Cart.hxx"
|
||||
|
||||
/**
|
||||
Enhanced cartridge base class used for multiple cart types.
|
||||
|
||||
@author Thomas Jentzsch
|
||||
*/
|
||||
class CartridgeEnhanced : public Cartridge
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Create a new cartridge using the specified image
|
||||
|
||||
@param image Pointer to the ROM image
|
||||
@param size The size of the ROM image
|
||||
@param md5 The md5sum of the ROM image
|
||||
@param settings A reference to the various settings (read-only)
|
||||
*/
|
||||
CartridgeEnhanced(const ByteBuffer& image, size_t size, const string& md5,
|
||||
const Settings& settings);
|
||||
virtual ~CartridgeEnhanced() = default;
|
||||
|
||||
public:
|
||||
/**
|
||||
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;
|
||||
|
||||
/**
|
||||
Reset device to its power-on state
|
||||
*/
|
||||
void reset() 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, uInt16 slice);
|
||||
|
||||
/**
|
||||
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 { return this->bank(bank, 0); }
|
||||
|
||||
/**
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
protected:
|
||||
// Pointer to a dynamically allocated ROM image of the cartridge
|
||||
ByteBuffer myImage{nullptr};
|
||||
|
||||
// Pointer to a dynamically allocated RAM area of the cartridge
|
||||
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:
|
||||
// log(ROM bank size) / log(2)
|
||||
static constexpr uInt16 BANK_SHIFT = 12;
|
||||
|
||||
// bank size
|
||||
static constexpr uInt16 BANK_SIZE = 1 << BANK_SHIFT; // 2 ^ 12 = 4K
|
||||
|
||||
// bank mask
|
||||
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};
|
||||
|
||||
protected:
|
||||
/**
|
||||
Check hotspots and switch bank if triggered.
|
||||
*/
|
||||
virtual bool checkSwitchBank(uInt16 address, uInt8 value = 0) = 0;
|
||||
|
||||
private:
|
||||
virtual uInt16 getStartBank() const { return 0; }
|
||||
|
||||
virtual uInt16 romHotspot() const { return 0; }
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
CartridgeEnhanced() = delete;
|
||||
CartridgeEnhanced(const CartridgeEnhanced&) = delete;
|
||||
CartridgeEnhanced(CartridgeEnhanced&&) = delete;
|
||||
CartridgeEnhanced& operator=(const CartridgeEnhanced&) = delete;
|
||||
CartridgeEnhanced& operator=(CartridgeEnhanced&&) = delete;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -15,159 +15,25 @@
|
|||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#include "System.hxx"
|
||||
#include "CartF0.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
CartridgeF0::CartridgeF0(const ByteBuffer& image, size_t size,
|
||||
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 CartridgeF0::reset()
|
||||
bool CartridgeF0::checkSwitchBank(uInt16 address, uInt8)
|
||||
{
|
||||
// Upon reset we switch to the startup bank
|
||||
initializeStartBank(15);
|
||||
bank(startBank());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeF0::install(System& system)
|
||||
{
|
||||
mySystem = &system;
|
||||
|
||||
// Install pages for the startup bank
|
||||
bank(startBank());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 CartridgeF0::peek(uInt16 address)
|
||||
{
|
||||
address &= 0x0FFF;
|
||||
|
||||
// Switch to next bank
|
||||
// Switch banks if necessary
|
||||
if(address == 0x0FF0)
|
||||
incbank();
|
||||
|
||||
return myImage[myBankOffset + address];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF0::poke(uInt16 address, uInt8)
|
||||
{
|
||||
address &= 0x0FFF;
|
||||
|
||||
// Switch to next bank
|
||||
if(address == 0x0FF0)
|
||||
incbank();
|
||||
|
||||
{
|
||||
// Switch to next bank
|
||||
uInt8 nextBank = ((getBank()) + 1) & 0x0F;
|
||||
bank(nextBank);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeF0::incbank()
|
||||
{
|
||||
// Determine current bank, and increment to the next one
|
||||
uInt8 nextBank = ((myBankOffset >> 12) + 1) & 0x0F;
|
||||
bank(nextBank);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF0::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 = (0x1FF0 & ~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>(0x1FF0U & ~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 CartridgeF0::getBank(uInt16) const
|
||||
{
|
||||
return myBankOffset >> 12;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 CartridgeF0::bankCount() const
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF0::patch(uInt16 address, uInt8 value)
|
||||
{
|
||||
myImage[myBankOffset + (address & 0x0FFF)] = value;
|
||||
return myBankChanged = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const uInt8* CartridgeF0::getImage(size_t& size) const
|
||||
{
|
||||
size = myImage.size();
|
||||
return myImage.data();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF0::save(Serializer& out) const
|
||||
{
|
||||
try
|
||||
{
|
||||
out.putShort(myBankOffset);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "ERROR: CartridgeF0::save" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF0::load(Serializer& in)
|
||||
{
|
||||
try
|
||||
{
|
||||
myBankOffset = in.getShort();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "ERROR: CartridgeF0::load" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remember what bank we were in
|
||||
bank(myBankOffset >> 12);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -18,10 +18,7 @@
|
|||
#ifndef CARTRIDGEF0_HXX
|
||||
#define CARTRIDGEF0_HXX
|
||||
|
||||
class System;
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Cart.hxx"
|
||||
#include "CartEnhanced.hxx"
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
#include "CartF0Widget.hxx"
|
||||
#endif
|
||||
|
@ -31,9 +28,9 @@ class System;
|
|||
There are 16 4K banks.
|
||||
Accessing $1FF0 switches to next bank.
|
||||
|
||||
@author Eckhard Stolberg
|
||||
@author Eckhard Stolberg, Thomas Jentzsch
|
||||
*/
|
||||
class CartridgeF0 : public Cartridge
|
||||
class CartridgeF0 : public CartridgeEnhanced
|
||||
{
|
||||
friend class CartridgeF0Widget;
|
||||
|
||||
|
@ -51,71 +48,6 @@ class CartridgeF0 : public Cartridge
|
|||
virtual ~CartridgeF0() = 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).
|
||||
|
||||
|
@ -135,35 +67,13 @@ class CartridgeF0 : public Cartridge
|
|||
}
|
||||
#endif
|
||||
|
||||
public:
|
||||
/**
|
||||
Get the byte at the specified address.
|
||||
protected:
|
||||
bool checkSwitchBank(uInt16 address, uInt8 value = 0);
|
||||
|
||||
@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;
|
||||
uInt16 romHotspot() const override { return 0x1FF0; }
|
||||
|
||||
private:
|
||||
/**
|
||||
Install pages for the next bank in the system
|
||||
*/
|
||||
void incbank();
|
||||
|
||||
private:
|
||||
// The 64K ROM image of the cartridge
|
||||
std::array<uInt8, 64_KB> myImage;
|
||||
|
||||
// Indicates the offset into the ROM image (aligns to current bank)
|
||||
uInt16 myBankOffset{0};
|
||||
uInt16 getStartBank() const override { return 15; }
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
|
|
|
@ -15,155 +15,24 @@
|
|||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#include "Random.hxx"
|
||||
#include "System.hxx"
|
||||
#include "CartF4.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
CartridgeF4::CartridgeF4(const ByteBuffer& image, size_t size,
|
||||
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 CartridgeF4::reset()
|
||||
bool CartridgeF4::checkSwitchBank(uInt16 address, uInt8)
|
||||
{
|
||||
// Upon reset we switch to the startup bank
|
||||
initializeStartBank(0);
|
||||
bank(startBank());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeF4::install(System& system)
|
||||
{
|
||||
mySystem = &system;
|
||||
|
||||
// Install pages for the startup bank
|
||||
bank(startBank());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 CartridgeF4::peek(uInt16 address)
|
||||
{
|
||||
address &= 0x0FFF;
|
||||
|
||||
// Switch banks if necessary
|
||||
// Note: addresses could be calculated from hotspot and bank count
|
||||
if((address >= 0x0FF4) && (address <= 0x0FFB))
|
||||
{
|
||||
bank(address - 0x0FF4);
|
||||
return true;
|
||||
}
|
||||
|
||||
return myImage[myBankOffset + address];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF4::poke(uInt16 address, uInt8)
|
||||
{
|
||||
address &= 0x0FFF;
|
||||
|
||||
// Switch banks if necessary
|
||||
if((address >= 0x0FF4) && (address <= 0x0FFB))
|
||||
{
|
||||
bank(address - 0x0FF4);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF4::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 = (0x1FF4 & ~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>(0x1FF4U & ~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 CartridgeF4::getBank(uInt16) const
|
||||
{
|
||||
return myBankOffset >> 12;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 CartridgeF4::bankCount() const
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF4::patch(uInt16 address, uInt8 value)
|
||||
{
|
||||
myImage[myBankOffset + (address & 0x0FFF)] = value;
|
||||
return myBankChanged = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const uInt8* CartridgeF4::getImage(size_t& size) const
|
||||
{
|
||||
size = myImage.size();
|
||||
return myImage.data();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF4::save(Serializer& out) const
|
||||
{
|
||||
try
|
||||
{
|
||||
out.putShort(myBankOffset);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "ERROR: CartridgeF4::save" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF4::load(Serializer& in)
|
||||
{
|
||||
try
|
||||
{
|
||||
myBankOffset = in.getShort();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "ERROR: CartridgeF4::load" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remember what bank we were in
|
||||
bank(myBankOffset >> 12);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -18,10 +18,7 @@
|
|||
#ifndef CARTRIDGEF4_HXX
|
||||
#define CARTRIDGEF4_HXX
|
||||
|
||||
class System;
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Cart.hxx"
|
||||
#include "CartEnhanced.hxx"
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
#include "CartF4Widget.hxx"
|
||||
#endif
|
||||
|
@ -30,9 +27,9 @@ class System;
|
|||
Cartridge class used for Atari's 32K bankswitched games. There are eight
|
||||
4K banks, accessible by read/write to $1FF4 - $1FFB.
|
||||
|
||||
@author Bradford W. Mott
|
||||
@author Bradford W. Mott, Thomas Jentzsch
|
||||
*/
|
||||
class CartridgeF4 : public Cartridge
|
||||
class CartridgeF4 : public CartridgeEnhanced
|
||||
{
|
||||
friend class CartridgeF4Widget;
|
||||
|
||||
|
@ -50,71 +47,6 @@ class CartridgeF4 : public Cartridge
|
|||
virtual ~CartridgeF4() = 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).
|
||||
|
||||
|
@ -134,31 +66,12 @@ class CartridgeF4 : public Cartridge
|
|||
}
|
||||
#endif
|
||||
|
||||
public:
|
||||
/**
|
||||
Get the byte at the specified address.
|
||||
protected:
|
||||
bool checkSwitchBank(uInt16 address, uInt8 value = 0);
|
||||
|
||||
@return The byte at the specified address
|
||||
*/
|
||||
uInt8 peek(uInt16 address) override;
|
||||
uInt16 romHotspot() const override { return 0x1FF4; }
|
||||
|
||||
/**
|
||||
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:
|
||||
// The 32K ROM image of the cartridge
|
||||
std::array<uInt8, 32_KB> myImage;
|
||||
|
||||
// Indicates the offset into the ROM image (aligns to current bank)
|
||||
uInt16 myBankOffset{0};
|
||||
|
||||
private:
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
CartridgeF4() = delete;
|
||||
CartridgeF4(const CartridgeF4&) = delete;
|
||||
|
|
|
@ -15,211 +15,13 @@
|
|||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#include "System.hxx"
|
||||
#include "CartF4SC.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
CartridgeF4SC::CartridgeF4SC(const ByteBuffer& image, size_t size,
|
||||
const string& md5, const Settings& settings)
|
||||
: Cartridge(settings, md5)
|
||||
: CartridgeF4(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 CartridgeF4SC::reset()
|
||||
{
|
||||
initializeRAM(myRAM.data(), myRAM.size());
|
||||
initializeStartBank(0);
|
||||
|
||||
// Upon reset we switch to the startup bank
|
||||
bank(startBank());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeF4SC::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 & 0x07F) + 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 CartridgeF4SC::peek(uInt16 address)
|
||||
{
|
||||
uInt16 peekAddress = address;
|
||||
address &= 0x0FFF;
|
||||
|
||||
// Switch banks if necessary
|
||||
if((address >= 0x0FF4) && (address <= 0x0FFB))
|
||||
bank(address - 0x0FF4);
|
||||
|
||||
if(address < 0x0080) // Write port is at 0xF000 - 0xF07F (128 bytes)
|
||||
return peekRAM(myRAM[address], peekAddress);
|
||||
else
|
||||
return myImage[myBankOffset + address];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF4SC::poke(uInt16 address, uInt8 value)
|
||||
{
|
||||
uInt16 pokeAddress = address;
|
||||
address &= 0x0FFF;
|
||||
|
||||
// Switch banks if necessary
|
||||
if((address >= 0x0FF4) && (address <= 0x0FFB))
|
||||
{
|
||||
bank(address - 0x0FF4);
|
||||
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 CartridgeF4SC::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 = (0x1FF4 & ~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>(0x1FF4U & ~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 CartridgeF4SC::getBank(uInt16) const
|
||||
{
|
||||
return myBankOffset >> 12;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 CartridgeF4SC::bankCount() const
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF4SC::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* CartridgeF4SC::getImage(size_t& size) const
|
||||
{
|
||||
size = myImage.size();
|
||||
return myImage.data();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF4SC::save(Serializer& out) const
|
||||
{
|
||||
try
|
||||
{
|
||||
out.putShort(myBankOffset);
|
||||
out.putByteArray(myRAM.data(), myRAM.size());
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "ERROR: CartridgeF4SC::save" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF4SC::load(Serializer& in)
|
||||
{
|
||||
try
|
||||
{
|
||||
myBankOffset = in.getShort();
|
||||
in.getByteArray(myRAM.data(), myRAM.size());
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "ERROR: CartridgeF4SC::load" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remember what bank we were in
|
||||
bank(myBankOffset >> 12);
|
||||
|
||||
return true;
|
||||
myRamSize = RAM_SIZE;
|
||||
myRamMask = RAM_MASK;
|
||||
}
|
||||
|
|
|
@ -18,10 +18,7 @@
|
|||
#ifndef CARTRIDGEF4SC_HXX
|
||||
#define CARTRIDGEF4SC_HXX
|
||||
|
||||
class System;
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Cart.hxx"
|
||||
#include "CartF4.hxx"
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
#include "CartF4SCWidget.hxx"
|
||||
#endif
|
||||
|
@ -31,9 +28,9 @@ class System;
|
|||
RAM. There are eight 4K banks, accessible by read/write to $1FF4 - $1FFB.
|
||||
RAM read port is $1080 - $10FF, write port is $1000 - $107F.
|
||||
|
||||
@author Bradford W. Mott
|
||||
@author Bradford W. Mott, Thomas Jentzsch
|
||||
*/
|
||||
class CartridgeF4SC : public Cartridge
|
||||
class CartridgeF4SC : public CartridgeF4
|
||||
{
|
||||
friend class CartridgeF4SCWidget;
|
||||
|
||||
|
@ -51,71 +48,6 @@ class CartridgeF4SC : public Cartridge
|
|||
virtual ~CartridgeF4SC() = 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).
|
||||
|
||||
|
@ -135,32 +67,12 @@ class CartridgeF4SC : 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:
|
||||
// The 32K ROM image of the cartridge
|
||||
std::array<uInt8, 32_KB> myImage;
|
||||
// RAM size
|
||||
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};
|
||||
// RAM mask
|
||||
static constexpr uInt16 RAM_MASK = RAM_SIZE - 1;
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
|
|
|
@ -15,195 +15,25 @@
|
|||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#include "System.hxx"
|
||||
#include "CartF6.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
CartridgeF6::CartridgeF6(const ByteBuffer& image, size_t size,
|
||||
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 CartridgeF6::reset()
|
||||
bool CartridgeF6::checkSwitchBank(uInt16 address, uInt8)
|
||||
{
|
||||
// Upon reset we switch to the startup bank
|
||||
initializeStartBank(0);
|
||||
bank(startBank());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeF6::install(System& system)
|
||||
{
|
||||
mySystem = &system;
|
||||
|
||||
// Upon install we'll setup the startup bank
|
||||
bank(startBank());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 CartridgeF6::peek(uInt16 address)
|
||||
{
|
||||
address &= 0x0FFF;
|
||||
|
||||
// Switch banks if necessary
|
||||
switch(address)
|
||||
// Note: addresses could be calculated from hotspot and bank count
|
||||
if((address >= 0x0FF6) && (address <= 0x0FF9))
|
||||
{
|
||||
case 0x0FF6:
|
||||
// Set the current bank to the first 4k bank
|
||||
bank(0);
|
||||
break;
|
||||
|
||||
case 0x0FF7:
|
||||
// Set the current bank to the second 4k bank
|
||||
bank(1);
|
||||
break;
|
||||
|
||||
case 0x0FF8:
|
||||
// Set the current bank to the third 4k bank
|
||||
bank(2);
|
||||
break;
|
||||
|
||||
case 0x0FF9:
|
||||
// Set the current bank to the forth 4k bank
|
||||
bank(3);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return myImage[myBankOffset + address];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF6::poke(uInt16 address, uInt8)
|
||||
{
|
||||
address &= 0x0FFF;
|
||||
|
||||
// Switch banks if necessary
|
||||
switch(address)
|
||||
{
|
||||
case 0x0FF6:
|
||||
// Set the current bank to the first 4k bank
|
||||
bank(0);
|
||||
break;
|
||||
|
||||
case 0x0FF7:
|
||||
// Set the current bank to the second 4k bank
|
||||
bank(1);
|
||||
break;
|
||||
|
||||
case 0x0FF8:
|
||||
// Set the current bank to the third 4k bank
|
||||
bank(2);
|
||||
break;
|
||||
|
||||
case 0x0FF9:
|
||||
// Set the current bank to the forth 4k bank
|
||||
bank(3);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
bank(address - 0x0FF6);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF6::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 = (0x1FF6 & ~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>(0x1FF6U & ~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 CartridgeF6::getBank(uInt16) const
|
||||
{
|
||||
return myBankOffset >> 12;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 CartridgeF6::bankCount() const
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF6::patch(uInt16 address, uInt8 value)
|
||||
{
|
||||
myImage[myBankOffset + (address & 0x0FFF)] = value;
|
||||
return myBankChanged = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const uInt8* CartridgeF6::getImage(size_t& size) const
|
||||
{
|
||||
size = myImage.size();
|
||||
return myImage.data();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF6::save(Serializer& out) const
|
||||
{
|
||||
try
|
||||
{
|
||||
out.putShort(myBankOffset);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "ERROR: CartridgeF6::save" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF6::load(Serializer& in)
|
||||
{
|
||||
try
|
||||
{
|
||||
myBankOffset = in.getShort();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "ERROR: CartridgeF6::load" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remember what bank we were in
|
||||
bank(myBankOffset >> 12);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -18,10 +18,7 @@
|
|||
#ifndef CARTRIDGEF6_HXX
|
||||
#define CARTRIDGEF6_HXX
|
||||
|
||||
class System;
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Cart.hxx"
|
||||
#include "CartEnhanced.hxx"
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
#include "CartF6Widget.hxx"
|
||||
#endif
|
||||
|
@ -30,9 +27,9 @@ class System;
|
|||
Cartridge class used for Atari's 16K bankswitched games. There are four
|
||||
4K banks, accessible by read/write to $1FF6 - $1FF9.
|
||||
|
||||
@author Bradford W. Mott
|
||||
@author Bradford W. Mott, Thomas Jentzsch
|
||||
*/
|
||||
class CartridgeF6 : public Cartridge
|
||||
class CartridgeF6 : public CartridgeEnhanced
|
||||
{
|
||||
friend class CartridgeF6Widget;
|
||||
|
||||
|
@ -50,71 +47,6 @@ class CartridgeF6 : public Cartridge
|
|||
virtual ~CartridgeF6() = 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).
|
||||
|
||||
|
@ -134,29 +66,10 @@ class CartridgeF6 : public Cartridge
|
|||
}
|
||||
#endif
|
||||
|
||||
public:
|
||||
/**
|
||||
Get the byte at the specified address.
|
||||
protected:
|
||||
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
|
||||
|
||||
@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:
|
||||
// The 16K ROM image of the cartridge
|
||||
std::array<uInt8, 16_KB> myImage;
|
||||
|
||||
// Indicates the offset into the ROM image (aligns to current bank)
|
||||
uInt16 myBankOffset{0};
|
||||
uInt16 romHotspot() const override { return 0x1FF6; }
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
|
|
|
@ -15,251 +15,13 @@
|
|||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#include "System.hxx"
|
||||
#include "CartF6SC.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
CartridgeF6SC::CartridgeF6SC(const ByteBuffer& image, size_t size,
|
||||
const string& md5, const Settings& settings)
|
||||
: Cartridge(settings, md5)
|
||||
: CartridgeF6(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 CartridgeF6SC::reset()
|
||||
{
|
||||
initializeRAM(myRAM.data(), myRAM.size());
|
||||
initializeStartBank(0);
|
||||
|
||||
// Upon reset we switch to the startup bank
|
||||
bank(startBank());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeF6SC::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 & 0x07F) + 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 CartridgeF6SC::peek(uInt16 address)
|
||||
{
|
||||
uInt16 peekAddress = address;
|
||||
address &= 0x0FFF;
|
||||
|
||||
// Switch banks if necessary
|
||||
switch(address)
|
||||
{
|
||||
case 0x0FF6:
|
||||
// Set the current bank to the first 4k bank
|
||||
bank(0);
|
||||
break;
|
||||
|
||||
case 0x0FF7:
|
||||
// Set the current bank to the second 4k bank
|
||||
bank(1);
|
||||
break;
|
||||
|
||||
case 0x0FF8:
|
||||
// Set the current bank to the third 4k bank
|
||||
bank(2);
|
||||
break;
|
||||
|
||||
case 0x0FF9:
|
||||
// Set the current bank to the forth 4k bank
|
||||
bank(3);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(address < 0x0080) // Write port is at 0xF000 - 0xF07F (128 bytes)
|
||||
return peekRAM(myRAM[address], peekAddress);
|
||||
else
|
||||
return myImage[myBankOffset + address];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF6SC::poke(uInt16 address, uInt8 value)
|
||||
{
|
||||
// Switch banks if necessary
|
||||
switch(address & 0x0FFF)
|
||||
{
|
||||
case 0x0FF6:
|
||||
// Set the current bank to the first 4k bank
|
||||
bank(0);
|
||||
return false;
|
||||
|
||||
case 0x0FF7:
|
||||
// Set the current bank to the second 4k bank
|
||||
bank(1);
|
||||
return false;
|
||||
|
||||
case 0x0FF8:
|
||||
// Set the current bank to the third 4k bank
|
||||
bank(2);
|
||||
return false;
|
||||
|
||||
case 0x0FF9:
|
||||
// Set the current bank to the forth 4k bank
|
||||
bank(3);
|
||||
return false;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
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 CartridgeF6SC::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 = (0x1FF6 & ~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>(0x1FF6U & ~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 CartridgeF6SC::getBank(uInt16) const
|
||||
{
|
||||
return myBankOffset >> 12;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 CartridgeF6SC::bankCount() const
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF6SC::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* CartridgeF6SC::getImage(size_t& size) const
|
||||
{
|
||||
size = myImage.size();
|
||||
return myImage.data();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF6SC::save(Serializer& out) const
|
||||
{
|
||||
try
|
||||
{
|
||||
out.putShort(myBankOffset);
|
||||
out.putByteArray(myRAM.data(), myRAM.size());
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "ERROR: CartridgeF6SC::save" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF6SC::load(Serializer& in)
|
||||
{
|
||||
try
|
||||
{
|
||||
myBankOffset = in.getShort();
|
||||
in.getByteArray(myRAM.data(), myRAM.size());
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "ERROR: CartridgeF6SC::load" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remember what bank we were in
|
||||
bank(myBankOffset >> 12);
|
||||
|
||||
return true;
|
||||
myRamSize = RAM_SIZE;
|
||||
myRamMask = RAM_MASK;
|
||||
}
|
||||
|
|
|
@ -18,10 +18,7 @@
|
|||
#ifndef CARTRIDGEF6SC_HXX
|
||||
#define CARTRIDGEF6SC_HXX
|
||||
|
||||
class System;
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Cart.hxx"
|
||||
#include "CartF6.hxx"
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
#include "CartF6SCWidget.hxx"
|
||||
#endif
|
||||
|
@ -31,9 +28,9 @@ class System;
|
|||
RAM. There are four 4K banks, accessible by read/write to $1FF6 - $1FF9.
|
||||
RAM read port is $1080 - $10FF, write port is $1000 - $107F.
|
||||
|
||||
@author Bradford W. Mott
|
||||
@author Bradford W. Mott, Thomas Jentzsch
|
||||
*/
|
||||
class CartridgeF6SC : public Cartridge
|
||||
class CartridgeF6SC : public CartridgeF6
|
||||
{
|
||||
friend class CartridgeF6SCWidget;
|
||||
|
||||
|
@ -51,71 +48,6 @@ class CartridgeF6SC : public Cartridge
|
|||
virtual ~CartridgeF6SC() = 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).
|
||||
|
||||
|
@ -135,32 +67,12 @@ class CartridgeF6SC : 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:
|
||||
// The 16K ROM image of the cartridge
|
||||
std::array<uInt8, 16_KB> myImage;
|
||||
// RAM size
|
||||
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};
|
||||
// RAM mask
|
||||
static constexpr uInt16 RAM_MASK = RAM_SIZE - 1;
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
|
|
|
@ -15,176 +15,33 @@
|
|||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#include "System.hxx"
|
||||
#include "CartF8.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
CartridgeF8::CartridgeF8(const ByteBuffer& image, size_t size,
|
||||
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 CartridgeF8::reset()
|
||||
bool CartridgeF8::checkSwitchBank(uInt16 address, uInt8)
|
||||
{
|
||||
initializeStartBank(1);
|
||||
|
||||
// Upon reset we switch to the reset bank
|
||||
bank(startBank());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeF8::install(System& system)
|
||||
{
|
||||
mySystem = &system;
|
||||
|
||||
// Install pages for the startup bank
|
||||
bank(startBank());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 CartridgeF8::peek(uInt16 address)
|
||||
{
|
||||
address &= 0x0FFF;
|
||||
|
||||
// Switch banks if necessary
|
||||
switch(address)
|
||||
{
|
||||
case 0x0FF8:
|
||||
// Set the current bank to the lower 4k bank
|
||||
bank(0);
|
||||
break;
|
||||
return true;
|
||||
|
||||
case 0x0FF9:
|
||||
// Set the current bank to the upper 4k bank
|
||||
bank(1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return myImage[myBankOffset + address];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF8::poke(uInt16 address, uInt8)
|
||||
{
|
||||
address &= 0x0FFF;
|
||||
|
||||
// Switch banks if necessary
|
||||
switch(address)
|
||||
{
|
||||
case 0x0FF8:
|
||||
// Set the current bank to the lower 4k bank
|
||||
bank(0);
|
||||
break;
|
||||
|
||||
case 0x0FF9:
|
||||
// Set the current bank to the upper 4k bank
|
||||
bank(1);
|
||||
break;
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF8::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 = (0x1FF8 & ~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>(0x1FF8U & ~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 CartridgeF8::getBank(uInt16) const
|
||||
{
|
||||
return myBankOffset >> 12;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 CartridgeF8::bankCount() const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF8::patch(uInt16 address, uInt8 value)
|
||||
{
|
||||
myImage[myBankOffset + (address & 0x0FFF)] = value;
|
||||
return myBankChanged = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const uInt8* CartridgeF8::getImage(size_t& size) const
|
||||
{
|
||||
size = myImage.size();
|
||||
return myImage.data();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF8::save(Serializer& out) const
|
||||
{
|
||||
try
|
||||
{
|
||||
out.putShort(myBankOffset);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "ERROR: CartridgeF8::save" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF8::load(Serializer& in)
|
||||
{
|
||||
try
|
||||
{
|
||||
myBankOffset = in.getShort();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "ERROR: CartridgeF8::load" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remember what bank we were in
|
||||
bank(myBankOffset >> 12);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -18,10 +18,7 @@
|
|||
#ifndef CARTRIDGEF8_HXX
|
||||
#define CARTRIDGEF8_HXX
|
||||
|
||||
class System;
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Cart.hxx"
|
||||
#include "CartEnhanced.hxx"
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
#include "CartF8Widget.hxx"
|
||||
#endif
|
||||
|
@ -30,9 +27,9 @@ class System;
|
|||
Cartridge class used for Atari's 8K bankswitched games. There are two
|
||||
4K banks, accessible by read/write to $1FF8 - $1FF9.
|
||||
|
||||
@author Bradford W. Mott
|
||||
@author Bradford W. Mott, Thomas Jentzsch
|
||||
*/
|
||||
class CartridgeF8 : public Cartridge
|
||||
class CartridgeF8 : public CartridgeEnhanced
|
||||
{
|
||||
friend class CartridgeF8Widget;
|
||||
|
||||
|
@ -50,71 +47,6 @@ class CartridgeF8 : public Cartridge
|
|||
virtual ~CartridgeF8() = 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).
|
||||
|
||||
|
@ -134,29 +66,13 @@ class CartridgeF8 : public Cartridge
|
|||
}
|
||||
#endif
|
||||
|
||||
public:
|
||||
/**
|
||||
Get the byte at the specified address.
|
||||
protected:
|
||||
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
|
||||
|
||||
@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;
|
||||
uInt16 romHotspot() const override { return 0x1FF8; }
|
||||
|
||||
private:
|
||||
// The 8K ROM image of the cartridge
|
||||
std::array<uInt8, 8_KB> myImage;
|
||||
|
||||
// Indicates the offset into the ROM image (aligns to current bank)
|
||||
uInt16 myBankOffset{0};
|
||||
uInt16 getStartBank() const override { return 1; }
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
|
|
|
@ -15,231 +15,13 @@
|
|||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#include "System.hxx"
|
||||
#include "CartF8SC.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
CartridgeF8SC::CartridgeF8SC(const ByteBuffer& image, size_t size,
|
||||
const string& md5, const Settings& settings)
|
||||
: Cartridge(settings, md5)
|
||||
: CartridgeF8(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 CartridgeF8SC::reset()
|
||||
{
|
||||
initializeRAM(myRAM.data(), myRAM.size());
|
||||
initializeStartBank(1);
|
||||
|
||||
// Upon reset we switch to the startup bank
|
||||
bank(startBank());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeF8SC::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 & 0x07F) + 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 CartridgeF8SC::peek(uInt16 address)
|
||||
{
|
||||
uInt16 peekAddress = address;
|
||||
address &= 0x0FFF;
|
||||
|
||||
// Switch banks if necessary
|
||||
switch(address)
|
||||
{
|
||||
case 0x0FF8:
|
||||
// Set the current bank to the lower 4k bank
|
||||
bank(0);
|
||||
break;
|
||||
|
||||
case 0x0FF9:
|
||||
// Set the current bank to the upper 4k bank
|
||||
bank(1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(address < 0x0080) // Write port is at 0xF000 - 0xF07F (128 bytes)
|
||||
return peekRAM(myRAM[address], peekAddress);
|
||||
else
|
||||
return myImage[myBankOffset + address];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF8SC::poke(uInt16 address, uInt8 value)
|
||||
{
|
||||
// Switch banks if necessary
|
||||
switch(address & 0x0FFF)
|
||||
{
|
||||
case 0x0FF8:
|
||||
// Set the current bank to the lower 4k bank
|
||||
bank(0);
|
||||
return false;
|
||||
|
||||
case 0x0FF9:
|
||||
// Set the current bank to the upper 4k bank
|
||||
bank(1);
|
||||
return false;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
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 CartridgeF8SC::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 = (0x1FF8 & ~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>(0x1FF8U & ~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 CartridgeF8SC::getBank(uInt16) const
|
||||
{
|
||||
return myBankOffset >> 12;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 CartridgeF8SC::bankCount() const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF8SC::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* CartridgeF8SC::getImage(size_t& size) const
|
||||
{
|
||||
size = myImage.size();
|
||||
return myImage.data();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF8SC::save(Serializer& out) const
|
||||
{
|
||||
try
|
||||
{
|
||||
out.putShort(myBankOffset);
|
||||
out.putByteArray(myRAM.data(), myRAM.size());
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "ERROR: CartridgeF8SC::save" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeF8SC::load(Serializer& in)
|
||||
{
|
||||
try
|
||||
{
|
||||
myBankOffset = in.getShort();
|
||||
in.getByteArray(myRAM.data(), myRAM.size());
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "ERROR: CartridgeF8SC::load" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remember what bank we were in
|
||||
bank(myBankOffset >> 12);
|
||||
|
||||
return true;
|
||||
myRamSize = RAM_SIZE;
|
||||
myRamMask = RAM_MASK;
|
||||
}
|
||||
|
|
|
@ -18,10 +18,7 @@
|
|||
#ifndef CARTRIDGEF8SC_HXX
|
||||
#define CARTRIDGEF8SC_HXX
|
||||
|
||||
class System;
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Cart.hxx"
|
||||
#include "CartF8.hxx"
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
#include "CartF8SCWidget.hxx"
|
||||
#endif
|
||||
|
@ -31,9 +28,9 @@ class System;
|
|||
RAM. There are two 4K banks, accessible by read/write to $1FF8 - $1FF9.
|
||||
RAM read port is $1080 - $10FF, write port is $1000 - $107F.
|
||||
|
||||
@author Bradford W. Mott
|
||||
@author Bradford W. Mott, Thomas Jentzsch
|
||||
*/
|
||||
class CartridgeF8SC : public Cartridge
|
||||
class CartridgeF8SC : public CartridgeF8
|
||||
{
|
||||
friend class CartridgeF8SCWidget;
|
||||
|
||||
|
@ -51,71 +48,6 @@ class CartridgeF8SC : public Cartridge
|
|||
virtual ~CartridgeF8SC() = 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).
|
||||
|
||||
|
@ -135,32 +67,12 @@ class CartridgeF8SC : 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:
|
||||
// The 8K ROM image of the cartridge
|
||||
std::array<uInt8, 8_KB> myImage;
|
||||
// RAM size
|
||||
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};
|
||||
// RAM mask
|
||||
static constexpr uInt16 RAM_MASK = RAM_SIZE - 1;
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
|
|
|
@ -21,52 +21,35 @@
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
CartridgeFC::CartridgeFC(const ByteBuffer& image, size_t size,
|
||||
const string& md5, const Settings& settings)
|
||||
: Cartridge(settings, md5),
|
||||
mySize(size)
|
||||
: 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 CartridgeFC::reset()
|
||||
{
|
||||
initializeStartBank(0);
|
||||
CartridgeEnhanced::reset();
|
||||
|
||||
myTargetBank = 0;
|
||||
|
||||
// Upon reset we switch to the reset bank
|
||||
bank(startBank());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeFC::install(System& system)
|
||||
bool CartridgeFC::checkSwitchBank(uInt16 address, uInt8)
|
||||
{
|
||||
mySystem = &system;
|
||||
|
||||
// Install pages for the startup bank
|
||||
bank(startBank());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 CartridgeFC::peek(uInt16 address)
|
||||
{
|
||||
address &= 0x0FFF;
|
||||
|
||||
// Switch banks if necessary
|
||||
if(address == 0x0FFC)
|
||||
{
|
||||
// Trigger the bank switch
|
||||
bank(myTargetBank);
|
||||
return true;
|
||||
}
|
||||
|
||||
return myImage[myBankOffset + address];
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeFC::poke(uInt16 address, uInt8 value)
|
||||
{
|
||||
address &= 0x0FFF;
|
||||
address &= myBankMask;
|
||||
|
||||
// Switch banks if necessary
|
||||
switch (address)
|
||||
|
@ -88,108 +71,8 @@ bool CartridgeFC::poke(uInt16 address, uInt8 value)
|
|||
myTargetBank = value % bankCount();
|
||||
break;
|
||||
|
||||
case 0x0FFC:
|
||||
// Trigger the bank switch
|
||||
bank(myTargetBank);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
checkSwitchBank(address);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeFC::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 = (0x1FF8 & ~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>(0x1FF8U & ~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);
|
||||
}
|
||||
myCurrentBank = myTargetBank;
|
||||
return myBankChanged = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 CartridgeFC::getBank(uInt16) const
|
||||
{
|
||||
return myBankOffset >> 12;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 CartridgeFC::bankCount() const
|
||||
{
|
||||
return uInt16(mySize >> 12);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeFC::patch(uInt16 address, uInt8 value)
|
||||
{
|
||||
myImage[myBankOffset + (address & 0x0FFF)] = value;
|
||||
return myBankChanged = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const uInt8* CartridgeFC::getImage(size_t& size) const
|
||||
{
|
||||
size = mySize;
|
||||
return myImage.data();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeFC::save(Serializer& out) const
|
||||
{
|
||||
try
|
||||
{
|
||||
out.putShort(myBankOffset);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
cerr << "ERROR: CartridgeFC::save" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeFC::load(Serializer& in)
|
||||
{
|
||||
try
|
||||
{
|
||||
myBankOffset = in.getShort();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
cerr << "ERROR: CartridgeFC::load" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remember what bank we were in
|
||||
bank(myBankOffset >> 12);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
class System;
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Cart.hxx"
|
||||
#include "CartEnhanced.hxx"
|
||||
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
#include "CartFCWidget.hxx"
|
||||
|
@ -30,12 +30,12 @@ class System;
|
|||
/**
|
||||
Cartridge class used for Amiga's 32K Power Play Arcade Video Game Album.
|
||||
There are eight 4K banks, writing to $1FF8 definies the two lowest bits
|
||||
of the wanted bank, writeing to $1FF9 defines the high bits. Reading from
|
||||
of the wanted bank, writeing to $1FF9 defines the high bits. Accessing
|
||||
$1FFC triggers the bank switching
|
||||
|
||||
@author Thomas Jentzsch
|
||||
*/
|
||||
class CartridgeFC : public Cartridge
|
||||
class CartridgeFC : public CartridgeEnhanced
|
||||
{
|
||||
friend class CartridgeFCWidget;
|
||||
|
||||
|
@ -58,66 +58,6 @@ class CartridgeFC : public Cartridge
|
|||
*/
|
||||
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).
|
||||
|
||||
|
@ -138,13 +78,6 @@ class CartridgeFC : 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
|
||||
|
||||
|
@ -154,19 +87,12 @@ class CartridgeFC : public Cartridge
|
|||
*/
|
||||
bool poke(uInt16 address, uInt8 value) override;
|
||||
|
||||
protected:
|
||||
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
|
||||
|
||||
uInt16 romHotspot() const override { return 0x1FF8; }
|
||||
|
||||
private:
|
||||
// The 32K ROM image of the cartridge
|
||||
std::array<uInt8, 32_KB> myImage;
|
||||
|
||||
// Size of the ROM image
|
||||
size_t mySize{0};
|
||||
|
||||
// Indicates the offset into the ROM image (aligns to current bank)
|
||||
uInt16 myBankOffset{0};
|
||||
|
||||
// Indicates which bank is currently active for the first segment
|
||||
uInt16 myCurrentBank{0};
|
||||
|
||||
// Target bank defined by writing to $1FF8/9
|
||||
uInt16 myTargetBank{0};
|
||||
|
||||
|
|
|
@ -22,20 +22,15 @@
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
CartridgeFE::CartridgeFE(const ByteBuffer& image, size_t size,
|
||||
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());
|
||||
myDirectPeek = false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeFE::reset()
|
||||
{
|
||||
// Decathlon requires this, since there is no startup vector in bank 1
|
||||
initializeStartBank(0);
|
||||
|
||||
bank(startBank());
|
||||
CartridgeEnhanced::reset();
|
||||
myLastAccessWasFE = false;
|
||||
}
|
||||
|
||||
|
@ -51,14 +46,27 @@ void CartridgeFE::install(System& system)
|
|||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeFE::checkSwitchBank(uInt16 address, uInt8 value)
|
||||
{
|
||||
if(myLastAccessWasFE)
|
||||
{
|
||||
bank((value & 0x20) ? 0 : 1);
|
||||
myLastAccessWasFE = false; // was: address == 0x01FE;
|
||||
return true;
|
||||
}
|
||||
myLastAccessWasFE = address == 0x01FE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 CartridgeFE::peek(uInt16 address)
|
||||
{
|
||||
uInt8 value = (address < 0x200) ? mySystem->m6532().peek(address) :
|
||||
myImage[myBankOffset + (address & 0x0FFF)];
|
||||
myImage[myBankOffset + (address & myBankMask)];
|
||||
|
||||
// Check if we hit hotspot
|
||||
checkBankSwitch(address, value);
|
||||
checkSwitchBank(address, value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
@ -70,83 +78,17 @@ bool CartridgeFE::poke(uInt16 address, uInt8 value)
|
|||
mySystem->m6532().poke(address, value);
|
||||
|
||||
// Check if we hit hotspot
|
||||
checkBankSwitch(address, value);
|
||||
checkSwitchBank(address, value);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeFE::checkBankSwitch(uInt16 address, uInt8 value)
|
||||
{
|
||||
if(bankLocked())
|
||||
return;
|
||||
|
||||
// Did we detect $01FE on the last address bus access?
|
||||
// If so, we bankswitch according to the upper 3 bits of the data bus
|
||||
// NOTE: see the header file for the significance of 'value & 0x20'
|
||||
if(myLastAccessWasFE)
|
||||
bank((value & 0x20) ? 0 : 1);
|
||||
|
||||
// On the next cycle, we use the (then) current data bus value to decode
|
||||
// the bank to use
|
||||
myLastAccessWasFE = address == 0x01FE;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeFE::bank(uInt16 bank)
|
||||
{
|
||||
if(bankLocked())
|
||||
return false;
|
||||
|
||||
myBankOffset = bank << 12;
|
||||
|
||||
System::PageAccess access(this, System::PageAccessType::READ);
|
||||
|
||||
// Setup the page access methods for the current bank
|
||||
// Map all of the cart accesses to call peek and poke
|
||||
for(uInt16 addr = 0x1000; 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);
|
||||
}
|
||||
|
||||
return myBankChanged = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 CartridgeFE::getBank(uInt16) const
|
||||
{
|
||||
return myBankOffset >> 12;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 CartridgeFE::bankCount() const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeFE::patch(uInt16 address, uInt8 value)
|
||||
{
|
||||
myImage[myBankOffset + (address & 0x0FFF)] = value;
|
||||
return myBankChanged = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const uInt8* CartridgeFE::getImage(size_t& size) const
|
||||
{
|
||||
size = myImage.size();
|
||||
return myImage.data();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeFE::save(Serializer& out) const
|
||||
{
|
||||
CartridgeEnhanced::save(out);
|
||||
try
|
||||
{
|
||||
out.putShort(myBankOffset);
|
||||
out.putBool(myLastAccessWasFE);
|
||||
}
|
||||
catch(...)
|
||||
|
@ -161,9 +103,9 @@ bool CartridgeFE::save(Serializer& out) const
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeFE::load(Serializer& in)
|
||||
{
|
||||
CartridgeEnhanced::load(in);
|
||||
try
|
||||
{
|
||||
myBankOffset = in.getShort();
|
||||
myLastAccessWasFE = in.getBool();
|
||||
}
|
||||
catch(...)
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
class System;
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Cart.hxx"
|
||||
#include "CartEnhanced.hxx"
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
#include "CartFEWidget.hxx"
|
||||
#endif
|
||||
|
@ -75,7 +75,7 @@ class System;
|
|||
@author Stephen Anthony; with ideas/research from Christian Speckner and
|
||||
alex_79 and TomSon (of AtariAge)
|
||||
*/
|
||||
class CartridgeFE : public Cartridge
|
||||
class CartridgeFE : public CartridgeEnhanced
|
||||
{
|
||||
friend class CartridgeFEWidget;
|
||||
|
||||
|
@ -106,42 +106,6 @@ class CartridgeFE : 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.
|
||||
|
||||
|
@ -194,20 +158,14 @@ class CartridgeFE : public Cartridge
|
|||
*/
|
||||
bool poke(uInt16 address, uInt8 value) override;
|
||||
|
||||
private:
|
||||
protected:
|
||||
/**
|
||||
Perform bankswitch when necessary, by monitoring for $01FE
|
||||
on the address bus and getting the bank number from the data bus.
|
||||
*/
|
||||
void checkBankSwitch(uInt16 address, uInt8 value);
|
||||
bool checkSwitchBank(uInt16 address, uInt8 value) override;
|
||||
|
||||
private:
|
||||
// The 8K ROM image of the cartridge
|
||||
std::array<uInt8, 8_KB> myImage;
|
||||
|
||||
// Indicates the offset into the ROM image (aligns to current bank)
|
||||
uInt16 myBankOffset{0};
|
||||
|
||||
// Whether previous address by peek/poke equals $01FE (hotspot)
|
||||
bool myLastAccessWasFE{false};
|
||||
|
||||
|
|
|
@ -106,7 +106,7 @@ class CartridgeMNetwork : public Cartridge
|
|||
uInt16 getBank(uInt16 address = 0) const override;
|
||||
|
||||
/**
|
||||
Query the number of banks supported by the cartridge.
|
||||
Query the number of banks supported by the cartridge.
|
||||
*/
|
||||
uInt16 bankCount() const override;
|
||||
|
||||
|
|
|
@ -22,20 +22,9 @@
|
|||
CartridgeUA::CartridgeUA(const ByteBuffer& image, size_t size,
|
||||
const string& md5, const Settings& settings,
|
||||
bool swapHotspots)
|
||||
: Cartridge(settings, md5),
|
||||
: CartridgeEnhanced(image, size, md5, settings),
|
||||
mySwappedHotspots(swapHotspots)
|
||||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeUA::reset()
|
||||
{
|
||||
// Upon reset we switch to the startup bank
|
||||
initializeStartBank(0);
|
||||
bank(startBank());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -60,26 +49,33 @@ void CartridgeUA::install(System& system)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 CartridgeUA::peek(uInt16 address)
|
||||
bool CartridgeUA::checkSwitchBank(uInt16 address, uInt8)
|
||||
{
|
||||
address &= 0x1FFF;
|
||||
|
||||
// Switch banks if necessary
|
||||
switch(address & 0x1260)
|
||||
{
|
||||
case 0x0220:
|
||||
// Set the current bank to the lower 4k bank
|
||||
bank(mySwappedHotspots ? 1 : 0);
|
||||
break;
|
||||
return true;
|
||||
|
||||
case 0x0240:
|
||||
// Set the current bank to the upper 4k bank
|
||||
bank(mySwappedHotspots ? 0 : 1);
|
||||
break;
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 CartridgeUA::peek(uInt16 address)
|
||||
{
|
||||
address &= myBankMask;
|
||||
|
||||
checkSwitchBank(address);
|
||||
|
||||
// Because of the way accessing is set up, we will only get here
|
||||
// when doing a TIA read
|
||||
|
@ -90,24 +86,9 @@ uInt8 CartridgeUA::peek(uInt16 address)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeUA::poke(uInt16 address, uInt8 value)
|
||||
{
|
||||
address &= 0x1FFF;
|
||||
address &= myBankMask;
|
||||
|
||||
// Switch banks if necessary
|
||||
switch(address & 0x1260)
|
||||
{
|
||||
case 0x0220:
|
||||
// Set the current bank to the lower 4k bank
|
||||
bank(mySwappedHotspots ? 1 : 0);
|
||||
break;
|
||||
|
||||
case 0x0240:
|
||||
// Set the current bank to the upper 4k bank
|
||||
bank(mySwappedHotspots ? 0 : 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
checkSwitchBank(address);
|
||||
|
||||
// Because of the way accessing is set up, we will may get here by
|
||||
// doing a write to TIA or cart; we ignore the cart write
|
||||
|
@ -119,87 +100,3 @@ bool CartridgeUA::poke(uInt16 address, uInt8 value)
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeUA::bank(uInt16 bank)
|
||||
{
|
||||
if(bankLocked()) return false;
|
||||
|
||||
// Remember what bank we're in
|
||||
myBankOffset = bank << 12;
|
||||
|
||||
// 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 < 0x2000; 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 CartridgeUA::getBank(uInt16) const
|
||||
{
|
||||
return myBankOffset >> 12;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 CartridgeUA::bankCount() const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeUA::patch(uInt16 address, uInt8 value)
|
||||
{
|
||||
myImage[myBankOffset + (address & 0x0FFF)] = value;
|
||||
return myBankChanged = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const uInt8* CartridgeUA::getImage(size_t& size) const
|
||||
{
|
||||
size = myImage.size();
|
||||
return myImage.data();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeUA::save(Serializer& out) const
|
||||
{
|
||||
try
|
||||
{
|
||||
out.putShort(myBankOffset);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "ERROR: " << name() << "::save" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeUA::load(Serializer& in)
|
||||
{
|
||||
try
|
||||
{
|
||||
myBankOffset = in.getShort();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "ERROR: " << name() << "::load" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remember what bank we were in
|
||||
bank(myBankOffset >> 12);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#define CARTRIDGEUA_HXX
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Cart.hxx"
|
||||
#include "CartEnhanced.hxx"
|
||||
#include "System.hxx"
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
#include "CartUAWidget.hxx"
|
||||
|
@ -30,9 +30,9 @@
|
|||
are two 4K banks, which are switched by accessing $0220 (bank 0) and
|
||||
$0240 (bank 1).
|
||||
|
||||
@author Bradford W. Mott
|
||||
@author Bradford W. Mott, Thomas Jentzsch
|
||||
*/
|
||||
class CartridgeUA : public Cartridge
|
||||
class CartridgeUA : public CartridgeEnhanced
|
||||
{
|
||||
friend class CartridgeUAWidget;
|
||||
|
||||
|
@ -51,11 +51,6 @@ class CartridgeUA : public Cartridge
|
|||
virtual ~CartridgeUA() = 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.
|
||||
|
@ -64,57 +59,6 @@ class CartridgeUA : 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).
|
||||
|
@ -152,16 +96,14 @@ class CartridgeUA : public Cartridge
|
|||
*/
|
||||
bool poke(uInt16 address, uInt8 value) override;
|
||||
|
||||
private:
|
||||
// The 8K ROM image of the cartridge
|
||||
std::array<uInt8, 8_KB> myImage;
|
||||
|
||||
protected:
|
||||
bool checkSwitchBank(uInt16 address, uInt8 value = 0) override;
|
||||
|
||||
private:
|
||||
// Previous Device's page access
|
||||
std::array<System::PageAccess, 2> myHotSpotPageAccess;
|
||||
|
||||
// Indicates the offset into the ROM image (aligns to current bank)
|
||||
uInt16 myBankOffset{0};
|
||||
|
||||
// Indicates if banks are swapped ("Mickey" cart)
|
||||
bool mySwappedHotspots{false};
|
||||
|
||||
|
|
|
@ -717,6 +717,7 @@
|
|||
<ClCompile Include="..\emucore\Bankswitch.cxx" />
|
||||
<ClCompile Include="..\emucore\Cart3EPlus.cxx" />
|
||||
<ClCompile Include="..\emucore\Cart4KSC.cxx" />
|
||||
<ClCompile Include="..\emucore\CartEnhanced.cxx" />
|
||||
<ClCompile Include="..\emucore\CartBF.cxx" />
|
||||
<ClCompile Include="..\emucore\CartBFSC.cxx" />
|
||||
<ClCompile Include="..\emucore\CartBUS.cxx" />
|
||||
|
@ -1739,6 +1740,7 @@
|
|||
<ClInclude Include="..\emucore\BSType.hxx" />
|
||||
<ClInclude Include="..\emucore\Cart3EPlus.hxx" />
|
||||
<ClInclude Include="..\emucore\Cart4KSC.hxx" />
|
||||
<ClInclude Include="..\emucore\CartEnhanced.hxx" />
|
||||
<ClInclude Include="..\emucore\CartBF.hxx" />
|
||||
<ClInclude Include="..\emucore\CartBFSC.hxx" />
|
||||
<ClInclude Include="..\emucore\CartBUS.hxx" />
|
||||
|
|
|
@ -1005,6 +1005,9 @@
|
|||
<ClCompile Include="..\gui\MessageDialog.cxx">
|
||||
<Filter>Source Files\gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\emucore\CartEnhanced.cxx">
|
||||
<Filter>Source Files\emucore</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\common\bspf.hxx">
|
||||
|
@ -2063,6 +2066,9 @@
|
|||
<ClInclude Include="..\gui\Stella16x32tFont.hxx">
|
||||
<Filter>Header Files\gui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\emucore\CartEnhanced.hxx">
|
||||
<Filter>Header Files\emucore</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="stella.ico">
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue