Created
August 8, 2021 02:56
-
-
Save gbrls/865c1415977765362ceb5b77cf603b71 to your computer and use it in GitHub Desktop.
Handmade hero hot reloading with sdl and linux
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define Kilobytes(x) ((x)*1024LL) | |
#define Megabytes(x) (Kilobytes(x)*(1024LL)) | |
#define Gigabytes(x) (Megabytes(x)*(1024LL)) | |
#define Terabytes(x) (Gigabytes(x)*(1024LL)) | |
#define u8 unsigned char | |
#define u32 unsigned int | |
struct game_memory { | |
u8* pixels; | |
u32 p_w; | |
u32 p_h; | |
u32 cnt; | |
}; | |
#define GAME_UPDATE_AND_RENDER(name) void name(game_memory* memory) | |
typedef GAME_UPDATE_AND_RENDER(game_update_and_render); | |
GAME_UPDATE_AND_RENDER(GameUpdateAndRenderStub) { | |
} | |
struct game_code { | |
void* dl; | |
game_update_and_render* UpdateAndRender; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include "game.h" | |
static const int B = 0; | |
static const int G = 1; | |
static const int R = 2; | |
// Use extern C to keep the function name from changing | |
extern "C" int update_and_render(game_memory* memory) { | |
for (int i = 0; i < memory->p_h; i++) { | |
for (int j = 0; j < memory->p_w; j++) { | |
u8* pixels = (u8*) memory->pixels; | |
pixels [ 4 * (i * memory->p_w + j) + R] = ~(memory->cnt / 2); | |
pixels [ 4 * (i * memory->p_w + j) + G] = (j * 32 + memory->cnt * 2); | |
pixels [ 4 * (i * memory->p_w + j) + B] = (i * 32 + memory->cnt / 2); | |
} | |
} | |
memory->cnt++; | |
return 10; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <SDL2/SDL.h> | |
#include <sys/mman.h> | |
#include <stdio.h> | |
#include <dlfcn.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include "game.h" | |
static SDL_Window* window = NULL; | |
static SDL_Surface* surf = NULL; | |
static void | |
start_OS_layer(game_memory* memory) { | |
if (SDL_Init(SDL_INIT_VIDEO) < 0) { | |
printf("Error initializing SDL: (%s)\n", SDL_GetError()); | |
} | |
window = SDL_CreateWindow("game", SDL_WINDOWPOS_UNDEFINED, | |
SDL_WINDOWPOS_UNDEFINED, 900, 600, | |
SDL_WINDOW_SHOWN); | |
if (!window) puts("Error creating window"); | |
surf = SDL_GetWindowSurface(window); | |
memory->pixels = (u8*) surf->pixels; | |
memory->p_w = surf->w; | |
memory->p_h = surf->h; | |
} | |
void LoadGameDL(game_code* code) { | |
if(code->dl != NULL) dlclose(code->dl); | |
SDL_Delay(100); | |
code->dl = dlopen("./file.so", RTLD_NOW | RTLD_GLOBAL); | |
if (code->dl == NULL) { | |
puts("Error opening DL"); | |
code->UpdateAndRender = GameUpdateAndRenderStub; | |
} else { | |
code->UpdateAndRender = (game_update_and_render*) dlsym(code->dl, "update_and_render"); | |
} | |
} | |
int | |
main() { | |
void* baseAddr = (void*) Terabytes(2); | |
size_t memSz = Gigabytes(1); | |
//@TODO: MAP_SHARED or MAP_PRIVATE? | |
void* mem = mmap(baseAddr, memSz, PROT_READ | PROT_WRITE, | |
MAP_FIXED | MAP_ANONYMOUS | MAP_SHARED, | |
0, 0); | |
if(mem == (void*) -1) { | |
puts("Err allocating mem"); | |
//@TODO: get errno | |
} | |
game_memory* memory = (game_memory*) mem; | |
game_code GameCode; | |
printf("baseAddr: %p\n", mem); | |
start_OS_layer(memory); | |
LoadGameDL(&GameCode); | |
SDL_Event e; | |
int quit = 0; | |
size_t t = 0; | |
struct stat st; | |
time_t old = {}; | |
while (!quit) { | |
while (SDL_PollEvent(&e)) { | |
if (e.type == SDL_QUIT) quit = true; | |
} | |
if (stat("./file.so", &st) != 0) { | |
puts("Err stat"); | |
} else { | |
if (st.st_ctime != old) { | |
old = st.st_ctime; | |
LoadGameDL(&GameCode); | |
} | |
} | |
SDL_UnlockSurface(surf); | |
GameCode.UpdateAndRender(memory); | |
SDL_UnlockSurface(surf); | |
SDL_UpdateWindowSurface(window); | |
} | |
if (munmap(mem, memSz)) { | |
puts("Err unmap"); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
nice