diff --git a/src/gba/io.c b/src/gba/io.c index 9956747b6..6ccb37116 100644 --- a/src/gba/io.c +++ b/src/gba/io.c @@ -973,7 +973,8 @@ void GBAIOSerialize(struct GBA* gba, struct GBASerializedState* state) { } void GBAIODeserialize(struct GBA* gba, const struct GBASerializedState* state) { - GBAAudioWriteSOUNDCNT_X(&gba->audio, state->io[REG_SOUNDCNT_X >> 1]); + LOAD_16(gba->memory.io[REG_SOUNDCNT_X >> 1], REG_SOUNDCNT_X, state->io); + GBAAudioWriteSOUNDCNT_X(&gba->audio, gba->memory.io[REG_SOUNDCNT_X >> 1]); int i; for (i = 0; i < REG_MAX; i += 2) { diff --git a/src/platform/test/cinema-main.c b/src/platform/test/cinema-main.c index 4042ae9af..25673bbd1 100644 --- a/src/platform/test/cinema-main.c +++ b/src/platform/test/cinema-main.c @@ -28,6 +28,8 @@ #include #endif +#include +#include #include #include #include @@ -79,6 +81,7 @@ struct CInemaTest { unsigned totalFrames; uint64_t totalDistance; uint64_t totalPixels; + jmp_buf errorCtx; }; struct CInemaImage { @@ -98,7 +101,6 @@ struct StringBuilder { struct StringList lines; struct StringList partial; unsigned repeat; - }; struct CInemaLogStream { @@ -1082,6 +1084,9 @@ void CInemaTestRun(struct CInemaTest* test) { bool xdiff = false; for (frame = 0; limit; ++frame, --limit) { _updateInput(core, frame, &input); + if (setjmp(test->errorCtx)) { + break; + } core->runFrame(core); ++test->totalFrames; unsigned frameCounter = core->frameCounter(core); @@ -1347,6 +1352,21 @@ void _log(struct mLogger* log, int category, enum mLogLevel level, const char* f CIerr(0, "[%s] %s\n", mLogCategoryName(category), buffer); } +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L +static void _signalHandler(int signal, siginfo_t* info, void* context) { + UNUSED(info); + UNUSED(context); + struct CInemaTest* test = ThreadLocalGetValue(currentTest); + if (test) { + test->status = CI_ERROR; + CIerr(0, "Test %s crashed with signal %i\n", test->name, signal); + } else { + CIerr(0, "Thread crashed with signal %i\n", signal); + } + longjmp(test->errorCtx, -1); +} +#endif + int main(int argc, char** argv) { ThreadLocalInitKey(&logStream); ThreadLocalSetKey(logStream, NULL); @@ -1418,7 +1438,7 @@ int main(int argc, char** argv) { } if (CInemaTestListSize(&tests) == 0) { - CIlog(1, "No tests found."); + CIlog(1, "No tests found.\n"); status = 1; } else { reduceTestList(&tests); @@ -1440,12 +1460,34 @@ int main(int argc, char** argv) { } else { MutexInit(&jobMutex); int i; + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L + struct sigaction sa = { + .sa_flags = SA_SIGINFO, + .sa_sigaction = _signalHandler, + }; + sigemptyset(&sa.sa_mask); + + sigaction(SIGSEGV, &sa, NULL); + sigaction(SIGBUS, &sa, NULL); + sigaction(SIGFPE, &sa, NULL); + sigaction(SIGILL, &sa, NULL); +#endif + for (i = 0; i < jobs; ++i) { ThreadCreate(&jobThreads[i], CInemaJob, &tests); } for (i = 0; i < jobs; ++i) { ThreadJoin(&jobThreads[i]); } + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L + signal(SIGSEGV, SIG_DFL); + signal(SIGBUS, SIG_DFL); + signal(SIGFPE, SIG_DFL); + signal(SIGILL, SIG_DFL); +#endif + MutexDeinit(&jobMutex); status = jobStatus; } diff --git a/src/util/gui/menu.c b/src/util/gui/menu.c index 0a51102d0..ae9949075 100644 --- a/src/util/gui/menu.c +++ b/src/util/gui/menu.c @@ -137,7 +137,7 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men if (reason != GUI_MENU_EXIT_BACK) { return reason; } - } else if ((*item)->validStates && !(*item)->data.v.p) { + } else if ((*item)->validStates && GUIVariantIsString((*item)->data)) { _itemNext(*item, true); } else { return GUI_MENU_EXIT_ACCEPT;