mirror of https://github.com/stella-emu/stella.git
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:
parent
6d6dd7632f
commit
40c8c81245
|
@ -24,11 +24,9 @@
|
||||||
#include "TIA.hxx"
|
#include "TIA.hxx"
|
||||||
#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,12 +92,11 @@ 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];
|
||||||
mySystem->setPageAccess(address>>shift, access);
|
mySystem->setPageAccess(address >> shift, access);
|
||||||
|
|
||||||
// TODO: Stephen: in this and other implementations we appear to be using "shift" as a system-dependant mangle for
|
// TODO: Stephen: in this and other implementations we appear to be using "shift" as a system-dependant mangle for
|
||||||
// different access types (byte/int/32bit) on different architectures. I think I understand that much. However,
|
// different access types (byte/int/32bit) on different architectures. I think I understand that much. However,
|
||||||
|
@ -112,7 +108,7 @@ void CartridgeDASH::install(System& system)
|
||||||
|
|
||||||
// Initialise bank values for the 4x 1K bank areas
|
// Initialise bank values for the 4x 1K bank areas
|
||||||
// This is used to reverse-lookup from address to bank location
|
// This is used to reverse-lookup from address to bank location
|
||||||
for(uInt32 b = 0; b < 3; b++)
|
for (uInt32 b = 0; b < 3; b++)
|
||||||
bankInUse[b] = BANK_UNDEFINED; // bank is undefined and inaccessible!
|
bankInUse[b] = BANK_UNDEFINED; // bank is undefined and inaccessible!
|
||||||
|
|
||||||
// Install pages for the startup bank into the first segment
|
// Install pages for the startup bank into the first segment
|
||||||
|
@ -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,15 +146,14 @@ 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'
|
||||||
// There are NO mirrored hotspots.
|
// There are NO mirrored hotspots.
|
||||||
|
|
||||||
if ( address == BANK_SWITCH_HOTSPOT)
|
if (address == BANK_SWITCH_HOTSPOT)
|
||||||
bank(value);
|
bank(value);
|
||||||
|
|
||||||
// Pass the poke through to the TIA. In a real Atari, both the cart and the
|
// Pass the poke through to the TIA. In a real Atari, both the cart and the
|
||||||
// TIA see the address lines, and both react accordingly. In Stella, each
|
// TIA see the address lines, and both react accordingly. In Stella, each
|
||||||
|
@ -172,9 +165,8 @@ 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
|
||||||
|
|
||||||
uInt16 shift = mySystem->pageShift();
|
uInt16 shift = mySystem->pageShift();
|
||||||
|
@ -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 true;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,252 +26,255 @@ class System;
|
||||||
#include "Cart.hxx"
|
#include "Cart.hxx"
|
||||||
|
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
class CartridgeDASHWidget;
|
class CartridgeDASHWidget;
|
||||||
// #include "CartDASHWidget.hxx"
|
// #include "CartDASHWidget.hxx"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Cartridge class for new tiling engine "Boulder Dash" format games with RAM.
|
Cartridge class for new tiling engine "Boulder Dash" format games with RAM.
|
||||||
Kind of a combination of 3F and 3E, with better switchability.
|
Kind of a combination of 3F and 3E, with better switchability.
|
||||||
B.Watson's Cart3E was used as a template for building this implementation.
|
B.Watson's Cart3E was used as a template for building this implementation.
|
||||||
|
|
||||||
Because a single bank number is used to define both the destination (0-3)
|
Because a single bank number is used to define both the destination (0-3)
|
||||||
AND the type (ROM/RAM) there are only 5 bits left to indicate the actual bank
|
AND the type (ROM/RAM) there are only 5 bits left to indicate the actual bank
|
||||||
number. This sets the limits of 32K ROM and 16K RAM.
|
number. This sets the limits of 32K ROM and 16K RAM.
|
||||||
|
|
||||||
D7 RAM/ROM flag (1=RAM)
|
D7 RAM/ROM flag (1=RAM)
|
||||||
D6D5 indicate the bank number (0-3)
|
D6D5 indicate the bank number (0-3)
|
||||||
D4D3D2D1D0 indicate the actual # (0-31) from the image/ram
|
D4D3D2D1D0 indicate the actual # (0-31) from the image/ram
|
||||||
|
|
||||||
Hotspot 0x3F is used for bank-switching, with the encoded bank # as above.
|
Hotspot 0x3F is used for bank-switching, with the encoded bank # as above.
|
||||||
|
|
||||||
ROM:
|
ROM:
|
||||||
|
|
||||||
In this scheme, the 4K address space is broken into four 1K ROM segments.
|
In this scheme, the 4K address space is broken into four 1K ROM segments.
|
||||||
living at 0x1000, 0x1400, 0x1800, 0x1C00 (or, same thing, 0xF000... etc.),
|
living at 0x1000, 0x1400, 0x1800, 0x1C00 (or, same thing, 0xF000... etc.),
|
||||||
and four 512 byte RAM segments, living at 0x1000, 0x1200, 0x1400, 0x1600
|
and four 512 byte RAM segments, living at 0x1000, 0x1200, 0x1400, 0x1600
|
||||||
with write-mirrors +0x800 of these. The last 1K ROM ($FC00-$FFFF) segment
|
with write-mirrors +0x800 of these. The last 1K ROM ($FC00-$FFFF) segment
|
||||||
is initialised to point to the FIRST 1K of the ROM image, but it may be
|
is initialised to point to the FIRST 1K of the ROM image, but it may be
|
||||||
switched out at any time. Note, this is DIFFERENT to 3E which switches in
|
switched out at any time. Note, this is DIFFERENT to 3E which switches in
|
||||||
the UPPER bank and this bank is fixed. This allows variable sized ROM
|
the UPPER bank and this bank is fixed. This allows variable sized ROM
|
||||||
without having to detect size. First bank (0) in ROM is the default fixed
|
without having to detect size. First bank (0) in ROM is the default fixed
|
||||||
bank mapped to $FC00.
|
bank mapped to $FC00.
|
||||||
|
|
||||||
The system requires the reset vectors to be valid on a reset, so either the
|
The system requires the reset vectors to be valid on a reset, so either the
|
||||||
hardware first switches in the first bank, or the programmer must ensure
|
hardware first switches in the first bank, or the programmer must ensure
|
||||||
that the reset vector is present in ALL ROM banks which might be switched
|
that the reset vector is present in ALL ROM banks which might be switched
|
||||||
into the last bank area. Currently the latter (programmer onus) is required,
|
into the last bank area. Currently the latter (programmer onus) is required,
|
||||||
but it would be nice for the cartridge hardware to auto-switch on reset.
|
but it would be nice for the cartridge hardware to auto-switch on reset.
|
||||||
|
|
||||||
ROM switching (write of block+bank number to $3F) D7=0 and D6D5 upper 2 bits of bank #
|
ROM switching (write of block+bank number to $3F) D7=0 and D6D5 upper 2 bits of bank #
|
||||||
indicates the destination segment (0-3, corresponding to $F000, $F400, $F800, $FC00),
|
indicates the destination segment (0-3, corresponding to $F000, $F400, $F800, $FC00),
|
||||||
and lower 5 bits indicate the 1K bank to switch in. Can handle 32 x 1K ROM banks (32K total).
|
and lower 5 bits indicate the 1K bank to switch in. Can handle 32 x 1K ROM banks (32K total).
|
||||||
|
|
||||||
D7 D6 D5 D4D3D2D1D0
|
D7 D6 D5 D4D3D2D1D0
|
||||||
0 0 0 x x x x x switch a 1K ROM bank xxxxx to $F000
|
0 0 0 x x x x x switch a 1K ROM bank xxxxx to $F000
|
||||||
0 0 1 switch a 1K ROM bank xxxxx to $F400
|
0 0 1 switch a 1K ROM bank xxxxx to $F400
|
||||||
0 1 0 switch a 1K ROM bank xxxxx to $F800
|
0 1 0 switch a 1K ROM bank xxxxx to $F800
|
||||||
0 1 1 switch a 1K ROM bank xxxxx to $FC00
|
0 1 1 switch a 1K ROM bank xxxxx to $FC00
|
||||||
|
|
||||||
RAM switching (write of segment+bank number to $3F) with D7=1 and D6D5 upper 2 bits of bank #
|
RAM switching (write of segment+bank number to $3F) with D7=1 and D6D5 upper 2 bits of bank #
|
||||||
indicates the destination RAM segment (0-3, corresponding to $F000, $F200, $F400, $F600).
|
indicates the destination RAM segment (0-3, corresponding to $F000, $F200, $F400, $F600).
|
||||||
Note that this allows contiguous 2K of RAM to be configured by setting 4 consecutive RAM segments
|
Note that this allows contiguous 2K of RAM to be configured by setting 4 consecutive RAM segments
|
||||||
each 512 bytes with consecutive addresses. However, as the write address of RAM is +0x800, this
|
each 512 bytes with consecutive addresses. However, as the write address of RAM is +0x800, this
|
||||||
invalidates ROM access as described below.
|
invalidates ROM access as described below.
|
||||||
|
|
||||||
can handle 32 x 512 byte RAM banks (16K total)
|
can handle 32 x 512 byte RAM banks (16K total)
|
||||||
|
|
||||||
D7 D6 D5 D4D3D2D1D0
|
D7 D6 D5 D4D3D2D1D0
|
||||||
1 0 0 x x x x x switch a 512 byte RAM bank xxxxx to $F000 with write @ $F800
|
1 0 0 x x x x x switch a 512 byte RAM bank xxxxx to $F000 with write @ $F800
|
||||||
0 1 switch a 512 byte RAM bank xxxxx to $F200 with write @ $FA00
|
0 1 switch a 512 byte RAM bank xxxxx to $F200 with write @ $FA00
|
||||||
1 0 switch a 512 byte RAM bank xxxxx to $F400 with write @ $FC00
|
1 0 switch a 512 byte RAM bank xxxxx to $F400 with write @ $FC00
|
||||||
1 1 switch a 512 byte RAM bank xxxxx to $F600 with write @ $FE00
|
1 1 switch a 512 byte RAM bank xxxxx to $F600 with write @ $FE00
|
||||||
|
|
||||||
It is possible to switch multiple RAM banks and ROM banks together
|
It is possible to switch multiple RAM banks and ROM banks together
|
||||||
|
|
||||||
For example,
|
For example,
|
||||||
F000-F1FF RAM bank A (512 byte READ)
|
F000-F1FF RAM bank A (512 byte READ)
|
||||||
F200-F3FF high 512 bytes of ROM bank previously loaded at F000
|
F200-F3FF high 512 bytes of ROM bank previously loaded at F000
|
||||||
F400 ROM bank 0 (1K)
|
F400 ROM bank 0 (1K)
|
||||||
F800 RAM bank A (512 byte WRITE)
|
F800 RAM bank A (512 byte WRITE)
|
||||||
FA00-FBFF high 512 bytes of ROM bank previously loaded at F400
|
FA00-FBFF high 512 bytes of ROM bank previously loaded at F400
|
||||||
FC00 ROM bank 1
|
FC00 ROM bank 1
|
||||||
|
|
||||||
This example shows 512 bytes of RAM, and 2 1K ROM banks and two 512 byte ROM
|
This example shows 512 bytes of RAM, and 2 1K ROM banks and two 512 byte ROM
|
||||||
bank halves.
|
bank halves.
|
||||||
|
|
||||||
Switching RAM blocks (D7D6 of $3E) partially invalidates ROM blocks, as below...
|
Switching RAM blocks (D7D6 of $3E) partially invalidates ROM blocks, as below...
|
||||||
|
|
||||||
RAM block Invalidates ROM block
|
RAM block Invalidates ROM block
|
||||||
0 0 (lower half), 2 (lower half)
|
0 0 (lower half), 2 (lower half)
|
||||||
1 0 (upper half), 2 (upper half)
|
1 0 (upper half), 2 (upper half)
|
||||||
2 1 (lower half), 3 (upper half)
|
2 1 (lower half), 3 (upper half)
|
||||||
3 1 (upper half), 3 (lower half)
|
3 1 (upper half), 3 (lower half)
|
||||||
|
|
||||||
For example, RAM block 1 uses address $F200-$F3FF and $FA00-$FBFF
|
For example, RAM block 1 uses address $F200-$F3FF and $FA00-$FBFF
|
||||||
ROM block 0 uses address $F000-$F3FF, and ROM block 2 uses address $F800-$FBFF
|
ROM block 0 uses address $F000-$F3FF, and ROM block 2 uses address $F800-$FBFF
|
||||||
Switching in RAM block 1 makes F200-F3FF ROM inaccessible, however F000-F1FF is
|
Switching in RAM block 1 makes F200-F3FF ROM inaccessible, however F000-F1FF is
|
||||||
still readable. So, care must be paid.
|
still readable. So, care must be paid.
|
||||||
|
|
||||||
TODO: THe partial reading of ROM blocks switched out by RAM is not yet implemented!!
|
TODO: THe partial reading of ROM blocks switched out by RAM is not yet implemented!!
|
||||||
|
|
||||||
This crazy RAM layout is useful as it allows contiguous RAM to be switched in,
|
This crazy RAM layout is useful as it allows contiguous RAM to be switched in,
|
||||||
up to 2K in one sequentially accessible block. This means you CAN have 2K of
|
up to 2K in one sequentially accessible block. This means you CAN have 2K of
|
||||||
consecutive RAM. If you don't detect ROM write area, then you would have NO ROM
|
consecutive RAM. If you don't detect ROM write area, then you would have NO ROM
|
||||||
switched in (don't forget to copy your reset vectors!)
|
switched in (don't forget to copy your reset vectors!)
|
||||||
|
|
||||||
@author Andrew Davie
|
@author Andrew Davie
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class CartridgeDASH: public Cartridge
|
class CartridgeDASH: public Cartridge {
|
||||||
{
|
|
||||||
friend class CartridgeDASHWidget;
|
friend class CartridgeDASHWidget;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
Create a new cartridge using the specified image and size
|
Create a new cartridge using the specified image and size
|
||||||
|
|
||||||
@param image Pointer to the ROM image
|
@param image Pointer to the ROM image
|
||||||
@param size The size of the ROM image
|
@param size The size of the ROM image
|
||||||
@param settings A reference to the various settings (read-only)
|
@param settings A reference to the various settings (read-only)
|
||||||
*/
|
*/
|
||||||
CartridgeDASH(const uInt8* image, uInt32 size, const Settings& settings);
|
CartridgeDASH(const uInt8* image, uInt32 size, const Settings& settings);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Destructor
|
Destructor
|
||||||
*/
|
*/
|
||||||
virtual ~CartridgeDASH();
|
virtual ~CartridgeDASH();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
Reset device to its power-on state
|
Reset device to its power-on state
|
||||||
*/
|
*/
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Install cartridge in the specified system. Invoked by the system
|
Install cartridge in the specified system. Invoked by the system
|
||||||
when the cartridge is attached to it.
|
when the cartridge is attached to it.
|
||||||
|
|
||||||
@param system The system the device should install itself in
|
@param system The system the device should install itself in
|
||||||
*/
|
*/
|
||||||
void install(System& system);
|
void install(System& system);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Install pages for the specified bank in the system.
|
Install pages for the specified bank in the system.
|
||||||
|
|
||||||
@param bank The bank that should be installed in the system
|
@param bank The bank that should be installed in the system
|
||||||
*/
|
*/
|
||||||
bool bank(uInt16 bank);
|
bool bank(uInt16 bank);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get the current bank.
|
Get the current bank.
|
||||||
*/
|
*/
|
||||||
uInt16 bank() const;
|
uInt16 bank() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Query the number of banks supported by the cartridge.
|
Query the number of banks supported by the cartridge.
|
||||||
*/
|
*/
|
||||||
uInt16 bankCount() const;
|
uInt16 bankCount() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Patch the cartridge ROM.
|
Patch the cartridge ROM.
|
||||||
|
|
||||||
@param address The ROM address to patch
|
@param address The ROM address to patch
|
||||||
@param value The value to place into the address
|
@param value The value to place into the address
|
||||||
@return Success or failure of the patch operation
|
@return Success or failure of the patch operation
|
||||||
*/
|
*/
|
||||||
bool patch(uInt16 address, uInt8 value);
|
bool patch(uInt16 address, uInt8 value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Access the internal ROM image for this cartridge.
|
Access the internal ROM image for this cartridge.
|
||||||
|
|
||||||
@param size Set to the size of the internal ROM image data
|
@param size Set to the size of the internal ROM image data
|
||||||
@return A pointer to the internal ROM image data
|
@return A pointer to the internal ROM image data
|
||||||
*/
|
*/
|
||||||
const uInt8* getImage(int& size) const;
|
const uInt8* getImage(int& size) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Save the current state of this cart to the given Serializer.
|
Save the current state of this cart to the given Serializer.
|
||||||
|
|
||||||
@param out The Serializer object to use
|
@param out The Serializer object to use
|
||||||
@return False on any errors, else true
|
@return False on any errors, else true
|
||||||
*/
|
*/
|
||||||
bool save(Serializer& out) const;
|
bool save(Serializer& out) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Load the current state of this cart from the given Serializer.
|
Load the current state of this cart from the given Serializer.
|
||||||
|
|
||||||
@param in The Serializer object to use
|
@param in The Serializer object to use
|
||||||
@return False on any errors, else true
|
@return False on any errors, else true
|
||||||
*/
|
*/
|
||||||
bool load(Serializer& in);
|
bool load(Serializer& in);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get a descriptor for the device name (used in error checking).
|
Get a descriptor for the device name (used in error checking).
|
||||||
|
|
||||||
@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
|
||||||
/**
|
/**
|
||||||
Get debugger widget responsible for accessing the inner workings
|
Get debugger widget responsible for accessing the inner workings
|
||||||
of the cart.
|
of the cart.
|
||||||
*/
|
*/
|
||||||
CartDebugWidget* debugWidget(GuiObject* boss, const GUI::Font& lfont,
|
CartDebugWidget* debugWidget(GuiObject* boss, const GUI::Font& lfont,
|
||||||
const GUI::Font& nfont, int x, int y, int w, int h)
|
const GUI::Font& nfont, int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
return 0;//new CartridgeDASHWidget(boss, lfont, nfont, x, y, w, h, *this);
|
return 0; //new CartridgeDASHWidget(boss, lfont, nfont, x, y, w, h, *this);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
Get the byte at the specified address
|
Get the byte at the specified address
|
||||||
|
|
||||||
@return The byte at the specified address
|
@return The byte at the specified address
|
||||||
*/
|
*/
|
||||||
uInt8 peek(uInt16 address);
|
uInt8 peek(uInt16 address);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Change the byte at the specified address to the given value
|
Change the byte at the specified address to the given value
|
||||||
|
|
||||||
@param address The address where the value should be stored
|
@param address The address where the value should be stored
|
||||||
@param value The value to be stored at the address
|
@param value The value to be stored at the address
|
||||||
@return True if the poke changed the device address space, else false
|
@return True if the poke changed the device address space, else false
|
||||||
*/
|
*/
|
||||||
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
|
||||||
|
|
||||||
Int16 bankInUse[4]; // bank being used for ROM/RAM (-1 = undefined)
|
Int16 bankInUse[4]; // bank being used for ROM/RAM (-1 = undefined)
|
||||||
|
|
||||||
static const uInt16 BANK_SWITCH_HOTSPOT = 0x3F; // writes to this address cause bankswitching
|
static const uInt16 BANK_SWITCH_HOTSPOT = 0x3F; // writes to this address cause bankswitching
|
||||||
|
|
||||||
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 uInt32 RAM_TOTAL_SIZE = RAM_BANK_COUNT * RAM_BANK_SIZE;
|
static const uInt16 BITMASK_RAM_BANK = (RAM_BANK_SIZE - 1);
|
||||||
|
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;
|
||||||
|
|
||||||
static const Int16 BANK_UNDEFINED = -1; // bank is undefined and inaccessible
|
static const Int16 BANK_UNDEFINED = -1; // bank is undefined and inaccessible
|
||||||
|
|
||||||
uInt8 myRAM[RAM_TOTAL_SIZE];
|
uInt8 myRAM[RAM_TOTAL_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue