ok
This commit is contained in:
Julia 2024-04-29 15:01:48 -05:00
parent 3de83d481e
commit 2e976a8d2e
11 changed files with 231 additions and 96 deletions

View file

@ -1,35 +1,67 @@
#pragma once
#include "ringbuffer.h"
#include <string.h>
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)
void *RingBufferGet(RingBufferT T, struct RingBufferHead *head, size_t i)
{
struct rbuf_generic *write = dest;
struct rbuf_generic *read = tmp;
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;
}

View file

@ -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) }
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
);

View file

@ -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;
}

View file

@ -1,7 +1,9 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#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,

View file

@ -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()

View file

@ -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,

View file

@ -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;

View file

@ -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);
bool EndInputThread(struct InputHandle *hand);
bool InputAquire(struct InputHandle *hand);
bool InputRelease(struct InputHandle *hand);

View file

@ -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;
return true;
}
case MOUSE_MOVE: {
ReadJoystick(out, 0, rec->mouse.pos.x, rec->mouse.pos.y);
case WINDOW_BUFFER_SIZE_EVENT:
return false;
// TODO: Handle window resizing
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;
}
}

View file

@ -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");
EventInvokeUpdate(&game.Update, nullptr);
//printf("%u\n", ctrl.recs.head.len);
//CtrlPoll(&ctrl);
if (!InputRelease(&input_hand))
ErrorExit("Release failed");
EventInvokeUpdate(&game.Update, 0);
}
return 0;

BIN
test.exe

Binary file not shown.