From fdc54072f4a519de74f9ba451c31269a6cf1c2a7 Mon Sep 17 00:00:00 2001 From: stephena Date: Fri, 21 Nov 2014 23:01:06 +0000 Subject: [PATCH] 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 --- src/emucore/CartDASH.cxx | 6 +- src/emucore/CartE0.cxx | 11 ++- src/emucore/CartE7.cxx | 11 ++- src/emucore/CartPPA.cxx | 160 +++++++++++++++++++++++++++++++++++++-- src/emucore/CartPPA.hxx | 31 +++++--- 5 files changed, 185 insertions(+), 34 deletions(-) diff --git a/src/emucore/CartDASH.cxx b/src/emucore/CartDASH.cxx index b37acd07f..6bbd92496 100644 --- a/src/emucore/CartDASH.cxx +++ b/src/emucore/CartDASH.cxx @@ -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); } } diff --git a/src/emucore/CartE0.cxx b/src/emucore/CartE0.cxx index 2d05c355b..dc7c4183f 100644 --- a/src/emucore/CartE0.cxx +++ b/src/emucore/CartE0.cxx @@ -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; } diff --git a/src/emucore/CartE7.cxx b/src/emucore/CartE7.cxx index 230879746..b6599f17d 100644 --- a/src/emucore/CartE7.cxx +++ b/src/emucore/CartE7.cxx @@ -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; } diff --git a/src/emucore/CartPPA.cxx b/src/emucore/CartPPA.cxx index 891a6ec42..54e50bb46 100644 --- a/src/emucore/CartPPA.cxx +++ b/src/emucore/CartPPA.cxx @@ -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 }, diff --git a/src/emucore/CartPPA.hxx b/src/emucore/CartPPA.hxx index 1028101d3..cd4b3a398 100644 --- a/src/emucore/CartPPA.hxx +++ b/src/emucore/CartPPA.hxx @@ -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];