X76 config fixes, add support for executables in flash images

This commit is contained in:
spicyjpeg 2024-03-20 18:25:11 +01:00
parent 355c4c0796
commit d8aa1806b6
No known key found for this signature in database
GPG Key ID: 5CC87404C01DF393
9 changed files with 78 additions and 59 deletions

View File

@ -11,3 +11,6 @@ insert_final_newline = true
[{*.yml,*.yaml,.clangd}]
indent_style = space
indent_size = 2
[assets/about.txt]
trim_trailing_whitespace = false

View File

@ -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"
)

View File

@ -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

View File

@ -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<const uint32_t *>(ptr + offset);
auto dest = reinterpret_cast<uint32_t *>(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<const uint32_t *>(ptr + ptrOffset);
auto dest = reinterpret_cast<uint32_t *>(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<const uint32_t *>(ptr + ptrOffset);
auto table = reinterpret_cast<const uint32_t *>(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<const uint8_t *>(ptr + _FLASH_EXE_OFFSET);
auto crcPtr = reinterpret_cast<const uint32_t *>(ptr + _FLASH_CRC_OFFSET);
auto data = reinterpret_cast<const uint8_t *>(ptr + FLASH_EXE_OFFSET);
auto crcPtr = reinterpret_cast<const uint32_t *>(ptr + FLASH_CRC_OFFSET);
auto table = reinterpret_cast<const uint32_t *>(CACHE_BASE);
io::setFlashBank(bank);

View File

@ -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;

View File

@ -3,6 +3,7 @@
#include <stdlib.h>
#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;

View File

@ -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

View File

@ -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);

View File

@ -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