Change back button combo, update readme, misc. cleanups

This commit is contained in:
spicyjpeg 2023-09-18 22:50:52 +02:00
parent 3e84285837
commit fa7beb023e
No known key found for this signature in database
GPG Key ID: 5CC87404C01DF393
13 changed files with 162 additions and 127 deletions

View File

@ -73,11 +73,13 @@ target_compile_definitions(
cart_tool PRIVATE cart_tool PRIVATE
VERSION="${PROJECT_VERSION}" VERSION="${PROJECT_VERSION}"
$<IF:$<CONFIG:Debug>, $<IF:$<CONFIG:Debug>,
ENABLE_CART_MENU=1
ENABLE_DUMMY_DRIVER=1 ENABLE_DUMMY_DRIVER=1
ENABLE_I2C_LOGGING=1 ENABLE_I2C_LOGGING=1
ENABLE_PS1_CONTROLLER=1 ENABLE_PS1_CONTROLLER=1
, ,
#ENABLE_ARGV=1 #ENABLE_ARGV=1
ENABLE_CART_MENU=1
ENABLE_PS1_CONTROLLER=1 ENABLE_PS1_CONTROLLER=1
> >
) )

View File

@ -1,10 +1,22 @@
Konami System 573 security cartridge tool Konami System 573 security cartridge tool
# Credits
Lead developer: spicyjpeg
Cartridge database: smf
Testing: Naoki Saito
# Disclaimer
This tool is experimental and provided with no warranty whatsoever. It is not
guaranteed to work and improper usage can PERMANENTLY BRICK your System 573
security cartridges. Use this tool at your own risk.
# License
(C) 2022-2023 spicyjpeg (C) 2022-2023 spicyjpeg
WARNING: This tool is experimental and provided with no warranty whatsoever. It TODO: add a license
is not guaranteed to work and improper usage can PERMANENTLY BRICK your System
573 security cartridges. Use this tool at your own risk.
# Third-party licenses # Third-party licenses
@ -101,11 +113,9 @@ the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so, the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions: subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
* The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software. all copies or substantial portions of the Software.
- The Software is provided "as is", without warranty of any kind, express or
* The Software is provided "as is", without warranty of any kind, express or
implied, including but not limited to the warranties of merchantability, implied, including but not limited to the warranties of merchantability,
fitness for a particular purpose and noninfringement. In no event shall the fitness for a particular purpose and noninfringement. In no event shall the
authors or copyright holders be liable for any claim, damages or other authors or copyright holders be liable for any claim, damages or other

View File

