diff --git a/src/emucore/CartELF.cxx b/src/emucore/CartELF.cxx index 6b8e183dd..48ac1c1bb 100644 --- a/src/emucore/CartELF.cxx +++ b/src/emucore/CartELF.cxx @@ -189,8 +189,6 @@ CartridgeELF::CartridgeELF(const ByteBuffer& image, size_t size, string_view md5 parseAndLinkElf(); setupMemoryMap(); - - reset(); } @@ -230,6 +228,8 @@ void CartridgeELF::reset() myVcsLib.vcsStartOverblank(); myVcsLib.vcsEndOverblank(); myVcsLib.vcsNop2n(1024); + + jumpToMain(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -277,6 +277,11 @@ bool CartridgeELF::poke(uInt16 address, uInt8 value) return false; } +void CartridgeELF::consoleChanged(ConsoleTiming timing) +{ + myConsoleTiming = timing; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - const ByteBuffer& CartridgeELF::getImage(size_t& size) const { @@ -284,6 +289,7 @@ const ByteBuffer& CartridgeELF::getImage(size_t& size) const return myImage; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 CartridgeELF::overdrivePeek(uInt16 address, uInt8 value) { value = driveBus(address, value); @@ -296,11 +302,13 @@ uInt8 CartridgeELF::overdrivePeek(uInt16 address, uInt8 value) return value; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 CartridgeELF::overdrivePoke(uInt16 address, uInt8 value) { return driveBus(address, value); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inline uInt8 CartridgeELF::driveBus(uInt16 address, uInt8 value) { auto* nextTransaction = myTransactionQueue.getNextTransaction(address); @@ -311,6 +319,7 @@ inline uInt8 CartridgeELF::driveBus(uInt16 address, uInt8 value) return value; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeELF::parseAndLinkElf() { ElfParser elfParser; @@ -359,6 +368,7 @@ void CartridgeELF::parseAndLinkElf() #endif } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeELF::setupMemoryMap() { mySectionStack = make_unique(STACK_SIZE); @@ -382,4 +392,63 @@ void CartridgeELF::setupMemoryMap() STUB_SIZE / CortexM0::PAGE_SIZE, true, &myVcsLib); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt32 CartridgeELF::getCoreClock() const +{ + switch (myConsoleTiming) { + case ConsoleTiming::ntsc: + return myArmCyclesPer6502Cycle * 262 * 76 * 60; + + case ConsoleTiming::pal: + case ConsoleTiming::secam: + return myArmCyclesPer6502Cycle * 312 * 76 * 50; + + default: + throw runtime_error("invalid console timing"); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +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::jumpToMain() +{ + if (!mySystem) throw runtime_error("cartridge not installed"); + + uInt32 sp = ADDR_STACK_BASE + STACK_SIZE; + CortexM0::err_t err = 0; + + // Feature flags + sp -= 4; + err |= myCortexEmu.write32(sp, 0); + + sp -= 4; + err |= myCortexEmu.write32(sp, getCoreClock()); + + sp -= 4; + err |= myCortexEmu.write32(sp, getSystemType()); + + if (err) throw runtime_error("unable to setup main args"); + + myCortexEmu + .setRegister(0, sp ) + .setRegister(14, RETURN_ADDR_MAIN) + .setRegister(15, myArmEntrypoint); +} + diff --git a/src/emucore/CartELF.hxx b/src/emucore/CartELF.hxx index ca3be468e..f5186859c 100644 --- a/src/emucore/CartELF.hxx +++ b/src/emucore/CartELF.hxx @@ -47,6 +47,8 @@ class CartridgeELF: public Cartridge { bool poke(uInt16 address, uInt8 value) override; + void consoleChanged(ConsoleTiming timing) override; + // Methods from Cartridge public: bool bankChanged() override { return false; } @@ -66,10 +68,13 @@ class CartridgeELF: public Cartridge { private: uInt8 driveBus(uInt16 address, uInt8 value); - private: void parseAndLinkElf(); void setupMemoryMap(); + uInt32 getCoreClock() const; + uInt32 getSystemType() const; + void jumpToMain(); + private: ByteBuffer myImage; size_t myImageSize{0}; @@ -94,6 +99,9 @@ class CartridgeELF: public Cartridge { unique_ptr mySectionTables; VcsLib myVcsLib; + + ConsoleTiming myConsoleTiming{ConsoleTiming::ntsc}; + uInt32 myArmCyclesPer6502Cycle{80}; }; #endif // CARTRIDGE_ELF diff --git a/src/emucore/CortexM0.hxx b/src/emucore/CortexM0.hxx index d16666123..babf422f3 100644 --- a/src/emucore/CortexM0.hxx +++ b/src/emucore/CortexM0.hxx @@ -105,6 +105,14 @@ class CortexM0 err_t run(uInt32 maxCycles, uInt32& cycles); + err_t read32(uInt32 address, uInt32& value); + err_t read16(uInt32 address, uInt16& value); + err_t read8(uInt32 address, uInt8& value); + + err_t write32(uInt32 address, uInt32 value); + err_t write16(uInt32 address, uInt16 value); + err_t write8(uInt32 address, uInt8 value); + private: enum class MemoryRegionType : uInt8 { @@ -154,14 +162,6 @@ class CortexM0 MemoryRegion& setupMapping(uInt32 pageBase, uInt32 pageCount, bool readOnly, MemoryRegionType type); - err_t read32(uInt32 address, uInt32& value); - err_t read16(uInt32 address, uInt16& value); - err_t read8(uInt32 address, uInt8& value); - - err_t write32(uInt32 address, uInt32 value); - err_t write16(uInt32 address, uInt16 value); - err_t write8(uInt32 address, uInt8 value); - err_t fetch16(uInt32 address, uInt16& value, uInt8& op); void do_cvflag(uInt32 a, uInt32 b, uInt32 c); diff --git a/src/emucore/elf/ElfEnvironment.hxx b/src/emucore/elf/ElfEnvironment.hxx index a190c0cd0..e90c51daa 100644 --- a/src/emucore/elf/ElfEnvironment.hxx +++ b/src/emucore/elf/ElfEnvironment.hxx @@ -106,6 +106,12 @@ namespace elfEnvironment { extern const uInt8 OVERBLANK_PROGRAM[]; extern const uInt32 OVERBLANK_PROGRAM_SIZE; + constexpr uInt32 ST_NTSC_2600 = 0; + constexpr uInt32 ST_PAL_2600 = 1; + constexpr uInt32 ST_PAL60_2600 = 2; + + constexpr uInt32 RETURN_ADDR_MAIN = 0xffffdead; + enum class Palette: uInt8 {pal, ntsc}; vector externalSymbols(Palette palette); diff --git a/src/emucore/elf/VcsLib.cxx b/src/emucore/elf/VcsLib.cxx index e25cdbed4..668f89641 100644 --- a/src/emucore/elf/VcsLib.cxx +++ b/src/emucore/elf/VcsLib.cxx @@ -55,6 +55,7 @@ void VcsLib::vcsStartOverblank() .yield(0x0080); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void VcsLib::vcsEndOverblank() { myTransactionQueue @@ -63,6 +64,7 @@ void VcsLib::vcsEndOverblank() .setNextInjectAddress(0x1000); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void VcsLib::vcsNop2n(uInt16 n) { if (n == 0) return;