mirror of https://github.com/stella-emu/stella.git
Set ELF system type and palette according to game props.
This commit is contained in:
parent
b45eb6247d
commit
a515988b0a
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue