mirror of
https://github.com/spicyjpeg/573in1.git
synced 2025-01-22 11:43:39 +01:00
More minor fixes and renames
This commit is contained in:
parent
3534e99dca
commit
fad8aa11bc
@ -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": {
|
||||
|
@ -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<volatile uint16_t *>(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;
|
||||
|
@ -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 {
|
||||
|
@ -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<uint8_t>();
|
||||
|
||||
initThread(
|
||||
// This is not how you implement delegates in C++.
|
||||
&_workerThread, util::forcedCast<ArgFunction>(&App::_worker), this,
|
||||
&_workerStack[(WORKER_STACK_SIZE - 1) & ~7]
|
||||
&stackBottom[(_WORKER_STACK_SIZE - 1) & ~7]
|
||||
);
|
||||
if (enable)
|
||||
enableInterrupts();
|
||||
|
@ -1,7 +1,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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"));
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {}
|
||||
|
@ -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<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
|
||||
@ -90,6 +91,7 @@ bool App::_romChecksumWorker(void) {
|
||||
}
|
||||
}
|
||||
|
||||
_checksumScreen.valid = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -709,6 +709,6 @@ template<typename T> const T *DB<T>::lookup(
|
||||
}
|
||||
|
||||
template class DB<CartDBEntry>;
|
||||
template class DB<FlashDBEntry>;
|
||||
template class DB<ROMHeaderDBEntry>;
|
||||
|
||||
}
|
||||
|
@ -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<CartDBEntry>;
|
||||
using FlashDB = DB<FlashDBEntry>;
|
||||
using CartDB = DB<CartDBEntry>;
|
||||
using ROMHeaderDB = DB<ROMHeaderDBEntry>;
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user