diff --git a/source/game/tetr.c b/source/fumo/tetr.c similarity index 100% rename from source/game/tetr.c rename to source/fumo/tetr.c diff --git a/source/game/tetr.h b/source/fumo/tetr.h similarity index 100% rename from source/game/tetr.h rename to source/fumo/tetr.h diff --git a/source/game/gametime.c b/source/game/gametime.c index f9bc5df..3c6fbcc 100644 --- a/source/game/gametime.c +++ b/source/game/gametime.c @@ -5,17 +5,17 @@ #include "win.h" #endif -double GetTime() +struct timespec TimeNow() +{ + struct timespec ts; + timespec_get(&ts, TIME_UTC); + return ts; +} + +double TimeNowDouble() { struct timespec ts; timespec_get(&ts, TIME_UTC); return ts.tv_sec + (double)ts.tv_nsec / 1000000000.0; -} - -bool Wait(double seconds) -{ - #ifdef _WIN32 - return WindowsWait(seconds); - #endif } \ No newline at end of file diff --git a/source/game/gametime.h b/source/game/gametime.h index a660ebb..4f227e7 100644 --- a/source/game/gametime.h +++ b/source/game/gametime.h @@ -1,6 +1,6 @@ #pragma once #include -double GetTime(); +struct timespec TimeNow(); -bool Wait(double seconds); \ No newline at end of file +double TimeNowDouble(); diff --git a/source/io/ctrl.c b/source/io/ctrl.c index dd76e6b..0bea90e 100644 --- a/source/io/ctrl.c +++ b/source/io/ctrl.c @@ -9,50 +9,9 @@ #include "fumotris.h" #include "hash.h" +#include "input.h" -#define IO_BUF_SIZE 16 - -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 CtrlAxis { struct timespec last_pressed; struct timespec last_released; @@ -78,25 +37,20 @@ struct ctrl_dict { u16 value; u8 type; - struct InputAxis *axis; + struct CtrlAxis *axis; } *bkts; }; -struct InputBuffer { - size_t len; - struct InputRecord records[IO_BUF_SIZE]; -}; - struct Controller { struct ctrl_dict codes; struct ctrl_dict binds; - struct InputAxis *axes; + struct CtrlAxis *axes; struct InputBuffer input_buf; struct { size_t len; - struct InputAxis *axes[IO_BUF_SIZE]; + struct CtrlAxis *axes[IO_BUF_SIZE]; } 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 *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) return false; @@ -126,7 +80,9 @@ bool NewCtrl(struct Controller *ctrl, size_t code_cap, size_t bind_cap) }, .axes = axes, - .input_buf.len = 0, + .input_buf = (struct InputBuffer) { + .len = 0, + }, .pending_buf.len = 0, }; return true; @@ -211,7 +167,7 @@ next: 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); if (bkt == nullptr) @@ -241,7 +197,7 @@ bool CtrlMap(struct Controller *ctrl, u16f code, u16f bind, u8f type) 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); if (code_bkt == nullptr) @@ -250,7 +206,7 @@ struct InputAxis *CtrlGet(struct Controller *ctrl, u16f code, u8f type) 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) { axis->is_down = true; @@ -268,7 +224,7 @@ void dispatch_update(struct InputAxis *axis, struct InputRecord *rec) bool CtrlPoll(struct Controller *ctrl) { 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_down = false; @@ -277,7 +233,7 @@ bool CtrlPoll(struct Controller *ctrl) for (size_t i = 0; i < ctrl->input_buf.len; 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) continue; @@ -308,7 +264,7 @@ int main() CtrlPoll(&ctrl); - struct InputAxis *a = CtrlGet(&ctrl, 123, BUTTON); + struct CtrlAxis *a = CtrlGet(&ctrl, 123, BUTTON); printf("%u\n", a->but.value); printf("success"); diff --git a/source/io/ctrl.h b/source/io/ctrl.h index e98260c..7da1970 100644 --- a/source/io/ctrl.h +++ b/source/io/ctrl.h @@ -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_released; @@ -94,25 +104,20 @@ struct ctrl_dict { u16 value; u8 type; - struct InputAxis *axis; + struct CtrlAxis *axis; } *bkts; }; -struct InputBuffer { - size_t len; - struct InputRecord records[IO_BUF_SIZE]; -}; - struct Controller { struct ctrl_dict codes; struct ctrl_dict binds; - struct InputAxis *axes; + struct CtrlAxis *axes; struct InputBuffer input_buf; struct { size_t len; - struct InputAxis *axes[IO_BUF_SIZE]; + struct CtrlAxis *axes[IO_BUF_SIZE]; } pending_buf; }; @@ -122,6 +127,6 @@ void FreeCtrl(struct Controller *ctrl); 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); \ No newline at end of file diff --git a/source/io/input.c b/source/io/input.c index 0816495..e834bc2 100644 --- a/source/io/input.c +++ b/source/io/input.c @@ -5,45 +5,162 @@ #include #include -#include "ctrl.h" #include "fumotris.h" +#include "platform.h" -#ifdef _WIN32 -#include "win.h" -#endif +#define IO_BUF_SIZE 16 -struct Input { - struct Controller ctrl; - - pthread_t thread; - pthread_mutex_t access_mutex; +enum InputType { + BUTTON, + AXIS, + JOYSTICK, + 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; - struct InputBuffer tmp_buf = { .len = 0 }; + return buf->records + (buf->start + 1) % IO_BUF_SIZE; +} + +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) { - if (!PlatformBlockInput(&tmp_buf)) + if (!PlatformReadInput(&tmp_buf)) 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; } -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); } \ No newline at end of file diff --git a/source/io/input.h b/source/io/input.h index 3c5e433..e0a5e74 100644 --- a/source/io/input.h +++ b/source/io/input.h @@ -12,7 +12,7 @@ struct Input { struct Controller ctrl; pthread_t thread; - pthread_mutex_t access_mutex; + pthread_mutex_t mutex; }; bool StartInput(struct Input *in); diff --git a/source/io/platforms/platform.c b/source/io/platforms/platform.c new file mode 100644 index 0000000..e69de29 diff --git a/source/io/platforms/platform.h b/source/io/platforms/platform.h new file mode 100644 index 0000000..f93ef27 --- /dev/null +++ b/source/io/platforms/platform.h @@ -0,0 +1,4 @@ +#pragma once +#ifdef _WIN32 +#include "win.h" +#endif \ No newline at end of file diff --git a/source/io/platforms/win.c b/source/io/platforms/win.c index f6262b0..ceb8ac7 100644 --- a/source/io/platforms/win.c +++ b/source/io/platforms/win.c @@ -4,22 +4,22 @@ #include #include #include -#include #include "fumotris.h" #include "ctrl.h" +#include "gametime.h" static struct Windows { - HANDLE in_handle; HANDLE timer; - DWORD in_len; - INPUT_RECORD in_buf[IO_BUF_SIZE]; + HANDLE input_handle; + DWORD input_n; + INPUT_RECORD input_buf[IO_BUF_SIZE]; } win; bool init_handles() { - win.in_handle = GetStdHandle(STD_INPUT_HANDLE); - if (win.in_handle == INVALID_HANDLE_VALUE) + win.input_handle = GetStdHandle(STD_INPUT_HANDLE); + if (win.input_handle == INVALID_HANDLE_VALUE) return false; win.timer = CreateWaitableTimer( @@ -40,7 +40,7 @@ bool init_console() | ENABLE_PROCESSED_OUTPUT | ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT; - return SetConsoleMode(win.in_handle, mode) != 0; + return SetConsoleMode(win.input_handle, mode) != 0; } bool PlatformInit() @@ -124,27 +124,23 @@ bool read_rec(struct InputRecord *rec, INPUT_RECORD win_rec) return false; } -bool PlatformBlockInput(struct InputBuffer *buf) +bool PlatformReadInput(struct InputBuffer *tmp) { if (!ReadConsoleInput( - win.in_handle, // Input handle - win.in_buf + buf->len, // Record buffer - IO_BUF_SIZE - buf->len, // Record buffer length - &win.in_len // Out number of records + win.input_handle, // Input handle + &win.input_buf[tmp->len], // Record buffer + IO_BUF_SIZE - tmp->len, // Record buffer length + &win.input_n // Out number of records )) return false; - - struct timespec now; - timespec_get(&now, TIME_UTC); - for (size_t i = 0; i < win.in_len; i++) { - struct InputRecord *rec = &buf->records[buf->len]; + struct InputRecord rec = { .timestamp = TimeNow() }; + 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; - rec->timestamp = now; - buf->len += 1; + InputBufferCopy(tmp, &rec); } return true; diff --git a/source/io/platforms/win.h b/source/io/platforms/win.h index b4a6148..85639dc 100644 --- a/source/io/platforms/win.h +++ b/source/io/platforms/win.h @@ -12,6 +12,6 @@ bool PlatformInit(); bool PlatformGetRefreshRate(u16f *out); -bool PlatformBlockInput(struct InputBuffer *buf); +bool PlatformReadInput(struct InputBuffer *buf); bool PlatformWait(struct timespec relative); \ No newline at end of file diff --git a/source/main.c b/source/main.c index 673583b..fcecd41 100644 --- a/source/main.c +++ b/source/main.c @@ -11,10 +11,7 @@ #include "term.h" #include "tetr.h" #include "event.h" - -#ifdef _WIN32 -#include "win.h" -#endif +#include "platform.h" struct Instance { struct Controller ctrl; diff --git a/source/game/hash.c b/source/misc/hash.c similarity index 100% rename from source/game/hash.c rename to source/misc/hash.c diff --git a/source/game/hash.h b/source/misc/hash.h similarity index 100% rename from source/game/hash.h rename to source/misc/hash.h