Skip to content

Instantly share code, notes, and snippets.

@gbrls
Created August 8, 2021 02:56
Show Gist options
  • Save gbrls/865c1415977765362ceb5b77cf603b71 to your computer and use it in GitHub Desktop.
Save gbrls/865c1415977765362ceb5b77cf603b71 to your computer and use it in GitHub Desktop.
Handmade hero hot reloading with sdl and linux
#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;
};
#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;
}
#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;
}
@vcnovaes
Copy link

vcnovaes commented Aug 8, 2021

nice

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment