Second pass at the new experimental scheme; it's a little closer now.

git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@3096 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2014-11-21 23:01:06 +00:00
parent 10fbcdc00c
commit fdc54072f4
5 changed files with 185 additions and 34 deletions

View File

@ -178,8 +178,6 @@ bool CartridgeDASH::bankRAM(uInt8 bank) {
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeDASH::bankRAMSlot(uInt16 bank) { void CartridgeDASH::bankRAMSlot(uInt16 bank) {
uInt16 shift = System::PAGE_SHIFT;
uInt16 bankNumber = (bank >> BANK_BITS) & 3; // which bank # we are switching TO (BITS D6,D7) to 512 byte block uInt16 bankNumber = (bank >> BANK_BITS) & 3; // which bank # we are switching TO (BITS D6,D7) to 512 byte block
uInt16 currentBank = bank & BIT_BANK_MASK; // Wrap around/restrict to valid range uInt16 currentBank = bank & BIT_BANK_MASK; // Wrap around/restrict to valid range
bool upper = bank & BITMASK_LOWERUPPER; // is this the read or write port bool upper = bank & BITMASK_LOWERUPPER; // is this the read or write port
@ -204,13 +202,13 @@ void CartridgeDASH::bankRAMSlot(uInt16 bank) {
uInt32 start = 0x1000 + (bankNumber << RAM_BANK_TO_POWER) + (upper ? RAM_WRITE_OFFSET : 0); uInt32 start = 0x1000 + (bankNumber << RAM_BANK_TO_POWER) + (upper ? RAM_WRITE_OFFSET : 0);
uInt32 end = start + RAM_BANK_SIZE - 1; uInt32 end = start + RAM_BANK_SIZE - 1;
for (uInt32 address = start; address <= end; address += (1 << shift)) { for (uInt32 address = start; address <= end; address += (1 << System::PAGE_SHIFT)) {
if(upper) if(upper)
access.directPokeBase = &myRAM[startCurrentBank + (address & (RAM_BANK_SIZE - 1))]; access.directPokeBase = &myRAM[startCurrentBank + (address & (RAM_BANK_SIZE - 1))];
else else
access.directPeekBase = &myRAM[startCurrentBank + (address & (RAM_BANK_SIZE - 1))]; access.directPeekBase = &myRAM[startCurrentBank + (address & (RAM_BANK_SIZE - 1))];
access.codeAccessBase = &myCodeAccessBase[mySize + startCurrentBank + (address & (RAM_BANK_SIZE - 1))]; access.codeAccessBase = &myCodeAccessBase[mySize + startCurrentBank + (address & (RAM_BANK_SIZE - 1))];
mySystem->setPageAccess(address >> shift, access); mySystem->setPageAccess(address >> System::PAGE_SHIFT, access);
} }
} }

View File

@ -129,16 +129,16 @@ void CartridgeE0::segmentZero(uInt16 slice)
// Remember the new slice // Remember the new slice
myCurrentSlice[0] = slice; myCurrentSlice[0] = slice;
uInt16 offset = slice << 10; uInt16 offset = slice << 10;
uInt16 shift = System::PAGE_SHIFT;
// Setup the page access methods for the current bank // Setup the page access methods for the current bank
System::PageAccess access(this, System::PA_READ); System::PageAccess access(this, System::PA_READ);
for(uInt32 address = 0x1000; address < 0x1400; address += (1 << shift)) for(uInt32 address = 0x1000; address < 0x1400;
address += (1 << System::PAGE_SHIFT))
{ {
access.directPeekBase = &myImage[offset + (address & 0x03FF)]; access.directPeekBase = &myImage[offset + (address & 0x03FF)];
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x03FF)]; access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x03FF)];
mySystem->setPageAccess(address >> shift, access); mySystem->setPageAccess(address >> System::PAGE_SHIFT, access);
} }
myBankChanged = true; myBankChanged = true;
} }
@ -151,16 +151,15 @@ void CartridgeE0::segmentOne(uInt16 slice)
// Remember the new slice // Remember the new slice
myCurrentSlice[1] = slice; myCurrentSlice[1] = slice;
uInt16 offset = slice << 10; uInt16 offset = slice << 10;
uInt16 shift = System::PAGE_SHIFT;
// Setup the page access methods for the current bank // Setup the page access methods for the current bank
System::PageAccess access(this, System::PA_READ); System::PageAccess access(this, System::PA_READ);
for(uInt32 address = 0x1400; address < 0x1800; address += (1 << shift)) for(uInt32 address = 0x1400; address < 0x1800; address += (1 << System::PAGE_SHIFT))
{ {
access.directPeekBase = &myImage[offset + (address & 0x03FF)]; access.directPeekBase = &myImage[offset + (address & 0x03FF)];
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x03FF)]; access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x03FF)];
mySystem->setPageAccess(address >> shift, access); mySystem->setPageAccess(address >> System::PAGE_SHIFT, access);
} }
myBankChanged = true; myBankChanged = true;
} }

