mirror of
https://gitlab.com/dosowisko.net/libsuperderpy.git
synced 2024-12-05 00:38:00 +01:00
support static linking the whole game into one binary
This commit is contained in:
parent
c724a490fb
commit
c6ef4a6199
13 changed files with 310 additions and 35 deletions
|
@ -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)
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
25
src/gamestates-constructor.c.in
Normal file
25
src/gamestates-constructor.c.in
Normal 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}
|
||||
}
|
24
src/gamestates-force-inclusion.c
Normal file
24
src/gamestates-force-inclusion.c
Normal 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
34
src/gamestates-stub.c.in
Normal 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}
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue