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:
parent
11dccb4fd0
commit
59e2d7a306
@ -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"),
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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 =
|
||||||
|
143
nx_main/main.c
143
nx_main/main.c
@ -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;
|
||||||
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user