summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmin Mesbah <mesbahamin@gmail.com>2017-11-12 23:44:15 -0800
committerAmin Mesbah <mesbahamin@gmail.com>2017-11-12 23:44:15 -0800
commitbf8ce781521b7eac2f95ea01895175ca661f2c3b (patch)
treeee4d164c44d1140ffc61857d363807ca899e9538
parent77656fe8dca89bf4953be96e186cf1ecd03fd889 (diff)
downloadohsp-features/live-reload.zip
ohsp-features/live-reload.tar.gz
Move linux-specific platform code to util_linux.hfeatures/live-reload
The plan is to include either util_linux.h or util_windows.h, which each supply platform-specific functions with the same signatures and names.
-rwxr-xr-xMakefile2
-rw-r--r--src/platform_sdl.c86
-rw-r--r--src/util_linux.h78
3 files changed, 88 insertions, 78 deletions
diff --git a/Makefile b/Makefile
index c912f3b..4331b6c 100755
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
CC = gcc
#TODO: add -Wpedantic back
CFLAGS = -std=c99 -Wall -Wextra -Wshadow -Wno-unused-parameter
-LDFLAGS = $(SDL_LDFLAGS) -lm
+LDFLAGS = $(SDL_LDFLAGS) -ldl -lm
SDL_CFLAGS := $(shell sdl2-config --cflags)
SDL_LDFLAGS := $(shell sdl2-config --libs)
diff --git a/src/platform_sdl.c b/src/platform_sdl.c
index c7227ee..d5daf4a 100644
--- a/src/platform_sdl.c
+++ b/src/platform_sdl.c
@@ -1,12 +1,14 @@
#include "platform_sdl.h"
+#ifdef __linux__
+#include "util_linux.h"
+#elif __WIN32
+#endif
+
#include <stdbool.h>
#include <stdio.h>
#include <time.h>
-// TODO: move to linux specific code
-#include <sys/stat.h>
-
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
@@ -16,76 +18,6 @@ extern bool PAUSED;
static struct SDLOffscreenBuffer global_back_buffer;
-time_t linux_file_get_modified_time(char *file_path)
-{
- time_t mtime = 0;
- struct stat file_status = {0};
- if (stat(file_path, &file_status) == 0)
- {
- //printf("File: %s last modified: %s\n", file_path, ctime(&file_status.st_mtime));
- mtime = file_status.st_mtime;
- }
- else
- {
- fprintf(stderr, "ERROR: Failed to stat file: %s\n", file_path);
- }
- return mtime;
-}
-
-
-void sdl_unload_game_code(struct SDLGameCode *game_code)
-{
- if (!game_code)
- {
- printf("Invalid pointer *game_code\n");
- return;
- }
-
- if (game_code->game_code_library)
- {
- SDL_UnloadObject(game_code->game_code_library);
- game_code->game_code_library = 0;
- }
- game_code->is_valid = false;
- game_code->game_update = 0;
- game_code->game_render = 0;
-}
-
-
-// TODO: Add backup dll in case loading fails
-struct SDLGameCode sdl_load_game_code(char *source_lib_path)
-{
- struct SDLGameCode game_code = {0};
-
- game_code.last_write_time = linux_file_get_modified_time(source_lib_path);
- if (game_code.last_write_time)
- {
- game_code.game_code_library = SDL_LoadObject(source_lib_path);
- if (game_code.game_code_library)
- {
- // NOTE: The C standard (as of C99) distinguishes function pointers
- // from object pointers (`void *` is an object pointer). Technically it
- // is undefined behavior to cast between these two pointer types. In
- // practice, it works on most modern platforms.
- //
- // In this case, we are protected by POSIX, which specifies that
- // function and data pointers must be the same size. We will only ever
- // be using SDL_LoadFunction on POSIX-compliant platforms.
- game_code.game_update = (game_update_t *) SDL_LoadFunction(game_code.game_code_library, "game_update");
- game_code.game_render = (game_render_t *) SDL_LoadFunction(game_code.game_code_library, "game_render");
- game_code.is_valid = (game_code.game_update && game_code.game_render);
- }
- }
-
- if (!game_code.is_valid)
- {
- fprintf(stderr, "ERROR: Game code is not valid: %s\n", SDL_GetError());
- }
-
- return game_code;
-}
-
-
struct SDLWindowDimension sdl_get_window_dimension(SDL_Window *window)
{
struct SDLWindowDimension result;
@@ -319,7 +251,7 @@ int main(int argc, char *argv[])
controller_input.right_stick_x = 0;
controller_input.right_stick_y = 0;
- struct SDLGameCode game_code = sdl_load_game_code(GAME_LIB_PATH);
+ struct SDLGameCode game_code = load_game_code(GAME_LIB_PATH);
while (running)
{
@@ -329,12 +261,12 @@ int main(int argc, char *argv[])
lag += elapsed_ms;
//printf("%" PRIu64 ", %" PRIu64 ", %f\n", elapsed_ms, lag, MS_PER_UPDATE);
- time_t last_write_time = linux_file_get_modified_time(GAME_LIB_PATH);
+ time_t last_write_time = file_get_modified_time(GAME_LIB_PATH);
bool game_code_has_changed = last_write_time && (last_write_time != game_code.last_write_time);
if (game_code_has_changed)
{
- sdl_unload_game_code(&game_code);
- game_code = sdl_load_game_code(GAME_LIB_PATH);
+ unload_game_code(&game_code);
+ game_code = load_game_code(GAME_LIB_PATH);
if (!game_code.is_valid)
{
// TODO: fall back to backup?
diff --git a/src/util_linux.h b/src/util_linux.h
new file mode 100644
index 0000000..4040a10
--- /dev/null
+++ b/src/util_linux.h
@@ -0,0 +1,78 @@
+#ifndef UTIL_LINUX_H
+#define UTIL_LINUX_H
+
+#include <dlfcn.h>
+#include <sys/stat.h>
+
+
+time_t file_get_modified_time(char *file_path)
+{
+ time_t mtime = 0;
+ struct stat file_status = {0};
+ if (stat(file_path, &file_status) == 0)
+ {
+ //printf("File: %s last modified: %s\n", file_path, ctime(&file_status.st_mtime));
+ mtime = file_status.st_mtime;
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Failed to stat file: %s\n", file_path);
+ }
+ return mtime;
+}
+
+
+void unload_game_code(struct SDLGameCode *game_code)
+{
+ if (!game_code)
+ {
+ printf("Invalid pointer *game_code\n");
+ return;
+ }
+
+ if (game_code->game_code_library)
+ {
+ dlclose(game_code->game_code_library);
+ game_code->game_code_library = 0;
+ }
+ game_code->is_valid = false;
+ game_code->game_update = 0;
+ game_code->game_render = 0;
+}
+
+
+// TODO: Add backup dll in case loading fails
+struct SDLGameCode load_game_code(char *source_lib_path)
+{
+ struct SDLGameCode game_code = {0};
+
+ game_code.last_write_time = file_get_modified_time(source_lib_path);
+ if (game_code.last_write_time)
+ {
+ game_code.game_code_library = dlopen(source_lib_path, RTLD_LAZY);
+ if (game_code.game_code_library)
+ {
+ // NOTE: The C standard (as of C99) distinguishes function pointers
+ // from object pointers (`void *` is an object pointer). Technically it
+ // is undefined behavior to cast between these two pointer types. In
+ // practice, it works on most modern platforms.
+ //
+ // In this case, we are protected by POSIX, which specifies that
+ // function and data pointers must be the same size. We will only ever
+ // be using dlsym on POSIX-compliant platforms.
+ game_code.game_update = (game_update_t *) dlsym(game_code.game_code_library, "game_update");
+ game_code.game_render = (game_render_t *) dlsym(game_code.game_code_library, "game_render");
+ game_code.is_valid = (game_code.game_update && game_code.game_render);
+ }
+ }
+
+ if (!game_code.is_valid)
+ {
+ fprintf(stderr, "ERROR: Game code is not valid: %s\n", dlerror());
+ }
+
+ return game_code;
+}
+
+
+#endif