View File

@ -147,7 +147,7 @@ bool CartridgeE7::poke(uInt16 address, uInt8)
bankRAM(address & 0x0003); bankRAM(address & 0x0003);
} }
// NOTE: This does not handle writing to RAM, however, this // NOTE: This does not handle writing to RAM, however, this
// function should never be called for RAM because of the // function should never be called for RAM because of the
// way page accessing has been setup // way page accessing has been setup
return false; return false;
@ -161,27 +161,26 @@ void CartridgeE7::bankRAM(uInt16 bank)
// Remember what bank we're in // Remember what bank we're in
myCurrentRAM = bank; myCurrentRAM = bank;
uInt16 offset = bank << 8; uInt16 offset = bank << 8;
uInt16 shift = System::PAGE_SHIFT;
// Setup the page access methods for the current bank // Setup the page access methods for the current bank
System::PageAccess access(this, System::PA_WRITE); System::PageAccess access(this, System::PA_WRITE);
// Set the page accessing method for the 256 bytes of RAM writing pages // Set the page accessing method for the 256 bytes of RAM writing pages
for(uInt32 j = 0x1800; j < 0x1900; j += (1 << shift)) for(uInt32 j = 0x1800; j < 0x1900; j += (1 << System::PAGE_SHIFT))
{ {
access.directPokeBase = &myRAM[1024 + offset + (j & 0x00FF)]; access.directPokeBase = &myRAM[1024 + offset + (j & 0x00FF)];
access.codeAccessBase = &myCodeAccessBase[8192 + 1024 + offset + (j & 0x00FF)]; access.codeAccessBase = &myCodeAccessBase[8192 + 1024 + offset + (j & 0x00FF)];
mySystem->setPageAccess(j >> shift, access); mySystem->setPageAccess(j >> System::PAGE_SHIFT, access);
} }
// Set the page accessing method for the 256 bytes of RAM reading pages // Set the page accessing method for the 256 bytes of RAM reading pages
access.directPokeBase = 0; access.directPokeBase = 0;
access.type = System::PA_READ; access.type = System::PA_READ;
for(uInt32 k = 0x1900; k < 0x1A00; k += (1 << shift)) for(uInt32 k = 0x1900; k < 0x1A00; k += (1 << System::PAGE_SHIFT))
{ {
access.directPeekBase = &myRAM[1024 + offset + (k & 0x00FF)]; access.directPeekBase = &myRAM[1024 + offset + (k & 0x00FF)];
access.codeAccessBase = &myCodeAccessBase[8192 + 1024 + offset + (k & 0x00FF)]; access.codeAccessBase = &myCodeAccessBase[8192 + 1024 + offset + (k & 0x00FF)];
mySystem->setPageAccess(k >> shift, access); mySystem->setPageAccess(k >> System::PAGE_SHIFT, access);
} }
myBankChanged = true; myBankChanged = true;
} }

View File

