Compare commits

..

5 Commits

Author SHA1 Message Date
63b53f0cdd update hiload 2025-05-06 22:51:05 +03:00
3fd1903147 add some comments to main 2025-05-06 22:45:12 +03:00
85b7140f11 turn HiisiEngine into a regular solib instead of built module 2025-05-06 21:27:16 +03:00
55e89cd54f remove old heload 2025-05-06 21:03:01 +03:00
5d362d4237 add heload, mid commit 2025-03-13 21:21:14 +02:00
8 changed files with 80 additions and 166 deletions

3
.gitmodules vendored
View File

@@ -1,3 +1,6 @@
[submodule "3rd/SDL"] [submodule "3rd/SDL"]
path = 3rd/SDL path = 3rd/SDL
url = https://github.com/libsdl-org/SDL.git url = https://github.com/libsdl-org/SDL.git
[submodule "hiload"]
path = hiload
url = git@git.kitemoonsche.me:schme/hiload.git

View File

@@ -1,16 +1,14 @@
cmake_minimum_required(VERSION 3.21) cmake_minimum_required(VERSION 3.21)
project(Hiisi) project(Hiisi)
# I just like to have this with my tooling
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
add_subdirectory(3rd/SDL EXCLUDE_FROM_ALL) add_subdirectory(3rd/SDL EXCLUDE_FROM_ALL)
add_subdirectory(hiload)
add_subdirectory(hiisi) add_subdirectory(hiisi)
target_link_options(SDL3-shared PRIVATE -Wl,-z,nodelete)
add_executable(hiisi-run add_executable(hiisi-run
hiisi/main.cpp) hiisi/main.cpp)
target_link_libraries(hiisi-run) target_link_libraries(hiisi-run hiisi-engine hiload)

View File

@@ -5,6 +5,8 @@ add_library(hiisi-engine SHARED
hiisi.h hiisi.h
hiisi.cpp) hiisi.cpp)
target_compile_options(hiisi-engine PRIVATE "-Wall" "-Wextra" "-Wpedantic")
set_property(TARGET hiisi-engine PROPERTY POSITION_INDEPENDENT_CODE ON) set_property(TARGET hiisi-engine PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET hiisi-engine PROPERTY LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}) set_property(TARGET hiisi-engine PROPERTY LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR})

View File

