diff --git a/project.config b/project.config index 92324c9..84781e7 100755 --- a/project.config +++ b/project.config @@ -58,7 +58,7 @@ case "$TASK" in # -fdata-sections -ffunction-sections -Wl,--gc-sections removes unused code C_ARGS="-O2 -flto=auto -fuse-linker-plugin -fprofile-use -fprofile-prefix-path=$(realpath $OBJDIR)/objects -fdata-sections -ffunction-sections -Wl,--gc-sections" CPP_ARGS="$C_ARGS" - LINKER_ARGS="$CPP_ARGS" + LINKER_ARGS="$CPP_ARGS $LINKER_LIBS" PRE_TASK_SCRIPT= TASK_SCRIPT=cbuild/default_tasks/build_exec.sh POST_TASK_SCRIPT= @@ -67,7 +67,7 @@ case "$TASK" in build_exec_dbg) C_ARGS="-O0 -g3" CPP_ARGS="$C_ARGS" - LINKER_ARGS="$CPP_ARGS" + LINKER_ARGS="$CPP_ARGS $LINKER_LIBS" PRE_TASK_SCRIPT= TASK_SCRIPT=cbuild/default_tasks/build_exec.sh POST_TASK_SCRIPT= @@ -76,7 +76,7 @@ case "$TASK" in build_shared_lib) C_ARGS="-O2 -fpic -flto -shared" CPP_ARGS="$C_ARGS" - LINKER_ARGS="$CPP_ARGS -Wl,-soname,$SHARED_LIB_FILE" + LINKER_ARGS="$CPP_ARGS $LINKER_LIBS -Wl,-soname,$SHARED_LIB_FILE" PRE_TASK_SCRIPT= TASK_SCRIPT=cbuild/default_tasks/build_shared_lib.sh POST_TASK_SCRIPT= @@ -85,7 +85,7 @@ case "$TASK" in build_shared_lib_dbg) C_ARGS="-O0 -g3 -fpic -shared" CPP_ARGS="$C_ARGS" - LINKER_ARGS="$CPP_ARGS -Wl,-soname,$SHARED_LIB_FILE" + LINKER_ARGS="$CPP_ARGS $LINKER_LIBS -Wl,-soname,$SHARED_LIB_FILE" PRE_TASK_SCRIPT= TASK_SCRIPT=cbuild/default_tasks/build_shared_lib.sh POST_TASK_SCRIPT= @@ -126,7 +126,7 @@ case "$TASK" in # -fprofile-prefix-path sets path where profiling info about objects will be saved C_ARGS="-O2 -flto=auto -fuse-linker-plugin -fprofile-generate -fprofile-prefix-path=$(realpath $OBJDIR)/objects" CPP_ARGS="$C_ARGS" - LINKER_ARGS="$CPP_ARGS" + LINKER_ARGS="$CPP_ARGS $LINKER_LIBS" PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh TASK_SCRIPT=cbuild/default_tasks/profile.sh POST_TASK_SCRIPT= @@ -139,7 +139,7 @@ case "$TASK" in # -pg adds code to executable, that generates file containing function call info (gmon.out) C_ARGS="-O2 -flto=auto -fuse-linker-plugin -pg" CPP_ARGS="$C_ARGS" - LINKER_ARGS="$CPP_ARGS" + LINKER_ARGS="$CPP_ARGS $LINKER_LIBS" PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh TASK_SCRIPT=cbuild/default_tasks/gprof.sh POST_TASK_SCRIPT= @@ -153,7 +153,7 @@ case "$TASK" in # -pg adds code to executable, that generates file containing function call info (gmon.out) C_ARGS="-O2 -flto=auto -fuse-linker-plugin" CPP_ARGS="$C_ARGS" - LINKER_ARGS="$CPP_ARGS" + LINKER_ARGS="$CPP_ARGS $LINKER_LIBS" PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh TASK_SCRIPT=cbuild/default_tasks/callgrind.sh POST_TASK_SCRIPT= @@ -163,7 +163,7 @@ case "$TASK" in OUTDIR="$OUTDIR/sanitize" C_ARGS="-O0 -g3 -fsanitize=undefined,address" CPP_ARGS="$C_ARGS" - LINKER_ARGS="$CPP_ARGS" + LINKER_ARGS="$CPP_ARGS $LINKER_LIBS" PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh TASK_SCRIPT=cbuild/default_tasks/exec.sh POST_TASK_SCRIPT= diff --git a/src/VM/Display/Display.c b/src/VM/Display/Display.c new file mode 100644 index 0000000..3dd1ee5 --- /dev/null +++ b/src/VM/Display/Display.c @@ -0,0 +1,90 @@ +#include +#include +#include "Display.h" + +typedef struct Display { + str name; + i32 width; + i32 height; + SDL_Window* window; + SDL_Renderer* renderer; +} Display; + +static SDL_InitState sdl_init_state = {0}; + + +Display* Display_create(str name, i32 w, i32 h, DisplayFlags flags){ + Display* d = malloc(sizeof(Display)); + + d->name = str_copy(name); + d->width = w; + d->height = h; + d->window = NULL; + d->renderer = NULL; + + if (SDL_ShouldInit(&sdl_init_state)) { + bool sdl_initialized = SDL_Init(SDL_INIT_VIDEO); + SDL_SetInitialized(&sdl_init_state, sdl_initialized); + if(!sdl_initialized) + return false; + } + + SDL_WindowFlags window_flags = SDL_WINDOW_ALWAYS_ON_TOP; + if(!SDL_CreateWindowAndRenderer(d->name.data, d->width, d->height, window_flags, &d->window, &d->renderer)){ + return false; + } + + return d; +} + +void Display_destroy(Display* d){ + free(d->name.data); + SDL_DestroyRenderer(d->renderer); + SDL_DestroyWindow(d->window); + free(d); + + // if (SDL_ShouldQuit(&sdl_init_state)) { + // SDL_Quit(); + // SDL_SetInitialized(&sdl_init_state, false); + // } +} + +bool Display_setName(Display* d, str name){ + d->name = str_copy(name); + return SDL_SetWindowTitle(d->window, name.data); +} + +bool Display_setSize(Display* d, u32 w, u32 h){ + d->width = w; + d->height = h; + return SDL_SetWindowSize(d->window, w, h); +} + +bool Display_setDrawingColor(Display* d, ColorRGBA color){ + return SDL_SetRenderDrawColor(d->renderer, color.r, color.g, color.b, color.a); +} + +bool Display_clear(Display* d){ + return SDL_RenderClear(d->renderer); +} + +#define Rect_copy(DST, SRC) {\ + DST.x = SRC.x;\ + DST.y = SRC.y;\ + DST.w = SRC.w;\ + DST.h = SRC.h;\ +} + +bool Display_fillRect(Display* d, Rect rect) { + SDL_FRect sdl_rect; + Rect_copy(sdl_rect, rect); + return SDL_RenderFillRect(d->renderer, &sdl_rect); +} + +bool Display_swapBuffers(Display* d){ + return SDL_RenderPresent(d->renderer); +} + +NULLABLE(cstr) Display_getError(){ + return SDL_GetError(); +} diff --git a/src/VM/Display/Display.h b/src/VM/Display/Display.h new file mode 100644 index 0000000..557b7c5 --- /dev/null +++ b/src/VM/Display/Display.h @@ -0,0 +1,32 @@ +#pragma once +#include "../../std.h" +#include "../../string/str.h" + +typedef struct Rect { + i32 x, y; + i32 w, h; +} Rect; +#define Rect_create(X, Y, W, H) ((Rect){ .x = X, .y = Y, .w = W, .h = H}) + +typedef struct ColorRGBA { + u8 r, g, b, a; +} ColorRGBA; +#define ColorRGBA_create(R, G, B, A) ((ColorRGBA){ .r = R, .g = G, .b = B, .a = A }) + + +typedef enum DisplayFlags { + DisplayFlags_Default = 0 +} DisplayFlags; + +typedef struct Display Display; + +Display* Display_create(str name, i32 w, i32 h, DisplayFlags flags); +void Display_destroy(Display* d); + +bool Display_setName(Display* d, str name); +bool Display_setSize(Display* d, u32 w, u32 h); +bool Display_setDrawingColor(Display* d, ColorRGBA color); +bool Display_clear(Display* d); +bool Display_fillRect(Display* d, Rect rect); +bool Display_swapBuffers(Display* d); +NULLABLE(cstr) Display_getError(); diff --git a/src/VM/time.c b/src/VM/time.c new file mode 100644 index 0000000..c25ec86 --- /dev/null +++ b/src/VM/time.c @@ -0,0 +1,18 @@ +#include +#include "time.h" + +void time_sleepMS(u32 ms){ + SDL_Delay(ms); +} + +void time_sleepNS(u64 ns){ + SDL_DelayNS(ns); +} + +u64 time_getMonotonicMS(){ + SDL_GetTicks(); +} + +u64 time_getMonotonicNS(){ + SDL_GetTicksNS(); +} diff --git a/src/VM/time.h b/src/VM/time.h new file mode 100644 index 0000000..810c5c8 --- /dev/null +++ b/src/VM/time.h @@ -0,0 +1,8 @@ +#pragma once + +#include "../std.h" + +void time_sleepMS(u32 ms); +void time_sleepNS(u64 ns); +u64 time_getMonotonicMS(); +u64 time_getMonotonicNS(); diff --git a/src/main.c b/src/main.c index c3b59a9..6d4d484 100644 --- a/src/main.c +++ b/src/main.c @@ -2,13 +2,61 @@ #include "instructions/instructions.h" #include "collections/List.h" #include "compiler/Compiler.h" +#include "VM/Display/Display.h" +#include #define arg_is(STR) (strcmp(argv[argi], STR) == 0) i32 compileSources(cstr source_file, cstr out_file, bool debug_log); i32 bootFromImage(cstr image_file); +#define assert_sdl(EXPR) if(!(EXPR)) { printf("assert failed: %s\nSDL_Error: %s\n", #EXPR, SDL_GetError()); return false; } + +bool test_display(){ + Display* display = Display_create(STR("le display"), 1600, 900, DisplayFlags_Default); + assert_sdl(display != NULL); + + i64 fps = 60; + i64 nsec_per_frame = 1e9 / fps; + for(u32 i = 0; i < 600; i++){ + static i64 last_frame_time = 0; + i64 current_frame_time = SDL_GetTicksNS(); + i64 delta_time = current_frame_time - last_frame_time; + last_frame_time = current_frame_time; + + SDL_Event event; + while(SDL_PollEvent(&event)) { + if(event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED){ + printfe("event WINDOW_CLOSE"); + return 0; + } + if(event.type == SDL_EVENT_QUIT){ + printfe("event QUIT"); + return 0; + } + } + + assert_sdl(Display_setDrawingColor(display, ColorRGBA_create(200, 200, 200, 255))); + assert_sdl(Display_clear(display)); + assert_sdl(Display_setDrawingColor(display, ColorRGBA_create(240, 40, 40, 255))); + assert_sdl(Display_fillRect(display, Rect_create(i, i, 64, 64))); + assert_sdl(Display_swapBuffers(display)); + + i64 time_ellapsed = SDL_GetTicksNS() - last_frame_time; + i64 delay = nsec_per_frame - time_ellapsed; + if (delay > 0) { + SDL_DelayNS(delay); + } + } + + Display_destroy(display); + return true; +} + i32 main(const i32 argc, cstr* argv){ + test_display(); + return 0; + if(argc < 2){ printfe("ERROR: no arguments provided. Use --help to know more.\n"); return 1; diff --git a/src/std.h b/src/std.h index 5a22ad4..03fbc55 100644 --- a/src/std.h +++ b/src/std.h @@ -8,6 +8,7 @@ #include #include #include +#include typedef int8_t i8; typedef uint8_t u8; @@ -20,10 +21,6 @@ typedef uint64_t u64; typedef float f32; typedef double f64; -typedef u8 bool; -#define true 1 -#define false 0 - typedef const char* cstr; #if defined(_WIN64) || defined(_WIN32)