diff --git a/src/emucore/Bankswitch.cxx b/src/emucore/Bankswitch.cxx index dbdec5e2b..b32abf5d5 100644 --- a/src/emucore/Bankswitch.cxx +++ b/src/emucore/Bankswitch.cxx @@ -199,7 +199,7 @@ Bankswitch::Sizes = {{ { 8_KB, 8_KB+5 }, // _WDSW { 8_KB, 8_KB }, // _WF8 { 64_KB, 64_KB }, // _X07 - { 4_KB, Bankswitch::any_KB }, // ELF + { Bankswitch::any_KB, Bankswitch::any_KB }, // ELF #if defined(CUSTOM_ARM) { Bankswitch::any_KB, Bankswitch::any_KB } #endif diff --git a/src/emucore/CartDetector.cxx b/src/emucore/CartDetector.cxx index 8a5b8d17d..1d01b8ac0 100755 --- a/src/emucore/CartDetector.cxx +++ b/src/emucore/CartDetector.cxx @@ -27,7 +27,7 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si // Guess type based on size Bankswitch::Type type = Bankswitch::Type::_AUTO; - if (size >= 4_KB && isProbablyELF(image, size)) { + if (size >= 128 && isProbablyELF(image, size)) { type =Bankswitch::Type::_ELF; } else if ((size % 8448) == 0 || size == 6_KB) @@ -865,7 +865,7 @@ bool CartDetector::isProbablyELF(const ByteBuffer& image, size_t size) { // Must start with ELF magic static constexpr uInt8 signature[] = { 0x7f, 'E', 'L', 'F' }; - if (!searchForBytes(image, sizeof(signature), signature, sizeof(signature), 1)) return false; + if (!searchForBytes(image, 2 * sizeof(signature), signature, sizeof(signature), 1)) return false; // We require little endian if (image[0x05] != 1) return false; diff --git a/src/emucore/CartELF.cxx b/src/emucore/CartELF.cxx index 77415eb37..462fbda6b 100644 --- a/src/emucore/CartELF.cxx +++ b/src/emucore/CartELF.cxx @@ -15,8 +15,17 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ +#include + +#include "System.hxx" +#include "exception/FatalEmulationError.hxx" + #include "CartELF.hxx" +namespace { + constexpr size_t READ_STREAM_CAPACITY = 512; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeELF::CartridgeELF(const ByteBuffer& image, size_t size, string_view md5, const Settings& settings) @@ -24,6 +33,8 @@ CartridgeELF::CartridgeELF(const ByteBuffer& image, size_t size, string_view md5 { myImage = make_unique(size); std::memcpy(myImage.get(), image.get(), size); + + createRomAccessArrays(0x1000); } @@ -31,10 +42,24 @@ CartridgeELF::CartridgeELF(const ByteBuffer& image, size_t size, string_view md5 CartridgeELF::~CartridgeELF() {} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeELF::reset() {} +void CartridgeELF::reset() +{ + myReadStream.Reset(); +} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeELF::install(System& system) {} +void CartridgeELF::install(System& system) +{ + mySystem = &system; + + for (size_t addr = 0; addr < 0x1000; addr += System::PAGE_SIZE) { + System::PageAccess access(this, System::PageAccessType::READ); + access.romPeekCounter = &myRomAccessCounter[addr]; + access.romPokeCounter = &myRomAccessCounter[addr]; + + mySystem->setPageAccess(0x1000 + addr, access); + } +} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeELF::save(Serializer& out) const @@ -51,7 +76,7 @@ bool CartridgeELF::load(Serializer& in) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 CartridgeELF::peek(uInt16 address) { - return 0; + return myReadStream.Pop(address); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -66,3 +91,69 @@ const ByteBuffer& CartridgeELF::getImage(size_t& size) const size = myImageSize; return myImage; } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +CartridgeELF::ReadStream::ReadStream() +{ + myStream = make_unique(READ_STREAM_CAPACITY); + Reset(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeELF::ReadStream::Reset() +{ + myStreamNext = myStreamSize = 0; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeELF::ReadStream::Push(uInt8 value) +{ + if (myNextReadAddress == 0xfff) + throw FatalEmulationError("read stream has reached the end of address space"); + + Push(value, myNextReadAddress + 1); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeELF::ReadStream::Push(uInt8 value, uInt8 address) +{ + if (myStreamSize == READ_STREAM_CAPACITY) + throw FatalEmulationError("read stream overflow"); + + address &= 0xfff; + + myStream[(myStreamNext + myStreamSize++) % READ_STREAM_CAPACITY] = + {.address = address, .value = value}; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeELF::ReadStream::HasPendingRead() const +{ + return myStreamSize > 0; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt16 CartridgeELF::ReadStream::GetNextReadAddress() const +{ + return myNextReadAddress; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 CartridgeELF::ReadStream::Pop(uInt16 readAddress) +{ + if (myStreamSize == 0) + throw FatalEmulationError("read stream underflow"); + + if ((readAddress & 0xfff) != myNextReadAddress) + { + ostringstream s; + s << "unexcpected cartridge read from 0x" << std::hex << std::setw(4) << readAddress; + + throw FatalEmulationError(s.str()); + } + + const uInt8 value = myStream[myStreamNext++].value; + myStreamNext %= READ_STREAM_CAPACITY; + + return value; +} diff --git a/src/emucore/CartELF.hxx b/src/emucore/CartELF.hxx index dd2a16dc6..c13003b94 100644 --- a/src/emucore/CartELF.hxx +++ b/src/emucore/CartELF.hxx @@ -51,9 +51,40 @@ class CartridgeELF: public Cartridge { string name() const override { return "CartridgeELF"; }; + private: + struct ScheduledRead { + uInt16 address; + uInt8 value; + }; + + class ReadStream { + public: + ReadStream(); + + void Reset(); + + void Push(uInt8 value); + void Push(uInt8 value, uInt8 address); + + bool HasPendingRead() const; + uInt16 GetNextReadAddress() const; + uInt8 Pop(uInt16 readAddress); + + private: + unique_ptr myStream; + size_t myStreamNext{0}; + size_t myStreamSize{0}; + + uInt16 myNextReadAddress{0}; + }; + private: ByteBuffer myImage; size_t myImageSize{0}; + + System* mySystem{nullptr}; + + ReadStream myReadStream; }; #endif // CARTRIDGE_ELF