diff --git a/Fumofumotris.code-workspace b/Fumofumotris.code-workspace index 3a25141..c4b7996 100644 --- a/Fumofumotris.code-workspace +++ b/Fumofumotris.code-workspace @@ -60,7 +60,8 @@ "stdbool.h": "c", "fumoengine.h": "c", "event.h": "c", - "fumocommon.h": "c" + "fumocommon.h": "c", + "terminal.h": "c" } } } \ No newline at end of file diff --git a/build/errors.txt b/build/errors.txt index c099047..170529f 100644 --- a/build/errors.txt +++ b/build/errors.txt @@ -1 +1 @@ -{"ringbuffer": "", "event": "", "ctrl": "", "terminal": "", "fumoengine": "", "parseinput": "", "dictionary": "", "fumocommon": "", "win": "", "input": "", "fumotris": "", "vector": "", "tetra": ""} \ No newline at end of file +{"ringbuffer": "", "event": "", "ctrl": "", "terminal": "", "fumoengine": "", "parseinput": "", "dictionary": "", "fumocommon": "", "win": "", "input": "", "fumotris": "\u001b[01m\u001b[Ksource\\fumotris\\fumotris.c:\u001b[m\u001b[K In function '\u001b[01m\u001b[Kmain\u001b[m\u001b[K':\n\u001b[01m\u001b[Ksource\\fumotris\\fumotris.c:120:37:\u001b[m\u001b[K \u001b[01;35m\u001b[Kwarning: \u001b[m\u001b[Kpassing argument 3 of '\u001b[01m\u001b[KEventAdd\u001b[m\u001b[K' from incompatible pointer type [\u001b[01;35m\u001b[K-Wincompatible-pointer-types\u001b[m\u001b[K]\n 120 | EventAdd(&inst.on_start, &game, \u001b[01;35m\u001b[KFumotrisStart\u001b[m\u001b[K);\n | \u001b[01;35m\u001b[K^~~~~~~~~~~~~\u001b[m\u001b[K\n | \u001b[01;35m\u001b[K|\u001b[m\u001b[K\n | \u001b[01;35m\u001b[Kvoid (*)(struct Instance *, struct Fumotris *)\u001b[m\u001b[K\nIn file included from \u001b[01m\u001b[Ksource\\fumoengine/fumoengine.h:3\u001b[m\u001b[K,\n from \u001b[01m\u001b[Ksource\\fumotris\\fumotris.h:2\u001b[m\u001b[K,\n from \u001b[01m\u001b[Ksource\\fumotris\\fumotris.c:1\u001b[m\u001b[K:\n\u001b[01m\u001b[Ksource\\fumoengine\\include/event.h:24:60:\u001b[m\u001b[K \u001b[01;36m\u001b[Knote: \u001b[m\u001b[Kexpected '\u001b[01m\u001b[Khandler\u001b[m\u001b[K' {aka '\u001b[01m\u001b[Kvoid (*)(void *, void *)\u001b[m\u001b[K'} but argument is of type '\u001b[01m\u001b[Kvoid (*)(struct Instance *, struct Fumotris *)\u001b[m\u001b[K'\n 24 | bool EventAdd(struct Event *event, void *instance, \u001b[01;36m\u001b[Khandler callback\u001b[m\u001b[K);\n | \u001b[01;36m\u001b[K~~~~~~~~^~~~~~~~\u001b[m\u001b[K\n\u001b[01m\u001b[Ksource\\fumotris\\fumotris.c:121:38:\u001b[m\u001b[K \u001b[01;35m\u001b[Kwarning: \u001b[m\u001b[Kpassing argument 3 of '\u001b[01m\u001b[KEventAdd\u001b[m\u001b[K' from incompatible pointer type [\u001b[01;35m\u001b[K-Wincompatible-pointer-types\u001b[m\u001b[K]\n 121 | EventAdd(&inst.on_update, &game, \u001b[01;35m\u001b[KFumotrisUpdate\u001b[m\u001b[K);\n | \u001b[01;35m\u001b[K^~~~~~~~~~~~~~\u001b[m\u001b[K\n | \u001b[01;35m\u001b[K|\u001b[m\u001b[K\n | \u001b[01;35m\u001b[Kvoid (*)(struct Instance *, struct Fumotris *)\u001b[m\u001b[K\n\u001b[01m\u001b[Ksource\\fumoengine\\include/event.h:24:60:\u001b[m\u001b[K \u001b[01;36m\u001b[Knote: \u001b[m\u001b[Kexpected '\u001b[01m\u001b[Khandler\u001b[m\u001b[K' {aka '\u001b[01m\u001b[Kvoid (*)(void *, void *)\u001b[m\u001b[K'} but argument is of type '\u001b[01m\u001b[Kvoid (*)(struct Instance *, struct Fumotris *)\u001b[m\u001b[K'\n 24 | bool EventAdd(struct Event *event, void *instance, \u001b[01;36m\u001b[Khandler callback\u001b[m\u001b[K);\n | \u001b[01;36m\u001b[K~~~~~~~~^~~~~~~~\u001b[m\u001b[K\n\u001b[01m\u001b[Ksource\\fumotris\\fumotris.c:122:36:\u001b[m\u001b[K \u001b[01;35m\u001b[Kwarning: \u001b[m\u001b[Kpassing argument 3 of '\u001b[01m\u001b[KEventAdd\u001b[m\u001b[K' from incompatible pointer type [\u001b[01;35m\u001b[K-Wincompatible-pointer-types\u001b[m\u001b[K]\n 122 | EventAdd(&inst.on_draw, &game, \u001b[01;35m\u001b[KFumotrisDraw\u001b[m\u001b[K);\n | \u001b[01;35m\u001b[K^~~~~~~~~~~~\u001b[m\u001b[K\n | \u001b[01;35m\u001b[K|\u001b[m\u001b[K\n | \u001b[01;35m\u001b[Kvoid (*)(struct Instance *, struct Fumotris *)\u001b[m\u001b[K\n\u001b[01m\u001b[Ksource\\fumoengine\\include/event.h:24:60:\u001b[m\u001b[K \u001b[01;36m\u001b[Knote: \u001b[m\u001b[Kexpected '\u001b[01m\u001b[Khandler\u001b[m\u001b[K' {aka '\u001b[01m\u001b[Kvoid (*)(void *, void *)\u001b[m\u001b[K'} but argument is of type '\u001b[01m\u001b[Kvoid (*)(struct Instance *, struct Fumotris *)\u001b[m\u001b[K'\n 24 | bool EventAdd(struct Event *event, void *instance, \u001b[01;36m\u001b[Khandler callback\u001b[m\u001b[K);\n | \u001b[01;36m\u001b[K~~~~~~~~^~~~~~~~\u001b[m\u001b[K\n\u001b[01m\u001b[Ksource\\fumotris\\fumotris.c:124:32:\u001b[m\u001b[K \u001b[01;35m\u001b[Kwarning: \u001b[m\u001b[Kpassing argument 3 of '\u001b[01m\u001b[KCoroutineAdd\u001b[m\u001b[K' from incompatible pointer type [\u001b[01;35m\u001b[K-Wincompatible-pointer-types\u001b[m\u001b[K]\n 124 | CoroutineAdd(&inst, &game, \u001b[01;35m\u001b[KFumotrisFall\u001b[m\u001b[K);\n | \u001b[01;35m\u001b[K^~~~~~~~~~~~\u001b[m\u001b[K\n | \u001b[01;35m\u001b[K|\u001b[m\u001b[K\n | \u001b[01;35m\u001b[Knsec (*)(struct Instance *, struct Fumotris *) {aka long long unsigned int (*)(struct Instance *, struct Fumotris *)}\u001b[m\u001b[K\n\u001b[01m\u001b[Ksource\\fumoengine/fumoengine.h:35:73:\u001b[m\u001b[K \u001b[01;36m\u001b[Knote: \u001b[m\u001b[Kexpected '\u001b[01m\u001b[Kcoroutine_handler\u001b[m\u001b[K' {aka '\u001b[01m\u001b[Klong long unsigned int (*)(void *, void *)\u001b[m\u001b[K'} but argument is of type '\u001b[01m\u001b[Knsec (*)(struct Instance *, struct Fumotris *)\u001b[m\u001b[K' {aka '\u001b[01m\u001b[Klong long unsigned int (*)(struct Instance *, struct Fumotris *)\u001b[m\u001b[K'}\n 35 | bool CoroutineAdd(struct Instance *inst, void *state, \u001b[01;36m\u001b[Kcoroutine_handler callback\u001b[m\u001b[K);\n | \u001b[01;36m\u001b[K~~~~~~~~~~~~~~~~~~^~~~~~~~\u001b[m\u001b[K\n", "vector": "", "tetra": ""} \ No newline at end of file diff --git a/build/hdr_checksums.txt b/build/hdr_checksums.txt index 37d3502..e0cb5ab 100644 --- a/build/hdr_checksums.txt +++ b/build/hdr_checksums.txt @@ -1 +1 @@ -["1d6bdf7e8de4ac751252b67027e5d57e", "9df90eabc8908cac60aa774d335a106c", "1420f33d62a8ed8429c8f1a96f1ab33e", "dc6df72158812bc9f6ed484a4cfb046b", "6669fc7fcffc77563f1315cb7710ec82", "333c7211bb2c72ad321495f53d11bff0", "088145536b04ef82517eb93630888dff", "f61af2abe56cd6881a830ae6222483e9", "e09059d1f20c982c6c42a61a0754c102", "fbccab3d5cd1838cbf8ad1d4e2a7c03b", "330b6f9493d091e7c340c1434b6f80b4", "e38bd5ea2b554a21849158242a2add8e"] \ No newline at end of file +["f315479de287d3cccdfa665c1e8c58bd", "7d30e573f96a566ed9510833b95d5520", "0eaec40fe47b9cb31ff5a70f7bfee15a", "72e1b62b85eac654ed094a8ecf009416", "5ce28b2bf9d7c5750ea290f80fbd1264", "0d65896ce70d098bdf4cb3587ca74508", "f6611a0f07f78cc4fd52df267e0d3d25", "9f0597e7cacc7c918163affc5f3d9841", "cd22e396133a64303ecae95280f8ba1a", "7d7451ae7d88f4d1f84055180f9e84a7", "29f6d19bcc5a1897b220a192ef6fc3cc", "1d88301163b019760c3dc8396ce2aa4b", "ec4912a725a2bc606bd76ba34159435c"] \ No newline at end of file diff --git a/build/src_checksums.txt b/build/src_checksums.txt index 0637a08..4e54ee3 100644 --- a/build/src_checksums.txt +++ b/build/src_checksums.txt @@ -1 +1 @@ -[] \ No newline at end of file +["4aa55dfc1d038e75d0efbf277e6033a4"] \ No newline at end of file diff --git a/debug.exe b/debug.exe index dda63fa..b86c932 100644 Binary files a/debug.exe and b/debug.exe differ diff --git a/objects/ctrl.o b/objects/ctrl.o index 9638d8e..ae0f4ec 100644 Binary files a/objects/ctrl.o and b/objects/ctrl.o differ diff --git a/objects/dictionary.o b/objects/dictionary.o index 5aa83ba..896882c 100644 Binary files a/objects/dictionary.o and b/objects/dictionary.o differ diff --git a/objects/event.o b/objects/event.o index 68654a0..1536ac0 100644 Binary files a/objects/event.o and b/objects/event.o differ diff --git a/objects/fumocommon.o b/objects/fumocommon.o index bb3f424..5e59d86 100644 Binary files a/objects/fumocommon.o and b/objects/fumocommon.o differ diff --git a/objects/fumoengine.o b/objects/fumoengine.o index 9b15b8a..fe83adc 100644 Binary files a/objects/fumoengine.o and b/objects/fumoengine.o differ diff --git a/objects/fumotris.o b/objects/fumotris.o index 3268eb1..467e9b5 100644 Binary files a/objects/fumotris.o and b/objects/fumotris.o differ diff --git a/objects/input.o b/objects/input.o index b9a14eb..4026661 100644 Binary files a/objects/input.o and b/objects/input.o differ diff --git a/objects/parseinput.o b/objects/parseinput.o index 3353ca8..08a24b4 100644 Binary files a/objects/parseinput.o and b/objects/parseinput.o differ diff --git a/objects/ringbuffer.o b/objects/ringbuffer.o index 550bf82..9f3e95a 100644 Binary files a/objects/ringbuffer.o and b/objects/ringbuffer.o differ diff --git a/objects/terminal.o b/objects/terminal.o index 7c54a21..9485235 100644 Binary files a/objects/terminal.o and b/objects/terminal.o differ diff --git a/objects/tetra.o b/objects/tetra.o index 871a9ab..9b3d35c 100644 Binary files a/objects/tetra.o and b/objects/tetra.o differ diff --git a/objects/vector.o b/objects/vector.o index 932cde8..a1bf4e5 100644 Binary files a/objects/vector.o and b/objects/vector.o differ diff --git a/objects/win.o b/objects/win.o index f9b8c56..10298db 100644 Binary files a/objects/win.o and b/objects/win.o differ diff --git a/source/fumoengine/fumocommon.c b/source/fumoengine/fumocommon.c index a340fc3..f70f559 100644 --- a/source/fumoengine/fumocommon.c +++ b/source/fumoengine/fumocommon.c @@ -2,11 +2,16 @@ #include -usize min_usize(usize a, usize b) +usize min(usize a, usize b) { return a < b ? a : b; } +usize max(usize a, usize b) +{ + return a > b ? a : b; +} + nsec TimeNow() { struct timespec ts; diff --git a/source/fumoengine/fumocommon.h b/source/fumoengine/fumocommon.h index 132da2e..86dc12b 100644 --- a/source/fumoengine/fumocommon.h +++ b/source/fumoengine/fumocommon.h @@ -40,7 +40,8 @@ typedef int_fast64_t i64f; typedef u64 nsec; -size_t min_usize(usize a, usize b); +size_t min(usize a, usize b); +size_t max(usize a, usize b); nsec TimeNow(); double TimeNowD(); diff --git a/source/fumoengine/fumoengine.c b/source/fumoengine/fumoengine.c index 0ed53bd..d2e0863 100644 --- a/source/fumoengine/fumoengine.c +++ b/source/fumoengine/fumoengine.c @@ -2,16 +2,35 @@ #include "platform.h" -const VectorT FUMOCO_T = VECTOR_T(struct FumoCoroutine); - - void Panic(char *message) { printf(message); exit(1); } -bool CreateFumoInstance(struct FumoInstance *instance) +bool CoroutineAdd(struct Instance *inst, void *state, coroutine_handler callback) +{ + return VectorAdd(&inst->coroutines, &(struct Coroutine) { + .callback = callback, + .state = state, + .next_scheduled = inst->time + }); +} + +void CoroutineTryInvoke(struct Instance *inst, struct Coroutine *co) +{ + while (inst->time > co->next_scheduled) { + nsec wait = co->callback(inst, co->state); + if (wait == 0) { + co->next_scheduled = inst->time; + break; + } else { + co->next_scheduled += wait; + } + } +} + +bool CreateFumoInstance(struct Instance *instance) { if (!PlatformInit()) Panic("Platform failed to initialize"); @@ -22,27 +41,27 @@ bool CreateFumoInstance(struct FumoInstance *instance) if (!CreateInputThread(&instance->input_hand)) Panic("Input handle failed to initialize"); - if (!CreateTerminal(&instance->term, 20, 10)) - Panic("Out of memory"); - if (!CreateEvent(&instance->on_start)) Panic("Out of memory"); if (!CreateEvent(&instance->on_update)) Panic("Out of memory"); + if (!CreateEvent(&instance->on_draw)) + Panic("Out of memory"); + + if (!CreateVector(&instance->coroutines, sizeof(struct Coroutine))) + Panic("Out of memory"); + instance->time = TimeNow(); return true; } -bool FumoInstanceRun(struct FumoInstance *inst) +bool FumoInstanceRun(struct Instance *inst) { EventInvoke(&inst->on_start, inst); - usize buf_n = TerminalMaxOut(&inst->term); - char *buf = malloc(buf_n); - while (true) { // Time nsec now = TimeNow(); @@ -57,28 +76,17 @@ bool FumoInstanceRun(struct FumoInstance *inst) if (!InputRelease(&inst->input_hand)) Panic("Release failed"); - + // Update EventInvoke(&inst->on_update, inst); + for (usize i = 0; i < inst->coroutines.len; i++) { - struct FumoCoroutine *co = VectorGet(FUMOCO_T, &inst->coroutines, i); - co->callback(); + CoroutineTryInvoke(inst, VectorGet(&inst->coroutines, i)); } // Draw EventInvoke(&inst->on_draw, inst); - TerminalPrint(&inst->term, buf, buf_n); - puts(buf); //_sleep(100); } -} - -bool CoroutineAdd(struct FumoInstance *inst, handler callback, nsec period) -{ - return VectorAdd(FUMOCO_T, &inst->coroutines, &(struct FumoCoroutine) { - .callback = callback, - .timer = 0, - .period = period - }); } \ No newline at end of file diff --git a/source/fumoengine/fumoengine.h b/source/fumoengine/fumoengine.h index 0b277ae..4e5f0ba 100644 --- a/source/fumoengine/fumoengine.h +++ b/source/fumoengine/fumoengine.h @@ -3,20 +3,21 @@ #include "event.h" #include "fumocommon.h" #include "input.h" -#include "terminal.h" #include "vector.h" -struct FumoCoroutine { - handler callback; - nsec timer; - nsec period; +typedef nsec (*coroutine_handler)(void *state, void *instance); + + +struct Coroutine { + coroutine_handler callback; + void *state; + nsec next_scheduled; }; -struct FumoInstance { +struct Instance { struct Controller ctrl; struct InputHandle input_hand; - struct Terminal term; struct Event on_start; struct Event on_update; @@ -31,6 +32,10 @@ struct FumoInstance { void Panic(char *message); -bool CreateFumoInstance(struct FumoInstance *game); +bool CoroutineAdd(struct Instance *inst, void *state, coroutine_handler callback); -bool FumoInstanceRun(struct FumoInstance *game); \ No newline at end of file +void CoroutineTryInvoke(struct Instance *inst, struct Coroutine *co); + +bool CreateFumoInstance(struct Instance *game); + +bool FumoInstanceRun(struct Instance *game); \ No newline at end of file diff --git a/source/fumoengine/include/dictionary.c b/source/fumoengine/include/dictionary.c index 2e69e08..f4ab940 100644 --- a/source/fumoengine/include/dictionary.c +++ b/source/fumoengine/include/dictionary.c @@ -1,21 +1,24 @@ #include "dictionary.h" +#include #include #include #include -bool CreateDictionary(DictT T, struct Dictionary *dict) +bool CreateDictionary(struct Dictionary *dict, usize value_size) { - void *bkts = calloc(16, T->BKT_SIZE); + void *bkts = calloc(16, value_size); if (bkts == nullptr) return false; - *dict = (struct Dictionary) { - .filled = 0, - .capacity = 16, - .bkts = bkts - }; + dict->value_size = value_size; + dict->value_offset = max(alignof(u32), alignof(u8[dict->value_size])); + dict->bkt_size = dict->value_offset + value_size; + + dict->filled = 0; + dict->capacity = 16; + dict->bkts = bkts; return true; } @@ -25,45 +28,45 @@ void FreeDictionary(struct Dictionary *dict) free(dict->bkts); } -void *index_bkt(DictT T, struct Dictionary *dict, usize i) +void *index_bkt(struct Dictionary *dict, usize i) { - return (u8 *)dict->bkts + i * T->BKT_SIZE; + return (u8 *)dict->bkts + i * dict->bkt_size; } -u32 *get_key(DictT T, void *bkt) +u32 *get_key(struct Dictionary *dict, void *bkt) { return (u32 *)bkt; } -void *get_val(DictT T, void *bkt) +void *get_value_ptr(struct Dictionary *dict, void *bkt) { - return (u8 *)bkt + T->VAL_OFS; + return (u8 *)bkt + dict->value_offset; } -void set_bkt(DictT T, void *bkt, u32 key, void *val) +void set_bkt(struct Dictionary *dict, void *bkt, u32 key, void *value_ptr) { - *get_key(T, bkt) = key; - memcpy(get_val(T, bkt), val, T->VAL_SIZE); + *get_key(dict, bkt) = key; + memcpy(get_value_ptr(dict, bkt), value_ptr, dict->value_size); } -void *probe_bkt(DictT T, struct Dictionary *dict, usize index, u32 key) +void *probe_bkt(struct Dictionary *dict, usize index, u32 key) { for (usize i = 0; i < dict->capacity; i++) { - void *bkt = index_bkt(T, dict, (index + i) % dict->capacity); + void *bkt = index_bkt(dict, (index + i) % dict->capacity); - if (*get_key(T, bkt) == key) + if (*get_key(dict, bkt) == key) return bkt; } return nullptr; } -void *probe_empty_bkt(DictT T, struct Dictionary *dict, usize index, u32 key) +void *probe_empty_bkt(struct Dictionary *dict, usize index, u32 key) { for (usize i = 0; i < dict->capacity; i++) { - void *bkt = index_bkt(T, dict, (index + i) % dict->capacity); + void *bkt = index_bkt(dict, (index + i) % dict->capacity); - u32 k = *get_key(T, bkt); + u32 k = *get_key(dict, bkt); if (k == 0 or k == key) return bkt; } @@ -71,25 +74,25 @@ void *probe_empty_bkt(DictT T, struct Dictionary *dict, usize index, u32 key) return nullptr; } -void *DictionaryFind(DictT T, struct Dictionary *dict, u32 key) +void *DictionaryFind(struct Dictionary *dict, u32 key) { usize index = key % dict->capacity; - void *bkt = probe_bkt(T, dict, index, key); + void *bkt = probe_bkt(dict, index, key); if (bkt == nullptr) return false; - return get_val(T, bkt); + return get_value_ptr(dict, bkt); } -void *DictionarySet(DictT T, struct Dictionary *dict, u32 key, void *val) +void *DictionarySet(struct Dictionary *dict, u32 key, void *value_ptr) { usize index = key % dict->capacity; - void *bkt = probe_empty_bkt(T, dict, index, key); + void *bkt = probe_empty_bkt(dict, index, key); - if (*get_key(T, bkt) == 0) - set_bkt(T, bkt, key, val); + if (*get_key(dict, bkt) == 0) + set_bkt(dict, bkt, key, value_ptr); return bkt; } \ No newline at end of file diff --git a/source/fumoengine/include/dictionary.h b/source/fumoengine/include/dictionary.h index d2e547d..1c12cb2 100644 --- a/source/fumoengine/include/dictionary.h +++ b/source/fumoengine/include/dictionary.h @@ -1,31 +1,21 @@ #pragma once #include "fumocommon.h" -#define DICT_T(DICT_VAL_T) \ - (&(struct DictT) { \ - .VAL_SIZE = sizeof(DICT_VAL_T), \ - .VAL_OFS = offsetof(struct { u32 k; DICT_VAL_T v; }, v), \ - .BKT_SIZE = sizeof(struct { u32 k; DICT_VAL_T v; }) \ - }) \ - - -typedef const struct DictT { - usize VAL_SIZE; - usize VAL_OFS; - usize BKT_SIZE; -} *const DictT; struct Dictionary { + usize value_size; + usize value_offset; + usize bkt_size; + usize filled; usize capacity; void *bkts; }; - -bool CreateDictionary(DictT T, struct Dictionary *dict); +bool CreateDictionary(struct Dictionary *dict, usize value_size); void FreeDictionary(struct Dictionary *dict); -void *DictionaryFind(DictT T, struct Dictionary *dict, u32 key); +void *DictionaryFind(struct Dictionary *dict, u32 key); -void *DictionarySet(DictT T, struct Dictionary *dict, u32 key, void *val); \ No newline at end of file +void *DictionarySet(struct Dictionary *dict, u32 key, void *value_ptr); \ No newline at end of file diff --git a/source/fumoengine/include/event.c b/source/fumoengine/include/event.c index 8814345..f28b710 100644 --- a/source/fumoengine/include/event.c +++ b/source/fumoengine/include/event.c @@ -22,7 +22,7 @@ void FreeEvent(struct Event *event) free(event->methods); } -bool EventAdd(struct Event *event, handler callback, void *instance) +bool EventAdd(struct Event *event, void *instance, handler callback) { if (event->len == event->capacity) { usize new_size = event->capacity * 2 * sizeof(struct Method); diff --git a/source/fumoengine/include/event.h b/source/fumoengine/include/event.h index bb25b41..637ca77 100644 --- a/source/fumoengine/include/event.h +++ b/source/fumoengine/include/event.h @@ -21,6 +21,6 @@ struct Event { bool CreateEvent(struct Event *event); -bool EventAdd(struct Event *event, handler callback, void *instance); +bool EventAdd(struct Event *event, void *instance, handler callback); void EventInvoke(struct Event *event, void *state); \ No newline at end of file diff --git a/source/fumoengine/include/ringbuffer.c b/source/fumoengine/include/ringbuffer.c index 6e6c16a..751699f 100644 --- a/source/fumoengine/include/ringbuffer.c +++ b/source/fumoengine/include/ringbuffer.c @@ -37,7 +37,7 @@ void RingBufferTransfer( struct RingBufferHead *dest, struct RingBufferHead *tmp ) { - usize copy_max = min_usize(T->LEN - dest->len, tmp->len); + usize copy_max = min(T->LEN - dest->len, tmp->len); for (usize i = 0; i < copy_max; i++) { void *to = RingBufferGet(T, dest, dest->len + i); @@ -55,7 +55,7 @@ usize RingBufferOut( void *dest, struct RingBufferHead *src ) { - usize copy_max = min_usize(n, src->len); + usize copy_max = min(n, src->len); for (usize i = 0; i < copy_max; i++) { void *to = (u8 *)dest + i * T->SIZE; diff --git a/source/fumoengine/include/vector.c b/source/fumoengine/include/vector.c index 19e1db7..fb766f7 100644 --- a/source/fumoengine/include/vector.c +++ b/source/fumoengine/include/vector.c @@ -3,13 +3,15 @@ #include -bool CreateVector(VectorT T, struct Vector *vec) +bool CreateVector(struct Vector *vec, usize value_size) { - void *array = malloc(16 * T->SIZE); + void *array = malloc(16 * value_size); if (array == nullptr) return false; + vec->value_size = value_size; + vec->len = 0; vec->capacity = 16; vec->array = array; @@ -22,16 +24,16 @@ void FreeVector(struct Vector *vec) free(vec->array); } -void *VectorGet(VectorT T, struct Vector *vec, usize i) +void *VectorGet(struct Vector *vec, usize i) { - return (u8 *)vec->array + i * T->SIZE; + return (u8 *)vec->array + i * vec->value_size; } -bool VectorAdd(VectorT T, struct Vector *vec, void *item) +bool VectorAdd(struct Vector *vec, void *item) { if (vec->len == vec->capacity) { usize new_capacity = vec->capacity * 2; - void *new_array = realloc(vec->array, new_capacity * T->SIZE); + void *new_array = realloc(vec->array, new_capacity * vec->value_size); if (new_array == nullptr) return false; @@ -39,7 +41,7 @@ bool VectorAdd(VectorT T, struct Vector *vec, void *item) vec->capacity = new_capacity; } - memcpy(VectorGet(T, vec, vec->len++), item, T->SIZE); + memcpy(VectorGet(vec, vec->len++), item, vec->value_size); return true; } \ No newline at end of file diff --git a/source/fumoengine/include/vector.h b/source/fumoengine/include/vector.h index 8610531..2f7c5fd 100644 --- a/source/fumoengine/include/vector.h +++ b/source/fumoengine/include/vector.h @@ -1,26 +1,19 @@ #include "fumocommon.h" -#define VECTOR_T(VEC_ITEM_T) \ - (&(struct VectorT) { \ - .SIZE = sizeof(VEC_ITEM_T) \ - }) \ - - -typedef const struct VectorT { - usize SIZE; -} *const VectorT; struct Vector { + usize value_size; + usize len; usize capacity; void *array; }; -bool CreateVector(VectorT T, struct Vector *vec); +bool CreateVector(struct Vector *vec, usize value_size); void FreeVector(struct Vector *vec); -void *VectorGet(VectorT T, struct Vector *vec, usize i); +void *VectorGet(struct Vector *vec, usize i); -bool VectorAdd(VectorT T, struct Vector *vec, void *item); \ No newline at end of file +bool VectorAdd(struct Vector *vec, void *item); \ No newline at end of file diff --git a/source/fumoengine/input/ctrl.c b/source/fumoengine/input/ctrl.c index fba729f..5b19a80 100644 --- a/source/fumoengine/input/ctrl.c +++ b/source/fumoengine/input/ctrl.c @@ -4,16 +4,13 @@ #define INIT_SIZE 16 -DictT BIND_T = DICT_T(struct InputAxis *); - - bool CreateController(struct Controller *ctrl) { struct InputAxis *axes = calloc(16, sizeof(struct InputAxis)); if (axes == nullptr) return false; - if (!CreateDictionary(BIND_T, &ctrl->binds)) + if (!CreateDictionary(&ctrl->binds, sizeof(struct InputAxis*))) return false; ctrl->pending_len = 0; @@ -39,7 +36,7 @@ bool ControllerBind(struct Controller *ctrl, u16 control, u16 code, u16 type) u32 hash = hash_bind(code, type); struct InputAxis *axis = &ctrl->axes[control]; - struct InputAxis **bind = DictionarySet(BIND_T, &ctrl->binds, hash, &axis); + struct InputAxis **bind = DictionarySet(&ctrl->binds, hash, &axis); if (bind == nullptr) return false; @@ -92,7 +89,7 @@ void ControllerPoll(struct Controller *ctrl, struct RecordBuffer *recs) struct InputRecord *rec = recs->buf + i; u32 hash = hash_bind(rec->code, rec->type); - struct InputAxis **axis = DictionaryFind(BIND_T, &ctrl->binds, hash); + struct InputAxis **axis = DictionaryFind(&ctrl->binds, hash); if (axis == nullptr) continue; @@ -102,44 +99,4 @@ void ControllerPoll(struct Controller *ctrl, struct RecordBuffer *recs) } recs->head.len = 0; -} - -/*int main() -{ - struct Controller ctrl; - if (!CreateController(&ctrl)) - return 1; - - ControllerMap(&ctrl, 123, 111, BUTTON); - ControllerMap(&ctrl, 0, 8, BUTTON); - - struct RecordBuffer recs = { .head.len = 0, .head.start = 0 }; - - recs.buf[recs.head.len++] = (struct InputRecord) { - .but.value = 69, - - .is_down = true, - - .id.bind = 111, - .id.type = BUTTON - }; - recs.buf[recs.head.len++] = (struct InputRecord) { - .but.value = 1000, - - .is_down = true, - - .id.bind = 8, - .id.type = BUTTON - }; - - ControllerPoll(&ctrl, &recs); - - struct InputAxis *a = ControllerGet(&ctrl, 123, BUTTON); - printf("%u\n", a->but.value); - - struct InputAxis *b = ControllerGet(&ctrl, 0, BUTTON); - printf("%u\n", b->but.value); - - printf("success"); - return 0; -}*/ \ No newline at end of file +} \ No newline at end of file diff --git a/source/fumoengine/terminal/terminal.c b/source/fumoengine/terminal/terminal.c index 3ae0e8b..7967f02 100644 --- a/source/fumoengine/terminal/terminal.c +++ b/source/fumoengine/terminal/terminal.c @@ -5,26 +5,30 @@ #define MAX_CH4_LEN 11 -usize TerminalMaxOut(struct Terminal *term) +usize TerminalMaxOut(usize wid, usize hgt) { return RESET_STR_LEN - + MAX_CH4_LEN * term->wid * term->hgt - + term->hgt + + MAX_CH4_LEN * wid * hgt + + hgt + 1; } bool CreateTerminal(struct Terminal *term, usize wid, usize hgt) { struct Char4 *ch4s = calloc(wid * hgt, sizeof(struct Char4)); - if (ch4s == nullptr) return false; - *term = (struct Terminal) { - .wid = wid, - .hgt = hgt, + char *str = malloc(TerminalMaxOut(wid, hgt)); + if (str == nullptr) + return false; - .buf = ch4s + *term = (struct Terminal) { + .buf = ch4s, + .str = str, + + .wid = wid, + .hgt = hgt }; return true; @@ -107,12 +111,12 @@ usize ch4_dif_to_str(char *out, struct Color4 *dif, struct Char4 *ch4) return len; } -usize TerminalPrint(struct Terminal *term, char *out, usize n) +usize TerminalPrint(struct Terminal *term) { struct Color4 dif = { 0, 0 }; usize len = 7; - memcpy(out, "\x1b[H\x1b[0m", 7); + memcpy(term->str, "\x1b[H\x1b[0m", 7); usize i = 0; for (usize y = 0; y < term->hgt; y++) { @@ -124,11 +128,11 @@ usize TerminalPrint(struct Terminal *term, char *out, usize n) ch4->ch = '#'; // DEBUG - len += ch4_dif_to_str(out + len, &dif, ch4); + len += ch4_dif_to_str(term->str + len, &dif, ch4); } - out[len++] = '\n'; + term->str[len++] = '\n'; } - out[len] = 0; + term->str[len] = 0; return len; } \ No newline at end of file diff --git a/source/fumoengine/terminal/terminal.h b/source/fumoengine/terminal/terminal.h index c3af9a0..c965bf5 100644 --- a/source/fumoengine/terminal/terminal.h +++ b/source/fumoengine/terminal/terminal.h @@ -1,10 +1,6 @@ #pragma once -#include -#include -#include #include #include - #include "fumocommon.h" @@ -19,16 +15,18 @@ struct Char4 { }; struct Terminal { + struct Char4 *buf; + char *str; + usize wid; usize hgt; - struct Char4 *buf; }; -usize TerminalMaxOut(struct Terminal *term); +usize TerminalMaxOut(usize wid, usize hgt); bool CreateTerminal(struct Terminal *term, usize wid, usize hgt); void FreeTerminal(struct Terminal *term); -usize TerminalPrint(struct Terminal *term, char *out, usize n); \ No newline at end of file +usize TerminalPrint(struct Terminal *term); \ No newline at end of file diff --git a/source/fumotris/fumotris.c b/source/fumotris/fumotris.c index 498641e..290c557 100644 --- a/source/fumotris/fumotris.c +++ b/source/fumotris/fumotris.c @@ -3,99 +3,143 @@ struct Fumotris { + struct Terminal term; + + struct TetraTemplate *bag[7]; + usize bag_i; + struct Tetra board; struct Tetra piece; bool is_ground; + + nsec last_moved; + nsec last_dropped; }; - -struct TetraTemplate *bag[7] = { &I, &O, &T, &S, &Z, &J, &L }; -usize bag_i = 0; - - -void shuffle() +void shuffle(struct Fumotris *fumo) { - for (usize i = 6; i >= 0; i--) { + for (usize i = 6; i > 0; i--) { usize swap = rand() % i; - struct TetraTemplate *tmp = bag[swap]; - bag[swap] = bag[i]; - bag[i] = tmp; + struct TetraTemplate *tmp = fumo->bag[swap]; + fumo->bag[swap] = fumo->bag[i]; + fumo->bag[i] = tmp; } } -void place_piece(struct Fumotris *fumo) +void check_clear() +{ + +} + +void place(struct Fumotris *fumo) { TetraOverlay(&fumo->piece, &fumo->board); - SetTetra(&fumo->piece, bag[bag_i++], 0, 0); - if (bag_i == 7) { - shuffle(); - bag_i = 0; + usize lines_cleared = fumo->piece.hgt; + + for (usize y = fumo->piece.y; y < fumo->piece.y + fumo->piece.hgt; y++) { + for (usize x = 0; x < fumo->board.wid; x++) { + if (fumo->board.blks[fumo->board.wid * y + x] == 0) { + lines_cleared -= 1; + break; + } + } } + + TetraSet(&fumo->piece, fumo->bag[fumo->bag_i++]); + + if (fumo->bag_i == 7) { + shuffle(fumo); + fumo->bag_i = 0; + } + } i16 get_horizontal(struct Controller *ctrl) { - return (-(i16)ctrl->axes[LEFT].is_down) + ctrl->axes[RIGHT].is_down; + return (-(i16)ctrl->axes[LEFT].is_held) + ctrl->axes[RIGHT].is_held; } -void FumotrisStart(struct FumoInstance *inst, struct Fumotris *fumo) +void FumotrisStart(struct Instance *inst, struct Fumotris *fumo) { - ControllerBindMulti(&inst->ctrl, BINDS_N, controls_g, codes_g, types_g); - CreateTetra(&fumo->board, 10, 10); + ControllerBindMulti(&inst->ctrl, BINDS_N, CONTROLS, CODES, TYPES); + CreateTerminal(&fumo->term, 20, 20); + for (usize i = 0; i < 7; i++) + fumo->bag[i] = templates[i]; + fumo->bag_i = 1; + + CreateTetra(&fumo->board, 10, 20); + TetraSet(&fumo->piece, fumo->bag[0]); fumo->is_ground = false; - - SetTetra(&fumo->piece, bag[bag_i++], 0, 0); + fumo->last_moved = 0; + fumo->last_dropped = 0; } -void FumotrisUpdate(struct FumoInstance *inst, struct Fumotris *fumo) +void FumotrisUpdate(struct Instance *inst, struct Fumotris *fumo) { - TetraMove(&fumo->piece, &fumo->board, get_horizontal(&inst->ctrl), 0); + i16 horizontal = get_horizontal(&inst->ctrl); - if (inst->ctrl.axes[SOFT_DROP].is_down) { + if (horizontal != 0 and fumo->last_moved < inst->time) { + fumo->last_moved = inst->time + 5e7; + TetraMove(&fumo->piece, &fumo->board, horizontal, 0); + } + + if (inst->ctrl.axes[ROTATE_CCW].is_down) + TetraRotate(&fumo->piece, &fumo->board, 1); + + if (inst->ctrl.axes[ROTATE_CW].is_down) + TetraRotate(&fumo->piece, &fumo->board, -1); + + if (inst->ctrl.axes[SOFT_DROP].is_held and fumo->last_dropped < inst->time) { + fumo->last_dropped = inst->time + 5e7; TetraMove(&fumo->piece, &fumo->board, 0, 1); } if (inst->ctrl.axes[HARD_DROP].is_down) { while (TetraMove(&fumo->piece, &fumo->board, 0, 1)); - place_piece(fumo); + place(fumo); } } -void FumotrisOnFall(struct FumoInstance *inst, struct Fumotris *fumo) +nsec FumotrisFall(struct Instance *inst, struct Fumotris *fumo) { if (!TetraMove(&fumo->piece, &fumo->board, 0, 1)) { if (!fumo->is_ground) fumo->is_ground = true; else - place_piece(fumo); + place(fumo); } + + return 5e8; } -void FumotrisDraw(struct FumoInstance *inst, struct Fumotris *fumo) +void FumotrisDraw(struct Instance *inst, struct Fumotris *fumo) { - TetraTerminalClear(&fumo->board, &inst->term); - TetraTerminalDraw(&fumo->board, &inst->term); - TetraTerminalDraw(&fumo->piece, &inst->term); + TetraTerminalClear(&fumo->board, &fumo->term); + TetraTerminalDraw(&fumo->board, &fumo->term); + TetraTerminalDraw(&fumo->piece, &fumo->term); + + TerminalPrint(&fumo->term); + puts(fumo->term.str); } int main() { - struct FumoInstance inst; + struct Instance inst; CreateFumoInstance(&inst); struct Fumotris game; - EventAdd(&inst.on_start, FumotrisStart, &game); - EventAdd(&inst.on_update, FumotrisUpdate, &game); - EventAdd(&inst.on_draw, FumotrisDraw, &game); + EventAdd(&inst.on_start, &game, FumotrisStart); + EventAdd(&inst.on_update, &game, FumotrisUpdate); + EventAdd(&inst.on_draw, &game, FumotrisDraw); - VectorAdd(FUMOCO_T, &inst.coroutines, ); + CoroutineAdd(&inst, &game, FumotrisFall); FumoInstanceRun(&inst); diff --git a/source/fumotris/fumotris.h b/source/fumotris/fumotris.h index 3aa2b06..8d8db95 100644 --- a/source/fumotris/fumotris.h +++ b/source/fumotris/fumotris.h @@ -1,5 +1,6 @@ #include "fumocommon.h" #include "fumoengine.h" +#include "terminal.h" #include "tetra.h" #define BINDS_N 12 @@ -23,7 +24,7 @@ enum FumotrisControls { }; -u16 controls_g[BINDS_N] = { +u16 CONTROLS[BINDS_N] = { LEFT, RIGHT, SOFT_DROP, @@ -40,7 +41,7 @@ u16 controls_g[BINDS_N] = { MOUSE, }; -u16 codes_g[BINDS_N] = { +u16 CODES[BINDS_N] = { 0x25, 0x27, 0x28, @@ -57,7 +58,7 @@ u16 codes_g[BINDS_N] = { 0 }; -u16 types_g[BINDS_N] = { +u16 TYPES[BINDS_N] = { BUTTON, BUTTON, BUTTON, @@ -75,7 +76,7 @@ u16 types_g[BINDS_N] = { }; struct TetraTemplate I = { - .blks = &(u8) { + .blks = (u8[16]) { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, @@ -86,18 +87,18 @@ struct TetraTemplate I = { }; struct TetraTemplate O = { - .blks = &(u8) { - 1, 1, - 1, 1 + .blks = (u8[4]) { + 2, 2, + 2, 2 }, .wid = 2, .hgt = 2 }; struct TetraTemplate T = { - .blks = &(u8) { - 0, 1, 0, - 1, 1, 1, + .blks = (u8[9]) { + 0, 3, 0, + 3, 3, 3, 0, 0, 0 }, .wid = 3, @@ -105,9 +106,9 @@ struct TetraTemplate T = { }; struct TetraTemplate S = { - .blks = &(u8) { - 0, 1, 1, - 1, 1, 0, + .blks = (u8[9]) { + 0, 4, 4, + 4, 4, 0, 0, 0, 0 }, .wid = 3, @@ -115,9 +116,9 @@ struct TetraTemplate S = { }; struct TetraTemplate Z = { - .blks = &(u8) { - 1, 1, 0, - 0, 1, 1, + .blks = (u8[9]) { + 5, 5, 0, + 0, 5, 5, 0, 0, 0 }, .wid = 3, @@ -125,9 +126,9 @@ struct TetraTemplate Z = { }; struct TetraTemplate J = { - .blks = &(u8) { - 1, 0, 0, - 1, 1, 1, + .blks = (u8[9]) { + 6, 0, 0, + 6, 6, 6, 0, 0, 0 }, .wid = 3, @@ -135,11 +136,13 @@ struct TetraTemplate J = { }; struct TetraTemplate L = { - .blks = &(u8) { - 0, 0, 1, - 1, 1, 1, + .blks = (u8[9]) { + 0, 0, 7, + 7, 7, 7, 0, 0, 0 }, .wid = 3, .hgt = 3 -}; \ No newline at end of file +}; + +struct TetraTemplate *templates[7] = { &I, &O, &T, &S, &Z, &J, &L }; \ No newline at end of file diff --git a/source/fumotris/tetra.c b/source/fumotris/tetra.c index 890cf1f..c0a7f57 100644 --- a/source/fumotris/tetra.c +++ b/source/fumotris/tetra.c @@ -1,20 +1,24 @@ #include "tetra.h" -bool CreateTetra(struct Tetra *map, u16 wid, u16 hgt) +bool CreateTetra(struct Tetra *tetra, u16 wid, u16 hgt) { u8 *blks = calloc(wid * hgt, sizeof(u8)); if (blks == nullptr) return false; - map->blks = blks; - map->wid = wid; - map->hgt = hgt; + *tetra = (struct Tetra) { + .blks = blks, - map->x = 0; - map->y = 0; - map->rot = 0; + .wid = wid, + .hgt = hgt, + + .x = 0, + .y = 0, + + .rot = 0 + }; return true; } @@ -24,37 +28,45 @@ void FreeTetra(struct Tetra *tetra) free(tetra->blks); } -void SetTetra(struct Tetra *map, struct TetraTemplate *t, i16 x, i16 y) +void TetraSet(struct Tetra *tetra, struct TetraTemplate *template) { - map->blks = t->blks; - map->wid = t->wid; - map->hgt = t->hgt; + tetra->blks = template->blks; + tetra->wid = template->wid; + tetra->hgt = template->hgt; + + tetra->x = 0; + tetra->y = 0; + tetra->rot = 0; +} + +usize rotate_index(usize i, usize wid, u8 rot) +{ + if(rot == 0) + return i; + + usize row = i / wid; + usize col = i % wid; - map->x = x; - map->y = y; - map->rot = 0; + switch (rot) { + case 1: + return (wid - col - 1) * wid + row; + case 2: + return (wid - row - 1) * wid + (wid - col - 1); + case 3: + return col * wid + (wid - row - 1); + } + + return 0; } -bool TetraMove(struct Tetra *piece, struct Tetra *board, i16 dx, i16 dy) +bool TetraIsCollision(struct Tetra *t, struct Tetra *board) { - if (TetraIsCollision(piece, board, dx, dy)) - return false; - - piece->x += dx; - piece->y += dy; - - return true; -} - -bool TetraIsCollision(struct Tetra *piece, struct Tetra *board, i16 dx, i16 dy) -{ - i16 x_start = piece->x + dx; - i16 y_start = piece->y + dy; - usize i = 0; - for (i16 y = y_start; y < y_start + piece->hgt; y++) { - for (i16 x = x_start; x < x_start + piece->wid; x++, i++) { - if(piece->blks[i] == 0) + for (i16 y = t->y; y < t->y + t->hgt; y++) { + for (i16 x = t->x; x < t->x + t->wid; x++, i++) { + usize rot_i = rotate_index(i, t->wid, t->rot); + + if(t->blks[rot_i] == 0) continue; if(x < 0 or x >= board->wid or y < 0 or y >= board->hgt) @@ -68,6 +80,53 @@ bool TetraIsCollision(struct Tetra *piece, struct Tetra *board, i16 dx, i16 dy) return false; } +bool TetraMove(struct Tetra *t, struct Tetra *board, i16 dx, i16 dy) +{ + t->x += dx; + t->y += dy; + + if (TetraIsCollision(t, board)) { + t->x -= dx; + t->y -= dy; + + return false; + } + + return true; +} + +bool TetraRotate(struct Tetra *t, struct Tetra *board, i8 dr) +{ + u8 rot = t->rot; + t->rot = (t->rot + 4 + dr) % 4; + + if (TetraIsCollision(t, board)) { + t->rot = rot; + + return false; + } + + return true; +} + +void TetraOverlay(struct Tetra *t, struct Tetra *board) +{ + usize i = 0; + for (i16 y = t->y; y < t->y + t->hgt; y++) { + for (i16 x = t->x; x < t->x + t->wid; x++, i++) { + usize rot_i = rotate_index(i, t->wid, t->rot); + + if(t->blks[rot_i] == 0) + continue; + + if(x < 0 or x >= board->wid or y < 0 or y >= board->hgt) + continue; + + board->blks[board->wid * y + x] = t->blks[rot_i]; + } + } +} + void TetraTerminalClear(struct Tetra *board, struct Terminal *term) { for (usize i = 0; i < board->wid * board->hgt; i++) { @@ -78,38 +137,24 @@ void TetraTerminalClear(struct Tetra *board, struct Terminal *term) } } -void TetraTerminalDraw(struct Tetra *tetra, struct Terminal *term) +void TetraTerminalDraw(struct Tetra *t, struct Terminal *term) { static const u8f blk_colors[8] = { 8, 14, 11, 13, 10, 9, 12, 3 }; usize i = 0; - for (usize y = 0; y < tetra->hgt; y++) { - for (usize x = 0; x < tetra->wid; x++, i++) { - if (tetra->blks[i] == 0) + for (usize y = 0; y < t->hgt; y++) { + for (usize x = 0; x < t->wid; x++, i++) { + usize rot_i = rotate_index(i, t->wid, t->rot); + + if (t->blks[rot_i] == 0) continue; - usize term_i = (y + tetra->y) * term->wid + (x + tetra->x) * 2; + usize term_i = (y + t->y) * term->wid + (x + t->x) * 2; struct Char4 *block = term->buf + term_i; - u8 fg = blk_colors[tetra->blks[i]]; + u8 fg = blk_colors[t->blks[rot_i]]; block[0] = (struct Char4) { .ch = '[', .color.fg = fg }; block[1] = (struct Char4) { .ch = ']', .color.fg = fg }; } } -} - -void TetraOverlay(struct Tetra *piece, struct Tetra *board) -{ - usize i = 0; - for (usize y = piece->y; y < piece->y + piece->hgt; y++) { - for (usize x = piece->x; x < piece->x + piece->wid; x++, i++) { - if(piece->blks[i] == 0) - continue; - - if(x < 0 or x >= board->wid or y < 0 or y >= board->hgt) - continue; - - board->blks[board->wid * y + x] = piece->blks[i]; - } - } } \ No newline at end of file diff --git a/source/fumotris/tetra.h b/source/fumotris/tetra.h index f0838cc..1f6541c 100644 --- a/source/fumotris/tetra.h +++ b/source/fumotris/tetra.h @@ -4,38 +4,38 @@ #include "terminal.h" -struct Tetra { +struct TetraTemplate { u8 *blks; + usize wid; + usize hgt; +}; + +struct Tetra { + u8 *blks; + u16 wid; u16 hgt; i16 x; i16 y; - - u8f rot; + u8 rot; }; -struct TetraTemplate { - u8 *blks; - - u16 wid; - u16 hgt; -}; +bool CreateTetra(struct Tetra *tetra, u16 wid, u16 hgt); +void FreeTetra(struct Tetra *tetra); -bool CreateTetra(struct Tetra *map, u16 wid, u16 hgt); +void TetraSet(struct Tetra *tetra, struct TetraTemplate *template); -void FreeTetra(struct Tetra *map); +bool TetraIsCollision(struct Tetra *t, struct Tetra *board); -void SetTetra(struct Tetra *map, struct TetraTemplate *t, i16 x, i16 y); +bool TetraMove(struct Tetra *t, struct Tetra *board, i16 dx, i16 dy); + +bool TetraRotate(struct Tetra *t, struct Tetra *board, i8 dr); + +void TetraOverlay(struct Tetra *t, struct Tetra *board); void TetraTerminalClear(struct Tetra *board, struct Terminal *term); -void TetraTerminalDraw(struct Tetra *map, struct Terminal *term); - -bool TetraMove(struct Tetra *piece, struct Tetra *board, i16 dx, i16 dy); - -bool TetraIsCollision(struct Tetra *piece, struct Tetra *board, i16 dx, i16 dy); - -void TetraOverlay(struct Tetra *piece, struct Tetra *board); \ No newline at end of file +void TetraTerminalDraw(struct Tetra *t, struct Terminal *term); \ No newline at end of file