diff --git a/CMakeLists.txt b/CMakeLists.txt index 0229f37..326f1e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,7 +49,12 @@ add_subdirectory(third-party/libxm SYSTEM) if(LINUX) - set(SYSTEM_SOURCE_FILES src/system/linux/twn_elf.c) + set(SYSTEM_SOURCE_FILES + src/system/linux/twn_elf.c + $<$:src/game_object/twn_linux_game_object.c>) +elseif(WIN32) + set(SYSTEM_SOURCE_FILES + $<$:src/game_object/twn_win32_game_object.c>) else() set(SYSTEM_SOURCE_FILES) endif() @@ -80,7 +85,6 @@ set(TWN_SOURCE_FILES src/twn_util.c include/twn_util.h src/twn_input.c include/twn_input.h src/twn_camera.c include/twn_camera.h - src/twn_game_object.c src/twn_textures.c src/twn_textures_c.h src/rendering/twn_rendering.c src/rendering/twn_rendering_c.h @@ -90,7 +94,8 @@ set(TWN_SOURCE_FILES src/rendering/twn_circles.c # for dynamic load based solution main is compiled in a separate target - $<$>:src/twn_main.c> + $<$>:src/twn_main.c + src/game_object/twn_static_game_object.c> ${SYSTEM_SOURCE_FILES}) diff --git a/src/game_object/twn_linux_game_object_c.h b/src/game_object/twn_linux_game_object.c similarity index 94% rename from src/game_object/twn_linux_game_object_c.h rename to src/game_object/twn_linux_game_object.c index 4bd0f39..cc5442c 100644 --- a/src/game_object/twn_linux_game_object_c.h +++ b/src/game_object/twn_linux_game_object.c @@ -140,3 +140,10 @@ bool game_object_try_reloading(void) { 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 +} diff --git a/src/game_object/twn_static_game_object_c.h b/src/game_object/twn_static_game_object.c similarity index 58% rename from src/game_object/twn_static_game_object_c.h rename to src/game_object/twn_static_game_object.c index 9b7935e..931f142 100644 --- a/src/game_object/twn_static_game_object_c.h +++ b/src/game_object/twn_static_game_object.c @@ -19,3 +19,10 @@ bool game_object_try_reloading(void) { 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 +} diff --git a/src/game_object/twn_win32_game_object_c.h b/src/game_object/twn_win32_game_object.c similarity index 100% rename from src/game_object/twn_win32_game_object_c.h rename to src/game_object/twn_win32_game_object.c diff --git a/src/system/linux/twn_elf.c b/src/system/linux/twn_elf.c index 9696c2f..cd5e219 100644 --- a/src/system/linux/twn_elf.c +++ b/src/system/linux/twn_elf.c @@ -1,10 +1,13 @@ -#include "elf.h" +#include "twn_elf.h" +#include "twn_game_object_c.h" #include #include #include #include #include +#define __USE_GNU +#include #include #include @@ -17,10 +20,21 @@ bool infer_elf_section_bounds(const char *const restrict name, { bool result = false; char buf[PATH_MAX]; - ssize_t l = readlink("/proc/self/exe", buf, PATH_MAX); - if (l == -1) - goto ERR_CANT_READLINK; - buf[l] = 0; /* readlink() doesn't write a terminator */ + bool from_shared_object; + Dl_info info; + + if (!dladdr(game_object_get_game_tick_address(), &info)) { + /* statically linked */ + from_shared_object = false; + ssize_t l = readlink("/proc/self/exe", buf, PATH_MAX); + if (l == -1) + goto ERR_CANT_READLINK; + buf[l] = 0; /* readlink() doesn't write a terminator */ + } else { + /* dynamically linked */ + from_shared_object = true; + memcpy(buf, "libgame.so", sizeof "libgame.so"); + } int elf = open(buf, O_RDONLY); if (elf == -1) @@ -51,8 +65,15 @@ bool infer_elf_section_bounds(const char *const restrict name, if (strcmp(&sh[shdr.sh_name], name) == 0) { result = true; - *vm_start = getauxval(AT_ENTRY) - ehdr.e_entry + (char *)shdr.sh_addr; - *vm_end = getauxval(AT_ENTRY) - ehdr.e_entry + (char *)shdr.sh_addr + shdr.sh_size; + + if (!from_shared_object) { + *vm_start = getauxval(AT_ENTRY) - ehdr.e_entry + (char *)shdr.sh_addr; + *vm_end = getauxval(AT_ENTRY) - ehdr.e_entry + (char *)shdr.sh_addr + shdr.sh_size; + } else { + *vm_start = (uintptr_t)info.dli_fbase + (char *)shdr.sh_addr; + *vm_end = (uintptr_t)info.dli_fbase + (char *)shdr.sh_addr + shdr.sh_size; + } + break; } } diff --git a/src/twn_game_object.c b/src/twn_game_object.c deleted file mode 100644 index 1431033..0000000 --- a/src/twn_game_object.c +++ /dev/null @@ -1,12 +0,0 @@ -#if defined(TWN_FEATURE_DYNLIB_GAME) - #if defined(__linux__) - #include "game_object/twn_linux_game_object_c.h" - #elif defined(_WIN32) - #include "game_object/twn_win32_game_object_c.h" - #else - #warning "TWN_FEATURE_DYNLIB_GAME is set, but not supported" - #include "game_object/twn_static_game_object_c.h" - #endif -#else - #include "game_object/twn_static_game_object_c.h" -#endif diff --git a/src/twn_game_object_c.h b/src/twn_game_object_c.h index 2c50ad9..1d11cc9 100644 --- a/src/twn_game_object_c.h +++ b/src/twn_game_object_c.h @@ -18,5 +18,6 @@ bool game_object_try_reloading(void); void game_object_tick(void); +void *game_object_get_game_tick_address(void); #endif diff --git a/src/twn_textures.c b/src/twn_textures.c index cfdf915..ffd9fdc 100644 --- a/src/twn_textures.c +++ b/src/twn_textures.c @@ -413,7 +413,7 @@ void textures_update_atlas(struct texture_cache *cache) { } /* EXPERIMANTAL: LIKELY TO BE REMOVED! */ -#if defined(__linux__) && !defined(HOT_RELOAD_SUPPORT) /* use rodata elf section for fast lookups of repeating textures */ +#if defined(__linux__) /* use rodata elf section for fast lookups of repeating textures */ #include "system/linux/twn_elf.h"