Fix ELF signature detection, read value stream.

This commit is contained in:
Christian Speckner 2024-06-30 11:56:07 +02:00
parent 8eb0d72eac
commit 41c8bff0c6
4 changed files with 128 additions and 6 deletions

View File

@ -199,7 +199,7 @@ Bankswitch::Sizes = {{
{ 8_KB, 8_KB+5 }, // _WDSW { 8_KB, 8_KB+5 }, // _WDSW
{ 8_KB, 8_KB }, // _WF8 { 8_KB, 8_KB }, // _WF8
{ 64_KB, 64_KB }, // _X07 { 64_KB, 64_KB }, // _X07
{ 4_KB, Bankswitch::any_KB }, // ELF { Bankswitch::any_KB, Bankswitch::any_KB }, // ELF
#if defined(CUSTOM_ARM) #if defined(CUSTOM_ARM)
{ Bankswitch::any_KB, Bankswitch::any_KB } { Bankswitch::any_KB, Bankswitch::any_KB }
#endif #endif

View File

@ -27,7 +27,7 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si
// Guess type based on size // Guess type based on size
Bankswitch::Type type = Bankswitch::Type::_AUTO; Bankswitch::Type type = Bankswitch::Type::_AUTO;
if (size >= 4_KB && isProbablyELF(image, size)) { if (size >= 128 && isProbablyELF(image, size)) {
type =Bankswitch::Type::_ELF; type =Bankswitch::Type::_ELF;
} }
else if ((size % 8448) == 0 || size == 6_KB) 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 // Must start with ELF magic
static constexpr uInt8 signature[] = { 0x7f, 'E', 'L', 'F' }; 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 // We require little endian
if (image[0x05] != 1) return false; if (image[0x05] != 1) return false;

View File

@ -15,8 +15,17 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================ //============================================================================
#include <sstream>
#include "System.hxx"
#include "exception/FatalEmulationError.hxx"
#include "CartELF.hxx" #include "CartELF.hxx"
namespace {
constexpr size_t READ_STREAM_CAPACITY = 512;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeELF::CartridgeELF(const ByteBuffer& image, size_t size, string_view md5, CartridgeELF::CartridgeELF(const ByteBuffer& image, size_t size, string_view md5,
const Settings& settings) const Settings& settings)
@ -24,6 +33,8 @@ CartridgeELF::CartridgeELF(const ByteBuffer& image, size_t size, string_view md5
{ {
myImage = make_unique<uInt8[]>(size); myImage = make_unique<uInt8[]>(size);
std::memcpy(myImage.get(), image.get(), 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() {} 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 bool CartridgeELF::save(Serializer& out) const
@ -51,7 +76,7 @@ bool CartridgeELF::load(Serializer& in)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeELF::peek(uInt16 address) 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; size = myImageSize;
return myImage; return myImage;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeELF::ReadStream::ReadStream()
{
myStream = make_unique<ScheduledRead[]>(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;
}

View File

@ -51,9 +51,40 @@ class CartridgeELF: public Cartridge {
string name() const override { return "CartridgeELF"; }; 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<ScheduledRead[]> myStream;
size_t myStreamNext{0};
size_t myStreamSize{0};
uInt16 myNextReadAddress{0};
};
private: private:
ByteBuffer myImage; ByteBuffer myImage;
size_t myImageSize{0}; size_t myImageSize{0};
System* mySystem{nullptr};
ReadStream myReadStream;
}; };
#endif // CARTRIDGE_ELF #endif // CARTRIDGE_ELF