@@ -1,14 +1,16 @@
#include "hiisi.h" #include "hiisi.h"
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#define WINDOW_WIDTH 1280 #define WINDOW_WIDTH 1280
#define WINDOW_HEIGHT 720 #define WINDOW_HEIGHT 720
/* This function runs once at startup. */ /* This function runs once at startup. */
int init(EngineData *state, int argc, char *argv[]) int HiisiEngine::init(int argc, char *argv[]) {
{ (void)argc;
(void)argv;
SDL_SetAppMetadata("Hiisi Engine", "0.0.1", "me.kitemoonsche.hiisi-engine"); SDL_SetAppMetadata("Hiisi Engine", "0.0.1", "me.kitemoonsche.hiisi-engine");
SDL_Window *window = 0; SDL_Window *window = 0;
@@ -19,44 +21,46 @@ int init(EngineData *state, int argc, char *argv[])
return SDL_APP_FAILURE; return SDL_APP_FAILURE;
} }
if (!SDL_CreateWindowAndRenderer("Hiisi Engine", WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer)) { if (!SDL_CreateWindowAndRenderer("Hiisi Engine", WINDOW_WIDTH,
WINDOW_HEIGHT, 0, &window, &renderer)) {
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
return SDL_APP_FAILURE; return SDL_APP_FAILURE;
} }
state->window = window; _window = window;
state->renderer = renderer; _renderer = renderer;
return SDL_APP_CONTINUE; /* carry on with the program! */ return SDL_APP_CONTINUE; /* carry on with the program! */
} }
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */ /* This function runs when a new event (mouse input, keypresses, etc) occurs. */
int event(EngineData* state) int HiisiEngine::event() {
{
SDL_Event event; SDL_Event event;
while (SDL_PollEvent(&event)) { while (SDL_PollEvent(&event)) {
if (event.type == SDL_EVENT_QUIT) { if (event.type == SDL_EVENT_QUIT) {
return 0; /* end the program, reporting success to the OS. */ return 0; /* end the program, reporting success to the OS. */
} }
} }
return 1; /* carry on with the program! */ return 1; /* carry on with the program! */
} }
/* This function runs once per frame, and is the heart of the program. */ /* This function runs once per frame, and is the heart of the program. */
int iterate(EngineData *state) int HiisiEngine::iterate() {
{ SDL_Renderer *renderer = (SDL_Renderer *)_renderer;
SDL_Renderer *renderer = (SDL_Renderer*)state->renderer;
SDL_FRect rects[16]; SDL_FRect rects[16];
const Uint64 now = SDL_GetTicks(); const Uint64 now = SDL_GetTicks();
int i; size_t i;
/* we'll have the rectangles grow and shrink over a few seconds. */ /* we'll have the rectangles grow and shrink over a few seconds. */
const float direction = ((now % 2000) >= 1000) ? 1.0f : -1.0f; const float direction = ((now % 2000) >= 1000) ? 1.0f : -1.0f;
const float scale = ((float) (((int) (now % 1000)) - 500) / 500.0f) * direction; const float scale =
((float)(((int)(now % 1000)) - 500) / 500.0f) * direction;
/* as you can see from this, rendering draws over whatever was drawn before it. */ /* as you can see from this, rendering draws over whatever was drawn before
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); /* black, full alpha */ * it. */
SDL_RenderClear(renderer); /* start with a blank canvas. */ SDL_SetRenderDrawColor(renderer, 0, 0, 0,
SDL_ALPHA_OPAQUE); /* black, full alpha */
SDL_RenderClear(renderer); /* start with a blank canvas. */
/* Rectangles are comprised of set of X and Y coordinates, plus width and /* Rectangles are comprised of set of X and Y coordinates, plus width and
height. (0, 0) is the top left of the window, and larger numbers go height. (0, 0) is the top left of the window, and larger numbers go
@@ -66,47 +70,49 @@ int iterate(EngineData *state)
/* Let's draw a single rectangle (square, really). */ /* Let's draw a single rectangle (square, really). */
rects[0].x = rects[0].y = 100; rects[0].x = rects[0].y = 100;
rects[0].w = rects[0].h = 100 + (100 * scale); rects[0].w = rects[0].h = 100 + (100 * scale);
SDL_SetRenderDrawColor(renderer, 250, 0, 255, SDL_ALPHA_OPAQUE); /* red, full alpha */ SDL_SetRenderDrawColor(renderer, 250, 0, 255,
SDL_ALPHA_OPAQUE); /* red, full alpha */
SDL_RenderRect(renderer, &rects[0]); SDL_RenderRect(renderer, &rects[0]);
/* Now let's draw several rectangles with one function call. */ /* Now let's draw several rectangles with one function call. */
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
const float size = (i+1) * 500.0f; const float size = (i + 1) * 500.0f;
rects[i].w = rects[i].h = size + (size * scale); rects[i].w = rects[i].h = size + (size * scale);
rects[i].x = (WINDOW_WIDTH - rects[i].w) / 2; /* center it. */ rects[i].x = (WINDOW_WIDTH - rects[i].w) / 2; /* center it. */
rects[i].y = (WINDOW_HEIGHT - rects[i].h) / 2; /* center it. */ rects[i].y = (WINDOW_HEIGHT - rects[i].h) / 2; /* center it. */
} }
SDL_SetRenderDrawColor(renderer, 255, 255, 0, SDL_ALPHA_OPAQUE); /* green, full alpha */ SDL_SetRenderDrawColor(renderer, 255, 255, 0,
SDL_RenderRects(renderer, rects, 3); /* draw three rectangles at once */ SDL_ALPHA_OPAQUE); /* green, full alpha */
SDL_RenderRects(renderer, rects, 3); /* draw three rectangles at once */
/* those were rectangle _outlines_, really. You can also draw _filled_ rectangles! */ /* those were rectangle _outlines_, really. You can also draw _filled_
* rectangles! */
rects[0].x = 400; rects[0].x = 400;
rects[0].y = 50; rects[0].y = 50;
rects[0].w = 100 + (100 * scale); rects[0].w = 100 + (100 * scale);
rects[0].h = 50 + (50 * scale); rects[0].h = 50 + (50 * scale);
SDL_SetRenderDrawColor(renderer, 50, 25, 255, SDL_ALPHA_OPAQUE); /* blue, full alpha */ SDL_SetRenderDrawColor(renderer, 50, 25, 255,
SDL_ALPHA_OPAQUE); /* blue, full alpha */
SDL_RenderFillRect(renderer, &rects[0]); SDL_RenderFillRect(renderer, &rects[0]);
/* ...and also fill a bunch of rectangles at once... */ /* ...and also fill a bunch of rectangles at once... */
for (i = 0; i < SDL_arraysize(rects); i++) { for (i = 0; i < SDL_arraysize(rects); i++) {
const float w = (float) (WINDOW_WIDTH / SDL_arraysize(rects)); const float w = (float)(WINDOW_WIDTH / SDL_arraysize(rects));
const float h = i * 8.0f; const float h = i * 8.0f;
rects[i].x = i * w; rects[i].x = i * w;
rects[i].y = WINDOW_HEIGHT - h; rects[i].y = WINDOW_HEIGHT - h;
rects[i].w = w; rects[i].w = w;
rects[i].h = h; rects[i].h = h;
} }
SDL_SetRenderDrawColor(renderer, 25, 255, 255, SDL_ALPHA_OPAQUE); /* white, full alpha */ SDL_SetRenderDrawColor(renderer, 25, 255, 255,
SDL_ALPHA_OPAQUE); /* white, full alpha */
SDL_RenderFillRects(renderer, rects, SDL_arraysize(rects)); SDL_RenderFillRects(renderer, rects, SDL_arraysize(rects));
SDL_RenderPresent(renderer); /* put it all on the screen! */ SDL_RenderPresent(renderer); /* put it all on the screen! */
return SDL_APP_CONTINUE; /* carry on with the program! */ return SDL_APP_CONTINUE; /* carry on with the program! */
} }
/* This function runs once at shutdown. */ /* This function runs once at shutdown. */
void quit(EngineData *state) void HiisiEngine::quit() { /* SDL will clean up the window/renderer for us. */
{
/* SDL will clean up the window/renderer for us. */
} }

