initial commit

This commit is contained in:
thrust26 2020-04-03 17:08:42 +02:00
parent 3f5453e9d4
commit 244fc3f7d3
410 changed files with 11017 additions and 2539 deletions

View File

@ -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)

View File

@ -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();
}

View File

@ -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(...)
{

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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};

View File

@ -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(...)

View File

@ -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};

View File

@ -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;

View File

@ -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;
}

View File

@ -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};

View File

@ -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" />

View File

@ -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.

Some files were not shown because too many files have changed in this diff Show More