From a515988b0a9e84848a9ed5d0e12ddd82eeabfc98 Mon Sep 17 00:00:00 2001 From: Christian Speckner Date: Sat, 10 Aug 2024 12:35:52 +0200 Subject: [PATCH] Set ELF system type and palette according to game props. --- src/emucore/Cart.cxx | 6 +++ src/emucore/Cart.hxx | 10 +++++ src/emucore/CartELF.cxx | 65 ++++++++++++++++++------------ src/emucore/CartELF.hxx | 6 ++- src/emucore/Console.cxx | 2 + src/emucore/elf/ElfEnvironment.cxx | 4 +- src/emucore/elf/ElfEnvironment.hxx | 4 +- src/emucore/elf/ElfLinker.cxx | 17 +++++++- src/emucore/elf/ElfLinker.hxx | 2 + 9 files changed, 84 insertions(+), 32 deletions(-) diff --git a/src/emucore/Cart.cxx b/src/emucore/Cart.cxx index 3c98e1c93..881dc6d27 100644 --- a/src/emucore/Cart.cxx +++ b/src/emucore/Cart.cxx @@ -42,6 +42,12 @@ Cartridge::Cartridge(const Settings& settings, string_view md5) myRamReadAccesses.reserve(5); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Cartridge::setProperties(const Properties* props) +{ + myProperties = props; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Cartridge::setAbout(string_view about, string_view type, string_view id) { diff --git a/src/emucore/Cart.hxx b/src/emucore/Cart.hxx index ea09b34ef..ec9448354 100644 --- a/src/emucore/Cart.hxx +++ b/src/emucore/Cart.hxx @@ -66,6 +66,13 @@ class Cartridge : public Device Cartridge(const Settings& settings, string_view md5); ~Cartridge() override = default; + /** + * @brief Set the game properties container + * + * @param props game properties container + */ + void setProperties(const Properties* props); + /** Set/query some information about this cartridge. */ @@ -450,6 +457,9 @@ class Cartridge : public Device // If myRandomHotspots is true, peeks to hotspots return semi-random values. bool myRandomHotspots{false}; + // Game properties. Set after construction when Console is created + const Properties* myProperties{nullptr}; + private: // The startup bank to use (where to look for the reset vector address) uInt16 myStartBank{0}; diff --git a/src/emucore/CartELF.cxx b/src/emucore/CartELF.cxx index 23577308c..ba5f60dff 100644 --- a/src/emucore/CartELF.cxx +++ b/src/emucore/CartELF.cxx @@ -22,10 +22,10 @@ #endif #include "System.hxx" -#include "ElfParser.hxx" #include "ElfLinker.hxx" #include "ElfEnvironment.hxx" #include "Logger.hxx" +#include "Props.hxx" #include "exception/FatalEmulationError.hxx" #include "CartELF.hxx" @@ -174,6 +174,35 @@ namespace { cout << "wrote executable image to " << IMAGE_FILE_NAME << '\n'; } #endif + + SystemType determineSystemType(const Properties* props) + { + if (!props) return SystemType::ntsc; + + string displayFormat = props->get(PropType::Display_Format); + + if(displayFormat == "PAL" || displayFormat == "SECAM") return SystemType::pal; + if(displayFormat == "PAL60") return SystemType::pal60; + + return SystemType::ntsc; + } + + uInt32 getSystemTypeParam(SystemType systemType) + { + switch (systemType) { + case SystemType::ntsc: + return ST_NTSC_2600; + + case SystemType::pal: + return ST_PAL_2600; + + case SystemType::pal60: + return ST_PAL60_2600; + + default: + throw runtime_error("invalid system type"); + } +} } // namespace // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -205,6 +234,9 @@ void CartridgeELF::reset() myDriveBusValue = 0; myArmCyclesOffset = 0; + mySystemType = determineSystemType(myProperties); + myLinker->relink(externalSymbols(mySystemType)); + std::memset(mySectionStack.get(), 0, STACK_SIZE); std::memset(mySectionText.get(), 0, TEXT_SIZE); std::memset(mySectionData.get(), 0, DATA_SIZE); @@ -361,21 +393,19 @@ inline uInt8 CartridgeELF::driveBus(uInt16 address, uInt8 value) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeELF::parseAndLinkElf() { - ElfParser elfParser; - try { - elfParser.parse(myImage.get(), myImageSize); + myElfParser.parse(myImage.get(), myImageSize); } catch (ElfParser::ElfParseError& e) { throw runtime_error("failed to initialize ELF: " + string(e.what())); } #ifdef DUMP_ELF - dumpElf(elfParser); + dumpElf(myElfParser); #endif - myLinker = make_unique(ADDR_TEXT_BASE, ADDR_DATA_BASE, ADDR_RODATA_BASE, elfParser); + myLinker = make_unique(ADDR_TEXT_BASE, ADDR_DATA_BASE, ADDR_RODATA_BASE, myElfParser); try { - myLinker->link(externalSymbols(Palette::ntsc)); + myLinker->link(externalSymbols(SystemType::ntsc)); } catch (const ElfLinker::ElfLinkError& e) { throw runtime_error("failed to link ELF: " + string(e.what())); } @@ -396,7 +426,7 @@ void CartridgeELF::parseAndLinkElf() throw runtime_error("rodata segment too large"); #ifdef DUMP_ELF - dumpLinkage(elfParser, *myLinker); + dumpLinkage(myElfParser, *myLinker); cout << "\nARM entrypoint: 0x" @@ -448,23 +478,6 @@ uInt32 CartridgeELF::getCoreClock() const } } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeELF::getSystemType() const -{ - switch (myConsoleTiming) { - case ConsoleTiming::ntsc: - return ST_NTSC_2600; - - // Use frame layout here instead - case ConsoleTiming::pal: - case ConsoleTiming::secam: - return ST_PAL_2600; - - default: - throw runtime_error("invalid console timing"); - } -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeELF::switchExecutionStage() { @@ -525,7 +538,7 @@ void CartridgeELF::callMain() err |= myCortexEmu.write32(sp, getCoreClock()); sp -= 4; - err |= myCortexEmu.write32(sp, getSystemType()); + err |= myCortexEmu.write32(sp, getSystemTypeParam(mySystemType)); if (err) throw runtime_error("unable to setup main args"); diff --git a/src/emucore/CartELF.hxx b/src/emucore/CartELF.hxx index f87279692..7d763038b 100644 --- a/src/emucore/CartELF.hxx +++ b/src/emucore/CartELF.hxx @@ -21,6 +21,8 @@ #include "bspf.hxx" #include "Cart.hxx" #include "CortexM0.hxx" +#include "ElfEnvironment.hxx" +#include "ElfParser.hxx" #include "BusTransactionQueue.hxx" #include "VcsLib.hxx" @@ -84,7 +86,6 @@ class CartridgeELF: public Cartridge { void setupMemoryMap(); uInt32 getCoreClock() const; - uInt32 getSystemType() const; void switchExecutionStage(); void callFn(uInt32 ptr, uInt32 sp); @@ -107,6 +108,7 @@ class CartridgeELF: public Cartridge { uInt32 myArmEntrypoint{0}; CortexM0 myCortexEmu; + ElfParser myElfParser; unique_ptr myLinker; unique_ptr mySectionStack; @@ -126,6 +128,8 @@ class CartridgeELF: public Cartridge { ExecutionStage myExecutionStage{ExecutionStage::boot}; uInt32 myInitFunctionIndex{0}; + elfEnvironment::SystemType mySystemType{elfEnvironment::SystemType::ntsc}; + private: // Following constructors and assignment operators not supported CartridgeELF(const CartridgeELF&) = delete; diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx index 33182f445..b8d8fc9da 100644 --- a/src/emucore/Console.cxx +++ b/src/emucore/Console.cxx @@ -120,6 +120,8 @@ Console::Console(OSystem& osystem, unique_ptr& cart, myCart{std::move(cart)}, myAudioSettings{audioSettings} { + myCart->setProperties(&myProperties); + // Create subsystems for the console my6502 = make_unique(myOSystem.settings()); myRiot = make_unique(*this, myOSystem.settings()); diff --git a/src/emucore/elf/ElfEnvironment.cxx b/src/emucore/elf/ElfEnvironment.cxx index 19cdb77df..9963c049a 100644 --- a/src/emucore/elf/ElfEnvironment.cxx +++ b/src/emucore/elf/ElfEnvironment.cxx @@ -113,7 +113,7 @@ const uInt8 elfEnvironment::LOOKUP_TABLES[3 * 256] = { }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -vector elfEnvironment::externalSymbols(elfEnvironment::Palette palette) +vector elfEnvironment::externalSymbols(elfEnvironment::SystemType systemType) { static const vector EXTERNAL_SYMBOLS_STATIC = { {"ADDR_IDR", ADDR_ADDR_IDR + 1}, @@ -166,7 +166,7 @@ vector elfEnvironment::externalSymbols(elfEnvironment externalSymbols = EXTERNAL_SYMBOLS_STATIC; externalSymbols.push_back({ "ColorLookup", - palette == Palette::ntsc ? ADDR_TABLE_COLOR_LOOKUP_NTSC : ADDR_TABLE_COLOR_LOOKUP_PAL + systemType == SystemType::ntsc ? ADDR_TABLE_COLOR_LOOKUP_NTSC : ADDR_TABLE_COLOR_LOOKUP_PAL }); return externalSymbols; diff --git a/src/emucore/elf/ElfEnvironment.hxx b/src/emucore/elf/ElfEnvironment.hxx index a615d633d..fb20edc7f 100644 --- a/src/emucore/elf/ElfEnvironment.hxx +++ b/src/emucore/elf/ElfEnvironment.hxx @@ -117,9 +117,9 @@ namespace elfEnvironment { constexpr uInt32 QUEUE_SIZE_LIMIT = 10; - enum class Palette: uInt8 {pal, ntsc}; + enum class SystemType: uInt8 {ntsc, pal, pal60}; - vector externalSymbols(Palette palette); + vector externalSymbols(SystemType systemType); } // namespace elfEnvironment #endif // ELF_ENVIRONMENT diff --git a/src/emucore/elf/ElfLinker.cxx b/src/emucore/elf/ElfLinker.cxx index 7125647eb..ec1114317 100644 --- a/src/emucore/elf/ElfLinker.cxx +++ b/src/emucore/elf/ElfLinker.cxx @@ -71,11 +71,20 @@ void ElfLinker::link(const vector& externalSymbols) myDataData.reset(); myRodataData.reset(); myRelocatedSections.resize(0); + + relocateSections(); + + relink(externalSymbols); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void ElfLinker::relink(const vector& externalSymbols) +{ myRelocatedSymbols.resize(0); myInitArray.resize(0); myPreinitArray.resize(0); - relocateSections(); + copySections(); relocateSymbols(externalSymbols); relocateInitArrays(); applyRelocationsToSections(); @@ -266,6 +275,12 @@ void ElfLinker::relocateSections() segmentData = make_unique(segmentSize); std::memset(segmentData.get(), 0, segmentSize); } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void ElfLinker::copySections() +{ + const auto& sections = myElf.getSections(); // copy segment data for (size_t i = 0; i < sections.size(); i++) { diff --git a/src/emucore/elf/ElfLinker.hxx b/src/emucore/elf/ElfLinker.hxx index cf90dc61b..53f82232d 100644 --- a/src/emucore/elf/ElfLinker.hxx +++ b/src/emucore/elf/ElfLinker.hxx @@ -81,6 +81,7 @@ class ElfLinker { ElfLinker& setUndefinedSymbolDefault(uInt32 defaultValue); void link(const vector& externalSymbols); + void relink(const vector& externalSymbols); uInt32 getSegmentSize(SegmentType type) const; const uInt8* getSegmentData(SegmentType type) const; @@ -99,6 +100,7 @@ class ElfLinker { unique_ptr& getSegmentDataRef(SegmentType type); void relocateSections(); + void copySections(); void relocateInitArrays(); void relocateSymbols(const vector& externalSymbols); void applyRelocationsToSections();