support static linking the whole game into one binary

This commit is contained in:
Sebastian Krzyszkowiak 2019-05-17 02:31:17 +02:00
parent c724a490fb
commit c6ef4a6199
No known key found for this signature in database
GPG key ID: E8F235CF3BDBC3FF
13 changed files with 310 additions and 35 deletions

View file

@ -1,4 +1,21 @@
FILE (GLOB gamestates "*.c")
if(LIBSUPERDERPY_STATIC_GAMESTATES)
set(LIBSUPERDERPY_GAMESTATES_CONSTRUCTOR "")
set(LIBSUPERDERPY_GAMESTATES_STUB "")
FOREACH(gamestate ${gamestates})
get_filename_component(gamestate_name ${gamestate} NAME_WE)
set(LIBSUPERDERPY_GAMESTATES_CONSTRUCTOR "${LIBSUPERDERPY_GAMESTATES_CONSTRUCTOR} void __libsuperderpy_init_${gamestate_name}_gamestate(void); __libsuperderpy_init_${gamestate_name}_gamestate();")
set(LIBSUPERDERPY_GAMESTATES_STUB "${LIBSUPERDERPY_GAMESTATES_STUB} GAMESTATE_STUB(${gamestate_name}) ")
ENDFOREACH(gamestate)
configure_file("${LIBSUPERDERPY_DIR}/src/gamestates-constructor.c.in" "${CMAKE_BINARY_DIR}/gen/gamestates-constructor.c")
configure_file("${LIBSUPERDERPY_DIR}/src/gamestates-stub.c.in" "${CMAKE_BINARY_DIR}/gen/gamestates-stub.c")
add_library(libsuperderpy-gamestates STATIC "${CMAKE_BINARY_DIR}/gen/gamestates-constructor.c")
add_library(libsuperderpy-gamestates-stub STATIC "${CMAKE_BINARY_DIR}/gen/gamestates-stub.c")
endif(LIBSUPERDERPY_STATIC_GAMESTATES)
FOREACH(gamestate ${gamestates})
get_filename_component(gamestate_name ${gamestate} NAME_WE)
set(sources "${gamestate_name}.c")
@ -8,4 +25,11 @@ FOREACH(gamestate ${gamestates})
list(APPEND sources "${gamestate_name}/${submodule_name}.c")
ENDFOREACH(submodule)
register_gamestate(${gamestate_name} "${sources}")
if (LIBSUPERDERPY_STATIC_GAMESTATES)
target_link_libraries("libsuperderpy-gamestates" lib${LIBSUPERDERPY_GAMENAME}-${gamestate_name})
endif (LIBSUPERDERPY_STATIC_GAMESTATES)
ENDFOREACH(gamestate)
if (LIBSUPERDERPY_STATIC_GAMESTATES)
target_link_libraries("libsuperderpy-gamestates" "-Wl,--allow-multiple" libsuperderpy-gamestates-stub)
endif (LIBSUPERDERPY_STATIC_GAMESTATES)

View file

@ -23,11 +23,22 @@ if (APPLE)
endif(APPLE)
install(TARGETS ${EXECUTABLE} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
add_library("lib${LIBSUPERDERPY_GAMENAME}" SHARED ${SHARED_SRC_LIST})
if (BUILD_SHARED_LIBS)
add_library("lib${LIBSUPERDERPY_GAMENAME}" SHARED ${SHARED_SRC_LIST})
else(BUILD_SHARED_LIBS)
add_library("lib${LIBSUPERDERPY_GAMENAME}" STATIC ${SHARED_SRC_LIST})
endif(BUILD_SHARED_LIBS)
set_target_properties("lib${LIBSUPERDERPY_GAMENAME}" PROPERTIES PREFIX "")
target_link_libraries("lib${LIBSUPERDERPY_GAMENAME}" libsuperderpy)
target_link_libraries("lib${LIBSUPERDERPY_GAMENAME}" libsuperderpy ${LIBSUPERDERPY_EXTRA_LIBS})
install(TARGETS "lib${LIBSUPERDERPY_GAMENAME}" DESTINATION ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX})
add_subdirectory("gamestates")
if(LIBSUPERDERPY_STATIC_GAMESTATES)
target_link_libraries(${EXECUTABLE} libsuperderpy-gamestates)
endif(LIBSUPERDERPY_STATIC_GAMESTATES)
libsuperderpy_copy(${EXECUTABLE})
target_link_libraries(${EXECUTABLE} ${LIBSUPERDERPY_EXTRA_LIBS})

