emscripten update WIP

This commit is contained in:
Sebastian Krzyszkowiak 2022-07-29 14:22:09 +02:00
parent 70c81c77ec
commit 79be91d474
No known key found for this signature in database
GPG key ID: E8F235CF3BDBC3FF
7 changed files with 78 additions and 178 deletions

View file

@ -31,5 +31,7 @@ FOREACH(gamestate ${gamestates})
ENDFOREACH(gamestate) ENDFOREACH(gamestate)
if (LIBSUPERDERPY_STATIC_GAMESTATES) 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) endif (LIBSUPERDERPY_STATIC_GAMESTATES)

View file

@ -67,11 +67,11 @@ if (NOT LIBSUPERDERPY_CONFIG_INCLUDED)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -ffast-math") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -ffast-math")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_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 # stack protector causes segfaults on Maemo and hangs on Vita
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_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") if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-return-type-c-linkage") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-return-type-c-linkage")
@ -116,12 +116,8 @@ if (NOT LIBSUPERDERPY_CONFIG_INCLUDED)
endif(SANITIZERS) endif(SANITIZERS)
if (EMSCRIPTEN) if (EMSCRIPTEN)
if(SANITIZERS_ARGS) set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g3 -s ASSERTIONS=1 -gsource-map")
message(STATUS "Sanitizers unavailable under Emscripten, disabling...") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g3 -s ASSERTIONS=1 -gsource-map")
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")
else() else()
if(MAEMO5 AND SANITIZERS_ARGS) if(MAEMO5 AND SANITIZERS_ARGS)
message(STATUS "Sanitizers unavailable on Maemo, disabling...") message(STATUS "Sanitizers unavailable on Maemo, disabling...")
@ -147,10 +143,10 @@ if (NOT LIBSUPERDERPY_CONFIG_INCLUDED)
if(APPLE) if(APPLE)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-undefined,error") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-undefined,error")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_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_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--no-undefined") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--no-undefined")
endif(APPLE) endif()
endif() endif()
option(USE_CLANG_TIDY "Analyze the code with clang-tidy" OFF) 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(POLICY CMP0069 AND LIBSUPERDERPY_LTO)
if(NOT USE_CLANG_TIDY AND NOT MINGW) # clang-tidy + GCC + LTO = errors; also, MinGW crashes if(NOT USE_CLANG_TIDY AND NOT MINGW) # clang-tidy + GCC + LTO = errors; also, MinGW crashes
cmake_policy(SET CMP0069 NEW) cmake_policy(SET CMP0069 NEW)
include(CheckIPOSupported) if (EMSCRIPTEN)
check_ipo_supported(RESULT IPO_SUPPORTED) 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}") message(STATUS "Link time optimization: ${IPO_SUPPORTED}")
if(IPO_SUPPORTED) if(IPO_SUPPORTED)
if(NOT EMSCRIPTEN) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -flto")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -flto") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -flto")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -flto") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_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()
endif() endif()
endif() endif()
endif() endif()
@ -213,12 +208,13 @@ if (NOT LIBSUPERDERPY_CONFIG_INCLUDED)
add_definitions("-DLIBSUPERDERPY_STATIC_GAMESTATES") add_definitions("-DLIBSUPERDERPY_STATIC_GAMESTATES")
endif(LIBSUPERDERPY_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) if(LIBSUPERDERPY_STATIC_DEPS)
SET(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a) SET(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a)
endif(LIBSUPERDERPY_STATIC_DEPS) 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) if(MAEMO5)
add_definitions(-DMAEMO5=1) 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}") set(CMAKE_INSTALL_RPATH "\$ORIGIN/../${LIB_DIR}/${LIBSUPERDERPY_GAMENAME}:\$ORIGIN/gamestates:\$ORIGIN:\$ORIGIN/../${LIB_DIR}:\$ORIGIN/${LIB_DIR}:\$ORIGIN/${BIN_DIR}")
if(EMSCRIPTEN) if(EMSCRIPTEN)
set(CMAKE_EXECUTABLE_SUFFIX ".bc") set(CMAKE_EXECUTABLE_SUFFIX ".html")
set(CMAKE_SHARED_LIBRARY_SUFFIX ".so")
# GNU extensions are needed for things like EM_ASM # GNU extensions are needed for things like EM_ASM
set(CMAKE_C_EXTENSIONS ON) 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_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O3")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_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_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")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --ignore-dynamic-linking") # -s FORCE_FILESYSTEM=1 --pre-js ${LIBSUPERDERPY_DIR}/src/emscripten-pre-js.js")
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 -s FULL_ES2=1 -s ERROR_ON_MISSING_LIBRARIES=1 -s ASYNCIFY)
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(LIBSUPERDERPY_EMSCRIPTEN_MODE "wasm" CACHE STRING "Emscripten compilation mode (JavaScript or WebAssembly)") set(LIBSUPERDERPY_EMSCRIPTEN_MODE "wasm" CACHE STRING "Emscripten compilation mode (JavaScript or WebAssembly)")
set_property(CACHE LIBSUPERDERPY_EMSCRIPTEN_MODE PROPERTY STRINGS "asm.js;wasm") set_property(CACHE LIBSUPERDERPY_EMSCRIPTEN_MODE PROPERTY STRINGS "asm.js;wasm")
if("${LIBSUPERDERPY_EMSCRIPTEN_MODE}" STREQUAL "wasm") if("${LIBSUPERDERPY_EMSCRIPTEN_MODE}" STREQUAL "wasm")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -s WASM=1") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s WASM=1 -s ALLOW_MEMORY_GROWTH=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")
add_definitions(-DLIBSUPERDERPY_WASM=1) add_definitions(-DLIBSUPERDERPY_WASM=1)
else() else()
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -s WASM=0") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s WASM=0 -s PRECISE_F32=1")
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")
endif() endif()
option(LIBSUPERDERPY_USE_WEBGL2 "Use WebGL 2 context" OFF) option(LIBSUPERDERPY_USE_WEBGL2 "Use WebGL 2 context" OFF)
if(LIBSUPERDERPY_USE_WEBGL2) 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) endif(LIBSUPERDERPY_USE_WEBGL2)
if(CMAKE_INSTALL_PREFIX MATCHES "/usr/local") # HACK 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") include_directories("${LIBSUPERDERPY_BINARY_DIR}/src/3rdparty/allegro5/include")
else (LIBSUPERDERPY_EMBEDDED_ALLEGRO) else (LIBSUPERDERPY_EMBEDDED_ALLEGRO)
find_package(Allegro5 REQUIRED) find_package(Allegro5 REQUIRED)
if(NOT EMSCRIPTEN) find_package(Allegro5Font REQUIRED)
find_package(Allegro5Font REQUIRED) find_package(Allegro5TTF REQUIRED)
find_package(Allegro5TTF REQUIRED) find_package(Allegro5Primitives REQUIRED)
find_package(Allegro5Primitives REQUIRED) find_package(Allegro5Audio REQUIRED)
find_package(Allegro5Audio REQUIRED) find_package(Allegro5ACodec REQUIRED)
find_package(Allegro5ACodec REQUIRED) find_package(Allegro5Image REQUIRED)
find_package(Allegro5Image REQUIRED) find_package(Allegro5Color REQUIRED)
find_package(Allegro5Color REQUIRED) find_package(Allegro5Video REQUIRED)
find_package(Allegro5Video REQUIRED) if(APPLE)
if(APPLE) find_package(Allegro5Main)
find_package(Allegro5Main) endif(APPLE)
endif(APPLE)
endif(NOT EMSCRIPTEN)
endif() 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}) 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}") add_dependencies(${LIBSUPERDERPY_GAMENAME}_apk "lib${LIBSUPERDERPY_GAMENAME}-${name}")
endif() 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() ENDMACRO()
MACRO(libsuperderpy_copy EXECUTABLE) MACRO(libsuperderpy_copy EXECUTABLE)
@ -558,17 +530,13 @@ if (NOT LIBSUPERDERPY_CONFIG_INCLUDED)
string(REPLACE " " ";" CFLAGS_L ${CMAKE_C_FLAGS} " " ${${CFLAGS}}) string(REPLACE " " ";" CFLAGS_L ${CMAKE_C_FLAGS} " " ${${CFLAGS}})
set(CFLAGS_LIST ${CFLAGS_L}) set(CFLAGS_LIST ${CFLAGS_L})
if("${LIBSUPERDERPY_EMSCRIPTEN_MODE}" STREQUAL "wasm") file(MAKE_DIRECTORY "${CMAKE_INSTALL_PREFIX}/${LIBSUPERDERPY_GAMENAME}")
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()
add_custom_target(${LIBSUPERDERPY_GAMENAME}_js 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}" 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 USES_TERMINAL
VERBATIM VERBATIM
) )

