More minor fixes and renames

This commit is contained in:
spicyjpeg 2024-04-17 15:59:36 +02:00
parent 3534e99dca
commit fad8aa11bc
No known key found for this signature in database
GPG Key ID: 5CC87404C01DF393
14 changed files with 192 additions and 143 deletions

View File

@ -242,10 +242,11 @@
"title": "{CART_ICON} Storage device checksums", "title": "{CART_ICON} Storage device checksums",
"prompt": "{RIGHT_ARROW} Press {START_BUTTON} to go back.", "prompt": "{RIGHT_ARROW} Press {START_BUTTON} to go back.",
"bios": "BIOS ROM (512 KB):\t\t\t\t%08X\n", "bios": "BIOS ROM (512 KB):\t\t\t\t%08X\n",
"rtc": "RTC RAM (8184 bytes):\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", "flash": "Internal flash (16 MB):\t\t\t%08X\n",
"pcmcia": "PCMCIA card in slot %d (first %d MB):\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": { "ConfirmScreen": {

View File

@ -190,6 +190,8 @@ enum IntelCommand : uint16_t {
}; };
enum FlashIdentifier : uint16_t { enum FlashIdentifier : uint16_t {
_ID_AM29F016 = 0x01 | (0xad << 8),
_ID_AM29F040 = 0x01 | (0xa4 << 8),
_ID_MBM29F016A = 0x04 | (0xad << 8), _ID_MBM29F016A = 0x04 | (0xad << 8),
_ID_MBM29F017A = 0x04 | (0x3d << 8), _ID_MBM29F017A = 0x04 | (0x3d << 8),
_ID_MBM29F040A = 0x04 | (0xa4 << 8), _ID_MBM29F040A = 0x04 | (0xa4 << 8),
@ -233,13 +235,18 @@ uint32_t FlashRegion::getJEDECID(void) const {
auto _ptr = reinterpret_cast<volatile uint16_t *>(ptr); auto _ptr = reinterpret_cast<volatile uint16_t *>(ptr);
_ptr[0x000] = _INTEL_RESET; _ptr[0x000] = _JEDEC_RESET;
_ptr[0x000] = _INTEL_RESET; _ptr[0x000] = _INTEL_RESET;
_ptr[0x555] = _JEDEC_HANDSHAKE1; _ptr[0x555] = _JEDEC_HANDSHAKE1;
_ptr[0x2aa] = _JEDEC_HANDSHAKE2; _ptr[0x2aa] = _JEDEC_HANDSHAKE2;
_ptr[0x555] = _JEDEC_GET_ID; // Same as _INTEL_GET_ID _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 { Driver *FlashRegion::newDriver(void) const {
@ -256,15 +263,17 @@ Driver *FlashRegion::newDriver(void) const {
if (low == high) { if (low == high) {
// Two 8-bit chips for each bank // Two 8-bit chips for each bank
switch (low) { switch (low) {
case _ID_AM29F016:
case _ID_MBM29F016A: case _ID_MBM29F016A:
case _ID_MBM29F017A: case _ID_MBM29F017A:
// The MBM29F017A datasheet incorrectly lists the device ID as // The MBM29F017A datasheet incorrectly lists the device ID as
// 0xad rather than 0x3d in some places. The chip behaves pretty // 0xad rather than 0x3d in some places. The chip behaves pretty
// much identically to the MBM29F016A. // much identically to the MBM29F016A.
return new MBM29F016ADriver(*this); return new AM29F016Driver(*this);
case _ID_AM29F040:
case _ID_MBM29F040A: case _ID_MBM29F040A:
return new MBM29F040ADriver(*this); return new AM29F040Driver(*this);
case _ID_28F016S5: case _ID_28F016S5:
// The chip used by Konami is actually the Sharp LH28F016S, // The chip used by Konami is actually the Sharp LH28F016S,
@ -319,6 +328,11 @@ static const ChipSize _STANDARD_CHIP_SIZE{
.eraseSectorLength = 2 * 0x10000 .eraseSectorLength = 2 * 0x10000
}; };
static const ChipSize _ALT_CHIP_SIZE{
.chipLength = 2 * 0x80000,
.eraseSectorLength = 2 * 0x10000
};
const ChipSize &Driver::getChipSize(void) const { const ChipSize &Driver::getChipSize(void) const {
return _DUMMY_CHIP_SIZE; return _DUMMY_CHIP_SIZE;
} }
@ -368,7 +382,7 @@ const ChipSize &RTCDriver::getChipSize(void) const {
return _RTC_CHIP_SIZE; return _RTC_CHIP_SIZE;
} }
/* Fujitsu MBM29F016A/017A driver */ /* AMD AM29F016/017 (Fujitsu MBM29F016A/017A) driver */
enum FujitsuStatusFlag : uint16_t { enum FujitsuStatusFlag : uint16_t {
_FUJITSU_STATUS_ERASE_TOGGLE = 1 << 2, _FUJITSU_STATUS_ERASE_TOGGLE = 1 << 2,
@ -378,29 +392,27 @@ enum FujitsuStatusFlag : uint16_t {
_FUJITSU_STATUS_POLL_BIT = 1 << 7 _FUJITSU_STATUS_POLL_BIT = 1 << 7
}; };
DriverError MBM29F016ADriver::_flush( DriverError AM29F016Driver::_flush(
uint32_t offset, uint16_t value, int timeout 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; int shift = (offset & 1) * 8;
uint8_t byte = (value >> shift) & 0xff; uint8_t byte = (value >> shift) & 0xff;
for (; timeout > 0; timeout--) { uint8_t status, diff;
uint8_t status = (*ptr >> shift) & 0xff;
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; 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) { if (status & _FUJITSU_STATUS_ERROR) {
LOG("error @ 0x%08x, stat=0x%02x", offset, status); LOG("error @ 0x%08x, stat=0x%02x", offset, status);
@ -411,13 +423,23 @@ DriverError MBM29F016ADriver::_flush(
delayMicroseconds(10); 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; *ptr = _JEDEC_RESET;
return CHIP_TIMEOUT; 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); volatile uint16_t *ptr = _region.getRawPtr(offset, true);
offset = (offset % FLASH_BANK_LENGTH) / 2; offset = (offset % FLASH_BANK_LENGTH) / 2;
@ -428,7 +450,7 @@ void MBM29F016ADriver::write(uint32_t offset, uint16_t value) {
ptr[offset] = value; ptr[offset] = value;
} }
void MBM29F016ADriver::eraseSector(uint32_t offset) { void AM29F016Driver::eraseSector(uint32_t offset) {
volatile uint16_t *ptr = _region.getRawPtr(offset, true); volatile uint16_t *ptr = _region.getRawPtr(offset, true);
offset = (offset % FLASH_BANK_LENGTH) / 2; offset = (offset % FLASH_BANK_LENGTH) / 2;
@ -441,7 +463,7 @@ void MBM29F016ADriver::eraseSector(uint32_t offset) {
ptr[offset] = _JEDEC_ERASE_SECTOR; 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); volatile uint16_t *ptr = _region.getRawPtr(offset, true);
ptr[0x000] = _JEDEC_RESET; ptr[0x000] = _JEDEC_RESET;
@ -453,7 +475,7 @@ void MBM29F016ADriver::eraseChip(uint32_t offset) {
ptr[0x555] = _JEDEC_ERASE_CHIP; ptr[0x555] = _JEDEC_ERASE_CHIP;
} }
DriverError MBM29F016ADriver::flushWrite( DriverError AM29F016Driver::flushWrite(
uint32_t offset, uint16_t value uint32_t offset, uint16_t value
) { ) {
auto error = _flush(offset, value, _FLASH_WRITE_TIMEOUT); auto error = _flush(offset, value, _FLASH_WRITE_TIMEOUT);
@ -464,7 +486,7 @@ DriverError MBM29F016ADriver::flushWrite(
return _flush(offset + 1, value, _FLASH_WRITE_TIMEOUT); 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); auto error = _flush(offset, 0xffff, _FLASH_ERASE_TIMEOUT);
if (error) if (error)
@ -473,16 +495,16 @@ DriverError MBM29F016ADriver::flushErase(uint32_t offset) {
return _flush(offset + 1, 0xffff, _FLASH_ERASE_TIMEOUT); return _flush(offset + 1, 0xffff, _FLASH_ERASE_TIMEOUT);
} }
const ChipSize &MBM29F016ADriver::getChipSize(void) const { const ChipSize &AM29F016Driver::getChipSize(void) const {
return _STANDARD_CHIP_SIZE; return _STANDARD_CHIP_SIZE;
} }
/* Fujitsu MBM29F040A driver */ /* AMD AM29F040 (Fujitsu MBM29F040A) driver */
// Konami's drivers handle this chip pretty much identically to the MBM29F016A, // Konami's drivers handle this chip pretty much identically to the MBM29F016A,
// but using 0x5555/0x2aaa as command addresses instead of 0x555/0x2aa. // 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); volatile uint16_t *ptr = _region.getRawPtr(offset, true);
offset = (offset % FLASH_BANK_LENGTH) / 2; offset = (offset % FLASH_BANK_LENGTH) / 2;
@ -493,7 +515,7 @@ void MBM29F040ADriver::write(uint32_t offset, uint16_t value) {
ptr[offset] = value; ptr[offset] = value;
} }
void MBM29F040ADriver::eraseSector(uint32_t offset) { void AM29F040Driver::eraseSector(uint32_t offset) {
volatile uint16_t *ptr = _region.getRawPtr(offset, true); volatile uint16_t *ptr = _region.getRawPtr(offset, true);
offset = (offset % FLASH_BANK_LENGTH) / 2; offset = (offset % FLASH_BANK_LENGTH) / 2;
@ -506,7 +528,7 @@ void MBM29F040ADriver::eraseSector(uint32_t offset) {
ptr[offset] = _JEDEC_ERASE_SECTOR; 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); volatile uint16_t *ptr = _region.getRawPtr(offset, true);
ptr[0x0005] = _JEDEC_RESET; ptr[0x0005] = _JEDEC_RESET;
@ -518,6 +540,10 @@ void MBM29F040ADriver::eraseChip(uint32_t offset) {
ptr[0x5555] = _JEDEC_ERASE_CHIP; ptr[0x5555] = _JEDEC_ERASE_CHIP;
} }
const ChipSize &AM29F040Driver::getChipSize(void) const {
return _ALT_CHIP_SIZE;
}
/* Intel 28F016S5 (Sharp LH28F016S) driver */ /* Intel 28F016S5 (Sharp LH28F016S) driver */
enum IntelStatusFlag : uint16_t { enum IntelStatusFlag : uint16_t {
@ -533,14 +559,15 @@ enum IntelStatusFlag : uint16_t {
DriverError Intel28F016S5Driver::_flush(uint32_t offset, int timeout) { DriverError Intel28F016S5Driver::_flush(uint32_t offset, int timeout) {
volatile uint16_t *ptr = _region.getRawPtr(offset & ~1); 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 // Not required as all write/erase commands already put the chip into status
// reading mode. // reading mode.
//*ptr = _INTEL_GET_STATUS; //*ptr = _INTEL_GET_STATUS;
for (; timeout > 0; timeout--) { for (; timeout > 0; timeout -= 10) {
uint8_t status = (*ptr >> shift) & 0xff; status = (*ptr >> shift) & 0xff;
if (status & (_INTEL_STATUS_DPS | _INTEL_STATUS_VPPS)) { if (status & (_INTEL_STATUS_DPS | _INTEL_STATUS_VPPS)) {
LOG("locked @ 0x%08x, stat=0x%02x", offset, status); LOG("locked @ 0x%08x, stat=0x%02x", offset, status);
@ -562,7 +589,7 @@ DriverError Intel28F016S5Driver::_flush(uint32_t offset, int timeout) {
delayMicroseconds(10); 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; *ptr = _INTEL_CLEAR_STATUS;
return CHIP_TIMEOUT; return CHIP_TIMEOUT;

View File

@ -128,12 +128,12 @@ public:
const ChipSize &getChipSize(void) const; const ChipSize &getChipSize(void) const;
}; };
class MBM29F016ADriver : public Driver { class AM29F016Driver : public Driver {
protected: protected:
DriverError _flush(uint32_t offset, uint16_t value, int timeout); DriverError _flush(uint32_t offset, uint16_t value, int timeout);
public: public:
inline MBM29F016ADriver(const FlashRegion &region) inline AM29F016Driver(const FlashRegion &region)
: Driver(region) {} : Driver(region) {}
virtual void write(uint32_t offset, uint16_t value); virtual void write(uint32_t offset, uint16_t value);
@ -144,14 +144,15 @@ public:
const ChipSize &getChipSize(void) const; const ChipSize &getChipSize(void) const;
}; };
class MBM29F040ADriver : public MBM29F016ADriver { class AM29F040Driver : public AM29F016Driver {
public: public:
inline MBM29F040ADriver(const FlashRegion &region) inline AM29F040Driver(const FlashRegion &region)
: MBM29F016ADriver(region) {} : AM29F016Driver(region) {}
void write(uint32_t offset, uint16_t value); void write(uint32_t offset, uint16_t value);
void eraseSector(uint32_t offset); void eraseSector(uint32_t offset);
void eraseChip(uint32_t offset); void eraseChip(uint32_t offset);
const ChipSize &getChipSize(void) const;
}; };
class Intel28F016S5Driver : public Driver { class Intel28F016S5Driver : public Driver {

View File

@ -58,6 +58,8 @@ void WorkerStatus::finish(void) {
/* App class */ /* App class */
static constexpr size_t _WORKER_STACK_SIZE = 0x20000;
App::App(ui::Context &ctx, file::ZIPProvider &resourceProvider) App::App(ui::Context &ctx, file::ZIPProvider &resourceProvider)
#ifdef ENABLE_LOG_BUFFER #ifdef ENABLE_LOG_BUFFER
: _overlayLayer(_logBuffer), : _overlayLayer(_logBuffer),
@ -65,9 +67,7 @@ App::App(ui::Context &ctx, file::ZIPProvider &resourceProvider)
: :
#endif #endif
_ctx(ctx), _resourceProvider(resourceProvider), _resourceFile(nullptr), _ctx(ctx), _resourceProvider(resourceProvider), _resourceFile(nullptr),
_cartDriver(nullptr), _cartParser(nullptr), _identified(nullptr) { _cartDriver(nullptr), _cartParser(nullptr), _identified(nullptr) {}
_workerStack = new uint8_t[WORKER_STACK_SIZE];
}
App::~App(void) { App::~App(void) {
_unloadCartData(); _unloadCartData();
@ -79,8 +79,6 @@ App::~App(void) {
} }
//_fileProvider.close(); //_fileProvider.close();
delete[] _workerStack;
} }
void App::_unloadCartData(void) { void App::_unloadCartData(void) {
@ -93,10 +91,10 @@ void App::_unloadCartData(void) {
_cartParser = nullptr; _cartParser = nullptr;
} }
_dump.chipType = cart::NONE; _cartDump.chipType = cart::NONE;
_dump.flags = 0; _cartDump.flags = 0;
_dump.clearIdentifiers(); _cartDump.clearIdentifiers();
_dump.clearData(); _cartDump.clearData();
_identified = nullptr; _identified = nullptr;
//_selectedEntry = nullptr; //_selectedEntry = nullptr;
@ -107,13 +105,16 @@ void App::_setupWorker(bool (App::*func)(void)) {
auto enable = disableInterrupts(); auto enable = disableInterrupts();
_workerStack.allocate(_WORKER_STACK_SIZE);
_workerStatus.reset(); _workerStatus.reset();
_workerFunction = func;
_workerFunction = func;
auto stackBottom = _workerStack.as<uint8_t>();
initThread( initThread(
// This is not how you implement delegates in C++. // This is not how you implement delegates in C++.
&_workerThread, util::forcedCast<ArgFunction>(&App::_worker), this, &_workerThread, util::forcedCast<ArgFunction>(&App::_worker), this,
&_workerStack[(WORKER_STACK_SIZE - 1) & ~7] &stackBottom[(_WORKER_STACK_SIZE - 1) & ~7]
); );
if (enable) if (enable)
enableInterrupts(); enableInterrupts();

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include <stdint.h>
#include "common/file.hpp" #include "common/file.hpp"
#include "main/app/cartactions.hpp" #include "main/app/cartactions.hpp"
#include "main/app/cartunlock.hpp" #include "main/app/cartunlock.hpp"
@ -50,8 +49,6 @@ public:
/* App class */ /* App class */
static constexpr size_t WORKER_STACK_SIZE = 0x20000;
class App { class App {
friend class WorkerStatusScreen; friend class WorkerStatusScreen;
friend class MessageScreen; friend class MessageScreen;
@ -110,13 +107,16 @@ private:
file::FATProvider _fileProvider; file::FATProvider _fileProvider;
file::StringTable _stringTable; file::StringTable _stringTable;
cart::CartDump _dump; cart::CartDump _cartDump;
cart::CartDB _db; cart::ROMHeaderDump _romHeaderDump;
Thread _workerThread; cart::CartDB _cartDB;
WorkerStatus _workerStatus; cart::ROMHeaderDB _romHeaderDB;
bool (App::*_workerFunction)(void);
Thread _workerThread;
util::Data _workerStack;
WorkerStatus _workerStatus;
bool (App::*_workerFunction)(void);
uint8_t *_workerStack;
cart::Driver *_cartDriver; cart::Driver *_cartDriver;
cart::CartParser *_cartParser; cart::CartParser *_cartParser;
const cart::CartDBEntry *_identified, *_selectedEntry; const cart::CartDBEntry *_identified, *_selectedEntry;

View File

@ -1,5 +1,4 @@
#include "common/defs.hpp"
#include "common/util.hpp" #include "common/util.hpp"
#include "main/app/cartactions.hpp" #include "main/app/cartactions.hpp"
#include "main/app/app.hpp" #include "main/app/app.hpp"
@ -139,12 +138,12 @@ void CartActionsScreen::resetSystemID(ui::Context &ctx) {
} }
void CartActionsScreen::matchSystemID(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( APP->_confirmScreen.setMessage(
*this, *this,
[](ui::Context &ctx) { [](ui::Context &ctx) {
APP->_cartParser->getIdentifiers()->systemID.copyFrom( APP->_cartParser->getIdentifiers()->systemID.copyFrom(
APP->_dump.systemID.data APP->_cartDump.systemID.data
); );
APP->_cartParser->flush(); APP->_cartParser->flush();
@ -238,12 +237,12 @@ void HexdumpScreen::show(ui::Context &ctx, bool goBack) {
_body = _bodyText; _body = _bodyText;
_prompt = STR("HexdumpScreen.prompt"); _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)]; char *ptr = _bodyText, *end = &_bodyText[sizeof(_bodyText)];
for (size_t i = 0; i < length; i += 16) { for (size_t i = 0; i < length; i += 16) {
ptr += snprintf(ptr, end - ptr, "%04X: ", i); 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'; *(ptr++) = '\n';
} }
@ -264,7 +263,7 @@ void HexdumpScreen::update(ui::Context &ctx) {
const char *ReflashGameScreen::_getItemName(ui::Context &ctx, int index) const { const char *ReflashGameScreen::_getItemName(ui::Context &ctx, int index) const {
static char name[96]; // TODO: get rid of this ugly crap 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; return name;
} }
@ -273,7 +272,7 @@ void ReflashGameScreen::show(ui::Context &ctx, bool goBack) {
_prompt = STR("ReflashGameScreen.prompt"); _prompt = STR("ReflashGameScreen.prompt");
_itemPrompt = STR("ReflashGameScreen.itemPrompt"); _itemPrompt = STR("ReflashGameScreen.itemPrompt");
_listLength = APP->_db.getNumEntries(); _listLength = APP->_cartDB.getNumEntries();
ListScreen::show(ctx, goBack); ListScreen::show(ctx, goBack);
} }
@ -294,7 +293,7 @@ void ReflashGameScreen::update(ui::Context &ctx) {
STR("CartActionsScreen.reflash.confirm") STR("CartActionsScreen.reflash.confirm")
); );
APP->_selectedEntry = APP->_db.get(_activeItem); APP->_selectedEntry = APP->_cartDB.get(_activeItem);
ctx.show(APP->_confirmScreen, false, true); ctx.show(APP->_confirmScreen, false, true);
} }
} }

View File

@ -40,7 +40,7 @@ void CartInfoScreen::show(ui::Context &ctx, bool goBack) {
_title = STR("CartInfoScreen.title"); _title = STR("CartInfoScreen.title");
_body = _bodyText; _body = _bodyText;
auto &dump = APP->_dump; auto &dump = APP->_cartDump;
char id1[32], id2[32], config[32]; char id1[32], id2[32], config[32];
char *ptr = _bodyText, *end = &_bodyText[sizeof(_bodyText)]; char *ptr = _bodyText, *end = &_bodyText[sizeof(_bodyText)];
@ -178,7 +178,7 @@ void CartInfoScreen::show(ui::Context &ctx, bool goBack) {
} else if ( } else if (
dump.flags & (cart::DUMP_PUBLIC_DATA_OK | cart::DUMP_PRIVATE_DATA_OK) 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 { } else {
state = UNKNOWN; state = UNKNOWN;
} }
@ -207,8 +207,8 @@ void CartInfoScreen::update(ui::Context &ctx) {
if (ctx.buttons.pressed(ui::BTN_START)) { if (ctx.buttons.pressed(ui::BTN_START)) {
if (ctx.buttons.held(ui::BTN_LEFT) || ctx.buttons.held(ui::BTN_RIGHT)) { if (ctx.buttons.held(ui::BTN_LEFT) || ctx.buttons.held(ui::BTN_RIGHT)) {
ctx.show(APP->_mainMenuScreen, true, true); ctx.show(APP->_mainMenuScreen, true, true);
} else if (APP->_dump.chipType) { } else if (APP->_cartDump.chipType) {
if (APP->_dump.flags & cart::DUMP_PRIVATE_DATA_OK) if (APP->_cartDump.flags & cart::DUMP_PRIVATE_DATA_OK)
ctx.show(APP->_cartActionsScreen, false, true); ctx.show(APP->_cartActionsScreen, false, true);
else else
ctx.show(APP->_unlockKeyScreen, false, true); 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 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; return name;
} }
void UnlockKeyScreen::autoUnlock(ui::Context &ctx) { void UnlockKeyScreen::autoUnlock(ui::Context &ctx) {
__builtin_memcpy( __builtin_memcpy(
APP->_dump.dataKey, APP->_identified->dataKey, APP->_cartDump.dataKey, APP->_identified->dataKey,
sizeof(APP->_dump.dataKey) sizeof(APP->_cartDump.dataKey)
); );
//APP->_selectedEntry = APP->_identified; //APP->_selectedEntry = APP->_identified;
@ -282,7 +282,7 @@ void UnlockKeyScreen::useCustomKey(ui::Context &ctx) {
void UnlockKeyScreen::use00Key(ui::Context &ctx) { void UnlockKeyScreen::use00Key(ui::Context &ctx) {
__builtin_memset( __builtin_memset(
APP->_dump.dataKey, 0x00, sizeof(APP->_dump.dataKey) APP->_cartDump.dataKey, 0x00, sizeof(APP->_cartDump.dataKey)
); );
APP->_selectedEntry = nullptr; APP->_selectedEntry = nullptr;
@ -291,7 +291,7 @@ void UnlockKeyScreen::use00Key(ui::Context &ctx) {
void UnlockKeyScreen::useFFKey(ui::Context &ctx) { void UnlockKeyScreen::useFFKey(ui::Context &ctx) {
__builtin_memset( __builtin_memset(
APP->_dump.dataKey, 0xff, sizeof(APP->_dump.dataKey) APP->_cartDump.dataKey, 0xff, sizeof(APP->_cartDump.dataKey)
); );
APP->_selectedEntry = nullptr; APP->_selectedEntry = nullptr;
@ -303,7 +303,7 @@ void UnlockKeyScreen::show(ui::Context &ctx, bool goBack) {
_prompt = STR("UnlockKeyScreen.prompt"); _prompt = STR("UnlockKeyScreen.prompt");
_itemPrompt = STR("UnlockKeyScreen.itemPrompt"); _itemPrompt = STR("UnlockKeyScreen.itemPrompt");
_listLength = APP->_db.getNumEntries() - _getSpecialEntryOffset(ctx); _listLength = APP->_cartDB.getNumEntries() - _getSpecialEntryOffset(ctx);
ListScreen::show(ctx, goBack); 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)) { if (ctx.buttons.held(ui::BTN_LEFT) || ctx.buttons.held(ui::BTN_RIGHT)) {
ctx.show(APP->_cartInfoScreen, true, true); ctx.show(APP->_cartInfoScreen, true, true);
} else { } else {
int index = _activeItem + _getSpecialEntryOffset(ctx); auto &dump = APP->_cartDump;
int index = _activeItem + _getSpecialEntryOffset(ctx);
APP->_confirmScreen.setMessage( APP->_confirmScreen.setMessage(
APP->_unlockKeyScreen, APP->_unlockKeyScreen,
@ -323,18 +324,18 @@ void UnlockKeyScreen::update(ui::Context &ctx) {
APP->_setupWorker(&App::_cartUnlockWorker); APP->_setupWorker(&App::_cartUnlockWorker);
ctx.show(APP->_workerStatusScreen, false, true); ctx.show(APP->_workerStatusScreen, false, true);
}, },
STRH(_UNLOCK_WARNINGS[APP->_dump.chipType]) STRH(_UNLOCK_WARNINGS[dump.chipType])
); );
if (index < 0) { if (index < 0) {
(this->*_SPECIAL_ENTRIES[-index].target)(ctx); (this->*_SPECIAL_ENTRIES[-index].target)(ctx);
} else { } else {
__builtin_memcpy( __builtin_memcpy(
APP->_dump.dataKey, APP->_db.get(index)->dataKey, dump.dataKey, APP->_cartDB.get(index)->dataKey,
sizeof(APP->_dump.dataKey) sizeof(dump.dataKey)
); );
APP->_selectedEntry = APP->_db.get(index); APP->_selectedEntry = APP->_cartDB.get(index);
ctx.show(APP->_confirmScreen, false, true); ctx.show(APP->_confirmScreen, false, true);
} }
} }
@ -363,6 +364,8 @@ void KeyEntryScreen::update(ui::Context &ctx) {
if (_activeButton == _buttonIndexOffset) { if (_activeButton == _buttonIndexOffset) {
ctx.show(APP->_unlockKeyScreen, true, true); ctx.show(APP->_unlockKeyScreen, true, true);
} else if (_activeButton == (_buttonIndexOffset + 1)) { } else if (_activeButton == (_buttonIndexOffset + 1)) {
auto &dump = APP->_cartDump;
// TODO: deduplicate this code (it is the same as UnlockKeyScreen) // TODO: deduplicate this code (it is the same as UnlockKeyScreen)
APP->_confirmScreen.setMessage( APP->_confirmScreen.setMessage(
APP->_unlockKeyScreen, APP->_unlockKeyScreen,
@ -370,12 +373,10 @@ void KeyEntryScreen::update(ui::Context &ctx) {
APP->_setupWorker(&App::_cartUnlockWorker); APP->_setupWorker(&App::_cartUnlockWorker);
ctx.show(APP->_workerStatusScreen, false, true); ctx.show(APP->_workerStatusScreen, false, true);
}, },
STRH(_UNLOCK_WARNINGS[APP->_dump.chipType]) STRH(_UNLOCK_WARNINGS[dump.chipType])
); );
__builtin_memcpy( __builtin_memcpy(dump.dataKey, _buffer, sizeof(dump.dataKey));
APP->_dump.dataKey, _buffer, sizeof(APP->_dump.dataKey)
);
ctx.show(APP->_confirmScreen, false, true); ctx.show(APP->_confirmScreen, false, true);
} }
} }

View File

@ -31,17 +31,17 @@ bool App::_cartDetectWorker(void) {
if (cart::dummyDriverDump.chipType) { if (cart::dummyDriverDump.chipType) {
LOG("using dummy cart driver"); LOG("using dummy cart driver");
_cartDriver = new cart::DummyDriver(_dump); _cartDriver = new cart::DummyDriver(_cartDump);
_cartDriver->readSystemID(); _cartDriver->readSystemID();
} else { } else {
_cartDriver = cart::newCartDriver(_dump); _cartDriver = cart::newCartDriver(_cartDump);
} }
#else #else
_cartDriver = cart::newCartDriver(_dump); _cartDriver = cart::newCartDriver(_cartDump);
#endif #endif
if (_dump.chipType) { if (_cartDump.chipType) {
LOG("cart dump @ 0x%08x", &_dump); LOG("cart dump @ 0x%08x", &_cartDump);
LOG("cart driver @ 0x%08x", _cartDriver); LOG("cart driver @ 0x%08x", _cartDriver);
auto error = _cartDriver->readCartID(); auto error = _cartDriver->readCartID();
@ -53,17 +53,17 @@ bool App::_cartDetectWorker(void) {
if (error) if (error)
LOG("read error [%s]", cart::getErrorString(error)); LOG("read error [%s]", cart::getErrorString(error));
else if (!_dump.isReadableDataEmpty()) else if (!_cartDump.isReadableDataEmpty())
_cartParser = cart::newCartParser(_dump); _cartParser = cart::newCartParser(_cartDump);
LOG("cart parser @ 0x%08x", _cartParser); LOG("cart parser @ 0x%08x", _cartParser);
_workerStatus.update(1, 3, WSTR("App.cartDetectWorker.identifyGame")); _workerStatus.update(1, 3, WSTR("App.cartDetectWorker.identifyGame"));
if (!_db.ptr) { if (!_cartDB.ptr) {
if (!_resourceProvider.loadData( 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; goto _cartInitDone;
} }
} }
@ -73,7 +73,7 @@ bool App::_cartDetectWorker(void) {
if (!_cartParser) if (!_cartParser)
goto _cartInitDone; goto _cartInitDone;
if (_cartParser->getCode(code) && _cartParser->getRegion(region)) if (_cartParser->getCode(code) && _cartParser->getRegion(region))
_identified = _db.lookup(code, region); _identified = _cartDB.lookup(code, region);
if (!_identified) if (!_identified)
goto _cartInitDone; goto _cartInitDone;
@ -81,7 +81,7 @@ bool App::_cartDetectWorker(void) {
// ambiguity between different formats). // ambiguity between different formats).
delete _cartParser; delete _cartParser;
_cartParser = cart::newCartParser( _cartParser = cart::newCartParser(
_dump, _identified->formatType, _identified->flags _cartDump, _identified->formatType, _identified->flags
); );
LOG("new cart parser @ 0x%08x", _cartParser); LOG("new cart parser @ 0x%08x", _cartParser);
@ -90,11 +90,12 @@ bool App::_cartDetectWorker(void) {
_cartInitDone: _cartInitDone:
_workerStatus.update(2, 3, WSTR("App.cartDetectWorker.readDigitalIO")); _workerStatus.update(2, 3, WSTR("App.cartDetectWorker.readDigitalIO"));
if (
#ifdef ENABLE_DUMMY_DRIVER #ifdef ENABLE_DUMMY_DRIVER
if (io::isDigitalIOPresent() && !(_dump.flags & cart::DUMP_SYSTEM_ID_OK)) { !(_cartDump.flags & cart::DUMP_SYSTEM_ID_OK) &&
#else
if (io::isDigitalIOPresent()) {
#endif #endif
io::isDigitalIOPresent()
) {
util::Data bitstream; util::Data bitstream;
bool ready; bool ready;
@ -141,7 +142,8 @@ bool App::_cartUnlockWorker(void) {
if (error) { if (error) {
_messageScreen.setMessage( _messageScreen.setMessage(
MESSAGE_ERROR, _cartInfoScreen, MESSAGE_ERROR, _cartInfoScreen,
WSTRH(_UNLOCK_ERRORS[_dump.chipType]), cart::getErrorString(error) WSTRH(_UNLOCK_ERRORS[_cartDump.chipType]),
cart::getErrorString(error)
); );
_workerStatus.setNextScreen(_messageScreen); _workerStatus.setNextScreen(_messageScreen);
@ -151,7 +153,7 @@ bool App::_cartUnlockWorker(void) {
if (_cartParser) if (_cartParser)
delete _cartParser; delete _cartParser;
_cartParser = cart::newCartParser(_dump); _cartParser = cart::newCartParser(_cartDump);
if (!_cartParser) if (!_cartParser)
return true; return true;
@ -162,7 +164,7 @@ bool App::_cartUnlockWorker(void) {
char code[8], region[8]; char code[8], region[8];
if (_cartParser->getCode(code) && _cartParser->getRegion(region)) 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), // If auto-identification failed (e.g. because the format has no game code),
// use the game whose unlocking key was selected as a hint. // use the game whose unlocking key was selected as a hint.
@ -177,7 +179,7 @@ bool App::_cartUnlockWorker(void) {
delete _cartParser; delete _cartParser;
_cartParser = cart::newCartParser( _cartParser = cart::newCartParser(
_dump, _identified->formatType, _identified->flags _cartDump, _identified->formatType, _identified->flags
); );
LOG("new cart parser @ 0x%08x", _cartParser); LOG("new cart parser @ 0x%08x", _cartParser);
@ -189,7 +191,7 @@ bool App::_qrCodeWorker(void) {
_workerStatus.setNextScreen(_qrCodeScreen); _workerStatus.setNextScreen(_qrCodeScreen);
_workerStatus.update(0, 2, WSTR("App.qrCodeWorker.compress")); _workerStatus.update(0, 2, WSTR("App.qrCodeWorker.compress"));
_dump.toQRString(qrString); _cartDump.toQRString(qrString);
_workerStatus.update(1, 2, WSTR("App.qrCodeWorker.generate")); _workerStatus.update(1, 2, WSTR("App.qrCodeWorker.generate"));
_qrCodeScreen.generateCode(qrString); _qrCodeScreen.generateCode(qrString);
@ -213,7 +215,7 @@ bool App::_cartDumpWorker(void) {
char code[8], region[8]; char code[8], region[8];
size_t length; size_t length;
length = _dump.getDumpLength(); length = _cartDump.getDumpLength();
if ( if (
_identified && _cartParser->getCode(code) && _identified && _cartParser->getCode(code) &&
@ -235,7 +237,7 @@ bool App::_cartDumpWorker(void) {
LOG("saving %s, length=%d", path, length); LOG("saving %s, length=%d", path, length);
if (_fileProvider.saveData(&_dump, length, path) != length) if (_fileProvider.saveData(&_cartDump, length, path) != length)
goto _error; goto _error;
_messageScreen.setMessage( _messageScreen.setMessage(
@ -273,7 +275,7 @@ bool App::_cartWriteWorker(void) {
return false; return false;
} }
_dump.copyKeyFrom(key); _cartDump.copyKeyFrom(key);
return _cartUnlockWorker(); return _cartUnlockWorker();
} }
@ -301,7 +303,7 @@ bool App::_cartRestoreWorker(void) {
_file->close(); _file->close();
delete _file; delete _file;
if (_dump.chipType != newDump.chipType) { if (_cartDump.chipType != newDump.chipType) {
_messageScreen.setMessage( _messageScreen.setMessage(
MESSAGE_ERROR, _filePickerScreen, MESSAGE_ERROR, _filePickerScreen,
WSTR("App.cartRestoreWorker.typeError"), path WSTR("App.cartRestoreWorker.typeError"), path
@ -321,9 +323,9 @@ bool App::_cartRestoreWorker(void) {
if (newDump.flags & ( if (newDump.flags & (
cart::DUMP_PUBLIC_DATA_OK | cart::DUMP_PRIVATE_DATA_OK 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) if (newDump.flags & cart::DUMP_CONFIG_OK)
_dump.copyConfigFrom(newDump.config); _cartDump.copyConfigFrom(newDump.config);
_workerStatus.update(2, 3, WSTR("App.cartRestoreWorker.write")); _workerStatus.update(2, 3, WSTR("App.cartRestoreWorker.write"));
error = _cartDriver->writeData(); 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. // Make sure a valid cart ID is present if required by the new data.
if ( if (
_selectedEntry->requiresCartID() && _selectedEntry->requiresCartID() &&
!(_dump.flags & cart::DUMP_CART_ID_OK) !(_cartDump.flags & cart::DUMP_CART_ID_OK)
) { ) {
_messageScreen.setMessage( _messageScreen.setMessage(
MESSAGE_ERROR, _cartInfoScreen, MESSAGE_ERROR, _cartInfoScreen,
@ -382,21 +384,23 @@ bool App::_cartReflashWorker(void) {
delete _cartParser; delete _cartParser;
_cartParser = cart::newCartParser( _cartParser = cart::newCartParser(
_dump, _selectedEntry->formatType, _selectedEntry->flags _cartDump, _selectedEntry->formatType, _selectedEntry->flags
); );
auto pri = _cartParser->getIdentifiers(); auto pri = _cartParser->getIdentifiers();
auto pub = _cartParser->getPublicIdentifiers(); auto pub = _cartParser->getPublicIdentifiers();
_dump.clearData(); _cartDump.clearData();
_dump.initConfig(9, _selectedEntry->flags & cart::DATA_HAS_PUBLIC_SECTION); _cartDump.initConfig(
9, _selectedEntry->flags & cart::DATA_HAS_PUBLIC_SECTION
);
if (pri) { if (pri) {
if (_selectedEntry->flags & cart::DATA_HAS_CART_ID) 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) if (_selectedEntry->flags & cart::DATA_HAS_TRACE_ID)
pri->updateTraceID( pri->updateTraceID(
_selectedEntry->traceIDType, _selectedEntry->traceIDParam, _selectedEntry->traceIDType, _selectedEntry->traceIDParam,
&_dump.cartID &_cartDump.cartID
); );
if (_selectedEntry->flags & cart::DATA_HAS_INSTALL_ID) { if (_selectedEntry->flags & cart::DATA_HAS_INSTALL_ID) {
// The private installation ID seems to be unused on carts with a // The private installation ID seems to be unused on carts with a

View File

@ -37,10 +37,14 @@ bool App::_startupWorker(void) {
_workerStatus.update(2, 4, WSTR("App.startupWorker.initFAT")); _workerStatus.update(2, 4, WSTR("App.startupWorker.initFAT"));
#if 0
// Attempt to mount the secondary drive first, then in case of failure try // Attempt to mount the secondary drive first, then in case of failure try
// mounting the primary drive instead. // mounting the primary drive instead.
if (!_fileProvider.init("1:")) if (!_fileProvider.init("1:"))
_fileProvider.init("0:"); _fileProvider.init("0:");
#else
_fileProvider.init("1:");
#endif
_workerStatus.update(3, 4, WSTR("App.startupWorker.loadResources")); _workerStatus.update(3, 4, WSTR("App.startupWorker.loadResources"));

View File

@ -299,7 +299,7 @@ void StorageActionsScreen::update(ui::Context &ctx) {
if (ctx.buttons.pressed(ui::BTN_START)) { if (ctx.buttons.pressed(ui::BTN_START)) {
if (ctx.buttons.held(ui::BTN_LEFT) || ctx.buttons.held(ui::BTN_RIGHT)) { 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 { } else {
if (action.region.isPresent()) { if (action.region.isPresent()) {
this->_selectedRegion = &(action.region); this->_selectedRegion = &(action.region);
@ -322,9 +322,9 @@ void ChecksumScreen::show(ui::Context &ctx, bool goBack) {
char *ptr = _bodyText, *end = &_bodyText[sizeof(_bodyText)]; char *ptr = _bodyText, *end = &_bodyText[sizeof(_bodyText)];
_PRINT(STR("ChecksumScreen.bios"), biosCRC); _PRINT(STR("ChecksumScreen.bios"), values.bios);
_PRINT(STR("ChecksumScreen.rtc"), rtcCRC); _PRINT(STR("ChecksumScreen.rtc"), values.rtc);
_PRINT(STR("ChecksumScreen.flash"), flashCRC); _PRINT(STR("ChecksumScreen.flash"), values.flash);
_PRINTLN(); _PRINTLN();
@ -333,7 +333,7 @@ void ChecksumScreen::show(ui::Context &ctx, bool goBack) {
continue; continue;
auto slot = i + 1; 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, 16, crc[0]);
_PRINT(STR("ChecksumScreen.pcmcia"), slot, 32, crc[1]); _PRINT(STR("ChecksumScreen.pcmcia"), slot, 32, crc[1]);
@ -342,7 +342,9 @@ void ChecksumScreen::show(ui::Context &ctx, bool goBack) {
_PRINTLN(); _PRINTLN();
} }
*(--ptr) = 0; _PRINT(STR("ChecksumScreen.description"));
//*(--ptr) = 0;
LOG("remaining=%d", end - ptr); LOG("remaining=%d", end - ptr);
TextScreen::show(ctx, goBack); TextScreen::show(ctx, goBack);

View File

@ -41,14 +41,21 @@ public:
void update(ui::Context &ctx); 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 { class ChecksumScreen : public ui::TextScreen {
private: private:
char _bodyText[2048]; char _bodyText[2048];
public: public:
bool valid; bool valid;
uint32_t biosCRC, rtcCRC, flashCRC; ChecksumValues values;
uint32_t pcmciaCRC[2][4];
inline ChecksumScreen(void) inline ChecksumScreen(void)
: valid(false) {} : valid(false) {}

View File

@ -23,31 +23,31 @@ static const RegionInfo _REGION_INFO[]{
.crcPrompt = "App.romChecksumWorker.hashBIOS"_h, .crcPrompt = "App.romChecksumWorker.hashBIOS"_h,
.path = "%s/bios.bin", .path = "%s/bios.bin",
.region = rom::bios, .region = rom::bios,
.crcOffset = offsetof(ChecksumScreen, biosCRC) .crcOffset = offsetof(ChecksumValues, bios)
}, { }, {
.dumpPrompt = "App.romDumpWorker.dumpRTC"_h, .dumpPrompt = "App.romDumpWorker.dumpRTC"_h,
.crcPrompt = "App.romChecksumWorker.hashRTC"_h, .crcPrompt = "App.romChecksumWorker.hashRTC"_h,
.path = "%s/rtc.bin", .path = "%s/rtc.bin",
.region = rom::rtc, .region = rom::rtc,
.crcOffset = offsetof(ChecksumScreen, rtcCRC) .crcOffset = offsetof(ChecksumValues, rtc)
}, { }, {
.dumpPrompt = "App.romDumpWorker.dumpFlash"_h, .dumpPrompt = "App.romDumpWorker.dumpFlash"_h,
.crcPrompt = "App.romChecksumWorker.hashFlash"_h, .crcPrompt = "App.romChecksumWorker.hashFlash"_h,
.path = "%s/flash.bin", .path = "%s/flash.bin",
.region = rom::flash, .region = rom::flash,
.crcOffset = offsetof(ChecksumScreen, flashCRC) .crcOffset = offsetof(ChecksumValues, flash)
}, { }, {
.dumpPrompt = "App.romDumpWorker.dumpPCMCIA1"_h, .dumpPrompt = "App.romDumpWorker.dumpPCMCIA1"_h,
.crcPrompt = "App.romChecksumWorker.hashPCMCIA1"_h, .crcPrompt = "App.romChecksumWorker.hashPCMCIA1"_h,
.path = "%s/pcmcia1.bin", .path = "%s/pcmcia1.bin",
.region = rom::pcmcia[0], .region = rom::pcmcia[0],
.crcOffset = offsetof(ChecksumScreen, pcmciaCRC[0]) .crcOffset = offsetof(ChecksumValues, pcmcia[0])
}, { }, {
.dumpPrompt = "App.romDumpWorker.dumpPCMCIA2"_h, .dumpPrompt = "App.romDumpWorker.dumpPCMCIA2"_h,
.crcPrompt = "App.romChecksumWorker.hashPCMCIA2"_h, .crcPrompt = "App.romChecksumWorker.hashPCMCIA2"_h,
.path = "%s/pcmcia2.bin", .path = "%s/pcmcia2.bin",
.region = rom::pcmcia[1], .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 offset = 0;
uint32_t crc = 0; uint32_t crc = 0;
auto crcPtr = reinterpret_cast<uint32_t *>( auto crcPtr = reinterpret_cast<uint32_t *>(
reinterpret_cast<uintptr_t>(&_checksumScreen) + entry.crcOffset reinterpret_cast<uintptr_t>(&_checksumScreen.values) +
entry.crcOffset
); );
// Flash cards can be 16, 32 or 64 MB, so copies of the current CRC are // 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; return true;
} }

View File

@ -709,6 +709,6 @@ template<typename T> const T *DB<T>::lookup(
} }
template class DB<CartDBEntry>; template class DB<CartDBEntry>;
template class DB<FlashDBEntry>; template class DB<ROMHeaderDBEntry>;
} }

View File

@ -295,7 +295,7 @@ public:
} }
}; };
class [[gnu::packed]] FlashDBEntry { class [[gnu::packed]] ROMHeaderDBEntry {
public: public:
// TODO: define these flags // TODO: define these flags
uint8_t flags; uint8_t flags;
@ -332,7 +332,7 @@ public:
const T *lookup(const char *code, const char *region) const; const T *lookup(const char *code, const char *region) const;
}; };
using CartDB = DB<CartDBEntry>; using CartDB = DB<CartDBEntry>;
using FlashDB = DB<FlashDBEntry>; using ROMHeaderDB = DB<ROMHeaderDBEntry>;
} }