uikhj
This commit is contained in:
Julia 2024-04-16 17:14:53 -05:00
parent f64b77ac21
commit e856594741
15 changed files with 200 additions and 125 deletions

View file

@ -5,17 +5,17 @@
#include "win.h" #include "win.h"
#endif #endif
double GetTime() struct timespec TimeNow()
{
struct timespec ts;
timespec_get(&ts, TIME_UTC);
return ts;
}
double TimeNowDouble()
{ {
struct timespec ts; struct timespec ts;
timespec_get(&ts, TIME_UTC); timespec_get(&ts, TIME_UTC);
return ts.tv_sec + (double)ts.tv_nsec / 1000000000.0; return ts.tv_sec + (double)ts.tv_nsec / 1000000000.0;
}
bool Wait(double seconds)
{
#ifdef _WIN32
return WindowsWait(seconds);
#endif
} }

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <stdbool.h> #include <stdbool.h>
double GetTime(); struct timespec TimeNow();
bool Wait(double seconds); double TimeNowDouble();

View file

@ -9,50 +9,9 @@
#include "fumotris.h" #include "fumotris.h"
#include "hash.h" #include "hash.h"
#include "input.h"
#define IO_BUF_SIZE 16 struct CtrlAxis {
enum InputType {
BUTTON,
AXIS,
JOYSTICK,
ESCAPE
};
struct Button {
u64 value;
};
struct Axis {
i64 value;
};
struct Joystick {
i32 x;
i32 y;
};
union InputData {
struct Button input_but;
struct Axis input_axis;
struct Joystick input_js;
};
struct InputRecord {
u16f bind;
struct timespec timestamp;
u8 type;
u8 is_down;
u8 is_held;
u8 is_up;
union {
struct Button but;
struct Axis axis;
struct Joystick js;
union InputData data;
};
};
struct InputAxis {
struct timespec last_pressed; struct timespec last_pressed;
struct timespec last_released; struct timespec last_released;
@ -78,25 +37,20 @@ struct ctrl_dict {
u16 value; u16 value;
u8 type; u8 type;
struct InputAxis *axis; struct CtrlAxis *axis;
} *bkts; } *bkts;
}; };
struct InputBuffer {
size_t len;
struct InputRecord records[IO_BUF_SIZE];
};
struct Controller { struct Controller {
struct ctrl_dict codes; struct ctrl_dict codes;
struct ctrl_dict binds; struct ctrl_dict binds;
struct InputAxis *axes; struct CtrlAxis *axes;
struct InputBuffer input_buf; struct InputBuffer input_buf;
struct { struct {
size_t len; size_t len;
struct InputAxis *axes[IO_BUF_SIZE]; struct CtrlAxis *axes[IO_BUF_SIZE];
} pending_buf; } pending_buf;
}; };
@ -104,7 +58,7 @@ bool NewCtrl(struct Controller *ctrl, size_t code_cap, size_t bind_cap)
{ {
struct ctrl_bkt *code_bkts = calloc(code_cap, sizeof(struct ctrl_bkt)); struct ctrl_bkt *code_bkts = calloc(code_cap, sizeof(struct ctrl_bkt));
struct ctrl_bkt *bind_bkts = calloc(bind_cap, sizeof(struct ctrl_bkt)); struct ctrl_bkt *bind_bkts = calloc(bind_cap, sizeof(struct ctrl_bkt));
struct InputAxis *axes = calloc(code_cap, sizeof(struct InputAxis)); struct CtrlAxis *axes = calloc(code_cap, sizeof(struct CtrlAxis));
if (code_bkts == nullptr or bind_bkts == nullptr or axes == nullptr) if (code_bkts == nullptr or bind_bkts == nullptr or axes == nullptr)
return false; return false;
@ -126,7 +80,9 @@ bool NewCtrl(struct Controller *ctrl, size_t code_cap, size_t bind_cap)
}, },
.axes = axes, .axes = axes,
.input_buf.len = 0, .input_buf = (struct InputBuffer) {
.len = 0,
},
.pending_buf.len = 0, .pending_buf.len = 0,
}; };
return true; return true;
@ -211,7 +167,7 @@ next:
return nullptr; return nullptr;
} }
struct InputAxis *find_axis(struct ctrl_dict *dict, u16f value, u8f type) struct CtrlAxis *find_axis(struct ctrl_dict *dict, u16f value, u8f type)
{ {
struct ctrl_bkt *bkt = find(dict, value, type); struct ctrl_bkt *bkt = find(dict, value, type);
if (bkt == nullptr) if (bkt == nullptr)
@ -241,7 +197,7 @@ bool CtrlMap(struct Controller *ctrl, u16f code, u16f bind, u8f type)
return true; return true;
} }
struct InputAxis *CtrlGet(struct Controller *ctrl, u16f code, u8f type) struct CtrlAxis *CtrlGet(struct Controller *ctrl, u16f code, u8f type)
{ {
struct ctrl_bkt *code_bkt = find(&ctrl->codes, code, type); struct ctrl_bkt *code_bkt = find(&ctrl->codes, code, type);
if (code_bkt == nullptr) if (code_bkt == nullptr)
@ -250,7 +206,7 @@ struct InputAxis *CtrlGet(struct Controller *ctrl, u16f code, u8f type)
return code_bkt->axis; return code_bkt->axis;
} }
void dispatch_update(struct InputAxis *axis, struct InputRecord *rec) void dispatch_update(struct CtrlAxis *axis, struct InputRecord *rec)
{ {
if (rec->is_down and !axis->is_held) { if (rec->is_down and !axis->is_held) {
axis->is_down = true; axis->is_down = true;
@ -268,7 +224,7 @@ void dispatch_update(struct InputAxis *axis, struct InputRecord *rec)
bool CtrlPoll(struct Controller *ctrl) bool CtrlPoll(struct Controller *ctrl)
{ {
for (size_t i = 0; i < ctrl->pending_buf.len; i++) { for (size_t i = 0; i < ctrl->pending_buf.len; i++) {
struct InputAxis *axis = ctrl->pending_buf.axes[i]; struct CtrlAxis *axis = ctrl->pending_buf.axes[i];
axis->is_up = false; axis->is_up = false;
axis->is_down = false; axis->is_down = false;
@ -277,7 +233,7 @@ bool CtrlPoll(struct Controller *ctrl)
for (size_t i = 0; i < ctrl->input_buf.len; i++) { for (size_t i = 0; i < ctrl->input_buf.len; i++) {
struct InputRecord *rec = &ctrl->input_buf.records[i]; struct InputRecord *rec = &ctrl->input_buf.records[i];
struct InputAxis *axis = find_axis(&ctrl->binds, rec->bind, rec->type); struct CtrlAxis *axis = find_axis(&ctrl->binds, rec->bind, rec->type);
if (axis == nullptr) if (axis == nullptr)
continue; continue;
@ -308,7 +264,7 @@ int main()
CtrlPoll(&ctrl); CtrlPoll(&ctrl);
struct InputAxis *a = CtrlGet(&ctrl, 123, BUTTON); struct CtrlAxis *a = CtrlGet(&ctrl, 123, BUTTON);
printf("%u\n", a->but.value); printf("%u\n", a->but.value);
printf("success"); printf("success");

View file

@ -53,7 +53,17 @@ struct InputRecord {
}; };
}; };
struct InputAxis { struct InputBuffer {
size_t len;
size_t start;
struct InputRecord records[IO_BUF_SIZE];
};
void InputBufferTransfer(struct InputBuffer *tmp, struct InputBuffer *dest);
void InputBufferCopy(struct InputBuffer *buf, struct InputRecord *src);
struct CtrlAxis {
struct timespec last_pressed; struct timespec last_pressed;
struct timespec last_released; struct timespec last_released;
@ -94,25 +104,20 @@ struct ctrl_dict {
u16 value; u16 value;
u8 type; u8 type;
struct InputAxis *axis; struct CtrlAxis *axis;
} *bkts; } *bkts;
}; };
struct InputBuffer {
size_t len;
struct InputRecord records[IO_BUF_SIZE];
};
struct Controller { struct Controller {
struct ctrl_dict codes; struct ctrl_dict codes;
struct ctrl_dict binds; struct ctrl_dict binds;
struct InputAxis *axes; struct CtrlAxis *axes;
struct InputBuffer input_buf; struct InputBuffer input_buf;
struct { struct {
size_t len; size_t len;
struct InputAxis *axes[IO_BUF_SIZE]; struct CtrlAxis *axes[IO_BUF_SIZE];
} pending_buf; } pending_buf;
}; };
@ -122,6 +127,6 @@ void FreeCtrl(struct Controller *ctrl);
bool CtrlMap(struct Controller *ctrl, u16f code, u16f bind, u8f type); bool CtrlMap(struct Controller *ctrl, u16f code, u16f bind, u8f type);
struct InputAxis *CtrlGet(struct Controller *ctrl, u16f code, u8f type); struct CtrlAxis *CtrlGet(struct Controller *ctrl, u16f code, u8f type);
bool CtrlPoll(struct Controller *ctrl); bool CtrlPoll(struct Controller *ctrl);

View file

@ -5,45 +5,162 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "ctrl.h"
#include "fumotris.h" #include "fumotris.h"
#include "platform.h"
#ifdef _WIN32 #define IO_BUF_SIZE 16
#include "win.h"
#endif
struct Input { enum InputType {
struct Controller ctrl; BUTTON,
AXIS,
pthread_t thread; JOYSTICK,
pthread_mutex_t access_mutex; ESCAPE
}; };
void *block_input(void *args_ptr) struct Button {
u64 value;
};
struct Axis {
i64 value;
};
struct Joystick {
i32 x;
i32 y;
};
union InputData {
struct Button input_but;
struct Axis input_axis;
struct Joystick input_js;
};
struct InputRecord {
u16f bind;
struct timespec timestamp;
u8 type;
u8 is_down;
u8 is_held;
u8 is_up;
union {
struct Button but;
struct Axis axis;
struct Joystick js;
union InputData data;
};
};
struct InputBuffer {
size_t len;
size_t start;
struct InputRecord records[IO_BUF_SIZE];
};
struct InputRecord *in_buf_get(struct InputBuffer *buf, size_t i)
{ {
struct Input *in = args_ptr; return buf->records + (buf->start + 1) % IO_BUF_SIZE;
struct InputBuffer tmp_buf = { .len = 0 }; }
void InputBufferTransfer(struct InputBuffer *tmp, struct InputBuffer *dest)
{
size_t n = IO_BUF_SIZE - (tmp->len > dest->len ? tmp->len : dest->len);
for (size_t i = 0; i < n; i++) {
*in_buf_get(dest, dest->len + i) = *in_buf_get(tmp, i);
}
if (n < tmp->len)
tmp->start += n;
tmp->len -= n;
dest->len += n;
}
void InputBufferCopy(struct InputBuffer *buf, struct InputRecord *src)
{
buf->records[(buf->start + buf->len) % IO_BUF_SIZE] = *src;
buf->len += 1;
}
struct thread_init {
pthread_mutex_t mutex;
pthread_cond_t cond;
bool done;
void *args;
};
struct input_args {
struct InputBuffer *buf;
pthread_mutex_t *mutex;
};
bool ThreadSignalInit()
{
}
void *block_input(void *args)
{
struct input_args *args = args + 1;
pthread_mutex_lock(&args->init.mutex);
args->init.is_init = true;
pthread_cond_signal(&args->init.cond);
pthread_mutex_unlock(&args->init.mutex);
struct InputBuffer tmp_buf = { .len = 0, .start = 0 };
while (true) { while (true) {
if (!PlatformBlockInput(&tmp_buf)) if (!PlatformReadInput(&tmp_buf))
return false; return false;
pthread_mutex_lock(&in->access_mutex); pthread_mutex_lock(&in->mutex);
{ {
InputBufferTransfer(&tmp_buf, buf);
} }
pthread_mutex_unlock(&in->access_mutex); pthread_mutex_unlock(&in->mutex);
} }
return nullptr; return nullptr;
} }
bool StartInput(struct Input *in) void *thread_wrap(void *init_ptr)
{ {
return pthread_create(&in->thread, nullptr, block_input, in) == 0; struct thread_init *init = init_ptr;
block_input();
} }
bool JoinInput(struct Input *in) bool ThreadWaitInit(void *(*func), size_t args_len, void *args)
{ {
return pthread_join(in->thread, nullptr) == 0; struct thread_init init = {
.mutex = PTHREAD_MUTEX_INITIALIZER,
.cond = PTHREAD_COND_INITIALIZER,
.done = false,
.args = &args,
};
pthread_t thread;
if (pthread_create(&thread, nullptr, thread_wrap, &init) != 0)
return false;
pthread_mutex_lock(&init.mutex);
{
while (!init.done)
pthread_cond_wait(&init.cond, &init.mutex);
}
pthread_mutex_unlock(&init.mutex);
pthread_mutex_destroy(&init.mutex);
pthread_cond_destroy(&init.cond);
}
bool InputStart(struct InputBuffer *buf, pthread_mutex_t *mutex)
{
struct input_args args = {
.buf = buf,
.mutex = mutex,
};
return ThreadWaitInit(block_input, &args);
} }

View file

@ -12,7 +12,7 @@ struct Input {
struct Controller ctrl; struct Controller ctrl;
pthread_t thread; pthread_t thread;
pthread_mutex_t access_mutex; pthread_mutex_t mutex;
}; };
bool StartInput(struct Input *in); bool StartInput(struct Input *in);

View file

View file

@ -0,0 +1,4 @@
#pragma once
#ifdef _WIN32
#include "win.h"
#endif

View file

@ -4,22 +4,22 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <windows.h> #include <windows.h>
#include <time.h>
#include "fumotris.h" #include "fumotris.h"
#include "ctrl.h" #include "ctrl.h"
#include "gametime.h"
static struct Windows { static struct Windows {
HANDLE in_handle;
HANDLE timer; HANDLE timer;
DWORD in_len; HANDLE input_handle;
INPUT_RECORD in_buf[IO_BUF_SIZE]; DWORD input_n;
INPUT_RECORD input_buf[IO_BUF_SIZE];
} win; } win;
bool init_handles() bool init_handles()
{ {
win.in_handle = GetStdHandle(STD_INPUT_HANDLE); win.input_handle = GetStdHandle(STD_INPUT_HANDLE);
if (win.in_handle == INVALID_HANDLE_VALUE) if (win.input_handle == INVALID_HANDLE_VALUE)
return false; return false;
win.timer = CreateWaitableTimer( win.timer = CreateWaitableTimer(
@ -40,7 +40,7 @@ bool init_console()
| ENABLE_PROCESSED_OUTPUT | ENABLE_PROCESSED_OUTPUT
| ENABLE_MOUSE_INPUT | ENABLE_MOUSE_INPUT
| ENABLE_WINDOW_INPUT; | ENABLE_WINDOW_INPUT;
return SetConsoleMode(win.in_handle, mode) != 0; return SetConsoleMode(win.input_handle, mode) != 0;
} }
bool PlatformInit() bool PlatformInit()
@ -124,27 +124,23 @@ bool read_rec(struct InputRecord *rec, INPUT_RECORD win_rec)
return false; return false;
} }
bool PlatformBlockInput(struct InputBuffer *buf) bool PlatformReadInput(struct InputBuffer *tmp)
{ {
if (!ReadConsoleInput( if (!ReadConsoleInput(
win.in_handle, // Input handle win.input_handle, // Input handle
win.in_buf + buf->len, // Record buffer &win.input_buf[tmp->len], // Record buffer
IO_BUF_SIZE - buf->len, // Record buffer length IO_BUF_SIZE - tmp->len, // Record buffer length
&win.in_len // Out number of records &win.input_n // Out number of records
)) ))
return false; return false;
struct timespec now;
timespec_get(&now, TIME_UTC);
for (size_t i = 0; i < win.in_len; i++) { struct InputRecord rec = { .timestamp = TimeNow() };
struct InputRecord *rec = &buf->records[buf->len]; for (size_t i = 0; i < win.input_n; i++) {
if (!read_rec(rec, win.in_buf[i])) if (!read_rec(&rec, win.input_buf[i]))
continue; continue;
rec->timestamp = now; InputBufferCopy(tmp, &rec);
buf->len += 1;
} }
return true; return true;

View file

@ -12,6 +12,6 @@ bool PlatformInit();
bool PlatformGetRefreshRate(u16f *out); bool PlatformGetRefreshRate(u16f *out);
bool PlatformBlockInput(struct InputBuffer *buf); bool PlatformReadInput(struct InputBuffer *buf);
bool PlatformWait(struct timespec relative); bool PlatformWait(struct timespec relative);

View file

@ -11,10 +11,7 @@
#include "term.h" #include "term.h"
#include "tetr.h" #include "tetr.h"
#include "event.h" #include "event.h"
#include "platform.h"
#ifdef _WIN32
#include "win.h"
#endif
struct Instance { struct Instance {
struct Controller ctrl; struct Controller ctrl;