From fad8aa11bc3387bc3ff0ebfa23a6c2ad308d8126 Mon Sep 17 00:00:00 2001 From: spicyjpeg Date: Wed, 17 Apr 2024 15:59:36 +0200 Subject: [PATCH] More minor fixes and renames --- assets/app.strings.json | 9 ++-- src/common/rom.cpp | 99 +++++++++++++++++++++++------------- src/common/rom.hpp | 11 ++-- src/main/app/app.cpp | 23 +++++---- src/main/app/app.hpp | 18 +++---- src/main/app/cartactions.cpp | 15 +++--- src/main/app/cartunlock.cpp | 39 +++++++------- src/main/app/cartworkers.cpp | 68 +++++++++++++------------ src/main/app/miscworkers.cpp | 4 ++ src/main/app/romactions.cpp | 14 ++--- src/main/app/romactions.hpp | 13 +++-- src/main/app/romworkers.cpp | 14 ++--- src/main/cartdata.cpp | 2 +- src/main/cartdata.hpp | 6 +-- 14 files changed, 192 insertions(+), 143 deletions(-) diff --git a/assets/app.strings.json b/assets/app.strings.json index 1f74ef8..63ab68f 100644 --- a/assets/app.strings.json +++ b/assets/app.strings.json @@ -242,10 +242,11 @@ "title": "{CART_ICON} Storage device checksums", "prompt": "{RIGHT_ARROW} Press {START_BUTTON} to go back.", - "bios": "BIOS ROM (512 KB):\t\t\t\t%08X\n", - "rtc": "RTC RAM (8184 bytes):\t\t\t%08X\n", - "flash": "Internal flash (16 MB):\t\t\t%08X\n", - "pcmcia": "PCMCIA card in slot %d (first %d MB):\t%08X\n" + "bios": "BIOS ROM (512 KB):\t\t\t\t%08X\n", + "rtc": "RTC RAM (8184 bytes):\t\t\t%08X\n", + "flash": "Internal flash (16 MB):\t\t\t%08X\n", + "pcmcia": "PCMCIA card in slot %d (first %d MB):\t%08X\n", + "description": "All checksums are computed using the standard CRC32 algorithm and parameters (polynomial 04C11DB7, initial value FFFFFFFF, input and output reflected, output bits negated)." }, "ConfirmScreen": { diff --git a/src/common/rom.cpp b/src/common/rom.cpp index fc22815..a797d79 100644 --- a/src/common/rom.cpp +++ b/src/common/rom.cpp @@ -190,6 +190,8 @@ enum IntelCommand : uint16_t { }; enum FlashIdentifier : uint16_t { + _ID_AM29F016 = 0x01 | (0xad << 8), + _ID_AM29F040 = 0x01 | (0xa4 << 8), _ID_MBM29F016A = 0x04 | (0xad << 8), _ID_MBM29F017A = 0x04 | (0x3d << 8), _ID_MBM29F040A = 0x04 | (0xa4 << 8), @@ -233,13 +235,18 @@ uint32_t FlashRegion::getJEDECID(void) const { auto _ptr = reinterpret_cast(ptr); - _ptr[0x000] = _INTEL_RESET; + _ptr[0x000] = _JEDEC_RESET; _ptr[0x000] = _INTEL_RESET; _ptr[0x555] = _JEDEC_HANDSHAKE1; _ptr[0x2aa] = _JEDEC_HANDSHAKE2; _ptr[0x555] = _JEDEC_GET_ID; // Same as _INTEL_GET_ID - return _ptr[0] | (_ptr[1] << 16); + uint32_t id = _ptr[0] | (_ptr[1] << 16); + + _ptr[0x000] = _JEDEC_RESET; + _ptr[0x000] = _INTEL_RESET; + + return id; } Driver *FlashRegion::newDriver(void) const { @@ -256,15 +263,17 @@ Driver *FlashRegion::newDriver(void) const { if (low == high) { // Two 8-bit chips for each bank switch (low) { + case _ID_AM29F016: case _ID_MBM29F016A: case _ID_MBM29F017A: // The MBM29F017A datasheet incorrectly lists the device ID as // 0xad rather than 0x3d in some places. The chip behaves pretty // much identically to the MBM29F016A. - return new MBM29F016ADriver(*this); + return new AM29F016Driver(*this); + case _ID_AM29F040: case _ID_MBM29F040A: - return new MBM29F040ADriver(*this); + return new AM29F040Driver(*this); case _ID_28F016S5: // The chip used by Konami is actually the Sharp LH28F016S, @@ -319,6 +328,11 @@ static const ChipSize _STANDARD_CHIP_SIZE{ .eraseSectorLength = 2 * 0x10000 }; +static const ChipSize _ALT_CHIP_SIZE{ + .chipLength = 2 * 0x80000, + .eraseSectorLength = 2 * 0x10000 +}; + const ChipSize &Driver::getChipSize(void) const { return _DUMMY_CHIP_SIZE; } @@ -368,7 +382,7 @@ const ChipSize &RTCDriver::getChipSize(void) const { return _RTC_CHIP_SIZE; } -/* Fujitsu MBM29F016A/017A driver */ +/* AMD AM29F016/017 (Fujitsu MBM29F016A/017A) driver */ enum FujitsuStatusFlag : uint16_t { _FUJITSU_STATUS_ERASE_TOGGLE = 1 << 2, @@ -378,29 +392,27 @@ enum FujitsuStatusFlag : uint16_t { _FUJITSU_STATUS_POLL_BIT = 1 << 7 }; -DriverError MBM29F016ADriver::_flush( +DriverError AM29F016Driver::_flush( uint32_t offset, uint16_t value, int timeout ) { - volatile uint16_t *ptr = _region.getRawPtr(offset & ~1); + volatile uint16_t *ptr = _region.getRawPtr(offset & ~1); int shift = (offset & 1) * 8; uint8_t byte = (value >> shift) & 0xff; - for (; timeout > 0; timeout--) { - uint8_t status = (*ptr >> shift) & 0xff; + uint8_t status, diff; - if (status == byte) + for (; timeout > 0; timeout -= 10) { + status = (*ptr >> shift) & 0xff; + diff = status ^ byte; + + // Some chips seem to flip the poll bit slightly before returning the + // newly written byte. + if (!diff) return NO_ERROR; + if (!(diff & _FUJITSU_STATUS_POLL_BIT)) + continue; - if (!((status ^ byte) & _FUJITSU_STATUS_POLL_BIT)) { - LOG( - "mismatch @ 0x%08x, exp=0x%02x, got=0x%02x", offset, byte, - status - ); - - *ptr = _JEDEC_RESET; - return VERIFY_MISMATCH; - } if (status & _FUJITSU_STATUS_ERROR) { LOG("error @ 0x%08x, stat=0x%02x", offset, status); @@ -411,13 +423,23 @@ DriverError MBM29F016ADriver::_flush( delayMicroseconds(10); } - LOG("timeout @ 0x%08x, stat=0x%02x", offset, (*ptr >> shift) & 0xff); + if (diff & _FUJITSU_STATUS_POLL_BIT) { + LOG("timeout @ 0x%08x, stat=0x%02x", offset, status); - *ptr = _JEDEC_RESET; - return CHIP_TIMEOUT; + *ptr = _JEDEC_RESET; + return CHIP_TIMEOUT; + } else { + LOG( + "mismatch @ 0x%08x, exp=0x%02x, got=0x%02x", offset, byte, + status + ); + + *ptr = _JEDEC_RESET; + return VERIFY_MISMATCH; + } } -void MBM29F016ADriver::write(uint32_t offset, uint16_t value) { +void AM29F016Driver::write(uint32_t offset, uint16_t value) { volatile uint16_t *ptr = _region.getRawPtr(offset, true); offset = (offset % FLASH_BANK_LENGTH) / 2; @@ -428,7 +450,7 @@ void MBM29F016ADriver::write(uint32_t offset, uint16_t value) { ptr[offset] = value; } -void MBM29F016ADriver::eraseSector(uint32_t offset) { +void AM29F016Driver::eraseSector(uint32_t offset) { volatile uint16_t *ptr = _region.getRawPtr(offset, true); offset = (offset % FLASH_BANK_LENGTH) / 2; @@ -441,7 +463,7 @@ void MBM29F016ADriver::eraseSector(uint32_t offset) { ptr[offset] = _JEDEC_ERASE_SECTOR; } -void MBM29F016ADriver::eraseChip(uint32_t offset) { +void AM29F016Driver::eraseChip(uint32_t offset) { volatile uint16_t *ptr = _region.getRawPtr(offset, true); ptr[0x000] = _JEDEC_RESET; @@ -453,7 +475,7 @@ void MBM29F016ADriver::eraseChip(uint32_t offset) { ptr[0x555] = _JEDEC_ERASE_CHIP; } -DriverError MBM29F016ADriver::flushWrite( +DriverError AM29F016Driver::flushWrite( uint32_t offset, uint16_t value ) { auto error = _flush(offset, value, _FLASH_WRITE_TIMEOUT); @@ -464,7 +486,7 @@ DriverError MBM29F016ADriver::flushWrite( return _flush(offset + 1, value, _FLASH_WRITE_TIMEOUT); } -DriverError MBM29F016ADriver::flushErase(uint32_t offset) { +DriverError AM29F016Driver::flushErase(uint32_t offset) { auto error = _flush(offset, 0xffff, _FLASH_ERASE_TIMEOUT); if (error) @@ -473,16 +495,16 @@ DriverError MBM29F016ADriver::flushErase(uint32_t offset) { return _flush(offset + 1, 0xffff, _FLASH_ERASE_TIMEOUT); } -const ChipSize &MBM29F016ADriver::getChipSize(void) const { +const ChipSize &AM29F016Driver::getChipSize(void) const { return _STANDARD_CHIP_SIZE; } -/* Fujitsu MBM29F040A driver */ +/* AMD AM29F040 (Fujitsu MBM29F040A) driver */ // Konami's drivers handle this chip pretty much identically to the MBM29F016A, // but using 0x5555/0x2aaa as command addresses instead of 0x555/0x2aa. -void MBM29F040ADriver::write(uint32_t offset, uint16_t value) { +void AM29F040Driver::write(uint32_t offset, uint16_t value) { volatile uint16_t *ptr = _region.getRawPtr(offset, true); offset = (offset % FLASH_BANK_LENGTH) / 2; @@ -493,7 +515,7 @@ void MBM29F040ADriver::write(uint32_t offset, uint16_t value) { ptr[offset] = value; } -void MBM29F040ADriver::eraseSector(uint32_t offset) { +void AM29F040Driver::eraseSector(uint32_t offset) { volatile uint16_t *ptr = _region.getRawPtr(offset, true); offset = (offset % FLASH_BANK_LENGTH) / 2; @@ -506,7 +528,7 @@ void MBM29F040ADriver::eraseSector(uint32_t offset) { ptr[offset] = _JEDEC_ERASE_SECTOR; } -void MBM29F040ADriver::eraseChip(uint32_t offset) { +void AM29F040Driver::eraseChip(uint32_t offset) { volatile uint16_t *ptr = _region.getRawPtr(offset, true); ptr[0x0005] = _JEDEC_RESET; @@ -518,6 +540,10 @@ void MBM29F040ADriver::eraseChip(uint32_t offset) { ptr[0x5555] = _JEDEC_ERASE_CHIP; } +const ChipSize &AM29F040Driver::getChipSize(void) const { + return _ALT_CHIP_SIZE; +} + /* Intel 28F016S5 (Sharp LH28F016S) driver */ enum IntelStatusFlag : uint16_t { @@ -533,14 +559,15 @@ enum IntelStatusFlag : uint16_t { DriverError Intel28F016S5Driver::_flush(uint32_t offset, int timeout) { volatile uint16_t *ptr = _region.getRawPtr(offset & ~1); - int shift = (offset & 1) * 8; + int shift = (offset & 1) * 8; + uint8_t status; // Not required as all write/erase commands already put the chip into status // reading mode. //*ptr = _INTEL_GET_STATUS; - for (; timeout > 0; timeout--) { - uint8_t status = (*ptr >> shift) & 0xff; + for (; timeout > 0; timeout -= 10) { + status = (*ptr >> shift) & 0xff; if (status & (_INTEL_STATUS_DPS | _INTEL_STATUS_VPPS)) { LOG("locked @ 0x%08x, stat=0x%02x", offset, status); @@ -562,7 +589,7 @@ DriverError Intel28F016S5Driver::_flush(uint32_t offset, int timeout) { delayMicroseconds(10); } - LOG("timeout @ 0x%08x, stat=0x%02x", offset, (*ptr >> shift) & 0xff); + LOG("timeout @ 0x%08x, stat=0x%02x", offset, status); *ptr = _INTEL_CLEAR_STATUS; return CHIP_TIMEOUT; diff --git a/src/common/rom.hpp b/src/common/rom.hpp index 506aaf7..c6a8f23 100644 --- a/src/common/rom.hpp +++ b/src/common/rom.hpp @@ -128,12 +128,12 @@ public: const ChipSize &getChipSize(void) const; }; -class MBM29F016ADriver : public Driver { +class AM29F016Driver : public Driver { protected: DriverError _flush(uint32_t offset, uint16_t value, int timeout); public: - inline MBM29F016ADriver(const FlashRegion ®ion) + inline AM29F016Driver(const FlashRegion ®ion) : Driver(region) {} virtual void write(uint32_t offset, uint16_t value); @@ -144,14 +144,15 @@ public: const ChipSize &getChipSize(void) const; }; -class MBM29F040ADriver : public MBM29F016ADriver { +class AM29F040Driver : public AM29F016Driver { public: - inline MBM29F040ADriver(const FlashRegion ®ion) - : MBM29F016ADriver(region) {} + inline AM29F040Driver(const FlashRegion ®ion) + : AM29F016Driver(region) {} void write(uint32_t offset, uint16_t value); void eraseSector(uint32_t offset); void eraseChip(uint32_t offset); + const ChipSize &getChipSize(void) const; }; class Intel28F016S5Driver : public Driver { diff --git a/src/main/app/app.cpp b/src/main/app/app.cpp index 39222b4..e8fb63b 100644 --- a/src/main/app/app.cpp +++ b/src/main/app/app.cpp @@ -58,6 +58,8 @@ void WorkerStatus::finish(void) { /* App class */ +static constexpr size_t _WORKER_STACK_SIZE = 0x20000; + App::App(ui::Context &ctx, file::ZIPProvider &resourceProvider) #ifdef ENABLE_LOG_BUFFER : _overlayLayer(_logBuffer), @@ -65,9 +67,7 @@ App::App(ui::Context &ctx, file::ZIPProvider &resourceProvider) : #endif _ctx(ctx), _resourceProvider(resourceProvider), _resourceFile(nullptr), -_cartDriver(nullptr), _cartParser(nullptr), _identified(nullptr) { - _workerStack = new uint8_t[WORKER_STACK_SIZE]; -} +_cartDriver(nullptr), _cartParser(nullptr), _identified(nullptr) {} App::~App(void) { _unloadCartData(); @@ -79,8 +79,6 @@ App::~App(void) { } //_fileProvider.close(); - - delete[] _workerStack; } void App::_unloadCartData(void) { @@ -93,10 +91,10 @@ void App::_unloadCartData(void) { _cartParser = nullptr; } - _dump.chipType = cart::NONE; - _dump.flags = 0; - _dump.clearIdentifiers(); - _dump.clearData(); + _cartDump.chipType = cart::NONE; + _cartDump.flags = 0; + _cartDump.clearIdentifiers(); + _cartDump.clearData(); _identified = nullptr; //_selectedEntry = nullptr; @@ -107,13 +105,16 @@ void App::_setupWorker(bool (App::*func)(void)) { auto enable = disableInterrupts(); + _workerStack.allocate(_WORKER_STACK_SIZE); _workerStatus.reset(); - _workerFunction = func; + + _workerFunction = func; + auto stackBottom = _workerStack.as(); initThread( // This is not how you implement delegates in C++. &_workerThread, util::forcedCast(&App::_worker), this, - &_workerStack[(WORKER_STACK_SIZE - 1) & ~7] + &stackBottom[(_WORKER_STACK_SIZE - 1) & ~7] ); if (enable) enableInterrupts(); diff --git a/src/main/app/app.hpp b/src/main/app/app.hpp index 1a11c8c..f4eff73 100644 --- a/src/main/app/app.hpp +++ b/src/main/app/app.hpp @@ -1,7 +1,6 @@ #pragma once -#include #include "common/file.hpp" #include "main/app/cartactions.hpp" #include "main/app/cartunlock.hpp" @@ -50,8 +49,6 @@ public: /* App class */ -static constexpr size_t WORKER_STACK_SIZE = 0x20000; - class App { friend class WorkerStatusScreen; friend class MessageScreen; @@ -110,13 +107,16 @@ private: file::FATProvider _fileProvider; file::StringTable _stringTable; - cart::CartDump _dump; - cart::CartDB _db; - Thread _workerThread; - WorkerStatus _workerStatus; - bool (App::*_workerFunction)(void); + cart::CartDump _cartDump; + cart::ROMHeaderDump _romHeaderDump; + cart::CartDB _cartDB; + cart::ROMHeaderDB _romHeaderDB; + + Thread _workerThread; + util::Data _workerStack; + WorkerStatus _workerStatus; + bool (App::*_workerFunction)(void); - uint8_t *_workerStack; cart::Driver *_cartDriver; cart::CartParser *_cartParser; const cart::CartDBEntry *_identified, *_selectedEntry; diff --git a/src/main/app/cartactions.cpp b/src/main/app/cartactions.cpp index 1ceda9a..47d6239 100644 --- a/src/main/app/cartactions.cpp +++ b/src/main/app/cartactions.cpp @@ -1,5 +1,4 @@ -#include "common/defs.hpp" #include "common/util.hpp" #include "main/app/cartactions.hpp" #include "main/app/app.hpp" @@ -139,12 +138,12 @@ void CartActionsScreen::resetSystemID(ui::Context &ctx) { } void CartActionsScreen::matchSystemID(ui::Context &ctx) { - if (APP->_dump.flags & cart::DUMP_SYSTEM_ID_OK) { + if (APP->_cartDump.flags & cart::DUMP_SYSTEM_ID_OK) { APP->_confirmScreen.setMessage( *this, [](ui::Context &ctx) { APP->_cartParser->getIdentifiers()->systemID.copyFrom( - APP->_dump.systemID.data + APP->_cartDump.systemID.data ); APP->_cartParser->flush(); @@ -238,12 +237,12 @@ void HexdumpScreen::show(ui::Context &ctx, bool goBack) { _body = _bodyText; _prompt = STR("HexdumpScreen.prompt"); - size_t length = APP->_dump.getChipSize().dataLength; + size_t length = APP->_cartDump.getChipSize().dataLength; char *ptr = _bodyText, *end = &_bodyText[sizeof(_bodyText)]; for (size_t i = 0; i < length; i += 16) { ptr += snprintf(ptr, end - ptr, "%04X: ", i); - ptr += util::hexToString(ptr, &APP->_dump.data[i], 16, ' '); + ptr += util::hexToString(ptr, &APP->_cartDump.data[i], 16, ' '); *(ptr++) = '\n'; } @@ -264,7 +263,7 @@ void HexdumpScreen::update(ui::Context &ctx) { const char *ReflashGameScreen::_getItemName(ui::Context &ctx, int index) const { static char name[96]; // TODO: get rid of this ugly crap - APP->_db.get(index)->getDisplayName(name, sizeof(name)); + APP->_cartDB.get(index)->getDisplayName(name, sizeof(name)); return name; } @@ -273,7 +272,7 @@ void ReflashGameScreen::show(ui::Context &ctx, bool goBack) { _prompt = STR("ReflashGameScreen.prompt"); _itemPrompt = STR("ReflashGameScreen.itemPrompt"); - _listLength = APP->_db.getNumEntries(); + _listLength = APP->_cartDB.getNumEntries(); ListScreen::show(ctx, goBack); } @@ -294,7 +293,7 @@ void ReflashGameScreen::update(ui::Context &ctx) { STR("CartActionsScreen.reflash.confirm") ); - APP->_selectedEntry = APP->_db.get(_activeItem); + APP->_selectedEntry = APP->_cartDB.get(_activeItem); ctx.show(APP->_confirmScreen, false, true); } } diff --git a/src/main/app/cartunlock.cpp b/src/main/app/cartunlock.cpp index 838e3e0..4c63c58 100644 --- a/src/main/app/cartunlock.cpp +++ b/src/main/app/cartunlock.cpp @@ -40,7 +40,7 @@ void CartInfoScreen::show(ui::Context &ctx, bool goBack) { _title = STR("CartInfoScreen.title"); _body = _bodyText; - auto &dump = APP->_dump; + auto &dump = APP->_cartDump; char id1[32], id2[32], config[32]; char *ptr = _bodyText, *end = &_bodyText[sizeof(_bodyText)]; @@ -178,7 +178,7 @@ void CartInfoScreen::show(ui::Context &ctx, bool goBack) { } else if ( dump.flags & (cart::DUMP_PUBLIC_DATA_OK | cart::DUMP_PRIVATE_DATA_OK) ) { - state = APP->_dump.isReadableDataEmpty() ? BLANK_CART : UNIDENTIFIED; + state = dump.isReadableDataEmpty() ? BLANK_CART : UNIDENTIFIED; } else { state = UNKNOWN; } @@ -207,8 +207,8 @@ void CartInfoScreen::update(ui::Context &ctx) { if (ctx.buttons.pressed(ui::BTN_START)) { if (ctx.buttons.held(ui::BTN_LEFT) || ctx.buttons.held(ui::BTN_RIGHT)) { ctx.show(APP->_mainMenuScreen, true, true); - } else if (APP->_dump.chipType) { - if (APP->_dump.flags & cart::DUMP_PRIVATE_DATA_OK) + } else if (APP->_cartDump.chipType) { + if (APP->_cartDump.flags & cart::DUMP_PRIVATE_DATA_OK) ctx.show(APP->_cartActionsScreen, false, true); else ctx.show(APP->_unlockKeyScreen, false, true); @@ -260,14 +260,14 @@ const char *UnlockKeyScreen::_getItemName(ui::Context &ctx, int index) const { static char name[96]; // TODO: get rid of this ugly crap - APP->_db.get(index)->getDisplayName(name, sizeof(name)); + APP->_cartDB.get(index)->getDisplayName(name, sizeof(name)); return name; } void UnlockKeyScreen::autoUnlock(ui::Context &ctx) { __builtin_memcpy( - APP->_dump.dataKey, APP->_identified->dataKey, - sizeof(APP->_dump.dataKey) + APP->_cartDump.dataKey, APP->_identified->dataKey, + sizeof(APP->_cartDump.dataKey) ); //APP->_selectedEntry = APP->_identified; @@ -282,7 +282,7 @@ void UnlockKeyScreen::useCustomKey(ui::Context &ctx) { void UnlockKeyScreen::use00Key(ui::Context &ctx) { __builtin_memset( - APP->_dump.dataKey, 0x00, sizeof(APP->_dump.dataKey) + APP->_cartDump.dataKey, 0x00, sizeof(APP->_cartDump.dataKey) ); APP->_selectedEntry = nullptr; @@ -291,7 +291,7 @@ void UnlockKeyScreen::use00Key(ui::Context &ctx) { void UnlockKeyScreen::useFFKey(ui::Context &ctx) { __builtin_memset( - APP->_dump.dataKey, 0xff, sizeof(APP->_dump.dataKey) + APP->_cartDump.dataKey, 0xff, sizeof(APP->_cartDump.dataKey) ); APP->_selectedEntry = nullptr; @@ -303,7 +303,7 @@ void UnlockKeyScreen::show(ui::Context &ctx, bool goBack) { _prompt = STR("UnlockKeyScreen.prompt"); _itemPrompt = STR("UnlockKeyScreen.itemPrompt"); - _listLength = APP->_db.getNumEntries() - _getSpecialEntryOffset(ctx); + _listLength = APP->_cartDB.getNumEntries() - _getSpecialEntryOffset(ctx); ListScreen::show(ctx, goBack); } @@ -315,7 +315,8 @@ void UnlockKeyScreen::update(ui::Context &ctx) { if (ctx.buttons.held(ui::BTN_LEFT) || ctx.buttons.held(ui::BTN_RIGHT)) { ctx.show(APP->_cartInfoScreen, true, true); } else { - int index = _activeItem + _getSpecialEntryOffset(ctx); + auto &dump = APP->_cartDump; + int index = _activeItem + _getSpecialEntryOffset(ctx); APP->_confirmScreen.setMessage( APP->_unlockKeyScreen, @@ -323,18 +324,18 @@ void UnlockKeyScreen::update(ui::Context &ctx) { APP->_setupWorker(&App::_cartUnlockWorker); ctx.show(APP->_workerStatusScreen, false, true); }, - STRH(_UNLOCK_WARNINGS[APP->_dump.chipType]) + STRH(_UNLOCK_WARNINGS[dump.chipType]) ); if (index < 0) { (this->*_SPECIAL_ENTRIES[-index].target)(ctx); } else { __builtin_memcpy( - APP->_dump.dataKey, APP->_db.get(index)->dataKey, - sizeof(APP->_dump.dataKey) + dump.dataKey, APP->_cartDB.get(index)->dataKey, + sizeof(dump.dataKey) ); - APP->_selectedEntry = APP->_db.get(index); + APP->_selectedEntry = APP->_cartDB.get(index); ctx.show(APP->_confirmScreen, false, true); } } @@ -363,6 +364,8 @@ void KeyEntryScreen::update(ui::Context &ctx) { if (_activeButton == _buttonIndexOffset) { ctx.show(APP->_unlockKeyScreen, true, true); } else if (_activeButton == (_buttonIndexOffset + 1)) { + auto &dump = APP->_cartDump; + // TODO: deduplicate this code (it is the same as UnlockKeyScreen) APP->_confirmScreen.setMessage( APP->_unlockKeyScreen, @@ -370,12 +373,10 @@ void KeyEntryScreen::update(ui::Context &ctx) { APP->_setupWorker(&App::_cartUnlockWorker); ctx.show(APP->_workerStatusScreen, false, true); }, - STRH(_UNLOCK_WARNINGS[APP->_dump.chipType]) + STRH(_UNLOCK_WARNINGS[dump.chipType]) ); - __builtin_memcpy( - APP->_dump.dataKey, _buffer, sizeof(APP->_dump.dataKey) - ); + __builtin_memcpy(dump.dataKey, _buffer, sizeof(dump.dataKey)); ctx.show(APP->_confirmScreen, false, true); } } diff --git a/src/main/app/cartworkers.cpp b/src/main/app/cartworkers.cpp index 323ec1e..76bc079 100644 --- a/src/main/app/cartworkers.cpp +++ b/src/main/app/cartworkers.cpp @@ -31,17 +31,17 @@ bool App::_cartDetectWorker(void) { if (cart::dummyDriverDump.chipType) { LOG("using dummy cart driver"); - _cartDriver = new cart::DummyDriver(_dump); + _cartDriver = new cart::DummyDriver(_cartDump); _cartDriver->readSystemID(); } else { - _cartDriver = cart::newCartDriver(_dump); + _cartDriver = cart::newCartDriver(_cartDump); } #else - _cartDriver = cart::newCartDriver(_dump); + _cartDriver = cart::newCartDriver(_cartDump); #endif - if (_dump.chipType) { - LOG("cart dump @ 0x%08x", &_dump); + if (_cartDump.chipType) { + LOG("cart dump @ 0x%08x", &_cartDump); LOG("cart driver @ 0x%08x", _cartDriver); auto error = _cartDriver->readCartID(); @@ -53,17 +53,17 @@ bool App::_cartDetectWorker(void) { if (error) LOG("read error [%s]", cart::getErrorString(error)); - else if (!_dump.isReadableDataEmpty()) - _cartParser = cart::newCartParser(_dump); + else if (!_cartDump.isReadableDataEmpty()) + _cartParser = cart::newCartParser(_cartDump); LOG("cart parser @ 0x%08x", _cartParser); _workerStatus.update(1, 3, WSTR("App.cartDetectWorker.identifyGame")); - if (!_db.ptr) { + if (!_cartDB.ptr) { if (!_resourceProvider.loadData( - _db, _CARTDB_PATHS[_dump.chipType]) + _cartDB, _CARTDB_PATHS[_cartDump.chipType]) ) { - LOG("%s not found", _CARTDB_PATHS[_dump.chipType]); + LOG("%s not found", _CARTDB_PATHS[_cartDump.chipType]); goto _cartInitDone; } } @@ -73,7 +73,7 @@ bool App::_cartDetectWorker(void) { if (!_cartParser) goto _cartInitDone; if (_cartParser->getCode(code) && _cartParser->getRegion(region)) - _identified = _db.lookup(code, region); + _identified = _cartDB.lookup(code, region); if (!_identified) goto _cartInitDone; @@ -81,7 +81,7 @@ bool App::_cartDetectWorker(void) { // ambiguity between different formats). delete _cartParser; _cartParser = cart::newCartParser( - _dump, _identified->formatType, _identified->flags + _cartDump, _identified->formatType, _identified->flags ); LOG("new cart parser @ 0x%08x", _cartParser); @@ -90,11 +90,12 @@ bool App::_cartDetectWorker(void) { _cartInitDone: _workerStatus.update(2, 3, WSTR("App.cartDetectWorker.readDigitalIO")); + if ( #ifdef ENABLE_DUMMY_DRIVER - if (io::isDigitalIOPresent() && !(_dump.flags & cart::DUMP_SYSTEM_ID_OK)) { -#else - if (io::isDigitalIOPresent()) { + !(_cartDump.flags & cart::DUMP_SYSTEM_ID_OK) && #endif + io::isDigitalIOPresent() + ) { util::Data bitstream; bool ready; @@ -141,7 +142,8 @@ bool App::_cartUnlockWorker(void) { if (error) { _messageScreen.setMessage( MESSAGE_ERROR, _cartInfoScreen, - WSTRH(_UNLOCK_ERRORS[_dump.chipType]), cart::getErrorString(error) + WSTRH(_UNLOCK_ERRORS[_cartDump.chipType]), + cart::getErrorString(error) ); _workerStatus.setNextScreen(_messageScreen); @@ -151,7 +153,7 @@ bool App::_cartUnlockWorker(void) { if (_cartParser) delete _cartParser; - _cartParser = cart::newCartParser(_dump); + _cartParser = cart::newCartParser(_cartDump); if (!_cartParser) return true; @@ -162,7 +164,7 @@ bool App::_cartUnlockWorker(void) { char code[8], region[8]; if (_cartParser->getCode(code) && _cartParser->getRegion(region)) - _identified = _db.lookup(code, region); + _identified = _cartDB.lookup(code, region); // If auto-identification failed (e.g. because the format has no game code), // use the game whose unlocking key was selected as a hint. @@ -177,7 +179,7 @@ bool App::_cartUnlockWorker(void) { delete _cartParser; _cartParser = cart::newCartParser( - _dump, _identified->formatType, _identified->flags + _cartDump, _identified->formatType, _identified->flags ); LOG("new cart parser @ 0x%08x", _cartParser); @@ -189,7 +191,7 @@ bool App::_qrCodeWorker(void) { _workerStatus.setNextScreen(_qrCodeScreen); _workerStatus.update(0, 2, WSTR("App.qrCodeWorker.compress")); - _dump.toQRString(qrString); + _cartDump.toQRString(qrString); _workerStatus.update(1, 2, WSTR("App.qrCodeWorker.generate")); _qrCodeScreen.generateCode(qrString); @@ -213,7 +215,7 @@ bool App::_cartDumpWorker(void) { char code[8], region[8]; size_t length; - length = _dump.getDumpLength(); + length = _cartDump.getDumpLength(); if ( _identified && _cartParser->getCode(code) && @@ -235,7 +237,7 @@ bool App::_cartDumpWorker(void) { LOG("saving %s, length=%d", path, length); - if (_fileProvider.saveData(&_dump, length, path) != length) + if (_fileProvider.saveData(&_cartDump, length, path) != length) goto _error; _messageScreen.setMessage( @@ -273,7 +275,7 @@ bool App::_cartWriteWorker(void) { return false; } - _dump.copyKeyFrom(key); + _cartDump.copyKeyFrom(key); return _cartUnlockWorker(); } @@ -301,7 +303,7 @@ bool App::_cartRestoreWorker(void) { _file->close(); delete _file; - if (_dump.chipType != newDump.chipType) { + if (_cartDump.chipType != newDump.chipType) { _messageScreen.setMessage( MESSAGE_ERROR, _filePickerScreen, WSTR("App.cartRestoreWorker.typeError"), path @@ -321,9 +323,9 @@ bool App::_cartRestoreWorker(void) { if (newDump.flags & ( cart::DUMP_PUBLIC_DATA_OK | cart::DUMP_PRIVATE_DATA_OK )) - _dump.copyDataFrom(newDump.data); + _cartDump.copyDataFrom(newDump.data); if (newDump.flags & cart::DUMP_CONFIG_OK) - _dump.copyConfigFrom(newDump.config); + _cartDump.copyConfigFrom(newDump.config); _workerStatus.update(2, 3, WSTR("App.cartRestoreWorker.write")); error = _cartDriver->writeData(); @@ -360,7 +362,7 @@ bool App::_cartReflashWorker(void) { // Make sure a valid cart ID is present if required by the new data. if ( _selectedEntry->requiresCartID() && - !(_dump.flags & cart::DUMP_CART_ID_OK) + !(_cartDump.flags & cart::DUMP_CART_ID_OK) ) { _messageScreen.setMessage( MESSAGE_ERROR, _cartInfoScreen, @@ -382,21 +384,23 @@ bool App::_cartReflashWorker(void) { delete _cartParser; _cartParser = cart::newCartParser( - _dump, _selectedEntry->formatType, _selectedEntry->flags + _cartDump, _selectedEntry->formatType, _selectedEntry->flags ); auto pri = _cartParser->getIdentifiers(); auto pub = _cartParser->getPublicIdentifiers(); - _dump.clearData(); - _dump.initConfig(9, _selectedEntry->flags & cart::DATA_HAS_PUBLIC_SECTION); + _cartDump.clearData(); + _cartDump.initConfig( + 9, _selectedEntry->flags & cart::DATA_HAS_PUBLIC_SECTION + ); if (pri) { if (_selectedEntry->flags & cart::DATA_HAS_CART_ID) - pri->cartID.copyFrom(_dump.cartID.data); + pri->cartID.copyFrom(_cartDump.cartID.data); if (_selectedEntry->flags & cart::DATA_HAS_TRACE_ID) pri->updateTraceID( _selectedEntry->traceIDType, _selectedEntry->traceIDParam, - &_dump.cartID + &_cartDump.cartID ); if (_selectedEntry->flags & cart::DATA_HAS_INSTALL_ID) { // The private installation ID seems to be unused on carts with a diff --git a/src/main/app/miscworkers.cpp b/src/main/app/miscworkers.cpp index 5f300ac..38ceda3 100644 --- a/src/main/app/miscworkers.cpp +++ b/src/main/app/miscworkers.cpp @@ -37,10 +37,14 @@ bool App::_startupWorker(void) { _workerStatus.update(2, 4, WSTR("App.startupWorker.initFAT")); +#if 0 // Attempt to mount the secondary drive first, then in case of failure try // mounting the primary drive instead. if (!_fileProvider.init("1:")) _fileProvider.init("0:"); +#else + _fileProvider.init("1:"); +#endif _workerStatus.update(3, 4, WSTR("App.startupWorker.loadResources")); diff --git a/src/main/app/romactions.cpp b/src/main/app/romactions.cpp index c63c412..74d6e8a 100644 --- a/src/main/app/romactions.cpp +++ b/src/main/app/romactions.cpp @@ -299,7 +299,7 @@ void StorageActionsScreen::update(ui::Context &ctx) { if (ctx.buttons.pressed(ui::BTN_START)) { if (ctx.buttons.held(ui::BTN_LEFT) || ctx.buttons.held(ui::BTN_RIGHT)) { - ctx.show(APP->_mainMenuScreen, true, true); + ctx.show(APP->_storageInfoScreen, true, true); } else { if (action.region.isPresent()) { this->_selectedRegion = &(action.region); @@ -322,9 +322,9 @@ void ChecksumScreen::show(ui::Context &ctx, bool goBack) { char *ptr = _bodyText, *end = &_bodyText[sizeof(_bodyText)]; - _PRINT(STR("ChecksumScreen.bios"), biosCRC); - _PRINT(STR("ChecksumScreen.rtc"), rtcCRC); - _PRINT(STR("ChecksumScreen.flash"), flashCRC); + _PRINT(STR("ChecksumScreen.bios"), values.bios); + _PRINT(STR("ChecksumScreen.rtc"), values.rtc); + _PRINT(STR("ChecksumScreen.flash"), values.flash); _PRINTLN(); @@ -333,7 +333,7 @@ void ChecksumScreen::show(ui::Context &ctx, bool goBack) { continue; auto slot = i + 1; - auto crc = pcmciaCRC[i]; + auto crc = values.pcmcia[i]; _PRINT(STR("ChecksumScreen.pcmcia"), slot, 16, crc[0]); _PRINT(STR("ChecksumScreen.pcmcia"), slot, 32, crc[1]); @@ -342,7 +342,9 @@ void ChecksumScreen::show(ui::Context &ctx, bool goBack) { _PRINTLN(); } - *(--ptr) = 0; + _PRINT(STR("ChecksumScreen.description")); + + //*(--ptr) = 0; LOG("remaining=%d", end - ptr); TextScreen::show(ctx, goBack); diff --git a/src/main/app/romactions.hpp b/src/main/app/romactions.hpp index c7b989c..d611253 100644 --- a/src/main/app/romactions.hpp +++ b/src/main/app/romactions.hpp @@ -41,14 +41,21 @@ public: void update(ui::Context &ctx); }; +// The CRCs have to be wrapped into their own structure in order to allow usage +// of offsetof(). +struct ChecksumValues { +public: + uint32_t bios, rtc, flash; + uint32_t pcmcia[2][4]; +}; + class ChecksumScreen : public ui::TextScreen { private: char _bodyText[2048]; public: - bool valid; - uint32_t biosCRC, rtcCRC, flashCRC; - uint32_t pcmciaCRC[2][4]; + bool valid; + ChecksumValues values; inline ChecksumScreen(void) : valid(false) {} diff --git a/src/main/app/romworkers.cpp b/src/main/app/romworkers.cpp index c5b0425..5010131 100644 --- a/src/main/app/romworkers.cpp +++ b/src/main/app/romworkers.cpp @@ -23,31 +23,31 @@ static const RegionInfo _REGION_INFO[]{ .crcPrompt = "App.romChecksumWorker.hashBIOS"_h, .path = "%s/bios.bin", .region = rom::bios, - .crcOffset = offsetof(ChecksumScreen, biosCRC) + .crcOffset = offsetof(ChecksumValues, bios) }, { .dumpPrompt = "App.romDumpWorker.dumpRTC"_h, .crcPrompt = "App.romChecksumWorker.hashRTC"_h, .path = "%s/rtc.bin", .region = rom::rtc, - .crcOffset = offsetof(ChecksumScreen, rtcCRC) + .crcOffset = offsetof(ChecksumValues, rtc) }, { .dumpPrompt = "App.romDumpWorker.dumpFlash"_h, .crcPrompt = "App.romChecksumWorker.hashFlash"_h, .path = "%s/flash.bin", .region = rom::flash, - .crcOffset = offsetof(ChecksumScreen, flashCRC) + .crcOffset = offsetof(ChecksumValues, flash) }, { .dumpPrompt = "App.romDumpWorker.dumpPCMCIA1"_h, .crcPrompt = "App.romChecksumWorker.hashPCMCIA1"_h, .path = "%s/pcmcia1.bin", .region = rom::pcmcia[0], - .crcOffset = offsetof(ChecksumScreen, pcmciaCRC[0]) + .crcOffset = offsetof(ChecksumValues, pcmcia[0]) }, { .dumpPrompt = "App.romDumpWorker.dumpPCMCIA2"_h, .crcPrompt = "App.romChecksumWorker.hashPCMCIA2"_h, .path = "%s/pcmcia2.bin", .region = rom::pcmcia[1], - .crcOffset = offsetof(ChecksumScreen, pcmciaCRC[1]) + .crcOffset = offsetof(ChecksumValues, pcmcia[1]) } }; @@ -71,7 +71,8 @@ bool App::_romChecksumWorker(void) { uint32_t offset = 0; uint32_t crc = 0; auto crcPtr = reinterpret_cast( - reinterpret_cast(&_checksumScreen) + entry.crcOffset + reinterpret_cast(&_checksumScreen.values) + + entry.crcOffset ); // Flash cards can be 16, 32 or 64 MB, so copies of the current CRC are @@ -90,6 +91,7 @@ bool App::_romChecksumWorker(void) { } } + _checksumScreen.valid = true; return true; } diff --git a/src/main/cartdata.cpp b/src/main/cartdata.cpp index a94fa44..1eee704 100644 --- a/src/main/cartdata.cpp +++ b/src/main/cartdata.cpp @@ -709,6 +709,6 @@ template const T *DB::lookup( } template class DB; -template class DB; +template class DB; } diff --git a/src/main/cartdata.hpp b/src/main/cartdata.hpp index c67f291..8c911c7 100644 --- a/src/main/cartdata.hpp +++ b/src/main/cartdata.hpp @@ -295,7 +295,7 @@ public: } }; -class [[gnu::packed]] FlashDBEntry { +class [[gnu::packed]] ROMHeaderDBEntry { public: // TODO: define these flags uint8_t flags; @@ -332,7 +332,7 @@ public: const T *lookup(const char *code, const char *region) const; }; -using CartDB = DB; -using FlashDB = DB; +using CartDB = DB; +using ROMHeaderDB = DB; }