mirror of
https://github.com/spicyjpeg/573in1.git
synced 2025-03-01 07:20:42 +01:00
Clean up worker API, implement autobooting
This commit is contained in:
parent
fd7bc1fa44
commit
e75a7f2e42
@ -57,6 +57,15 @@ target_include_directories(
|
||||
src
|
||||
src/libc
|
||||
)
|
||||
target_compile_options(
|
||||
common PUBLIC
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wno-unused-parameter
|
||||
$<$<COMPILE_LANGUAGE:CXX>:
|
||||
-Wno-pmf-conversions
|
||||
>
|
||||
)
|
||||
target_compile_definitions(common PUBLIC VERSION="${PROJECT_VERSION}")
|
||||
link_libraries(common)
|
||||
|
||||
@ -127,6 +136,7 @@ addExecutable(
|
||||
target_compile_definitions(
|
||||
main PRIVATE
|
||||
$<IF:$<CONFIG:Debug>,
|
||||
ENABLE_AUTOBOOT=1
|
||||
ENABLE_DUMMY_DRIVER=1
|
||||
ENABLE_FULL_IDE_DRIVER=1
|
||||
ENABLE_I2C_LOGGING=1
|
||||
@ -135,6 +145,7 @@ target_compile_definitions(
|
||||
ENABLE_PS1_CONTROLLER=1
|
||||
#ENABLE_X76F100_DRIVER=1
|
||||
,
|
||||
ENABLE_AUTOBOOT=1
|
||||
#ENABLE_DUMMY_DRIVER=1
|
||||
ENABLE_FULL_IDE_DRIVER=1
|
||||
#ENABLE_I2C_LOGGING=1
|
||||
|
@ -8,7 +8,8 @@
|
||||
"ideInitWorker": {
|
||||
"initDrives": "Initializing IDE devices...\nDo not turn off the 573 or unplug drives.",
|
||||
"initFileIO": "Detecting and mounting filesystems...\nDo not turn off the 573 or unplug drives.",
|
||||
"loadResources": "Loading resource pack...\nDo not turn off the 573 or unplug drives."
|
||||
"loadResources": "Loading resource pack...\nDo not turn off the 573 or unplug drives.",
|
||||
"autoboot": "Searching for boot executables...\nDo not turn off the 573 or unplug drives."
|
||||
},
|
||||
"cartDetectWorker": {
|
||||
"readDigitalIO": "Retrieving digital I/O board ID...",
|
||||
@ -110,6 +111,13 @@
|
||||
}
|
||||
},
|
||||
|
||||
"AutobootScreen": {
|
||||
"title": "Note",
|
||||
"body": "A valid boot executable has been found and will be launched shortly. You may disable automatic booting by turning off DIP switch 1 or creating a file named noboot.txt in the root of the filesystem.\n\nFile: %s",
|
||||
|
||||
"cancel": "{START_BUTTON} Cancel (%ds)"
|
||||
},
|
||||
|
||||
"ButtonMappingScreen": {
|
||||
"title": "{RIGHT_ARROW} Select button mapping",
|
||||
"prompt": "Use {START_BUTTON} or the Test button to select a mapping preset suitable for your cabinet or JAMMA setup. Other buttons will be enabled once a mapping is selected.",
|
||||
|
@ -81,8 +81,8 @@ static inline void clearWatchdog(void) {
|
||||
SYS573_WATCHDOG = 0;
|
||||
}
|
||||
|
||||
static inline uint32_t getDIPSwitches(void) {
|
||||
return SYS573_DIP_CART & 0xf;
|
||||
static inline bool getDIPSwitch(int bit) {
|
||||
return !((SYS573_DIP_CART >> bit) & 1);
|
||||
}
|
||||
|
||||
static inline bool getCartInsertionStatus(void) {
|
||||
|
@ -18,12 +18,13 @@
|
||||
|
||||
/* Worker status class */
|
||||
|
||||
void WorkerStatus::reset(void) {
|
||||
void WorkerStatus::reset(ui::Screen &next, bool goBack) {
|
||||
status = WORKER_IDLE;
|
||||
progress = 0;
|
||||
progressTotal = 1;
|
||||
message = nullptr;
|
||||
nextScreen = nullptr;
|
||||
nextScreen = &next;
|
||||
nextGoBack = goBack;
|
||||
}
|
||||
|
||||
void WorkerStatus::update(int part, int total, const char *text) {
|
||||
@ -38,30 +39,27 @@ void WorkerStatus::update(int part, int total, const char *text) {
|
||||
enableInterrupts();
|
||||
}
|
||||
|
||||
void WorkerStatus::setStatus(WorkerStatusType value) {
|
||||
ui::Screen &WorkerStatus::setNextScreen(ui::Screen &next, bool goBack) {
|
||||
auto enable = disableInterrupts();
|
||||
auto oldNext = nextScreen;
|
||||
nextScreen = &next;
|
||||
nextGoBack = goBack;
|
||||
|
||||
if (enable)
|
||||
enableInterrupts();
|
||||
|
||||
return *oldNext;
|
||||
}
|
||||
|
||||
WorkerStatusType WorkerStatus::setStatus(WorkerStatusType value) {
|
||||
auto enable = disableInterrupts();
|
||||
auto oldStatus = status;
|
||||
status = value;
|
||||
|
||||
if (enable)
|
||||
enableInterrupts();
|
||||
}
|
||||
|
||||
void WorkerStatus::setNextScreen(ui::Screen &next, bool goBack) {
|
||||
auto enable = disableInterrupts();
|
||||
_nextGoBack = goBack;
|
||||
_nextScreen = &next;
|
||||
|
||||
if (enable)
|
||||
enableInterrupts();
|
||||
}
|
||||
|
||||
void WorkerStatus::finish(void) {
|
||||
auto enable = disableInterrupts();
|
||||
status = _nextGoBack ? WORKER_NEXT_BACK : WORKER_NEXT;
|
||||
nextScreen = _nextScreen;
|
||||
|
||||
if (enable)
|
||||
enableInterrupts();
|
||||
return oldStatus;
|
||||
}
|
||||
|
||||
/* Filesystem manager class */
|
||||
@ -97,10 +95,7 @@ void FileIOManager::initIDE(void) {
|
||||
}
|
||||
|
||||
ide[i] = iso;
|
||||
bool mapped = vfs.mount("cdrom:", iso, true);
|
||||
|
||||
if (mapped)
|
||||
LOG("mapped cdrom: -> %s", name);
|
||||
vfs.mount("cdrom:", iso, true);
|
||||
} else {
|
||||
auto fat = new file::FATProvider();
|
||||
|
||||
@ -110,10 +105,7 @@ void FileIOManager::initIDE(void) {
|
||||
}
|
||||
|
||||
ide[i] = fat;
|
||||
bool mapped = vfs.mount("hdd:", fat, true);
|
||||
|
||||
if (mapped)
|
||||
LOG("mapped hdd: -> %s", name);
|
||||
vfs.mount("hdd:", fat, true);
|
||||
}
|
||||
|
||||
vfs.mount(name, ide[i], true);
|
||||
@ -199,26 +191,6 @@ void App::_unloadCartData(void) {
|
||||
//_selectedEntry = nullptr;
|
||||
}
|
||||
|
||||
void App::_setupWorker(bool (App::*func)(void)) {
|
||||
LOG("restarting worker, func=0x%08x", func);
|
||||
|
||||
auto enable = disableInterrupts();
|
||||
|
||||
_workerStack.allocate(_WORKER_STACK_SIZE);
|
||||
_workerStatus.reset();
|
||||
|
||||
_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,
|
||||
&stackBottom[(_WORKER_STACK_SIZE - 1) & ~7]
|
||||
);
|
||||
if (enable)
|
||||
enableInterrupts();
|
||||
}
|
||||
|
||||
void App::_setupInterrupts(void) {
|
||||
setInterruptHandler(
|
||||
util::forcedCast<ArgFunction>(&App::_interruptHandler), this
|
||||
@ -282,7 +254,7 @@ bool App::_getNumberedPath(char *output, size_t length, const char *path) {
|
||||
}
|
||||
|
||||
bool App::_takeScreenshot(void) {
|
||||
char path[32];
|
||||
char path[file::MAX_PATH_LENGTH];
|
||||
|
||||
if (!_createDataDirectory())
|
||||
return false;
|
||||
@ -299,10 +271,31 @@ bool App::_takeScreenshot(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void App::_runWorker(
|
||||
bool (App::*func)(void), ui::Screen &next, bool goBack, bool playSound
|
||||
) {
|
||||
auto enable = disableInterrupts();
|
||||
|
||||
_workerStatus.reset(next, goBack);
|
||||
_workerStack.allocate(_WORKER_STACK_SIZE);
|
||||
|
||||
_workerFunction = func;
|
||||
auto stackBottom = _workerStack.as<uint8_t>();
|
||||
|
||||
initThread(
|
||||
&_workerThread, util::forcedCast<ArgFunction>(&App::_worker), this,
|
||||
&stackBottom[(_WORKER_STACK_SIZE - 1) & ~7]
|
||||
);
|
||||
if (enable)
|
||||
enableInterrupts();
|
||||
|
||||
_ctx.show(_workerStatusScreen, false, playSound);
|
||||
}
|
||||
|
||||
void App::_worker(void) {
|
||||
if (_workerFunction) {
|
||||
(this->*_workerFunction)();
|
||||
_workerStatus.finish();
|
||||
_workerStatus.setStatus(WORKER_DONE);
|
||||
}
|
||||
|
||||
// Do nothing while waiting for vblank once the task is done.
|
||||
@ -334,15 +327,6 @@ void App::_interruptHandler(void) {
|
||||
_fileIO.resource.init(resourcePtr, resourceLength);
|
||||
_loadResources();
|
||||
|
||||
#ifdef NDEBUG
|
||||
_workerStatus.setNextScreen(_warningScreen);
|
||||
#else
|
||||
// Skip the warning screen in debug builds.
|
||||
_workerStatus.setNextScreen(_buttonMappingScreen);
|
||||
#endif
|
||||
_setupWorker(&App::_ideInitWorker);
|
||||
_setupInterrupts();
|
||||
|
||||
char dateString[24];
|
||||
|
||||
_textOverlay.leftText = dateString;
|
||||
@ -357,7 +341,9 @@ void App::_interruptHandler(void) {
|
||||
_ctx.overlays[0] = &_logOverlay;
|
||||
#endif
|
||||
_ctx.overlays[1] = &_screenshotOverlay;
|
||||
_ctx.show(_workerStatusScreen);
|
||||
|
||||
_runWorker(&App::_ideInitWorker, _warningScreen);
|
||||
_setupInterrupts();
|
||||
|
||||
for (;;) {
|
||||
util::Date date;
|
||||
|
@ -25,17 +25,12 @@ enum WorkerStatusType {
|
||||
WORKER_REBOOT = 1,
|
||||
WORKER_BUSY = 2,
|
||||
WORKER_BUSY_SUSPEND = 3, // Prevent main thread from running
|
||||
WORKER_NEXT = 4, // Go to next screen (goBack=false)
|
||||
WORKER_NEXT_BACK = 5 // Go to next screen (goBack=true)
|
||||
WORKER_DONE = 4 // Go to next screen
|
||||
};
|
||||
|
||||
// This class is used by the worker thread to report its current status back to
|
||||
// the main thread and the WorkerStatusScreen.
|
||||
class WorkerStatus {
|
||||
private:
|
||||
volatile bool _nextGoBack;
|
||||
ui::Screen *volatile _nextScreen;
|
||||
|
||||
public:
|
||||
volatile WorkerStatusType status;
|
||||
|
||||
@ -43,12 +38,12 @@ public:
|
||||
|
||||
const char *volatile message;
|
||||
ui::Screen *volatile nextScreen;
|
||||
volatile bool nextGoBack;
|
||||
|
||||
void reset(void);
|
||||
void reset(ui::Screen &next, bool goBack = false);
|
||||
void update(int part, int total, const char *text = nullptr);
|
||||
void setStatus(WorkerStatusType value);
|
||||
void setNextScreen(ui::Screen &next, bool goBack = false);
|
||||
void finish(void);
|
||||
ui::Screen &setNextScreen(ui::Screen &next, bool goBack = false);
|
||||
WorkerStatusType setStatus(WorkerStatusType value);
|
||||
};
|
||||
|
||||
/* Filesystem manager class */
|
||||
@ -86,6 +81,7 @@ class App {
|
||||
friend class ConfirmScreen;
|
||||
friend class FilePickerScreen;
|
||||
friend class FileBrowserScreen;
|
||||
friend class AutobootScreen;
|
||||
friend class WarningScreen;
|
||||
friend class ButtonMappingScreen;
|
||||
friend class MainMenuScreen;
|
||||
@ -112,6 +108,7 @@ private:
|
||||
ConfirmScreen _confirmScreen;
|
||||
FilePickerScreen _filePickerScreen;
|
||||
FileBrowserScreen _fileBrowserScreen;
|
||||
AutobootScreen _autobootScreen;
|
||||
WarningScreen _warningScreen;
|
||||
ButtonMappingScreen _buttonMappingScreen;
|
||||
MainMenuScreen _mainMenuScreen;
|
||||
@ -159,12 +156,15 @@ private:
|
||||
const cart::CartDBEntry *_identified, *_selectedEntry;
|
||||
|
||||
void _unloadCartData(void);
|
||||
void _setupWorker(bool (App::*func)(void));
|
||||
void _setupInterrupts(void);
|
||||
void _loadResources(void);
|
||||
bool _createDataDirectory(void);
|
||||
bool _getNumberedPath(char *output, size_t length, const char *path);
|
||||
bool _takeScreenshot(void);
|
||||
void _runWorker(
|
||||
bool (App::*func)(void), ui::Screen &next, bool goBack = false,
|
||||
bool playSound = false
|
||||
);
|
||||
|
||||
// cartworkers.cpp
|
||||
bool _cartDetectWorker(void);
|
||||
|
@ -59,17 +59,18 @@ const char *CartActionsScreen::_getItemName(ui::Context &ctx, int index) const {
|
||||
}
|
||||
|
||||
void CartActionsScreen::qrDump(ui::Context &ctx) {
|
||||
if (APP->_qrCodeScreen.valid) {
|
||||
if (APP->_qrCodeScreen.valid)
|
||||
ctx.show(APP->_qrCodeScreen, false, true);
|
||||
} else {
|
||||
APP->_setupWorker(&App::_qrCodeWorker);
|
||||
ctx.show(APP->_workerStatusScreen, false, true);
|
||||
}
|
||||
else
|
||||
APP->_runWorker(&App::_qrCodeWorker, APP->_qrCodeScreen, false, true);
|
||||
}
|
||||
|
||||
void CartActionsScreen::hddDump(ui::Context &ctx) {
|
||||
APP->_setupWorker(&App::_cartDumpWorker);
|
||||
ctx.show(APP->_workerStatusScreen, false, true);
|
||||
APP->_messageScreen.previousScreens[MESSAGE_SUCCESS] =
|
||||
&(APP->_cartInfoScreen);
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] = this;
|
||||
|
||||
APP->_runWorker(&App::_cartDumpWorker, APP->_messageScreen, false, true);
|
||||
}
|
||||
|
||||
void CartActionsScreen::hexdump(ui::Context &ctx) {
|
||||
@ -77,18 +78,23 @@ void CartActionsScreen::hexdump(ui::Context &ctx) {
|
||||
}
|
||||
|
||||
void CartActionsScreen::hddRestore(ui::Context &ctx) {
|
||||
APP->_filePickerScreen.previousScreen = this;
|
||||
APP->_filePickerScreen.setMessage(
|
||||
*this,
|
||||
[](ui::Context &ctx) {
|
||||
ctx.show(APP->_confirmScreen, false, true);
|
||||
},
|
||||
STR("CartActionsScreen.hddRestore.filePrompt")
|
||||
);
|
||||
|
||||
APP->_confirmScreen.previousScreen = &(APP->_fileBrowserScreen);
|
||||
APP->_confirmScreen.setMessage(
|
||||
APP->_fileBrowserScreen,
|
||||
[](ui::Context &ctx) {
|
||||
APP->_setupWorker(&App::_cartRestoreWorker);
|
||||
ctx.show(APP->_workerStatusScreen, false, true);
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] =
|
||||
&(APP->_fileBrowserScreen);
|
||||
|
||||
APP->_runWorker(
|
||||
&App::_cartRestoreWorker, APP->_cartInfoScreen, true, true
|
||||
);
|
||||
},
|
||||
STR("CartActionsScreen.hddRestore.confirm")
|
||||
);
|
||||
@ -101,11 +107,15 @@ void CartActionsScreen::reflash(ui::Context &ctx) {
|
||||
}
|
||||
|
||||
void CartActionsScreen::erase(ui::Context &ctx) {
|
||||
APP->_confirmScreen.previousScreen = this;
|
||||
APP->_confirmScreen.setMessage(
|
||||
*this,
|
||||
[](ui::Context &ctx) {
|
||||
APP->_setupWorker(&App::_cartEraseWorker);
|
||||
ctx.show(APP->_workerStatusScreen, false, true);
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] =
|
||||
&(APP->_cartActionsScreen);
|
||||
|
||||
APP->_runWorker(
|
||||
&App::_cartEraseWorker, APP->_cartInfoScreen, true, true
|
||||
);
|
||||
},
|
||||
STR("CartActionsScreen.erase.confirm")
|
||||
);
|
||||
@ -115,22 +125,27 @@ void CartActionsScreen::erase(ui::Context &ctx) {
|
||||
|
||||
void CartActionsScreen::resetSystemID(ui::Context &ctx) {
|
||||
if (!(APP->_cartParser->getIdentifiers()->systemID.isEmpty())) {
|
||||
APP->_confirmScreen.previousScreen = this;
|
||||
APP->_confirmScreen.setMessage(
|
||||
*this,
|
||||
[](ui::Context &ctx) {
|
||||
util::clear(APP->_cartParser->getIdentifiers()->systemID);
|
||||
APP->_cartParser->flush();
|
||||
|
||||
APP->_setupWorker(&App::_cartWriteWorker);
|
||||
ctx.show(APP->_workerStatusScreen, false, true);
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] =
|
||||
&(APP->_cartActionsScreen);
|
||||
|
||||
APP->_runWorker(
|
||||
&App::_cartWriteWorker, APP->_cartInfoScreen, true, true
|
||||
);
|
||||
},
|
||||
STR("CartActionsScreen.resetSystemID.confirm")
|
||||
);
|
||||
|
||||
ctx.show(APP->_confirmScreen, false, true);
|
||||
} else {
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] = this;
|
||||
APP->_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, *this, STR("CartActionsScreen.resetSystemID.error")
|
||||
MESSAGE_ERROR, STR("CartActionsScreen.resetSystemID.error")
|
||||
);
|
||||
|
||||
ctx.show(APP->_messageScreen, false, true);
|
||||
@ -139,24 +154,29 @@ void CartActionsScreen::resetSystemID(ui::Context &ctx) {
|
||||
|
||||
void CartActionsScreen::matchSystemID(ui::Context &ctx) {
|
||||
if (APP->_cartDump.flags & cart::DUMP_SYSTEM_ID_OK) {
|
||||
APP->_confirmScreen.previousScreen = this;
|
||||
APP->_confirmScreen.setMessage(
|
||||
*this,
|
||||
[](ui::Context &ctx) {
|
||||
APP->_cartParser->getIdentifiers()->systemID.copyFrom(
|
||||
APP->_cartDump.systemID.data
|
||||
);
|
||||
APP->_cartParser->flush();
|
||||
|
||||
APP->_setupWorker(&App::_cartWriteWorker);
|
||||
ctx.show(APP->_workerStatusScreen, false, true);
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] =
|
||||
&(APP->_cartActionsScreen);
|
||||
|
||||
APP->_runWorker(
|
||||
&App::_cartWriteWorker, APP->_cartInfoScreen, true, true
|
||||
);
|
||||
},
|
||||
STR("CartActionsScreen.matchSystemID.confirm")
|
||||
);
|
||||
|
||||
ctx.show(APP->_confirmScreen, false, true);
|
||||
} else {
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] = this;
|
||||
APP->_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, *this, STR("CartActionsScreen.matchSystemID.error")
|
||||
MESSAGE_ERROR, STR("CartActionsScreen.matchSystemID.error")
|
||||
);
|
||||
|
||||
ctx.show(APP->_messageScreen, false, true);
|
||||
@ -164,22 +184,6 @@ void CartActionsScreen::matchSystemID(ui::Context &ctx) {
|
||||
}
|
||||
|
||||
void CartActionsScreen::editSystemID(ui::Context &ctx) {
|
||||
APP->_confirmScreen.setMessage(
|
||||
APP->_systemIDEntryScreen,
|
||||
[](ui::Context &ctx) {
|
||||
APP->_systemIDEntryScreen.setSystemID(*(APP->_cartParser));
|
||||
|
||||
APP->_setupWorker(&App::_cartWriteWorker);
|
||||
ctx.show(APP->_workerStatusScreen, false, true);
|
||||
},
|
||||
STR("CartActionsScreen.editSystemID.confirm")
|
||||
);
|
||||
|
||||
APP->_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, APP->_systemIDEntryScreen,
|
||||
STR("CartActionsScreen.editSystemID.error")
|
||||
);
|
||||
|
||||
APP->_systemIDEntryScreen.getSystemID(*(APP->_cartParser));
|
||||
ctx.show(APP->_systemIDEntryScreen, false, true);
|
||||
}
|
||||
@ -284,11 +288,16 @@ void ReflashGameScreen::update(ui::Context &ctx) {
|
||||
if (ctx.buttons.held(ui::BTN_LEFT) || ctx.buttons.held(ui::BTN_RIGHT)) {
|
||||
ctx.show(APP->_cartActionsScreen, true, true);
|
||||
} else {
|
||||
APP->_confirmScreen.previousScreen = this;
|
||||
APP->_confirmScreen.setMessage(
|
||||
*this,
|
||||
[](ui::Context &ctx) {
|
||||
APP->_setupWorker(&App::_cartReflashWorker);
|
||||
ctx.show(APP->_workerStatusScreen, false, true);
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] =
|
||||
&(APP->_reflashGameScreen);
|
||||
|
||||
APP->_runWorker(
|
||||
&App::_cartReflashWorker, APP->_cartInfoScreen, true,
|
||||
true
|
||||
);
|
||||
},
|
||||
STR("CartActionsScreen.reflash.confirm")
|
||||
);
|
||||
@ -319,10 +328,35 @@ void SystemIDEntryScreen::update(ui::Context &ctx) {
|
||||
if (_activeButton == _buttonIndexOffset) {
|
||||
ctx.show(APP->_cartActionsScreen, true, true);
|
||||
} else if (_activeButton == (_buttonIndexOffset + 1)) {
|
||||
if (util::dsCRC8(_buffer, 7) == _buffer[7])
|
||||
if (util::dsCRC8(_buffer, 7) == _buffer[7]) {
|
||||
APP->_confirmScreen.previousScreen = this;
|
||||
APP->_confirmScreen.setMessage(
|
||||
[](ui::Context &ctx) {
|
||||
APP->_systemIDEntryScreen.setSystemID(
|
||||
*(APP->_cartParser)
|
||||
);
|
||||
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] =
|
||||
&(APP->_systemIDEntryScreen);
|
||||
|
||||
APP->_runWorker(
|
||||
&App::_cartWriteWorker, APP->_cartInfoScreen, true,
|
||||
true
|
||||
);
|
||||
},
|
||||
STR("CartActionsScreen.editSystemID.confirm")
|
||||
);
|
||||
|
||||
ctx.show(APP->_confirmScreen, false, true);
|
||||
else
|
||||
} else {
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] = this;
|
||||
APP->_messageScreen.setMessage(
|
||||
MESSAGE_ERROR,
|
||||
STR("CartActionsScreen.editSystemID.error")
|
||||
);
|
||||
|
||||
ctx.show(APP->_messageScreen, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -308,11 +308,16 @@ void UnlockKeyScreen::update(ui::Context &ctx) {
|
||||
auto &dump = APP->_cartDump;
|
||||
int offset = _getNumSpecialEntries(ctx);
|
||||
|
||||
APP->_confirmScreen.previousScreen = this;
|
||||
APP->_confirmScreen.setMessage(
|
||||
APP->_unlockKeyScreen,
|
||||
[](ui::Context &ctx) {
|
||||
APP->_setupWorker(&App::_cartUnlockWorker);
|
||||
ctx.show(APP->_workerStatusScreen, false, true);
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] =
|
||||
&(APP->_unlockKeyScreen);
|
||||
|
||||
APP->_runWorker(
|
||||
&App::_cartUnlockWorker, APP->_cartInfoScreen, false,
|
||||
true
|
||||
);
|
||||
},
|
||||
STRH(_UNLOCK_WARNINGS[dump.chipType])
|
||||
);
|
||||
@ -353,11 +358,16 @@ void KeyEntryScreen::update(ui::Context &ctx) {
|
||||
auto &dump = APP->_cartDump;
|
||||
|
||||
// TODO: deduplicate this code (it is the same as UnlockKeyScreen)
|
||||
APP->_confirmScreen.previousScreen = this;
|
||||
APP->_confirmScreen.setMessage(
|
||||
APP->_unlockKeyScreen,
|
||||
[](ui::Context &ctx) {
|
||||
APP->_setupWorker(&App::_cartUnlockWorker);
|
||||
ctx.show(APP->_workerStatusScreen, false, true);
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] =
|
||||
&(APP->_keyEntryScreen);
|
||||
|
||||
APP->_runWorker(
|
||||
&App::_cartUnlockWorker, APP->_cartInfoScreen, false,
|
||||
true
|
||||
);
|
||||
},
|
||||
STRH(_UNLOCK_WARNINGS[dump.chipType])
|
||||
);
|
||||
|
@ -141,11 +141,9 @@ bool App::_cartUnlockWorker(void) {
|
||||
|
||||
if (error) {
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, _cartInfoScreen,
|
||||
WSTRH(_UNLOCK_ERRORS[_cartDump.chipType]),
|
||||
MESSAGE_ERROR, WSTRH(_UNLOCK_ERRORS[_cartDump.chipType]),
|
||||
cart::getErrorString(error)
|
||||
);
|
||||
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
return false;
|
||||
}
|
||||
@ -189,7 +187,6 @@ bool App::_cartUnlockWorker(void) {
|
||||
bool App::_qrCodeWorker(void) {
|
||||
char qrString[cart::MAX_QR_STRING_LENGTH];
|
||||
|
||||
_workerStatus.setNextScreen(_qrCodeScreen);
|
||||
_workerStatus.update(0, 2, WSTR("App.qrCodeWorker.compress"));
|
||||
_cartDump.toQRString(qrString);
|
||||
|
||||
@ -202,7 +199,7 @@ bool App::_qrCodeWorker(void) {
|
||||
bool App::_cartDumpWorker(void) {
|
||||
_workerStatus.update(0, 1, WSTR("App.cartDumpWorker.save"));
|
||||
|
||||
char path[32], code[8], region[8];
|
||||
char path[file::MAX_PATH_LENGTH], code[8], region[8];
|
||||
size_t length = _cartDump.getDumpLength();
|
||||
|
||||
if (!_createDataDirectory())
|
||||
@ -228,17 +225,14 @@ bool App::_cartDumpWorker(void) {
|
||||
goto _error;
|
||||
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_SUCCESS, _cartInfoScreen, WSTR("App.cartDumpWorker.success"),
|
||||
path
|
||||
MESSAGE_SUCCESS, WSTR("App.cartDumpWorker.success"), path
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
return true;
|
||||
|
||||
_error:
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, _cartInfoScreen, WSTR("App.cartDumpWorker.error"), path
|
||||
MESSAGE_ERROR, WSTR("App.cartDumpWorker.error"), path
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -255,7 +249,7 @@ bool App::_cartWriteWorker(void) {
|
||||
|
||||
if (error) {
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, _cartInfoScreen, WSTR("App.cartWriteWorker.error"),
|
||||
MESSAGE_ERROR, WSTR("App.cartWriteWorker.error"),
|
||||
cart::getErrorString(error)
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
@ -292,8 +286,7 @@ bool App::_cartRestoreWorker(void) {
|
||||
|
||||
if (_cartDump.chipType != newDump.chipType) {
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, _fileBrowserScreen,
|
||||
WSTR("App.cartRestoreWorker.typeError"), path
|
||||
MESSAGE_ERROR, WSTR("App.cartRestoreWorker.typeError"), path
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
return false;
|
||||
@ -322,8 +315,7 @@ bool App::_cartRestoreWorker(void) {
|
||||
|
||||
if (error) {
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, _fileBrowserScreen,
|
||||
WSTR("App.cartRestoreWorker.writeError"),
|
||||
MESSAGE_ERROR, WSTR("App.cartRestoreWorker.writeError"),
|
||||
cart::getErrorString(error)
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
@ -338,8 +330,7 @@ _fileError:
|
||||
|
||||
_fileOpenError:
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, _fileBrowserScreen,
|
||||
WSTR("App.cartRestoreWorker.fileError"), path
|
||||
MESSAGE_ERROR, WSTR("App.cartRestoreWorker.fileError"), path
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
return false;
|
||||
@ -352,8 +343,7 @@ bool App::_cartReflashWorker(void) {
|
||||
!(_cartDump.flags & cart::DUMP_CART_ID_OK)
|
||||
) {
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, _cartInfoScreen,
|
||||
WSTR("App.cartReflashWorker.idError")
|
||||
MESSAGE_ERROR, WSTR("App.cartReflashWorker.idError")
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
return false;
|
||||
@ -418,8 +408,7 @@ bool App::_cartReflashWorker(void) {
|
||||
|
||||
if (error) {
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, _cartInfoScreen,
|
||||
WSTR("App.cartReflashWorker.writeError"),
|
||||
MESSAGE_ERROR, WSTR("App.cartReflashWorker.writeError"),
|
||||
cart::getErrorString(error)
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
@ -437,7 +426,7 @@ bool App::_cartEraseWorker(void) {
|
||||
|
||||
if (error) {
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, _cartInfoScreen, WSTR("App.cartEraseWorker.error"),
|
||||
MESSAGE_ERROR, WSTR("App.cartEraseWorker.error"),
|
||||
cart::getErrorString(error)
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
|
@ -8,6 +8,7 @@
|
||||
/* Main menu screens */
|
||||
|
||||
static constexpr int _WARNING_COOLDOWN = 10;
|
||||
static constexpr int _AUTOBOOT_DELAY = 5;
|
||||
|
||||
void WarningScreen::show(ui::Context &ctx, bool goBack) {
|
||||
_title = STR("WarningScreen.title");
|
||||
@ -17,18 +18,20 @@ void WarningScreen::show(ui::Context &ctx, bool goBack) {
|
||||
_locked = true;
|
||||
_numButtons = 1;
|
||||
|
||||
_cooldownTimer = ctx.time + ctx.gpuCtx.refreshRate * _WARNING_COOLDOWN;
|
||||
#ifdef NDEBUG
|
||||
_timer = ctx.time + ctx.gpuCtx.refreshRate * _WARNING_COOLDOWN;
|
||||
#else
|
||||
_timer = 0;
|
||||
#endif
|
||||
_buttonText[0] = 0;
|
||||
|
||||
MessageBoxScreen::show(ctx, goBack);
|
||||
|
||||
ctx.buttons.buttonMap = ui::MAP_SINGLE_BUTTON;
|
||||
ctx.buttons.reset();
|
||||
}
|
||||
|
||||
void WarningScreen::update(ui::Context &ctx) {
|
||||
MessageBoxScreen::update(ctx);
|
||||
|
||||
int time = _cooldownTimer - ctx.time;
|
||||
int time = _timer - ctx.time;
|
||||
_locked = (time > 0);
|
||||
|
||||
if (_locked) {
|
||||
@ -43,10 +46,53 @@ void WarningScreen::update(ui::Context &ctx) {
|
||||
|
||||
_buttons[0] = STR("WarningScreen.ok");
|
||||
|
||||
if (ctx.buttons.pressed(ui::BTN_RIGHT) || ctx.buttons.pressed(ui::BTN_START))
|
||||
if (ctx.buttons.pressed(ui::BTN_START))
|
||||
ctx.show(APP->_buttonMappingScreen, false, true);
|
||||
}
|
||||
|
||||
void AutobootScreen::show(ui::Context &ctx, bool goBack) {
|
||||
_title = STR("AutobootScreen.title");
|
||||
_body = _bodyText;
|
||||
_buttons[0] = _buttonText;
|
||||
|
||||
_numButtons = 1;
|
||||
|
||||
_timer = ctx.time + ctx.gpuCtx.refreshRate * _AUTOBOOT_DELAY;
|
||||
_buttonText[0] = 0;
|
||||
|
||||
snprintf(_bodyText, sizeof(_bodyText), STR("AutobootScreen.body"), path);
|
||||
|
||||
MessageBoxScreen::show(ctx, goBack);
|
||||
}
|
||||
|
||||
void AutobootScreen::update(ui::Context &ctx) {
|
||||
MessageBoxScreen::update(ctx);
|
||||
|
||||
int time = _timer - ctx.time;
|
||||
|
||||
if (time < 0) {
|
||||
__builtin_strncpy(
|
||||
APP->_fileBrowserScreen.selectedPath, path,
|
||||
sizeof(APP->_fileBrowserScreen.selectedPath)
|
||||
);
|
||||
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] =
|
||||
&(APP->_warningScreen);
|
||||
|
||||
APP->_runWorker(&App::_executableWorker, APP->_mainMenuScreen, true);
|
||||
return;
|
||||
}
|
||||
|
||||
time = (time / ctx.gpuCtx.refreshRate) + 1;
|
||||
|
||||
snprintf(
|
||||
_buttonText, sizeof(_buttonText), STR("AutobootScreen.cancel"), time
|
||||
);
|
||||
|
||||
if (ctx.buttons.pressed(ui::BTN_START))
|
||||
ctx.show(APP->_warningScreen, false, true);
|
||||
}
|
||||
|
||||
static const util::Hash _MAPPING_NAMES[]{
|
||||
"ButtonMappingScreen.joystick"_h,
|
||||
"ButtonMappingScreen.ddrCab"_h,
|
||||
@ -55,7 +101,9 @@ static const util::Hash _MAPPING_NAMES[]{
|
||||
"ButtonMappingScreen.dmxCab"_h
|
||||
};
|
||||
|
||||
const char *ButtonMappingScreen::_getItemName(ui::Context &ctx, int index) const {
|
||||
const char *ButtonMappingScreen::_getItemName(
|
||||
ui::Context &ctx, int index
|
||||
) const {
|
||||
return STRH(_MAPPING_NAMES[index]);
|
||||
}
|
||||
|
||||
@ -67,18 +115,14 @@ void ButtonMappingScreen::show(ui::Context &ctx, bool goBack) {
|
||||
_listLength = ui::NUM_BUTTON_MAPS - 1;
|
||||
|
||||
ListScreen::show(ctx, goBack);
|
||||
|
||||
ctx.buttons.buttonMap = ui::MAP_SINGLE_BUTTON;
|
||||
ctx.buttons.reset();
|
||||
ctx.buttons.setButtonMap(ui::MAP_SINGLE_BUTTON);
|
||||
}
|
||||
|
||||
void ButtonMappingScreen::update(ui::Context &ctx) {
|
||||
ListScreen::update(ctx);
|
||||
|
||||
if (ctx.buttons.pressed(ui::BTN_START)) {
|
||||
ctx.buttons.buttonMap = ui::ButtonMap(_activeItem);
|
||||
ctx.buttons.reset();
|
||||
|
||||
ctx.buttons.setButtonMap(ui::ButtonMap(_activeItem));
|
||||
ctx.show(APP->_mainMenuScreen, false, true);
|
||||
}
|
||||
}
|
||||
@ -134,12 +178,12 @@ const char *MainMenuScreen::_getItemName(ui::Context &ctx, int index) const {
|
||||
}
|
||||
|
||||
void MainMenuScreen::cartInfo(ui::Context &ctx) {
|
||||
if (APP->_cartDriver) {
|
||||
if (APP->_cartDriver)
|
||||
ctx.show(APP->_cartInfoScreen, false, true);
|
||||
} else {
|
||||
APP->_setupWorker(&App::_cartDetectWorker);
|
||||
ctx.show(APP->_workerStatusScreen, false, true);
|
||||
}
|
||||
else
|
||||
APP->_runWorker(
|
||||
&App::_cartDetectWorker, APP->_cartInfoScreen, false, true
|
||||
);
|
||||
}
|
||||
|
||||
void MainMenuScreen::storageInfo(ui::Context &ctx) {
|
||||
@ -151,11 +195,15 @@ void MainMenuScreen::ideInfo(ui::Context &ctx) {
|
||||
}
|
||||
|
||||
void MainMenuScreen::runExecutable(ui::Context &ctx) {
|
||||
APP->_filePickerScreen.previousScreen = this;
|
||||
APP->_filePickerScreen.setMessage(
|
||||
*this,
|
||||
[](ui::Context &ctx) {
|
||||
APP->_setupWorker(&App::_executableWorker);
|
||||
ctx.show(APP->_workerStatusScreen, false, true);
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] =
|
||||
&(APP->_fileBrowserScreen);
|
||||
|
||||
APP->_runWorker(
|
||||
&App::_executableWorker, APP->_mainMenuScreen, true, true
|
||||
);
|
||||
},
|
||||
STR("MainMenuScreen.runExecutable.filePrompt")
|
||||
);
|
||||
@ -176,13 +224,14 @@ void MainMenuScreen::about(ui::Context &ctx) {
|
||||
}
|
||||
|
||||
void MainMenuScreen::ejectCD(ui::Context &ctx) {
|
||||
APP->_setupWorker(&App::_atapiEjectWorker);
|
||||
ctx.show(APP->_workerStatusScreen, false, true);
|
||||
APP->_messageScreen.previousScreens[MESSAGE_SUCCESS] = this;
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] = this;
|
||||
|
||||
APP->_runWorker(&App::_atapiEjectWorker, *this, true, true);
|
||||
}
|
||||
|
||||
void MainMenuScreen::reboot(ui::Context &ctx) {
|
||||
APP->_setupWorker(&App::_rebootWorker);
|
||||
ctx.show(APP->_workerStatusScreen, false, true);
|
||||
APP->_runWorker(&App::_rebootWorker, *this, true, true);
|
||||
}
|
||||
|
||||
void MainMenuScreen::show(ui::Context &ctx, bool goBack) {
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
class WarningScreen : public ui::MessageBoxScreen {
|
||||
private:
|
||||
int _cooldownTimer;
|
||||
int _timer;
|
||||
char _buttonText[16];
|
||||
|
||||
public:
|
||||
@ -17,6 +17,18 @@ public:
|
||||
void update(ui::Context &ctx);
|
||||
};
|
||||
|
||||
class AutobootScreen : public ui::MessageBoxScreen {
|
||||
private:
|
||||
int _timer;
|
||||
char _bodyText[512], _buttonText[16];
|
||||
|
||||
public:
|
||||
const char *path;
|
||||
|
||||
void show(ui::Context &ctx, bool goBack = false);
|
||||
void update(ui::Context &ctx);
|
||||
};
|
||||
|
||||
class ButtonMappingScreen : public ui::ListScreen {
|
||||
protected:
|
||||
const char *_getItemName(ui::Context &ctx, int index) const;
|
||||
|
@ -4,12 +4,23 @@
|
||||
#include "common/defs.hpp"
|
||||
#include "common/file.hpp"
|
||||
#include "common/ide.hpp"
|
||||
#include "common/io.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "main/app/app.hpp"
|
||||
#include "ps1/system.h"
|
||||
|
||||
static const char *const _AUTOBOOT_PATHS[][2]{
|
||||
{ "hdd:/noboot.txt", "hdd:/psx.exe" },
|
||||
{ "cdrom:/noboot.txt", "cdrom:/psx.exe" },
|
||||
{ "cdrom:/noboot.txt", "cdrom:/qsy.dxd" },
|
||||
{ "cdrom:/noboot.txt", "cdrom:/ssw.bxf" },
|
||||
{ "cdrom:/noboot.txt", "cdrom:/tsv.axg" },
|
||||
{ "cdrom:/noboot.txt", "cdrom:/gse.nxx" },
|
||||
{ "cdrom:/noboot.txt", "cdrom:/nse.gxx" }
|
||||
};
|
||||
|
||||
bool App::_ideInitWorker(void) {
|
||||
_workerStatus.update(0, 3, WSTR("App.ideInitWorker.initDrives"));
|
||||
_workerStatus.update(0, 4, WSTR("App.ideInitWorker.initDrives"));
|
||||
|
||||
for (size_t i = 0; i < util::countOf(ide::devices); i++) {
|
||||
auto &dev = ide::devices[i];
|
||||
@ -21,13 +32,33 @@ bool App::_ideInitWorker(void) {
|
||||
dev.goIdle();
|
||||
}
|
||||
|
||||
_workerStatus.update(1, 3, WSTR("App.ideInitWorker.initFileIO"));
|
||||
_workerStatus.update(1, 4, WSTR("App.ideInitWorker.initFileIO"));
|
||||
_fileIO.initIDE();
|
||||
|
||||
_workerStatus.update(2, 3, WSTR("App.ideInitWorker.loadResources"));
|
||||
_workerStatus.update(2, 4, WSTR("App.ideInitWorker.loadResources"));
|
||||
if (_fileIO.loadResourceFile(EXTERNAL_DATA_DIR "/resource.zip"))
|
||||
_loadResources();
|
||||
|
||||
#ifdef ENABLE_AUTOBOOT
|
||||
// Only try to autoboot if DIP switch 1 is on.
|
||||
if (io::getDIPSwitch(0)) {
|
||||
_workerStatus.update(3, 4, WSTR("App.ideInitWorker.autoboot"));
|
||||
|
||||
for (auto path : _AUTOBOOT_PATHS) {
|
||||
file::FileInfo info;
|
||||
|
||||
if (_fileIO.vfs.getFileInfo(info, path[0]))
|
||||
continue;
|
||||
if (!_fileIO.vfs.getFileInfo(info, path[1]))
|
||||
continue;
|
||||
|
||||
_autobootScreen.path = path[1];
|
||||
_workerStatus.setNextScreen(_autobootScreen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
_ctx.sounds[ui::SOUND_STARTUP].play();
|
||||
return true;
|
||||
}
|
||||
@ -69,8 +100,7 @@ bool App::_executableWorker(void) {
|
||||
|
||||
if (!header.validateMagic()) {
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, _fileBrowserScreen,
|
||||
WSTR("App.executableWorker.fileError"), path
|
||||
MESSAGE_ERROR, WSTR("App.executableWorker.fileError"), path
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
return false;
|
||||
@ -79,7 +109,7 @@ bool App::_executableWorker(void) {
|
||||
auto executableEnd = header.textOffset + header.textLength;
|
||||
auto stackTop = uintptr_t(header.getStackPtr());
|
||||
|
||||
LOG("ptr=0x%08x, length=0x%x", header.textOffset, header.textLength);
|
||||
LOG("load=0x%08x, length=0x%x", header.textOffset, header.textLength);
|
||||
|
||||
// Find a launcher that does not overlap the new executable and can thus be
|
||||
// used to load it. Note that this implicitly assumes that none of the
|
||||
@ -150,16 +180,14 @@ bool App::_executableWorker(void) {
|
||||
}
|
||||
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, _fileBrowserScreen,
|
||||
WSTR("App.executableWorker.addressError"), path, header.textOffset,
|
||||
executableEnd - 1, stackTop
|
||||
MESSAGE_ERROR, WSTR("App.executableWorker.addressError"), path,
|
||||
header.textOffset, executableEnd - 1, stackTop
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool App::_atapiEjectWorker(void) {
|
||||
_workerStatus.setNextScreen(_mainMenuScreen, true);
|
||||
_workerStatus.update(0, 1, WSTR("App.atapiEjectWorker.eject"));
|
||||
|
||||
for (auto &dev : ide::devices) {
|
||||
@ -173,8 +201,7 @@ bool App::_atapiEjectWorker(void) {
|
||||
|
||||
if (error) {
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, _mainMenuScreen,
|
||||
WSTR("App.atapiEjectWorker.ejectError"),
|
||||
MESSAGE_ERROR, WSTR("App.atapiEjectWorker.ejectError"),
|
||||
ide::getErrorString(error)
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
@ -185,7 +212,7 @@ bool App::_atapiEjectWorker(void) {
|
||||
}
|
||||
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, _mainMenuScreen, WSTR("App.atapiEjectWorker.noDrive")
|
||||
MESSAGE_ERROR, WSTR("App.atapiEjectWorker.noDrive")
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
return false;
|
||||
|
@ -21,13 +21,10 @@ void WorkerStatusScreen::show(ui::Context &ctx, bool goBack) {
|
||||
|
||||
void WorkerStatusScreen::update(ui::Context &ctx) {
|
||||
auto &worker = APP->_workerStatus;
|
||||
auto nextScreen = worker.nextScreen;
|
||||
|
||||
if ((worker.status == WORKER_NEXT) || (worker.status == WORKER_NEXT_BACK)) {
|
||||
worker.reset();
|
||||
ctx.show(*nextScreen, worker.status == WORKER_NEXT_BACK);
|
||||
|
||||
LOG("worker finished, next=0x%08x", nextScreen);
|
||||
if (worker.status == WORKER_DONE) {
|
||||
worker.setStatus(WORKER_IDLE);
|
||||
ctx.show(*worker.nextScreen, worker.nextGoBack);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -41,11 +38,8 @@ static const util::Hash _MESSAGE_TITLES[]{
|
||||
"MessageScreen.title.error"_h
|
||||
};
|
||||
|
||||
void MessageScreen::setMessage(
|
||||
MessageType type, ui::Screen &prev, const char *format, ...
|
||||
) {
|
||||
void MessageScreen::setMessage(MessageType type, const char *format, ...) {
|
||||
_type = type;
|
||||
_prevScreen = &prev;
|
||||
|
||||
va_list ap;
|
||||
|
||||
@ -60,7 +54,7 @@ void MessageScreen::show(ui::Context &ctx, bool goBack) {
|
||||
_buttons[0] = STR("MessageScreen.ok");
|
||||
|
||||
_numButtons = 1;
|
||||
_locked = _prevScreen ? false : true;
|
||||
//_locked = !previousScreen;
|
||||
|
||||
MessageBoxScreen::show(ctx, goBack);
|
||||
ctx.sounds[ui::SOUND_ALERT].play();
|
||||
@ -70,14 +64,12 @@ void MessageScreen::update(ui::Context &ctx) {
|
||||
MessageBoxScreen::update(ctx);
|
||||
|
||||
if (ctx.buttons.pressed(ui::BTN_START))
|
||||
ctx.show(*_prevScreen, true, true);
|
||||
ctx.show(*previousScreens[_type], true, true);
|
||||
}
|
||||
|
||||
void ConfirmScreen::setMessage(
|
||||
ui::Screen &prev, void (*callback)(ui::Context &ctx), const char *format,
|
||||
...
|
||||
void (*callback)(ui::Context &ctx), const char *format, ...
|
||||
) {
|
||||
_prevScreen = &prev;
|
||||
_callback = callback;
|
||||
|
||||
va_list ap;
|
||||
@ -106,7 +98,7 @@ void ConfirmScreen::update(ui::Context &ctx) {
|
||||
if (_activeButton)
|
||||
_callback(ctx);
|
||||
else
|
||||
ctx.show(*_prevScreen, true, true);
|
||||
ctx.show(*previousScreen, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,10 +153,8 @@ const char *FilePickerScreen::_getItemName(ui::Context &ctx, int index) const {
|
||||
}
|
||||
|
||||
void FilePickerScreen::setMessage(
|
||||
ui::Screen &prev, void (*callback)(ui::Context &ctx), const char *format,
|
||||
...
|
||||
void (*callback)(ui::Context &ctx), const char *format, ...
|
||||
) {
|
||||
_prevScreen = &prev;
|
||||
_callback = callback;
|
||||
|
||||
va_list ap;
|
||||
@ -181,9 +171,9 @@ void FilePickerScreen::reloadAndShow(ui::Context &ctx) {
|
||||
if (!dev.atapiPoll())
|
||||
continue;
|
||||
|
||||
APP->_workerStatus.setNextScreen(*this);
|
||||
APP->_setupWorker(&App::_ideInitWorker);
|
||||
ctx.show(APP->_workerStatusScreen, false, true);
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] = this;
|
||||
|
||||
APP->_runWorker(&App::_ideInitWorker, *this, false, true);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -213,8 +203,9 @@ void FilePickerScreen::update(ui::Context &ctx) {
|
||||
ListScreen::update(ctx);
|
||||
|
||||
if (!_listLength) {
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] = previousScreen;
|
||||
APP->_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, *_prevScreen, STR("FilePickerScreen.noDeviceError")
|
||||
MESSAGE_ERROR, STR("FilePickerScreen.noDeviceError")
|
||||
);
|
||||
ctx.show(APP->_messageScreen, false, true);
|
||||
return;
|
||||
@ -222,7 +213,7 @@ void FilePickerScreen::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(*_prevScreen, true, true);
|
||||
ctx.show(*previousScreen, true, true);
|
||||
} else {
|
||||
int index = _activeItem;
|
||||
#ifndef NDEBUG
|
||||
@ -259,9 +250,8 @@ void FilePickerScreen::update(ui::Context &ctx) {
|
||||
else
|
||||
error = "FilePickerScreen.ideError"_h;
|
||||
|
||||
APP->_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, *this, STRH(error)
|
||||
);
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] = this;
|
||||
APP->_messageScreen.setMessage(MESSAGE_ERROR, STRH(error));
|
||||
ctx.show(APP->_messageScreen, false, true);
|
||||
}
|
||||
}
|
||||
@ -427,9 +417,10 @@ void FileBrowserScreen::update(ui::Context &ctx) {
|
||||
if (loadDirectory(ctx, selectedPath) < 0) {
|
||||
loadDirectory(ctx, _currentPath, false);
|
||||
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] = this;
|
||||
APP->_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, *this,
|
||||
STR("FileBrowserScreen.subdirError"), selectedPath
|
||||
MESSAGE_ERROR, STR("FileBrowserScreen.subdirError"),
|
||||
selectedPath
|
||||
);
|
||||
ctx.show(APP->_messageScreen, false, true);
|
||||
}
|
||||
|
@ -16,6 +16,8 @@ public:
|
||||
void update(ui::Context &ctx);
|
||||
};
|
||||
|
||||
static constexpr size_t NUM_MESSAGE_TYPES = 3;
|
||||
|
||||
enum MessageType {
|
||||
MESSAGE_SUCCESS = 0,
|
||||
MESSAGE_WARNING = 1,
|
||||
@ -26,12 +28,11 @@ class MessageScreen : public ui::MessageBoxScreen {
|
||||
private:
|
||||
MessageType _type;
|
||||
char _bodyText[512];
|
||||
ui::Screen *_prevScreen;
|
||||
|
||||
public:
|
||||
void setMessage(
|
||||
MessageType type, ui::Screen &prev, const char *format, ...
|
||||
);
|
||||
ui::Screen *previousScreens[NUM_MESSAGE_TYPES];
|
||||
|
||||
void setMessage(MessageType type, const char *format, ...);
|
||||
|
||||
void show(ui::Context &ctx, bool goBack = false);
|
||||
void update(ui::Context &ctx);
|
||||
@ -40,13 +41,13 @@ public:
|
||||
class ConfirmScreen : public ui::MessageBoxScreen {
|
||||
private:
|
||||
char _bodyText[512];
|
||||
ui::Screen *_prevScreen;
|
||||
void (*_callback)(ui::Context &ctx);
|
||||
|
||||
public:
|
||||
ui::Screen *previousScreen;
|
||||
|
||||
void setMessage(
|
||||
ui::Screen &prev, void (*callback)(ui::Context &ctx),
|
||||
const char *format, ...
|
||||
void (*callback)(ui::Context &ctx), const char *format, ...
|
||||
);
|
||||
|
||||
void show(ui::Context &ctx, bool goBack = false);
|
||||
@ -60,7 +61,6 @@ class FilePickerScreen : public ui::ListScreen {
|
||||
|
||||
private:
|
||||
char _promptText[512];
|
||||
ui::Screen *_prevScreen;
|
||||
void (*_callback)(ui::Context &ctx);
|
||||
|
||||
int _drives[util::countOf(ide::devices)];
|
||||
@ -69,9 +69,10 @@ protected:
|
||||
const char *_getItemName(ui::Context &ctx, int index) const;
|
||||
|
||||
public:
|
||||
ui::Screen *previousScreen;
|
||||
|
||||
void setMessage(
|
||||
ui::Screen &prev, void (*callback)(ui::Context &ctx),
|
||||
const char *format, ...
|
||||
void (*callback)(ui::Context &ctx), const char *format, ...
|
||||
);
|
||||
void reloadAndShow(ui::Context &ctx);
|
||||
|
||||
|
@ -205,20 +205,26 @@ const char *StorageActionsScreen::_getItemName(
|
||||
}
|
||||
|
||||
void StorageActionsScreen::checksum(ui::Context &ctx) {
|
||||
if (APP->_checksumScreen.valid) {
|
||||
if (APP->_checksumScreen.valid)
|
||||
ctx.show(APP->_checksumScreen, false, true);
|
||||
} else {
|
||||
APP->_setupWorker(&App::_romChecksumWorker);
|
||||
ctx.show(APP->_workerStatusScreen, false, true);
|
||||
}
|
||||
else
|
||||
APP->_runWorker(
|
||||
&App::_romChecksumWorker, APP->_checksumScreen, false, true
|
||||
);
|
||||
}
|
||||
|
||||
void StorageActionsScreen::dump(ui::Context &ctx) {
|
||||
APP->_confirmScreen.previousScreen = this;
|
||||
APP->_confirmScreen.setMessage(
|
||||
*this,
|
||||
[](ui::Context &ctx) {
|
||||
APP->_setupWorker(&App::_romDumpWorker);
|
||||
ctx.show(APP->_workerStatusScreen, false, true);
|
||||
APP->_messageScreen.previousScreens[MESSAGE_SUCCESS] =
|
||||
&(APP->_storageInfoScreen);
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] =
|
||||
&(APP->_storageActionsScreen);
|
||||
|
||||
APP->_runWorker(
|
||||
&App::_romDumpWorker, APP->_messageScreen, false, true
|
||||
);
|
||||
},
|
||||
STR("StorageActionsScreen.dump.confirm")
|
||||
);
|
||||
@ -227,18 +233,25 @@ void StorageActionsScreen::dump(ui::Context &ctx) {
|
||||
}
|
||||
|
||||
void StorageActionsScreen::restore(ui::Context &ctx) {
|
||||
APP->_filePickerScreen.previousScreen = this;
|
||||
APP->_filePickerScreen.setMessage(
|
||||
*this,
|
||||
[](ui::Context &ctx) {
|
||||
ctx.show(APP->_confirmScreen, false, true);
|
||||
},
|
||||
STR("StorageActionsScreen.restore.filePrompt")
|
||||
);
|
||||
|
||||
APP->_confirmScreen.previousScreen = &(APP->_fileBrowserScreen);
|
||||
APP->_confirmScreen.setMessage(
|
||||
APP->_fileBrowserScreen,
|
||||
[](ui::Context &ctx) {
|
||||
APP->_setupWorker(&App::_romRestoreWorker);
|
||||
ctx.show(APP->_workerStatusScreen, false, true);
|
||||
APP->_messageScreen.previousScreens[MESSAGE_SUCCESS] =
|
||||
&(APP->_storageInfoScreen);
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] =
|
||||
&(APP->_fileBrowserScreen);
|
||||
|
||||
APP->_runWorker(
|
||||
&App::_romRestoreWorker, APP->_messageScreen, false, true
|
||||
);
|
||||
},
|
||||
STR("StorageActionsScreen.restore.confirm")
|
||||
);
|
||||
@ -247,11 +260,17 @@ void StorageActionsScreen::restore(ui::Context &ctx) {
|
||||
}
|
||||
|
||||
void StorageActionsScreen::erase(ui::Context &ctx) {
|
||||
APP->_confirmScreen.previousScreen = this;
|
||||
APP->_confirmScreen.setMessage(
|
||||
*this,
|
||||
[](ui::Context &ctx) {
|
||||
APP->_setupWorker(&App::_romEraseWorker);
|
||||
ctx.show(APP->_workerStatusScreen, false, true);
|
||||
APP->_messageScreen.previousScreens[MESSAGE_SUCCESS] =
|
||||
&(APP->_storageInfoScreen);
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] =
|
||||
&(APP->_storageActionsScreen);
|
||||
|
||||
APP->_runWorker(
|
||||
&App::_romEraseWorker, APP->_messageScreen, false, true
|
||||
);
|
||||
},
|
||||
STR("StorageActionsScreen.erase.confirm")
|
||||
);
|
||||
@ -260,12 +279,18 @@ void StorageActionsScreen::erase(ui::Context &ctx) {
|
||||
}
|
||||
|
||||
void StorageActionsScreen::resetFlashHeader(ui::Context &ctx) {
|
||||
APP->_confirmScreen.previousScreen = this;
|
||||
APP->_confirmScreen.setMessage(
|
||||
*this,
|
||||
[](ui::Context &ctx) {
|
||||
util::clear(APP->_romHeaderDump.data);
|
||||
APP->_setupWorker(&App::_flashHeaderWriteWorker);
|
||||
ctx.show(APP->_workerStatusScreen, false, true);
|
||||
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] =
|
||||
&(APP->_storageActionsScreen);
|
||||
|
||||
APP->_runWorker(
|
||||
&App::_flashHeaderWriteWorker, APP->_storageInfoScreen, true,
|
||||
true
|
||||
);
|
||||
},
|
||||
STR("StorageActionsScreen.resetFlashHeader.confirm")
|
||||
);
|
||||
@ -313,8 +338,9 @@ void StorageActionsScreen::update(ui::Context &ctx) {
|
||||
(this->*action.target)(ctx);
|
||||
}
|
||||
} else {
|
||||
APP->_messageScreen.previousScreens[MESSAGE_ERROR] = this;
|
||||
APP->_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, *this, STR("StorageActionsScreen.cardError")
|
||||
MESSAGE_ERROR, STR("StorageActionsScreen.cardError")
|
||||
);
|
||||
|
||||
ctx.show(APP->_messageScreen, false, true);
|
||||
|
@ -57,7 +57,6 @@ static constexpr size_t _DUMP_CHUNKS_PER_CRC = 32; // Save CRC32 every 16 MB
|
||||
// TODO: all these *really* need a cleanup...
|
||||
|
||||
bool App::_romChecksumWorker(void) {
|
||||
_workerStatus.setNextScreen(_checksumScreen);
|
||||
_checksumScreen.valid = false;
|
||||
|
||||
for (auto &entry : _REGION_INFO) {
|
||||
@ -100,7 +99,7 @@ bool App::_romDumpWorker(void) {
|
||||
|
||||
// Store all dumps in a subdirectory named "dumpNNNN" within the main data
|
||||
// folder.
|
||||
char dirPath[32], filePath[32];
|
||||
char dirPath[file::MAX_PATH_LENGTH], filePath[file::MAX_PATH_LENGTH];
|
||||
|
||||
if (!_createDataDirectory())
|
||||
goto _initError;
|
||||
@ -158,26 +157,20 @@ bool App::_romDumpWorker(void) {
|
||||
}
|
||||
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_SUCCESS, _storageInfoScreen, WSTR("App.romDumpWorker.success"),
|
||||
dirPath
|
||||
MESSAGE_SUCCESS, WSTR("App.romDumpWorker.success"), dirPath
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
return true;
|
||||
|
||||
_initError:
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, _storageInfoScreen, WSTR("App.romDumpWorker.initError"),
|
||||
dirPath
|
||||
MESSAGE_ERROR, WSTR("App.romDumpWorker.initError"), dirPath
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
return false;
|
||||
|
||||
_fileError:
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, _storageInfoScreen, WSTR("App.romDumpWorker.fileError"),
|
||||
filePath
|
||||
MESSAGE_ERROR, WSTR("App.romDumpWorker.fileError"), filePath
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -299,18 +292,13 @@ bool App::_romRestoreWorker(void) {
|
||||
delete _file;
|
||||
delete driver;
|
||||
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_SUCCESS, _storageInfoScreen, WSTRH(message), bytesWritten
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
_messageScreen.setMessage(MESSAGE_SUCCESS, WSTRH(message), bytesWritten);
|
||||
return true;
|
||||
|
||||
_fileError:
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, _storageInfoScreen,
|
||||
WSTR("App.romRestoreWorker.fileError"), path
|
||||
MESSAGE_ERROR, WSTR("App.romRestoreWorker.fileError"), path
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
return false;
|
||||
|
||||
_flashError:
|
||||
@ -321,11 +309,9 @@ _flashError:
|
||||
delete driver;
|
||||
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, _storageInfoScreen,
|
||||
WSTR("App.romRestoreWorker.flashError"), rom::getErrorString(error),
|
||||
bytesWritten
|
||||
MESSAGE_ERROR, WSTR("App.romRestoreWorker.flashError"),
|
||||
rom::getErrorString(error), bytesWritten
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -366,31 +352,25 @@ bool App::_romEraseWorker(void) {
|
||||
delete driver;
|
||||
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_SUCCESS, _storageInfoScreen, WSTR("App.romEraseWorker.success"),
|
||||
sectorsErased
|
||||
MESSAGE_SUCCESS, WSTR("App.romEraseWorker.success"), sectorsErased
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
return true;
|
||||
|
||||
_flashError:
|
||||
delete driver;
|
||||
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, _storageInfoScreen,
|
||||
WSTR("App.romEraseWorker.flashError"), rom::getErrorString(error),
|
||||
sectorsErased
|
||||
MESSAGE_ERROR, WSTR("App.romEraseWorker.flashError"),
|
||||
rom::getErrorString(error), sectorsErased
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
return false;
|
||||
|
||||
_unsupported:
|
||||
delete driver;
|
||||
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, _storageInfoScreen,
|
||||
WSTR("App.romEraseWorker.unsupported")
|
||||
MESSAGE_ERROR, WSTR("App.romEraseWorker.unsupported")
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -460,8 +440,6 @@ bool App::_flashHeaderWriteWorker(void) {
|
||||
|
||||
buffer.destroy();
|
||||
delete driver;
|
||||
|
||||
_workerStatus.setNextScreen(_storageInfoScreen);
|
||||
return true;
|
||||
|
||||
_flashError:
|
||||
@ -469,8 +447,7 @@ _flashError:
|
||||
delete driver;
|
||||
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, _storageInfoScreen,
|
||||
WSTR("App.flashHeaderWriteWorker.flashError"),
|
||||
MESSAGE_ERROR, WSTR("App.flashHeaderWriteWorker.flashError"),
|
||||
rom::getErrorString(error)
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
@ -480,8 +457,7 @@ _unsupported:
|
||||
delete driver;
|
||||
|
||||
_messageScreen.setMessage(
|
||||
MESSAGE_ERROR, _storageInfoScreen,
|
||||
WSTR("App.flashHeaderWriteWorker.unsupported")
|
||||
MESSAGE_ERROR, WSTR("App.flashHeaderWriteWorker.unsupported")
|
||||
);
|
||||
_workerStatus.setNextScreen(_messageScreen);
|
||||
return false;
|
||||
|
@ -52,14 +52,14 @@ static const uint32_t _BUTTON_MAPPINGS[NUM_BUTTON_MAPS][NUM_BUTTONS]{
|
||||
};
|
||||
|
||||
ButtonState::ButtonState(void)
|
||||
: _held(0), _prevHeld(0), _longHeld(0), _prevLongHeld(0), _pressed(0),
|
||||
_released(0), _longPressed(0), _longReleased(0), _repeatTimer(0),
|
||||
buttonMap(MAP_JOYSTICK) {}
|
||||
: _buttonMap(MAP_JOYSTICK), _held(0), _prevHeld(0), _longHeld(0),
|
||||
_prevLongHeld(0), _pressed(0), _released(0), _longPressed(0), _longReleased(0),
|
||||
_repeatTimer(0) {}
|
||||
|
||||
uint8_t ButtonState::_getHeld(void) const {
|
||||
uint32_t inputs = io::getJAMMAInputs();
|
||||
uint8_t held = 0;
|
||||
auto map = _BUTTON_MAPPINGS[buttonMap];
|
||||
auto map = _BUTTON_MAPPINGS[_buttonMap];
|
||||
|
||||
#ifdef ENABLE_PS1_CONTROLLER
|
||||
if (pad::ports[0].pollPad() || pad::ports[1].pollPad()) {
|
||||
@ -115,30 +115,33 @@ void ButtonState::update(void) {
|
||||
|
||||
uint32_t changed = _prevHeld ^ _held;
|
||||
|
||||
if (buttonMap == MAP_SINGLE_BUTTON) {
|
||||
if (_buttonMap == MAP_SINGLE_BUTTON) {
|
||||
_pressed = 0;
|
||||
_released = 0;
|
||||
_longHeld = 0;
|
||||
|
||||
// In single-button mode, interpret a short button press as the right
|
||||
// button and a long press as start.
|
||||
if (_held) {
|
||||
// button and a long press as start. Note that the repeat timer is not
|
||||
// started if single button mode is enabled while a button is held down.
|
||||
if (changed & _held) {
|
||||
_repeatTimer = 1;
|
||||
} else if (changed & _prevHeld) {
|
||||
if (_repeatTimer && (_repeatTimer < REPEAT_DELAY))
|
||||
_pressed |= 1 << BTN_RIGHT;
|
||||
|
||||
_repeatTimer = 0;
|
||||
} else if (_held && _repeatTimer) {
|
||||
if (_repeatTimer == REPEAT_DELAY)
|
||||
_pressed |= 1 << BTN_START;
|
||||
|
||||
_repeatTimer++;
|
||||
} else if (_prevHeld) {
|
||||
if (_repeatTimer >= REPEAT_DELAY)
|
||||
_released |= 1 << BTN_START;
|
||||
else
|
||||
_pressed |= 1 << BTN_RIGHT;
|
||||
|
||||
_repeatTimer = 0;
|
||||
}
|
||||
} else {
|
||||
if (changed)
|
||||
if (changed & _held)
|
||||
_repeatTimer = 1;
|
||||
else if (changed & _prevHeld)
|
||||
_repeatTimer = 0;
|
||||
else if (_held)
|
||||
else if (_held && _repeatTimer)
|
||||
_repeatTimer++;
|
||||
|
||||
_pressed = (changed & _held) & ~_pressed;
|
||||
@ -162,7 +165,7 @@ Context::Context(gpu::Context &gpuCtx, void *screenData)
|
||||
}
|
||||
|
||||
void Context::show(Screen &screen, bool goBack, bool playSound) {
|
||||
auto oldScreen = _screens[_currentScreen];
|
||||
auto oldScreen = getCurrentScreen();
|
||||
|
||||
if (oldScreen)
|
||||
oldScreen->hide(*this, goBack);
|
||||
@ -177,8 +180,8 @@ void Context::show(Screen &screen, bool goBack, bool playSound) {
|
||||
}
|
||||
|
||||
void Context::draw(void) {
|
||||
auto oldScreen = _screens[_currentScreen ^ 1];
|
||||
auto newScreen = _screens[_currentScreen];
|
||||
auto oldScreen = getInactiveScreen();
|
||||
auto newScreen = getCurrentScreen();
|
||||
|
||||
for (auto layer : backgrounds) {
|
||||
if (layer)
|
||||
@ -204,8 +207,10 @@ void Context::update(void) {
|
||||
layer->update(*this);
|
||||
}
|
||||
|
||||
if (_screens[_currentScreen])
|
||||
_screens[_currentScreen]->update(*this);
|
||||
auto screen = getCurrentScreen();
|
||||
|
||||
if (screen)
|
||||
screen->update(*this);
|
||||
}
|
||||
|
||||
/* Layer classes */
|
||||
|
@ -105,7 +105,9 @@ enum ButtonMap {
|
||||
|
||||
class ButtonState {
|
||||
private:
|
||||
ButtonMap _buttonMap;
|
||||
uint32_t _mappings[NUM_BUTTONS];
|
||||
|
||||
uint8_t _held, _prevHeld;
|
||||
uint8_t _longHeld, _prevLongHeld;
|
||||
uint8_t _pressed, _released;
|
||||
@ -116,7 +118,10 @@ private:
|
||||
uint8_t _getHeld(void) const;
|
||||
|
||||
public:
|
||||
ButtonMap buttonMap;
|
||||
inline void setButtonMap(ButtonMap map) {
|
||||
reset();
|
||||
_buttonMap = map;
|
||||
}
|
||||
|
||||
inline bool held(Button button) const {
|
||||
return (_held >> button) & 1;
|
||||
@ -167,6 +172,12 @@ public:
|
||||
int time;
|
||||
void *screenData; // Opaque, can be accessed by screens
|
||||
|
||||
inline Screen *getCurrentScreen(void) const {
|
||||
return _screens[_currentScreen];
|
||||
}
|
||||
inline Screen *getInactiveScreen(void) const {
|
||||
return _screens[_currentScreen ^ 1];
|
||||
}
|
||||
inline void tick(void) {
|
||||
//buttons.update();
|
||||
time++;
|
||||
|
Loading…
x
Reference in New Issue
Block a user