View file

@ -169,9 +169,20 @@ if (NOT LIBSUPERDERPY_CONFIG_INCLUDED)
endif()
endif()
option(LIBSUPERDERPY_STATIC "Compile and link libsuperderpy as a static library." OFF)
option(BUILD_SHARED_LIBS "Use dynamic linking" ON)
if (NOT BUILD_SHARED_LIBS)
set(STATIC_DEFAULT ON)
else()
set(STATIC_DEFAULT OFF)
endif()
option(LIBSUPERDERPY_STATIC_DEPS "Link dependencies (e.g. Allegro) statically." OFF)
option(LIBSUPERDERPY_STATIC "Compile and link libsuperderpy as a static library." ${STATIC_DEFAULT})
option(LIBSUPERDERPY_STATIC_GAMESTATES "Compile and link gamestates as static libraries" ${STATIC_DEFAULT})
if(LIBSUPERDERPY_STATIC_GAMESTATES)
add_definitions("-DLIBSUPERDERPY_STATIC_GAMESTATES")
endif(LIBSUPERDERPY_STATIC_GAMESTATES)
option(LIBSUPERDERPY_STATIC_DEPS "Link dependencies (e.g. Allegro) statically." ${STATIC_DEFAULT})
if(LIBSUPERDERPY_STATIC_DEPS)
SET(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a)
endif(LIBSUPERDERPY_STATIC_DEPS)
@ -189,6 +200,10 @@ if (NOT LIBSUPERDERPY_CONFIG_INCLUDED)
add_definitions(-DLIBSUPERDERPY_EMULATE_TOUCH=1)
endif(MAEMO5 OR POCKETCHIP)
if(EMSCRIPTEN OR SWITCH)
add_definitions(-DLIBSUPERDERPY_NO_RESTART=1)
endif(EMSCRIPTEN OR SWITCH)
set(GAMESTATE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}")
if(APPLE)
@ -285,16 +300,22 @@ if (NOT LIBSUPERDERPY_CONFIG_INCLUDED)
MACRO(register_gamestate name sources)
add_library("lib${LIBSUPERDERPY_GAMENAME}-${name}" MODULE ${sources})
if (LIBSUPERDERPY_STATIC_GAMESTATES)
add_library("lib${LIBSUPERDERPY_GAMENAME}-${name}" STATIC ${sources})
else(LIBSUPERDERPY_STATIC_GAMESTATES)
add_library("lib${LIBSUPERDERPY_GAMENAME}-${name}" MODULE ${sources})
endif(LIBSUPERDERPY_STATIC_GAMESTATES)
target_compile_definitions("lib${LIBSUPERDERPY_GAMENAME}-${name}" PRIVATE LIBSUPERDERPY_GAMESTATE=${name})
set_target_properties("lib${LIBSUPERDERPY_GAMENAME}-${name}" PROPERTIES PREFIX "")
if (NOT EMSCRIPTEN)
if (TARGET lib${LIBSUPERDERPY_GAMENAME})
target_link_libraries("lib${LIBSUPERDERPY_GAMENAME}-${name}" lib${LIBSUPERDERPY_GAMENAME})
target_link_libraries("lib${LIBSUPERDERPY_GAMENAME}-${name}" lib${LIBSUPERDERPY_GAMENAME} ${LIBSUPERDERPY_EXTRA_LIBS})
else (TARGET lib${LIBSUPERDERPY_GAMENAME})
if (NOT LIBSUPERDERPY_STATIC)
target_link_libraries("lib${LIBSUPERDERPY_GAMENAME}-${name}" libsuperderpy)
target_link_libraries("lib${LIBSUPERDERPY_GAMENAME}-${name}" libsuperderpy ${LIBSUPERDERPY_EXTRA_LIBS})
endif (NOT LIBSUPERDERPY_STATIC)
endif(TARGET lib${LIBSUPERDERPY_GAMENAME})
endif (NOT EMSCRIPTEN)
@ -418,9 +439,15 @@ if (NOT LIBSUPERDERPY_CONFIG_INCLUDED)
endif (ANDROID OR EMSCRIPTEN)
MACRO(add_libsuperderpy_target EXECUTABLE_SRC_LIST)
if (LIBSUPERDERPY_STATIC_GAMESTATES)
set(SRC_LIST ${EXECUTABLE_SRC_LIST} "${LIBSUPERDERPY_DIR}/src/gamestates-force-inclusion.c")
else()
set(SRC_LIST ${EXECUTABLE_SRC_LIST})
endif()
if(ANDROID)
set(EXECUTABLE superderpy-game)
add_library(${EXECUTABLE} SHARED ${EXECUTABLE_SRC_LIST})
add_library(${EXECUTABLE} SHARED ${SRC_LIST})
set(APK_PATH ${CMAKE_BINARY_DIR}/android/bin/${LIBSUPERDERPY_GAMENAME}-debug.apk)
@ -447,7 +474,7 @@ if (NOT LIBSUPERDERPY_CONFIG_INCLUDED)
)
else(ANDROID)
add_executable(${EXECUTABLE} WIN32 MACOSX_BUNDLE ${EXECUTABLE_SRC_LIST})
add_executable(${EXECUTABLE} WIN32 MACOSX_BUNDLE ${SRC_LIST})
endif(ANDROID)
if(EMSCRIPTEN)