View File

@@ -1,25 +1,17 @@
#ifndef HIISI_H_ #ifndef HIISI_H_
#define HIISI_H_ #define HIISI_H_
extern "C" { class HiisiEngine {
public:
int init(int argc, char *argv[]);
int event();
int iterate();
void quit();
struct EngineData { private:
void *window = 0; void *_window = 0;
void *renderer = 0; void *_renderer = 0;
}; void *_module = 0;
};
struct Engine {
void *module = 0;
int (*init)(EngineData *, int, char**);
int (*event)(EngineData *);
int (*iterate)(EngineData *);
void (*quit)(EngineData *);
};
int init(EngineData *state, int argc, char *argv[]);
int event(EngineData *state);
int iterate(EngineData *state);
void quit(EngineData *state);
}
#endif // HIISI_H_ #endif // HIISI_H_

View File

@@ -1,114 +1,37 @@
#include "hiisi.h" #include "hiisi.h"
#include "hiload.h"
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <atomic>
#include <stdlib.h>
#include <dlfcn.h> #include <dlfcn.h>
#include <link.h> #include <link.h>
#include <signal.h> #include <signal.h>
#include <atomic> #include <stdio.h>
#include <stdlib.h>
std::atomic<bool> reload_requested(false);
void reload_signal_handler(int) {
reload_requested = true;
}
Engine load_hiisi() {
const char *name = "build/hiisi/libhiisi-engine.so";
void *mod = dlopen(name, RTLD_NOW);
Lmid_t list;
dlinfo(mod, RTLD_DI_LMID, &list);
printf("link-map list id: %ld\n", list);
link_map *lmap = 0;
dlinfo(mod, RTLD_DI_LINKMAP, &lmap);
printf("Link map:\n");
printf("addr: %lu\n", lmap->l_addr);
printf("name: %s\n", lmap->l_name);
printf("dynamic section: %p\n", lmap->l_ld);
char pathname[256];
dlinfo(mod, RTLD_DI_ORIGIN, pathname);
printf("path: %s\n", pathname);
/* Discover the size of the buffer that we must pass to
RTLD_DI_SERINFO. */
Dl_serinfo serinfo;
Dl_serinfo *sip;
if (dlinfo(mod, RTLD_DI_SERINFOSIZE, &serinfo) == -1) {
fprintf(stderr, "RTLD_DI_SERINFOSIZE failed: %s\n", dlerror());
exit(EXIT_FAILURE);
}
/* Allocate the buffer for use with RTLD_DI_SERINFO. */
sip = (Dl_serinfo*)malloc(serinfo.dls_size);
if (sip == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
/* Initialize the 'dls_size' and 'dls_cnt' fields in the newly
allocated buffer. */
if (dlinfo(mod, RTLD_DI_SERINFOSIZE, sip) == -1) {
fprintf(stderr, "RTLD_DI_SERINFOSIZE failed: %s\n", dlerror());
exit(EXIT_FAILURE);
}
/* Fetch and print library search list. */
if (dlinfo(mod, RTLD_DI_SERINFO, sip) == -1) {
fprintf(stderr, "RTLD_DI_SERINFO failed: %s\n", dlerror());
exit(EXIT_FAILURE);
}
for (size_t j = 0; j < serinfo.dls_cnt; j++)
printf("dls_serpath[%zu].dls_name = %s\n",
j, sip->dls_serpath[j].dls_name);
Engine engine;
engine.module = mod;
*(void **)&engine.init = dlsym(mod, "init");
*(void **)&engine.event = dlsym(mod, "event");
*(void **)&engine.iterate = dlsym(mod, "iterate");
*(void **)&engine.quit = dlsym(mod, "quit");
assert(engine.init);
assert(engine.event);
assert(engine.iterate);
assert(engine.quit);
return engine;
}
int main(int argc, char **argv) { int main(int argc, char **argv) {
signal(SIGUSR1, reload_signal_handler); /* Hiload hotreloader is compiled as a shared library, these are the
* only required changes for the code to successfully reload */
EngineData state; // Init hiload
const char *himodules[] = {"", "libhiisi-engine.so"};
hi_init(2, himodules);
Engine hiisi = load_hiisi(); HiisiEngine hiisi;
if (!hiisi.module) {
printf("%s\n", dlerror()); hiisi.init(argc, argv);
return 1; while (hiisi.event()) {
hiisi.iterate();
// Reload changes
hi_reload();
} }
hiisi.init(&state, argc, argv); hiisi.quit();
while (hiisi.event(&state)) {
hiisi.iterate(&state);
if (reload_requested) {
dlclose(hiisi.module);
hiisi = load_hiisi();
reload_requested = false;
}
}
dlclose(hiisi.module);
// Deinit hiload
hi_deinit();
return 0; return 0;
} }

1
hiload Submodule

Submodule hiload added at c7ff4f8813

View File

@@ -1,11 +0,0 @@
#!/usr/bin/env bash
echo "Watching changes in hiisi..."
inotifywait --monitor -e modify build/hiisi/ |
while read -r _ action file; do
sleep 0.1
echo "$(date +%H:%M:%S): Hiisi changed!"
echo "$action on $file"
HIISI_PID=$(pgrep -x hiisi-run)
kill -USR1 "${HIISI_PID}" && echo "Signal sent!" || echo "Signal send failed!"
done