Set ELF system type and palette according to game props.

This commit is contained in:
Christian Speckner 2024-08-10 12:35:52 +02:00
parent b45eb6247d
commit a515988b0a
9 changed files with 84 additions and 32 deletions

View File

@ -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)
{

View File

@ -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};

View File

@ -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<ElfLinker>(ADDR_TEXT_BASE, ADDR_DATA_BASE, ADDR_RODATA_BASE, elfParser);
myLinker = make_unique<ElfLinker>(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");

View File

@ -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<ElfLinker> myLinker;
unique_ptr<uInt8[]> 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;

View File

@ -120,6 +120,8 @@ Console::Console(OSystem& osystem, unique_ptr<Cartridge>& cart,
myCart{std::move(cart)},
myAudioSettings{audioSettings}
{
myCart->setProperties(&myProperties);
// Create subsystems for the console
my6502 = make_unique<M6502>(myOSystem.settings());
myRiot = make_unique<M6532>(*this, myOSystem.settings());

View File

@ -113,7 +113,7 @@ const uInt8 elfEnvironment::LOOKUP_TABLES[3 * 256] = {
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
vector<ElfLinker::ExternalSymbol> elfEnvironment::externalSymbols(elfEnvironment::Palette palette)
vector<ElfLinker::ExternalSymbol> elfEnvironment::externalSymbols(elfEnvironment::SystemType systemType)
{
static const vector<ElfLinker::ExternalSymbol> EXTERNAL_SYMBOLS_STATIC = {
{"ADDR_IDR", ADDR_ADDR_IDR + 1},
@ -166,7 +166,7 @@ vector<ElfLinker::ExternalSymbol> 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;

View File

@ -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<ElfLinker::ExternalSymbol> externalSymbols(Palette palette);
vector<ElfLinker::ExternalSymbol> externalSymbols(SystemType systemType);
} // namespace elfEnvironment
#endif // ELF_ENVIRONMENT

View File

@ -71,11 +71,20 @@ void ElfLinker::link(const vector<ExternalSymbol>& externalSymbols)
myDataData.reset();
myRodataData.reset();
myRelocatedSections.resize(0);
relocateSections();
relink(externalSymbols);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ElfLinker::relink(const vector<ExternalSymbol>& 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<uInt8[]>(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++) {

View File

@ -81,6 +81,7 @@ class ElfLinker {
ElfLinker& setUndefinedSymbolDefault(uInt32 defaultValue);
void link(const vector<ExternalSymbol>& externalSymbols);
void relink(const vector<ExternalSymbol>& externalSymbols);
uInt32 getSegmentSize(SegmentType type) const;
const uInt8* getSegmentData(SegmentType type) const;
@ -99,6 +100,7 @@ class ElfLinker {
unique_ptr<uInt8[]>& getSegmentDataRef(SegmentType type);
void relocateSections();
void copySections();
void relocateInitArrays();
void relocateSymbols(const vector<ExternalSymbol>& externalSymbols);
void applyRelocationsToSections();