From 27a3bbde96e68ef77662ff1a04a585bbcc9e0d5f Mon Sep 17 00:00:00 2001 From: Tobin Date: Fri, 17 Apr 2026 17:42:07 -0400 Subject: [PATCH] init --- .gitignore | 2 + cat_api.h | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++++ main.c | 54 +++++++++++++++++++ makefile | 6 +++ 4 files changed, 217 insertions(+) create mode 100644 .gitignore create mode 100644 cat_api.h create mode 100644 main.c create mode 100644 makefile diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8e434fc --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.swp +bin/ diff --git a/cat_api.h b/cat_api.h new file mode 100644 index 0000000..25271cc --- /dev/null +++ b/cat_api.h @@ -0,0 +1,155 @@ +#include +#include +#include + +enum cat_events +{ + QUIT, + KEYDOWN, + KEYUP, + MOUSEMOVE, + MOUSEDOWN, + MOUSEUP +}; + +struct cat_event +{ + enum cat_events type; + char key; + unsigned char mouse_button; + int mousex; + int mousey; +}; + +/* SDL stuff */ +static unsigned int* fg_framebuffer = NULL; +static unsigned int* bg_framebuffer = NULL; +static unsigned int* comp_framebuffer = NULL; +static SDL_Window* window = NULL; +static SDL_Renderer* renderer = NULL; +static SDL_Texture* texture = NULL; +static int screen_width = 0; +static int screen_height = 0; + +void cat_pixel(int layer, int visible, int x, int y, unsigned char r, unsigned char g, unsigned char b) +{ + if (comp_framebuffer == NULL) + { + printf("Warning: tried to write a pixel while screen uninitialized\n"); + return; + } + if (x >= screen_width || y >= screen_height) + { + printf("Warning: (%u, %u): coordinate off screen\n", x, y); + return; + } + unsigned int draw_color = (r << 16) + (g << 8) + b; + if (visible) draw_color += 0xff000000; + if (layer) fg_framebuffer[y * screen_width + x] = draw_color; + else bg_framebuffer[y * screen_width + x] = draw_color; +} + +void cat_de_init_screen(void) +{ + if (window != NULL) SDL_DestroyWindow(window); + window = NULL; + renderer = NULL; + texture = NULL; + free(fg_framebuffer); + free(bg_framebuffer); + free(comp_framebuffer); + fg_framebuffer = NULL; /* this might be redundant */ + bg_framebuffer = NULL; + comp_framebuffer = NULL; +} + +void cat_create_window(int w, int h) +{ + screen_width = w; + screen_height = h; + if (window != NULL || renderer != NULL || texture != NULL) cat_de_init_screen(); + fg_framebuffer = malloc(screen_width * screen_height * sizeof(unsigned int)); + bg_framebuffer = malloc(screen_width * screen_height * sizeof(unsigned int)); + comp_framebuffer = malloc(screen_width * screen_height * sizeof(unsigned int)); + window = SDL_CreateWindow("cfhfg", SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, screen_width, screen_height, SDL_WINDOW_RESIZABLE); + renderer = SDL_CreateRenderer(window, -1, 0); + texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_STREAMING, screen_width, screen_height); + SDL_ShowCursor(SDL_DISABLE); +} + +void comp_buffers(void) +{ + int x, y; for (y = 0; y < screen_height; y++) + { + for (x = 0; x < screen_width; x++) + { + if (fg_framebuffer[y * screen_width + x] & 0xff000000) + comp_framebuffer[y * screen_width + x] = fg_framebuffer[y * screen_width + x]; + else comp_framebuffer[y * screen_width + x] = bg_framebuffer[y * screen_width + x] | 0xff000000; + /* TODO decide if this should be left + as 0 if "erasing", to make a black + pixel, ignoring other color info */ + } + } +} + +void cat_render(void) +{ + comp_buffers(); + SDL_UpdateTexture(texture, NULL, (const void*)comp_framebuffer, screen_width * sizeof(unsigned int)); + SDL_RenderCopy(renderer, texture, NULL, NULL); + SDL_RenderPresent(renderer); +} + +void cat_init(void) +{ + SDL_Init(SDL_INIT_EVERYTHING); +} + +void cat_fill(int layer, int visible, int x, int y, int w, int h, unsigned char r, unsigned char g, unsigned char b) +{ + int cy, cx; + for (cy = 0; cy < h; cy++) + for (cx = 0; cx < w; cx++) + cat_pixel(layer, visible, cx + x, cy + y, r, g, b); +} + +/* TODO: cat bresenham */ + +struct cat_event* cat_get_event(void) +{ + struct cat_event* out = malloc(sizeof(struct cat_event)); + SDL_Event e; + (void)SDL_PollEvent(&e); + if (e.type == SDL_QUIT) out->type = QUIT; + else if (e.type == SDL_KEYDOWN) + { + out->type = KEYDOWN; + out->key = (e.key.keysym.sym); + } + else if (e.type == SDL_KEYUP) + { + out->type = KEYUP; + out->key = (e.key.keysym.sym); + } + else if (e.type == SDL_MOUSEMOTION) + { + out->type = MOUSEMOVE; + out->mousex = e.motion.x; + out->mousey = e.motion.y; + } + else if (e.type == SDL_MOUSEBUTTONDOWN) + { + out->type = MOUSEDOWN; + out->mouse_button = e.button.button; + } + else if (e.type == SDL_MOUSEBUTTONUP) + { + out->type = MOUSEUP; + out->mouse_button = e.button.button; + } + else return NULL; + return out; +} diff --git a/main.c b/main.c new file mode 100644 index 0000000..3420927 --- /dev/null +++ b/main.c @@ -0,0 +1,54 @@ +#include "cat_api.h" +#include + +#define NS_PER_TICK 30000000 + +void bye(void) +{ + printf("bye!\n"); + exit(0); +} + +void process_input(void) +{ + struct cat_event* e = cat_get_event(); + if (e == NULL) return; + if (e->type == QUIT) bye(); + else if (e->type == KEYDOWN) printf("keypress! %c\n", e->key); + else if (e->type == KEYUP) printf("key up! %c\n", e->key); + else if (e->type == MOUSEMOVE) printf("mouse move! (%d, %d)\n", e->mousex, e->mousey); + else if (e->type == MOUSEDOWN) printf("mouse down! %02x\n", e->mouse_button); + else if (e->type == MOUSEUP) printf("mouse up! %02x\n", e->mouse_button); +} + +static long last_sec = 0; +static long last_nsec = 0; + +void tick(void) +{ + /* run every N milliseconds... nanoseconds? idk */ + struct timespec t; + clock_gettime(CLOCK_REALTIME, &t); + if (last_sec == 0) goto yes; + else if ((t.tv_sec - last_sec) > 0) goto yes; + else if ((t.tv_nsec - last_nsec) > NS_PER_TICK) goto yes; + else return; + yes: last_sec = t.tv_sec; + last_nsec = t.tv_nsec; +} + +void game_loop(void) +{ + process_input(); + tick(); + cat_render(); +} + +int main(int argc, char** argv) +{ + cat_init(); + cat_create_window(1920, 1080); + cat_fill(0, 1, 0, 0, screen_width - 1, screen_height - 1, 132, 155, 132); + while (1) game_loop(); + return 0; +} diff --git a/makefile b/makefile new file mode 100644 index 0000000..4b605ed --- /dev/null +++ b/makefile @@ -0,0 +1,6 @@ +all: + if ! [ -d bin ]; then mkdir bin; fi + cc -o bin/cfhfg main.c -lSDL2 + +run: all + bin/cfhfg