From 79be91d47449937ea8c16abaf341d7187b7b6eb8 Mon Sep 17 00:00:00 2001 From: Sebastian Krzyszkowiak Date: Fri, 29 Jul 2022 14:22:09 +0200 Subject: [PATCH] emscripten update WIP --- cmake/libsuperderpy-gamestates.cmake | 4 +- cmake/libsuperderpy.cmake | 114 ++++++++++----------------- src/emscripten-pre-js.js | 5 -- src/internal.c | 4 +- src/internal.h | 6 -- src/libsuperderpy.c | 57 ++++++-------- src/mainloop.c | 66 +++------------- 7 files changed, 78 insertions(+), 178 deletions(-) delete mode 100644 src/emscripten-pre-js.js diff --git a/cmake/libsuperderpy-gamestates.cmake b/cmake/libsuperderpy-gamestates.cmake index 6eb9a3d..1fd1ca6 100644 --- a/cmake/libsuperderpy-gamestates.cmake +++ b/cmake/libsuperderpy-gamestates.cmake @@ -31,5 +31,7 @@ FOREACH(gamestate ${gamestates}) ENDFOREACH(gamestate) if (LIBSUPERDERPY_STATIC_GAMESTATES) - target_link_libraries("libsuperderpy-gamestates" "-Wl,--allow-multiple" libsuperderpy-gamestates-stub) + if (NOT EMSCRIPTEN) + target_link_libraries("libsuperderpy-gamestates" "-Wl,--allow-multiple" libsuperderpy-gamestates-stub) + endif (NOT EMSCRIPTEN) endif (LIBSUPERDERPY_STATIC_GAMESTATES) diff --git a/cmake/libsuperderpy.cmake b/cmake/libsuperderpy.cmake index c3afe54..5121461 100644 --- a/cmake/libsuperderpy.cmake +++ b/cmake/libsuperderpy.cmake @@ -67,11 +67,11 @@ if (NOT LIBSUPERDERPY_CONFIG_INCLUDED) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -ffast-math") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -ffast-math") - if (NOT MAEMO5 AND NOT VITA) + if (NOT MAEMO5 AND NOT VITA AND NOT EMSCRIPTEN) # stack protector causes segfaults on Maemo and hangs on Vita set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector") - endif(NOT MAEMO5 AND NOT VITA) + endif(NOT MAEMO5 AND NOT VITA AND NOT EMSCRIPTEN) if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-return-type-c-linkage") @@ -116,12 +116,8 @@ if (NOT LIBSUPERDERPY_CONFIG_INCLUDED) endif(SANITIZERS) if (EMSCRIPTEN) - if(SANITIZERS_ARGS) - message(STATUS "Sanitizers unavailable under Emscripten, disabling...") - set(SANITIZERS_ARGS "") - endif() - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g3 -s ASSERTIONS=1") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g3 -s ASSERTIONS=1") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g3 -s ASSERTIONS=1 -gsource-map") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g3 -s ASSERTIONS=1 -gsource-map") else() if(MAEMO5 AND SANITIZERS_ARGS) message(STATUS "Sanitizers unavailable on Maemo, disabling...") @@ -147,10 +143,10 @@ if (NOT LIBSUPERDERPY_CONFIG_INCLUDED) if(APPLE) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-undefined,error") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-undefined,error") - else(APPLE) + elseif(NOT EMSCRIPTEN) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--no-undefined") - endif(APPLE) + endif() endif() option(USE_CLANG_TIDY "Analyze the code with clang-tidy" OFF) @@ -178,19 +174,18 @@ if (NOT LIBSUPERDERPY_CONFIG_INCLUDED) if(POLICY CMP0069 AND LIBSUPERDERPY_LTO) if(NOT USE_CLANG_TIDY AND NOT MINGW) # clang-tidy + GCC + LTO = errors; also, MinGW crashes cmake_policy(SET CMP0069 NEW) - include(CheckIPOSupported) - check_ipo_supported(RESULT IPO_SUPPORTED) + if (EMSCRIPTEN) + set(IPO_SUPPORTED ON) # checking on emscripten takes a long time; we know it's supported there + else (EMSCRIPTEN) + include(CheckIPOSupported) + check_ipo_supported(RESULT IPO_SUPPORTED) + endif (EMSCRIPTEN) message(STATUS "Link time optimization: ${IPO_SUPPORTED}") if(IPO_SUPPORTED) - if(NOT EMSCRIPTEN) - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -flto") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -flto") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto") - else() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --llvm-lto 3") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --llvm-lto 3") - endif() + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -flto") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -flto") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto") endif() endif() endif() @@ -213,12 +208,13 @@ if (NOT LIBSUPERDERPY_CONFIG_INCLUDED) add_definitions("-DLIBSUPERDERPY_STATIC_GAMESTATES") endif(LIBSUPERDERPY_STATIC_GAMESTATES) - option(LIBSUPERDERPY_STATIC_DEPS "Link dependencies (e.g. Allegro) statically." OFF) + option(LIBSUPERDERPY_STATIC_DEPS "Force static linking for dependencies (e.g. Allegro)." OFF) if(LIBSUPERDERPY_STATIC_DEPS) SET(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a) endif(LIBSUPERDERPY_STATIC_DEPS) - set(LIBSUPERDERPY_EXTRA_LIBS "${LIBSUPERDERPY_EXTRA_LIBS_INIT}" CACHE STRING "Additional platform libraries to link to") + string(STRIP "${LIBSUPERDERPY_EXTRA_LIBS_INIT} $ENV{LIBSUPERDERPY_EXTRA_LIBS}" LIBSUPERDERPY_EXTRA_LIBS_DEFAULT) + set(LIBSUPERDERPY_EXTRA_LIBS "${LIBSUPERDERPY_EXTRA_LIBS_DEFAULT}" CACHE STRING "Additional platform libraries to link to") if(MAEMO5) add_definitions(-DMAEMO5=1) @@ -275,8 +271,7 @@ if (NOT LIBSUPERDERPY_CONFIG_INCLUDED) set(CMAKE_INSTALL_RPATH "\$ORIGIN/../${LIB_DIR}/${LIBSUPERDERPY_GAMENAME}:\$ORIGIN/gamestates:\$ORIGIN:\$ORIGIN/../${LIB_DIR}:\$ORIGIN/${LIB_DIR}:\$ORIGIN/${BIN_DIR}") if(EMSCRIPTEN) - set(CMAKE_EXECUTABLE_SUFFIX ".bc") - set(CMAKE_SHARED_LIBRARY_SUFFIX ".so") + set(CMAKE_EXECUTABLE_SUFFIX ".html") # GNU extensions are needed for things like EM_ASM set(CMAKE_C_EXTENSIONS ON) @@ -286,35 +281,22 @@ if (NOT LIBSUPERDERPY_CONFIG_INCLUDED) set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O3") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3") - set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -s SIDE_MODULE=2 -s EXPORTED_FUNCTIONS=[\"_Gamestate_ProgressCount\"]") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --ignore-dynamic-linking") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --ignore-dynamic-linking") - set(EMSCRIPTEN_FLAGS -s TOTAL_MEMORY=${EMSCRIPTEN_TOTAL_MEMORY}MB --emit-symbol-map --use-preload-plugins --use-preload-cache -s FULL_ES2=1 -s EMTERPRETIFY=1 -s EMTERPRETIFY_FILE=\"${LIBSUPERDERPY_GAMENAME}.emterpret.js\" -s EMTERPRETIFY_ASYNC=1 -s EMTERPRETIFY_WHITELIST=[\"_main\", \"_libsuperderpy_emscripten_mainloop\",\"_libsuperderpy_mainloop\",\"_MainloopTick\",\"_GamestateLoadingThread\"] -s INCLUDE_FULL_LIBRARY=1 -s ERROR_ON_MISSING_LIBRARIES=1) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=['$autoResumeAudioContext','$dynCall'] -s TOTAL_MEMORY=${EMSCRIPTEN_TOTAL_MEMORY}MB --emit-symbol-map -s FULL_ES2=1 -s ERROR_ON_MISSING_LIBRARIES=1 -s ASYNCIFY") + # -s FORCE_FILESYSTEM=1 --pre-js ${LIBSUPERDERPY_DIR}/src/emscripten-pre-js.js") + #set(EMSCRIPTEN_FLAGS -s TOTAL_MEMORY=${EMSCRIPTEN_TOTAL_MEMORY}MB --emit-symbol-map -s FULL_ES2=1 -s ERROR_ON_MISSING_LIBRARIES=1 -s ASYNCIFY) set(LIBSUPERDERPY_EMSCRIPTEN_MODE "wasm" CACHE STRING "Emscripten compilation mode (JavaScript or WebAssembly)") set_property(CACHE LIBSUPERDERPY_EMSCRIPTEN_MODE PROPERTY STRINGS "asm.js;wasm") if("${LIBSUPERDERPY_EMSCRIPTEN_MODE}" STREQUAL "wasm") - set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -s WASM=1") - set(EMSCRIPTEN_FLAGS ${EMSCRIPTEN_FLAGS} -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 --no-heap-copy -s BINARYEN_TRAP_MODE=\"clamp\") - - option(EMSCRIPTEN_DCE "Enable dead code elimination in WebAssembly build" ON) - if (EMSCRIPTEN_DCE) - set(EMSCRIPTEN_FLAGS ${EMSCRIPTEN_FLAGS} -s MAIN_MODULE=2 -s EXPORTED_FUNCTIONS=@${CMAKE_BINARY_DIR}/emscripten-imports.json) - else (EMSCRIPTEN_DCE) - set(EMSCRIPTEN_FLAGS ${EMSCRIPTEN_FLAGS} -s MAIN_MODULE=1 -s EXPORT_ALL=1) - endif(EMSCRIPTEN_DCE) - - set(CMAKE_SHARED_MODULE_SUFFIX ".wasm.so") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s WASM=1 -s ALLOW_MEMORY_GROWTH=1") add_definitions(-DLIBSUPERDERPY_WASM=1) else() - set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -s WASM=0") - set(EMSCRIPTEN_FLAGS ${EMSCRIPTEN_FLAGS} -s WASM=0 -s PRECISE_F32=1 -s MAIN_MODULE=1 -s EXPORT_ALL=1) - set(CMAKE_SHARED_MODULE_SUFFIX ".js") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s WASM=0 -s PRECISE_F32=1") endif() option(LIBSUPERDERPY_USE_WEBGL2 "Use WebGL 2 context" OFF) if(LIBSUPERDERPY_USE_WEBGL2) - set(EMSCRIPTEN_FLAGS ${EMSCRIPTEN_FLAGS} -s USE_WEBGL2=1) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s USE_WEBGL2=1") endif(LIBSUPERDERPY_USE_WEBGL2) if(CMAKE_INSTALL_PREFIX MATCHES "/usr/local") # HACK @@ -352,19 +334,17 @@ if (NOT LIBSUPERDERPY_CONFIG_INCLUDED) include_directories("${LIBSUPERDERPY_BINARY_DIR}/src/3rdparty/allegro5/include") else (LIBSUPERDERPY_EMBEDDED_ALLEGRO) find_package(Allegro5 REQUIRED) - if(NOT EMSCRIPTEN) - find_package(Allegro5Font REQUIRED) - find_package(Allegro5TTF REQUIRED) - find_package(Allegro5Primitives REQUIRED) - find_package(Allegro5Audio REQUIRED) - find_package(Allegro5ACodec REQUIRED) - find_package(Allegro5Image REQUIRED) - find_package(Allegro5Color REQUIRED) - find_package(Allegro5Video REQUIRED) - if(APPLE) - find_package(Allegro5Main) - endif(APPLE) - endif(NOT EMSCRIPTEN) + find_package(Allegro5Font REQUIRED) + find_package(Allegro5TTF REQUIRED) + find_package(Allegro5Primitives REQUIRED) + find_package(Allegro5Audio REQUIRED) + find_package(Allegro5ACodec REQUIRED) + find_package(Allegro5Image REQUIRED) + find_package(Allegro5Color REQUIRED) + find_package(Allegro5Video REQUIRED) + if(APPLE) + find_package(Allegro5Main) + endif(APPLE) endif() include_directories(${Allegro5_INCLUDE_DIR} ${Allegro5Font_INCLUDE_DIR} ${Allegro5TTF_INCLUDE_DIR} ${Allegro5Primitives_INCLUDE_DIR} ${Allegro5Audio_INCLUDE_DIR} ${Allegro5Acodec_INCLUDE_DIR} ${Allegro5Video_INCLUDE_DIR} ${Allegro5Image_INCLUDE_DIR} ${Allegro5Color_INCLUDE_DIR}) @@ -397,14 +377,6 @@ if (NOT LIBSUPERDERPY_CONFIG_INCLUDED) add_dependencies(${LIBSUPERDERPY_GAMENAME}_apk "lib${LIBSUPERDERPY_GAMENAME}-${name}") endif() - if (EMSCRIPTEN) - string(TOUPPER "CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE}" CFLAGS) - string(REPLACE " " ";" CFLAGS_L ${CMAKE_C_FLAGS}) - set(CFLAGS_LIST ${CFLAGS_L} ${${CFLAGS}}) - - install(FILES "${CMAKE_BINARY_DIR}/src/gamestates/lib${LIBSUPERDERPY_GAMENAME}-${name}${CMAKE_SHARED_MODULE_SUFFIX}" DESTINATION ${CMAKE_INSTALL_PREFIX}/${LIBSUPERDERPY_GAMENAME}/gamestates) - endif() - ENDMACRO() MACRO(libsuperderpy_copy EXECUTABLE) @@ -558,17 +530,13 @@ if (NOT LIBSUPERDERPY_CONFIG_INCLUDED) string(REPLACE " " ";" CFLAGS_L ${CMAKE_C_FLAGS} " " ${${CFLAGS}}) set(CFLAGS_LIST ${CFLAGS_L}) - if("${LIBSUPERDERPY_EMSCRIPTEN_MODE}" STREQUAL "wasm") - add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/emscripten-imports.json COMMAND bash -c "(for file in ${CMAKE_INSTALL_PREFIX}/*.wasm.so; do wasm-dis $file; done) | grep \"(import \\\"env\\\" \" | awk '{print $3}' | awk -F '$' '{ print $2?$2:$0}' | sort -u | awk 'BEGIN {printf \"[\\\"_main\\\"\" } END {print \"]\"} {printf \",%s\", $1}' > ${CMAKE_BINARY_DIR}/emscripten-imports.json" DEPENDS ${LIBSUPERDERPY_GAMENAME}_install WORKING_DIRECTORY ${CMAKE_BINARY_DIR} USES_TERMINAL VERBATIM) - else() - # not implemented yet for asm.js - add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/emscripten-imports.json COMMAND bash -c "echo '[\"_main\"]' > ${CMAKE_BINARY_DIR}/emscripten-imports.json" DEPENDS ${LIBSUPERDERPY_GAMENAME}_install WORKING_DIRECTORY ${CMAKE_BINARY_DIR} USES_TERMINAL VERBATIM) - endif() + file(MAKE_DIRECTORY "${CMAKE_INSTALL_PREFIX}/${LIBSUPERDERPY_GAMENAME}") add_custom_target(${LIBSUPERDERPY_GAMENAME}_js - DEPENDS ${LIBSUPERDERPY_GAMENAME}_install ${LIBSUPERDERPY_GAMENAME}_flac_to_lossy ${LIBSUPERDERPY_GAMENAME}_img_to_webp ${CMAKE_BINARY_DIR}/emscripten-imports.json + DEPENDS ${LIBSUPERDERPY_GAMENAME}_install ${LIBSUPERDERPY_GAMENAME}_flac_to_lossy ${LIBSUPERDERPY_GAMENAME}_img_to_webp WORKING_DIRECTORY "${CMAKE_INSTALL_PREFIX}/${LIBSUPERDERPY_GAMENAME}" - COMMAND "${CMAKE_C_COMPILER}" ${CFLAGS_LIST} ../${BIN_DIR}/${LIBSUPERDERPY_GAMENAME}${CMAKE_EXECUTABLE_SUFFIX} ../lib/libsuperderpy${CMAKE_SHARED_LIBRARY_SUFFIX} ../lib/lib${LIBSUPERDERPY_GAMENAME}${CMAKE_SHARED_LIBRARY_SUFFIX} ${Allegro5_LIBS} ${EMSCRIPTEN_FLAGS} -o ${LIBSUPERDERPY_GAMENAME}.html --pre-js ${LIBSUPERDERPY_DIR}/src/emscripten-pre-js.js --preload-file ../${SHARE_DIR}/${LIBSUPERDERPY_GAMENAME}/data@/data --preload-file gamestates@/ + COMMAND "${CMAKE_C_COMPILER}" ${CFLAGS_LIST} ../${BIN_DIR}/${LIBSUPERDERPY_GAMENAME}${CMAKE_EXECUTABLE_SUFFIX} ${EMSCRIPTEN_FLAGS} -o ${LIBSUPERDERPY_GAMENAME}.html --use-preload-cache --preload-file ../${SHARE_DIR}/${LIBSUPERDERPY_GAMENAME}/data@/data + #COMMAND "$ENV{EMSCRIPTEN}/tools/file_packager" ${LIBSUPERDERPY_GAMENAME}.data --preload="../${SHARE_DIR}/${LIBSUPERDERPY_GAMENAME}/data@/data" --use-preload-cache USES_TERMINAL VERBATIM ) diff --git a/src/emscripten-pre-js.js b/src/emscripten-pre-js.js deleted file mode 100644 index aa25064..0000000 --- a/src/emscripten-pre-js.js +++ /dev/null @@ -1,5 +0,0 @@ -var Module; -if (!Module) Module = (typeof Module !== 'undefined' ? Module : null) || {}; -// Disable image and audio decoding -Module.noImageDecoding = true; -Module.noAudioDecoding = true; diff --git a/src/internal.c b/src/internal.c index da042a5..a585d4b 100644 --- a/src/internal.c +++ b/src/internal.c @@ -358,9 +358,7 @@ SYMBOL_INTERNAL void GamestateProgress(struct Game* game) { if (game->loading.shown) { game->_priv.loading.gamestate->api->logic(game, game->_priv.loading.gamestate->data, delta); } - DrawGamestates(game); - DrawConsole(game); - al_flip_display(); + RedrawScreen(game); #endif } diff --git a/src/internal.h b/src/internal.h index ce163b4..f70e96c 100644 --- a/src/internal.h +++ b/src/internal.h @@ -49,12 +49,6 @@ #ifdef ALLEGRO_WINDOWS #define LIBRARY_EXTENSION ".dll" -#elif defined(__EMSCRIPTEN__) -#if defined(LIBSUPERDERPY_WASM) -#define LIBRARY_EXTENSION ".wasm.so" -#else -#define LIBRARY_EXTENSION ".js" -#endif #else #define LIBRARY_EXTENSION ".so" #endif diff --git a/src/libsuperderpy.c b/src/libsuperderpy.c index 30704cc..a213dcb 100644 --- a/src/libsuperderpy.c +++ b/src/libsuperderpy.c @@ -498,40 +498,20 @@ SYMBOL_EXPORT int libsuperderpy_start(struct Game* game) { return 0; } -#ifdef __EMSCRIPTEN__ -SYMBOL_INTERNAL void libsuperderpy_emscripten_mainloop(void* game) { - if (!libsuperderpy_mainloop(game)) { - libsuperderpy_destroy(game); - printf("Halted.\n"); - emscripten_cancel_main_loop(); - } -} - -SYMBOL_INTERNAL EM_BOOL libsuperderpy_emscripten_focus_change(int eventType, const EmscriptenFocusEvent* focusEvent, void* game) { - libsuperderpy_emscripten_mainloop(game); - return false; -} - -#endif - SYMBOL_EXPORT int libsuperderpy_run(struct Game* game) { int ret = libsuperderpy_start(game); if (ret) { return ret; } #ifdef __EMSCRIPTEN__ - emscripten_set_blur_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, game, false, libsuperderpy_emscripten_focus_change); if (game->config.autopause && !EM_ASM_INT({document.hasFocus()})) { PrintConsole(game, "Window not focused, autopausing..."); PauseExecution(game); } - emscripten_set_main_loop_arg(libsuperderpy_emscripten_mainloop, game, 0, false); - return 0; -#else +#endif while (libsuperderpy_mainloop(game)) {} libsuperderpy_destroy(game); return 0; -#endif } SYMBOL_EXPORT void libsuperderpy_destroy(struct Game* game) { @@ -583,8 +563,20 @@ SYMBOL_EXPORT void libsuperderpy_destroy(struct Game* game) { } DestroyShaders(game); + PrintConsole(game, "Shutting down..."); + SetBackgroundColor(game, al_map_rgb(0, 0, 0)); ClearScreen(game); + DrawConsole(game); + al_flip_display(); + + while (game->_priv.garbage) { + free(game->_priv.garbage->data); + game->_priv.garbage = game->_priv.garbage->next; + } + free(game->_priv.transforms); + Console_Unload(game); + #ifdef __EMSCRIPTEN__ { ALLEGRO_BITMAP* bmp = al_create_bitmap(320, 180); @@ -594,23 +586,19 @@ SYMBOL_EXPORT void libsuperderpy_destroy(struct Game* game) { al_draw_text(font, al_map_rgb(228, 127, 59), 320 / 2, 180 / 2 - 8 - 6, ALLEGRO_ALIGN_CENTER, "It's now safe to turn off"); al_draw_text(font, al_map_rgb(228, 127, 59), 320 / 2, 180 / 2 - 8 + 6, ALLEGRO_ALIGN_CENTER, "your browser."); al_set_target_backbuffer(game->display); - al_draw_scaled_bitmap(bmp, 0, 0, 320, 180, 0, -game->viewport.height * 0.2, game->viewport.width, game->viewport.height * 1.4, 0); + al_reset_clipping_rectangle(); + ALLEGRO_TRANSFORM t; + al_identity_transform(&t); + al_use_transform(&t); + al_draw_scaled_bitmap(bmp, 0, 0, 320, 180, 0, -al_get_display_height(game->display) * 0.2, al_get_display_width(game->display), al_get_display_height(game->display) * 1.4, 0); al_flip_display(); al_destroy_bitmap(bmp); al_destroy_font(font); } + printf("Halted.\n"); + return; #endif - PrintConsole(game, "Shutting down..."); - DrawConsole(game); - al_flip_display(); - while (game->_priv.garbage) { - free(game->_priv.garbage->data); - game->_priv.garbage = game->_priv.garbage->next; - } - free(game->_priv.transforms); - Console_Unload(game); - al_destroy_display(game->display); al_destroy_user_event_source(&(game->event_source)); al_destroy_event_queue(game->_priv.event_queue); al_restore_default_mixer(); @@ -624,11 +612,10 @@ SYMBOL_EXPORT void libsuperderpy_destroy(struct Game* game) { al_destroy_cond(game->_priv.bsod_cond); al_destroy_mutex(game->_priv.bsod_mutex); al_destroy_mutex(game->_priv.mutex); - al_uninstall_audio(); DeinitConfig(game); -#ifndef __EMSCRIPTEN__ // ??? + al_uninstall_audio(); + al_destroy_display(game->display); al_uninstall_system(); -#endif #ifndef LIBSUPERDERPY_NO_RESTART char** argv = game->_priv.argv; diff --git a/src/mainloop.c b/src/mainloop.c index 4fb151a..6069df8 100644 --- a/src/mainloop.c +++ b/src/mainloop.c @@ -224,7 +224,7 @@ static inline bool MainloopEvents(struct Game* game) { do { ALLEGRO_EVENT ev; - if (game->_priv.paused && !IS_EMSCRIPTEN) { + if (game->_priv.paused) { // there's no frame flipping when paused, so avoid pointless busylooping al_wait_for_event(game->_priv.event_queue, &ev); } else if (!al_get_next_event(game->_priv.event_queue, &ev)) { @@ -292,10 +292,6 @@ static inline bool MainloopTick(struct Game* game) { struct Gamestate* tmp = game->_priv.gamestates; -#ifdef __EMSCRIPTEN__ - emscripten_pause_main_loop(); -#endif - game->_priv.loading.to_load = 0; game->_priv.loading.loaded = 0; game->_priv.loading.lock = true; @@ -323,7 +319,7 @@ static inline bool MainloopTick(struct Game* game) { while (tmp) { if (tmp->pending_unload) { #ifdef __EMSCRIPTEN__ - StopAudio(game); + //StopAudio(game); #endif PrintConsole(game, "Unloading gamestate \"%s\"...", tmp->name); tmp->loaded = false; @@ -332,12 +328,12 @@ static inline bool MainloopTick(struct Game* game) { (*tmp->api->unload)(game, tmp->data); PrintConsole(game, "Gamestate \"%s\" unloaded successfully.", tmp->name); #ifdef __EMSCRIPTEN__ - SetupAudio(game); + //SetupAudio(game); #endif } if (tmp->pending_load) { #ifdef __EMSCRIPTEN__ - StopAudio(game); + //StopAudio(game); #endif #ifdef __vita__ int vita_arm_freq = scePowerGetArmClockFrequency(); @@ -372,12 +368,7 @@ static inline bool MainloopTick(struct Game* game) { CalculateProgress(game); if (tmp->show_loading) { game->loading.shown = true; - DrawGamestates(game); - DrawConsole(game); - al_flip_display(); -#ifdef __EMSCRIPTEN__ - emscripten_sleep(0); -#endif + RedrawScreen(game); } #ifndef LIBSUPERDERPY_SINGLE_THREAD al_run_detached_thread(GamestateLoadingThread, &data); @@ -388,15 +379,13 @@ static inline bool MainloopTick(struct Game* game) { if (game->loading.shown && game->_priv.loading.gamestate->open) { (*game->_priv.loading.gamestate->api->logic)(game, game->_priv.loading.gamestate->data, delta); } - DrawGamestates(game); if (game->_priv.texture_sync) { al_convert_memory_bitmaps(); game->_priv.texture_sync = false; al_signal_cond(game->_priv.texture_sync_cond); game->_priv.loading.time = al_get_time(); // TODO: rethink time management during loading } - DrawConsole(game); - al_flip_display(); + RedrawScreen(game); if (game->_priv.bsod_sync) { al_set_target_bitmap(NULL); @@ -412,12 +401,7 @@ static inline bool MainloopTick(struct Game* game) { } #else GamestateLoadingThread(&data); - DrawGamestates(game); - DrawConsole(game); - al_flip_display(); -#ifdef __EMSCRIPTEN__ - emscripten_sleep(0); -#endif + RedrawScreen(game); #endif al_convert_memory_bitmaps(); @@ -435,12 +419,7 @@ static inline bool MainloopTick(struct Game* game) { PrintConsole(game, "Gamestate \"%s\" loaded successfully in %f seconds.", tmp->name, al_get_time() - time); game->_priv.loading.loaded++; - DrawGamestates(game); - DrawConsole(game); - al_flip_display(); -#ifdef __EMSCRIPTEN__ - emscripten_sleep(0); -#endif + RedrawScreen(game); tmp->loaded = true; tmp->pending_load = false; @@ -452,7 +431,7 @@ static inline bool MainloopTick(struct Game* game) { game->loading.shown = false; game->_priv.timestamp = al_get_time(); #ifdef __EMSCRIPTEN__ - SetupAudio(game); + //SetupAudio(game); #endif #ifdef __vita__ scePowerSetArmClockFrequency(vita_arm_freq); @@ -465,12 +444,6 @@ static inline bool MainloopTick(struct Game* game) { if (game->_priv.loading.loaded) { MainloopEvents(game); // consume queued events -#ifdef __EMSCRIPTEN__ - DrawGamestates(game); - DrawConsole(game); - al_flip_display(); - emscripten_sleep(0); -#endif } bool gameActive = false; @@ -500,15 +473,11 @@ static inline bool MainloopTick(struct Game* game) { } game->_priv.loading.lock = false; -#ifdef __EMSCRIPTEN__ - emscripten_resume_main_loop(); -#endif if (!gameActive) { PrintConsole(game, "No gamestates left, exiting..."); ClearScreen(game); - DrawConsole(game); - al_flip_display(); + RedrawScreen(game); return false; } @@ -518,22 +487,9 @@ static inline bool MainloopTick(struct Game* game) { game->_priv.timestamp += delta; delta *= game->_priv.speed; -#ifdef LIBSUPERDERPY_IMGUI - ImGui_ImplAllegro5_NewFrame(); - igNewFrame(); -#endif - LogicGamestates(game, delta); - DrawGamestates(game); + RedrawScreen(game); -#ifdef LIBSUPERDERPY_IMGUI - igRender(); - ImGui_ImplAllegro5_RenderDrawData(igGetDrawData()); -#endif - - DrawConsole(game); - - al_flip_display(); return true; }