mirror of https://github.com/stella-emu/stella.git
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:
parent
10fbcdc00c
commit
fdc54072f4
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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];
|
||||
|
|
Loading…
Reference in New Issue