diff --git a/source/fumoengine/include/dictionary.c b/source/fumoengine/include/dictionary.c new file mode 100644 index 0000000..3eae7c6 --- /dev/null +++ b/source/fumoengine/include/dictionary.c @@ -0,0 +1,82 @@ +#include "dictionary.h" +#include + + +bool CreateDictionary(DictT T, struct Dictionary *dict) +{ + void *bkts = calloc(16, T->BKT_SIZE); + + if (bkts == nullptr) + return false; + + *dict = (struct Dictionary) { + .filled = 0, + .capacity = 16, + .bkts = bkts, + }; + + return true; +} + +void FreeDictionary(struct Dictionary *dict) +{ + free(dict->bkts); +} + +void *index_bkt(DictT T, struct Dictionary *dict, usize i) +{ + return (u8 *)dict->bkts + i * T->BKT_SIZE; +} + +u32 get_key(DictT T, void *bkt) +{ + return *(u32 *)bkt; +} + +void *get_val(DictT T, void *bkt) +{ + return (u8 *)bkt + T->VAL_OFS; +} + +void *probe_bkt(DictT T, 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); + + if (get_key(T, bkt) == key) + return bkt; + } + + return nullptr; +} + +void *probe_empty_bkt(DictT T, 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); + + u32 k = get_key(T, bkt); + if (k == 0 or k == key) + return bkt; + } + + return nullptr; +} + +void *DictionaryFind(DictT T, struct Dictionary *dict, u32 key) +{ + usize index = key % dict->capacity; + + return probe_bkt(T, dict, index, key); +} + +void *DictionarySet(DictT T, struct Dictionary *dict, u32 key, void *val) +{ + usize index = key % dict->capacity; + + void *bkt = probe_empty_bkt(T, dict, index, key); + if (get_key(T, bkt) == 0) + set_bkt(T, bkt, key, val); + + return bkt; +} \ No newline at end of file diff --git a/source/fumoengine/include/dictionary.h b/source/fumoengine/include/dictionary.h new file mode 100644 index 0000000..d2e547d --- /dev/null +++ b/source/fumoengine/include/dictionary.h @@ -0,0 +1,31 @@ +#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 filled; + usize capacity; + void *bkts; +}; + + +bool CreateDictionary(DictT T, struct Dictionary *dict); + +void FreeDictionary(struct Dictionary *dict); + +void *DictionaryFind(DictT T, struct Dictionary *dict, u32 key); + +void *DictionarySet(DictT T, struct Dictionary *dict, u32 key, void *val); \ No newline at end of file diff --git a/source/fumoengine/input/ctrl.c b/source/fumoengine/input/ctrl.c index f75dc3d..150bf19 100644 --- a/source/fumoengine/input/ctrl.c +++ b/source/fumoengine/input/ctrl.c @@ -4,91 +4,27 @@ #define INIT_SIZE 16 +DictT CODES_T = DICT_T(struct ControlAxis); +DictT BINDS_T = DICT_T(struct ControlAxis *); + + bool CreateController(struct Controller *ctrl) { - struct ctrl_bkt *code_bkts = calloc(INIT_SIZE, sizeof(struct ctrl_bkt)); - struct ctrl_bkt *bind_bkts = calloc(INIT_SIZE, sizeof(struct ctrl_bkt)); - struct ControlAxis *axes = calloc(INIT_SIZE, sizeof(struct ControlAxis)); - - if (code_bkts == nullptr or bind_bkts == nullptr or axes == nullptr) + if (!CreateDictionary(CODES_T, &ctrl->codes)) return false; - *ctrl = (struct Controller) { - .pending_buf.len = 0, + if (!CreateDictionary(BINDS_T, &ctrl->binds)) + return false; + + *ctrl = (struct Controller) { .pending.len = 0 }; - .axis_vec = (struct ctrl_axis_vec) { - .axes = axes, - .size = INIT_SIZE, - .len = 0, - }, - .codes = (struct ctrl_dict) { - .bkts = code_bkts, - .capacity = INIT_SIZE, - .filled = 0, - }, - .binds = (struct ctrl_dict) { - .bkts = bind_bkts, - .capacity = INIT_SIZE, - .filled = 0, - }, - }; return true; } void FreeController(struct Controller *ctrl) { - free(ctrl->codes.bkts); - free(ctrl->binds.bkts); - free(ctrl->axis_vec.axes); -} - -struct ctrl_bkt *get_bkt(struct ctrl_dict *dict, usize i) { - return &dict->bkts[i]; -} - -usize wrap_index(usize i, usize max) { - return i % (SIZE_MAX - max + 1); -} - -struct ctrl_bkt *find_set(struct ctrl_dict *dict, union InputID id) -{ - usize i = id.hash % dict->capacity; - - usize last = wrap_index(i - 1, dict->capacity); - while (i != last) { - struct ctrl_bkt *bkt = get_bkt(dict, i); - - if (bkt->axis == nullptr) { - bkt->id.hash = id.hash; - dict->filled += 1; - - return bkt; - } - - if (bkt->id.hash == id.hash) - return bkt; - - i = (i + 1) % dict->capacity; - } - - return nullptr; -} - -struct ctrl_bkt *find(struct ctrl_dict *dict, union InputID id) -{ - usize i = id.hash % dict->capacity; - - usize last = wrap_index(i - 1, dict->capacity); - while (i != last) { - struct ctrl_bkt *bkt = get_bkt(dict, i); - - if (bkt->id.hash == id.hash) - return bkt; - - i = (i + 1) % dict->capacity; - }; - - return nullptr; + FreeDictionary(&ctrl->codes); + FreeDictionary(&ctrl->binds); } struct ControlAxis *find_axis(struct ctrl_dict *dict, union InputID id) @@ -100,37 +36,37 @@ struct ControlAxis *find_axis(struct ctrl_dict *dict, union InputID id) return bkt->axis; } -union InputID as_id(u16f value, u16f type) { - return (union InputID) { .value = value, .type = type }; -} - -bool ControllerMap(struct Controller *ctrl, struct ControlMapping *mapping) -{ - struct ctrl_bkt *code_bkt = find_set(&ctrl->codes, as_id(mapping->code, mapping->type)); - struct ctrl_bkt *bind_bkt = find_set(&ctrl->binds, as_id(mapping->bind, mapping->type)); +struct ControlAxis *ControllerMap( + struct Controller *ctrl, + struct ControlMapping *map +) { + struct ControlAxis *axis = DictionarySet(CODES_T, &ctrl->codes, map->code); + struct ctrl_bkt *bind_bkt = set(&ctrl->binds, map->bind, map->type); if (code_bkt->axis == nullptr) code_bkt->axis = &ctrl->axis_vec.axes[ctrl->axis_vec.len++]; else if (code_bkt->axis == bind_bkt->axis) - return false; + return nullptr; bind_bkt->axis = code_bkt->axis; - code_bkt->axis->id.type = mapping->type; + code_bkt->axis->id.type = map->type; - mapping->axis = code_bkt->axis; - return true; + return code_bkt->axis; } bool ControllerMapMulti( struct Controller *ctrl, usize n, - struct ControlMapping *mappings + struct ControlMapping *maps, + struct ControlAxis **axis_ptrs ) { for (usize i = 0; i < n; i++) { - struct ControlMapping *mapping = mappings + i; + struct ControlAxis *axis = ControllerMap(ctrl, maps + i); - if (!ControllerMap(ctrl, mapping)) + if (axis == nullptr) return false; + + axis_ptrs[i] = axis; } return true; @@ -162,14 +98,14 @@ void dispatch_update(struct ControlAxis *axis, struct InputRecord *rec) void ControllerPoll(struct Controller *ctrl, struct RecordBuffer *recs) { - for (usize i = 0; i < ctrl->pending_buf.len; i++) { - struct ControlAxis *axis = ctrl->pending_buf.axes[i]; + for (usize i = 0; i < ctrl->pending.len; i++) { + struct ControlAxis *axis = ctrl->pending.buf[i]; axis->is_up = false; axis->is_down = false; } - ctrl->pending_buf.len = 0; + ctrl->pending.len = 0; for (usize i = 0; i < recs->head.len; i++) { struct InputRecord *rec = &recs->buf[i]; @@ -179,7 +115,7 @@ void ControllerPoll(struct Controller *ctrl, struct RecordBuffer *recs) continue; dispatch_update(axis, rec); - ctrl->pending_buf.axes[ctrl->pending_buf.len++] = axis; + ctrl->pending.buf[ctrl->pending.len++] = axis; } recs->head.len = 0; diff --git a/source/fumoengine/input/ctrl.h b/source/fumoengine/input/ctrl.h index e8f6344..ff49c58 100644 --- a/source/fumoengine/input/ctrl.h +++ b/source/fumoengine/input/ctrl.h @@ -1,14 +1,15 @@ #pragma once -#include -#include -#include -#include -#include - +#include "dictionary.h" #include "fumocommon.h" #include "input.h" +struct ControlMapping { + u16 code; + u16 bind; + u16 type; +}; + struct ControlAxis { nsec last_pressed; nsec last_released; @@ -29,39 +30,14 @@ struct ControlAxis { }; }; -struct ctrl_bkt { - struct ControlAxis *axis; - union InputID id; -}; - -struct ctrl_dict { - struct ctrl_bkt *bkts; - u16f capacity; - u16f filled; -}; - -struct ctrl_axis_vec { - struct ControlAxis *axes; - u16f size; - u16f len; -}; - struct Controller { struct { - struct ControlAxis *axes[IO_BUF_SIZE]; + struct ControlAxis *buf[IO_BUF_SIZE]; u8f len; - } pending_buf; + } pending; - struct ctrl_axis_vec axis_vec; - struct ctrl_dict codes; - struct ctrl_dict binds; -}; - -struct ControlMapping { - u16 code; - u16 bind; - u16 type; - struct ControlAxis *axis; + struct Dictionary codes; + struct Dictionary binds; }; @@ -69,12 +45,16 @@ bool CreateController(struct Controller *ctrl); void FreeController(struct Controller *ctrl); -bool ControllerMap(struct Controller *ctrl, struct ControlMapping *mapping); +struct ControlAxis *ControllerMap( + struct Controller *ctrl, + struct ControlMapping *map +); bool ControllerMapMulti( struct Controller *ctrl, usize n, - struct ControlMapping *mappings + struct ControlMapping *maps, + struct ControlAxis **axis_ptrs ); struct ControlAxis *ControllerGet(struct Controller *ctrl, u16f code, u16f type); diff --git a/source/fumoengine/input/input.c b/source/fumoengine/input/input.c index 365820a..9e2a83e 100644 --- a/source/fumoengine/input/input.c +++ b/source/fumoengine/input/input.c @@ -1,6 +1,5 @@ #include "input.h" #include - #include "platform.h" @@ -8,12 +7,12 @@ RingBufferT IO_BUF_T = RINGBUF_T(struct InputRecord, IO_BUF_SIZE); RingBufferT STR_BUF_T = RINGBUF_T(char, STR_BUF_SIZE); -void *input_worker(void *arg) +void *input_worker(void *hand_arg) { - struct InputHandle *hand = arg; + struct InputHandle *hand = hand_arg; - struct RecordBuffer tmp_recs = { .head.len = 0, .head.start = 0 }; - struct StringBuffer tmp_str = { .head.len = 0, .head.start = 0 }; + struct RecordBuffer tmp_recs = { .head = RINGBUF_HEAD_INIT }; + struct StringBuffer tmp_str = { .head = RINGBUF_HEAD_INIT }; while (!hand->is_terminating) { if (!PlatformReadInput(&tmp_recs, &tmp_str)) { @@ -67,7 +66,7 @@ bool CreateInputThread(struct InputHandle *hand) return true; } -bool EndInputThread(struct InputHandle *hand) +bool JoinInputThread(struct InputHandle *hand) { hand->is_terminating = true; diff --git a/source/fumoengine/input/input.h b/source/fumoengine/input/input.h index 26e05c0..dd4bb08 100644 --- a/source/fumoengine/input/input.h +++ b/source/fumoengine/input/input.h @@ -13,10 +13,6 @@ #define STR_BUF_SIZE (IO_BUF_SIZE * 4) -extern RingBufferT IO_BUF_T; -extern RingBufferT STR_BUF_T; - - enum InputType { BUTTON, AXIS, @@ -100,9 +96,14 @@ struct InputHandle { bool is_terminating; }; + +extern RingBufferT IO_BUF_T; +extern RingBufferT STR_BUF_T; + + bool CreateInputThread(struct InputHandle *hand); -bool EndInputThread(struct InputHandle *hand); +bool JoinInputThread(struct InputHandle *hand); bool InputAquire(struct InputHandle *hand); diff --git a/source/fumotris/fumotris.c b/source/fumotris/fumotris.c index b7b3c6e..028de4b 100644 --- a/source/fumotris/fumotris.c +++ b/source/fumotris/fumotris.c @@ -2,31 +2,34 @@ struct Fumotris { + struct ControlMapping mappings[BINDS_N]; + struct ControlAxis *input[BINDS_N]; + struct TetrMap board; struct TetrMap piece; }; -void FumotrisStart(void *engine, void *app) +void FumotrisStart(void *inst_arg, void *game_arg) { - struct FumoInstance *inst = engine; - struct Fumotris *game = app; + struct FumoInstance *inst = inst_arg; + struct Fumotris *game = game_arg; - ControllerMapMulti(&inst->ctrl, CODE_COUNT, mappings_global); + ControllerMapMulti(&inst->ctrl, BINDS_N, game->mappings, game->input); CreateTetrMap(&game->board, 10, 10); CreateTetrMap(&game->piece, 3, 3); game->piece.blks = T; } -void FumotrisUpdate(void *engine, void *app) +void FumotrisUpdate(void *inst_arg, void *game_arg) { - struct FumoInstance *inst = engine; - struct Fumotris *game = app; + struct FumoInstance *inst = inst_arg; + struct Fumotris *game = game_arg; - if (mappings_global[LEFT].axis->is_down) + if (game->input[LEFT]->is_down) game->piece.x -= 1; - if (mappings_global[RIGHT].axis->is_down) + if (game->input[RIGHT]->is_down) game->piece.x += 1; TetrMapDraw(&game->board, &inst->term); diff --git a/source/fumotris/fumotris.h b/source/fumotris/fumotris.h index bbdd4bc..27cdfaa 100644 --- a/source/fumotris/fumotris.h +++ b/source/fumotris/fumotris.h @@ -2,10 +2,10 @@ #include "fumoengine.h" #include "tetr.h" +#define BINDS_N 12 -#define CODE_COUNT 12 -enum ControlCode { +enum FumotrisCode { LEFT, RIGHT, SOFT_DROP, @@ -20,7 +20,8 @@ enum ControlCode { MOUSE }; -struct ControlMapping mappings_global[12] = { + +struct ControlMapping mappings_global[BINDS_N] = { { LEFT, 0x25, BUTTON }, { RIGHT, 0x27, BUTTON }, { SOFT_DROP, 0x28, BUTTON }, @@ -35,8 +36,6 @@ struct ControlMapping mappings_global[12] = { { MOUSE, 0, JOYSTICK } }; - - const u8 I[16] = { 0, 0, 0, 0, 0, 0, 0, 0,