@ -30,6 +30,9 @@ CartridgePPA::CartridgePPA(const uInt8* image, uInt32 size,
// Copy the ROM image into my buffer // Copy the ROM image into my buffer
memcpy(myImage, image, BSPF_min(8192u, size)); memcpy(myImage, image, BSPF_min(8192u, size));
createCodeAccessBase(8192); createCodeAccessBase(8192);
// Remember startup bank
myStartBank = 0;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -40,26 +43,95 @@ CartridgePPA::~CartridgePPA()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgePPA::reset() void CartridgePPA::reset()
{ {
// Initialize RAM
if(mySettings.getBool("ramrandom"))
for(uInt32 i = 0; i < 64; ++i)
myRAM[i] = mySystem->randGenerator().next();
else
memset(myRAM, 0, 64);
// Setup segments to some default slices // Setup segments to some default slices
bank(0); bank(myStartBank);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgePPA::install(System& system) void CartridgePPA::install(System& system)
{ {
mySystem = &system; mySystem = &system;
bank(0);
System::PageAccess access(this, System::PA_READ);
// Set the page accessing method for the RAM writing pages
access.type = System::PA_WRITE;
for(uInt32 j = 0x1040; j < 0x1080; j += (1 << System::PAGE_SHIFT))
{
access.directPokeBase = &myRAM[j & 0x003F];
access.codeAccessBase = &myCodeAccessBase[0x80 + (j & 0x003F)];
mySystem->setPageAccess(j >> System::PAGE_SHIFT, access);
}
// Set the page accessing method for the RAM reading pages
// The first 48 bytes map directly to RAM
access.directPeekBase = access.directPokeBase = 0;
access.type = System::PA_READ;
for(uInt32 k = 0x1000; k < 0x1030; k += (1 << System::PAGE_SHIFT))
{
access.directPeekBase = &myRAM[k & 0x003F];
access.codeAccessBase = &myCodeAccessBase[k & 0x003F];
mySystem->setPageAccess(k >> System::PAGE_SHIFT, access);
}
access.directPeekBase = access.directPokeBase = 0;
// The last 16 bytes are hotspots, so they're handled separately
for(uInt32 k = 0x1030; k < 0x1040; k += (1 << System::PAGE_SHIFT))
{
access.codeAccessBase = &myCodeAccessBase[k & 0x003F];
mySystem->setPageAccess(k >> System::PAGE_SHIFT, access);
}
// Setup segments to some default slices
bank(myStartBank);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgePPA::peek(uInt16 address) uInt8 CartridgePPA::peek(uInt16 address)
{ {
uInt16 peekAddress = address;
address &= 0x0FFF;
if(address < 0x0040) // RAM read port
{
// Hotspots at $30 - $3F
bank(address & 0x000F);
// Read from RAM
return myRAM[address & 0x003F];
}
else if(address < 0x0080) // RAM write port
{
// Reading from the write port @ $1040 - $107F triggers an unwanted write
uInt8 value = mySystem->getDataBusState(0xFF);
if(bankLocked())
return value;
else
{
triggerReadFromWritePort(peekAddress);
return myRAM[address & 0x003F] = value;
}
}
// NOTE: This does not handle reading from RAM, however, this
// function should never be called for ROM because of the
// way page accessing has been setup
return 0; return 0;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgePPA::poke(uInt16 address, uInt8) bool CartridgePPA::poke(uInt16 address, uInt8)
{ {
// NOTE: This does not handle writing to RAM, however, this
// function should never be called for RAM because of the
// way page accessing has been setup
return false; return false;
} }
@ -68,6 +140,8 @@ bool CartridgePPA::bank(uInt16 bank)
{ {
if(bankLocked() || bank > 15) return false; if(bankLocked() || bank > 15) return false;
myCurrentBank = bank;
segmentZero(ourBankOrg[bank].zero); segmentZero(ourBankOrg[bank].zero);
segmentOne(ourBankOrg[bank].one); segmentOne(ourBankOrg[bank].one);
segmentTwo(ourBankOrg[bank].two); segmentTwo(ourBankOrg[bank].two);
@ -79,33 +153,101 @@ bool CartridgePPA::bank(uInt16 bank)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgePPA::segmentZero(uInt8 slice) void CartridgePPA::segmentZero(uInt8 slice)
{ {
cerr << __func__ << " : slice " << (int)slice << endl;
uInt16 offset = slice << 10;
System::PageAccess access(this, System::PA_READ);
// Skip first 128 bytes; it is always RAM
for(uInt32 address = 0x1080; address < 0x1400;
address += (1 << System::PAGE_SHIFT))
{
access.directPeekBase = &myImage[offset + (address & 0x03FF)];
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x03FF)];
mySystem->setPageAccess(address >> System::PAGE_SHIFT, access);
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgePPA::segmentOne(uInt8 slice) void CartridgePPA::segmentOne(uInt8 slice)
{ {
cerr << __func__ << " : slice " << (int)slice << endl;
uInt16 offset = slice << 10;
System::PageAccess access(this, System::PA_READ);
for(uInt32 address = 0x1400; address < 0x1800;
address += (1 << System::PAGE_SHIFT))
{
access.directPeekBase = &myImage[offset + (address & 0x03FF)];
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x03FF)];
mySystem->setPageAccess(address >> System::PAGE_SHIFT, access);
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgePPA::segmentTwo(uInt8 slice) void CartridgePPA::segmentTwo(uInt8 slice)
{ {
cerr << __func__ << " : slice " << (int)slice << endl;
uInt16 offset = slice << 10;
System::PageAccess access(this, System::PA_READ);
for(uInt32 address = 0x1800; address < 0x1C00;
address += (1 << System::PAGE_SHIFT))
{
access.directPeekBase = &myImage[offset + (address & 0x03FF)];
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x03FF)];
mySystem->setPageAccess(address >> System::PAGE_SHIFT, access);
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgePPA::segmentThree(uInt8 slice, bool map3bytes) void CartridgePPA::segmentThree(uInt8 slice, bool map3bytes)
{ {
cerr << __func__ << ": slice " << (int)slice << endl;
uInt16 offset = slice << 10;
// Make a copy of the address space pointed to by the slice
// Then map in the extra 3 bytes, if required
memcpy(mySegment3, myImage+offset, 1024);
if(map3bytes)
{
mySegment3[0x3FC] = myImage[0x2000+0];
mySegment3[0x3FD] = myImage[0x2000+1];
mySegment3[0x3FE] = myImage[0x2000+2];
}
System::PageAccess access(this, System::PA_READ);
for(uInt32 address = 0x1C00; address < 0x2000;
address += (1 << System::PAGE_SHIFT))
{
access.directPeekBase = &mySegment3[address & 0x03FF];
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x03FF)];
mySystem->setPageAccess(address >> System::PAGE_SHIFT, access);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgePPA::getBank() const
{
return myCurrentBank;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgePPA::bankCount() const
{
return 8;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgePPA::patch(uInt16 address, uInt8 value) bool CartridgePPA::patch(uInt16 address, uInt8 value)
{ {
return false; return false; // TODO
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt8* CartridgePPA::getImage(int& size) const const uInt8* CartridgePPA::getImage(int& size) const
{ {
size = 8192; size = 8195;
return myImage; return myImage;
} }
@ -115,7 +257,8 @@ bool CartridgePPA::save(Serializer& out) const
try try
{ {
out.putString(name()); out.putString(name());
out.putByteArray(myCurrentSlice, 4); out.putShort(myCurrentBank);
out.putByteArray(myRAM, 64);
} }
catch(...) catch(...)
{ {
@ -134,7 +277,10 @@ bool CartridgePPA::load(Serializer& in)
if(in.getString() != name()) if(in.getString() != name())
return false; return false;
in.getByteArray(myCurrentSlice, 4); myCurrentBank = in.getShort();
in.getByteArray(myRAM, 64);
bank(myCurrentBank);
} }
catch(...) catch(...)
{ {
@ -157,7 +303,7 @@ CartridgePPA::BankOrg CartridgePPA::ourBankOrg[16] = {
{ 6, 0, 5, 1, false }, { 6, 0, 5, 1, false },
{ 0, 0, 1, 2, false }, { 0, 0, 1, 2, false },
{ 0, 1, 3, 2, false }, { 0, 1, 3, 2, false },
{ 4, 5, 6, 8, false }, { 4, 5, 6, 7, false },
{ 7, 4, 3, 2, false }, { 7, 4, 3, 2, false },
{ 0, 0, 6, 7, true }, { 0, 0, 6, 7, true },
{ 0, 1, 7, 6, true }, { 0, 1, 7, 6, true },

View File

@ -97,6 +97,23 @@ class CartridgePPA : public Cartridge
*/ */
void install(System& system); void install(System& system);
/**
Install pages for the specified bank in the system.
@param bank The bank that should be installed in the system
*/
bool bank(uInt16 bank);
/**
Get the current bank.
*/
uInt16 getBank() const;
/**
Query the number of banks supported by the cartridge.
*/
uInt16 bankCount() const;
/** /**
Patch the cartridge ROM. Patch the cartridge ROM.
@ -167,16 +184,8 @@ class CartridgePPA : public Cartridge
bool poke(uInt16 address, uInt8 value); bool poke(uInt16 address, uInt8 value);
private: private:
/**
Install slices for all four segments according to the bank index.
@param bank Index into BankOrg structure
*/
bool bank(uInt16 bank);
/** /**
Install the specified slice for segment zero. Install the specified slice for segment zero.
Note that this method also takes care of mapping RAM.
@param slice The slice to map into the segment @param slice The slice to map into the segment
*/ */
@ -206,11 +215,11 @@ class CartridgePPA : public Cartridge
void segmentThree(uInt8 slice, bool map3bytes); void segmentThree(uInt8 slice, bool map3bytes);
private: private:
// Indicates the slice mapped into each of the four segments // Indicates which bank is currently active
uInt8 myCurrentSlice[4]; uInt16 myCurrentBank;
// The 8K ROM image of the cartridge // The 8K ROM image of the cartridge
uInt8 myImage[8192]; uInt8 myImage[8195];
// The 64 bytes RAM of the cartridge // The 64 bytes RAM of the cartridge
uInt8 myRAM[64]; uInt8 myRAM[64];