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) {
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 currentBank = bank & BIT_BANK_MASK; // Wrap around/restrict to valid range
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 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)
access.directPokeBase = &myRAM[startCurrentBank + (address & (RAM_BANK_SIZE - 1))];
else
access.directPeekBase = &myRAM[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
myCurrentSlice[0] = slice;
uInt16 offset = slice << 10;
uInt16 shift = System::PAGE_SHIFT;
// Setup the page access methods for the current bank
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.codeAccessBase = &myCodeAccessBase[offset + (address & 0x03FF)];
mySystem->setPageAccess(address >> shift, access);
mySystem->setPageAccess(address >> System::PAGE_SHIFT, access);
}
myBankChanged = true;
}
@ -151,16 +151,15 @@ void CartridgeE0::segmentOne(uInt16 slice)
// Remember the new slice
myCurrentSlice[1] = slice;
uInt16 offset = slice << 10;
uInt16 shift = System::PAGE_SHIFT;
// Setup the page access methods for the current bank
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.codeAccessBase = &myCodeAccessBase[offset + (address & 0x03FF)];
mySystem->setPageAccess(address >> shift, access);
mySystem->setPageAccess(address >> System::PAGE_SHIFT, access);
}
myBankChanged = true;
}

View File

@ -147,7 +147,7 @@ bool CartridgeE7::poke(uInt16 address, uInt8)
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
// way page accessing has been setup
return false;
@ -161,27 +161,26 @@ void CartridgeE7::bankRAM(uInt16 bank)
// Remember what bank we're in
myCurrentRAM = bank;
uInt16 offset = bank << 8;
uInt16 shift = System::PAGE_SHIFT;
// Setup the page access methods for the current bank
System::PageAccess access(this, System::PA_WRITE);
// 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.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
access.directPokeBase = 0;
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.codeAccessBase = &myCodeAccessBase[8192 + 1024 + offset + (k & 0x00FF)];
mySystem->setPageAccess(k >> shift, access);
mySystem->setPageAccess(k >> System::PAGE_SHIFT, access);
}
myBankChanged = true;
}

View File

@ -30,6 +30,9 @@ CartridgePPA::CartridgePPA(const uInt8* image, uInt32 size,
// Copy the ROM image into my buffer
memcpy(myImage, image, BSPF_min(8192u, size));
createCodeAccessBase(8192);
// Remember startup bank
myStartBank = 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -40,26 +43,95 @@ CartridgePPA::~CartridgePPA()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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
bank(0);
bank(myStartBank);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgePPA::install(System& 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)
{
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;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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;
}
@ -68,6 +140,8 @@ bool CartridgePPA::bank(uInt16 bank)
{
if(bankLocked() || bank > 15) return false;
myCurrentBank = bank;
segmentZero(ourBankOrg[bank].zero);
segmentOne(ourBankOrg[bank].one);
segmentTwo(ourBankOrg[bank].two);
@ -79,33 +153,101 @@ bool CartridgePPA::bank(uInt16 bank)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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)
{
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)
{
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)
{
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)
{
return false;
return false; // TODO
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt8* CartridgePPA::getImage(int& size) const
{
size = 8192;
size = 8195;
return myImage;
}
@ -115,7 +257,8 @@ bool CartridgePPA::save(Serializer& out) const
try
{
out.putString(name());
out.putByteArray(myCurrentSlice, 4);
out.putShort(myCurrentBank);
out.putByteArray(myRAM, 64);
}
catch(...)
{
@ -134,7 +277,10 @@ bool CartridgePPA::load(Serializer& in)
if(in.getString() != name())
return false;
in.getByteArray(myCurrentSlice, 4);
myCurrentBank = in.getShort();
in.getByteArray(myRAM, 64);
bank(myCurrentBank);
}
catch(...)
{
@ -157,7 +303,7 @@ CartridgePPA::BankOrg CartridgePPA::ourBankOrg[16] = {
{ 6, 0, 5, 1, false },
{ 0, 0, 1, 2, false },
{ 0, 1, 3, 2, false },
{ 4, 5, 6, 8, false },
{ 4, 5, 6, 7, false },
{ 7, 4, 3, 2, false },
{ 0, 0, 6, 7, true },
{ 0, 1, 7, 6, true },

View File

@ -97,6 +97,23 @@ class CartridgePPA : public Cartridge
*/
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.
@ -167,16 +184,8 @@ class CartridgePPA : public Cartridge
bool poke(uInt16 address, uInt8 value);
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.
Note that this method also takes care of mapping RAM.
@param slice The slice to map into the segment
*/
@ -206,11 +215,11 @@ class CartridgePPA : public Cartridge
void segmentThree(uInt8 slice, bool map3bytes);
private:
// Indicates the slice mapped into each of the four segments
uInt8 myCurrentSlice[4];
// Indicates which bank is currently active
uInt16 myCurrentBank;
// The 8K ROM image of the cartridge
uInt8 myImage[8192];
uInt8 myImage[8195];
// The 64 bytes RAM of the cartridge
uInt8 myRAM[64];