@ -7,7 +7,6 @@
"App": { "App": {
"cartDetectWorker": { "cartDetectWorker": {
"readDigitalIO": "Retrieving digital I/O board ID...", "readDigitalIO": "Retrieving digital I/O board ID...",
"identifyCart": "Identifying security cartridge...",
"readCart": "Reading security cartridge...", "readCart": "Reading security cartridge...",
"identifyGame": "Attempting to identify game..." "identifyGame": "Attempting to identify game..."
}, },
@ -50,7 +49,8 @@
"atapiEjectWorker": { "atapiEjectWorker": {
"eject": "Sending eject command...", "eject": "Sending eject command...",
"success": "The drive's tray has been opened.\n\nYou may safely remove or replace the disc and close the tray. All data has been loaded into RAM and the tool will keep running until the 573 is turned off.", "success": "The drive's tray has been opened.\n\nYou may safely remove or replace the disc and close the tray. All data has been loaded into RAM and the tool will keep running until the 573 is turned off.",
"error": "Failed to open the drive's tray. Your drive might be incompatible with the ATAPI driver used by this tool.\n\nPress the Test button to view debug logs." "atapiError": "The drive currently configured as primary on the IDE bus is not an ATAPI CD-ROM drive and does not support ejecting.\n\nPress the Test button to view debug logs.",
"ejectError": "Failed to open the drive's tray. Your drive might be incompatible with the ATAPI driver used by this tool.\n\nPress the Test button to view debug logs."
}, },
"rebootWorker": { "rebootWorker": {
"reboot": "Rebooting system..." "reboot": "Rebooting system..."
@ -71,7 +71,7 @@
"CartActionsScreen": { "CartActionsScreen": {
"title": "{CART_ICON} Cartridge options", "title": "{CART_ICON} Cartridge options",
"itemPrompt": "{RIGHT_ARROW} Press {START_BUTTON} to select, hold {LEFT_BUTTON} + {RIGHT_BUTTON} to go back", "itemPrompt": "{RIGHT_ARROW} Press {START_BUTTON} to select, hold {LEFT_BUTTON}{RIGHT_BUTTON} + {START_BUTTON} to go back",
"qrDump": { "qrDump": {
"name": "Dump cartridge as QR code", "name": "Dump cartridge as QR code",
@ -157,9 +157,9 @@
} }
}, },
"prompt": { "prompt": {
"locked": "Press {START_BUTTON} to unlock the cartridge, hold {LEFT_BUTTON} + {RIGHT_BUTTON} to go back.", "locked": "Press {START_BUTTON} to unlock, hold {LEFT_BUTTON}{RIGHT_BUTTON} + {START_BUTTON} to go back.",
"unlocked": "Press {START_BUTTON} to continue, hold {LEFT_BUTTON} + {RIGHT_BUTTON} to go back.", "unlocked": "Press {START_BUTTON} to continue, hold {LEFT_BUTTON}{RIGHT_BUTTON} + {START_BUTTON} to go back.",
"error": "Hold {LEFT_BUTTON} + {RIGHT_BUTTON} to go back." "error": "Hold {LEFT_BUTTON}{RIGHT_BUTTON} + {START_BUTTON} to go back."
}, },
"x76f041": { "x76f041": {
@ -245,7 +245,7 @@
"ReflashGameScreen": { "ReflashGameScreen": {
"title": "{CART_ICON} Select game to convert cartridge to", "title": "{CART_ICON} Select game to convert cartridge to",
"prompt": "Make sure you select the correct region. Note that cartridges can only be converted for use with games that accept the same cartridge type.", "prompt": "Make sure you select the correct region. Note that cartridges can only be converted for use with games that accept the same cartridge type.",
"itemPrompt": "{RIGHT_ARROW} Press {START_BUTTON} to select, hold {LEFT_BUTTON} + {RIGHT_BUTTON} to go back" "itemPrompt": "{RIGHT_ARROW} Press {START_BUTTON} to select, hold {LEFT_BUTTON}{RIGHT_BUTTON} + {START_BUTTON} to go back"
}, },
"SystemIDEntryScreen": { "SystemIDEntryScreen": {
@ -263,7 +263,7 @@
"UnlockKeyScreen": { "UnlockKeyScreen": {
"title": "{CART_ICON} Select unlocking key", "title": "{CART_ICON} Select unlocking key",
"prompt": "If the cartridge has been converted before, select the game it was last converted to. If it is currently blank, select 00-00-00-00-00-00-00-00.", "prompt": "If the cartridge has been converted before, select the game it was last converted to. If it is currently blank, select 00-00-00-00-00-00-00-00.",
"itemPrompt": "{RIGHT_ARROW} Press {START_BUTTON} to select, hold {LEFT_BUTTON} + {RIGHT_BUTTON} to go back", "itemPrompt": "{RIGHT_ARROW} Press {START_BUTTON} to select, hold {LEFT_BUTTON}{RIGHT_BUTTON} + {START_BUTTON} to go back",
"autoUnlock": "Use key from identified game (recommended)", "autoUnlock": "Use key from identified game (recommended)",
"useCustomKey": "Enter key manually...", "useCustomKey": "Enter key manually...",

View File

@ -1,16 +1,27 @@
Konami System 573 security cartridge reset tool Konami System 573 security cartridge tool
=============================================== =========================================
Version ${PROJECT_VERSION} Release ${PROJECT_VERSION}
Use this disc by simply putting it into your 573; make sure DIP switch 4 (the # Usage
rightmost one) is off. Remember to insert the cartridge you want to reset or
dump prior to turning on the system. Use this disc by simply inserting it into your System 573 and rebooting. Ensure
DIP switch 4 (the rightmost one) is off in order to force the 573 to boot from
the CD-ROM drive rather than the internal flash memory. Remember to insert the
cartridge you want to reset, reflash or dump prior to turning on the system.
# Credits
Lead developer: spicyjpeg
Cartridge database: smf
Testing: Naoki Saito
# Disclaimer
This tool is experimental and provided with no warranty whatsoever. It is not
guaranteed to work and improper usage can PERMANENTLY BRICK your System 573
security cartridges. Use this tool at your own risk.
More information and source code are available at: More information and source code are available at:
${PROJECT_HOMEPAGE_URL} ${PROJECT_HOMEPAGE_URL}
WARNING: This tool is experimental and provided with no warranty whatsoever. It
is not guaranteed to work and improper usage can PERMANENTLY BRICK your System
573 security cartridges. Use this tool at your own risk.

View File

@ -71,7 +71,7 @@ static const char *const _CARTDB_PATHS[cart::NUM_CHIP_TYPES]{
bool App::_cartDetectWorker(void) { bool App::_cartDetectWorker(void) {
_workerStatus.setNextScreen(_cartInfoScreen); _workerStatus.setNextScreen(_cartInfoScreen);
_workerStatus.update(0, 4, WSTR("App.cartDetectWorker.identifyCart")); _workerStatus.update(0, 3, WSTR("App.cartDetectWorker.readCart"));
_unloadCartData(); _unloadCartData();
#ifdef ENABLE_DUMMY_DRIVER #ifdef ENABLE_DUMMY_DRIVER
@ -81,6 +81,7 @@ bool App::_cartDetectWorker(void) {
if (cart::dummyDriverDump.chipType) { if (cart::dummyDriverDump.chipType) {
LOG("using dummy cart driver"); LOG("using dummy cart driver");
_driver = new cart::DummyDriver(_dump); _driver = new cart::DummyDriver(_dump);
_driver->readSystemID();
} else { } else {
_driver = cart::newCartDriver(_dump); _driver = cart::newCartDriver(_dump);
} }
@ -91,7 +92,6 @@ bool App::_cartDetectWorker(void) {
if (_dump.chipType) { if (_dump.chipType) {
LOG("cart dump @ 0x%08x", &_dump); LOG("cart dump @ 0x%08x", &_dump);
LOG("cart driver @ 0x%08x", _driver); LOG("cart driver @ 0x%08x", _driver);
_workerStatus.update(1, 4, WSTR("App.cartDetectWorker.readCart"));
auto error = _driver->readCartID(); auto error = _driver->readCartID();
@ -106,7 +106,7 @@ bool App::_cartDetectWorker(void) {
_parser = cart::newCartParser(_dump); _parser = cart::newCartParser(_dump);
LOG("cart parser @ 0x%08x", _parser); LOG("cart parser @ 0x%08x", _parser);
_workerStatus.update(2, 4, WSTR("App.cartDetectWorker.identifyGame")); _workerStatus.update(1, 3, WSTR("App.cartDetectWorker.identifyGame"));
if (!_db.ptr) { if (!_db.ptr) {
if (!_resourceProvider->loadData( if (!_resourceProvider->loadData(
@ -137,9 +137,13 @@ bool App::_cartDetectWorker(void) {
} }
_cartInitDone: _cartInitDone:
_workerStatus.update(3, 4, WSTR("App.cartDetectWorker.readDigitalIO")); _workerStatus.update(2, 3, WSTR("App.cartDetectWorker.readDigitalIO"));
#ifdef ENABLE_DUMMY_DRIVER
if (io::isDigitalIOPresent() && !(_dump.flags & cart::DUMP_SYSTEM_ID_OK)) {
#else
if (io::isDigitalIOPresent()) { if (io::isDigitalIOPresent()) {
#endif
util::Data bitstream; util::Data bitstream;
bool ready; bool ready;
@ -158,14 +162,12 @@ _cartInitDone:
delayMicroseconds(5000); // Probably not necessary delayMicroseconds(5000); // Probably not necessary
io::initKonamiBitstream(); io::initKonamiBitstream();
}
// This must be outside of the if block above to make sure the system ID
// gets read with the dummy driver.
auto error = _driver->readSystemID(); auto error = _driver->readSystemID();
if (error) if (error)
LOG("XID error [%s]", util::getErrorString(error)); LOG("XID error [%s]", util::getErrorString(error));
}
return true; return true;
} }
@ -330,8 +332,6 @@ bool App::_cartReflashWorker(void) {
_parser->flush(); _parser->flush();
auto error = _driver->setDataKey(_selectedEntry->dataKey); auto error = _driver->setDataKey(_selectedEntry->dataKey);
delayMicroseconds(1000000); // TODO: does this fix ZS01 bricking?
if (error) if (error)
LOG("key error [%s]", util::getErrorString(error)); LOG("key error [%s]", util::getErrorString(error));
else else
@ -356,8 +356,6 @@ bool App::_cartEraseWorker(void) {
_workerStatus.update(0, 1, WSTR("App.cartEraseWorker.erase")); _workerStatus.update(0, 1, WSTR("App.cartEraseWorker.erase"));
auto error = _driver->erase(); auto error = _driver->erase();
delayMicroseconds(1000000); // TODO: does this fix ZS01 bricking?
_cartDetectWorker(); _cartDetectWorker();
if (error) { if (error) {
@ -533,6 +531,17 @@ _writeError:
bool App::_atapiEjectWorker(void) { bool App::_atapiEjectWorker(void) {
_workerStatus.update(0, 1, WSTR("App.atapiEjectWorker.eject")); _workerStatus.update(0, 1, WSTR("App.atapiEjectWorker.eject"));
if (!(ide::devices[0].flags & ide::DEVICE_ATAPI)) {
LOG("primary drive is not ATAPI");
_messageScreen.setMessage(
MESSAGE_ERROR, _mainMenuScreen,
WSTR("App.atapiEjectWorker.atapiError")
);
_workerStatus.setNextScreen(_messageScreen);
return false;
}
ide::Packet packet; ide::Packet packet;
packet.setStartStopUnit(ide::START_STOP_MODE_OPEN_TRAY); packet.setStartStopUnit(ide::START_STOP_MODE_OPEN_TRAY);
@ -542,7 +551,8 @@ bool App::_atapiEjectWorker(void) {
LOG("eject error [%s]", util::getErrorString(error)); LOG("eject error [%s]", util::getErrorString(error));
_messageScreen.setMessage( _messageScreen.setMessage(
MESSAGE_ERROR, _mainMenuScreen, WSTR("App.atapiEjectWorker.error") MESSAGE_ERROR, _mainMenuScreen,
WSTR("App.atapiEjectWorker.ejectError")
); );
_workerStatus.setNextScreen(_messageScreen); _workerStatus.setNextScreen(_messageScreen);
return false; return false;

View File

@ -179,10 +179,12 @@ void CartActionsScreen::update(ui::Context &ctx) {
ListScreen::update(ctx); ListScreen::update(ctx);
if (ctx.buttons.pressed(ui::BTN_START)) if (ctx.buttons.pressed(ui::BTN_START)) {
(this->*action.target)(ctx); if (ctx.buttons.held(ui::BTN_LEFT) || ctx.buttons.held(ui::BTN_RIGHT))
if (ctx.buttons.bothPressed(ui::BTN_LEFT, ui::BTN_RIGHT))
ctx.show(APP->_cartInfoScreen, true, true); ctx.show(APP->_cartInfoScreen, true, true);
else
(this->*action.target)(ctx);
}
} }
static constexpr int _QR_CODE_SCALE = 2; static constexpr int _QR_CODE_SCALE = 2;
@ -200,10 +202,7 @@ void QRCodeScreen::show(ui::Context &ctx, bool goBack) {
} }
void QRCodeScreen::update(ui::Context &ctx) { void QRCodeScreen::update(ui::Context &ctx) {
if ( if (ctx.buttons.pressed(ui::BTN_START))
ctx.buttons.pressed(ui::BTN_START) ||
ctx.buttons.bothPressed(ui::BTN_LEFT, ui::BTN_RIGHT)
)
ctx.show(APP->_cartActionsScreen, true, true); ctx.show(APP->_cartActionsScreen, true, true);
} }
@ -230,10 +229,7 @@ void HexdumpScreen::show(ui::Context &ctx, bool goBack) {
void HexdumpScreen::update(ui::Context &ctx) { void HexdumpScreen::update(ui::Context &ctx) {
TextScreen::update(ctx); TextScreen::update(ctx);
if ( if (ctx.buttons.pressed(ui::BTN_START))
ctx.buttons.pressed(ui::BTN_START) ||
ctx.buttons.bothPressed(ui::BTN_LEFT, ui::BTN_RIGHT)
)
ctx.show(APP->_cartActionsScreen, true, true); ctx.show(APP->_cartActionsScreen, true, true);
} }
@ -258,6 +254,9 @@ void ReflashGameScreen::update(ui::Context &ctx) {
ListScreen::update(ctx); ListScreen::update(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)) {
ctx.show(APP->_cartActionsScreen, true, true);
} else {
APP->_confirmScreen.setMessage( APP->_confirmScreen.setMessage(
*this, *this,
[](ui::Context &ctx) { [](ui::Context &ctx) {
@ -269,8 +268,7 @@ void ReflashGameScreen::update(ui::Context &ctx) {
APP->_selectedEntry = APP->_db.get(_activeItem); APP->_selectedEntry = APP->_db.get(_activeItem);
ctx.show(APP->_confirmScreen, false, true); ctx.show(APP->_confirmScreen, false, true);
} else if (ctx.buttons.bothPressed(ui::BTN_LEFT, ui::BTN_RIGHT)) { }
ctx.show(APP->_cartActionsScreen, true, true);
} }
} }

View File

@ -207,14 +207,16 @@ void CartInfoScreen::show(ui::Context &ctx, bool goBack) {
void CartInfoScreen::update(ui::Context &ctx) { void CartInfoScreen::update(ui::Context &ctx) {
TextScreen::update(ctx); TextScreen::update(ctx);
if (APP->_dump.chipType && 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)) {
ctx.show(APP->_mainMenuScreen, true, true);
} else if (APP->_dump.chipType) {
if (APP->_dump.flags & cart::DUMP_PRIVATE_DATA_OK) if (APP->_dump.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);
} }
if (ctx.buttons.bothPressed(ui::BTN_LEFT, ui::BTN_RIGHT)) }
ctx.show(APP->_mainMenuScreen, true, true);
} }
enum SpecialEntryIndex { enum SpecialEntryIndex {
@ -313,6 +315,9 @@ void UnlockKeyScreen::update(ui::Context &ctx) {
ListScreen::update(ctx); ListScreen::update(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)) {
ctx.show(APP->_cartInfoScreen, true, true);
} else {
int index = _activeItem + _getSpecialEntryOffset(ctx); int index = _activeItem + _getSpecialEntryOffset(ctx);
APP->_confirmScreen.setMessage( APP->_confirmScreen.setMessage(
@ -341,8 +346,6 @@ void UnlockKeyScreen::update(ui::Context &ctx) {
ctx.show(APP->_confirmScreen, false, true); ctx.show(APP->_confirmScreen, false, true);
} }
} }
if (ctx.buttons.bothPressed(ui::BTN_LEFT, ui::BTN_RIGHT)) {
ctx.show(APP->_cartInfoScreen, true, true);
} }
} }

View File

@ -81,14 +81,20 @@ public:
void (MainMenuScreen::*target)(ui::Context &ctx); void (MainMenuScreen::*target)(ui::Context &ctx);
}; };
#ifdef ENABLE_CART_MENU
static constexpr int _NUM_MENU_ENTRIES = 5; static constexpr int _NUM_MENU_ENTRIES = 5;
#else
static constexpr int _NUM_MENU_ENTRIES = 4;
#endif
static const MenuEntry _MENU_ENTRIES[_NUM_MENU_ENTRIES]{ static const MenuEntry _MENU_ENTRIES[_NUM_MENU_ENTRIES]{
{ {
#ifdef ENABLE_CART_MENU
.name = "MainMenuScreen.cartInfo.name"_h, .name = "MainMenuScreen.cartInfo.name"_h,
.prompt = "MainMenuScreen.cartInfo.prompt"_h, .prompt = "MainMenuScreen.cartInfo.prompt"_h,
.target = &MainMenuScreen::cartInfo .target = &MainMenuScreen::cartInfo
}, { }, {
#endif
.name = "MainMenuScreen.dump.name"_h, .name = "MainMenuScreen.dump.name"_h,
.prompt = "MainMenuScreen.dump.prompt"_h, .prompt = "MainMenuScreen.dump.prompt"_h,
.target = &MainMenuScreen::dump .target = &MainMenuScreen::dump
@ -194,11 +200,14 @@ void AboutScreen::show(ui::Context &ctx, bool goBack) {
auto ptr = reinterpret_cast<char *>(_text.ptr); auto ptr = reinterpret_cast<char *>(_text.ptr);
_body = ptr; _body = ptr;
// Replace single newlines with spaces to reflow the text. The last // Replace single newlines with spaces to reflow the text, unless the line
// character is also cut off and replaced with a null terminator. // preceding the newline ends with a space. The last character is also cut
// off and replaced with a null terminator.
for (size_t i = _text.length - 1; i; i--, ptr++) { for (size_t i = _text.length - 1; i; i--, ptr++) {
if (*ptr != '\n') if (*ptr != '\n')
continue; continue;
if (__builtin_isspace(ptr[-1]))
continue;
if (ptr[1] == '\n') if (ptr[1] == '\n')
i--, ptr++; i--, ptr++;
@ -221,9 +230,6 @@ void AboutScreen::hide(ui::Context &ctx, bool goBack) {
void AboutScreen::update(ui::Context &ctx) { void AboutScreen::update(ui::Context &ctx) {
TextScreen::update(ctx); TextScreen::update(ctx);
if ( if (ctx.buttons.pressed(ui::BTN_START))
ctx.buttons.pressed(ui::BTN_START) ||
ctx.buttons.bothPressed(ui::BTN_LEFT, ui::BTN_RIGHT)
)
ctx.show(APP->_mainMenuScreen, true, true); ctx.show(APP->_mainMenuScreen, true, true);
} }

View File

@ -29,6 +29,11 @@ void Identifier::updateDSCRC(void) {
} }
bool Identifier::validateDSCRC(void) const { bool Identifier::validateDSCRC(void) const {
if (!data[0] || (data[0] == 0xff)) {
LOG("invalid 1-wire prefix 0x%02x", data[0]);
return false;
}
uint8_t value = util::dsCRC8(data, 7); uint8_t value = util::dsCRC8(data, 7);
if (value != data[7]) { if (value != data[7]) {

View File

@ -28,7 +28,7 @@ void Font::draw(
switch (ch) { switch (ch) {
case '\t': case '\t':
x += metrics.tabWidth - 1; x += metrics.tabWidth;
x -= x % metrics.tabWidth; x -= x % metrics.tabWidth;
break; break;
@ -144,7 +144,7 @@ void Font::getStringBounds(
if (breakOnSpace) if (breakOnSpace)
goto _break; goto _break;
x += metrics.tabWidth - 1; x += metrics.tabWidth;
x -= x % metrics.tabWidth; x -= x % metrics.tabWidth;
break; break;
@ -214,7 +214,7 @@ int Font::getStringWidth(const char *str, bool breakOnSpace) const {
if (breakOnSpace) if (breakOnSpace)
goto _break; goto _break;
width += metrics.tabWidth - 1; width += metrics.tabWidth;
width -= width % metrics.tabWidth; width -= width % metrics.tabWidth;
break; break;

View File

@ -18,7 +18,7 @@ public:
inline uint32_t getCharacterSize(uint8_t ch) const { inline uint32_t getCharacterSize(uint8_t ch) const {
uint32_t sizes = characterSizes[ch]; uint32_t sizes = characterSizes[ch];
if (!sizes) if (!sizes)
return characterSizes[FONT_INVALID_CHAR]; return characterSizes[int(FONT_INVALID_CHAR)];
return sizes; return sizes;
} }

View File

@ -125,15 +125,6 @@ void ButtonState::update(void) {
} }
} }
bool ButtonState::bothPressed(Button buttonA, Button buttonB) {
if (pressed(buttonA) && held(buttonB))
return true;
if (held(buttonA) && pressed(buttonB))
return true;
return false;
}
/* UI context */ /* UI context */
Context::Context(gpu::Context &gpuCtx, void *screenData) Context::Context(gpu::Context &gpuCtx, void *screenData)

View File

@ -128,7 +128,6 @@ public:
ButtonState(void); ButtonState(void);
void update(void); void update(void);
bool bothPressed(Button buttonA, Button buttonB);
}; };
/* UI context */ /* UI context */