diff --git a/CMakeLists.txt b/CMakeLists.txt index d977eb1..19d00a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -173,14 +173,14 @@ function(give_options_without_warnings target) ${BUILD_FLAGS} $<$:${BUILD_FLAGS_RELEASE}> $<$:${BUILD_FLAGS_DEBUG}> - $<$:-Wl,-rpath,./>) + $<$:-Wl,-rpath,$ORIGIN/>) target_link_options(${target} PUBLIC ${BUILD_FLAGS} # -Wl,--no-undefined # TODO: use later for implementing no-libc $<$:${BUILD_FLAGS_RELEASE}> $<$:${BUILD_FLAGS_DEBUG}> - $<$:-Wl,-rpath,./>) + $<$:-Wl,-rpath,$ORIGIN/>) target_compile_definitions(${target} PUBLIC ORGANIZATION_NAME="${ORGANIZATION_NAME}" diff --git a/src/game_object/twn_linux_game_object.c b/src/game_object/twn_linux_game_object.c index cc5442c..fb1afca 100644 --- a/src/game_object/twn_linux_game_object.c +++ b/src/game_object/twn_linux_game_object.c @@ -7,7 +7,7 @@ #include -#define GAME_OBJECT_PATH "./libgame.so" +#define GAME_OBJECT_NAME "libgame.so" #define MODIFIED_TICKS_MERGED 10 @@ -21,6 +21,7 @@ static uint64_t 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 */ @@ -31,7 +32,7 @@ static void load_game_object(void) { game_end_callback = NULL; } - void *new_handle = dlopen(GAME_OBJECT_PATH, RTLD_LAZY); + 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; @@ -95,10 +96,12 @@ static void watcher_callback(XWATCHER_FILE_EVENT event, 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.path = game_object_path; dir.callback_func = watcher_callback; xWatcher_appendFile(watcher, &dir); diff --git a/src/system/linux/twn_elf.c b/src/system/linux/twn_elf.c index cd5e219..244fa12 100644 --- a/src/system/linux/twn_elf.c +++ b/src/system/linux/twn_elf.c @@ -1,5 +1,6 @@ #include "twn_elf.h" #include "twn_game_object_c.h" +#include "twn_engine_context_c.h" #include #include @@ -9,6 +10,8 @@ #define __USE_GNU #include +#include + #include #include #include @@ -33,7 +36,8 @@ bool infer_elf_section_bounds(const char *const restrict name, } else { /* dynamically linked */ from_shared_object = true; - memcpy(buf, "libgame.so", sizeof "libgame.so"); + if (SDL_snprintf(buf, sizeof buf, "%s%s", ctx.base_dir, "libgame.so") < 0) + goto ERR_CANT_APPEND_BASE_PATH; } int elf = open(buf, O_RDONLY); @@ -84,6 +88,7 @@ ERR_NOT_ELF: close(elf); ERR_CANT_OPEN_SELF: +ERR_CANT_APPEND_BASE_PATH: ERR_CANT_READLINK: return result; } diff --git a/src/twn_engine_context_c.h b/src/twn_engine_context_c.h index 6e6ecbc..496b929 100644 --- a/src/twn_engine_context_c.h +++ b/src/twn_engine_context_c.h @@ -21,6 +21,8 @@ typedef struct EngineContext { /* the program's actual argc and argv */ int argc; char **argv; + /* where the app was run from, used as the root for packs */ + char *base_dir; /* configuration */ toml_table_t *config_table; diff --git a/src/twn_loop.c b/src/twn_loop.c index de12118..9f62e93 100644 --- a/src/twn_loop.c +++ b/src/twn_loop.c @@ -232,7 +232,7 @@ static void resolve_pack_dependencies(const char *pack_name) { } char *dep_pack_name; - if (SDL_asprintf(&dep_pack_name, "%s.btw", dep_name.u.s) == -1) { + if (SDL_asprintf(&dep_pack_name, "%s%s.btw", ctx.base_dir, dep_name.u.s) == -1) { CRY("resolve_pack_dependencies()", "Allocation error"); SDL_free(dep_name.u.s); goto ERR_DEP_PATH_ALLOC_FAIL; @@ -249,12 +249,21 @@ static void resolve_pack_dependencies(const char *pack_name) { continue; } - if (!PHYSFS_mount(dep_source.u.s, "/", true)) + char *dep_source_path; + if (SDL_asprintf(&dep_source_path, "%s%s", ctx.base_dir, dep_source.u.s) == -1) { + CRY("resolve_pack_dependencies()", "Allocation error"); + SDL_free(dep_name.u.s); + SDL_free(dep_pack_name); + goto ERR_DEP_PATH_ALLOC_FAIL; + } + + if (!PHYSFS_mount(dep_source_path, "/", true)) CRY("Cannot load pack", "Nothing is given to work with"); log_info("Pack loaded: %s\n", dep_source.u.s); SDL_free(dep_source.u.s); + SDL_free(dep_source_path); } else log_info("Pack loaded: %s\n", dep_pack_name); @@ -638,6 +647,7 @@ static void clean_up(void) { toml_free(ctx.config_table); PHYSFS_deinit(); + SDL_free(ctx.base_dir); SDL_GL_DeleteContext(ctx.gl_context); SDL_Quit(); } @@ -652,6 +662,7 @@ static void reset_state(void) { int enter_loop(int argc, char **argv) { ctx.argc = argc; ctx.argv = argv; + ctx.base_dir = SDL_GetBasePath(); /* needs to be done before anything else so config can be loaded */ /* TODO: ANDROID: see the warning in physicsfs PHYSFS_init docs/header */ @@ -699,11 +710,17 @@ int enter_loop(int argc, char **argv) { /* data path not explicitly specified, look into convention defined places */ if (!data_dir_mounted) { /* try mouning data folder first, relative to executable root */ - if (!PHYSFS_mount("data", NULL, true)) { - if (!PHYSFS_mount("data.btw", NULL, true)) + char *full_path; + SDL_asprintf(&full_path, "%sdata", ctx.base_dir); + if (!PHYSFS_mount(full_path, NULL, true)) { + SDL_free(full_path); + SDL_asprintf(&full_path, "%sdata.btw", ctx.base_dir); + if (!PHYSFS_mount(full_path, NULL, true)) + SDL_free(full_path); CRY_PHYSFS("Cannot find data.btw or data directory in root. Please create them or specify with --data-dir parameter."); return EXIT_FAILURE; } + SDL_free(full_path); } if (!initialize())