From 2921bc29de9f92d50961b0ff2d4b1126d8e26066 Mon Sep 17 00:00:00 2001 From: Thomas Jentzsch Date: Sat, 9 Oct 2021 23:28:28 +0200 Subject: [PATCH] initial commit --- src/emucore/Cart.hxx | 17 +++++ src/emucore/CartAR.cxx | 122 +++++++++++--------------------- src/emucore/CartAR.hxx | 5 ++ src/emucore/CartCreator.cxx | 32 +++++---- src/emucore/CartCreator.hxx | 8 ++- src/emucore/OSystem.cxx | 11 ++- src/emucore/ProfilingRunner.cxx | 4 +- src/emucore/ProfilingRunner.hxx | 3 + 8 files changed, 102 insertions(+), 100 deletions(-) diff --git a/src/emucore/Cart.hxx b/src/emucore/Cart.hxx index 19d07e7e1..0a854024a 100644 --- a/src/emucore/Cart.hxx +++ b/src/emucore/Cart.hxx @@ -49,6 +49,11 @@ class Cartridge : public Device public: using StartBankFromPropsFunc = std::function; + /** + Callback type for general cart messages + */ + using messageCallback = std::function; + // Maximum size of a ROM cart that Stella can support static constexpr size_t maxSize() { return 512_KB; } @@ -136,6 +141,15 @@ class Cartridge : public Device */ virtual bool isPlusROM() const { return false; } + /** + Set the callback for displaying messages + */ + void setMessageCallback(const messageCallback& callback) + { + if(myMsgCallback == nullptr) + myMsgCallback = &callback; + } + #ifdef DEBUGGER_SUPPORT /** To be called at the start of each instruction. @@ -400,6 +414,9 @@ class Cartridge : public Device // Total size of ROM access area (might include RAM too) uInt32 myAccessSize; + // Callback to output messages + const messageCallback* myMsgCallback{nullptr}; + private: // The startup bank to use (where to look for the reset vector address) uInt16 myStartBank{0}; diff --git a/src/emucore/CartAR.cxx b/src/emucore/CartAR.cxx index 70349b3e5..b62fd7daa 100644 --- a/src/emucore/CartAR.cxx +++ b/src/emucore/CartAR.cxx @@ -24,17 +24,17 @@ CartridgeAR::CartridgeAR(const ByteBuffer& image, size_t size, const string& md5, const Settings& settings) : Cartridge(settings, md5), - mySize{std::max(size, 8448)} + mySize{std::max(size, LOAD_SIZE)} { // Create a load image buffer and copy the given image myLoadImages = make_unique(mySize); - myNumberOfLoadImages = uInt8(mySize / 8448); + myNumberOfLoadImages = uInt8(mySize / LOAD_SIZE); std::copy_n(image.get(), size, myLoadImages.get()); // Add header if image doesn't include it - if(size < 8448) + if(size < LOAD_SIZE) std::copy_n(ourDefaultHeader.data(), ourDefaultHeader.size(), - myLoadImages.get()+myImage.size()); + myLoadImages.get() + myImage.size()); // We use System::PageAccess.romAccessBase, but don't allow its use // through a pointer, since the AR scheme doesn't support bankswitching @@ -91,7 +91,7 @@ uInt8 CartridgeAR::peek(uInt16 addr) return myImage[(addr & 0x07FF) + myImageOffset[(addr & 0x0800) ? 1 : 0]]; // Is the "dummy" SC BIOS hotspot for reading a load being accessed? - if(((addr & 0x1FFF) == 0x1850) && (myImageOffset[1] == (3 << 11))) + if(((addr & 0x1FFF) == 0x1850) && (myImageOffset[1] == RAM_SIZE)) { // Get load that's being accessed (BIOS places load number at 0x80) uInt8 load = mySystem->peek(0x0080); @@ -133,7 +133,7 @@ uInt8 CartridgeAR::peek(uInt16 addr) myImage[(addr & 0x07FF) + myImageOffset[0]] = myDataHoldRegister; mySystem->setDirtyPage(addr); } - else if(myImageOffset[1] != (3 << 11)) // Can't poke to ROM :-) + else if(myImageOffset[1] != (3 * BANK_SIZE)) // Can't poke to ROM :-) { myImage[(addr & 0x07FF) + myImageOffset[1]] = myDataHoldRegister; mySystem->setDirtyPage(addr); @@ -180,7 +180,7 @@ bool CartridgeAR::poke(uInt16 addr, uInt8) myImage[(addr & 0x07FF) + myImageOffset[0]] = myDataHoldRegister; modified = true; } - else if(myImageOffset[1] != (3 << 11)) // Can't poke to ROM :-) + else if(myImageOffset[1] != (3 * BANK_SIZE)) // Can't poke to ROM :-) { myImage[(addr & 0x07FF) + myImageOffset[1]] = myDataHoldRegister; modified = true; @@ -227,72 +227,22 @@ bool CartridgeAR::bankConfiguration(uInt8 configuration) // to happen. 0 = disabled, and the cart acts like ROM.) // p = ROM Power (0 = enabled, 1 = off.) Only power the ROM if you're // wanting to access the ROM for multiloads. Otherwise set to 1. + const uInt32 OFFSET_0[8] = {2 * BANK_SIZE, 0 * BANK_SIZE, 2 * BANK_SIZE, 0 * BANK_SIZE, + 2 * BANK_SIZE, 1 * BANK_SIZE, 2 * BANK_SIZE, 1 * BANK_SIZE}; + const uInt32 OFFSET_1[8] = {3 * BANK_SIZE, 3 * BANK_SIZE, 0 * BANK_SIZE, 2 * BANK_SIZE, + 3 * BANK_SIZE, 3 * BANK_SIZE, 1 * BANK_SIZE, 2 * BANK_SIZE}; + const int bankConfig = (configuration & 0b11100) >> 2; - myCurrentBank = configuration & 0x1F; // remember for the bank() method + myCurrentBank = configuration & 0b11111; // remember for the bank() method // Handle ROM power configuration - myPower = !(configuration & 0x01); + myPower = !(configuration & 0b00001); - myWriteEnabled = configuration & 0x02; + myWriteEnabled = configuration & 0b00010; - switch((configuration >> 2) & 0x07) - { - case 0: - { - myImageOffset[0] = 2 << 11; - myImageOffset[1] = 3 << 11; - break; - } + myImageOffset[0] = OFFSET_0[bankConfig]; + myImageOffset[1] = OFFSET_1[bankConfig]; - case 1: - { - myImageOffset[0] = 0 ; - myImageOffset[1] = 3 << 11; - break; - } - - case 2: - { - myImageOffset[0] = 2 << 11; - myImageOffset[1] = 0 ; - break; - } - - case 3: - { - myImageOffset[0] = 0 ; - myImageOffset[1] = 2 << 11; - break; - } - - case 4: - { - myImageOffset[0] = 2 << 11; - myImageOffset[1] = 3 << 11; - break; - } - - case 5: - { - myImageOffset[0] = 1 << 11; - myImageOffset[1] = 3 << 11; - break; - } - - case 6: - { - myImageOffset[0] = 2 << 11; - myImageOffset[1] = 1 << 11; - break; - } - - case 7: - { - myImageOffset[0] = 1 << 11; - myImageOffset[1] = 2 << 11; - break; - } - } return myBankChanged = true; } @@ -314,16 +264,16 @@ void CartridgeAR::initializeROM() ourDummyROMCode[281] = mySystem->randGenerator().next(); // Initialize ROM with illegal 6502 opcode that causes a real 6502 to jam - std::fill_n(myImage.begin() + (3<<11), 2_KB, 0x02); + std::fill_n(myImage.begin() + (RAM_SIZE), BANK_SIZE, 0x02); // Copy the "dummy" Supercharger BIOS code into the ROM area - std::copy_n(ourDummyROMCode.data(), ourDummyROMCode.size(), myImage.data() + (3<<11)); + std::copy_n(ourDummyROMCode.data(), ourDummyROMCode.size(), myImage.data() + (RAM_SIZE)); // Finally set 6502 vectors to point to initial load code at 0xF80A of BIOS - myImage[(3<<11) + 2044] = 0x0A; - myImage[(3<<11) + 2045] = 0xF8; - myImage[(3<<11) + 2046] = 0x0A; - myImage[(3<<11) + 2047] = 0xF8; + myImage[(RAM_SIZE) + BANK_SIZE - 4] = 0x0A; + myImage[(RAM_SIZE) + BANK_SIZE - 3] = 0xF8; + myImage[(RAM_SIZE) + BANK_SIZE - 2] = 0x0A; + myImage[(RAM_SIZE) + BANK_SIZE - 1] = 0xF8; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -340,40 +290,48 @@ uInt8 CartridgeAR::checksum(uInt8* s, uInt16 length) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeAR::loadIntoRAM(uInt8 load) { + bool success = true; uInt16 image; // Scan through all of the loads to see if we find the one we're looking for for(image = 0; image < myNumberOfLoadImages; ++image) { // Is this the correct load? - if(myLoadImages[(image * 8448) + myImage.size() + 5] == load) + if(myLoadImages[(image * LOAD_SIZE) + myImage.size() + 5] == load) { // Copy the load's header - std::copy_n(myLoadImages.get() + (image * 8448) + myImage.size(), myHeader.size(), myHeader.data()); + std::copy_n(myLoadImages.get() + (image * LOAD_SIZE) + myImage.size(), myHeader.size(), myHeader.data()); // Verify the load's header if(checksum(myHeader.data(), 8) != 0x55) + { cerr << "WARNING: The Supercharger header checksum is invalid...\n"; + (*myMsgCallback)("Supercharger load #" + std::to_string(load) + " done with hearder checksum error"); + success = false; + } // Load all of the pages from the load bool invalidPageChecksumSeen = false; for(uInt32 j = 0; j < myHeader[3]; ++j) { - uInt32 bank = myHeader[16 + j] & 0x03; - uInt32 page = (myHeader[16 + j] >> 2) & 0x07; - uInt8* src = myLoadImages.get() + (image * 8448) + (j * 256); + uInt32 bank = myHeader[16 + j] & 0b00011; + uInt32 page = (myHeader[16 + j] & 0b11100) >> 2; + uInt8* src = myLoadImages.get() + (image * LOAD_SIZE) + (j * 256); uInt8 sum = checksum(src, 256) + myHeader[16 + j] + myHeader[64 + j]; if(!invalidPageChecksumSeen && (sum != 0x55)) { cerr << "WARNING: Some Supercharger page checksums are invalid...\n"; + (*myMsgCallback)("Supercharger load #" + std::to_string(load) + " done with page #" + + std::to_string(j) + " checksum error"); invalidPageChecksumSeen = true; } // Copy page to Supercharger RAM (don't allow a copy into ROM area) if(bank < 3) - std::copy_n(src, 256, myImage.data() + (bank * 2048) + (page * 256)); + std::copy_n(src, 256, myImage.data() + (bank * BANK_SIZE) + (page * 256)); } + success &= !invalidPageChecksumSeen; // Copy the bank switching byte and starting address into the 2600's // RAM for the "dummy" SC BIOS to access it @@ -382,6 +340,8 @@ void CartridgeAR::loadIntoRAM(uInt8 load) mySystem->poke(0x80, myHeader[2]); myBankChanged = true; + if(success) + (*myMsgCallback)("Supercharger load #" + std::to_string(load) + " done"); return; } } @@ -442,7 +402,7 @@ bool CartridgeAR::save(Serializer& out) const // All of the 8448 byte loads associated with the game // Note that the size of this array is myNumberOfLoadImages * 8448 - out.putByteArray(myLoadImages.get(), myNumberOfLoadImages * 8448); + out.putByteArray(myLoadImages.get(), myNumberOfLoadImages * LOAD_SIZE); // Indicates how many 8448 loads there are out.putByte(myNumberOfLoadImages); @@ -487,7 +447,7 @@ bool CartridgeAR::load(Serializer& in) // All of the 8448 byte loads associated with the game // Note that the size of this array is myNumberOfLoadImages * 8448 - in.getByteArray(myLoadImages.get(), myNumberOfLoadImages * 8448); + in.getByteArray(myLoadImages.get(), myNumberOfLoadImages * LOAD_SIZE); // Indicates how many 8448 loads there are myNumberOfLoadImages = in.getByte(); diff --git a/src/emucore/CartAR.hxx b/src/emucore/CartAR.hxx index fd99713b2..16fcf6a41 100644 --- a/src/emucore/CartAR.hxx +++ b/src/emucore/CartAR.hxx @@ -43,6 +43,11 @@ class CartridgeAR : public Cartridge { friend class CartridgeARWidget; + public: + static constexpr uInt32 BANK_SIZE = uInt32(2_KB); + static constexpr uInt32 RAM_SIZE = 3 * BANK_SIZE; + static constexpr uInt32 LOAD_SIZE = 8448; + public: /** Create a new cartridge using the specified image and size diff --git a/src/emucore/CartCreator.cxx b/src/emucore/CartCreator.cxx index 9657c787e..4c31066cb 100644 --- a/src/emucore/CartCreator.cxx +++ b/src/emucore/CartCreator.cxx @@ -71,7 +71,7 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - unique_ptr CartCreator::create(const FilesystemNode& file, const ByteBuffer& image, size_t size, string& md5, - const string& propertiesType, Settings& settings) + const string& propertiesType, OSystem& osystem) { unique_ptr cartridge; Bankswitch::Type type = Bankswitch::nameToType(propertiesType), @@ -89,7 +89,7 @@ unique_ptr CartCreator::create(const FilesystemNode& file, // See if we should try to auto-detect the cartridge type // If we ask for extended info, always do an autodetect - if(type == Bankswitch::Type::_AUTO || settings.getBool("rominfo")) + if(type == Bankswitch::Type::_AUTO || osystem.settings().getBool("rominfo")) { detectedType = CartDetector::autodetectType(image, size); if(type != Bankswitch::Type::_AUTO && type != detectedType) @@ -111,7 +111,7 @@ unique_ptr CartCreator::create(const FilesystemNode& file, if(size == 2*2_KB || size == 2*4_KB || size == 2*8_KB || size == 2*16_KB || size == 2*32_KB) { cartridge = - createFromMultiCart(image, size, 2, md5, detectedType, id, settings); + createFromMultiCart(image, size, 2, md5, detectedType, id, osystem); buf << id; } else @@ -124,7 +124,7 @@ unique_ptr CartCreator::create(const FilesystemNode& file, if(size == 4*2_KB || size == 4*4_KB || size == 4*8_KB || size == 4*16_KB) { cartridge = - createFromMultiCart(image, size, 4, md5, detectedType, id, settings); + createFromMultiCart(image, size, 4, md5, detectedType, id, osystem); buf << id; } else @@ -137,7 +137,7 @@ unique_ptr CartCreator::create(const FilesystemNode& file, if(size == 8*2_KB || size == 8*4_KB || size == 8*8_KB) { cartridge = - createFromMultiCart(image, size, 8, md5, detectedType, id, settings); + createFromMultiCart(image, size, 8, md5, detectedType, id, osystem); buf << id; } else @@ -150,7 +150,7 @@ unique_ptr CartCreator::create(const FilesystemNode& file, if(size == 16*2_KB || size == 16*4_KB || size == 16*8_KB) { cartridge = - createFromMultiCart(image, size, 16, md5, detectedType, id, settings); + createFromMultiCart(image, size, 16, md5, detectedType, id, osystem); buf << id; } else @@ -163,7 +163,7 @@ unique_ptr CartCreator::create(const FilesystemNode& file, if(size == 32*2_KB || size == 32*4_KB) { cartridge = - createFromMultiCart(image, size, 32, md5, detectedType, id, settings); + createFromMultiCart(image, size, 32, md5, detectedType, id, osystem); buf << id; } else @@ -176,7 +176,7 @@ unique_ptr CartCreator::create(const FilesystemNode& file, if(size == 64*2_KB || size == 64*4_KB) { cartridge = - createFromMultiCart(image, size, 64, md5, detectedType, id, settings); + createFromMultiCart(image, size, 64, md5, detectedType, id, osystem); buf << id; } else @@ -189,7 +189,7 @@ unique_ptr CartCreator::create(const FilesystemNode& file, if(size == 128*2_KB || size == 128*4_KB) { cartridge = - createFromMultiCart(image, size, 128, md5, detectedType, id, settings); + createFromMultiCart(image, size, 128, md5, detectedType, id, osystem); buf << id; } else @@ -198,11 +198,11 @@ unique_ptr CartCreator::create(const FilesystemNode& file, break; case Bankswitch::Type::_MVC: - cartridge = make_unique(file.getPath(), size, md5, settings); + cartridge = make_unique(file.getPath(), size, md5, osystem.settings()); break; default: - cartridge = createFromImage(image, size, detectedType, md5, settings); + cartridge = createFromImage(image, size, detectedType, md5, osystem); break; } @@ -219,8 +219,10 @@ unique_ptr CartCreator::create(const FilesystemNode& file, // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - unique_ptr CartCreator::createFromMultiCart(const ByteBuffer& image, size_t& size, - uInt32 numroms, string& md5, Bankswitch::Type type, string& id, Settings& settings) + uInt32 numroms, string& md5, Bankswitch::Type type, string& id, OSystem& osystem) { + Settings& settings = osystem.settings(); + // Get a piece of the larger image uInt32 i = settings.getInt("romloadcount"); @@ -250,14 +252,16 @@ CartCreator::createFromMultiCart(const ByteBuffer& image, size_t& size, else /* default */ type = Bankswitch::Type::_4K; - return createFromImage(slice, size, type, md5, settings); + return createFromImage(slice, size, type, md5, osystem); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - unique_ptr CartCreator::createFromImage(const ByteBuffer& image, size_t size, Bankswitch::Type type, - const string& md5, Settings& settings) + const string& md5, OSystem& osystem) { + Settings& settings = osystem.settings(); + // We should know the cart's type by now so let's create it switch(type) { diff --git a/src/emucore/CartCreator.hxx b/src/emucore/CartCreator.hxx index 3aa3a6217..02d6cf66a 100644 --- a/src/emucore/CartCreator.hxx +++ b/src/emucore/CartCreator.hxx @@ -21,6 +21,7 @@ class Cartridge; class Properties; class Settings; +class OSystem; #include "Bankswitch.hxx" #include "bspf.hxx" @@ -47,7 +48,7 @@ class CartCreator */ static unique_ptr create(const FilesystemNode& file, const ByteBuffer& image, size_t size, string& md5, - const string& dtype, Settings& settings); + const string& dtype, OSystem& osystem); private: /** @@ -67,7 +68,7 @@ class CartCreator static unique_ptr createFromMultiCart(const ByteBuffer& image, size_t& size, uInt32 numroms, string& md5, Bankswitch::Type type, string& id, - Settings& settings); + OSystem& osystem); /** Create a cartridge from the entire image pointer. @@ -82,7 +83,8 @@ class CartCreator */ static unique_ptr createFromImage(const ByteBuffer& image, size_t size, Bankswitch::Type type, - const string& md5, Settings& settings); + const string& md5, OSystem& osystem); + private: // Following constructors and assignment operators not supported diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx index 35f48a87f..8a2f3601f 100644 --- a/src/emucore/OSystem.cxx +++ b/src/emucore/OSystem.cxx @@ -632,8 +632,17 @@ unique_ptr OSystem::openConsole(const FilesystemNode& romfile, string& // Now create the cartridge string cartmd5 = md5; const string& type = props.get(PropType::Cart_Type); + const Cartridge::messageCallback callback = [&os = *this](const string& msg) + { + bool devSettings = os.settings().getBool("dev.settings"); + + if(os.settings().getBool(devSettings ? "dev.eepromaccess" : "plr.eepromaccess")) + os.frameBuffer().showTextMessage(msg); + }; + unique_ptr cart = - CartCreator::create(romfile, image, size, cartmd5, type, *mySettings); + CartCreator::create(romfile, image, size, cartmd5, type, *this); + cart->setMessageCallback(callback); // Some properties may not have a name set; we can't leave it blank if(props.get(PropType::Cart_Name) == EmptyString) diff --git a/src/emucore/ProfilingRunner.cxx b/src/emucore/ProfilingRunner.cxx index e8ed88797..4fb332ccd 100644 --- a/src/emucore/ProfilingRunner.cxx +++ b/src/emucore/ProfilingRunner.cxx @@ -26,6 +26,7 @@ #include "Control.hxx" #include "M6502.hxx" #include "M6532.hxx" +#include "MediaFactory.hxx" #include "TIA.hxx" #include "ConsoleTiming.hxx" #include "FrameManager.hxx" @@ -73,6 +74,7 @@ ProfilingRunner::ProfilingRunner(int argc, char* argv[]) } } + myOSystem = MediaFactory::createOSystem(); mySettings.setValue("fastscbios", true); } @@ -110,7 +112,7 @@ bool ProfilingRunner::runOne(const ProfilingRun& run) string md5 = MD5::hash(image, size); string type = ""; unique_ptr cartridge = CartCreator::create( - imageFile, image, size, md5, type, mySettings); + imageFile, image, size, md5, type, *myOSystem); if (!cartridge) { cout << "ERROR: unable to determine cartridge type" << endl; diff --git a/src/emucore/ProfilingRunner.hxx b/src/emucore/ProfilingRunner.hxx index bb9d298e2..40ee04823 100644 --- a/src/emucore/ProfilingRunner.hxx +++ b/src/emucore/ProfilingRunner.hxx @@ -18,6 +18,8 @@ #ifndef PROFILING_RUNNER #define PROFILING_RUNNER +class OSystem; + #include "bspf.hxx" #include "Control.hxx" #include "Switches.hxx" @@ -57,6 +59,7 @@ class ProfilingRunner { vector profilingRuns; + unique_ptr myOSystem; Settings mySettings; Properties myProps;