diff --git a/source/datastructures/ringbuffer.c b/source/datastructures/ringbuffer.c index fb90b00..720e4c7 100644 --- a/source/datastructures/ringbuffer.c +++ b/source/datastructures/ringbuffer.c @@ -1,35 +1,67 @@ -#pragma once #include "ringbuffer.h" #include -struct rbuf_generic { +struct ring_buf { struct RingBufferHead head; - u8 arr[]; + u8 bytes[]; }; -inline void *rbuf_start(RingBufferT T, struct rbuf_generic *rbuf, size_t i) +void *get_ptr(RingBufferT T, struct RingBufferHead *head, size_t i) { - size_t wrap_i = (rbuf->head.start + i) % T->LEN; - return rbuf->arr + wrap_i * T->SIZE; + struct ring_buf *ring = (struct ring_buf *)head; + return ring->bytes + T->SIZE * i; } -inline void *rbuf_tail(RingBufferT T, struct rbuf_generic *rbuf, size_t i) +size_t RingBufferEmpty(RingBufferT T, struct RingBufferHead *head) { - size_t wrap_i = (rbuf->head.start + rbuf->head.len + i) % T->LEN; - return rbuf->arr + i * T->SIZE; + return T->LEN - head->len; } -void RingBufferTransfer(RingBufferT T, RingBuffer *dest, RingBuffer *tmp) -{ - struct rbuf_generic *write = dest; - struct rbuf_generic *read = tmp; +void *RingBufferGet(RingBufferT T, struct RingBufferHead *head, size_t i) +{ + size_t wrap_i = (head->start + i) % T->LEN; + return get_ptr(T, head, wrap_i); +} - size_t copy_max = min_size(T->LEN - write->head.len, read->head.len); +void *RingBufferNext(RingBufferT T, struct RingBufferHead *head) +{ + size_t wrap_i = (head->start + head->len) % T->LEN; + return get_ptr(T, head, wrap_i); +} + +void RingBufferAdd(RingBufferT T, struct RingBufferHead *dest, void *item) +{ + memcpy(RingBufferNext(T, dest), item, T->SIZE); +} + +void RingBufferTransfer( + RingBufferT T, + struct RingBufferHead *dest, + struct RingBufferHead *src +) { + size_t copy_max = min_size(T->LEN - dest->len, src->len); for (size_t i = 0; i < copy_max; i++) { - memcpy(rbuf_tail(T, write, i), rbuf_start(T, read, i), T->LEN); + void *to = RingBufferGet(T, dest_head, dest->len + i); + void *from = RingBufferGet(T, src_head, i); + memcpy(to, from, T->SIZE); } - write->head.start += copy_max; - read->head.len -= copy_max; + dest->len += copy_max; + src->len -= copy_max; +} + +size_t RingBufferOut(RingBufferT T, size_t n, void *dest, void *src_head) +{ + struct ring_buf *src = src_head; + + size_t copy_max = min_size(n, src->head.len); + + for (size_t i = 0; i < copy_max; i++) { + void *to = (char *)dest + i * T->SIZE; + void *from = RingBufferGet(T, src, i); + memcpy(to, from, T->SIZE); + } + + return copy_max; } \ No newline at end of file diff --git a/source/datastructures/ringbuffer.h b/source/datastructures/ringbuffer.h index 6f5af8c..8038491 100644 --- a/source/datastructures/ringbuffer.h +++ b/source/datastructures/ringbuffer.h @@ -7,8 +7,6 @@ #include "fumotris.h" -typedef void *RingBuffer; - typedef const struct RingBufferT { size_t LEN; size_t SIZE; @@ -19,6 +17,27 @@ struct RingBufferHead { u8f start; }; -void RingBufferTransfer(RingBufferT T, RingBuffer *dest, RingBuffer *tmp); +#define RINGBUF_HEAD_INIT ((struct RingBufferHead) { 0, 0 }) -#define INIT_RING_BUF_T(len, type) &(struct RingBufferT) { len, sizeof(type) } \ No newline at end of file +size_t RingBufferEmpty(RingBufferT T, struct RingBufferHead *head); + +void *RingBufferGet( + RingBufferT T, + struct RingBufferHead *head, + size_t i +); + +void *RingBufferNext(RingBufferT T, struct RingBufferHead *head); + +void RingBufferTransfer( + RingBufferT T, + struct RingBufferHead *dest, + struct RingBufferHead *tmp +); + +size_t RingBufferOut( + RingBufferT T, + size_t n, + void *dest, + struct RingBufferHead *src +); \ No newline at end of file diff --git a/source/fumotris.c b/source/fumotris.c index d81b99a..ac5853f 100644 --- a/source/fumotris.c +++ b/source/fumotris.c @@ -1,6 +1,6 @@ #include "fumotris.h" -inline size_t min_size(size_t a, size_t b) +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 d7488a6..4fb5281 100644 --- a/source/fumotris.h +++ b/source/fumotris.h @@ -1,7 +1,9 @@ #pragma once +#include #include -#define nullptr ((void*)0) +#define nullptr ((void *)0) + typedef uint8_t u8; typedef uint_fast8_t u8f; @@ -28,7 +30,9 @@ 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); + +size_t min_size(size_t a, size_t b); + /*const u8 I[16] = { 0, 0, 0, 0, diff --git a/source/io/ctrl.c b/source/io/ctrl.c index f2b283d..2fda0ef 100644 --- a/source/io/ctrl.c +++ b/source/io/ctrl.c @@ -1,5 +1,7 @@ #include "ctrl.h" +#include "ringbuffer.h" + #define INIT_SIZE 16 bool CreateCtrl(struct Controller *ctrl) @@ -12,7 +14,7 @@ bool CreateCtrl(struct Controller *ctrl) return false; *ctrl = (struct Controller) { - .recs.len = 0, + .recs.head = RINGBUF_HEAD_INIT, .pending_buf.len = 0, .axis_vec = (struct ctrl_axis_vec) { @@ -49,7 +51,7 @@ size_t wrap_index(size_t i, size_t max) { return i % (SIZE_MAX - max + 1); } -struct ctrl_bkt *find_or_set(struct ctrl_dict *dict, union InputID id) +struct ctrl_bkt *find_set(struct ctrl_dict *dict, union InputID id) { size_t i = id.hash % dict->capacity; @@ -99,14 +101,14 @@ struct InputAxis *find_axis(struct ctrl_dict *dict, union InputID id) return bkt->axis; } -union InputID to_id(u16f value, u16f type) { +union InputID as_id(u16f value, u16f type) { return (union InputID) { .value = value, .type = type }; } bool CtrlMap(struct Controller *ctrl, u16f code, u16f type, u16f bind) { - struct ctrl_bkt *code_bkt = find_or_set(&ctrl->codes, to_id(code, type)); - struct ctrl_bkt *bind_bkt = find_or_set(&ctrl->binds, to_id(bind, type)); + struct ctrl_bkt *code_bkt = find_set(&ctrl->codes, as_id(code, type)); + struct ctrl_bkt *bind_bkt = find_set(&ctrl->binds, as_id(bind, type)); if (code_bkt->axis == nullptr) code_bkt->axis = &ctrl->axis_vec.axes[ctrl->axis_vec.len++]; @@ -120,7 +122,7 @@ bool CtrlMap(struct Controller *ctrl, u16f code, u16f type, u16f bind) struct InputAxis *CtrlGet(struct Controller *ctrl, u16f code, u16f type) { - struct ctrl_bkt *code_bkt = find(&ctrl->codes, to_id(code, type)); + struct ctrl_bkt *code_bkt = find(&ctrl->codes, as_id(code, type)); if (code_bkt == nullptr) return nullptr; @@ -152,7 +154,7 @@ void CtrlPoll(struct Controller *ctrl) } ctrl->pending_buf.len = 0; - for (size_t i = 0; i < ctrl->recs.len; i++) { + for (size_t i = 0; i < ctrl->recs.head.len; i++) { struct InputRecord *rec = &ctrl->recs.buf[i]; struct InputAxis *axis = find_axis(&ctrl->binds, rec->id); @@ -164,12 +166,12 @@ void CtrlPoll(struct Controller *ctrl) ctrl->pending_buf.axes[ctrl->pending_buf.len++] = axis; } - ctrl->recs.len = 0; + ctrl->recs.head.len = 0; } size_t CtrlInputString(struct Controller *ctrl, size_t n, char *buf) { - size_t copy_max = min_size(ctrl->str.len, n); + return RingBufferOut(&STR_BUF_T, n, buf, &ctrl->str.head); } /*int main() diff --git a/source/io/ctrl.h b/source/io/ctrl.h index e64d4e8..875475a 100644 --- a/source/io/ctrl.h +++ b/source/io/ctrl.h @@ -68,7 +68,9 @@ 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, struct InputThreadHandle *hand); +void CtrlPoll(struct Controller *ctrl); + +size_t CtrlInputString(struct Controller *ctrl, size_t n, char *buf); enum ControlCode { LEFT, diff --git a/source/io/input.c b/source/io/input.c index ffd3223..a1c5300 100644 --- a/source/io/input.c +++ b/source/io/input.c @@ -3,65 +3,114 @@ #include "platform.h" -void *input_thread_loop(void *arg) -{ - struct InputThreadHandle *hand = arg; +const struct RingBufferT IO_BUF_T = { + .LEN = IO_BUF_SIZE, + .SIZE = sizeof(struct InputRecord) +}; - struct InputRecordBuf tmp_in = { .head.len = 0, .head.start = 0 }; +const struct RingBufferT STR_BUF_T = { + .LEN = STR_BUF_SIZE, + .SIZE = sizeof(char) +}; + +void *input_worker(void *arg) +{ + struct InputHandle *hand = arg; + + struct InputRecordBuf tmp_recs = { .head.len = 0, .head.start = 0 }; struct InputStringBuf tmp_str = { .head.len = 0, .head.start = 0 }; while (!hand->is_terminating) { - if (!PlatformReadInput(&tmp_in, &tmp_str)) + if (!PlatformReadInput(&tmp_recs, &tmp_str)) { + hand->err = true; return nullptr; + } + printf("input read, len:%u\n", hand->recs->head.len); - if (hand->err = pthread_mutex_lock(&hand->mutex)) - return nullptr; - - while (tmp_in.head.len == IO_BUF_SIZE) { - if (hand->err = pthread_cond_wait(&hand->consume, &hand->mutex)) - return nullptr; + for (int i = 0; i < hand->recs->head.len; i++) { + struct InputRecord *rec = RingBufferGet(&IO_BUF_T, &hand->recs->head, i); + printf("\ti:%u, type:%u, but:%u\n", i, rec->id.type, rec->id.bind); } - RingBufferTransfer(IO_BUF_T, hand->in, &tmp_in); - RingBufferTransfer(STR_BUF_T, hand->str, &tmp_str); - - if (hand->err = pthread_mutex_unlock(&hand->mutex)) + if (pthread_mutex_lock(&hand->mutex) != 0) { + hand->err = true; return nullptr; + } + + while (tmp_recs.head.len == IO_BUF_SIZE) { + if (pthread_cond_wait(&hand->is_consumed, &hand->mutex) != 0) { + hand->err = true; + return nullptr; + } + } + + RingBufferTransfer(&IO_BUF_T, &hand->recs->head, &tmp_recs.head); + RingBufferTransfer(&STR_BUF_T, &hand->str->head, &tmp_str.head); + + if (pthread_mutex_unlock(&hand->mutex) != 0) { + hand->err = true; + return nullptr; + } } return nullptr; } bool BeginInputThread( - struct InputThreadHandle *hand, + struct InputHandle *hand, struct InputRecordBuf *in, struct InputStringBuf *str ) { - *hand = (struct InputThreadHandle) { - .in = in, + *hand = (struct InputHandle) { + .recs = 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; + if (pthread_mutex_init(&hand->mutex, nullptr) != 0) + return false; + + if (pthread_cond_init(&hand->is_consumed, nullptr) != 0) + return false; + + if (pthread_create(&hand->thread, nullptr, input_worker, hand) != 0) + return false; + + return true; } -bool EndInputThread(struct InputThreadHandle *hand) +bool EndInputThread(struct InputHandle *hand) { hand->is_terminating = true; if (!PlatformStopInput()) return false; - if (!pthread_mutex_destroy(&hand->mutex)) + if (pthread_mutex_destroy(&hand->mutex) != 0) return false; - if (!pthread_join(hand->thread, nullptr)) + if (pthread_join(hand->thread, nullptr) != 0) + return false; + + return true; +} + +bool InputAquire(struct InputHandle *hand) +{ + if (pthread_mutex_lock(&hand->mutex) != 0) + return false; + + return true; +} + +bool InputRelease(struct InputHandle *hand) +{ + if (pthread_cond_signal(&hand->is_consumed) != 0) + return false; + + if (pthread_mutex_unlock(&hand->mutex) != 0) return false; return true; diff --git a/source/io/input.h b/source/io/input.h index 9869bec..d21d391 100644 --- a/source/io/input.h +++ b/source/io/input.h @@ -68,8 +68,8 @@ struct InputRecord { }; }; -RingBufferT IO_BUF_T = INIT_RING_BUF_T(IO_BUF_SIZE, struct InputRecord); -RingBufferT STR_BUF_T = INIT_RING_BUF_T(STR_BUF_SIZE, char); +extern const struct RingBufferT IO_BUF_T; +extern const struct RingBufferT STR_BUF_T; struct InputRecordBuf { struct RingBufferHead head; @@ -81,22 +81,26 @@ struct InputStringBuf { char buf[STR_BUF_SIZE]; }; -struct InputThreadHandle { - struct InputRecordBuf *in; +struct InputHandle { + struct InputRecordBuf *recs; struct InputStringBuf *str; pthread_t thread; pthread_mutex_t mutex; - pthread_cond_t consume; + pthread_cond_t is_consumed; int err; bool is_terminating; }; bool BeginInputThread( - struct InputThreadHandle *hand, + struct InputHandle *hand, struct InputRecordBuf *in, struct InputStringBuf *str ); -bool EndInputThread(struct InputThreadHandle *hand); \ No newline at end of file +bool EndInputThread(struct InputHandle *hand); + +bool InputAquire(struct InputHandle *hand); + +bool InputRelease(struct InputHandle *hand); \ No newline at end of file diff --git a/source/io/platforms/win.c b/source/io/platforms/win.c index aa0b62f..3f78519 100644 --- a/source/io/platforms/win.c +++ b/source/io/platforms/win.c @@ -5,6 +5,7 @@ #include "gametime.h" #include "input.h" #include "parseinput.h" +#include "ringbuffer.h" #define MOUSE_MOVE (MOUSE_EVENT | MOUSE_MOVED) #define MOUSE_VWHEEL (MOUSE_EVENT | MOUSE_WHEELED) @@ -71,6 +72,11 @@ struct win_rec { }; }; +union record { + struct win_rec native; + INPUT_RECORD win; +}; + bool init_handles() { win.input_hand = GetStdHandle(STD_INPUT_HANDLE); @@ -127,46 +133,56 @@ bool dispatch_rec( u8f type = rec->type | (rec->is_mouse & rec->mouse.flags); switch (type) { - case KEY_EVENT: - ReadButton(out, rec->key.vk_code, rec->key.is_down); - str->len += UCS2ToUTF8(&str->buf[str->len], rec->key.ucs2_char); - return true; + case KEY_EVENT: { + ReadButton(out, rec->key.vk_code, rec->key.is_down); - case MOUSE_MOVE: - ReadJoystick(out, 0, rec->mouse.pos.x, rec->mouse.pos.y); - return true; + char *to = RingBufferGet(&STR_BUF_T, &str->head, str->head.len); + str->head.len += UCS2ToUTF8(to, rec->key.ucs2_char); - case MOUSE_VWHEEL: - case MOUSE_HWHEEL: - ReadAxis(out, rec->mouse.is_hwheel, rec->mouse.but); - return true; - - case WINDOW_BUFFER_SIZE_EVENT: - return false; - // TODO: Handle window resizing + return true; + } + case MOUSE_MOVE: { + ReadJoystick(out, 0, rec->mouse.pos.x, rec->mouse.pos.y); + + return true; + } + case MOUSE_VWHEEL: { + ReadAxis(out, 0, rec->mouse.but); + + return true; + } + case MOUSE_HWHEEL: { + ReadAxis(out, 1, rec->mouse.but); + + return true; + } + case WINDOW_BUFFER_SIZE_EVENT: { + // TODO: Handle window resizing + + return false; + } } return false; } -bool PlatformReadInput(struct InputRecordBuf *in, struct InputStringBuf *str) +bool PlatformReadInput(struct InputRecordBuf *recs, struct InputStringBuf *str) { - DWORD max_records = IO_BUF_SIZE - in->len; - struct win_rec win_buf[max_records]; + DWORD read_max = RingBufferEmpty(&IO_BUF_T, &recs->head); + union record win_buf[read_max]; DWORD filled; - if (!ReadConsoleInputW(win.input_hand, win_buf, max_records, &filled)) + if (!ReadConsoleInputW(win.input_hand, &win_buf->win, read_max, &filled)) return false; Time now = TimeNow(); for (size_t i = 0; i < filled; i++) { - size_t rec_i = (in->start + in->len) % IO_BUF_SIZE; - struct InputRecord *rec = &in->buf[rec_i]; + struct InputRecord *rec = RingBufferNext(&IO_BUF_T, &recs->head); - if (dispatch_rec(rec, str, win_buf + i)) { + if (dispatch_rec(rec, str, &win_buf->native + i)) { rec->time = now; - in->len += 1; + recs->head.len += 1; } } diff --git a/source/main.c b/source/main.c index 9767d58..359551a 100644 --- a/source/main.c +++ b/source/main.c @@ -36,20 +36,27 @@ int main() if (!CreateCtrl(&ctrl)) ErrorExit("Out of memory"); + CtrlMap(&ctrl, 0, BUTTON, 'A'); + struct Game game; CreateEvent(&game.Update); - struct InputThreadHandle input_hand; + struct InputHandle input_hand; if (!BeginInputThread(&input_hand, &ctrl.recs, &ctrl.str)) ErrorExit("Input handle failed to initialize"); - CtrlMap(&ctrl, 0, BUTTON, 'A'); - + _sleep(1000000); while (true) { - if(!CtrlPoll(&ctrl, &input_hand)) - ErrorExit("Poll failed"); + if (!InputAquire(&input_hand)) + ErrorExit("Aquire failed"); + + //printf("%u\n", ctrl.recs.head.len); + //CtrlPoll(&ctrl); - EventInvokeUpdate(&game.Update, nullptr); + if (!InputRelease(&input_hand)) + ErrorExit("Release failed"); + + EventInvokeUpdate(&game.Update, 0); } return 0; diff --git a/test.exe b/test.exe index 0c466d4..978fa63 100644 Binary files a/test.exe and b/test.exe differ