Display an error screen with print-console instead of using fatalSimple. Display a msgbox in launchFile() when an error occurs instead of using fatalSimple. Better error handling etc in worker/launch.

This commit is contained in:
yellows8 2018-10-18 19:05:53 -04:00
parent 11dccb4fd0
commit 59e2d7a306
11 changed files with 163 additions and 52 deletions

View File

@ -221,6 +221,11 @@ const char* const g_strings[StrId_Max][16] =
STR_TW("程式執行時發生錯誤:"), STR_TW("程式執行時發生錯誤:"),
}, },
[StrId_AppLaunchError] =
{
STR_EN("Failed to launch the application:"),
},
[StrId_AppInfo_Author] = [StrId_AppInfo_Author] =
{ {
STR_EN("Author"), STR_EN("Author"),

View File

@ -15,6 +15,7 @@ typedef enum
StrId_NoAppsFound_Msg, StrId_NoAppsFound_Msg,
StrId_LastLoadResult, StrId_LastLoadResult,
StrId_AppLaunchError,
StrId_AppInfo_Author, StrId_AppInfo_Author,
StrId_AppInfo_Version, StrId_AppInfo_Version,

View File

@ -16,7 +16,7 @@ typedef struct
//void (* useTitle)(u64 tid, u8 mediatype); //void (* useTitle)(u64 tid, u8 mediatype);
} loaderFuncs_s; } loaderFuncs_s;
void launchInit(void); bool launchInit(void);
void launchExit(void); void launchExit(void);
const loaderFuncs_s* launchGetLoader(void); const loaderFuncs_s* launchGetLoader(void);
size_t launchAddArg(argData_s* ad, const char* arg); size_t launchAddArg(argData_s* ad, const char* arg);

View File

