From 4b63f9149495d977929ac3aac523df547c53c413 Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Wed, 10 Jan 2024 11:42:02 +0700 Subject: [PATCH] Hot reloading: Finally got it working with the `stat` syscall --- boids_game.c | 16 ++++++-- boids_main.c | 111 ++++++++++++++------------------------------------- hours.org | 2 +- 3 files changed, 43 insertions(+), 86 deletions(-) diff --git a/boids_game.c b/boids_game.c index 1230fd5..2e8e87a 100644 --- a/boids_game.c +++ b/boids_game.c @@ -5,8 +5,10 @@ #include "boids_game.h" #include "lib.h" -#define SCREEN_WIDTH 1300 -#define SCREEN_HEIGHT 1080 +// #define SCREEN_WIDTH 1300 +// #define SCREEN_HEIGHT 1080 +#define SCREEN_WIDTH 800 +#define SCREEN_HEIGHT 600 typedef struct Boid { Point position; @@ -25,6 +27,13 @@ typedef struct GameState { static GameState *init() { InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Boids"); + int monitor = GetCurrentMonitor(); + int monitor_width = GetMonitorWidth(monitor); + // int monitor_height = GetMonitorHeight(monitor); + int win_pos_x = monitor_width - SCREEN_WIDTH - 7; + int win_pos_y = 30; + SetWindowPosition(win_pos_x, win_pos_y); + SetTargetFPS(60); GameState *state = malloc(sizeof(struct GameApi)); @@ -99,7 +108,6 @@ static int step(GameState *state) { boid->position = Vector2Add(boid->position, boid->velocity); } - // Update BeginDrawing(); { @@ -113,7 +121,7 @@ static int step(GameState *state) { DrawCircle(boid->position.x, boid->position.y, 27, BLACK); DrawCircle(boid->position.x, boid->position.y, 20, GREEN); } - + DrawFPS(SCREEN_WIDTH - 80, 10); } EndDrawing(); return return_int; diff --git a/boids_main.c b/boids_main.c index 55d76fe..0d0adeb 100644 --- a/boids_main.c +++ b/boids_main.c @@ -2,10 +2,8 @@ #include #include #include +#include #include -#include -#include -// #include "inotify-syscalls.h" #include "include/raylib.h" #include "include/raymath.h" #include "boids_game.h" @@ -15,11 +13,11 @@ #define TARGET_FPS 60 const char* GAME_LIB = "./libboids.so"; -char epoll_buf[1024]; +char inotify_buf[1024]; -struct Game -{ +struct Game { void* handle; + ino_t gamelib_id; struct GameApi api; struct GameState* state; }; @@ -27,92 +25,43 @@ struct Game #define MAX_EVENTS 1 void load_game(struct Game* game) { - if (game->handle) { - game->api.unload(game->state); - dlclose(game->handle); - } - void* handle = dlopen(GAME_LIB, RTLD_NOW); - - if (handle) { - game->handle = handle; - const struct GameApi* api = dlsym(game->handle, "GAME_API"); - if (api != NULL) { - printf("Loaded API, calling init()\n"); - game->api = *api; - if (game->state == NULL) { - game->state = game->api.init(); - } - game->api.reload(game->state); - } else { - printf("Failed to load API\n"); + struct stat attr; + if ((stat(GAME_LIB, &attr) == 0) && (game->gamelib_id != attr.st_ino)) { + if (game->handle) { + game->api.unload(game->state); dlclose(game->handle); } - } else { - fprintf(stderr, "Error loading %s\n", GAME_LIB); - fprintf(stderr, "Error was: %s\n", dlerror()); - exit(1); + void* handle = dlopen(GAME_LIB, RTLD_NOW); + if (handle) { + game->handle = handle; + game->gamelib_id = attr.st_ino; + const struct GameApi* api = dlsym(game->handle, "GAME_API"); + if (api != NULL) { + printf("Loaded API, calling init()\n"); + game->api = *api; + if (game->state == NULL) { + game->state = game->api.init(); + } + game->api.reload(game->state); + } else { + printf("Failed to load API\n"); + dlclose(game->handle); + } + } else { + fprintf(stderr, "Error loading %s\n", GAME_LIB); + fprintf(stderr, "Error was: %s\n", dlerror()); + exit(1); + } } } int main(void) { - int fd = inotify_init(); - if (fd < 0) { - fprintf(stderr, "Error initializing inotify\n"); - } - int wd; - wd = inotify_add_watch(fd, GAME_LIB, IN_MODIFY); - - // create epoll instance - int epollfd = epoll_create1(0); - if (epollfd == -1) { - fprintf(stderr, "Error creating epoll instance\n"); - } - - struct epoll_event event; - event.events = EPOLLIN; - event.data.fd = fd; - - if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event) == -1) { - fprintf(stderr, "Error adding inotify descriptor to epoll\n"); - } - - struct epoll_event events[MAX_EVENTS]; - struct Game game = {0}; - load_game(&game); int should_exit = 0; while (should_exit != 1) { - int nfds = epoll_wait(epollfd, events, MAX_EVENTS, 0); - if (nfds == -1) { - fprintf(stderr, "epoll_wait failed\n"); - break; - } - - // printf("%d %d\n", nfds, fd); - for (int n = 0; n < nfds; ++n) { - // printf("DO I EVER GET CALLED\n", events[n].data.fd, fd); - printf("DO I EVER GET CALLED\n"); - if (events[n].data.fd == fd) { - printf("SO has been updated!\n"); - // This clears the inotify queue so we don't get any more events - read(fd, epoll_buf, sizeof(epoll_buf)); - load_game(&game); - } - } - + load_game(&game); should_exit = game.api.step(game.state); - if (should_exit == 2) { - printf("I should exit?\n"); - load_game(&game); - should_exit = 0; - usleep(1000); - } } - game.api.finalize(game.state); free(game.state); - inotify_rm_watch(fd, wd); - close(fd); - close(epollfd); - // CloseWindow(); } diff --git a/hours.org b/hours.org index c5d6fe4..99a778d 100644 --- a/hours.org +++ b/hours.org @@ -22,5 +22,5 @@ CLOCK: [2024-01-09 Tue 10:45]--[2024-01-09 Tue 11:15] => 0:30 :END: ** <2024-01-10 Wed> :LOGBOOK: -CLOCK: [2024-01-10 Wed 08:10] +CLOCK: [2024-01-10 Wed 08:10]--[2024-01-10 Wed 09:40] => 1:30 :END: