diff --git a/src/error.c b/src/error.c new file mode 100644 index 0000000..e69de29 diff --git a/src/error.h b/src/error.h new file mode 100644 index 0000000..e0ad536 --- /dev/null +++ b/src/error.h @@ -0,0 +1,9 @@ +#ifndef ERROR_H +#define ERROR_H + +#include + +#define error(x) fprintf(stderr, "ERROR: (%s:%d): %s\n", __FILE__, __LINE__, (x)) +#define debug(x) fprintf(stdout, "DEBUG: (%s:%d): %s\n", __FILE__, __LINE__, (x)) + +#endif diff --git a/src/gc.c b/src/gc.c new file mode 100644 index 0000000..d8dd605 --- /dev/null +++ b/src/gc.c @@ -0,0 +1,71 @@ +#include "gc.h" +#include "error.h" + +#define MAX_OBJECTS 64 + +//private +static int idx = 0; //INDEX +static freeable rp[MAX_OBJECTS]; //release pool + +//public + +//allocate new pool +arp *arp_new(size_t cap) { + arp *arp = calloc(1, sizeof(arp)); + arp->objects = calloc(cap, sizeof(freeable)); + arp->idx = 0; + arp->cap = cap; + //arp_add(arp, arp, arp_release); //free self upon draining + return arp; +} + +//add object to pool +void arp_add(arp *arp, void *obj, void *des) { + if (arp->idx >= arp->cap) { + error("autoreleasepool at max capacity"); + return; //max capacity + } + + arp->objects[arp->idx++] = (freeable) { + .self = obj, + .free = des, + }; +} + +//release all objects in pool +void arp_drain(arp *arp) { + for (int i = 0; i < arp->idx; i++) { + freeable obj = arp->objects[i]; + obj.free(obj.self); + } + + arp->idx = 0; +} + +//release pool +void arp_release(arp *arp) { + for (int i = 0; i < arp->idx; i++) { + debug("freed object"); + freeable obj = arp->objects[i]; + obj.free(obj.self); + } + free(arp->objects); + free(arp); +} + +//add object to pool +void autorelease(void *obj, void *des) { + rp[idx++] = (freeable) { + .self = obj, + .free = des, + }; +} + +//release all objects +void release(void) { + for (int i = 0; i < idx; i++) { + rp[i].free(rp[i].self); + } + + idx = 0; +} diff --git a/src/gc.h b/src/gc.h new file mode 100644 index 0000000..f32d46d --- /dev/null +++ b/src/gc.h @@ -0,0 +1,27 @@ +#ifndef GC_H +#define GC_H + +#include + +typedef void (*destructor)(void *); +typedef struct freeable { + void *self; + destructor free; +} freeable; + +typedef struct arp { + freeable *objects; + int idx; + int cap; +} arp; + +arp *arp_new(size_t cap); //allocate new pool +void arp_add(arp *arp, void *obj, void *des); //add object to pool +void arp_drain(arp *arp); //release all objects in pool +void arp_release(arp *arp); //release pool + +//add an already allocated object to the gc +void autorelease(void *obj, void *des); +void release(void); + +#endif diff --git a/src/layout.c b/src/layout.c new file mode 100644 index 0000000..b9e5887 --- /dev/null +++ b/src/layout.c @@ -0,0 +1,42 @@ +#include +#include "layout.h" +#include "error.h" + +renderable rable_new(void *obj, void (*func)(void *, float, float)) { + return (renderable) { + .object = obj, + .render = func, + .pos = (Vector2){0,0} + }; +} + +void rable_render(renderable rable) { + rable.render(rable.object, rable.pos.x, rable.pos.y); +} + +renderer *rdr_new(int cap) { + renderer *rdr = calloc(1, sizeof(renderer)); + rdr->objects = calloc(cap, sizeof(renderable)); + rdr->cap = cap; + rdr->idx = 0; + return rdr; +} + +void rdr_add(renderer *rdr, void *obj, renderfunc func) { + if (rdr->idx >= rdr->cap) { + error("renderer at max capacity"); + return; + } + + rdr->objects[rdr->idx++] = rable_new(obj, func); +} +void rdr_render(renderer *rdr) { + for (int i = 0; i < rdr->idx; i++) { + rdr->objects[i].render(rdr->objects[i].object, rdr->objects[i].pos.x, rdr->objects[i].pos.y); + } +} + +void rdr_free(renderer *rdr) { + free(rdr->objects); + free(rdr); +} diff --git a/src/layout.h b/src/layout.h new file mode 100644 index 0000000..9311d99 --- /dev/null +++ b/src/layout.h @@ -0,0 +1,33 @@ +#ifndef LM_H //layout manager +#define LM_H + +#include + +/* + need to make a get_size function for objects + so the layout manager can place them correctly +*/ + +typedef void (*renderfunc)(void *, float, float); + +typedef struct renderable { + void *object; + void (*render)(void *object, float x, float y); + Vector2 pos; +} renderable; + +renderable rable_new(void *obj, void (*func)(void *, float, float)); +void rable_render(renderable rable); + +typedef struct renderer { + renderable *objects; + int idx; + int cap; +} renderer; + +renderer *rdr_new(int cap); +void rdr_add(renderer *rdr, void *obj, renderfunc func); +void rdr_render(renderer *rdr); +void rdr_free(renderer *rdr); + +#endif diff --git a/src/main.c b/src/main.c index 43e5453..34ae2a5 100644 --- a/src/main.c +++ b/src/main.c @@ -6,6 +6,9 @@ #include "controller.h" #include "splits.h" #include "file.h" +#include "layout.h" +#include "gc.h" +#include "error.h" #include #if defined(PLATFORM_DESKTOP) @@ -26,12 +29,6 @@ int remote_state = 0; Font font; -//extern this in other files -void error(const char *msg) { - fprintf(stderr, ERROR, msg); - exit(EXIT_FAILURE); -} - //extern void print_xml(const char *path); //testing control function void control(void) { @@ -59,6 +56,8 @@ int main(int argc, char *argv[]) { exit(EXIT_FAILURE); } + arp *autoreleasepool = arp_new(256); + segment_list segs = open_splits_file(argv[1]); //size of window can be determined by height of all components visible @@ -74,7 +73,7 @@ int main(int argc, char *argv[]) { GenTextureMipmaps(&font.texture); ghost ghost = ghost_new(); - + ctrl_binder *binder = create_ctrl_binder(ghost, &segs); ctrl_bind_segments(binder, &segs); @@ -97,6 +96,7 @@ int main(int argc, char *argv[]) { for (int i = 0; i < 3; i++) { txtcol_font(col[i], font); + arp_add(autoreleasepool, col[i], txtcol_free); } char buffer[64]; @@ -145,13 +145,16 @@ int main(int argc, char *argv[]) { BeginDrawing(); ClearBackground(BLACK); - if (ghost.rta->running) + + + if (ghost.rta->running && !ghost.rta->paused) DrawRectangle(0, (binder->scrollers[1]->index) * font.baseSize/16, windowWidth, (float)font.baseSize/16, BLUE); ctrl_scroller_op(binder, scroll_draw); //yummy render_timer(tr); EndDrawing(); } + arp_release(autoreleasepool); ghost_delete(ghost); CloseWindow(); } diff --git a/src/splits2.c b/src/splits2.c index ff8dec6..1eb5274 100644 --- a/src/splits2.c +++ b/src/splits2.c @@ -6,9 +6,9 @@ #include "splits.h" #include "fmt.h" #include "xml.h" +#include "error.h" struct xml_node *get_node_by_name(struct xml_node *node, char *tag); -extern void error(const char *msg); //put this in a header typedef struct run_data { char *game_name; @@ -51,6 +51,11 @@ static inline int get_file_size(FILE *file) { return size; } +//might not need idk +char *extract_string(struct xml_node *node, char *(ex_func)(struct xml_node *node)) { + return ex_func(node); +} + //create a segment from xml_segment_data segment segment_from_data(xml_segment_data data) { segment seg; @@ -114,10 +119,17 @@ segment_list open_splits_file(const char *path) { } xml_run_data data = get_run_data(xml); + if (data.segments == NULL) error("data.segs is null"); + + xml_node_child(data.segments, 0); + xml_node_child(data.segments, 1); int n = xml_node_children(data.segments); segment *segs = calloc(n, sizeof(segment)); + if (segs == NULL) error("segs is null"); + for (int i = 0; i < n; i++) { + //segfault if compiled with -O0 segs[i] = segment_from_node(xml_node_child(data.segments, i)); } diff --git a/src/text.c b/src/text.c index 0d3ccec..e66aa8d 100644 --- a/src/text.c +++ b/src/text.c @@ -30,6 +30,10 @@ void txt_draw(text *t) { //DrawRectangle(0, t->pos.y * 30, windowWidth, t->font.baseSize/16, BLUE); } +void txt_draw_pos(text *t, float x, float y) { + DrawTextEx(t->font, t->string, (Vector2){x, y}, t->font.baseSize/SCALE, 1, t->color); +} + void txt_font(text *t, Font font) { t->font = font; } diff --git a/src/text.h b/src/text.h index 53790bd..308e0c0 100644 --- a/src/text.h +++ b/src/text.h @@ -19,6 +19,7 @@ text *txt_new(char *s, int max); void txt_set(text *t, char *s); void txt_free(text *t); void txt_draw(text *t); +void txt_draw_pos(text *t, float x, float y); void txt_print(text *t); void txt_color(text *t, Color color); void txt_font(text *t, Font font); @@ -56,6 +57,7 @@ typedef struct scroller { int index; //where the bar should be on the splits int view_index; //the first split displayed text_column *txtcol; + Vector2 pos; } scroller; scroller *scroll_new(int c, text_column *tc); diff --git a/src/title.c b/src/title.c new file mode 100644 index 0000000..a1d760e --- /dev/null +++ b/src/title.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include "title.h" +//^ includes "text.h" + +title title_new(char *name, char *cat, int a, int c) { + char *at = calloc(32, sizeof(char)); + sprintf(at, "%d/%d", a, c); + text *at_text = txt_new(at, strlen(at)); //does a memcpy + free(at); + + return (title) { + .game_name = txt_new(name, strlen(name)), + .category = txt_new(cat, strlen(cat)), + .attempts = at_text + }; +} + +void title_render(title *t, float x, float y) { + //draw the stuff +} diff --git a/src/title.h b/src/title.h new file mode 100644 index 0000000..ca5ab78 --- /dev/null +++ b/src/title.h @@ -0,0 +1,15 @@ +#ifndef TITLE_H +#define TITLE_H +#include "text.h" + +typedef struct title { + text *game_name; + text *category; + text *attempts; +} title; + +title title_new(char *name, char *cat, int a, int c); +void title_render(title *t, float x, float y); +void title_free(title *t); + +#endif