diff --git a/src/libsuperderpy.c b/src/libsuperderpy.c index 5a24cad..7c30aca 100644 --- a/src/libsuperderpy.c +++ b/src/libsuperderpy.c @@ -105,6 +105,10 @@ SYMBOL_EXPORT struct Game* libsuperderpy_init(int argc, char** argv, const char* game->_priv.texture_sync_cond = al_create_cond(); game->_priv.texture_sync_mutex = al_create_mutex(); + game->_priv.in_bsod = false; + game->_priv.bsod_cond = al_create_cond(); + game->_priv.bsod_mutex = al_create_mutex(); + game->config.fullscreen = strtol(GetConfigOptionDefault(game, "SuperDerpy", "fullscreen", "1"), NULL, 10); game->config.music = strtol(GetConfigOptionDefault(game, "SuperDerpy", "music", "10"), NULL, 10); game->config.voice = strtol(GetConfigOptionDefault(game, "SuperDerpy", "voice", "10"), NULL, 10); @@ -488,6 +492,8 @@ SYMBOL_EXPORT void libsuperderpy_destroy(struct Game* game) { al_destroy_voice(game->audio.v); // FIXME: doesn't seem to work in Chromium under Emscripten al_destroy_cond(game->_priv.texture_sync_cond); al_destroy_mutex(game->_priv.texture_sync_mutex); + al_destroy_cond(game->_priv.bsod_cond); + al_destroy_mutex(game->_priv.bsod_mutex); al_uninstall_audio(); DeinitConfig(game); #ifndef __EMSCRIPTEN__ diff --git a/src/libsuperderpy.h b/src/libsuperderpy.h index cb19fad..d30f9ab 100644 --- a/src/libsuperderpy.h +++ b/src/libsuperderpy.h @@ -164,6 +164,11 @@ struct Game { ALLEGRO_MUTEX* texture_sync_mutex; ALLEGRO_COND* texture_sync_cond; + volatile bool in_bsod; + volatile bool bsod_sync; + ALLEGRO_MUTEX* bsod_mutex; + ALLEGRO_COND* bsod_cond; + struct { bool verbose, livereload, autopause; } debug; diff --git a/src/mainloop.c b/src/mainloop.c index 1ba7516..3d5e626 100644 --- a/src/mainloop.c +++ b/src/mainloop.c @@ -269,6 +269,20 @@ static inline bool MainloopTick(struct Game* game) { } DrawConsole(game); al_flip_display(); + +#ifndef LIBSUPERDERPY_SINGLE_THREAD + if (game->_priv.bsod_sync) { + al_set_target_bitmap(NULL); + game->_priv.bsod_sync = false; + al_signal_cond(game->_priv.bsod_cond); + } + + al_lock_mutex(game->_priv.bsod_mutex); + while (game->_priv.in_bsod) { + al_wait_cond(game->_priv.bsod_cond, game->_priv.bsod_mutex); + } + al_unlock_mutex(game->_priv.bsod_mutex); +#endif } #else GamestateLoadingThread(&data); diff --git a/src/utils.c b/src/utils.c index d164766..4558ebb 100644 --- a/src/utils.c +++ b/src/utils.c @@ -217,7 +217,19 @@ SYMBOL_EXPORT void FatalErrorWithContext(struct Game* game, int line, const char va_end(vl); fprintf(stderr, "%s:%d [%s]\n%s\n", file, line, func, text); - // TODO: synchronize with loading thread +#ifndef LIBSUPERDERPY_SINGLE_THREAD + if (game->_priv.loading.inProgress) { + al_lock_mutex(game->_priv.bsod_mutex); + game->_priv.in_bsod = true; + game->_priv.bsod_sync = true; + while (game->_priv.bsod_sync) { + al_wait_cond(game->_priv.bsod_cond, game->_priv.bsod_mutex); + } + al_unlock_mutex(game->_priv.bsod_mutex); + } +#endif + + al_set_target_backbuffer(game->display); ALLEGRO_TRANSFORM trans; al_identity_transform(&trans); @@ -227,7 +239,6 @@ SYMBOL_EXPORT void FatalErrorWithContext(struct Game* game, int line, const char game->_priv.font_bsod = al_create_builtin_font(); } - al_set_target_backbuffer(game->display); al_clear_to_color(al_map_rgb(0, 0, 170)); al_flip_display(); al_rest(0.6); @@ -309,6 +320,13 @@ SYMBOL_EXPORT void FatalErrorWithContext(struct Game* game, int line, const char #endif } al_use_transform(&game->projection); +#ifndef LIBSUPERDERPY_SINGLE_THREAD + if (game->_priv.loading.inProgress) { + PrintConsole(game, "Resuming the main thread..."); + game->_priv.in_bsod = false; + al_signal_cond(game->_priv.bsod_cond); + } +#endif } static void TestPath(const char* filename, const char* subpath, char** result) {