Implement hot reloading

This commit is contained in:
2025-01-05 19:41:44 +00:00
parent 1531817dc4
commit 2077ecde63
6 changed files with 100 additions and 13 deletions

View File

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

View File

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

View File

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