diff --git a/source/game/event.c b/source/game/event.c index a8ac7ad..fe2a9da 100644 --- a/source/game/event.c +++ b/source/game/event.c @@ -1,51 +1,58 @@ -#include -#include -#include -#include -#include +#include "event.h" -#include "fumotris.h" +#define INIT_CAPACITY 16 -struct Delegate { - size_t len; - size_t capacity; - void (**events)(void *args); -}; - -size_t delegate_size(size_t capacity) -{ - return sizeof(void(*)(void *)) * capacity; +size_t clbks_size(size_t capacity) { + return sizeof(union func) * capacity; } -bool NewDelegate(struct Delegate *d, size_t capacity) +bool CreateEvent(struct Event *event) { - void (**events)(void *args) = malloc(delegate_size(capacity)); + union func *callbacks = malloc(clbks_size(INIT_CAPACITY)); - if (events == nullptr) + if (callbacks == nullptr) return false; - *d = (struct Delegate) { + *event = (struct Event) { + .clbks = callbacks, .len = 0, - .capacity = capacity, - .events = malloc(delegate_size(capacity)) + .capacity = INIT_CAPACITY, }; return true; } -void Subscribe(struct Delegate *d, void (*event)(void *args)) +void FreeEvent(struct Event *event) { - if (d->len == d->capacity) { - d->capacity *= 2; - d->events = realloc(d->events, delegate_size(d->capacity)); - } - - d->events[d->len] = event; - d->len += 1; + free(event->clbks); } -void Invoke(struct Delegate *d, void *args) +bool EventSubscribe(struct Event *event, union func callback) { - for (size_t i = 0; i < d->len; i++) { - d->events[i](args); + if (event->len == event->capacity) { + size_t new_cap = event->capacity * 2; + union func *new_clbks = realloc(event->clbks, clbks_size(new_cap)); + + if (new_clbks == nullptr) + return false; + + event->clbks = new_clbks; + event->capacity = new_cap; + } + + event->clbks[event->len++] = callback; + return true; +} + +void EventInvoke(struct Event *event, void *arg) +{ + for (size_t i = 0; i < event->len; i++) { + event->clbks[i].generic(arg); + } +} + +void EventInvokeUpdate(struct Event *event, u64 dt) +{ + for (size_t i = 0; i < event->len; i++) { + event->clbks[i].update(dt); } } \ No newline at end of file diff --git a/source/game/event.h b/source/game/event.h index a3ae0cf..5e4182a 100644 --- a/source/game/event.h +++ b/source/game/event.h @@ -6,15 +6,23 @@ #include #include "fumotris.h" +#include "gametime.h" -struct Delegate { - size_t len; - size_t capacity; - void (**events)(void *args); +union func { + void (*generic)(void *arg); + void (*update)(Time dt); }; -bool NewDelegate(struct Delegate *d, size_t capacity); +struct Event { + union func *clbks; + size_t len; + size_t capacity; +}; -void Subscribe(struct Delegate *d, void (*event)(void *args)); +bool CreateEvent(struct Event *event); -void Invoke(struct Delegate *d, void *args); \ No newline at end of file +bool EventSubscribe(struct Event *event, union func callback); + +void EventInvoke(struct Event *event, void *arg); + +void EventInvokeUpdate(struct Event *event, Time dt); \ No newline at end of file diff --git a/source/game/gametime.c b/source/game/gametime.c index 635a645..50d9b43 100644 --- a/source/game/gametime.c +++ b/source/game/gametime.c @@ -1,24 +1,17 @@ +#include "gametime.h" #include -#include -#ifdef _WIN32 -#include "win.h" -#endif +#define ONE_E_9 1000000000 -struct Time { - u32 sec; - u32 nsec; -}; - -struct Time TimeNow() +Time TimeNow() { struct timespec ts; - // Need to check for failiure timespec_get(&ts, TIME_UTC); - return (struct Time) { ts.tv_sec, ts.tv_nsec }; + + return ts.tv_nsec + ts.tv_sec * ONE_E_9; } -double TimeNowDouble() +double TimeNowD() { struct timespec ts; timespec_get(&ts, TIME_UTC); diff --git a/source/game/gametime.h b/source/game/gametime.h index 61c8dd6..630a436 100644 --- a/source/game/gametime.h +++ b/source/game/gametime.h @@ -1,11 +1,11 @@ #pragma once #include +#include -struct Time { - u32 sec; - u32 nsec; -}; +#include "fumotris.h" -struct Time TimeNow(); +typedef u64 Time; -double TimeNowDouble(); +Time TimeNow(); + +double TimeNowD(); diff --git a/source/io/ctrl.c b/source/io/ctrl.c index 7e25593..cea9ca6 100644 --- a/source/io/ctrl.c +++ b/source/io/ctrl.c @@ -1,5 +1,7 @@ #include "ctrl.h" +#include + #define INIT_SIZE 16 bool CreateCtrl(struct Controller *ctrl) @@ -142,7 +144,7 @@ void dispatch_update(struct InputAxis *axis, struct InputRecord *rec) axis->data = rec->data; } -bool CtrlPoll(struct Controller *ctrl) +bool read_input_buf(struct Controller *ctrl) { for (size_t i = 0; i < ctrl->pending_buf.len; i++) { struct InputAxis *axis = ctrl->pending_buf.axes[i]; @@ -150,22 +152,38 @@ bool CtrlPoll(struct Controller *ctrl) axis->is_up = false; axis->is_down = false; } - ctrl->pending_buf.len = ctrl->buf.len; - + ctrl->pending_buf.len = 0; + for (size_t i = 0; i < ctrl->buf.len; i++) { struct InputRecord *rec = &ctrl->buf.recs[i]; union InputID rec_id = to_id(rec->bind, rec->type); struct InputAxis *axis = find_axis(&ctrl->binds, rec_id); + if (axis == nullptr) continue; dispatch_update(axis, rec); - - ctrl->pending_buf.axes[i] = axis; + ctrl->pending_buf.axes[ctrl->pending_buf.len++] = axis; } - ctrl->buf.len = 0; + ctrl->buf.len = 0; + return true; +} + +bool CtrlPoll(struct Controller *ctrl, struct InputThreadHandle *hand) +{ + if (pthread_mutex_lock(&hand->mutex) != 0) + return false; + + read_input_buf(ctrl); + + if (pthread_cond_signal(&hand->buf_read) != 0) + return false; + + if (pthread_mutex_unlock(&hand->mutex) != 0) + return false; + return true; } diff --git a/source/io/ctrl.h b/source/io/ctrl.h index ce82582..ab6f2e3 100644 --- a/source/io/ctrl.h +++ b/source/io/ctrl.h @@ -1,6 +1,5 @@ #pragma once #include -#include #include #include #include @@ -11,8 +10,8 @@ #include "input.h" struct InputAxis { - struct Time last_pressed; - struct Time last_released; + Time last_pressed; + Time last_released; union { struct Button but; @@ -46,15 +45,18 @@ struct ctrl_axis_vec { struct Controller { struct InputBuffer buf; - struct { - struct InputAxis *axes[IO_BUF_SIZE]; - u16f len; - } pending_buf; + + struct InputAxis *pending_axes[IO_BUF_SIZE]; + char string_input[IO_BUF_SIZE]; + + u8f pending_axes_len; + u8f string_input_len; struct ctrl_axis_vec axis_vec; struct ctrl_dict codes; struct ctrl_dict binds; }; +size_t a = sizeof(struct Controller); bool CreateCtrl(struct Controller *ctrl); @@ -64,7 +66,7 @@ bool CtrlMap(struct Controller *ctrl, u16f code, u16f type, u16f bind); struct InputAxis *CtrlGet(struct Controller *ctrl, u16f code, u16f type); -bool CtrlPoll(struct Controller *ctrl); +bool CtrlPoll(struct Controller *ctrl, struct InputThreadHandle *hand); enum ControlCode { LEFT, diff --git a/source/io/input.c b/source/io/input.c index 7332cd3..93e91c6 100644 --- a/source/io/input.c +++ b/source/io/input.c @@ -6,13 +6,13 @@ struct InputRecord *buf_get(struct InputBuffer *buf, size_t i) { return buf->recs + (buf->start + i) % IO_BUF_SIZE; } -size_t max_size(size_t a, size_t b) { - return a > b ? a : b; +size_t min_size(size_t a, size_t b) { + return a < b ? a : b; } void InputBufferTransfer(struct InputBuffer *dest, struct InputBuffer *src) { - size_t copy_amt = IO_BUF_SIZE - max_size(dest->len, src->len); + size_t copy_amt = min_size(IO_BUF_SIZE - dest->len, src->len); for (size_t i = 0; i < copy_amt; i++) *buf_get(dest, dest->len + i) = *buf_get(src, i); @@ -35,7 +35,6 @@ void *input_thread_loop(void *arg) struct InputBuffer tmp_buf = { .len = 0, .start = 0 }; while (!hand->is_terminating) { - printf("\tinput cycle"); if (!PlatformReadInput(&tmp_buf)) { hand->err = true; return nullptr; @@ -45,7 +44,13 @@ void *input_thread_loop(void *arg) if (hand->err) return nullptr; - InputBufferTransfer(&tmp_buf, hand->buf); + while (tmp_buf.len == IO_BUF_SIZE) { + hand->err = pthread_cond_wait(&hand->buf_read, &hand->mutex); + if (hand->err) + return nullptr; + } + + InputBufferTransfer(hand->buf, &tmp_buf); hand->err = pthread_mutex_unlock(&hand->mutex); if (hand->err) @@ -57,7 +62,11 @@ void *input_thread_loop(void *arg) bool BeginInputThread(struct InputThreadHandle *hand, struct InputBuffer *buf) { + hand->buf = buf; hand->mutex = PTHREAD_MUTEX_INITIALIZER; + hand->buf_read = PTHREAD_COND_INITIALIZER; + hand->err = 0; + return pthread_create(&hand->thread, nullptr, input_thread_loop, hand) == 0; } diff --git a/source/io/input.h b/source/io/input.h index 48d40d2..78dda40 100644 --- a/source/io/input.h +++ b/source/io/input.h @@ -48,7 +48,7 @@ union InputData { }; struct InputRecord { - struct Time time; + Time time; union { struct Button but; @@ -76,6 +76,7 @@ struct InputThreadHandle { pthread_t thread; pthread_mutex_t mutex; + pthread_cond_t buf_read; int err; bool is_terminating; diff --git a/source/io/platforms/platform.h b/source/io/platforms/platform.h index ec995b9..c5fcb49 100644 --- a/source/io/platforms/platform.h +++ b/source/io/platforms/platform.h @@ -20,4 +20,4 @@ bool PlatformReadInput(struct InputBuffer *buf); bool PlatformStopInput(); -bool PlatformWait(struct Time relative); \ No newline at end of file +bool PlatformWait(Time duration); \ No newline at end of file diff --git a/source/io/platforms/win.c b/source/io/platforms/win.c index 7b2825f..1e644bd 100644 --- a/source/io/platforms/win.c +++ b/source/io/platforms/win.c @@ -6,13 +6,7 @@ #include "input.h" struct windows { - union { - HANDLE input_hands[2]; - struct { - HANDLE input_hand; - HANDLE early_exit_hand; - }; - }; + HANDLE input_hand; HANDLE timer; } win; @@ -26,10 +20,6 @@ bool init_handles() if (win.timer == NULL) return false; - win.early_exit_hand = CreateEventW(NULL, FALSE, FALSE, NULL); - if (win.early_exit_hand == NULL) - return false; - return true; } @@ -68,7 +58,7 @@ bool PlatformGetRefreshRate(u16f *out) return true; } -void copy_key_event(struct InputRecord *rec, KEY_EVENT_RECORD *win_key) +void read_key_event(struct InputRecord *rec, KEY_EVENT_RECORD *win_key) { rec->type = BUTTON; rec->bind = win_key->wVirtualKeyCode; @@ -77,7 +67,7 @@ void copy_key_event(struct InputRecord *rec, KEY_EVENT_RECORD *win_key) rec->is_up = !win_key->bKeyDown; } -bool copy_mouse_event(struct InputRecord *rec, MOUSE_EVENT_RECORD *win_mouse) +bool read_mouse_event(struct InputRecord *rec, MOUSE_EVENT_RECORD *win_mouse) { if (win_mouse->dwEventFlags == MOUSE_MOVED) { rec->type = JOYSTICK; @@ -99,15 +89,15 @@ bool copy_mouse_event(struct InputRecord *rec, MOUSE_EVENT_RECORD *win_mouse) return false; } -bool copy_rec(struct InputRecord *rec, INPUT_RECORD *win_rec) +bool read_rec(struct InputRecord *rec, INPUT_RECORD *win_rec) { switch (win_rec->EventType) { case KEY_EVENT: - copy_key_event(rec, &win_rec->Event.KeyEvent); + read_key_event(rec, &win_rec->Event.KeyEvent); return true; case MOUSE_EVENT: - return copy_mouse_event(rec, &win_rec->Event.MouseEvent); + return read_mouse_event(rec, &win_rec->Event.MouseEvent); case WINDOW_BUFFER_SIZE_EVENT: return false; @@ -120,22 +110,17 @@ bool copy_rec(struct InputRecord *rec, INPUT_RECORD *win_rec) bool PlatformReadInput(struct InputBuffer *buf) { - DWORD wait_status = WaitForMultipleObjects(2, win.input_hands, FALSE, 0); - - if (wait_status != 0) - return wait_status == 1; - DWORD max_records = IO_BUF_SIZE - buf->len; INPUT_RECORD win_buf[max_records]; DWORD filled; - + if (!ReadConsoleInputW(win.input_hand, win_buf, max_records, &filled)) return false; struct InputRecord rec = { .time = TimeNow() }; for (size_t i = 0; i < filled; i++) { - if (!copy_rec(&rec, win_buf + i)) + if (!read_rec(&rec, win_buf + i)) continue; InputBufferAdd(buf, &rec); @@ -146,15 +131,15 @@ bool PlatformReadInput(struct InputBuffer *buf) bool PlatformStopInput() { - return SetEvent(win.early_exit_hand) == 0; + return CancelSynchronousIo(win.input_hand); } -bool PlatformWait(struct Time relative) +bool PlatformWait(Time duration) { - LARGE_INTEGER duration; - duration.QuadPart = -10000000 * relative.sec - relative.nsec / 100; + LARGE_INTEGER nsec_div_100; + nsec_div_100.QuadPart = -duration / 100; - if (!SetWaitableTimer(win.timer, &duration, 0, NULL, NULL, FALSE)) + if (!SetWaitableTimer(win.timer, &nsec_div_100, 0, NULL, NULL, FALSE)) return false; DWORD result = WaitForSingleObject(win.timer, INFINITE); diff --git a/source/main.c b/source/main.c index d2314cc..4ba0caf 100644 --- a/source/main.c +++ b/source/main.c @@ -10,7 +10,6 @@ #include "input.h" #include "fumotris.h" #include "term.h" -#include "tetr.h" #include "event.h" #include "platform.h" @@ -20,6 +19,14 @@ void ErrorExit(char *message) exit(1); } +struct Game { + struct Event Start; + struct Event Draw; + struct Event Update; + + Time time; +}; + int main() { if (!PlatformInit()) @@ -29,20 +36,20 @@ int main() if (!CreateCtrl(&ctrl)) ErrorExit("Out of memory"); - struct InputThreadHandle input; - if (!BeginInputThread(&input, &ctrl.buf)) + struct Game game; + CreateEvent(&game.Update); + + struct InputThreadHandle input_hand; + if (!BeginInputThread(&input_hand, &ctrl.buf)) ErrorExit("Input handle failed to initialize"); CtrlMap(&ctrl, 0, BUTTON, 'A'); while (true) { - bool poll = CtrlPoll(&ctrl); - printf("poll: %u\n", poll); + if(!CtrlPoll(&ctrl, &input_hand)) + ErrorExit("Poll failed"); - struct InputAxis *a = CtrlGet(&ctrl, 0, BUTTON); - printf("get: %llu\n", a); - - printf("val: %u\n", a->but.value); + EventInvokeUpdate(&game.Update, nullptr); } return 0; diff --git a/test.exe b/test.exe index 0f79fc9..0c466d4 100644 Binary files a/test.exe and b/test.exe differ