View file

@ -31,15 +31,18 @@ else (LIBSUPERDERPY_STATIC)
add_library("libsuperderpy" SHARED ${SRC_LIST})
endif (LIBSUPERDERPY_STATIC)
if (WIN32 AND LIBSUPERDERPY_DLFCN)
set(BUILD_SHARED_LIBS OFF CACHE STRING "" FORCE)
add_subdirectory(3rdparty/dlfcn-win32 EXCLUDE_FROM_ALL)
set_property(TARGET "dl" PROPERTY POSITION_INDEPENDENT_CODE ON)
endif(WIN32 AND LIBSUPERDERPY_DLFCN)
SET_TARGET_PROPERTIES("libsuperderpy" PROPERTIES PREFIX "")
target_link_libraries("libsuperderpy" ${ALLEGRO5_LIBRARIES} ${ALLEGRO5_FONT_LIBRARIES} ${ALLEGRO5_TTF_LIBRARIES} ${ALLEGRO5_PRIMITIVES_LIBRARIES} ${ALLEGRO5_AUDIO_LIBRARIES} ${ALLEGRO5_ACODEC_LIBRARIES} ${ALLEGRO5_VIDEO_LIBRARIES} ${ALLEGRO5_COLOR_LIBRARIES} ${ALLEGRO5_IMAGE_LIBRARIES} m dl)
if (NOT LIBSUPERDERPY_STATIC_GAMESTATES)
if (WIN32 AND LIBSUPERDERPY_DLFCN)
set(BUILD_SHARED_LIBS OFF CACHE STRING "" FORCE)
add_subdirectory(3rdparty/dlfcn-win32 EXCLUDE_FROM_ALL)
set_property(TARGET "dl" PROPERTY POSITION_INDEPENDENT_CODE ON)
endif(WIN32 AND LIBSUPERDERPY_DLFCN)
target_link_libraries("libsuperderpy" dl)
endif()
target_link_libraries("libsuperderpy" ${ALLEGRO5_LIBRARIES} ${ALLEGRO5_FONT_LIBRARIES} ${ALLEGRO5_TTF_LIBRARIES} ${ALLEGRO5_PRIMITIVES_LIBRARIES} ${ALLEGRO5_AUDIO_LIBRARIES} ${ALLEGRO5_ACODEC_LIBRARIES} ${ALLEGRO5_VIDEO_LIBRARIES} ${ALLEGRO5_COLOR_LIBRARIES} ${ALLEGRO5_IMAGE_LIBRARIES} m)
if (LIBSUPERDERPY_IMGUI)
target_link_libraries("libsuperderpy" cimgui)

View file

