summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAmin Mesbah <mesbahamin@gmail.com>2017-11-12 23:08:40 -0800
committerAmin Mesbah <mesbahamin@gmail.com>2017-11-12 23:08:40 -0800
commit77656fe8dca89bf4953be96e186cf1ecd03fd889 (patch)
tree47b3732caa91a9db21dc41182cff8eef77c6be97 /src
parent02e84b7d701f83d128b5779a3a15d53a37e2e2cf (diff)
downloadohsp-77656fe8dca89bf4953be96e186cf1ecd03fd889.zip
ohsp-77656fe8dca89bf4953be96e186cf1ecd03fd889.tar.gz
Load game code instantaneously on Linux
Stat is used to read the last modification time of the game.so file. It is loaded if that time is different from the time at last load. This means that it's loaded basically as soon as it's compiled. In the makefile I specified that the game code lib should be compiled to a temp, then copied to the actual .so file. This is because when I tried compiling directly to the .so, the platform would detect the change in the file's modified time, and would try to load it before compilation was complete.
Diffstat (limited to 'src')
-rw-r--r--src/game.c20
-rw-r--r--src/platform_sdl.c78
-rw-r--r--src/platform_sdl.h1
3 files changed, 61 insertions, 38 deletions
diff --git a/src/game.c b/src/game.c
index 83f89f1..e7f41fa 100644
--- a/src/game.c
+++ b/src/game.c
@@ -45,19 +45,19 @@ void game_update(struct GameState *game_state, struct GameControllerInput game_i
game_state->thrust_vector01.angle = atan2f(game_input.left_stick_y, game_input.left_stick_x);
game_state->thrust_vector01.length = hypotf(game_input.left_stick_x, game_input.left_stick_y);
- printf("(lx: %f, ly: %f, thrust_a: %f, thrust_l: %f)\n",
- game_input.left_stick_x,
- game_input.left_stick_y,
- game_state->thrust_vector01.angle,
- game_state->thrust_vector01.length);
+ //printf("(lx: %f, ly: %f, thrust_a: %f, thrust_l: %f)\n",
+ // game_input.left_stick_x,
+ // game_input.left_stick_y,
+ // game_state->thrust_vector01.angle,
+ // game_state->thrust_vector01.length);
game_state->thrust_vector02.angle = atan2f(game_input.right_stick_y, game_input.right_stick_x);
game_state->thrust_vector02.length = hypotf(game_input.right_stick_x, game_input.right_stick_y);
- printf("(rx: %f, ry: %f, thrust_a: %f, thrust_l: %f)\n",
- game_input.right_stick_x,
- game_input.right_stick_y,
- game_state->thrust_vector02.angle,
- game_state->thrust_vector02.length);
+ //printf("(rx: %f, ry: %f, thrust_a: %f, thrust_l: %f)\n",
+ // game_input.right_stick_x,
+ // game_input.right_stick_y,
+ // game_state->thrust_vector02.angle,
+ // game_state->thrust_vector02.length);
game_state->thrust_vector_sum = vec2d_add(
game_state->thrust_vector01.angle,
diff --git a/src/platform_sdl.c b/src/platform_sdl.c
index 9c1cd2c..c7227ee 100644
--- a/src/platform_sdl.c
+++ b/src/platform_sdl.c
@@ -4,6 +4,9 @@
#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
@@ -13,6 +16,23 @@ 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)
@@ -27,36 +47,39 @@ void sdl_unload_game_code(struct SDLGameCode *game_code)
game_code->game_code_library = 0;
}
game_code->is_valid = false;
- // TODO: see if we need to set these function pointers to stubs (hmh021)
game_code->game_update = 0;
game_code->game_render = 0;
}
-// TODO: Add temp dll in case loading fails
+// TODO: Add backup dll in case loading fails
struct SDLGameCode sdl_load_game_code(char *source_lib_path)
{
- struct SDLGameCode game_code;
- game_code.is_valid = false;
- game_code.game_code_library = 0;
- game_code.game_update = 0;
- game_code.game_render = 0;
-
- game_code.game_code_library = SDL_LoadObject(source_lib_path);
- if (game_code.game_code_library)
+ struct SDLGameCode game_code = {0};
+
+ game_code.last_write_time = linux_file_get_modified_time(source_lib_path);
+ if (game_code.last_write_time)
{
- // 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.
- 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);
+ 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)
{
- printf("Game code is not valid: %s\n", SDL_GetError());
+ fprintf(stderr, "ERROR: Game code is not valid: %s\n", SDL_GetError());
}
return game_code;
@@ -296,9 +319,7 @@ int main(int argc, char *argv[])
controller_input.right_stick_x = 0;
controller_input.right_stick_y = 0;
- // TODO: Make this not hard-coded
- struct SDLGameCode game_code = sdl_load_game_code("./release/game.so");
- int counter = 0;
+ struct SDLGameCode game_code = sdl_load_game_code(GAME_LIB_PATH);
while (running)
{
@@ -308,15 +329,16 @@ int main(int argc, char *argv[])
lag += elapsed_ms;
//printf("%" PRIu64 ", %" PRIu64 ", %f\n", elapsed_ms, lag, MS_PER_UPDATE);
- if (counter < 500)
- {
- ++counter;
- }
- else
+ time_t last_write_time = linux_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("./release/game.so");
- counter = 0;
+ game_code = sdl_load_game_code(GAME_LIB_PATH);
+ if (!game_code.is_valid)
+ {
+ // TODO: fall back to backup?
+ }
}
SDL_Event event;
diff --git a/src/platform_sdl.h b/src/platform_sdl.h
index 98cc700..bcb8ad5 100644
--- a/src/platform_sdl.h
+++ b/src/platform_sdl.h
@@ -5,6 +5,7 @@
#include <stdbool.h>
+#define GAME_LIB_PATH "./release/game.so"
#define MAX_CONTROLLERS 4
#define DEADZONE_THRESHOLD 9000