ilimination of system code, removal of x-watcher and replacement of it by dmon, fixes in audio code, dynamic asset reload

This commit is contained in:
veclavtalica
2025-01-30 04:30:20 +03:00
parent 4b2a22bf3c
commit 74d7190c62
21 changed files with 2164 additions and 1427 deletions

View File

@ -0,0 +1,98 @@
#include "twn_game_object_c.h"
#include "twn_engine_context_c.h"
#include "twn_filewatch_c.h"
#include "twn_util_c.h"
#include "twn_util.h"
#include "twn_loop_c.h"
#include <SDL2/SDL.h>
#ifdef _WIN32
#define GAME_OBJECT_NAME "libgame.dll"
#else
#define GAME_OBJECT_NAME "libgame.so"
#endif
static void (*game_tick_callback)(void);
static void (*game_end_callback)(void);
static void *handle = NULL;
static void game_object_file_action(char const *path, enum FilewatchAction action) {
(void)action;
if (action == FILEWATCH_ACTION_FILE_DELETED)
return;
if (handle) {
SDL_UnloadObject(handle);
game_tick_callback = NULL;
game_end_callback = NULL;
handle = NULL;
}
handle = SDL_LoadObject(path);
if (!handle) {
CRY_SDL("Hot Reload Error: Cannot open game code shared object");
return;
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
game_tick_callback = (void (*)(void))SDL_LoadFunction(handle, "game_tick");
if (!game_tick_callback) {
CRY("Hot Reload Error", "game_tick_callback() symbol wasn't found");
goto ERR_GETTING_PROC;
}
game_end_callback = (void (*)(void))SDL_LoadFunction(handle, "game_end");
if (!game_end_callback) {
CRY("Hot Reload Error", "game_end_callback() symbol wasn't found");
goto ERR_GETTING_PROC;
}
#pragma GCC diagnostic pop
if (fabsf(0.0f - ctx.game.frame_number) > 0.00001f) {
log_info("Game object was reloaded\n");
reset_state();
}
return;
ERR_GETTING_PROC:
SDL_UnloadObject(handle);
handle = NULL;
game_tick_callback = NULL;
game_end_callback = NULL;
}
void game_object_load(void) {
static bool filewatch_attached;
if (!filewatch_attached) {
char *game_object_path;
SDL_asprintf(&game_object_path, "%s%s", ctx.base_dir, GAME_OBJECT_NAME);
filewatch_add_file(game_object_path, game_object_file_action);
game_object_file_action(game_object_path, FILEWATCH_ACTION_FILE_MODIFIED);
SDL_free(game_object_path);
filewatch_attached = true;
}
}
void game_object_unload(void) {
game_end_callback();
/* needs to be closed otherwise symbols aren't resolved again */
SDL_UnloadObject(handle);
game_tick_callback = NULL;
game_end_callback = NULL;
handle = NULL;
}
void game_object_tick(void) {
game_tick_callback();
}

View File

@ -1,161 +0,0 @@
#include "twn_game_object_c.h"
#include "twn_engine_context_c.h"
#include "twn_util_c.h"
#include "twn_util.h"
#include <x-watcher.h>
#include <SDL2/SDL.h>
#include <dlfcn.h>
#define GAME_OBJECT_NAME "libgame.so"
#define MODIFIED_TICKS_MERGED 10
static void (*game_tick_callback)(void);
static void (*game_end_callback)(void);
static x_watcher *watcher;
static void *handle = NULL;
static float last_tick_modified;
static bool loaded_after_modification = true;
static SDL_mutex *lock;
static char *game_object_path;
static void load_game_object(void) {
/* needs to be closed otherwise symbols aren't resolved again */
if (handle) {
dlclose(handle);
handle = NULL;
game_tick_callback = NULL;
game_end_callback = NULL;
}
void *new_handle = dlopen(game_object_path, RTLD_LAZY);
if (!new_handle) {
log_critical("Hot Reload Error: Cannot open game code shared object (%s)", dlerror());
goto ERR_OPENING_SO;
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
game_tick_callback = (void (*)(void))dlsym(new_handle, "game_tick");
if (!game_tick_callback) {
CRY("Hot Reload Error", "game_tick_callback() symbol wasn't found");
goto ERR_GETTING_PROC;
}
game_end_callback = (void (*)(void))dlsym(new_handle, "game_end");
if (!game_end_callback) {
CRY("Hot Reload Error", "game_end_callback() symbol wasn't found");
goto ERR_GETTING_PROC;
}
#pragma GCC diagnostic pop
handle = new_handle;
if (fabsf(0.0f - ctx.game.frame_number) > 0.00001f)
log_info("Game object was reloaded\n");
return;
ERR_GETTING_PROC:
dlclose(new_handle);
game_tick_callback = NULL;
game_end_callback = NULL;
ERR_OPENING_SO:
SDL_UnlockMutex(lock);
}
static void watcher_callback(XWATCHER_FILE_EVENT event,
const char *path,
int context,
void *data)
{
(void)context;
(void)path;
(void)data;
switch(event) {
case XWATCHER_FILE_CREATED:
case XWATCHER_FILE_MODIFIED:
SDL_LockMutex(lock);
last_tick_modified = ctx.game.frame_number;
loaded_after_modification = false;
SDL_UnlockMutex(lock);
break;
case XWATCHER_FILE_UNSPECIFIED:
case XWATCHER_FILE_REMOVED:
case XWATCHER_FILE_OPENED:
case XWATCHER_FILE_ATTRIBUTES_CHANGED:
case XWATCHER_FILE_NONE:
case XWATCHER_FILE_RENAMED:
default:
break;
}
}
void game_object_load(void) {
SDL_asprintf(&game_object_path, "%s%s", ctx.base_dir, GAME_OBJECT_NAME);
watcher = xWatcher_create();
xWatcher_reference dir;
dir.path = game_object_path;
dir.callback_func = watcher_callback;
xWatcher_appendFile(watcher, &dir);
xWatcher_start(watcher);
lock = SDL_CreateMutex();
load_game_object();
}
void game_object_unload(void) {
game_end_callback();
xWatcher_destroy(watcher);
watcher = NULL;
dlclose(handle);
handle = NULL;
game_tick_callback = NULL;
game_end_callback = NULL;
SDL_DestroyMutex(lock);
}
bool game_object_try_reloading(void) {
bool result = false;
/* only load the modified library after some time, as compilers make a lot of modifications */
SDL_LockMutex(lock);
if (ctx.game.frame_number - last_tick_modified > MODIFIED_TICKS_MERGED &&
!loaded_after_modification) {
load_game_object();
loaded_after_modification = true;
result = true;
} SDL_UnlockMutex(lock);
return result;
}
void game_object_tick(void) {
game_tick_callback();
}
void *game_object_get_game_tick_address(void) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
return (void *)&game_tick_callback;
#pragma GCC diagnostic pop
}

View File

@ -5,24 +5,10 @@
void game_object_load(void) {
}
void game_object_unload(void) {
game_end();
}
bool game_object_try_reloading(void) {
return false;
}
void game_object_tick(void) {
game_tick();
}
void *game_object_get_game_tick_address(void) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
return (void *)&game_tick;
#pragma GCC diagnostic pop
}

