diff --git a/.vscode/settings.json b/.vscode/settings.json index dddf55c..9070c03 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -54,6 +54,8 @@ "stdbool.h": "c", "gametime.h": "c", "stdlib.h": "c", - "stdio.h": "c" + "stdio.h": "c", + "platform.h": "c", + "ringbuffer.h": "c" } } \ No newline at end of file diff --git a/source/fumotris.c b/source/fumotris.c new file mode 100644 index 0000000..d81b99a --- /dev/null +++ b/source/fumotris.c @@ -0,0 +1,6 @@ +#include "fumotris.h" + +inline size_t min_size(size_t a, size_t b) +{ + return a < b ? a : b; +} \ No newline at end of file diff --git a/source/fumotris.h b/source/fumotris.h index 17ae408..d7488a6 100644 --- a/source/fumotris.h +++ b/source/fumotris.h @@ -28,6 +28,8 @@ typedef int_fast32_t i32f; typedef int64_t i64; typedef int_fast64_t i64f; +inline size_t min_size(size_t a, size_t b); + /*const u8 I[16] = { 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/source/io/ctrl.c b/source/io/ctrl.c index 8b4993e..f2b283d 100644 --- a/source/io/ctrl.c +++ b/source/io/ctrl.c @@ -1,7 +1,5 @@ #include "ctrl.h" -#include - #define INIT_SIZE 16 bool CreateCtrl(struct Controller *ctrl) @@ -14,7 +12,7 @@ bool CreateCtrl(struct Controller *ctrl) return false; *ctrl = (struct Controller) { - .buf.len = 0, + .recs.len = 0, .pending_buf.len = 0, .axis_vec = (struct ctrl_axis_vec) { @@ -144,7 +142,7 @@ void dispatch_update(struct InputAxis *axis, struct InputRecord *rec) axis->data = rec->data; } -void read_input_buf(struct Controller *ctrl) +void CtrlPoll(struct Controller *ctrl) { for (size_t i = 0; i < ctrl->pending_buf.len; i++) { struct InputAxis *axis = ctrl->pending_buf.axes[i]; @@ -154,8 +152,8 @@ void read_input_buf(struct Controller *ctrl) } ctrl->pending_buf.len = 0; - for (size_t i = 0; i < ctrl->buf.len; i++) { - struct InputRecord *rec = &ctrl->buf.buf[i]; + for (size_t i = 0; i < ctrl->recs.len; i++) { + struct InputRecord *rec = &ctrl->recs.buf[i]; struct InputAxis *axis = find_axis(&ctrl->binds, rec->id); @@ -166,29 +164,12 @@ void read_input_buf(struct Controller *ctrl) ctrl->pending_buf.axes[ctrl->pending_buf.len++] = axis; } - ctrl->buf.len = 0; + ctrl->recs.len = 0; } -void read_str_buf(struct Controller *ctrl) +size_t CtrlInputString(struct Controller *ctrl, size_t n, char *buf) { - ctrl->string -} - -bool CtrlPoll(struct Controller *ctrl, struct InputThreadHandle *hand) -{ - if (pthread_mutex_lock(&hand->mutex) != 0) - return false; - - read_input_buf(ctrl); - read_str_buf(ctrl); - - if (pthread_cond_signal(&hand->buf_read) != 0) - return false; - - if (pthread_mutex_unlock(&hand->mutex) != 0) - return false; - - return true; + size_t copy_max = min_size(ctrl->str.len, n); } /*int main() diff --git a/source/io/ctrl.h b/source/io/ctrl.h index 13b016e..4740c56 100644 --- a/source/io/ctrl.h +++ b/source/io/ctrl.h @@ -47,8 +47,8 @@ struct ctrl_axis_vec { }; struct Controller { - struct InputBuffer buf; - struct InputString string; + struct RecordBuffer recs; + struct StringBuffer str; struct { struct InputAxis *axes[IO_BUF_SIZE]; diff --git a/source/io/input.c b/source/io/input.c index 827cb8e..7e89d9b 100644 --- a/source/io/input.c +++ b/source/io/input.c @@ -3,82 +3,82 @@ #include "platform.h" -inline size_t min_size(size_t a, size_t b) { - return a < b ? a : b; -} - -void InputBufferTransfer(struct InputBuffer *dest, struct InputBuffer *src) +void InputBufferTransfer(struct RecordBuffer *dest, struct RecordBuffer *src) { - size_t copy_amt = min_size(IO_BUF_SIZE - dest->len, src->len); + size_t copy_max = min_size(IO_BUF_SIZE - dest->len, src->len); - for (size_t i = 0; i < dest->start; i++) { + for (size_t i = 0; i < copy_max; i++) { size_t dest_i = (dest->start + dest->len + i) % IO_BUF_SIZE; size_t src_i = (src->start + i) % IO_BUF_SIZE; dest->buf[dest_i] = src->buf[src_i]; } - dest->start += copy_amt; - if (copy_amt < src->len) - src->len -= copy_amt; + dest->start += copy_max; + if (copy_max < src->len) + src->len -= copy_max; } -void InputStringTransfer(struct InputString *dest, struct InputString *src) +void StringBufferTransfer(struct StringBuffer *dest, struct StringBuffer *src) { - size_t copy_amt = min_size(STR_BUF_SIZE - dest->len, src->len); + size_t copy_max = min_size(STR_BUF_SIZE - dest->len, src->len); - for (size_t i = 0; i < copy_amt; i++) { + for (size_t i = 0; i < copy_max; i++) { size_t dest_i = (dest->start + dest->len + i) % STR_BUF_SIZE; size_t src_i = (src->start + i) % STR_BUF_SIZE; dest->buf[dest_i] = src->buf[src_i]; } - dest->start += copy_amt; - if (copy_amt < src->len) - src->len -= copy_amt; + dest->start += copy_max; + if (copy_max < src->len) + src->len -= copy_max; } void *input_thread_loop(void *arg) { struct InputThreadHandle *hand = arg; - struct InputBuffer tmp_in = { .len = 0 }; - struct InputString tmp_str = { .len = 0 }; + struct RecordBuffer tmp_in = { .len = 0, .start = 0 }; + struct StringBuffer tmp_str = { .len = 0, .start = 0 }; while (!hand->is_terminating) { - if (!PlatformReadInput(&tmp_in, &tmp_str)) { - hand->err = true; + if (!PlatformReadInput(&tmp_in, &tmp_str)) return nullptr; - } - hand->err = pthread_mutex_lock(&hand->mutex); - if (hand->err) + if (hand->err = pthread_mutex_lock(&hand->mutex)) return nullptr; while (tmp_in.len == IO_BUF_SIZE) { - hand->err = pthread_cond_wait(&hand->buf_read, &hand->mutex); - if (hand->err) + if (hand->err = pthread_cond_wait(&hand->consume, &hand->mutex)) return nullptr; } InputBufferTransfer(hand->in, &tmp_in); - InputStringTransfer(hand->str, &tmp_str); + StringBufferTransfer(hand->str, &tmp_str); - hand->err = pthread_mutex_unlock(&hand->mutex); - if (hand->err) + if (hand->err = pthread_mutex_unlock(&hand->mutex)) return nullptr; } return nullptr; } -bool BeginInputThread(struct InputThreadHandle *hand, struct InputBuffer *buf) -{ - hand->in = buf; - hand->mutex = PTHREAD_MUTEX_INITIALIZER; - hand->buf_read = PTHREAD_COND_INITIALIZER; - hand->err = 0; +bool BeginInputThread( + struct InputThreadHandle *hand, + struct RecordBuffer *in, + struct StringBuffer *str +) { + *hand = (struct InputThreadHandle) { + .in = in, + .str = str, + + .mutex = PTHREAD_MUTEX_INITIALIZER, + .consume = PTHREAD_COND_INITIALIZER, + + .err = 0, + .is_terminating = false, + }; return pthread_create(&hand->thread, nullptr, input_thread_loop, hand) == 0; } diff --git a/source/io/input.h b/source/io/input.h index a3a8f04..a86e8e9 100644 --- a/source/io/input.h +++ b/source/io/input.h @@ -67,34 +67,36 @@ struct InputRecord { }; }; -struct InputBuffer { +struct RecordBuffer { struct InputRecord buf[IO_BUF_SIZE]; u8f len; u8f start; }; -struct InputString { +struct StringBuffer { char buf[STR_BUF_SIZE]; u8f len; u8f start; }; struct InputThreadHandle { - struct InputBuffer *in; - struct InputString *str; + struct RecordBuffer *in; + struct StringBuffer *str; pthread_t thread; pthread_mutex_t mutex; - pthread_cond_t buf_read; + pthread_cond_t consume; int err; bool is_terminating; }; -void InputBufferTransfer(struct InputBuffer *tmp, struct InputBuffer *dest); +void InputBufferTransfer(struct RecordBuffer *tmp, struct RecordBuffer *dest); -void InputBufferAdd(struct InputBuffer *buf, struct InputRecord *src); - -bool BeginInputThread(struct InputThreadHandle *hand, struct InputBuffer *buf); +bool BeginInputThread( + struct InputThreadHandle *hand, + struct RecordBuffer *in, + struct StringBuffer *str +); bool EndInputThread(struct InputThreadHandle *hand); \ No newline at end of file diff --git a/source/io/platforms/parseinput.c b/source/io/platforms/parseinput.c index 7320f25..a627478 100644 --- a/source/io/platforms/parseinput.c +++ b/source/io/platforms/parseinput.c @@ -1,21 +1,40 @@ #include "parseinput.h" -void ParseButton(struct InputRecord *rec, u16f bind, bool is_down) +void ReadButton(struct InputRecord *rec, u16f bind, bool is_down) { rec->id = (union InputID) { .bind = bind, .type = BUTTON }; rec->is_down = is_down; rec->is_up = !is_down; } -void ParseAxis(struct InputRecord *rec, u16f bind, u64 value) +void ReadAxis(struct InputRecord *rec, u16f bind, u64 value) { rec->id = (union InputID) { .bind = bind, .type = AXIS }; rec->axis.value = value; } -void ParseJoystick(struct InputRecord *rec, u16f bind, i32 x, i32 y) +void ReadJoystick(struct InputRecord *rec, u16f bind, i32 x, i32 y) { rec->id = (union InputID) { .bind = bind, .type = JOYSTICK }; rec->js.x = x; rec->js.y = y; +} + +size_t UCS2ToUTF8(char *buf, u16f ucs2) +{ + if (ucs2 < 0xFF) { + buf[0] = ucs2; + return 1; + } + + if (ucs2 < 0x7FF) { + buf[0] = 0xC0 + (ucs2 >> 6); + buf[1] = 0x80 + (ucs2 & 0x3F); + return 2; + } + + buf[0] = 0xE0 + (ucs2 >> 12); + buf[1] = 0x80 + ((ucs2 >> 6) & 0x3F); + buf[2] = 0x80 + (ucs2 & 0x3F); + return 3; } \ No newline at end of file diff --git a/source/io/platforms/parseinput.h b/source/io/platforms/parseinput.h index 4e97352..cb14119 100644 --- a/source/io/platforms/parseinput.h +++ b/source/io/platforms/parseinput.h @@ -7,8 +7,10 @@ #include "fumotris.h" #include "input.h" -void ParseButton(struct InputRecord *rec, u16f bind, bool is_down); +void ReadButton(struct InputRecord *rec, u16f bind, bool is_down); -void ParseAxis(struct InputRecord *rec, u16f bind, u64 value); +void ReadAxis(struct InputRecord *rec, u16f bind, u64 value); -void ParseJoystick(struct InputRecord *rec, u16f bind, i32 x, i32 y); \ No newline at end of file +void ReadJoystick(struct InputRecord *rec, u16f bind, i32 x, i32 y); + +size_t UCS2ToUTF8(char *buf, u16f ucs2); \ No newline at end of file diff --git a/source/io/platforms/platform.h b/source/io/platforms/platform.h index 7a286fc..2aee8e3 100644 --- a/source/io/platforms/platform.h +++ b/source/io/platforms/platform.h @@ -16,7 +16,7 @@ bool PlatformInit(); bool PlatformGetRefreshRate(u16f *out); -bool PlatformReadInput(struct InputBuffer *in, struct InputString *str); +bool PlatformReadInput(struct RecordBuffer *in, struct StringBuffer *str); bool PlatformStopInput(); diff --git a/source/io/platforms/win.c b/source/io/platforms/win.c index 63a238d..75b1d21 100644 --- a/source/io/platforms/win.c +++ b/source/io/platforms/win.c @@ -20,6 +20,37 @@ struct win_coord { SHORT y; }; +struct win_key { + BOOL is_down; + WORD repeat; + WORD vk_code; + WORD vs_code; + WCHAR ucs2_char; + DWORD state; +}; + +struct win_mouse { + struct win_coord pos; + DWORD but; + DWORD state; + + union { + DWORD flags; + + struct { + DWORD is_moved : 1; + DWORD is_dbl_clk : 1; + DWORD is_vwheel : 1; + DWORD is_hwheel : 1; + }; + + struct { + DWORD : 2; + DWORD wheel : 2; + }; + }; +}; + struct win_rec { union { WORD type; @@ -34,37 +65,8 @@ struct win_rec { }; union { - struct { - BOOL is_down; - WORD repeat; - WORD vk_code; - WORD vs_code; - WCHAR ucs2_char; - DWORD state; - } key; - - struct { - struct win_coord pos; - DWORD but; - DWORD state; - - union { - DWORD flags; - - struct { - DWORD is_moved : 1; - DWORD is_dbl_clk : 1; - DWORD is_vwheel : 1; - DWORD is_hwheel : 1; - }; - - struct { - DWORD : 2; - DWORD wheel : 2; - }; - }; - } mouse; - + struct win_key key; + struct win_mouse mouse; struct win_coord window; }; }; @@ -117,47 +119,26 @@ bool PlatformGetRefreshRate(u16f *out) return true; } -size_t ucs2_to_utf8(char *buf, u16f ucs2) -{ - if (ucs2 < 0xFF) { - buf[0] = ucs2; - return 1; - } - - if (ucs2 < 0x7FF) { - buf[0] = 0xC0 + (ucs2 >> 6); - buf[1] = 0x80 + (ucs2 & 0x3F); - return 2; - } - - buf[0] = 0xE0 + (ucs2 >> 12); - buf[1] = 0x80 + ((ucs2 >> 6) & 0x3F); - buf[2] = 0x80 + (ucs2 & 0x3F); - return 3; -} - -inline u8f win_rec_type(struct win_rec *rec) { - return rec->type | (rec->is_mouse & rec->mouse.flags); -} - -bool read_rec( +bool dispatch_rec( struct InputRecord *out, - struct InputString *str, - struct win_rec *in + struct StringBuffer *str, + struct win_rec *rec ) { - switch (win_rec_type(in)) { + u8f type = rec->type | (rec->is_mouse & rec->mouse.flags); + + switch (type) { case KEY_EVENT: - ParseButton(out, in->key.vk_code, in->key.is_down); - str->len += ucs2_to_utf8(&str->buf[str->len], in->key.ucs2_char); + ReadButton(out, rec->key.vk_code, rec->key.is_down); + str->len += UCS2ToUTF8(&str->buf[str->len], rec->key.ucs2_char); return true; case MOUSE_MOVE: - ParseJoystick(out, 0, in->mouse.pos.x, in->mouse.pos.y); + ReadJoystick(out, 0, rec->mouse.pos.x, rec->mouse.pos.y); return true; case MOUSE_VWHEEL: case MOUSE_HWHEEL: - ParseAxis(out, in->mouse.is_hwheel, in->mouse.but); + ReadAxis(out, rec->mouse.is_hwheel, rec->mouse.but); return true; case WINDOW_BUFFER_SIZE_EVENT: @@ -168,7 +149,7 @@ bool read_rec( return false; } -bool PlatformReadInput(struct InputBuffer *in, struct InputString *str) +bool PlatformReadInput(struct RecordBuffer *in, struct StringBuffer *str) { DWORD max_records = IO_BUF_SIZE - in->len; struct win_rec win_buf[max_records]; @@ -177,9 +158,16 @@ bool PlatformReadInput(struct InputBuffer *in, struct InputString *str) if (!ReadConsoleInputW(win.input_hand, win_buf, max_records, &filled)) return false; + Time now = TimeNow(); + for (size_t i = 0; i < filled; i++) { - if (read_rec(in, str, win_buf + i)) + size_t rec_i = (in->start + in->len) % IO_BUF_SIZE; + struct InputRecord *rec = &in->buf[rec_i]; + + if (dispatch_rec(rec, str, win_buf + i)) { + rec->time = now; in->len += 1; + } } return true; diff --git a/source/main.c b/source/main.c index 4ba0caf..9767d58 100644 --- a/source/main.c +++ b/source/main.c @@ -40,7 +40,7 @@ int main() CreateEvent(&game.Update); struct InputThreadHandle input_hand; - if (!BeginInputThread(&input_hand, &ctrl.buf)) + if (!BeginInputThread(&input_hand, &ctrl.recs, &ctrl.str)) ErrorExit("Input handle failed to initialize"); CtrlMap(&ctrl, 0, BUTTON, 'A');