diff --git a/src/debugger/gui/CartCDFInfoWidget.cxx b/src/debugger/gui/CartCDFInfoWidget.cxx index b56c61ca1..ab183af33 100644 --- a/src/debugger/gui/CartCDFInfoWidget.cxx +++ b/src/debugger/gui/CartCDFInfoWidget.cxx @@ -23,16 +23,28 @@ CartridgeCDFInfoWidget::CartridgeCDFInfoWidget( int x, int y, int w, int h, CartridgeCDF& cart) : CartDebugWidget(boss, lfont, nfont, x, y, w, h) { - uInt16 size = 8 * 4096; - + uInt32 size; ostringstream info; - info << describeCDFVersion(cart.myCDFSubtype) << " cartridge\n" - << "32K ROM, seven 4K banks are accessible to 2600\n" - << "8K CDF RAM\n" - << "CDF registers accessible @ $FFF0 - $FFF3\n" - << "Banks accessible at hotspots $FFF5 to $FFFB\n" - << "Startup bank = " << cart.startBank() << "\n"; + if (cart.myCDFSubtype == CartridgeCDF::CDFSubtype::CDFJplus) { + size = 512 * 1024; + info << describeCDFVersion(cart.myCDFSubtype) << " cartridge\n" + << "512K ROM (seven 4K banks are accessible to 2600)\n" + << "32K RAM\n" + << "Functions accessible @ $FFF0 - $FFF3\n" + << "Banks accessible @ $FFF4 to $FFFB\n" + << "Startup bank = " << cart.startBank() << "\n"; + + } else { + size = 8 * 4096; + info << describeCDFVersion(cart.myCDFSubtype) << " cartridge\n" + << "32K ROM (seven 4K banks are accessible to 2600)\n" + << "8K RAM\n" + << "Functions accessible @ $FFF0 - $FFF3\n" + << "Banks accessible @ $FFF4 to $FFFB\n" + << "Startup bank = " << cart.startBank() << "\n"; + } + #if 0 // Eventually, we should query this from the debugger/disassembler for(uInt32 i = 0, offset = 0xFFC, spot = 0xFF5; i < 7; ++i, offset += 0x1000) @@ -61,6 +73,9 @@ string CartridgeCDFInfoWidget::describeCDFVersion(CartridgeCDF::CDFSubtype subty case CartridgeCDF::CDFSubtype::CDFJ: return "CDFJ"; + case CartridgeCDF::CDFSubtype::CDFJplus: + return "CDFJ+"; + default: throw runtime_error("unreachable"); } diff --git a/src/debugger/gui/CartCDFWidget.cxx b/src/debugger/gui/CartCDFWidget.cxx index 8c4fdf2fc..3488dd9fe 100644 --- a/src/debugger/gui/CartCDFWidget.cxx +++ b/src/debugger/gui/CartCDFWidget.cxx @@ -467,6 +467,9 @@ string CartridgeCDFWidget::describeCDFVersion(CartridgeCDF::CDFSubtype subtype) case CartridgeCDF::CDFSubtype::CDFJ: return "CDFJ"; + case CartridgeCDF::CDFSubtype::CDFJplus: + return "CDFJ+"; + default: throw runtime_error("unreachable"); } @@ -475,5 +478,6 @@ string CartridgeCDFWidget::describeCDFVersion(CartridgeCDF::CDFSubtype subtype) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeCDFWidget::isCDFJ() const { - return myCart.myCDFSubtype == CartridgeCDF::CDFSubtype::CDFJ; + return (myCart.myCDFSubtype == CartridgeCDF::CDFSubtype::CDFJ || + myCart.myCDFSubtype == CartridgeCDF::CDFSubtype::CDFJplus); // FIXME: Separate settings for CDFJ+ } diff --git a/src/emucore/CartBUS.cxx b/src/emucore/CartBUS.cxx index 46d220bbf..edd56d72c 100644 --- a/src/emucore/CartBUS.cxx +++ b/src/emucore/CartBUS.cxx @@ -68,8 +68,12 @@ CartridgeBUS::CartridgeBUS(const ByteBuffer& image, size_t size, reinterpret_cast(myImage.get()), reinterpret_cast(myRAM.data()), static_cast(32_KB), - devSettings ? settings.getBool("dev.thumb.trapfatal") : false, Thumbulator::ConfigureFor::BUS, this - ); + 0x00000800, + 0x00000808, + 0x40001FDC, + devSettings ? settings.getBool("dev.thumb.trapfatal") : false, + Thumbulator::ConfigureFor::BUS, + this); setInitialState(); } diff --git a/src/emucore/CartCDF.cxx b/src/emucore/CartCDF.cxx index e09480464..867b66a7b 100644 --- a/src/emucore/CartCDF.cxx +++ b/src/emucore/CartCDF.cxx @@ -29,14 +29,17 @@ #include "TIA.hxx" #include "exception/FatalEmulationError.hxx" -#define DSRAM 0x0800 - #define COMMSTREAM 0x20 #define JUMPSTREAM_BASE 0x21 #define FAST_FETCH_ON ((myMode & 0x0F) == 0) #define DIGITAL_AUDIO_ON ((myMode & 0xF0) == 0) +#define getUInt32(_array, _address) ((_array)[(_address) + 0] + \ + ((_array)[(_address) + 1] << 8) + \ + ((_array)[(_address) + 2] << 16) + \ + ((_array)[(_address) + 3] << 24)) + namespace { Thumbulator::ConfigureFor thumulatorConfiguration(CartridgeCDF::CDFSubtype subtype) { @@ -50,6 +53,9 @@ namespace { case CartridgeCDF::CDFSubtype::CDFJ: return Thumbulator::ConfigureFor::CDFJ; + case CartridgeCDF::CDFSubtype::CDFJplus: + return Thumbulator::ConfigureFor::CDFJplus; + default: throw runtime_error("unreachable"); } @@ -60,34 +66,53 @@ namespace { CartridgeCDF::CartridgeCDF(const ByteBuffer& image, size_t size, const string& md5, const Settings& settings) : Cartridge(settings, md5), - myImage(make_unique(32_KB)) + myImage(make_unique(512_KB)) { // Copy the ROM image into my buffer - std::fill_n(myImage.get(), 32_KB, 0); - std::copy_n(image.get(), std::min(32_KB, size), myImage.get()); + std::fill_n(myImage.get(), 512_KB, 0); + std::copy_n(image.get(), std::min(512_KB, size), myImage.get()); - // even though the ROM is 32K, only 28K is accessible to the 6507 - createRomAccessArrays(28_KB); + // Detect cart version + setupVersion(); - // Pointer to the program ROM (28K @ 0 byte offset) - // which starts after the 2K CDF Driver and 2K C Code - myProgramImage = myImage.get() + 4_KB; + // CDFJ+ has different settings + bool cdfjPlus = (myCDFSubtype == CDFSubtype::CDFJplus); + + // The lowest 2K is not accessible to the debugger + createRomAccessArrays(cdfjPlus ? 510_KB : 28_KB); + + // Pointer to the program ROM + // which starts after the 2K driver (and 2K C Code for CDF) + myProgramImage = myImage.get() + (cdfjPlus ? 2_KB : 4_KB); // Pointer to CDF driver in RAM myDriverImage = myRAM.data(); - // Pointer to the display RAM - myDisplayImage = myRAM.data() + DSRAM; + // Pointer to the display RAM (starts after 2K driver) + myDisplayImage = myRAM.data() + 2_KB; - setupVersion(); + // C addresses + uInt32 cBase, cStart, cStack; + if (cdfjPlus) { + cBase = getUInt32(myImage.get(), 0x17F8) & 0xFFFFFFFE; // C Base Address + cStart = cBase; // C Start Address + cStack = getUInt32(myImage.get(), 0x17F4); // C Stack + } else { + cBase = 0x800; // C Base Address + cStart = 0x808; // C Start Address (skip ARM header) + cStack = 0x40001FDC; // C Stack + } // Create Thumbulator ARM emulator bool devSettings = settings.getBool("dev.settings"); myThumbEmulator = make_unique( reinterpret_cast(myImage.get()), reinterpret_cast(myRAM.data()), - static_cast(32_KB), - devSettings ? settings.getBool("dev.thumb.trapfatal") : false, thumulatorConfiguration(myCDFSubtype), this); + static_cast(512_KB), + cBase, cStart, cStack, + devSettings ? settings.getBool("dev.thumb.trapfatal") : false, + thumulatorConfiguration(myCDFSubtype), + this); setInitialState(); } @@ -97,8 +122,8 @@ void CartridgeCDF::reset() { initializeRAM(myRAM.data()+2_KB, myRAM.size()-2_KB); - // CDF always starts in bank 6 - initializeStartBank(6); + // CDF always starts in bank 6, CDFJ+ in bank 0 + initializeStartBank((myCDFSubtype == CDFSubtype::CDFJplus) ? 0 : 6); myAudioCycles = myARMCycles = 0; myFractionalClocks = 0.0; @@ -123,7 +148,6 @@ void CartridgeCDF::setInitialState() myBankOffset = myLDAimmediateOperandAddress = myJMPoperandAddress = 0; myFastJumpActive = myFastJumpStream = 0; - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -194,8 +218,9 @@ inline void CartridgeCDF::callFunction(uInt8 value) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 CartridgeCDF::peek(uInt16 address) { - address &= 0x0FFF; + bool cdfjPlus = (myCDFSubtype == CDFSubtype::CDFJplus); + address &= 0x0FFF; uInt8 peekvalue = myProgramImage[myBankOffset + address]; // In debugger/bank-locked mode, we ignore all hotspots and in general @@ -214,8 +239,14 @@ uInt8 CartridgeCDF::peek(uInt16 address) ++myJMPoperandAddress; pointer = getDatastreamPointer(myFastJumpStream); - value = myDisplayImage[ pointer >> 20 ]; - pointer += 0x100000; // always increment by 1 + if (cdfjPlus) { + value = myDisplayImage[ pointer >> 16 ]; + pointer += 0x00010000; // always increment by 1 + } else { + value = myDisplayImage[ pointer >> 20 ]; + pointer += 0x00100000; // always increment by 1 + } + setDatastreamPointer(myFastJumpStream, pointer); return value; @@ -254,9 +285,9 @@ uInt8 CartridgeCDF::peek(uInt16 address) uInt32 sampleaddress = getSample() + (myMusicCounters[0] >> 21); // get sample value from ROM or RAM - if (sampleaddress < 0x8000) + if (sampleaddress < 0x00080000) peekvalue = myImage[sampleaddress]; - else if (sampleaddress >= 0x40000000 && sampleaddress < 0x40002000) // check for RAM + else if (sampleaddress >= 0x40000000 && sampleaddress < 0x40008000) // check for RAM peekvalue = myRAM[sampleaddress - 0x40000000]; else peekvalue = 0; @@ -284,39 +315,36 @@ uInt8 CartridgeCDF::peek(uInt16 address) // Switch banks if necessary switch(address) { - case 0xFF5: - // Set the current bank to the first 4k bank - bank(0); + case 0x0FF4: + bank(cdfjPlus ? 0 : 6); + break; + + case 0x0FF5: + bank(cdfjPlus ? 1 : 0); break; case 0x0FF6: - // Set the current bank to the second 4k bank - bank(1); + bank(cdfjPlus ? 2 : 1); break; case 0x0FF7: - // Set the current bank to the third 4k bank - bank(2); + bank(cdfjPlus ? 3 : 2); break; case 0x0FF8: - // Set the current bank to the fourth 4k bank - bank(3); + bank(cdfjPlus ? 4 : 3); break; case 0x0FF9: - // Set the current bank to the fifth 4k bank - bank(4); + bank(cdfjPlus ? 5 : 4); break; case 0x0FFA: - // Set the current bank to the sixth 4k bank - bank(5); + bank(cdfjPlus ? 6 : 5); break; case 0x0FFB: - // Set the current bank to the last 4k bank - bank(6); + bank(cdfjPlus ? 0 : 6); break; default: @@ -333,67 +361,74 @@ uInt8 CartridgeCDF::peek(uInt16 address) bool CartridgeCDF::poke(uInt16 address, uInt8 value) { uInt32 pointer; + bool cdfjPlus = (myCDFSubtype == CDFSubtype::CDFJplus); address &= 0x0FFF; - switch(address) { - case 0xFF0: // DSWRITE + case 0x0FF0: // DSWRITE pointer = getDatastreamPointer(COMMSTREAM); - myDisplayImage[ pointer >> 20 ] = value; - pointer += 0x100000; // always increment by 1 when writing + if (cdfjPlus) { + myDisplayImage[ pointer >> 16 ] = value; + pointer += 0x00010000; // always increment by 1 when writing + } else { + myDisplayImage[ pointer >> 20 ] = value; + pointer += 0x00100000; // always increment by 1 when writing + } setDatastreamPointer(COMMSTREAM, pointer); break; - case 0xFF1: // DSPTR + case 0x0FF1: // DSPTR pointer = getDatastreamPointer(COMMSTREAM); - pointer <<=8; - pointer &= 0xf0000000; - pointer |= (value << 20); + pointer <<= 8; + if (cdfjPlus) { + pointer &= 0xff000000; + pointer |= (value << 16); + } else { + pointer &= 0xf0000000; + pointer |= (value << 20); + } setDatastreamPointer(COMMSTREAM, pointer); break; - case 0xFF2: // SETMODE + case 0x0FF2: // SETMODE myMode = value; break; - case 0xFF3: // CALLFN + case 0x0FF3: // CALLFN callFunction(value); break; - case 0xFF5: - // Set the current bank to the first 4k bank - bank(0); + case 0x00FF4: + bank(cdfjPlus ? 0 : 6); + break; + + case 0x0FF5: + bank(cdfjPlus ? 1 : 0); break; case 0x0FF6: - // Set the current bank to the second 4k bank - bank(1); + bank(cdfjPlus ? 2 : 1); break; case 0x0FF7: - // Set the current bank to the third 4k bank - bank(2); + bank(cdfjPlus ? 3 : 2); break; case 0x0FF8: - // Set the current bank to the fourth 4k bank - bank(3); + bank(cdfjPlus ? 4 : 3); break; case 0x0FF9: - // Set the current bank to the fifth 4k bank - bank(4); + bank(cdfjPlus ? 5 : 4); break; case 0x0FFA: - // Set the current bank to the sixth 4k bank - bank(5); + bank(cdfjPlus ? 6 : 5); break; case 0x0FFB: - // Set the current bank to the last 4k bank - bank(6); + bank(cdfjPlus ? 0 : 6); break; default: @@ -419,7 +454,7 @@ bool CartridgeCDF::bank(uInt16 bank, uInt16) { access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)]; access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)]; - access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + 28_KB]; + access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + 28_KB]; // TODO: Change for CDFJ+??? mySystem->setPageAccess(addr, access); } return myBankChanged = true; @@ -455,7 +490,7 @@ bool CartridgeCDF::patch(uInt16 address, uInt8 value) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - const ByteBuffer& CartridgeCDF::getImage(size_t& size) const { - size = 32_KB; + size = 512_KB; return myImage; } @@ -617,11 +652,13 @@ uInt32 CartridgeCDF::getWaveform(uInt8 index) const (myRAM[address + 2] << 16) + (myRAM[address + 3] << 24); // high byte - result -= (0x40000000 + DSRAM); - - if (result >= 4096) - result &= 4095; + result -= (0x40000000 + 2_KB); + if (myCDFSubtype != CDFSubtype::CDFJplus) { + if (result >= 4096) { + result &= 4095; + } + } return result; } @@ -659,8 +696,17 @@ uInt8 CartridgeCDF::readFromDatastream(uInt8 index) uInt32 pointer = getDatastreamPointer(index); uInt16 increment = getDatastreamIncrement(index); - uInt8 value = myDisplayImage[ pointer >> 20 ]; - pointer += (increment << 12); + + uInt8 value; + bool cdfjPlus = (myCDFSubtype == CDFSubtype::CDFJplus); + if (cdfjPlus) { + value = myDisplayImage[ pointer >> 16 ]; + pointer += (increment << 8); + } else { + value = myDisplayImage[ pointer >> 20 ]; + pointer += (increment << 12); + } + setDatastreamPointer(index, pointer); return value; } @@ -668,8 +714,21 @@ uInt8 CartridgeCDF::readFromDatastream(uInt8 index) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeCDF::setupVersion() { - uInt8 subversion = 0; + // CDFJ+ detection + if (getUInt32(myImage.get(), 0x174) == 0x53554c50 && // Plus + getUInt32(myImage.get(), 0x178) == 0x4a464443 && // CDFJ + getUInt32(myImage.get(), 0x17C) == 0x00000001) { // V1 + myCDFSubtype = CDFSubtype::CDFJplus; + myAmplitudeStream = 0x23; + myFastjumpStreamIndexMask = 0xfe; + myDatastreamBase = 0x0098; + myDatastreamIncrementBase = 0x0124; + myWaveformBase = 0x01b0; + return; + } + + uInt8 subversion = 0; for(uInt32 i = 0; i < 2048; i += 4) { // CDF signature occurs 3 times in a row, i+3 (+7 or +11) is version @@ -683,6 +742,7 @@ void CartridgeCDF::setupVersion() } switch (subversion) { + case 0x4a: myCDFSubtype = CDFSubtype::CDFJ; @@ -727,6 +787,8 @@ string CartridgeCDF::name() const return "CartridgeCDF1"; case CDFSubtype::CDFJ: return "CartridgeCDFJ"; + case CDFSubtype::CDFJplus: + return "CartridgeCDFJplus"; default: return "Cart unknown"; } diff --git a/src/emucore/CartCDF.hxx b/src/emucore/CartCDF.hxx index cf172b8d2..180c08f44 100644 --- a/src/emucore/CartCDF.hxx +++ b/src/emucore/CartCDF.hxx @@ -25,16 +25,15 @@ class Thumbulator; #include "Cart.hxx" /** - Cartridge class used for CDF. + Cartridge class used for CDF/CDFJ/CDFJ+. There are seven 4K program banks, a 4K Display Data RAM, 1K C Variable and Stack, and the CDF chip. CDF chip access is mapped to $1000 - $103F (both read and write). - Program banks are accessible by read/write to $1FF5 - $1FFB. - + Program banks are accessible by read/write to $1FF5 - $1FFB FIXME: THIS NEEDS TO BE UPDATED - @authors: Darrell Spice Jr, Chris Walton, Fred Quimby, + @authors: Darrell Spice Jr, Chris Walton, Fred Quimby, John Champeau Stephen Anthony, Bradford W. Mott */ class CartridgeCDF : public Cartridge @@ -48,7 +47,8 @@ class CartridgeCDF : public Cartridge enum class CDFSubtype { CDF0, CDF1, - CDFJ + CDFJ, + CDFJplus }; public: @@ -220,23 +220,26 @@ class CartridgeCDF : public Cartridge void setupVersion(); private: - // The 32K ROM image of the cartridge + // The ROM image of the cartridge ByteBuffer myImage; - // Pointer to the 28K program ROM image of the cartridge + // Pointer to the program ROM image of the cartridge uInt8* myProgramImage{nullptr}; - // Pointer to the 4K display ROM image of the cartridge + // Pointer to the display ROM image of the cartridge uInt8* myDisplayImage{nullptr}; - // Pointer to the 2K CDF driver image in RAM + // Pointer to the driver image in RAM uInt8* myDriverImage{nullptr}; - // The CDF 8k RAM image, used as: - // $0000 - 2K CDF driver + // The CDFJ 8K RAM image, used as: + // $0000 - 2K Driver // $0800 - 4K Display Data // $1800 - 2K C Variable & Stack - std::array myRAM; + // For CDFJ+, used as: + // $0000 - 2K Driver + // $0800 - Display Data, C Variables & Stack + std::array myRAM; // Pointer to the Thumb ARM emulator object unique_ptr myThumbEmulator; diff --git a/src/emucore/CartDPCPlus.cxx b/src/emucore/CartDPCPlus.cxx index 71500ee94..17494b8cb 100644 --- a/src/emucore/CartDPCPlus.cxx +++ b/src/emucore/CartDPCPlus.cxx @@ -54,6 +54,9 @@ CartridgeDPCPlus::CartridgeDPCPlus(const ByteBuffer& image, size_t size, (reinterpret_cast(myImage.get()), reinterpret_cast(myDPCRAM.data()), static_cast(32_KB), + 0x00000C00, + 0x00000C08, + 0x40001FDC, devSettings ? settings.getBool("dev.thumb.trapfatal") : false, Thumbulator::ConfigureFor::DPCplus, this); diff --git a/src/emucore/CartDetector.cxx b/src/emucore/CartDetector.cxx index dba8bb3e4..6874c2576 100644 --- a/src/emucore/CartDetector.cxx +++ b/src/emucore/CartDetector.cxx @@ -169,6 +169,8 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si type = Bankswitch::Type::_3E; else if(isProbably3F(image, size)) type = Bankswitch::Type::_3F; + else if (isProbablyCDF(image, size)) + type = Bankswitch::Type::_CDF; else if(isProbably4A50(image, size)) type = Bankswitch::Type::_4A50; else if(isProbablyEF(image, size, type)) @@ -188,6 +190,8 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si ; // type has been set directly in the function else if(isProbably3F(image, size)) type = Bankswitch::Type::_3F; + else if (isProbablyCDF(image, size)) + type = Bankswitch::Type::_CDF; else if(isProbably4A50(image, size)) type = Bankswitch::Type::_4A50; else /*if(isProbablySB(image, size))*/ @@ -203,6 +207,8 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si ; // type has been set directly in the function else if(isProbably3F(image, size)) type = Bankswitch::Type::_3F; + else if (isProbablyCDF(image, size)) + type = Bankswitch::Type::_CDF; else /*if(isProbablySB(image, size))*/ type = Bankswitch::Type::_SB; } @@ -216,6 +222,8 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si type = Bankswitch::Type::_3E; else if(isProbably3F(image, size)) type = Bankswitch::Type::_3F; + else if (isProbablyCDF(image, size)) + type = Bankswitch::Type::_CDF; } else // what else can we do? { @@ -444,7 +452,9 @@ bool CartDetector::isProbablyCDF(const ByteBuffer& image, size_t size) // Note: all Harmony/Melody custom drivers also contain the value // 0x10adab1e (LOADABLE) if needed for future improvement uInt8 cdf[] = { 'C', 'D', 'F' }; - return searchForBytes(image, size, cdf, 3, 3); + uInt8 cdfjplus[] = { 'P', 'L', 'U', 'S', 'C', 'D', 'F', 'J' }; + return (searchForBytes(image, size, cdf, 3, 3) || + searchForBytes(image, size, cdfjplus, 8, 1)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/Thumbulator.cxx b/src/emucore/Thumbulator.cxx index 2984159cd..a9d5f3435 100644 --- a/src/emucore/Thumbulator.cxx +++ b/src/emucore/Thumbulator.cxx @@ -54,10 +54,14 @@ using Common::Base; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Thumbulator::Thumbulator(const uInt16* rom_ptr, uInt16* ram_ptr, uInt16 rom_size, + const uInt32 c_base, const uInt32 c_start, const uInt32 c_stack, bool traponfatal, Thumbulator::ConfigureFor configurefor, Cartridge* cartridge) : rom(rom_ptr), romSize(rom_size), + cBase(c_base), + cStart(c_start), + cStack(c_stack), decodedRom(make_unique(romSize / 2)), // NOLINT ram(ram_ptr), configuration(configurefor), @@ -217,7 +221,7 @@ uInt32 Thumbulator::fetch16(uInt32 addr) void Thumbulator::write16(uInt32 addr, uInt32 data) { #ifndef UNSAFE_OPTIMIZATIONS - if((addr > 0x40001fff) && (addr < 0x50000000)) + if((addr > 0x40007fff) && (addr < 0x50000000)) fatalError("write16", addr, "abort - out of range"); if (isProtected(addr)) fatalError("write16", addr, "to driver area"); @@ -376,6 +380,7 @@ bool Thumbulator::isProtected(uInt32 addr) return (addr < 0x0800) && (addr > 0x0028) && !((addr >= 0x00a0) && (addr < (0x00a0 + 284))); case ConfigureFor::CDFJ: + case ConfigureFor::CDFJplus: return (addr < 0x0800) && (addr > 0x0028) && !((addr >= 0x0098) && (addr < (0x0098 + 292))); case ConfigureFor::BUS: @@ -391,9 +396,9 @@ uInt32 Thumbulator::read16(uInt32 addr) { uInt32 data; #ifndef UNSAFE_OPTIMIZATIONS - if((addr > 0x40001fff) && (addr < 0x50000000)) + if((addr > 0x40007fff) && (addr < 0x50000000)) fatalError("read16", addr, "abort - out of range"); - else if((addr > 0x7fff) && (addr < 0x10000000)) + else if((addr > 0x0007ffff) && (addr < 0x10000000)) fatalError("read16", addr, "abort - out of range"); if(addr & 1) fatalError("read16", addr, "abort - misaligned"); @@ -1424,6 +1429,7 @@ int Thumbulator::execute() case ConfigureFor::CDF1: case ConfigureFor::CDFJ: + case ConfigureFor::CDFJplus: // this subroutine interface is used in the CDF driver, // it starts at address 0x00000750 // _SetNote: @@ -2521,25 +2527,10 @@ int Thumbulator::execute() int Thumbulator::reset() { reg_norm.fill(0); - reg_norm[13] = 0x40001FB4; - switch(configuration) - { - // future 2K Harmony/Melody drivers will most likely use these settings - case ConfigureFor::BUS: - case ConfigureFor::CDF: - case ConfigureFor::CDF1: - case ConfigureFor::CDFJ: - reg_norm[14] = 0x00000800; // Link Register - reg_norm[15] = 0x0000080B; // Program Counter - break; - - // future 3K Harmony/Melody drivers will most likely use these settings - case ConfigureFor::DPCplus: - reg_norm[14] = 0x00000C00; // Link Register - reg_norm[15] = 0x00000C0B; // Program Counter - break; - } + reg_norm[13] = cStack; // SP + reg_norm[14] = cBase; // LR + reg_norm[15] = (cStart + 2) | 1; // PC (+2 for pipeline, lower bit for THUMB) cpsr = mamcr = 0; handler_mode = false; diff --git a/src/emucore/Thumbulator.hxx b/src/emucore/Thumbulator.hxx index ae62d1755..2fd043627 100644 --- a/src/emucore/Thumbulator.hxx +++ b/src/emucore/Thumbulator.hxx @@ -35,11 +35,11 @@ class Cartridge; #define NO_THUMB_STATS #endif -#define ROMADDMASK 0x7FFF -#define RAMADDMASK 0x1FFF +#define ROMADDMASK 0x7FFFF +#define RAMADDMASK 0x7FFF -#define ROMSIZE (ROMADDMASK+1) -#define RAMSIZE (RAMADDMASK+1) +#define ROMSIZE (ROMADDMASK+1) // 512KB +#define RAMSIZE (RAMADDMASK+1) // 32KB #define CPSR_N (1u<<31) #define CPSR_Z (1u<<30) @@ -55,11 +55,13 @@ class Thumbulator BUS, // cartridges of type BUS CDF, // cartridges of type CDF CDF1, // cartridges of type CDF version 1 - CDFJ, // cartrdiges of type CDFJ + CDFJ, // cartridges of type CDFJ + CDFJplus, // cartridges of type CDFJ+ DPCplus // cartridges of type DPC+ }; Thumbulator(const uInt16* rom_ptr, uInt16* ram_ptr, uInt16 rom_size, + const uInt32 c_base, const uInt32 c_start, const uInt32 c_stack, bool traponfatal, Thumbulator::ConfigureFor configurefor, Cartridge* cartridge); @@ -187,9 +189,11 @@ class Thumbulator private: const uInt16* rom{nullptr}; uInt16 romSize{0}; + uInt32 cBase{0}; + uInt32 cStart{0}; + uInt32 cStack{0}; const unique_ptr decodedRom; // NOLINT uInt16* ram{nullptr}; - std::array reg_norm; // normal execution mode, do not have a thread mode uInt32 cpsr{0}, mamcr{0}; bool handler_mode{false};