View File

@ -1,90 +0,0 @@
#include "twn_game_object_c.h"
#include "twn_engine_context_c.h"
#include "twn_util_c.h"
#include "twn_util.h"
#include <errhandlingapi.h>
#include <libloaderapi.h>
#define GAME_OBJECT_PATH "libgame.dll"
static void (*game_tick_callback)(void);
static void (*game_end_callback)(void);
static void *handle = NULL;
static void load_game_object(void) {
/* needs to be closed otherwise symbols aren't resolved again */
if (handle) {
FreeLibrary(handle);
handle = NULL;
game_tick_callback = NULL;
game_end_callback = NULL;
}
void *new_handle = LoadLibraryA(GAME_OBJECT_PATH);
if (!new_handle) {
log_critical("Hot Reload Error: Cannot open game code shared object (%s)", GetLastError());
goto ERR_OPENING_SO;
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
game_tick_callback = (void (*)(void))GetProcAddress(new_handle, "game_tick");
if (!game_tick_callback) {
CRY("Hot Reload Error", "game_tick_callback() symbol wasn't found");
goto ERR_GETTING_PROC;
}
game_end_callback = (void (*)(void))GetProcAddress(new_handle, "game_end");
if (!game_end_callback) {
CRY("Hot Reload Error", "game_end_callback() symbol wasn't found");
goto ERR_GETTING_PROC;
}
#pragma GCC diagnostic pop
handle = new_handle;
if (ctx.game.frame_number != 0)
log_info("Game object was reloaded\n");
return;
ERR_GETTING_PROC:
FreeLibrary(new_handle);
game_tick_callback = NULL;
game_end_callback = NULL;
ERR_OPENING_SO:
die_abruptly();
}
void game_object_load(void) {
load_game_object();
}
void game_object_unload(void) {
game_end_callback();
FreeLibrary(handle);
handle = NULL;
game_tick_callback = NULL;
game_end_callback = NULL;
}
/* doesn't support reloading because of problems with file watching */
bool game_object_try_reloading(void) {
return false;
}
void game_object_tick(void) {
game_tick_callback();
}