Implement hot reloading
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
add_library(engine engine.c)
|
||||
if(${HOTRELOAD})
|
||||
add_executable(engine engine.c)
|
||||
else()
|
||||
add_library(engine SHARED engine.c)
|
||||
endif()
|
||||
set_default_target_options(engine)
|
||||
target_include_directories(engine PUBLIC include)
|
||||
if(${PERFMON})
|
||||
target_compile_definitions(engine PRIVATE PERFMON)
|
||||
endif()
|
||||
target_link_libraries(engine PRIVATE SDL2::SDL2)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "engine_hooks.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
@@ -25,8 +26,44 @@ typedef struct {
|
||||
double max_start, max_evt, max_update, max_render, max_total;
|
||||
} perf_t;
|
||||
|
||||
#ifdef HOTRELOAD
|
||||
static void *game_lib;
|
||||
static engineconf_t game_conf;
|
||||
|
||||
#define X(hook) static hook##_t *hook;
|
||||
HOOKS_XLIST
|
||||
#undef X
|
||||
|
||||
static void load_game_lib(void)
|
||||
{
|
||||
bool firstload = game_lib == NULL;
|
||||
if (!firstload)
|
||||
dlclose(game_lib);
|
||||
|
||||
game_lib = dlopen(GAMELIB, RTLD_NOW);
|
||||
assert(game_lib);
|
||||
|
||||
// We're copying this rather than using it as a pointer so that
|
||||
// the syntax to use it with/without hot reloading is the same.
|
||||
engineconf_t *conf = (engineconf_t *)dlsym(game_lib, "game_conf");
|
||||
if (!firstload)
|
||||
assert(conf->memsize == game_conf.memsize);
|
||||
memcpy(&game_conf, conf, sizeof(engineconf_t));
|
||||
|
||||
#define X(hook) \
|
||||
hook = (hook##_t *)dlsym(game_lib, #hook); \
|
||||
assert(hook);
|
||||
HOOKS_XLIST
|
||||
#undef X
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#ifdef HOTRELOAD
|
||||
load_game_lib();
|
||||
#endif
|
||||
|
||||
int err = SDL_Init(SDL_INIT_VIDEO);
|
||||
assert(0 == err);
|
||||
|
||||
@@ -56,6 +93,10 @@ int main(int argc, char *argv[])
|
||||
// Handle all events currently in queue
|
||||
SDL_Event evt;
|
||||
while (SDL_PollEvent(&evt)) {
|
||||
#ifdef HOTRELOAD
|
||||
if (evt.type == SDL_KEYDOWN && evt.key.keysym.sym == SDLK_F5)
|
||||
load_game_lib();
|
||||
#endif
|
||||
if (game_evt(gamemem, &evt) != GAMESTATUS_OK)
|
||||
goto quit;
|
||||
}
|
||||
|
||||
@@ -21,14 +21,28 @@ typedef enum {
|
||||
GAMESTATUS_QUIT,
|
||||
} gamestatus_t;
|
||||
|
||||
typedef void
|
||||
game_init_t(int argc, char *argv[], void *mem, SDL_Renderer *renderer);
|
||||
typedef void game_teardown_t(void *mem);
|
||||
|
||||
typedef gamestatus_t game_evt_t(void *mem, const SDL_Event *evt);
|
||||
typedef gamestatus_t game_update_t(void *mem, double dt);
|
||||
|
||||
typedef void
|
||||
game_render_t(const void *mem, SDL_Renderer *renderer, long unsigned t);
|
||||
|
||||
#define HOOKS_XLIST \
|
||||
X(game_init) \
|
||||
X(game_teardown) \
|
||||
X(game_evt) \
|
||||
X(game_update) \
|
||||
X(game_render)
|
||||
|
||||
#ifndef HOTRELOAD
|
||||
extern const engineconf_t game_conf;
|
||||
|
||||
void game_init(int argc, char *argv[], void *mem, SDL_Renderer *renderer);
|
||||
void game_teardown(void *mem);
|
||||
|
||||
gamestatus_t game_evt(void *mem, const SDL_Event *evt);
|
||||
gamestatus_t game_update(void *mem, double dt);
|
||||
|
||||
void game_render(const void *mem, SDL_Renderer *renderer, long unsigned t);
|
||||
#define X(hook) hook##_t hook;
|
||||
HOOKS_XLIST
|
||||
#undef X
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user