From 879e8f2af25a58a6afbfcd5b0f95c7beb735e0ad Mon Sep 17 00:00:00 2001 From: Julia <145168563+julia-aph@users.noreply.github.com> Date: Tue, 9 Apr 2024 17:10:30 -0500 Subject: [PATCH] hh jhhj --- source/fumotris.h | 15 ++- source/game/event.c | 10 +- source/game/event.h | 2 +- source/io/ctrl.c | 203 +++++++++++++++++-------------- source/io/ctrl.h | 39 +++--- source/io/input.c | 4 +- source/io/input.h | 4 +- source/io/platforms/win.c | 11 +- source/io/platforms/winhandler.c | 56 +++++---- source/main.c | 45 +++---- source/term/term.c | 20 +-- test.exe | Bin 82015 -> 82590 bytes 12 files changed, 227 insertions(+), 182 deletions(-) diff --git a/source/fumotris.h b/source/fumotris.h index e747a8a..6bfc324 100644 --- a/source/fumotris.h +++ b/source/fumotris.h @@ -13,4 +13,17 @@ typedef uint32_t u32; typedef uint_fast32_t u32f; typedef uint64_t u64; -typedef uint_fast64_t u64f; \ No newline at end of file +typedef uint_fast64_t u64f; + + +typedef int8_t i8; +typedef int_fast8_t i8f; + +typedef int16_t i16; +typedef int_fast16_t i16f; + +typedef int32_t i32; +typedef int_fast32_t i32f; + +typedef int64_t i64; +typedef int_fast64_t i64f; \ No newline at end of file diff --git a/source/game/event.c b/source/game/event.c index 1365202..a8ac7ad 100644 --- a/source/game/event.c +++ b/source/game/event.c @@ -17,13 +17,19 @@ size_t delegate_size(size_t capacity) return sizeof(void(*)(void *)) * capacity; } -struct Delegate NewDelegate(size_t capacity) +bool NewDelegate(struct Delegate *d, size_t capacity) { - return (struct Delegate) { + void (**events)(void *args) = malloc(delegate_size(capacity)); + + if (events == nullptr) + return false; + + *d = (struct Delegate) { .len = 0, .capacity = capacity, .events = malloc(delegate_size(capacity)) }; + return true; } void Subscribe(struct Delegate *d, void (*event)(void *args)) diff --git a/source/game/event.h b/source/game/event.h index 03e47bc..a3ae0cf 100644 --- a/source/game/event.h +++ b/source/game/event.h @@ -13,7 +13,7 @@ struct Delegate { void (**events)(void *args); }; -struct Delegate NewDelegate(size_t capacity); +bool NewDelegate(struct Delegate *d, size_t capacity); void Subscribe(struct Delegate *d, void (*event)(void *args)); diff --git a/source/io/ctrl.c b/source/io/ctrl.c index 2a851ea..604d0b4 100644 --- a/source/io/ctrl.c +++ b/source/io/ctrl.c @@ -11,54 +11,48 @@ #define IO_BUF_SIZE 16 -enum CtrlType { +enum InputType { KEY, AXIS, JOYSTICK, ESCAPE }; -struct Record { - u16 id; +struct Button { + u32 value; + bool is_down; + bool is_held; + bool is_up; +}; + +struct Axis { + i64 value; +}; + +struct Joystick { + i32 x; + i32 y; +}; + +struct InputRecord { + u16 bind; u8 type; union { - struct { - bool is_down; - } key; - struct { - u64 value; - } axis; - struct { - u32 x; - u32 y; - } joystick; - } data; + struct Button but; + struct Axis axis; + struct Joystick js; + }; struct timespec timestamp; }; -struct RecordBuffer { - struct Record records[IO_BUF_SIZE]; - size_t count; - pthread_mutex_t mutex; -}; - -struct Axis { +struct InputAxis { union { - struct { - u32 value; - u32 is_down : 1; - u32 is_up : 1; - } key; - struct { - u64 value; - } axis; - struct { - u32 x; - u32 y; - } joystick; - } data; + struct Button but; + struct Axis axis; + struct Joystick js; + }; struct timespec last_pressed; struct timespec last_released; @@ -81,41 +75,44 @@ hashtype Hash(void *item, size_t size) hashtype hash_id(u16f value, u8f type) { - struct id { - u16 id; - u8 type; - }; - - struct id id = { value, type }; - return Hash(&id, sizeof(struct id)); + struct { u16 id; u8 type; } id = { value, type }; + return Hash(&id, sizeof(id)); } -struct ctrl_bkt { - hashtype hash; - u16 value; - u8 type; - struct Axis *axis; -}; - struct ctrl_dict { size_t capacity; size_t filled; - struct ctrl_bkt *bkts; + + struct ctrl_bkt { + hashtype hash; + u16 value; + u8 type; + + struct InputAxis *axis; + } *bkts; }; -struct Ctrl { +struct Controller { struct ctrl_dict codes; struct ctrl_dict binds; + struct InputAxis *axes; - struct RecordBuffer buf; - pthread_t thread; + struct { + struct InputRecord records[IO_BUF_SIZE]; + size_t len; + } input_buf; + + struct { + size_t indexes[IO_BUF_SIZE]; + size_t len; + } pending_state_buf; }; -bool NewCtrl(struct Ctrl *ctrl, size_t code_cap, size_t bind_cap) +bool NewCtrl(struct Controller *ctrl, size_t code_cap, size_t bind_cap) { struct ctrl_bkt *code_bkts = calloc(code_cap, sizeof(struct ctrl_bkt)); struct ctrl_bkt *bind_bkts = calloc(bind_cap, sizeof(struct ctrl_bkt)); - struct Axis *axes = calloc(code_cap, sizeof(struct Axis)); + struct InputAxis *axes = calloc(code_cap, sizeof(struct InputAxis)); if (code_bkts == nullptr or bind_bkts == nullptr or axes == nullptr) return false; @@ -124,7 +121,7 @@ bool NewCtrl(struct Ctrl *ctrl, size_t code_cap, size_t bind_cap) code_bkts[i].axis = axes + i; } - *ctrl = (struct Ctrl) { + *ctrl = (struct Controller) { .codes = (struct ctrl_dict) { .capacity = code_cap, .filled = 0, @@ -135,19 +132,23 @@ bool NewCtrl(struct Ctrl *ctrl, size_t code_cap, size_t bind_cap) .filled = 0, .bkts = bind_bkts, }, + .axes = axes, - .buf = (struct RecordBuffer) { - .count = 0, - .mutex = PTHREAD_MUTEX_INITIALIZER, + .input_buf = { + .len = 0, + }, + .pending_state_buf = { + .len = 0, }, }; return true; } -void FreeCtrl(struct Ctrl *ctrl) +void FreeCtrl(struct Controller *ctrl) { free(ctrl->codes.bkts); free(ctrl->binds.bkts); + free(ctrl->axes); } struct ctrl_bkt *get_bkt(struct ctrl_dict *dict, size_t i) @@ -216,7 +217,7 @@ next: return nullptr; } -struct Axis *find_axis(struct ctrl_dict *dict, u16f value, u8f type) +struct InputAxis *find_axis(struct ctrl_dict *dict, u16f value, u8f type) { struct ctrl_bkt *bkt = find(dict, value, type); if (bkt == nullptr) @@ -225,7 +226,7 @@ struct Axis *find_axis(struct ctrl_dict *dict, u16f value, u8f type) return bkt->axis; } -bool CtrlMap(struct Ctrl *ctrl, u16f code, u16f bind, u8f type) +bool CtrlMap(struct Controller *ctrl, u16f code, u16f bind, u8f type) { if (ctrl->codes.filled >= ctrl->codes.capacity or ctrl->binds.filled >= ctrl->binds.capacity) { printf("fatal error"); @@ -245,7 +246,7 @@ bool CtrlMap(struct Ctrl *ctrl, u16f code, u16f bind, u8f type) return true; } -struct Axis *CtrlGet(struct Ctrl *ctrl, u16f code, u8f type) +struct InputAxis *CtrlGet(struct Controller *ctrl, u16f code, u8f type) { struct ctrl_bkt *code_bkt = find(&ctrl->codes, code, type); if (code_bkt == nullptr) @@ -254,53 +255,69 @@ struct Axis *CtrlGet(struct Ctrl *ctrl, u16f code, u8f type) return code_bkt->axis; } -void update_key(struct Axis *axis, struct Record *record) +void update_key(struct InputAxis *axis, struct InputRecord *rec) { - if (record->data.key.is_down) - axis->last_pressed = record->timestamp; - else - axis->last_released = record->timestamp; - - axis->data.key.is_down = record->data.key.is_down; + if (rec->but.is_down) { + axis->last_pressed = rec->timestamp; + axis->but.is_held = true; + } else { + axis->last_released = rec->timestamp; + axis->but.is_held = false; + } + + axis->but.is_down |= rec->but.is_down; + axis->but.is_up |= rec->but.is_up; } -void update_axis(struct Axis *axis, struct Record *record) +void update_axis(struct InputAxis *axis, struct InputRecord *rec) { - axis->data.axis.value = record->data.axis.value; - axis->last_pressed = record->timestamp; + axis->axis.value = rec->axis.value; + + axis->last_pressed = rec->timestamp; } -void update_joystick(struct Axis *axis, struct Record *record) +void update_joystick(struct InputAxis *axis, struct InputRecord *rec) { - axis->data.joystick.x = record->data.joystick.x; - axis->data.joystick.y = record->data.joystick.y; - axis->last_pressed = record->timestamp; + axis->js.x = rec->js.x; + axis->js.y = rec->js.y; + + axis->last_pressed = rec->timestamp; } -bool CtrlPoll(struct Ctrl *ctrl) +bool dispatch_update(struct InputAxis *axis, struct InputRecord *rec) { - for (size_t i = 0; i < ctrl->buf.count; i++) { - struct Record *rec = &ctrl->buf.records[i]; + switch (rec->type) { + case KEY: + update_key(axis, rec); + printf("axis:%hu\n", axis->but.is_down); + return true; - struct Axis *axis = find_axis(&ctrl->binds, rec->id, rec->type); + case AXIS: + update_axis(axis, rec); + return true; + + case JOYSTICK: + update_joystick(axis, rec); + return true; + } + + return false; +} + +bool CtrlPoll(struct Controller *ctrl) +{ + for (size_t i = 0; i < ctrl->input_buf.len; i++) { + struct InputRecord *rec = &ctrl->input_buf.records[i]; + printf("i:%hu\n", rec->bind); + + struct InputAxis *axis = find_axis(&ctrl->binds, rec->bind, rec->type); if (axis == nullptr) continue; - switch (rec->type) { - case KEY: - update_key(axis, rec); - break; - case AXIS: - update_axis(axis, rec); - break; - case JOYSTICK: - update_joystick(axis, rec); - break; - default: + if (!dispatch_update(axis, rec)) return false; - } } - ctrl->buf.count = 0; + ctrl->input_buf.len = 0; return true; } \ No newline at end of file diff --git a/source/io/ctrl.h b/source/io/ctrl.h index 0e6635b..01cc646 100644 --- a/source/io/ctrl.h +++ b/source/io/ctrl.h @@ -12,21 +12,22 @@ #define IO_BUF_SIZE 16 -enum CtrlType { +enum InputType { KEY, AXIS, JOYSTICK, ESCAPE }; -struct Record { - u16 id; +struct InputRecord { + u16 bind; u8 type; union { struct { bool is_down; - } key; + bool is_up; + } button; struct { u64 value; } axis; @@ -34,24 +35,25 @@ struct Record { u32 x; u32 y; } joystick; - } data; + }; struct timespec timestamp; }; struct RecordBuffer { - struct Record records[IO_BUF_SIZE]; + struct InputRecord records[IO_BUF_SIZE]; size_t count; pthread_mutex_t mutex; }; -struct Axis { +struct InputAxis { union { struct { u32 value; - u32 is_down : 1; - u32 is_up : 1; - } key; + bool is_down; + bool is_held; + bool is_up; + } button; struct { u64 value; } axis; @@ -59,7 +61,7 @@ struct Axis { u32 x; u32 y; } joystick; - } data; + }; struct timespec last_pressed; struct timespec last_released; @@ -86,7 +88,7 @@ struct ctrl_bkt { hashtype hash; u16 value; u8 type; - struct Axis *axis; + struct InputAxis *axis; }; struct ctrl_dict { @@ -95,20 +97,21 @@ struct ctrl_dict { struct ctrl_bkt *bkts; }; -struct Ctrl { +struct Controller { struct ctrl_dict codes; struct ctrl_dict binds; + struct InputAxis *axes; struct RecordBuffer buf; pthread_t thread; }; -bool NewCtrl(struct Ctrl *ctrl, size_t code_cap, size_t bind_cap); +bool NewCtrl(struct Controller *ctrl, size_t code_cap, size_t bind_cap); -void FreeCtrl(struct Ctrl *ctrl); +void FreeCtrl(struct Controller *ctrl); -bool CtrlMap(struct Ctrl *ctrl, u16f code, u16f bind, u8f type); +bool CtrlMap(struct Controller *ctrl, u16f code, u16f bind, u8f type); -struct Axis *CtrlGet(struct Ctrl *ctrl, u16f code, u8f type); +struct InputAxis *CtrlGet(struct Controller *ctrl, u16f code, u8f type); -bool CtrlPoll(struct Ctrl *ctrl); \ No newline at end of file +bool CtrlPoll(struct Controller *ctrl); \ No newline at end of file diff --git a/source/io/input.c b/source/io/input.c index 87ddc34..3af6458 100644 --- a/source/io/input.c +++ b/source/io/input.c @@ -32,12 +32,12 @@ void *block_input(void *args_ptr) return nullptr; } -void StartInput(struct Ctrl *ctrl) +void StartInput(struct Controller *ctrl) { pthread_create(&ctrl->thread, nullptr, block_input, &ctrl->buf); } -void JoinInput(struct Ctrl *ctrl) +void JoinInput(struct Controller *ctrl) { pthread_join(ctrl->thread, nullptr); } \ No newline at end of file diff --git a/source/io/input.h b/source/io/input.h index c9b3732..3b9ba11 100644 --- a/source/io/input.h +++ b/source/io/input.h @@ -8,6 +8,6 @@ #include "ctrl.h" #include "fumotris.h" -void StartInput(struct Ctrl *ctrl); +void StartInput(struct Controller *ctrl); -void JoinInput(struct Ctrl *ctrl); \ No newline at end of file +void JoinInput(struct Controller *ctrl); \ No newline at end of file diff --git a/source/io/platforms/win.c b/source/io/platforms/win.c index 18ffe6c..37944b1 100644 --- a/source/io/platforms/win.c +++ b/source/io/platforms/win.c @@ -10,22 +10,17 @@ #include "winhandler.h" #include "term.h" -#include - bool WindowsInit(struct Terminal *term) { if (!WinInitHandles()) return false; - printf("shid "); - if (!WinInitConsole()) { - printf("%u\n", GetLastError()); + if (!WinInitConsole()) return false; - } - printf("console"); + if (!WinGetRefreshRate(&term->refresh_rate)) return false; - printf("???"); + return true; } diff --git a/source/io/platforms/winhandler.c b/source/io/platforms/winhandler.c index 066bf4c..d813b30 100644 --- a/source/io/platforms/winhandler.c +++ b/source/io/platforms/winhandler.c @@ -39,9 +39,9 @@ bool WinInitConsole() { DWORD mode = ENABLE_EXTENDED_FLAGS | ENABLE_PROCESSED_INPUT + | ENABLE_PROCESSED_OUTPUT | ENABLE_MOUSE_INPUT - | ENABLE_WINDOW_INPUT - | ENABLE_VIRTUAL_TERMINAL_PROCESSING; + | ENABLE_WINDOW_INPUT; return SetConsoleMode(win.input_handle, mode) != 0; } @@ -62,34 +62,36 @@ bool WinGetRefreshRate(u16f *out) return true; } -void set_key_record(struct Record *record, KEY_EVENT_RECORD win_key) +void set_key_record(struct InputRecord *rec, KEY_EVENT_RECORD win_key) { - record->type = KEY; - record->id = win_key.wVirtualKeyCode; - record->data.key.is_down = win_key.bKeyDown; + rec->type = KEY; + rec->bind = win_key.wVirtualKeyCode; + + rec->button.is_down = win_key.bKeyDown; + rec->button.is_up = !win_key.bKeyDown; if (win_key.wVirtualKeyCode == VK_ESCAPE) - record->type = ESCAPE; + rec->type = ESCAPE; } -bool set_mouse_record(struct Record *record, MOUSE_EVENT_RECORD win_mouse) +bool set_mouse_record(struct InputRecord *rec, MOUSE_EVENT_RECORD win_mouse) { switch (win_mouse.dwEventFlags) { case MOUSE_WHEELED: - record->type = AXIS; - record->id = 0; - record->data.axis.value = win_mouse.dwButtonState; + rec->type = AXIS; + rec->bind = 0; + rec->axis.value = win_mouse.dwButtonState; break; case MOUSE_HWHEELED: - record->type = AXIS; - record->id = 1; - record->data.axis.value = win_mouse.dwButtonState; + rec->type = AXIS; + rec->bind = 1; + rec->axis.value = win_mouse.dwButtonState; break; case MOUSE_MOVED: - record->type = JOYSTICK; - record->id = 0; - record->data.joystick.x = win_mouse.dwMousePosition.X; - record->data.joystick.y = win_mouse.dwMousePosition.Y; + rec->type = JOYSTICK; + rec->bind = 0; + rec->joystick.x = win_mouse.dwMousePosition.X; + rec->joystick.y = win_mouse.dwMousePosition.Y; break; default: return false; @@ -97,19 +99,19 @@ bool set_mouse_record(struct Record *record, MOUSE_EVENT_RECORD win_mouse) return true; } -bool dispatch_record(struct Record *record, INPUT_RECORD win_record) +bool dispatch_record(struct InputRecord *rec, INPUT_RECORD win_rec) { - switch (win_record.EventType) { + switch (win_rec.EventType) { case KEY_EVENT: - set_key_record(record, win_record.Event.KeyEvent); + set_key_record(rec, win_rec.Event.KeyEvent); break; case MOUSE_EVENT: - return set_mouse_record(record, win_record.Event.MouseEvent); + return set_mouse_record(rec, win_rec.Event.MouseEvent); case WINDOW_BUFFER_SIZE_EVENT: // TODO: Handle window resizing return false; default: - record->type = ESCAPE; + rec->type = ESCAPE; } return true; } @@ -134,14 +136,14 @@ bool WinBlockInput(struct RecordBuffer *buf) pthread_mutex_lock(&buf->mutex); for (size_t i = 0; i < count; i++) { - struct Record record; - record.timestamp = now; + struct InputRecord rec; + rec.timestamp = now; - bool include = dispatch_record(&record, win_buf[i]); + bool include = dispatch_record(&rec, win_buf[i]); if (!include) continue; - buf->records[buf->count++] = record; + buf->records[buf->count++] = rec; } pthread_mutex_unlock(&buf->mutex); diff --git a/source/main.c b/source/main.c index 77c0442..8a2396c 100644 --- a/source/main.c +++ b/source/main.c @@ -16,6 +16,15 @@ #include "win.h" #endif +struct Instance { + struct Controller ctrl; + struct Terminal term; + + struct Delegate on_start; + struct Delegate on_update; + struct Delegate on_draw; +}; + const u8 I[16] = { 0, 0, 0, 0, 0, 0, 0, 0, @@ -58,16 +67,6 @@ const u8 L[9] = { 0, 0, 0 }; -struct Instance { - struct Ctrl ctrl; - - struct Delegate on_start; - struct Delegate on_update; - struct Delegate on_draw; - - struct Terminal term; -}; - struct CtrlBind { enum CtrlCode code; u16 bind; @@ -94,19 +93,18 @@ void *Update(void *args) { struct Instance *game = args; - struct TChar4 blks[game->term.area]; - game->term.blks = blks; - while (true) { // Input CtrlPoll(&game->ctrl); + if (CtrlGet(&game->ctrl, LEFT, KEY)->button.is_down) + printf("left down this frame\n"); // Game logic - Invoke(&game->on_update, game); + //Invoke(&game->on_update, game); // Draw - TermOut(&game->term); - puts(game->term.buf); + //TermOut(&game->term); + //puts(game->term.buf); } } @@ -128,6 +126,13 @@ bool Start(struct Instance *game) if (!NewTerm(&game->term, 20, 20)) return false; + + if (!NewDelegate(&game->on_start, 16)) + return false; + if (!NewDelegate(&game->on_update, 16)) + return false; + if (!NewDelegate(&game->on_draw, 16)) + return false; return true; } @@ -135,15 +140,13 @@ bool Start(struct Instance *game) int main() { struct Instance game; - Start(&game); + if (!Start(&game)) + exit(1); #ifdef _WIN32 - if(!WindowsInit(&game.term)) { - printf("FUCK"); + if(!WindowsInit(&game.term)) exit(1); - } #endif - printf("does it work"); StartInput(&game.ctrl); Loop(&game); diff --git a/source/term/term.c b/source/term/term.c index 6f7dc38..c829669 100644 --- a/source/term/term.c +++ b/source/term/term.c @@ -35,9 +35,14 @@ size_t term_buf_size(size_t area, size_t hgt) return reset_str_len + (max_color_str_len + 1) * area + hgt + 1; } -size_t blks_size(size_t area) +struct TChar4 *alloc_blks(size_t area) { - return area * sizeof(struct TChar4); + return calloc(area, sizeof(struct TChar4)); +} + +char *alloc_buf(size_t buf_size) +{ + return malloc(buf_size); } bool NewTerm(struct Terminal *term, size_t wid, size_t hgt) @@ -45,17 +50,17 @@ bool NewTerm(struct Terminal *term, size_t wid, size_t hgt) size_t area = wid * hgt; size_t buf_size = term_buf_size(area, hgt); - struct TChar4 *tchs = malloc(blks_size(area)); - char *buf = malloc(buf_size); + struct TChar4 *blks = alloc_blks(area); + char *buf = alloc_buf(buf_size); - if (tchs == nullptr or buf == nullptr) + if (blks == nullptr or buf == nullptr) return false; *term = (struct Terminal) { .wid = wid, .hgt = hgt, .area = area, - .blks = tchs, + .blks = blks, .buf_size = buf_size, .buf = buf, @@ -70,8 +75,9 @@ bool ResizeTerm(struct Terminal *term, size_t wid, size_t hgt) size_t area = wid * hgt; size_t buf_size = term_buf_size(area, hgt); - struct TChar4 *tchs = realloc(term->blks, blks_size(area)); + struct TChar4 *tchs = realloc(term->blks, area * sizeof(struct TChar4)); char *buf = realloc(term->buf, buf_size); + if (tchs == nullptr or buf == nullptr) return false; diff --git a/test.exe b/test.exe index e084d5b381f7ab23a185ab5b12253520e99d31e2..3e4986bbff17579de7c10a51102407071e81eafd 100644 GIT binary patch delta 16976 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 Z?bHiK_N>Ck7D`@NlK0l8RB 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 Daf6WA