@ -41,7 +41,8 @@ SYMBOL_EXPORT void RegisterGamestate(struct Game* game, const char* name, struct
PrintConsole(game, "Trying to register already registered gamestate \"%s\"!", name);
return;
}
gs->api = api;
gs->api = malloc(sizeof(struct GamestateAPI));
*gs->api = *api;
gs->fromlib = false;
PrintConsole(game, "Gamestate \"%s\" registered.", name);
}

View file

@ -68,6 +68,27 @@ bool IsGamestateVisible(struct Game* game, struct Gamestate* gamestate);
// Gamestate API
#if defined(LIBSUPERDERPY_STATIC_GAMESTATES) && defined(LIBSUPERDERPY_GAMESTATE)
#define GAMESTATE_CONCAT_STR(x, y) x##y
#define GAMESTATE_CONCAT(x, y) GAMESTATE_CONCAT_STR(x, y)
#define Gamestate_ProgressCount GAMESTATE_CONCAT(LIBSUPERDERPY_GAMESTATE, _Gamestate_ProgressCount)
#define Gamestate_Draw GAMESTATE_CONCAT(LIBSUPERDERPY_GAMESTATE, _Gamestate_Draw)
#define Gamestate_Logic GAMESTATE_CONCAT(LIBSUPERDERPY_GAMESTATE, _Gamestate_Logic)
#define Gamestate_Tick GAMESTATE_CONCAT(LIBSUPERDERPY_GAMESTATE, _Gamestate_Tick)
#define Gamestate_Load GAMESTATE_CONCAT(LIBSUPERDERPY_GAMESTATE, _Gamestate_Load)
#define Gamestate_PostLoad GAMESTATE_CONCAT(LIBSUPERDERPY_GAMESTATE, _Gamestate_PostLoad)
#define Gamestate_Start GAMESTATE_CONCAT(LIBSUPERDERPY_GAMESTATE, _Gamestate_Start)
#define Gamestate_Pause GAMESTATE_CONCAT(LIBSUPERDERPY_GAMESTATE, _Gamestate_Pause)
#define Gamestate_Resume GAMESTATE_CONCAT(LIBSUPERDERPY_GAMESTATE, _Gamestate_Resume)
#define Gamestate_Stop GAMESTATE_CONCAT(LIBSUPERDERPY_GAMESTATE, _Gamestate_Stop)
#define Gamestate_Unload GAMESTATE_CONCAT(LIBSUPERDERPY_GAMESTATE, _Gamestate_Unload)
#define Gamestate_ProcessEvent GAMESTATE_CONCAT(LIBSUPERDERPY_GAMESTATE, Gamestate_ProcessEvent)
#define Gamestate_Reload GAMESTATE_CONCAT(LIBSUPERDERPY_GAMESTATE, _Gamestate_Reload)
#endif
extern int Gamestate_ProgressCount;
__attribute__((used)) void Gamestate_Draw(struct Game* game, struct GamestateResources* data);
__attribute__((used)) void Gamestate_Logic(struct Game* game, struct GamestateResources* data, double delta);
@ -82,4 +103,39 @@ __attribute__((used)) void Gamestate_Unload(struct Game* game, struct GamestateR
__attribute__((used)) void Gamestate_ProcessEvent(struct Game* game, struct GamestateResources* data, ALLEGRO_EVENT* ev);
__attribute__((used)) void Gamestate_Reload(struct Game* game, struct GamestateResources* data);
#if defined(LIBSUPERDERPY_STATIC_GAMESTATES) && defined(LIBSUPERDERPY_GAMESTATE)
#define GAMESTATE_INIT_NAME_STR(x) __libsuperderpy_init_##x##_gamestate
#define GAMESTATE_INIT_NAME(x) GAMESTATE_INIT_NAME_STR(x)
#define GAMESTATE_STR(b) #b
#define GAMESTATE_STRINGIFY(a) GAMESTATE_STR(a)
void __libsuperderpy_register_gamestate(const char*, struct GamestateAPI*, struct Game*);
void GAMESTATE_INIT_NAME(LIBSUPERDERPY_GAMESTATE)(void) {
struct GamestateAPI api = {
.draw = (void*)Gamestate_Draw,
.logic = (void*)Gamestate_Logic,
.tick = (void*)Gamestate_Tick,
.load = (void*)Gamestate_Load,
.post_load = (void*)Gamestate_PostLoad,
.start = (void*)Gamestate_Start,
.pause = (void*)Gamestate_Pause,
.resume = (void*)Gamestate_Resume,
.stop = (void*)Gamestate_Stop,
.unload = (void*)Gamestate_Unload,
.process_event = (void*)Gamestate_ProcessEvent,
.reload = (void*)Gamestate_Reload,
.progress_count = &Gamestate_ProgressCount,
};
__libsuperderpy_register_gamestate(GAMESTATE_STRINGIFY(LIBSUPERDERPY_GAMESTATE), &api, NULL);
}
#undef GAMESTATE_INIT_NAME_STR
#undef GAMESTATE_INIT_NAME
#undef GAMESTATE_STR
#undef GAMESTATE_STRINGIFY
#endif
#endif /* LIBSUPERDERPY_GAMESTATE_H */

View file

@ -0,0 +1,25 @@
/*
* Copyright (c) Sebastian Krzyszkowiak <dos@dosowisko.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libsuperderpy.h>
extern int __libsuperderpy_gamestates_force_inclusion;
int __libsuperderpy_gamestates_force_inclusion = 0x42;
__attribute__((constructor)) static void __libsuperderpy_gamestates_do_force_inclusion(void) {
${LIBSUPERDERPY_GAMESTATES_CONSTRUCTOR}
}

View file

@ -0,0 +1,24 @@
/*
* Copyright (c) Sebastian Krzyszkowiak <dos@dosowisko.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "internal.h"
extern int __libsuperderpy_gamestates_force_inclusion;
__attribute__((constructor)) static void force_linking(void) {
__libsuperderpy_gamestates_force_inclusion = 42;
}

34
src/gamestates-stub.c.in Normal file
View file

@ -0,0 +1,34 @@
/*
* Copyright (c) Sebastian Krzyszkowiak <dos@dosowisko.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define GAMESTATES_STUB_CONCAT_STR(x, y) x##y
#define GAMESTATES_STUB_CONCAT(x, y) GAMESTATES_STUB_CONCAT_STR(x, y)
#define GAMESTATE_STUB(name) \
__attribute__((used)) void GAMESTATES_STUB_CONCAT(name, _Gamestate_Tick)(); \
__attribute__((used)) void GAMESTATES_STUB_CONCAT(name, _Gamestate_PostLoad)(); \
__attribute__((used)) void GAMESTATES_STUB_CONCAT(name, _Gamestate_Pause)(); \
__attribute__((used)) void GAMESTATES_STUB_CONCAT(name, _Gamestate_Resume)(); \
__attribute__((used)) void GAMESTATES_STUB_CONCAT(name, _Gamestate_Reload)(); \
void GAMESTATES_STUB_CONCAT(name, _Gamestate_Tick)() {} \
void GAMESTATES_STUB_CONCAT(name, _Gamestate_PostLoad)() {} \
void GAMESTATES_STUB_CONCAT(name, _Gamestate_Pause)() {} \
void GAMESTATES_STUB_CONCAT(name, _Gamestate_Resume)() {} \
void GAMESTATES_STUB_CONCAT(name, _Gamestate_Reload)() {}
${LIBSUPERDERPY_GAMESTATES_STUB}

View file

@ -19,7 +19,10 @@
#include "internal.h"
#include "3rdparty/valgrind.h"
#ifndef LIBSUPERDERPY_STATIC_GAMESTATES
#include <dlfcn.h>
#endif
SYMBOL_INTERNAL void SimpleCompositor(struct Game* game) {
struct Gamestate* tmp = GetNextGamestate(game, NULL);
@ -338,6 +341,7 @@ SYMBOL_INTERNAL void GamestateProgress(struct Game* game) {
SYMBOL_INTERNAL bool OpenGamestate(struct Game* game, struct Gamestate* gamestate, bool required) {
PrintConsole(game, "Opening gamestate \"%s\"...", gamestate->name);
#ifndef LIBSUPERDERPY_STATIC_GAMESTATES
char libname[1024];
snprintf(libname, 1024, "lib%s-%s" LIBRARY_EXTENSION, game->_priv.name, gamestate->name);
gamestate->handle = dlopen(AddGarbage(game, GetLibraryPath(game, libname)), RTLD_NOW);
@ -347,6 +351,12 @@ SYMBOL_INTERNAL bool OpenGamestate(struct Game* game, struct Gamestate* gamestat
}
return false;
}
#else
if (gamestate->fromlib) {
FatalError(game, false, "Tried to open a not registered gamestate \"%s\"!", gamestate->name);
return false;
}
#endif
if (game->_priv.params.handlers.compositor) {
gamestate->fb = CreateNotPreservedBitmap(game->clip_rect.w, game->clip_rect.h);
} else {
@ -357,6 +367,8 @@ SYMBOL_INTERNAL bool OpenGamestate(struct Game* game, struct Gamestate* gamestat
}
SYMBOL_INTERNAL bool LinkGamestate(struct Game* game, struct Gamestate* gamestate) {
PrintConsole(game, "Linking gamestate \"%s\"...", gamestate->name);
#ifndef LIBSUPERDERPY_STATIC_GAMESTATES
gamestate->api = calloc(1, sizeof(struct GamestateAPI));
#define GS_ERROR \
@ -380,12 +392,18 @@ SYMBOL_INTERNAL bool LinkGamestate(struct Game* game, struct Gamestate* gamestat
gamestate->api->reload = dlsym(gamestate->handle, "Gamestate_Reload");
gamestate->api->progress_count = dlsym(gamestate->handle, "Gamestate_ProgressCount");
#undef GS_ERROR
#else
if (!gamestate->api) {
return false;
}
#endif
if (gamestate->api->progress_count) {
gamestate->progress_count = *gamestate->api->progress_count;
}
#undef GS_ERROR
return true;
}
@ -413,22 +431,26 @@ SYMBOL_INTERNAL struct Gamestate* AllocateGamestate(struct Game* game, const cha
}
SYMBOL_INTERNAL void CloseGamestate(struct Game* game, struct Gamestate* gamestate) {
if (!gamestate->open) {
return;
}
if (gamestate->handle && !RUNNING_ON_VALGRIND) {
#ifndef LEAK_SANITIZER
PrintConsole(game, "Closing gamestate \"%s\"...", gamestate->name);
dlclose(gamestate->handle);
gamestate->handle = NULL;
#endif
}
PrintConsole(game, "Closing gamestate \"%s\"...", gamestate->name);
if (gamestate->api) {
free(gamestate->api);
gamestate->api = NULL;
}
if (!gamestate->open) {
PrintConsole(game, "Gamestate \"%s\" already closed.", gamestate->name);
return;
}
#ifndef LIBSUPERDERPY_STATIC_GAMESTATES
if (gamestate->handle && !RUNNING_ON_VALGRIND) {
#ifndef LEAK_SANITIZER
dlclose(gamestate->handle);
gamestate->handle = NULL;
#endif
}
#endif
al_destroy_bitmap(gamestate->fb);
gamestate->fb = NULL;
gamestate->open = false;
}
SYMBOL_INTERNAL struct List* AddToList(struct List* list, void* data) {
@ -772,3 +794,24 @@ SYMBOL_INTERNAL void SetupViewport(struct Game* game) {
PrintConsole(game, "Viewport %dx%d; display %dx%d", game->viewport.width, game->viewport.height, al_get_display_width(game->display), al_get_display_height(game->display));
}
#ifdef LIBSUPERDERPY_STATIC_GAMESTATES
SYMBOL_EXPORT void __libsuperderpy_register_gamestate(const char* name, struct GamestateAPI* api, struct Game* game) {
static int counter = 0;
static struct GamestateAPI apis[256];
static const char* names[256];
if (counter == 255) {
return;
}
if (api) {
names[counter] = name;
apis[counter++] = *api;
}
if (game) {
for (int i = 0; i < counter; i++) {
RegisterGamestate(game, names[i], &apis[i]);
}
}
}
#endif

View file

@ -21,7 +21,6 @@
#endif
#include "internal.h"
#include <dlfcn.h>
#include <getopt.h>
#include <libgen.h>
#include <locale.h>
@ -352,9 +351,15 @@ SYMBOL_EXPORT struct Game* libsuperderpy_init(int argc, char** argv, const char*
game->loading.progress = 0;
#ifdef LIBSUPERDERPY_STATIC_GAMESTATES
__libsuperderpy_register_gamestate(NULL, NULL, game);
#endif
return game;
}
static void ProgressStub(struct Game* game) {}
SYMBOL_EXPORT int libsuperderpy_start(struct Game* game) {
al_register_event_source(game->_priv.event_queue, al_get_display_event_source(game->display));
al_register_event_source(game->_priv.event_queue, al_get_keyboard_event_source());
@ -383,16 +388,31 @@ SYMBOL_EXPORT int libsuperderpy_start(struct Game* game) {
{
struct Gamestate* tmp = game->_priv.gamestates;
#ifdef LIBSUPERDERPY_STATIC_GAMESTATES
if (tmp && strcmp(tmp->name, "loading") == 0) {
game->_priv.gamestates = tmp->next;
game->_priv.loading.gamestate = tmp;
tmp = game->_priv.gamestates;
}
#endif
while (tmp) {
// don't show loading screen on init if requested
tmp->show_loading = game->_priv.params.show_loading_on_launch;
#ifdef LIBSUPERDERPY_STATIC_GAMESTATES
if (tmp->next && strcmp(tmp->next->name, "loading") == 0) {
game->_priv.loading.gamestate = tmp->next;
tmp->next = tmp->next->next;
}
#endif
tmp = tmp->next;
}
}
game->_priv.loading.gamestate = AllocateGamestate(game, "loading");
if (!game->_priv.loading.gamestate) {
game->_priv.loading.gamestate = AllocateGamestate(game, "loading");
}
if (OpenGamestate(game, game->_priv.loading.gamestate, false) && LinkGamestate(game, game->_priv.loading.gamestate)) {
game->_priv.loading.gamestate->data = (*game->_priv.loading.gamestate->api->load)(game, NULL);
game->_priv.loading.gamestate->data = (*game->_priv.loading.gamestate->api->load)(game, ProgressStub);
game->_priv.loading.gamestate->loaded = true;
PrintConsole(game, "Loading screen registered.");
} else {
@ -486,7 +506,7 @@ SYMBOL_EXPORT void libsuperderpy_destroy(struct Game* game) {
tmp = pom;
}
if (game->_priv.loading.gamestate->api) {
if (game->_priv.loading.gamestate->open && game->_priv.loading.gamestate->api) {
(*game->_priv.loading.gamestate->api->unload)(game, game->_priv.loading.gamestate->data);
}
CloseGamestate(game, game->_priv.loading.gamestate);
@ -540,8 +560,11 @@ SYMBOL_EXPORT void libsuperderpy_destroy(struct Game* game) {
al_destroy_mutex(game->_priv.mutex);
al_uninstall_audio();
DeinitConfig(game);
#ifndef __EMSCRIPTEN__
#ifndef __EMSCRIPTEN__ // ???
al_uninstall_system();
#endif
#ifndef LIBSUPERDERPY_NO_RESTART
char** argv = game->_priv.argv;
bool restart = game->_priv.restart;
free(game->_priv.name);

View file

@ -278,4 +278,8 @@ int libsuperderpy_start(struct Game* game);
int libsuperderpy_run(struct Game* game);
void libsuperderpy_destroy(struct Game* game);
#ifdef LIBSUPERDERPY_STATIC_GAMESTATES
void __libsuperderpy_register_gamestate(const char* name, struct GamestateAPI* api, struct Game* game);
#endif
#endif /* LIBSUPERDERPY_MAIN_H */

View file

@ -303,7 +303,7 @@ static inline bool MainloopTick(struct Game* game) {
(*game->_priv.loading.gamestate->api->start)(game, game->_priv.loading.gamestate->data);
}
if (!tmp->api) {
if (!tmp->open) {
if (!OpenGamestate(game, tmp, true) || !LinkGamestate(game, tmp)) {
tmp->pending_load = false;
tmp->pending_start = false;