From fc0c70ad611dab564bf13a24e8e32cfda81ab044 Mon Sep 17 00:00:00 2001 From: igor Date: Thu, 19 Mar 2026 15:54:13 -0700 Subject: [PATCH] Date 22 complete. --- Makefile | 3 +++ sdl_handmade.cpp | 69 +++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 63 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 02a1b55..5be5b21 100644 --- a/Makefile +++ b/Makefile @@ -47,6 +47,9 @@ libhandmade: handmade.cpp $(EXE): sdl_handmade.cpp libhandmade $(CC) $(FLAGS) $(UFLAGS) $(INCLUDE) sdl_handmade.cpp $(LIBS) $(FRAMEWORKS) -o $@ +run: + ./$(EXE) + tags: $(OBJS) ctags -R *.h *.c diff --git a/sdl_handmade.cpp b/sdl_handmade.cpp index 4232287..dacbb82 100644 --- a/sdl_handmade.cpp +++ b/sdl_handmade.cpp @@ -11,8 +11,12 @@ #include // fstat #include // open -#include // close, read +#include // close, read, readlink #include // dlopen +#include // stat +#if __APPLE__ && __MACH__ +#include +#endif // NOTE: This is so it compiles on ARM. #if __x86_64__ || __i386__ @@ -326,17 +330,34 @@ static F32 SDLGetSecondsElapsed(U64 Start, U64 End) typedef struct sdl_game_code { void *GameCodeDLL; + U32 DLLLastWriteTime; + void (*UpdateAndRender)(game_memory *, game_input *, game_offscreen_buffer *, game_sound_output_buffer *); B32 IsValid; } sdl_game_code; -static sdl_game_code SDLLoadGameCode() +static U32 GetLastWriteTime(const char *FileName) +{ + struct stat file_info = {0}; + + if(stat(FileName, &file_info) != 0) { + // TODO: Diagnostic. perror("stat failed"); + } + + return (U32)file_info.st_mtime; +} + +#define GAME_DLL_NAME "libhandmade.so" + +static sdl_game_code SDLLoadGameCode(char *DLLPath) { sdl_game_code Result = {0}; - Result.GameCodeDLL = dlopen("./libhandmade.so", RTLD_NOW); + Result.GameCodeDLL = dlopen(DLLPath, RTLD_NOW); if(Result.GameCodeDLL) { + Result.DLLLastWriteTime = GetLastWriteTime(DLLPath); + Result.UpdateAndRender = (void(*)(game_memory *, game_input *, game_offscreen_buffer *, game_sound_output_buffer *))dlsym(Result.GameCodeDLL, "UpdateAndRender"); if(!Result.UpdateAndRender) { // TODO: Diagnostic. dlerror() @@ -362,8 +383,40 @@ static void SDLUnloadGameCode(sdl_game_code *GameCode) GameCode->UpdateAndRender = NULL; } +char *GetExecutablePath() +{ + static char path[1024] = ""; // NOTE: We choose 1024 only because MacOS's MAXPATHLEN says such a value. + ssize_t size = (ssize_t)sizeof(path); // WARNING: size_t is usually an unsigned integer, whilst ssize_t is signed. We don't care because the path is not long. + +#if __APPLE__ && __MACH__ + if(_NSGetExecutablePath(path, &size) != 0) { // NOTE: Not an absolute path. + // TODO: Diagnostics. + } +#else + size = readlink("/proc/self/exe", path, size - 1); + if(size != -1) { + path[size] = '\0'; + } else { + // TODO: Diagnostics. + } +#endif + + return path; +} + S32 main(S32 argc, char *argv[]) { + char *path = GetExecutablePath(); + U32 len = strlen(path); + U32 i = len; + while(path[i] != '/' || i == 0) { + i--; + } + path[i+1] = '\0'; + + char game_dll_path[1024]; + snprintf(game_dll_path, sizeof(game_dll_path), "%s%s", path, GAME_DLL_NAME); + if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER | SDL_INIT_AUDIO)) { /* TODO: This didn't work . . . */ } @@ -431,8 +484,7 @@ S32 main(S32 argc, char *argv[]) U64 LastCycleCount; #endif - sdl_game_code Game = SDLLoadGameCode(); - U32 LoadCounter = 0; + sdl_game_code Game = SDLLoadGameCode(game_dll_path); while(GlobalRunning) { LastCounter = SDLGetWallClock(); @@ -445,12 +497,11 @@ S32 main(S32 argc, char *argv[]) S32 GameUpdateHz = MonitorRefreshHz / 2; F32 TargetSecondsPerFrame = 1.0f / (F32)GameUpdateHz; - if(LoadCounter > (U32)(GameUpdateHz * 2)) { + U32 NewDLLWriteTime = GetLastWriteTime(game_dll_path); + if(NewDLLWriteTime > Game.DLLLastWriteTime) { SDLUnloadGameCode(&Game); - Game = SDLLoadGameCode(); - LoadCounter = 0; + Game = SDLLoadGameCode(game_dll_path); } - LoadCounter++; game_controller_input *OldKeyboardController = GetController(OldInput, 0); game_controller_input *NewKeyboardController = GetController(NewInput, 0);