From f65cc081b3851c22df1925ad947619391aeac5f0 Mon Sep 17 00:00:00 2001 From: Julia <145168563+julia-aph@users.noreply.github.com> Date: Mon, 29 Apr 2024 23:43:41 -0500 Subject: [PATCH] klj ; --- source/datastructures/ringbuffer.c | 36 ++++++++++++++--------------- source/datastructures/ringbuffer.h | 9 +++++--- source/io/ctrl.c | 3 ++- source/io/input.c | 22 +++++++----------- source/io/platforms/platform.h | 2 +- source/io/platforms/win.c | 17 +++++--------- source/main.c | 14 ++++++++--- test.exe | Bin 85631 -> 85681 bytes 8 files changed, 52 insertions(+), 51 deletions(-) diff --git a/source/datastructures/ringbuffer.c b/source/datastructures/ringbuffer.c index 720e4c7..de2e8a3 100644 --- a/source/datastructures/ringbuffer.c +++ b/source/datastructures/ringbuffer.c @@ -1,15 +1,10 @@ #include "ringbuffer.h" #include -struct ring_buf { - struct RingBufferHead head; - u8 bytes[]; -}; - void *get_ptr(RingBufferT T, struct RingBufferHead *head, size_t i) { - struct ring_buf *ring = (struct ring_buf *)head; - return ring->bytes + T->SIZE * i; + u8 *bytes = (u8 *)head; + return bytes + T->OFFSET + T->SIZE * i; } size_t RingBufferEmpty(RingBufferT T, struct RingBufferHead *head) @@ -32,36 +27,41 @@ void *RingBufferNext(RingBufferT T, struct RingBufferHead *head) void RingBufferAdd(RingBufferT T, struct RingBufferHead *dest, void *item) { memcpy(RingBufferNext(T, dest), item, T->SIZE); + dest->len += 1; } void RingBufferTransfer( RingBufferT T, struct RingBufferHead *dest, - struct RingBufferHead *src + struct RingBufferHead *tmp ) { - size_t copy_max = min_size(T->LEN - dest->len, src->len); + size_t copy_max = min_size(T->LEN - dest->len, tmp->len); for (size_t i = 0; i < copy_max; i++) { - void *to = RingBufferGet(T, dest_head, dest->len + i); - void *from = RingBufferGet(T, src_head, i); + void *to = RingBufferGet(T, dest, dest->len + i); + void *from = RingBufferGet(T, tmp, i); memcpy(to, from, T->SIZE); } dest->len += copy_max; - src->len -= copy_max; + tmp->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); +size_t RingBufferOut( + RingBufferT T, + size_t n, + void *dest, + struct RingBufferHead *src +) { + size_t copy_max = min_size(n, src->len); for (size_t i = 0; i < copy_max; i++) { - void *to = (char *)dest + i * T->SIZE; + void *to = (u8 *)dest + i * T->SIZE; void *from = RingBufferGet(T, src, i); memcpy(to, from, T->SIZE); } + src->len -= copy_max; + return copy_max; } \ No newline at end of file diff --git a/source/datastructures/ringbuffer.h b/source/datastructures/ringbuffer.h index 8038491..267aa3f 100644 --- a/source/datastructures/ringbuffer.h +++ b/source/datastructures/ringbuffer.h @@ -8,13 +8,14 @@ #include "fumotris.h" typedef const struct RingBufferT { - size_t LEN; + size_t OFFSET; size_t SIZE; + size_t LEN; } *const RingBufferT; struct RingBufferHead { - u8f len; - u8f start; + size_t len; + size_t start; }; #define RINGBUF_HEAD_INIT ((struct RingBufferHead) { 0, 0 }) @@ -29,6 +30,8 @@ void *RingBufferGet( void *RingBufferNext(RingBufferT T, struct RingBufferHead *head); +void RingBufferAdd(RingBufferT T, struct RingBufferHead *dest, void *item); + void RingBufferTransfer( RingBufferT T, struct RingBufferHead *dest, diff --git a/source/io/ctrl.c b/source/io/ctrl.c index 2fda0ef..affe3ed 100644 --- a/source/io/ctrl.c +++ b/source/io/ctrl.c @@ -156,9 +156,10 @@ void CtrlPoll(struct Controller *ctrl) for (size_t i = 0; i < ctrl->recs.head.len; i++) { struct InputRecord *rec = &ctrl->recs.buf[i]; + if (rec->id.type == BUTTON and rec->is_down) + ctrl->str struct InputAxis *axis = find_axis(&ctrl->binds, rec->id); - if (axis == nullptr) continue; diff --git a/source/io/input.c b/source/io/input.c index a1c5300..9440bff 100644 --- a/source/io/input.c +++ b/source/io/input.c @@ -4,13 +4,15 @@ #include "platform.h" const struct RingBufferT IO_BUF_T = { - .LEN = IO_BUF_SIZE, - .SIZE = sizeof(struct InputRecord) + .OFFSET = offsetof(struct InputRecordBuf, buf), + .SIZE = sizeof(struct InputRecord), + .LEN = IO_BUF_SIZE }; const struct RingBufferT STR_BUF_T = { - .LEN = STR_BUF_SIZE, - .SIZE = sizeof(char) + .OFFSET = offsetof(struct InputStringBuf, buf), + .SIZE = sizeof(char), + .LEN = STR_BUF_SIZE }; void *input_worker(void *arg) @@ -18,20 +20,13 @@ 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_recs, &tmp_str)) { + if (!PlatformReadInput(&tmp_recs)) { hand->err = true; return nullptr; } - printf("input read, len:%u\n", hand->recs->head.len); - - 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); - } - + if (pthread_mutex_lock(&hand->mutex) != 0) { hand->err = true; return nullptr; @@ -45,7 +40,6 @@ void *input_worker(void *arg) } 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; diff --git a/source/io/platforms/platform.h b/source/io/platforms/platform.h index 0938bf1..f4dd9ca 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 InputRecordBuf *in, struct InputStringBuf *str); +bool PlatformReadInput(struct InputRecordBuf *in); bool PlatformStopInput(); diff --git a/source/io/platforms/win.c b/source/io/platforms/win.c index 3f78519..f6b91cf 100644 --- a/source/io/platforms/win.c +++ b/source/io/platforms/win.c @@ -125,20 +125,15 @@ bool PlatformGetRefreshRate(u16f *out) return true; } -bool dispatch_rec( - struct InputRecord *out, - struct InputStringBuf *str, - struct win_rec *rec -) { - u8f type = rec->type | (rec->is_mouse & rec->mouse.flags); +bool dispatch_rec(struct InputRecord *out, struct win_rec *rec) { + u8f type = rec->type + | (rec->is_mouse & rec->mouse.flags) + | (rec->is_key & rec->key.is_down); switch (type) { case KEY_EVENT: { ReadButton(out, rec->key.vk_code, rec->key.is_down); - char *to = RingBufferGet(&STR_BUF_T, &str->head, str->head.len); - str->head.len += UCS2ToUTF8(to, rec->key.ucs2_char); - return true; } case MOUSE_MOVE: { @@ -166,7 +161,7 @@ bool dispatch_rec( return false; } -bool PlatformReadInput(struct InputRecordBuf *recs, struct InputStringBuf *str) +bool PlatformReadInput(struct InputRecordBuf *recs) { DWORD read_max = RingBufferEmpty(&IO_BUF_T, &recs->head); union record win_buf[read_max]; @@ -180,7 +175,7 @@ bool PlatformReadInput(struct InputRecordBuf *recs, struct InputStringBuf *str) for (size_t i = 0; i < filled; i++) { struct InputRecord *rec = RingBufferNext(&IO_BUF_T, &recs->head); - if (dispatch_rec(rec, str, &win_buf->native + i)) { + if (dispatch_rec(rec, &win_buf->native + i)) { rec->time = now; recs->head.len += 1; } diff --git a/source/main.c b/source/main.c index 359551a..3d1091f 100644 --- a/source/main.c +++ b/source/main.c @@ -45,17 +45,25 @@ int main() if (!BeginInputThread(&input_hand, &ctrl.recs, &ctrl.str)) ErrorExit("Input handle failed to initialize"); - _sleep(1000000); while (true) { if (!InputAquire(&input_hand)) ErrorExit("Aquire failed"); - //printf("%u\n", ctrl.recs.head.len); - //CtrlPoll(&ctrl); + CtrlPoll(&ctrl); + + struct InputAxis *a = CtrlGet(&ctrl, 0, BUTTON); + printf("%u", a); + printf("\t%u\n", a->is_down); + + char silly[100] = { 0 }; + CtrlInputString(&ctrl, 100, silly); + printf("%s\n", silly); if (!InputRelease(&input_hand)) ErrorExit("Release failed"); + _sleep(100); + EventInvokeUpdate(&game.Update, 0); } diff --git a/test.exe b/test.exe index 978fa636adcfa5922497446d53a9cb18da00d021..cc8b6c2e7cb0856e17a45f661ec5e66afae8e8b9 100644 GIT binary patch delta 18415 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