mirror of
https://github.com/spicyjpeg/573in1.git
synced 2025-02-02 04:27:56 +01:00
X76 config fixes, add support for executables in flash images
This commit is contained in:
parent
355c4c0796
commit
d8aa1806b6
@ -11,3 +11,6 @@ insert_final_newline = true
|
||||
[{*.yml,*.yaml,.clangd}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[assets/about.txt]
|
||||
trim_trailing_whitespace = false
|
||||
|
@ -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"
|
||||
)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user