View file

@ -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;

View file

@ -358,9 +358,7 @@ SYMBOL_INTERNAL void GamestateProgress(struct Game* game) {
if (game->loading.shown) { if (game->loading.shown) {
game->_priv.loading.gamestate->api->logic(game, game->_priv.loading.gamestate->data, delta); game->_priv.loading.gamestate->api->logic(game, game->_priv.loading.gamestate->data, delta);
} }
DrawGamestates(game); RedrawScreen(game);
DrawConsole(game);
al_flip_display();
#endif #endif
} }

View file

@ -49,12 +49,6 @@
#ifdef ALLEGRO_WINDOWS #ifdef ALLEGRO_WINDOWS
#define LIBRARY_EXTENSION ".dll" #define LIBRARY_EXTENSION ".dll"
#elif defined(__EMSCRIPTEN__)
#if defined(LIBSUPERDERPY_WASM)
#define LIBRARY_EXTENSION ".wasm.so"
#else
#define LIBRARY_EXTENSION ".js"
#endif
#else #else
#define LIBRARY_EXTENSION ".so" #define LIBRARY_EXTENSION ".so"
#endif #endif

View file

@ -498,40 +498,20 @@ SYMBOL_EXPORT int libsuperderpy_start(struct Game* game) {
return 0; 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) { SYMBOL_EXPORT int libsuperderpy_run(struct Game* game) {
int ret = libsuperderpy_start(game); int ret = libsuperderpy_start(game);
if (ret) { if (ret) {
return ret; return ret;
} }
#ifdef __EMSCRIPTEN__ #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()})) { if (game->config.autopause && !EM_ASM_INT({document.hasFocus()})) {
PrintConsole(game, "Window not focused, autopausing..."); PrintConsole(game, "Window not focused, autopausing...");
PauseExecution(game); PauseExecution(game);
} }
emscripten_set_main_loop_arg(libsuperderpy_emscripten_mainloop, game, 0, false); #endif
return 0;
#else
while (libsuperderpy_mainloop(game)) {} while (libsuperderpy_mainloop(game)) {}
libsuperderpy_destroy(game); libsuperderpy_destroy(game);
return 0; return 0;
#endif
} }
SYMBOL_EXPORT void libsuperderpy_destroy(struct Game* game) { SYMBOL_EXPORT void libsuperderpy_destroy(struct Game* game) {
@ -583,8 +563,20 @@ SYMBOL_EXPORT void libsuperderpy_destroy(struct Game* game) {
} }
DestroyShaders(game); DestroyShaders(game);
PrintConsole(game, "Shutting down...");
SetBackgroundColor(game, al_map_rgb(0, 0, 0)); SetBackgroundColor(game, al_map_rgb(0, 0, 0));
ClearScreen(game); 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__ #ifdef __EMSCRIPTEN__
{ {
ALLEGRO_BITMAP* bmp = al_create_bitmap(320, 180); 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, "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_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_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_flip_display();
al_destroy_bitmap(bmp); al_destroy_bitmap(bmp);
al_destroy_font(font); al_destroy_font(font);
} }
printf("Halted.\n");
return;
#endif #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_user_event_source(&(game->event_source));
al_destroy_event_queue(game->_priv.event_queue); al_destroy_event_queue(game->_priv.event_queue);
al_restore_default_mixer(); 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_cond(game->_priv.bsod_cond);
al_destroy_mutex(game->_priv.bsod_mutex); al_destroy_mutex(game->_priv.bsod_mutex);
al_destroy_mutex(game->_priv.mutex); al_destroy_mutex(game->_priv.mutex);
al_uninstall_audio();
DeinitConfig(game); DeinitConfig(game);
#ifndef __EMSCRIPTEN__ // ??? al_uninstall_audio();
al_destroy_display(game->display);
al_uninstall_system(); al_uninstall_system();
#endif
#ifndef LIBSUPERDERPY_NO_RESTART #ifndef LIBSUPERDERPY_NO_RESTART
char** argv = game->_priv.argv; char** argv = game->_priv.argv;

View file

@ -224,7 +224,7 @@ static inline bool MainloopEvents(struct Game* game) {
do { do {
ALLEGRO_EVENT ev; ALLEGRO_EVENT ev;
if (game->_priv.paused && !IS_EMSCRIPTEN) { if (game->_priv.paused) {
// there's no frame flipping when paused, so avoid pointless busylooping // there's no frame flipping when paused, so avoid pointless busylooping
al_wait_for_event(game->_priv.event_queue, &ev); al_wait_for_event(game->_priv.event_queue, &ev);
} else if (!al_get_next_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; struct Gamestate* tmp = game->_priv.gamestates;
#ifdef __EMSCRIPTEN__
emscripten_pause_main_loop();
#endif
game->_priv.loading.to_load = 0; game->_priv.loading.to_load = 0;
game->_priv.loading.loaded = 0; game->_priv.loading.loaded = 0;
game->_priv.loading.lock = true; game->_priv.loading.lock = true;
@ -323,7 +319,7 @@ static inline bool MainloopTick(struct Game* game) {
while (tmp) { while (tmp) {
if (tmp->pending_unload) { if (tmp->pending_unload) {
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
StopAudio(game); //StopAudio(game);
#endif #endif
PrintConsole(game, "Unloading gamestate \"%s\"...", tmp->name); PrintConsole(game, "Unloading gamestate \"%s\"...", tmp->name);
tmp->loaded = false; tmp->loaded = false;
@ -332,12 +328,12 @@ static inline bool MainloopTick(struct Game* game) {
(*tmp->api->unload)(game, tmp->data); (*tmp->api->unload)(game, tmp->data);
PrintConsole(game, "Gamestate \"%s\" unloaded successfully.", tmp->name); PrintConsole(game, "Gamestate \"%s\" unloaded successfully.", tmp->name);
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
SetupAudio(game); //SetupAudio(game);
#endif #endif
} }
if (tmp->pending_load) { if (tmp->pending_load) {
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
StopAudio(game); //StopAudio(game);
#endif #endif
#ifdef __vita__ #ifdef __vita__
int vita_arm_freq = scePowerGetArmClockFrequency(); int vita_arm_freq = scePowerGetArmClockFrequency();
@ -372,12 +368,7 @@ static inline bool MainloopTick(struct Game* game) {
CalculateProgress(game); CalculateProgress(game);
if (tmp->show_loading) { if (tmp->show_loading) {
game->loading.shown = true; game->loading.shown = true;
DrawGamestates(game); RedrawScreen(game);
DrawConsole(game);
al_flip_display();
#ifdef __EMSCRIPTEN__
emscripten_sleep(0);
#endif
} }
#ifndef LIBSUPERDERPY_SINGLE_THREAD #ifndef LIBSUPERDERPY_SINGLE_THREAD
al_run_detached_thread(GamestateLoadingThread, &data); 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) { if (game->loading.shown && game->_priv.loading.gamestate->open) {
(*game->_priv.loading.gamestate->api->logic)(game, game->_priv.loading.gamestate->data, delta); (*game->_priv.loading.gamestate->api->logic)(game, game->_priv.loading.gamestate->data, delta);
} }
DrawGamestates(game);
if (game->_priv.texture_sync) { if (game->_priv.texture_sync) {
al_convert_memory_bitmaps(); al_convert_memory_bitmaps();
game->_priv.texture_sync = false; game->_priv.texture_sync = false;
al_signal_cond(game->_priv.texture_sync_cond); al_signal_cond(game->_priv.texture_sync_cond);
game->_priv.loading.time = al_get_time(); // TODO: rethink time management during loading game->_priv.loading.time = al_get_time(); // TODO: rethink time management during loading
} }
DrawConsole(game); RedrawScreen(game);
al_flip_display();
if (game->_priv.bsod_sync) { if (game->_priv.bsod_sync) {
al_set_target_bitmap(NULL); al_set_target_bitmap(NULL);
@ -412,12 +401,7 @@ static inline bool MainloopTick(struct Game* game) {
} }
#else #else
GamestateLoadingThread(&data); GamestateLoadingThread(&data);
DrawGamestates(game); RedrawScreen(game);
DrawConsole(game);
al_flip_display();
#ifdef __EMSCRIPTEN__
emscripten_sleep(0);
#endif
#endif #endif
al_convert_memory_bitmaps(); 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); PrintConsole(game, "Gamestate \"%s\" loaded successfully in %f seconds.", tmp->name, al_get_time() - time);
game->_priv.loading.loaded++; game->_priv.loading.loaded++;
DrawGamestates(game); RedrawScreen(game);
DrawConsole(game);
al_flip_display();
#ifdef __EMSCRIPTEN__
emscripten_sleep(0);
#endif
tmp->loaded = true; tmp->loaded = true;
tmp->pending_load = false; tmp->pending_load = false;
@ -452,7 +431,7 @@ static inline bool MainloopTick(struct Game* game) {
game->loading.shown = false; game->loading.shown = false;
game->_priv.timestamp = al_get_time(); game->_priv.timestamp = al_get_time();
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
SetupAudio(game); //SetupAudio(game);
#endif #endif
#ifdef __vita__ #ifdef __vita__
scePowerSetArmClockFrequency(vita_arm_freq); scePowerSetArmClockFrequency(vita_arm_freq);
@ -465,12 +444,6 @@ static inline bool MainloopTick(struct Game* game) {
if (game->_priv.loading.loaded) { if (game->_priv.loading.loaded) {
MainloopEvents(game); // consume queued events MainloopEvents(game); // consume queued events
#ifdef __EMSCRIPTEN__
DrawGamestates(game);
DrawConsole(game);
al_flip_display();
emscripten_sleep(0);
#endif
} }
bool gameActive = false; bool gameActive = false;
@ -500,15 +473,11 @@ static inline bool MainloopTick(struct Game* game) {
} }
game->_priv.loading.lock = false; game->_priv.loading.lock = false;
#ifdef __EMSCRIPTEN__
emscripten_resume_main_loop();
#endif
if (!gameActive) { if (!gameActive) {
PrintConsole(game, "No gamestates left, exiting..."); PrintConsole(game, "No gamestates left, exiting...");
ClearScreen(game); ClearScreen(game);
DrawConsole(game); RedrawScreen(game);
al_flip_display();
return false; return false;
} }
@ -518,22 +487,9 @@ static inline bool MainloopTick(struct Game* game) {
game->_priv.timestamp += delta; game->_priv.timestamp += delta;
delta *= game->_priv.speed; delta *= game->_priv.speed;
#ifdef LIBSUPERDERPY_IMGUI
ImGui_ImplAllegro5_NewFrame();
igNewFrame();
#endif
LogicGamestates(game, delta); LogicGamestates(game, delta);
DrawGamestates(game); RedrawScreen(game);
#ifdef LIBSUPERDERPY_IMGUI
igRender();
ImGui_ImplAllegro5_RenderDrawData(igGetDrawData());
#endif
DrawConsole(game);
al_flip_display();
return true; return true;
} }