autoformatted. still stabilising to stella standard.

Tabs removed, replaced with 2-char spacing. 
constants for bit masking added
corrected the patch code for the bit-allocations for RAM/ROM banks switch


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2900 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
adavie 2014-06-03 13:53:49 +00:00
parent 6d6dd7632f
commit 40c8c81245
2 changed files with 259 additions and 276 deletions

View File

@ -25,10 +25,8 @@
#include "CartDASH.hxx" #include "CartDASH.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeDASH::CartridgeDASH(const uInt8* image, uInt32 size, const Settings& settings) CartridgeDASH::CartridgeDASH(const uInt8* image, uInt32 size, const Settings& settings) :
: Cartridge(settings), Cartridge(settings), mySize(size) {
mySize(size)
{
// Allocate array for the ROM image // Allocate array for the ROM image
myImage = new uInt8[mySize]; myImage = new uInt8[mySize];
@ -46,20 +44,20 @@ CartridgeDASH::CartridgeDASH(const uInt8* image, uInt32 size, const Settings& se
registerRamArea(0x1400, RAM_BANK_SIZE, 0x00, RAM_WRITE_OFFSET); // 512 bytes RAM @ 0x1400 registerRamArea(0x1400, RAM_BANK_SIZE, 0x00, RAM_WRITE_OFFSET); // 512 bytes RAM @ 0x1400
registerRamArea(0x1600, RAM_BANK_SIZE, 0x00, RAM_WRITE_OFFSET); // 512 bytes RAM @ 0x1600 registerRamArea(0x1600, RAM_BANK_SIZE, 0x00, RAM_WRITE_OFFSET); // 512 bytes RAM @ 0x1600
myCurrentBank = -1; // nothing switched
// Remember startup bank (0 per spec, rather than last per 3E scheme). // Remember startup bank (0 per spec, rather than last per 3E scheme).
// Set this to go to 3rd 1K Bank. // Set this to go to 3rd 1K Bank.
myStartBank = (3 << BANK_BITS) | 0; myStartBank = (3 << BANK_BITS) | 0;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeDASH::~CartridgeDASH() CartridgeDASH::~CartridgeDASH() {
{
delete[] myImage; delete[] myImage;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeDASH::reset() void CartridgeDASH::reset() {
{
// Initialize RAM // Initialize RAM
if (mySettings.getBool("ramrandom")) if (mySettings.getBool("ramrandom"))
for (uInt32 i = 0; i < RAM_TOTAL_SIZE; ++i) for (uInt32 i = 0; i < RAM_TOTAL_SIZE; ++i)
@ -73,8 +71,7 @@ void CartridgeDASH::reset()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeDASH::install(System& system) void CartridgeDASH::install(System& system) {
{
mySystem = &system; mySystem = &system;
uInt16 shift = mySystem->pageShift(); uInt16 shift = mySystem->pageShift();
@ -95,8 +92,7 @@ void CartridgeDASH::install(System& system)
// Setup the last segment (of 4, each 1K) to point to the first ROM slice // Setup the last segment (of 4, each 1K) to point to the first ROM slice
// Actually we DO NOT want "always". It's just on bootup, and can be out switched later // Actually we DO NOT want "always". It's just on bootup, and can be out switched later
access.type = System::PA_READ; access.type = System::PA_READ;
for (uInt32 byte = 0; byte < ROM_BANK_SIZE; byte++) for (uInt32 byte = 0; byte < ROM_BANK_SIZE; byte++) {
{
uInt32 address = (0x1000 - ROM_BANK_SIZE) + (byte << shift); // which byte in last bank of 2600 address space uInt32 address = (0x1000 - ROM_BANK_SIZE) + (byte << shift); // which byte in last bank of 2600 address space
access.directPeekBase = &myImage[byte]; // from base address 0x0000 in image, so just use 'byte' access.directPeekBase = &myImage[byte]; // from base address 0x0000 in image, so just use 'byte'
access.codeAccessBase = &myCodeAccessBase[byte]; access.codeAccessBase = &myCodeAccessBase[byte];
@ -120,31 +116,29 @@ void CartridgeDASH::install(System& system)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeDASH::peek(uInt16 address) uInt8 CartridgeDASH::peek(uInt16 address) {
{
uInt8 value = 0; uInt8 value = 0;
uInt32 bank = (address >> ROM_BANK_TO_POWER) & 3; // convert to 1K bank index (0-3) uInt32 bank = (address >> ROM_BANK_TO_POWER) & 3; // convert to 1K bank index (0-3)
Int16 imageBank = bankInUse[bank]; // the ROM/RAM bank that's here Int16 imageBank = bankInUse[bank]; // the ROM/RAM bank that's here
if(imageBank == BANK_UNDEFINED) // an uninitialised bank? if (imageBank == BANK_UNDEFINED) { // an uninitialised bank?
{
// accessing invalid bank, so return should be... random? // accessing invalid bank, so return should be... random?
// TODO: Stephen -- throw some sort of error; looking at undefined data // TODO: Stephen -- throw some sort of error; looking at undefined data
assert(false); assert(false);
value = mySystem->randGenerator().next(); value = mySystem->randGenerator().next();
}
else if (imageBank & ROMRAM) // a RAM bank } else if (imageBank & BITMASK_ROMRAM) { // a RAM bank
{
Int32 ramBank = imageBank & BIT_BANK_MASK; // discard irrelevant bits Int32 ramBank = imageBank & BIT_BANK_MASK; // discard irrelevant bits
Int32 offset = ramBank << RAM_BANK_TO_POWER; // base bank address in RAM Int32 offset = ramBank << RAM_BANK_TO_POWER; // base bank address in RAM
offset += (address & (RAM_BANK_SIZE-1)); // + byte offset in RAM bank offset += (address & BITMASK_RAM_BANK); // + byte offset in RAM bank
value = myRAM[offset]; value = myRAM[offset];
}
else // accessing ROM } else { // accessing ROM
{
Int32 offset = imageBank << ROM_BANK_TO_POWER; // base bank address in image Int32 offset = imageBank << ROM_BANK_TO_POWER; // base bank address in image
offset += (address & (ROM_BANK_SIZE-1)); // + byte offset in image bank offset += (address & BITMASK_ROM_BANK); // + byte offset in image bank
value = myImage[offset]; value = myImage[offset];
} }
@ -152,8 +146,7 @@ uInt8 CartridgeDASH::peek(uInt16 address)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeDASH::poke(uInt16 address, uInt8 value) bool CartridgeDASH::poke(uInt16 address, uInt8 value) {
{
address &= 0x0FFF; // restrict to 4K address range address &= 0x0FFF; // restrict to 4K address range
// Check for write to the bank switch address. RAM/ROM and bank # are encoded in 'value' // Check for write to the bank switch address. RAM/ROM and bank # are encoded in 'value'
@ -172,8 +165,7 @@ bool CartridgeDASH::poke(uInt16 address, uInt8 value)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeDASH::bank(uInt16 bank) bool CartridgeDASH::bank(uInt16 bank) {
{
if (bankLocked()) if (bankLocked())
return false; // TODO: Stephen -- ? no idea return false; // TODO: Stephen -- ? no idea
@ -182,12 +174,12 @@ bool CartridgeDASH::bank(uInt16 bank)
uInt16 bankNumber = (bank >> BANK_BITS) & 3; // which bank # we are switching TO (BITS D6,D7) uInt16 bankNumber = (bank >> BANK_BITS) & 3; // which bank # we are switching TO (BITS D6,D7)
uInt16 bankID = bank & BIT_BANK_MASK; // The actual bank # to switch in (BITS D5-D0) uInt16 bankID = bank & BIT_BANK_MASK; // The actual bank # to switch in (BITS D5-D0)
if(bank & ROMRAM) // switching to a 512 byte RAM bank if (bank & BITMASK_ROMRAM) { // switching to a 512 byte RAM bank
{
// Wrap around/restrict to valid range // Wrap around/restrict to valid range
uInt16 currentBank = (bank & BIT_BANK_MASK) % RAM_BANK_COUNT; uInt16 currentBank = bank & BIT_BANK_MASK;
// Record which bank switched in (marked as RAM) // Record which bank switched in (marked as RAM)
myCurrentBank = bankInUse[bankNumber] = (Int16) (ROM_BANK_COUNT + currentBank); myCurrentBank = bankInUse[bankNumber] = (Int16) (BITMASK_ROMRAM | currentBank);
// Effectively * 512 bytes // Effectively * 512 bytes
uInt32 startCurrentBank = currentBank << RAM_BANK_TO_POWER; uInt32 startCurrentBank = currentBank << RAM_BANK_TO_POWER;
@ -195,8 +187,7 @@ bool CartridgeDASH::bank(uInt16 bank)
System::PageAccess access(0, 0, 0, this, System::PA_READ); System::PageAccess access(0, 0, 0, this, System::PA_READ);
// Map read-port RAM image into the system // Map read-port RAM image into the system
for(uInt32 byte = 0; byte < RAM_BANK_SIZE; byte += (1 << shift)) for (uInt32 byte = 0; byte < RAM_BANK_SIZE; byte += (1 << shift)) {
{
access.directPeekBase = &myRAM[startCurrentBank + byte]; access.directPeekBase = &myRAM[startCurrentBank + byte];
// TODO: Stephen please explain/review the use of mySize as an offset for RAM access here.... // TODO: Stephen please explain/review the use of mySize as an offset for RAM access here....
@ -209,14 +200,12 @@ bool CartridgeDASH::bank(uInt16 bank)
access.type = System::PA_WRITE; access.type = System::PA_WRITE;
// Map write-port RAM image into the system // Map write-port RAM image into the system
for (uInt32 byte = 0; byte < RAM_BANK_SIZE; byte += (1 << shift)) for (uInt32 byte = 0; byte < RAM_BANK_SIZE; byte += (1 << shift)) {
{
access.directPokeBase = &myRAM[startCurrentBank + RAM_WRITE_OFFSET + byte]; access.directPokeBase = &myRAM[startCurrentBank + RAM_WRITE_OFFSET + byte];
access.codeAccessBase = &myCodeAccessBase[mySize + startCurrentBank + RAM_WRITE_OFFSET + byte]; access.codeAccessBase = &myCodeAccessBase[mySize + startCurrentBank + RAM_WRITE_OFFSET + byte];
mySystem->setPageAccess((startCurrentBank + byte) >> shift, access); mySystem->setPageAccess((startCurrentBank + byte) >> shift, access);
} }
} } else // ROM 1K banks
else // ROM 1K banks
{ {
// Map ROM bank image into the system into the correct slot // Map ROM bank image into the system into the correct slot
// Memory map is 1K slots at 0x1000, 0x1400, 0x1800, 0x1C00 // Memory map is 1K slots at 0x1000, 0x1400, 0x1800, 0x1C00
@ -231,8 +220,7 @@ bool CartridgeDASH::bank(uInt16 bank)
uInt32 bankStart = 0x1000 + (bankNumber << ROM_BANK_TO_POWER); // *1K uInt32 bankStart = 0x1000 + (bankNumber << ROM_BANK_TO_POWER); // *1K
for (uInt32 byte = 0; byte < ROM_BANK_SIZE; byte += (1 << shift)) for (uInt32 byte = 0; byte < ROM_BANK_SIZE; byte += (1 << shift)) {
{
access.directPeekBase = &myImage[startCurrentBank + byte]; access.directPeekBase = &myImage[startCurrentBank + byte];
access.codeAccessBase = &myCodeAccessBase[startCurrentBank + byte]; access.codeAccessBase = &myCodeAccessBase[startCurrentBank + byte];
mySystem->setPageAccess((bankStart + byte) >> shift, access); mySystem->setPageAccess((bankStart + byte) >> shift, access);
@ -243,8 +231,7 @@ bool CartridgeDASH::bank(uInt16 bank)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeDASH::bank() const uInt16 CartridgeDASH::bank() const {
{
// TODO: Stephen -- what to do here? We don't really HAVE a "current bank"; we have 4 banks // TODO: Stephen -- what to do here? We don't really HAVE a "current bank"; we have 4 banks
// and they are defined in bankInUse[...]. // and they are defined in bankInUse[...].
// What I've done is kept track of the last switched bank, and return that. But that doesn't tell us WHERE. :( // What I've done is kept track of the last switched bank, and return that. But that doesn't tell us WHERE. :(
@ -253,27 +240,26 @@ uInt16 CartridgeDASH::bank() const
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeDASH::bankCount() const uInt16 CartridgeDASH::bankCount() const {
{
// Because the RAM banks always start above the ROM banks (see ROM_BANK_COUNT) for value, // We have a constant # banks for this scheme; 32 ROM and 32 RAM (or, at least, RAM_BANK_COUNT and ROM_BANK_COUNT)
// we require the number of ROM banks to be == ROM_BANK_COUNT. Banks are therefore 0-63 ROM 64-127 RAM // See usage of bank bits.
// TODO: Stephen -- ROM banks are 1K. RAM banks are 512 bytes. How does this affect what this routine should return? // TODO: Stephen -- What should this return, given the mangled bank value?
return ROM_BANK_COUNT + RAM_BANK_COUNT; return ROM_BANK_COUNT + RAM_BANK_COUNT;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeDASH::patch(uInt16 address, uInt8 value) bool CartridgeDASH::patch(uInt16 address, uInt8 value) {
{
// Patch the cartridge ROM // Patch the cartridge ROM
// TODO: Stephen... I assume this is for some sort of debugger support....? // TODO: Stephen... I assume this is for some sort of debugger support....?
myBankChanged = true; myBankChanged = true;
uInt32 bankNumber = (address >> 10) & 3; // now 1K bank # (ie: 0-3) uInt32 bankNumber = (address >> ROM_BANK_TO_POWER) & 3; // now 1K bank # (ie: 0-3)
Int32 whichBankIsThere = bankInUse[bankNumber]; // ROM or RAM bank reference Int32 whichBankIsThere = bankInUse[bankNumber]; // ROM or RAM bank reference
if(whichBankIsThere <= BANK_UNDEFINED) if (whichBankIsThere == BANK_UNDEFINED) {
{
// We're trying to access undefined memory (no bank here yet) // We're trying to access undefined memory (no bank here yet)
// TODO: Stephen -- what to do here? Fail silently? // TODO: Stephen -- what to do here? Fail silently?
@ -281,64 +267,58 @@ bool CartridgeDASH::patch(uInt16 address, uInt8 value)
assert(false); assert(false);
myBankChanged = false; myBankChanged = false;
}
else if(whichBankIsThere < ROM_BANK_COUNT) // patching ROM (1K banks) } else if (whichBankIsThere & BITMASK_ROMRAM) { // patching RAM (512 byte banks)
{
uInt32 byteOffset = address & (ROM_BANK_SIZE-1); uInt32 byteOffset = address & BITMASK_RAM_BANK;
uInt32 baseAddress = ((whichBankIsThere & BIT_BANK_MASK) << RAM_BANK_TO_POWER) + byteOffset;
myRAM[baseAddress] = value; // write to RAM
} else { // patching ROM (1K banks)
uInt32 byteOffset = address & BITMASK_ROM_BANK;
uInt32 baseAddress = (whichBankIsThere << ROM_BANK_TO_POWER) + byteOffset; uInt32 baseAddress = (whichBankIsThere << ROM_BANK_TO_POWER) + byteOffset;
myImage[baseAddress] = value; // write to the image myImage[baseAddress] = value; // write to the image
} }
else // patching RAM (512 byte banks)
{
uInt32 byteOffset = address & (RAM_BANK_SIZE-1);
uInt32 baseAddress = ((whichBankIsThere - ROM_BANK_COUNT) << RAM_BANK_TO_POWER) + byteOffset;
myRAM[baseAddress] = value; // write to RAM
}
return myBankChanged; return myBankChanged;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt8* CartridgeDASH::getImage(int& size) const const uInt8* CartridgeDASH::getImage(int& size) const {
{
size = mySize; size = mySize;
return myImage; return myImage;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeDASH::save(Serializer& out) const bool CartridgeDASH::save(Serializer& out) const {
{ try {
try
{
out.putString(name()); out.putString(name());
out.putShort(myCurrentBank); out.putShort(myCurrentBank);
for (uInt32 bank = 0; bank < 4; bank++) for (uInt32 bank = 0; bank < 4; bank++)
out.putShort(bankInUse[bank]); out.putShort(bankInUse[bank]);
out.putByteArray(myRAM, RAM_TOTAL_SIZE); out.putByteArray(myRAM, RAM_TOTAL_SIZE);
} } catch (...) {
catch (...)
{
cerr << "ERROR: CartridgeDASH::save" << endl; cerr << "ERROR: CartridgeDASH::save" << endl;
{
return false; return false;
} }
return true; return true;
} }
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeDASH::load(Serializer& in) bool CartridgeDASH::load(Serializer& in) {
{ try {
try
{
if (in.getString() != name()) if (in.getString() != name())
return false; return false;
myCurrentBank = in.getShort(); myCurrentBank = in.getShort();
for (uInt32 bank = 0; bank < 4; bank++) for (uInt32 bank = 0; bank < 4; bank++)
bankInUse[bank] = in.getShort(); bankInUse[bank] = in.getShort();
in.getByteArray(myRAM, RAM_TOTAL_SIZE); in.getByteArray(myRAM, RAM_TOTAL_SIZE);
} } catch (...) {
catch (...)
{
cerr << "ERROR: CartridgeDASH::load" << endl; cerr << "ERROR: CartridgeDASH::load" << endl;
return false; return false;
} }

View File

@ -123,8 +123,7 @@ class System;
@author Andrew Davie @author Andrew Davie
*/ */
class CartridgeDASH: public Cartridge class CartridgeDASH: public Cartridge {
{
friend class CartridgeDASHWidget; friend class CartridgeDASHWidget;
public: public:
@ -211,7 +210,9 @@ class CartridgeDASH: public Cartridge
@return The name of the object @return The name of the object
*/ */
string name() const { return "CartridgeDASH"; } string name() const {
return "CartridgeDASH";
}
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
/** /**
@ -243,7 +244,7 @@ class CartridgeDASH: public Cartridge
bool poke(uInt16 address, uInt8 value); bool poke(uInt16 address, uInt8 value);
private: private:
uInt16 myCurrentBank; // whatever the LAST switched bank was... Int16 myCurrentBank; // whatever the LAST switched bank was...
uInt32 mySize; // Size of the ROM image uInt32 mySize; // Size of the ROM image
uInt8* myImage; // Pointer to a dynamically allocated ROM image of the cartridge uInt8* myImage; // Pointer to a dynamically allocated ROM image of the cartridge
@ -254,18 +255,20 @@ class CartridgeDASH: public Cartridge
static const uInt8 BANK_BITS = 5; // # bits for bank static const uInt8 BANK_BITS = 5; // # bits for bank
static const uInt8 BIT_BANK_MASK = (1 << BANK_BITS) - 1; // mask for those bits static const uInt8 BIT_BANK_MASK = (1 << BANK_BITS) - 1; // mask for those bits
static const uInt8 ROMRAM = 0x80; // flags ROM or RAM bank switching (1==RAM) static const uInt8 BITMASK_ROMRAM = 0x80; // flags ROM or RAM bank switching (1==RAM)
static const uInt16 RAM_BANK_COUNT = 32; static const uInt16 RAM_BANK_COUNT = 32;
static const uInt16 RAM_BANK_TO_POWER = 9; // 2^n = 512 static const uInt16 RAM_BANK_TO_POWER = 9; // 2^n = 512
static const uInt16 RAM_BANK_SIZE = (1 << RAM_BANK_TO_POWER); static const uInt16 RAM_BANK_SIZE = (1 << RAM_BANK_TO_POWER);
static const uInt16 BITMASK_RAM_BANK = (RAM_BANK_SIZE - 1);
static const uInt32 RAM_TOTAL_SIZE = RAM_BANK_COUNT * RAM_BANK_SIZE; static const uInt32 RAM_TOTAL_SIZE = RAM_BANK_COUNT * RAM_BANK_SIZE;
static const uInt16 ROM_BANK_TO_POWER = 10; // 2^n = 1024 static const uInt16 ROM_BANK_TO_POWER = 10; // 2^n = 1024
static const uInt16 ROM_BANK_SIZE = (1 << ROM_BANK_TO_POWER); static const uInt16 ROM_BANK_SIZE = (1 << ROM_BANK_TO_POWER);
static const uInt16 BITMASK_ROM_BANK = (ROM_BANK_SIZE -1);
static const uInt16 ROM_BANK_COUNT = 32; static const uInt16 ROM_BANK_COUNT = 32;
static const uInt16 ROM_BANK_MASK = (ROM_BANK_COUNT - 1); static const uInt16 BITMASK_ROM_BANK = (ROM_BANK_COUNT - 1);
static const uInt16 RAM_WRITE_OFFSET = 0x800; static const uInt16 RAM_WRITE_OFFSET = 0x800;