From d8aa1806b63957d24e29a2659a54851a887467e0 Mon Sep 17 00:00:00 2001 From: spicyjpeg Date: Wed, 20 Mar 2024 18:25:11 +0100 Subject: [PATCH] X76 config fixes, add support for executables in flash images --- .editorconfig | 3 ++ cmake/setup.cmake | 2 +- cmake/toolchain.cmake | 2 +- src/common/rom.cpp | 16 ++++------- src/common/rom.hpp | 4 +++ src/launcher/main.cpp | 31 +++++++++++++------- src/main/app/miscworkers.cpp | 22 ++++++++++++--- src/main/cartio.cpp | 55 +++++++++++++++--------------------- src/main/uibase.cpp | 2 +- 9 files changed, 78 insertions(+), 59 deletions(-) diff --git a/.editorconfig b/.editorconfig index 93c80e1..f35696c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,3 +11,6 @@ insert_final_newline = true [{*.yml,*.yaml,.clangd}] indent_style = space indent_size = 2 + +[assets/about.txt] +trim_trailing_whitespace = false diff --git a/cmake/setup.cmake b/cmake/setup.cmake index 74cbb48..96877e5 100644 --- a/cmake/setup.cmake +++ b/cmake/setup.cmake @@ -79,5 +79,5 @@ target_link_options( -nostdlib -Wl,-gc-sections -G8 - -T${CMAKE_CURRENT_LIST_DIR}/executable.ld + "-T${CMAKE_CURRENT_LIST_DIR}/executable.ld" ) diff --git a/cmake/toolchain.cmake b/cmake/toolchain.cmake index 1ff733c..3514d58 100644 --- a/cmake/toolchain.cmake +++ b/cmake/toolchain.cmake @@ -34,7 +34,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # custom variables through to autogenerated "compiler test" projects. This will # prevent the compiler detection process from erroring out. set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) -set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES TOOLCHAIN_PATH TOOLCHAIN_TARGET) +set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES TOOLCHAIN_PATH) # Always generate compile_commands.json when building. This allows some IDEs and # tools (such as clangd) to automatically configure include directories and diff --git a/src/common/rom.cpp b/src/common/rom.cpp index d55f753..cab50f8 100644 --- a/src/common/rom.cpp +++ b/src/common/rom.cpp @@ -13,10 +13,6 @@ namespace rom { // TODO: implement bounds checks in these -static constexpr size_t _FLASH_BANK_LENGTH = 0x400000; -static constexpr uint32_t _FLASH_CRC_OFFSET = 0x20; -static constexpr uint32_t _FLASH_EXE_OFFSET = 0x24; - void Region::read(void *data, uint32_t offset, size_t length) const { auto source = reinterpret_cast(ptr + offset); auto dest = reinterpret_cast(data); @@ -93,8 +89,8 @@ void FlashRegion::read(void *data, uint32_t offset, size_t length) const { // The internal flash and PCMCIA cards can only be accessed 4 MB at a time. // FIXME: this implementation will not handle reads that cross bank // boundaries properly - int bankOffset = offset / _FLASH_BANK_LENGTH; - int ptrOffset = offset % _FLASH_BANK_LENGTH; + int bankOffset = offset / FLASH_BANK_LENGTH; + int ptrOffset = offset % FLASH_BANK_LENGTH; auto source = reinterpret_cast(ptr + ptrOffset); auto dest = reinterpret_cast(data); @@ -112,8 +108,8 @@ uint32_t FlashRegion::zipCRC32( ) const { // FIXME: this implementation will not handle reads that cross bank // boundaries properly - int bankOffset = offset / _FLASH_BANK_LENGTH; - int ptrOffset = offset % _FLASH_BANK_LENGTH; + int bankOffset = offset / FLASH_BANK_LENGTH; + int ptrOffset = offset % FLASH_BANK_LENGTH; auto source = reinterpret_cast(ptr + ptrOffset); auto table = reinterpret_cast(CACHE_BASE); @@ -140,8 +136,8 @@ uint32_t FlashRegion::zipCRC32( bool FlashRegion::hasBootExecutable(void) const { // FIXME: this implementation will not detect executables that cross bank // boundaries (but it shouldn't matter as executables must be <4 MB anyway) - auto data = reinterpret_cast(ptr + _FLASH_EXE_OFFSET); - auto crcPtr = reinterpret_cast(ptr + _FLASH_CRC_OFFSET); + auto data = reinterpret_cast(ptr + FLASH_EXE_OFFSET); + auto crcPtr = reinterpret_cast(ptr + FLASH_CRC_OFFSET); auto table = reinterpret_cast(CACHE_BASE); io::setFlashBank(bank); diff --git a/src/common/rom.hpp b/src/common/rom.hpp index 7136ba2..e3fd6a9 100644 --- a/src/common/rom.hpp +++ b/src/common/rom.hpp @@ -10,6 +10,10 @@ namespace rom { /* ROM region dumpers */ +static constexpr size_t FLASH_BANK_LENGTH = 0x400000; +static constexpr uint32_t FLASH_CRC_OFFSET = 0x20; +static constexpr uint32_t FLASH_EXE_OFFSET = 0x24; + class Region { public: uintptr_t ptr; diff --git a/src/launcher/main.cpp b/src/launcher/main.cpp index 1514561..285b74f 100644 --- a/src/launcher/main.cpp +++ b/src/launcher/main.cpp @@ -3,6 +3,7 @@ #include #include "common/ide.hpp" #include "common/io.hpp" +#include "common/rom.hpp" #include "common/util.hpp" #include "ps1/system.h" #include "vendor/ff.h" @@ -83,7 +84,7 @@ public: } bool openFile(void); - bool readHeader(void); + bool readHeader(uint64_t offset); bool readBody(void); void exit(void); [[noreturn]] void run(void); @@ -121,9 +122,13 @@ bool Launcher::openFile(void) { return true; } -bool Launcher::readHeader(void) { +bool Launcher::readHeader(uint64_t offset) { size_t length; + if (f_lseek(&_file, offset)) { + LOG("seek to header failed, path=%s", _settings.path); + return false; + } if (f_read(&_file, &_header, sizeof(_header), &length)) { LOG("header read failed, path=%s", _settings.path); return false; @@ -132,9 +137,13 @@ bool Launcher::readHeader(void) { LOG("invalid header length %d", length); return false; } + if (!_header.validateMagic()) { + LOG("invalid executable magic"); + return false; + } - if (_header.getTextPtr() >= _textStart) { - LOG("executable overlaps launcher"); + if (f_lseek(&_file, offset + util::EXECUTABLE_BODY_OFFSET)) { + LOG("seek to body failed, path=%s", _settings.path); return false; } @@ -145,10 +154,6 @@ bool Launcher::readHeader(void) { bool Launcher::readBody(void) { size_t length; - if (f_lseek(&_file, util::EXECUTABLE_BODY_OFFSET)) { - LOG("seek to body failed, path=%s", _settings.path); - return false; - } if (f_read(&_file, _header.getTextPtr(), _header.textLength, &length)) { LOG("body read failed, path=%s", _settings.path); return false; @@ -207,8 +212,14 @@ int main(int argc, const char **argv) { if (!launcher.openFile()) return 1; - if (!launcher.readHeader()) - return 2; + + if (!launcher.readHeader(0)) { + // If the file is not an executable, check if it is a flash image that + // contains an executable. Note that the CRC32 is not validated. + if (!launcher.readHeader(rom::FLASH_EXE_OFFSET)) + return 2; + } + if (!launcher.readBody()) return 3; diff --git a/src/main/app/miscworkers.cpp b/src/main/app/miscworkers.cpp index d62c45a..baedc09 100644 --- a/src/main/app/miscworkers.cpp +++ b/src/main/app/miscworkers.cpp @@ -292,15 +292,26 @@ bool App::_executableWorker(void) { size_t length; if (!_file) - goto _fileError; + goto _fileOpenError; length = _file->read(&header, sizeof(header)); - delete _file; if (length != sizeof(header)) goto _fileError; - if (!header.validateMagic()) - goto _fileError; + + if (!header.validateMagic()) { + // If the file is not an executable, check if it is a flash image that + // contains an executable. Note that the CRC32 is not validated. + _file->seek(rom::FLASH_EXE_OFFSET); + length = _file->read(&header, sizeof(header)); + + if (length != sizeof(header)) + goto _fileError; + if (!header.validateMagic()) + goto _fileError; + } + + delete _file; executableEnd = header.textOffset + header.textLength; stackTop = uintptr_t(header.getStackPtr()); @@ -378,6 +389,9 @@ bool App::_executableWorker(void) { return false; _fileError: + delete _file; + +_fileOpenError: _messageScreen.setMessage( MESSAGE_ERROR, _execPickerScreen, WSTR("App.executableWorker.fileError"), path diff --git a/src/main/cartio.cpp b/src/main/cartio.cpp index 8dcfd89..58f8102 100644 --- a/src/main/cartio.cpp +++ b/src/main/cartio.cpp @@ -276,17 +276,8 @@ DriverError X76F041Driver::readPrivateData(void) { if (error) return error; - io::i2cReadByte(); - io::i2cStart(); - - io::i2cWriteByte(0); - if (!io::i2cGetACK()) { - io::i2cStopWithCS(); - LOG("NACK after resending dummy byte"); - return X76_NACK; - } - - io::i2cReadBytes(_dump.config, 8); + _dump.clearConfig(); + io::i2cReadBytes(_dump.config, 5); io::i2cStopWithCS(); _dump.flags |= DUMP_CONFIG_OK; @@ -302,13 +293,13 @@ DriverError X76F041Driver::writeData(void) { if (error) return error; - if (!io::i2cWriteBytes(&_dump.data[i], 8)) { - io::i2cStopWithCS(_X76_WRITE_DELAY); + auto ok = io::i2cWriteBytes(&_dump.data[i], 8); + io::i2cStopWithCS(_X76_WRITE_DELAY); + + if (!ok) { LOG("NACK while sending data bytes"); return X76_NACK; } - - io::i2cStopWithCS(_X76_WRITE_DELAY); } auto error = _x76Command( @@ -317,14 +308,14 @@ DriverError X76F041Driver::writeData(void) { if (error) return error; - if (!io::i2cWriteBytes(_dump.config, 8)) { - io::i2cStopWithCS(_X76_WRITE_DELAY); - LOG("NACK while sending data bytes"); + auto ok = io::i2cWriteBytes(_dump.config, 5); + io::i2cStopWithCS(_X76_WRITE_DELAY); + + if (!ok) { + LOG("NACK while sending config registers"); return X76_NACK; } - io::i2cStopWithCS(_X76_WRITE_DELAY); - return NO_ERROR; } @@ -395,13 +386,13 @@ DriverError X76F100Driver::writeData(void) { if (error) return error; - if (!io::i2cWriteBytes(&_dump.data[i], 8)) { - io::i2cStopWithCS(_X76_WRITE_DELAY); + auto ok = io::i2cWriteBytes(&_dump.data[i], 8); + io::i2cStopWithCS(_X76_WRITE_DELAY); + + if (!ok) { LOG("NACK while sending data bytes"); return X76_NACK; } - - io::i2cStopWithCS(_X76_WRITE_DELAY); } return NO_ERROR; @@ -419,13 +410,13 @@ DriverError X76F100Driver::erase(void) { if (error) return error; - if (!io::i2cWriteBytes(dummy, 8)) { - io::i2cStopWithCS(_X76_WRITE_DELAY); + auto ok = io::i2cWriteBytes(dummy, 8); + io::i2cStopWithCS(_X76_WRITE_DELAY); + + if (!ok) { LOG("NACK while sending data bytes"); return X76_NACK; } - - io::i2cStopWithCS(_X76_WRITE_DELAY); } return setDataKey(dummy); @@ -441,13 +432,13 @@ DriverError X76F100Driver::setDataKey(const uint8_t *key) { if (error) return error; - if (!io::i2cWriteBytes(key, sizeof(_dump.dataKey))) { - io::i2cStopWithCS(_X76_WRITE_DELAY); + auto ok = io::i2cWriteBytes(key, sizeof(_dump.dataKey)); + io::i2cStopWithCS(_X76_WRITE_DELAY); + + if (!ok) { LOG("NACK while setting new data key"); return X76_NACK; } - - io::i2cStopWithCS(_X76_WRITE_DELAY); } _dump.copyKeyFrom(key); diff --git a/src/main/uibase.cpp b/src/main/uibase.cpp index a9225bf..58d522c 100644 --- a/src/main/uibase.cpp +++ b/src/main/uibase.cpp @@ -15,7 +15,7 @@ static const uint32_t _BUTTON_MAPPINGS[NUM_BUTTON_MAPS][NUM_BUTTONS]{ { // MAP_JOYSTICK io::JAMMA_P1_LEFT | io::JAMMA_P1_UP | io::JAMMA_P2_LEFT | io::JAMMA_P2_UP, io::JAMMA_P1_RIGHT | io::JAMMA_P1_DOWN | io::JAMMA_P2_RIGHT | io::JAMMA_P2_DOWN, - io::JAMMA_P1_START | io::JAMMA_P2_START, + io::JAMMA_P1_START | io::JAMMA_P1_BUTTON1 | io::JAMMA_P2_START | io::JAMMA_P2_BUTTON1, io::JAMMA_TEST | io::JAMMA_SERVICE }, { // MAP_DDR_CAB