@ -8,7 +8,7 @@ static int s_textLang = SetLanguage_ENUS;
static int s_textLang = 1; static int s_textLang = 1;
#endif #endif
void textInit(void) { Result textInit(void) {
#ifdef __SWITCH__ #ifdef __SWITCH__
s32 Language=0; s32 Language=0;
@ -19,11 +19,13 @@ void textInit(void) {
if (R_SUCCEEDED(rc)) rc = setMakeLanguage(s_textLanguageCode, &Language); if (R_SUCCEEDED(rc)) rc = setMakeLanguage(s_textLanguageCode, &Language);
//if (R_SUCCEEDED(rc) && Language < 16) s_textLang = Language;//TODO: Re-enable this once language.c supports all used languages. //if (R_SUCCEEDED(rc) && Language < 16) s_textLang = Language;//TODO: Re-enable this once language.c supports all used languages.
setExit(); setExit();
if (R_FAILED(rc)) fatalSimple(-8); if (R_FAILED(rc)) return rc;
#else #else
s_textLang = 1; s_textLang = 1;
#endif #endif
}
return 0;
}
int textGetLang(void) { int textGetLang(void) {
return s_textLang; return s_textLang;

View File

@ -2,7 +2,7 @@
#include "common.h" #include "common.h"
#include "language.h" #include "language.h"
void textInit(void); Result textInit(void);
int textGetLang(void); int textGetLang(void);
const char* textGetString(StrId id); const char* textGetString(StrId id);
u64 textGetLanguageCode(void); u64 textGetLanguageCode(void);

View File

@ -1,5 +1,6 @@
#include "worker.h" #include "worker.h"
static bool s_workerInitialized = 0;
static thrd_t s_workerThread; static thrd_t s_workerThread;
static cnd_t s_workerCdn; static cnd_t s_workerCdn;
static mtx_t s_workerMtx; static mtx_t s_workerMtx;
@ -31,18 +32,33 @@ static int workerThreadProc(void* unused)
return 0; return 0;
} }
void workerInit(void) bool workerInit(void)
{ {
cnd_init(&s_workerCdn); if (s_workerInitialized) return 1;
mtx_init(&s_workerMtx, mtx_plain);
thrd_create(&s_workerThread, workerThreadProc, 0); if (cnd_init(&s_workerCdn) != thrd_success) return 0;
if (mtx_init(&s_workerMtx, mtx_plain) != thrd_success) {
cnd_destroy(&s_workerCdn);
return 0;
}
if (thrd_create(&s_workerThread, workerThreadProc, 0) != thrd_success) {
mtx_destroy(&s_workerMtx);
cnd_destroy(&s_workerCdn);
return 0;
}
s_workerInitialized = 1;
return 1;
} }
void workerExit(void) void workerExit(void)
{ {
int res=0; int res=0;
if (!s_workerInitialized) return;
s_workerInitialized = 0;
mtx_lock(&s_workerMtx); mtx_lock(&s_workerMtx);
s_workerParam.exit = true; s_workerParam.exit = true;
cnd_signal(&s_workerCdn); cnd_signal(&s_workerCdn);
@ -55,6 +71,8 @@ void workerExit(void)
void workerSchedule(workerThreadFunc func, void* data) void workerSchedule(workerThreadFunc func, void* data)
{ {
if (!s_workerInitialized) return;
mtx_lock(&s_workerMtx); mtx_lock(&s_workerMtx);
s_workerParam.func = func; s_workerParam.func = func;
s_workerParam.data = data; s_workerParam.data = data;

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "common.h" #include "common.h"
void workerInit(void); bool workerInit(void);
void workerExit(void); void workerExit(void);
void workerSchedule(workerThreadFunc func, void* data); void workerSchedule(workerThreadFunc func, void* data);

View File

@ -53,6 +53,7 @@ static void deinit(void)
static void launchFile(const char* path, argData_s* args) static void launchFile(const char* path, argData_s* args)
{ {
char msg[256];
/*if (strncmp(path, "sdmc:/",6) == 0) /*if (strncmp(path, "sdmc:/",6) == 0)
path += 5;*/ path += 5;*/
memset(argBuf, 0, sizeof(argBuf)); memset(argBuf, 0, sizeof(argBuf));
@ -68,9 +69,15 @@ static void launchFile(const char* path, argData_s* args)
init_args(argBuf, sizeof(argBuf)-1, args->buf, sizeof(args->buf)); init_args(argBuf, sizeof(argBuf)-1, args->buf, sizeof(args->buf));
Result rc = envSetNextLoad(path, argBuf); Result rc = envSetNextLoad(path, argBuf);
if(R_FAILED(rc)) {
memset(msg, 0, sizeof(msg));
snprintf(msg, sizeof(msg)-1, "%s\n0x%x", textGetString(StrId_AppLaunchError), rc);
if(R_FAILED(rc)) fatalSimple(rc);//TODO: How should failing be handled? menuCreateMsgBox(780, 300, msg);
uiExitLoop(); }
else {
uiExitLoop();
}
} }
const loaderFuncs_s loader_builtin = const loaderFuncs_s loader_builtin =

View File

@ -8,6 +8,8 @@
uint8_t* g_framebuf; uint8_t* g_framebuf;
u32 g_framebuf_width; u32 g_framebuf_width;
bool menuUpdateErrorScreen(void);
#ifdef PERF_LOG #ifdef PERF_LOG
u64 g_tickdiff_vsync=0; u64 g_tickdiff_vsync=0;
u64 g_tickdiff_frame=0; u64 g_tickdiff_frame=0;
@ -18,82 +20,144 @@ void audio_initialize(void);
void audio_exit(void); void audio_exit(void);
#endif #endif
extern u32 __nx_applet_exit_mode;
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
bool error_screen=0;
Result lastret=0; Result lastret=0;
Result rc=0; Result rc=0;
char msg[256]; char msg[256];
char errormsg[256];//Can't use StrId for these error messages since it would be unavailable if textInit fails.
#ifdef PERF_LOG #ifdef PERF_LOG
u64 start_tick=0; u64 start_tick=0;
#endif #endif
gfxInitDefault(); memset(errormsg, 0, sizeof(errormsg));
appletSetScreenShotPermission(1); appletSetScreenShotPermission(1);
ColorSetId theme; ColorSetId theme;
rc = setsysInitialize(); rc = setsysInitialize();
if (R_FAILED(rc)) fatalSimple(-5); if (R_FAILED(rc)) snprintf(errormsg, sizeof(errormsg)-1, "Error: setsysInitialize() failed: 0x%x.", rc);
setsysGetColorSetId(&theme); if (R_SUCCEEDED(rc)) setsysGetColorSetId(&theme);
rc = plInitialize(); if (R_SUCCEEDED(rc)) {
if (R_FAILED(rc)) fatalSimple(-6); rc = plInitialize();
if (R_FAILED(rc)) snprintf(errormsg, sizeof(errormsg)-1, "Error: plInitialize() failed: 0x%x.", rc);
}
menuStartupPath(); if (R_SUCCEEDED(rc)) {
rc = textInit();
if (R_FAILED(rc)) {
snprintf(errormsg, sizeof(errormsg)-1, "Error: textInit() failed: 0x%x.", rc);
}
}
themeStartup((ThemePreset)theme); if (R_SUCCEEDED(rc)) {
textInit(); menuStartupPath();
powerInit();
workerInit();
menuStartup();
launchInit(); themeStartup((ThemePreset)theme);
if (!fontInitialize()) fatalSimple(-7); }
if (R_SUCCEEDED(rc)) powerInit();
if (R_SUCCEEDED(rc) && !workerInit()) {
rc = 1;
snprintf(errormsg, sizeof(errormsg)-1, "Error: workerInit() failed.");
}
if (R_SUCCEEDED(rc)) menuStartup();
if (R_SUCCEEDED(rc)) {
if (!launchInit()) {
rc = 2;
snprintf(errormsg, sizeof(errormsg)-1, "Error: launchInit() failed.");
}
}
if (R_SUCCEEDED(rc) && !fontInitialize()) {
rc = 3;
snprintf(errormsg, sizeof(errormsg)-1, "Error: fontInitialize() failed.");
}
#ifdef ENABLE_AUDIO #ifdef ENABLE_AUDIO
audio_initialize(); if (R_SUCCEEDED(rc)) audio_initialize();
#endif #endif
lastret = envGetLastLoadResult(); if (R_SUCCEEDED(rc)) {
lastret = envGetLastLoadResult();
if (R_FAILED(lastret)) { if (R_FAILED(lastret)) {
memset(msg, 0, sizeof(msg)); memset(msg, 0, sizeof(msg));
snprintf(msg, sizeof(msg)-1, "%s\n0x%x", textGetString(StrId_LastLoadResult), lastret); snprintf(msg, sizeof(msg)-1, "%s\n0x%x", textGetString(StrId_LastLoadResult), lastret);
menuCreateMsgBox(780, 300, msg); menuCreateMsgBox(780, 300, msg);
}
}
if (errormsg[0]) error_screen = 1;
if (!error_screen) {
gfxInitDefault();
}
else {
consoleInit(NULL);
printf("%s\n", errormsg);
printf("Press the + button to exit.\n");
} }
#ifdef PERF_LOG #ifdef PERF_LOG
gfxWaitForVsync(); if (!error_screen) {
gfxWaitForVsync();
start_tick = svcGetSystemTick(); start_tick = svcGetSystemTick();
gfxWaitForVsync(); gfxWaitForVsync();
g_tickdiff_vsync = svcGetSystemTick() - start_tick; g_tickdiff_vsync = svcGetSystemTick() - start_tick;
}
#endif #endif
while (appletMainLoop()) while (appletMainLoop())
{ {
#ifdef PERF_LOG #ifdef PERF_LOG
start_tick = svcGetSystemTick(); if (!error_screen) start_tick = svcGetSystemTick();
#endif #endif
//Scan all the inputs. This should be done once for each frame //Scan all the inputs. This should be done once for each frame
hidScanInput(); hidScanInput();
g_framebuf = gfxGetFramebuffer(&g_framebuf_width, NULL); if (!error_screen) {
memset(g_framebuf, 237, gfxGetFramebufferSize()); g_framebuf = gfxGetFramebuffer(&g_framebuf_width, NULL);
if (!uiUpdate()) break; memset(g_framebuf, 237, gfxGetFramebufferSize());
menuLoop(); if (!uiUpdate()) break;
menuLoop();
}
else {
if (menuUpdateErrorScreen()) break;
}
gfxFlushBuffers(); if (!error_screen) {
gfxFlushBuffers();
#ifdef PERF_LOG #ifdef PERF_LOG
g_tickdiff_frame = svcGetSystemTick() - start_tick; g_tickdiff_frame = svcGetSystemTick() - start_tick;
#endif #endif
gfxSwapBuffers(); gfxSwapBuffers();
}
else {
consoleUpdate(NULL);
}
}
if (!error_screen) {
gfxExit();
}
else {
consoleExit(NULL);
__nx_applet_exit_mode = 1;
} }
#ifdef ENABLE_AUDIO #ifdef ENABLE_AUDIO
@ -107,7 +171,6 @@ int main(int argc, char **argv)
plExit(); plExit();
setsysExit(); setsysExit();
gfxExit();
return 0; return 0;
} }
@ -154,3 +217,15 @@ bool menuUpdate(void) {
return exitflag; return exitflag;
} }
bool menuUpdateErrorScreen(void) {
bool exitflag = 0;
u32 down = hidKeysDown(CONTROLLER_P1_AUTO);
if (down & KEY_PLUS)
{
exitflag = 1;
}
return exitflag;
}

View File

@ -2,25 +2,27 @@
static const loaderFuncs_s* s_loader; static const loaderFuncs_s* s_loader;
void launchInit(void) { bool launchInit(void) {
#define ADD_LOADER(_name) do \ #define ADD_LOADER(_name) do \
{ \ { \
extern const loaderFuncs_s _name; \ extern const loaderFuncs_s _name; \
if (_name.init()) \ if (_name.init()) \
{ \ { \
s_loader = &_name; \ s_loader = &_name; \
return; \ return 1; \
} \ } \
} while(0) } while(0)
ADD_LOADER(loader_builtin); ADD_LOADER(loader_builtin);
// Shouldn't happen // Shouldn't happen
fatalSimple(-1);//TODO: What value should be used for this? s_loader = NULL;
return 0;
} }
void launchExit(void) { void launchExit(void) {
s_loader->deinit(); if (s_loader) s_loader->deinit();
s_loader = NULL;
} }
const loaderFuncs_s* launchGetLoader(void) { const loaderFuncs_s* launchGetLoader(void) {
@ -71,5 +73,6 @@ void launchMenuEntry(menuEntry_s* me) {
descriptorScanFile(&me->descriptor, me->path);*/ descriptorScanFile(&me->descriptor, me->path);*/
// Launch it // Launch it
if (s_loader == NULL) return;
s_loader->launchFile(me->path, &me->args); s_loader->launchFile(me->path, &me->args);
} }

View File

@ -2,8 +2,8 @@
static const loaderFuncs_s* s_loader; static const loaderFuncs_s* s_loader;
void launchInit(void) { bool launchInit(void) {
return 1;
} }
void launchExit(void) { void launchExit(void) {