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);
|
myRamReadAccesses.reserve(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void Cartridge::setProperties(const Properties* props)
|
||||||
|
{
|
||||||
|
myProperties = props;
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Cartridge::setAbout(string_view about, string_view type, string_view id)
|
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(const Settings& settings, string_view md5);
|
||||||
~Cartridge() override = default;
|
~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.
|
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.
|
// If myRandomHotspots is true, peeks to hotspots return semi-random values.
|
||||||
bool myRandomHotspots{false};
|
bool myRandomHotspots{false};
|
||||||
|
|
||||||
|
// Game properties. Set after construction when Console is created
|
||||||
|
const Properties* myProperties{nullptr};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The startup bank to use (where to look for the reset vector address)
|
// The startup bank to use (where to look for the reset vector address)
|
||||||
uInt16 myStartBank{0};
|
uInt16 myStartBank{0};
|
||||||
|
|
|
@ -22,10 +22,10 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "System.hxx"
|
#include "System.hxx"
|
||||||
#include "ElfParser.hxx"
|
|
||||||
#include "ElfLinker.hxx"
|
#include "ElfLinker.hxx"
|
||||||
#include "ElfEnvironment.hxx"
|
#include "ElfEnvironment.hxx"
|
||||||
#include "Logger.hxx"
|
#include "Logger.hxx"
|
||||||
|
#include "Props.hxx"
|
||||||
#include "exception/FatalEmulationError.hxx"
|
#include "exception/FatalEmulationError.hxx"
|
||||||
|
|
||||||
#include "CartELF.hxx"
|
#include "CartELF.hxx"
|
||||||
|
@ -174,6 +174,35 @@ namespace {
|
||||||
cout << "wrote executable image to " << IMAGE_FILE_NAME << '\n';
|
cout << "wrote executable image to " << IMAGE_FILE_NAME << '\n';
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
} // namespace
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -205,6 +234,9 @@ void CartridgeELF::reset()
|
||||||
myDriveBusValue = 0;
|
myDriveBusValue = 0;
|
||||||
myArmCyclesOffset = 0;
|
myArmCyclesOffset = 0;
|
||||||
|
|
||||||
|
mySystemType = determineSystemType(myProperties);
|
||||||
|
myLinker->relink(externalSymbols(mySystemType));
|
||||||
|
|
||||||
std::memset(mySectionStack.get(), 0, STACK_SIZE);
|
std::memset(mySectionStack.get(), 0, STACK_SIZE);
|
||||||
std::memset(mySectionText.get(), 0, TEXT_SIZE);
|
std::memset(mySectionText.get(), 0, TEXT_SIZE);
|
||||||
std::memset(mySectionData.get(), 0, DATA_SIZE);
|
std::memset(mySectionData.get(), 0, DATA_SIZE);
|
||||||
|
@ -361,21 +393,19 @@ inline uInt8 CartridgeELF::driveBus(uInt16 address, uInt8 value)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void CartridgeELF::parseAndLinkElf()
|
void CartridgeELF::parseAndLinkElf()
|
||||||
{
|
{
|
||||||
ElfParser elfParser;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
elfParser.parse(myImage.get(), myImageSize);
|
myElfParser.parse(myImage.get(), myImageSize);
|
||||||
} catch (ElfParser::ElfParseError& e) {
|
} catch (ElfParser::ElfParseError& e) {
|
||||||
throw runtime_error("failed to initialize ELF: " + string(e.what()));
|
throw runtime_error("failed to initialize ELF: " + string(e.what()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DUMP_ELF
|
#ifdef DUMP_ELF
|
||||||
dumpElf(elfParser);
|
dumpElf(myElfParser);
|
||||||
#endif
|
#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 {
|
try {
|
||||||
myLinker->link(externalSymbols(Palette::ntsc));
|
myLinker->link(externalSymbols(SystemType::ntsc));
|
||||||
} catch (const ElfLinker::ElfLinkError& e) {
|
} catch (const ElfLinker::ElfLinkError& e) {
|
||||||
throw runtime_error("failed to link ELF: " + string(e.what()));
|
throw runtime_error("failed to link ELF: " + string(e.what()));
|
||||||
}
|
}
|
||||||
|
@ -396,7 +426,7 @@ void CartridgeELF::parseAndLinkElf()
|
||||||
throw runtime_error("rodata segment too large");
|
throw runtime_error("rodata segment too large");
|
||||||
|
|
||||||
#ifdef DUMP_ELF
|
#ifdef DUMP_ELF
|
||||||
dumpLinkage(elfParser, *myLinker);
|
dumpLinkage(myElfParser, *myLinker);
|
||||||
|
|
||||||
cout
|
cout
|
||||||
<< "\nARM entrypoint: 0x"
|
<< "\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()
|
void CartridgeELF::switchExecutionStage()
|
||||||
{
|
{
|
||||||
|
@ -525,7 +538,7 @@ void CartridgeELF::callMain()
|
||||||
err |= myCortexEmu.write32(sp, getCoreClock());
|
err |= myCortexEmu.write32(sp, getCoreClock());
|
||||||
|
|
||||||
sp -= 4;
|
sp -= 4;
|
||||||
err |= myCortexEmu.write32(sp, getSystemType());
|
err |= myCortexEmu.write32(sp, getSystemTypeParam(mySystemType));
|
||||||
|
|
||||||
if (err) throw runtime_error("unable to setup main args");
|
if (err) throw runtime_error("unable to setup main args");
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "Cart.hxx"
|
#include "Cart.hxx"
|
||||||
#include "CortexM0.hxx"
|
#include "CortexM0.hxx"
|
||||||
|
#include "ElfEnvironment.hxx"
|
||||||
|
#include "ElfParser.hxx"
|
||||||
#include "BusTransactionQueue.hxx"
|
#include "BusTransactionQueue.hxx"
|
||||||
#include "VcsLib.hxx"
|
#include "VcsLib.hxx"
|
||||||
|
|
||||||
|
@ -84,7 +86,6 @@ class CartridgeELF: public Cartridge {
|
||||||
void setupMemoryMap();
|
void setupMemoryMap();
|
||||||
|
|
||||||
uInt32 getCoreClock() const;
|
uInt32 getCoreClock() const;
|
||||||
uInt32 getSystemType() const;
|
|
||||||
|
|
||||||
void switchExecutionStage();
|
void switchExecutionStage();
|
||||||
void callFn(uInt32 ptr, uInt32 sp);
|
void callFn(uInt32 ptr, uInt32 sp);
|
||||||
|
@ -107,6 +108,7 @@ class CartridgeELF: public Cartridge {
|
||||||
uInt32 myArmEntrypoint{0};
|
uInt32 myArmEntrypoint{0};
|
||||||
|
|
||||||
CortexM0 myCortexEmu;
|
CortexM0 myCortexEmu;
|
||||||
|
ElfParser myElfParser;
|
||||||
unique_ptr<ElfLinker> myLinker;
|
unique_ptr<ElfLinker> myLinker;
|
||||||
|
|
||||||
unique_ptr<uInt8[]> mySectionStack;
|
unique_ptr<uInt8[]> mySectionStack;
|
||||||
|
@ -126,6 +128,8 @@ class CartridgeELF: public Cartridge {
|
||||||
ExecutionStage myExecutionStage{ExecutionStage::boot};
|
ExecutionStage myExecutionStage{ExecutionStage::boot};
|
||||||
uInt32 myInitFunctionIndex{0};
|
uInt32 myInitFunctionIndex{0};
|
||||||
|
|
||||||
|
elfEnvironment::SystemType mySystemType{elfEnvironment::SystemType::ntsc};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
CartridgeELF(const CartridgeELF&) = delete;
|
CartridgeELF(const CartridgeELF&) = delete;
|
||||||
|
|
|
@ -120,6 +120,8 @@ Console::Console(OSystem& osystem, unique_ptr<Cartridge>& cart,
|
||||||
myCart{std::move(cart)},
|
myCart{std::move(cart)},
|
||||||
myAudioSettings{audioSettings}
|
myAudioSettings{audioSettings}
|
||||||
{
|
{
|
||||||
|
myCart->setProperties(&myProperties);
|
||||||
|
|
||||||
// Create subsystems for the console
|
// Create subsystems for the console
|
||||||
my6502 = make_unique<M6502>(myOSystem.settings());
|
my6502 = make_unique<M6502>(myOSystem.settings());
|
||||||
myRiot = make_unique<M6532>(*this, 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 = {
|
static const vector<ElfLinker::ExternalSymbol> EXTERNAL_SYMBOLS_STATIC = {
|
||||||
{"ADDR_IDR", ADDR_ADDR_IDR + 1},
|
{"ADDR_IDR", ADDR_ADDR_IDR + 1},
|
||||||
|
@ -166,7 +166,7 @@ vector<ElfLinker::ExternalSymbol> elfEnvironment::externalSymbols(elfEnvironment
|
||||||
externalSymbols = EXTERNAL_SYMBOLS_STATIC;
|
externalSymbols = EXTERNAL_SYMBOLS_STATIC;
|
||||||
externalSymbols.push_back({
|
externalSymbols.push_back({
|
||||||
"ColorLookup",
|
"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;
|
return externalSymbols;
|
||||||
|
|
|
@ -117,9 +117,9 @@ namespace elfEnvironment {
|
||||||
|
|
||||||
constexpr uInt32 QUEUE_SIZE_LIMIT = 10;
|
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
|
} // namespace elfEnvironment
|
||||||
|
|
||||||
#endif // ELF_ENVIRONMENT
|
#endif // ELF_ENVIRONMENT
|
||||||
|
|
|
@ -71,11 +71,20 @@ void ElfLinker::link(const vector<ExternalSymbol>& externalSymbols)
|
||||||
myDataData.reset();
|
myDataData.reset();
|
||||||
myRodataData.reset();
|
myRodataData.reset();
|
||||||
myRelocatedSections.resize(0);
|
myRelocatedSections.resize(0);
|
||||||
|
|
||||||
|
relocateSections();
|
||||||
|
|
||||||
|
relink(externalSymbols);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void ElfLinker::relink(const vector<ExternalSymbol>& externalSymbols)
|
||||||
|
{
|
||||||
myRelocatedSymbols.resize(0);
|
myRelocatedSymbols.resize(0);
|
||||||
myInitArray.resize(0);
|
myInitArray.resize(0);
|
||||||
myPreinitArray.resize(0);
|
myPreinitArray.resize(0);
|
||||||
|
|
||||||
relocateSections();
|
copySections();
|
||||||
relocateSymbols(externalSymbols);
|
relocateSymbols(externalSymbols);
|
||||||
relocateInitArrays();
|
relocateInitArrays();
|
||||||
applyRelocationsToSections();
|
applyRelocationsToSections();
|
||||||
|
@ -266,6 +275,12 @@ void ElfLinker::relocateSections()
|
||||||
segmentData = make_unique<uInt8[]>(segmentSize);
|
segmentData = make_unique<uInt8[]>(segmentSize);
|
||||||
std::memset(segmentData.get(), 0, segmentSize);
|
std::memset(segmentData.get(), 0, segmentSize);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void ElfLinker::copySections()
|
||||||
|
{
|
||||||
|
const auto& sections = myElf.getSections();
|
||||||
|
|
||||||
// copy segment data
|
// copy segment data
|
||||||
for (size_t i = 0; i < sections.size(); i++) {
|
for (size_t i = 0; i < sections.size(); i++) {
|
||||||
|
|
|
@ -81,6 +81,7 @@ class ElfLinker {
|
||||||
|
|
||||||
ElfLinker& setUndefinedSymbolDefault(uInt32 defaultValue);
|
ElfLinker& setUndefinedSymbolDefault(uInt32 defaultValue);
|
||||||
void link(const vector<ExternalSymbol>& externalSymbols);
|
void link(const vector<ExternalSymbol>& externalSymbols);
|
||||||
|
void relink(const vector<ExternalSymbol>& externalSymbols);
|
||||||
|
|
||||||
uInt32 getSegmentSize(SegmentType type) const;
|
uInt32 getSegmentSize(SegmentType type) const;
|
||||||
const uInt8* getSegmentData(SegmentType type) const;
|
const uInt8* getSegmentData(SegmentType type) const;
|
||||||
|
@ -99,6 +100,7 @@ class ElfLinker {
|
||||||
unique_ptr<uInt8[]>& getSegmentDataRef(SegmentType type);
|
unique_ptr<uInt8[]>& getSegmentDataRef(SegmentType type);
|
||||||
|
|
||||||
void relocateSections();
|
void relocateSections();
|
||||||
|
void copySections();
|
||||||
void relocateInitArrays();
|
void relocateInitArrays();
|
||||||
void relocateSymbols(const vector<ExternalSymbol>& externalSymbols);
|
void relocateSymbols(const vector<ExternalSymbol>& externalSymbols);
|
||||||
void applyRelocationsToSections();
|
void applyRelocationsToSections();
|
||||||
|
|
Loading…
Reference in New Issue