diff --git a/hi.exe b/hi.exe index 1eb5afa..e4ef518 100644 Binary files a/hi.exe and b/hi.exe differ diff --git a/source/io/ctrl.c b/source/io/ctrl.c index e4cbb8d..dd76e6b 100644 --- a/source/io/ctrl.c +++ b/source/io/ctrl.c @@ -13,44 +13,60 @@ #define IO_BUF_SIZE 16 enum InputType { - KEY, + BUTTON, AXIS, JOYSTICK, ESCAPE }; -struct Input { +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 { - u64 value; - } but; - struct Axis { - i64 value; - } axis; - struct Joystick { - i32 x; - i32 y; - } js; + struct Button but; + struct Axis axis; + struct Joystick js; + union InputData data; }; }; -struct InputRecord { - u16f bind; - struct Input dat; - - struct timespec timestamp; -}; - struct InputAxis { - struct Input dat; - struct timespec last_pressed; struct timespec last_released; + + 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 ctrl_dict { @@ -66,20 +82,21 @@ struct ctrl_dict { } *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 InputBuffer { - struct InputRecord records[IO_BUF_SIZE]; - size_t len; - size_t start; - } input_buf; + struct InputBuffer input_buf; struct { - size_t indexes[IO_BUF_SIZE]; size_t len; + struct InputAxis *axes[IO_BUF_SIZE]; } pending_buf; }; @@ -109,13 +126,8 @@ bool NewCtrl(struct Controller *ctrl, size_t code_cap, size_t bind_cap) }, .axes = axes, - .input_buf = { - .len = 0, - .start = 0, - }, - .pending_buf = { - .len = 0, - }, + .input_buf.len = 0, + .pending_buf.len = 0, }; return true; } @@ -238,73 +250,67 @@ struct InputAxis *CtrlGet(struct Controller *ctrl, u16f code, u8f type) return code_bkt->axis; } -void update_key(struct InputAxis *axis, struct InputRecord *rec) +void dispatch_update(struct InputAxis *axis, struct InputRecord *rec) { - if (rec->but.is_down) { + if (rec->is_down and !axis->is_held) { + axis->is_down = true; + axis->is_held = true; axis->last_pressed = rec->timestamp; - axis->but.is_held = true; - } else { + } else if (rec->is_up) { + axis->is_up = true; + axis->is_held = false; axis->last_released = rec->timestamp; - axis->but.is_held = false; - } - - axis->but.is_down |= rec->but.is_down; - axis->but.is_up |= rec->but.is_up; -} - -void update_axis(struct InputAxis *axis, struct InputRecord *rec) -{ - axis->axis.value = rec->axis.value; - - axis->last_pressed = rec->timestamp; -} - -void update_joystick(struct InputAxis *axis, struct InputRecord *rec) -{ - axis->js.x = rec->js.x; - axis->js.y = rec->js.y; - - axis->last_pressed = rec->timestamp; -} - -bool dispatch_update(struct InputAxis *axis, struct InputRecord *rec) -{ - switch (rec->type) { - case KEY: - update_key(axis, rec); - printf("axis:%hu\n", axis->but.is_down); - return true; - - case AXIS: - update_axis(axis, rec); - return true; - - case JOYSTICK: - update_joystick(axis, rec); - return true; } - return false; + axis->data = rec->data; } bool CtrlPoll(struct Controller *ctrl) { for (size_t i = 0; i < ctrl->pending_buf.len; i++) { + struct InputAxis *axis = ctrl->pending_buf.axes[i]; + axis->is_up = false; + axis->is_down = false; } + ctrl->pending_buf.len = ctrl->input_buf.len; for (size_t i = 0; i < ctrl->input_buf.len; i++) { struct InputRecord *rec = &ctrl->input_buf.records[i]; - printf("i:%hu\n", rec->bind); - struct InputAxis *axis = find_axis(&ctrl->binds, rec->bind, rec->type); + if (axis == nullptr) continue; - if (!dispatch_update(axis, rec)) - return false; - } + dispatch_update(axis, rec); + ctrl->pending_buf.axes[i] = axis; + } ctrl->input_buf.len = 0; + return true; +} + +int main() +{ + struct Controller ctrl; + if (!NewCtrl(&ctrl, 3, 3)) + return 1; + + CtrlMap(&ctrl, 123, 111, BUTTON); + + ctrl.input_buf.records[ctrl.input_buf.len++] = (struct InputRecord) { + .bind = 111, + .type = BUTTON, + .is_down = true, + .but.value = 69 + }; + + CtrlPoll(&ctrl); + + struct InputAxis *a = CtrlGet(&ctrl, 123, BUTTON); + printf("%u\n", a->but.value); + + printf("success"); + return 0; } \ No newline at end of file diff --git a/source/io/ctrl.h b/source/io/ctrl.h index 7baefe3..e98260c 100644 --- a/source/io/ctrl.h +++ b/source/io/ctrl.h @@ -9,54 +9,65 @@ #include #include "fumotris.h" +#include "hash.h" #define IO_BUF_SIZE 16 enum InputType { - KEY, + BUTTON, AXIS, JOYSTICK, ESCAPE }; struct Button { - u32 value; - bool is_down; - bool is_held; - bool is_up; + 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 { - u16 bind; + 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 timespec timestamp; }; struct InputAxis { + struct timespec last_pressed; + struct timespec last_released; + + 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 timespec last_pressed; - struct timespec last_released; }; enum CtrlCode { @@ -74,8 +85,6 @@ enum CtrlCode { MOUSE }; -typedef u32 hashtype; - struct ctrl_dict { size_t capacity; size_t filled; @@ -89,20 +98,21 @@ struct ctrl_dict { } *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 InputBuffer { - struct InputRecord records[IO_BUF_SIZE]; - size_t len; - size_t start; - } input_buf; + struct InputBuffer input_buf; struct { - size_t indexes[IO_BUF_SIZE]; size_t len; + struct InputAxis *axes[IO_BUF_SIZE]; } pending_buf; }; diff --git a/source/io/input.c b/source/io/input.c index ab8e8e1..d47437e 100644 --- a/source/io/input.c +++ b/source/io/input.c @@ -19,11 +19,6 @@ struct Input { pthread_mutex_t access_mutex; }; -struct InputRecord *get_at(struct InputBuffer *buf, size_t i) -{ - return &buf->records[(buf->start + i) % IO_BUF_SIZE]; -} - void *block_input(void *args_ptr) { struct Input *in = args_ptr; diff --git a/source/io/platforms/win.c b/source/io/platforms/win.c index 37944b1..0a8ff30 100644 --- a/source/io/platforms/win.c +++ b/source/io/platforms/win.c @@ -3,19 +3,72 @@ #include #include #include +#include #include -#include -#include "input.h" -#include "winhandler.h" +#include "fumotris.h" +#include "ctrl.h" #include "term.h" -bool WindowsInit(struct Terminal *term) +struct Windows { + HANDLE in_handle; + HANDLE timer; + DWORD in_len; + INPUT_RECORD in_buf[IO_BUF_SIZE]; +}; + +typedef struct Windows *platform; + +bool WinInitHandles(struct Windows *win) { - if (!WinInitHandles()) + win->in_handle = GetStdHandle(STD_INPUT_HANDLE); + if (win->in_handle == INVALID_HANDLE_VALUE) return false; - if (!WinInitConsole()) + win->timer = CreateWaitableTimer( + NULL, // Timer attributes + TRUE, // Manual reset + NULL // Name + ); + if (win->timer == NULL) + return false; + + return true; +} + +bool WinInitConsole(struct Windows *win) +{ + DWORD mode = ENABLE_EXTENDED_FLAGS + | ENABLE_PROCESSED_INPUT + | ENABLE_PROCESSED_OUTPUT + | ENABLE_MOUSE_INPUT + | ENABLE_WINDOW_INPUT; + return SetConsoleMode(win->in_handle, mode) != 0; +} + +bool WinGetRefreshRate(u16f *out) +{ + DEVMODE mode; + mode.dmSize = sizeof(DEVMODE); + mode.dmDriverExtra = 0; + + if(!EnumDisplaySettingsA( + NULL, // Device name (null for current) + ENUM_CURRENT_SETTINGS, // Mode + &mode // Out + )) + return false; + + *out = mode.dmDisplayFrequency; + return true; +} + +bool WindowsInit(platform win, struct Terminal *term) +{ + if (!WinInitHandles(win)) + return false; + + if (!WinInitConsole(win)) return false; if (!WinGetRefreshRate(&term->refresh_rate)) @@ -24,17 +77,103 @@ bool WindowsInit(struct Terminal *term) return true; } -bool WindowsBlockInput(struct RecordBuffer *buf) +void read_key_rec(struct InputRecord *rec, KEY_EVENT_RECORD win_key) { - return WinBlockInput(buf); + rec->type = BUTTON; + rec->bind = win_key.wVirtualKeyCode; + + rec->is_down = win_key.bKeyDown; + rec->is_up = !win_key.bKeyDown; } -bool WindowsWait(double seconds) +bool read_mouse_rec(struct InputRecord *rec, MOUSE_EVENT_RECORD win_mouse) { - struct timespec duration = { - .tv_sec = seconds, - .tv_nsec = fmod(seconds, 1) * 1e9 - }; + if (win_mouse.dwEventFlags == MOUSE_MOVED) { + rec->type = JOYSTICK; + rec->bind = 0; + rec->js.x = win_mouse.dwMousePosition.X; + rec->js.y = win_mouse.dwMousePosition.Y; + + return true; + } - return WinWait(duration); + if (win_mouse.dwEventFlags == MOUSE_WHEELED) { + rec->bind = 0; + } else if (win_mouse.dwEventFlags == MOUSE_HWHEELED) { + rec->bind = 1; + } else { + return false; + } + + rec->type = AXIS; + rec->axis.value = win_mouse.dwButtonState; + + return true; +} + +bool read_rec(struct InputRecord *rec, INPUT_RECORD win_rec) +{ + switch (win_rec.EventType) { + case KEY_EVENT: + read_key_rec(rec, win_rec.Event.KeyEvent); + return true; + + case MOUSE_EVENT: + return read_mouse_rec(rec, win_rec.Event.MouseEvent); + + case WINDOW_BUFFER_SIZE_EVENT: + return false; + // TODO: Handle window resizing + } + + rec->type = ESCAPE; + return false; +} + +bool WinBlockInput(platform win, struct InputBuffer *buf) +{ + 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 + )) + 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]; + + if (!read_rec(rec, win->in_buf[i])) + continue; + + rec->timestamp = now; + buf->len += 1; + } + + return true; +} + +bool WinWait(platform win, struct timespec relative) +{ + LARGE_INTEGER duration; + duration.QuadPart = -10000000 * relative.tv_sec - relative.tv_nsec / 100; + + if (!SetWaitableTimer( + win->timer, // Timer + &duration, // Duration + 0, // Period + NULL, // Completion coroutine + NULL, // Completion coroutine arg + FALSE // Resume + )) + return false; + + DWORD result = WaitForSingleObject(win->timer, INFINITE); + if (result != WAIT_OBJECT_0) + return false; + + return true; } \ No newline at end of file diff --git a/source/io/platforms/win.h b/source/io/platforms/win.h index fdebbae..8e0015b 100644 --- a/source/io/platforms/win.h +++ b/source/io/platforms/win.h @@ -1,16 +1,18 @@ #pragma once -#include #include #include #include #include #include +#include -#include "input.h" +#include "fumotris.h" #include "term.h" -bool WindowsInit(struct Terminal *term); +typedef struct Windows *platform; -bool WindowsBlockInput(struct RecordBuffer *buf); +bool WindowsInit(platform win, struct Terminal *term); -bool WindowsWait(double seconds); \ No newline at end of file +bool WinBlockInput(platform win, struct InputBuffer *buf); + +bool WinWait(platform win, struct timespec relative); \ No newline at end of file diff --git a/source/io/platforms/winhandler.c b/source/io/platforms/winhandler.c deleted file mode 100644 index 9865469..0000000 --- a/source/io/platforms/winhandler.c +++ /dev/null @@ -1,173 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "fumotris.h" -#include "gametime.h" -#include "input.h" -#include "term.h" - -struct Windows { - HANDLE input_handle; - HANDLE timer; -}; -static struct Windows win; - -bool WinInitHandles() -{ - win.input_handle = GetStdHandle(STD_INPUT_HANDLE); - if (win.input_handle == INVALID_HANDLE_VALUE) - return false; - - win.timer = CreateWaitableTimer( - NULL, // Timer attributes - TRUE, // Manual reset - NULL // Name - ); - if (!win.timer) - return false; - - return true; -} - -bool WinInitConsole() -{ - DWORD mode = ENABLE_EXTENDED_FLAGS - | ENABLE_PROCESSED_INPUT - | ENABLE_PROCESSED_OUTPUT - | ENABLE_MOUSE_INPUT - | ENABLE_WINDOW_INPUT; - return SetConsoleMode(win.input_handle, mode) != 0; -} - -bool WinGetRefreshRate(u16f *out) -{ - DEVMODE mode; - mode.dmSize = sizeof(DEVMODE); - mode.dmDriverExtra = 0; - - if(!EnumDisplaySettingsA( - NULL, // Device name (null for current) - ENUM_CURRENT_SETTINGS, // Mode - &mode // Out - )) - return false; - - *out = mode.dmDisplayFrequency; - return true; -} - -void set_key_record(struct InputRecord *rec, KEY_EVENT_RECORD win_key) -{ - rec->type = KEY; - rec->bind = win_key.wVirtualKeyCode; - - rec->but.is_down = win_key.bKeyDown; - rec->but.is_up = !win_key.bKeyDown; - - if (win_key.wVirtualKeyCode == VK_ESCAPE) - rec->type = ESCAPE; -} - -bool set_mouse_record(struct InputRecord *rec, MOUSE_EVENT_RECORD win_mouse) -{ - switch (win_mouse.dwEventFlags) { - case MOUSE_WHEELED: - rec->type = AXIS; - rec->bind = 0; - rec->axis.value = win_mouse.dwButtonState; - break; - case MOUSE_HWHEELED: - rec->type = AXIS; - rec->bind = 1; - rec->axis.value = win_mouse.dwButtonState; - break; - case MOUSE_MOVED: - rec->type = JOYSTICK; - rec->bind = 0; - rec->js.x = win_mouse.dwMousePosition.X; - rec->js.y = win_mouse.dwMousePosition.Y; - break; - default: - return false; - } - return true; -} - -bool dispatch_record(struct InputRecord *rec, INPUT_RECORD win_rec) -{ - switch (win_rec.EventType) { - case KEY_EVENT: - set_key_record(rec, win_rec.Event.KeyEvent); - break; - case MOUSE_EVENT: - return set_mouse_record(rec, win_rec.Event.MouseEvent); - case WINDOW_BUFFER_SIZE_EVENT: - // TODO: Handle window resizing - return false; - default: - rec->type = ESCAPE; - } - return true; -} - -bool WinBlockInput(struct Controller *ctrl) -{ - size_t win_size = IO_BUF_SIZE - ctrl->input_buf.len; - INPUT_RECORD win_buf[win_size]; - DWORD count; - - if (!ReadConsoleInput( - win.input_handle, // Input handle - win_buf, // Record buffer - win_size, // Record buffer length - &count // Out number of records - )) - return false; - - struct timespec now; - timespec_get(&now, TIME_UTC); - - pthread_mutex_lock(&buf->mutex); - - for (size_t i = 0; i < count; i++) { - struct InputRecord rec; - rec.timestamp = now; - - bool include = dispatch_record(&rec, win_buf[i]); - if (!include) - continue; - - buf->records[buf->count++] = rec; - } - - pthread_mutex_unlock(&buf->mutex); - return true; -} - -bool WinWait(struct timespec relative) -{ - LARGE_INTEGER duration; - duration.QuadPart = -10000000 * relative.tv_sec - relative.tv_nsec / 100; - - if (!SetWaitableTimer( - win.timer, // Timer - &duration, // Duration - 0, // Period - NULL, // Completion coroutine - NULL, // Completion coroutine arg - FALSE // Resume - )) - return false; - - DWORD result = WaitForSingleObject(win.timer, INFINITE); - if (result != WAIT_OBJECT_0) - return false; - - return true; -} \ No newline at end of file diff --git a/source/io/platforms/winhandler.h b/source/io/platforms/winhandler.h deleted file mode 100644 index 61d4fae..0000000 --- a/source/io/platforms/winhandler.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -#include "fumotris.h" - -bool WinInitHandles(); - -bool WinInitConsole(); - -bool WinGetRefreshRate(u16f *out); - -bool WinBlockInput(struct RecordBuffer *buf); - -bool WinWait(struct timespec relative); \ No newline at end of file diff --git a/source/main.c b/source/main.c index 8a2396c..8113cd0 100644 --- a/source/main.c +++ b/source/main.c @@ -75,15 +75,15 @@ struct CtrlBind { const size_t code_count = 12; const struct CtrlBind ctrl_binds[12] = { - { LEFT, 0x25, KEY }, - { RIGHT, 0x27, KEY }, - { SOFT_DROP, 0x28, KEY }, - { HARD_DROP, 0x20, KEY }, - { ROTATE_CCW, 'Z', KEY }, - { ROTATE_CW, 'X', KEY }, - { ROTATE_180, 'A', KEY }, - { SWAP, 'C', KEY }, - { ESC, 0x1B, KEY }, + { LEFT, 0x25, BUTTON }, + { RIGHT, 0x27, BUTTON }, + { SOFT_DROP, 0x28, BUTTON }, + { HARD_DROP, 0x20, BUTTON }, + { ROTATE_CCW, 'Z', BUTTON }, + { ROTATE_CW, 'X', BUTTON }, + { ROTATE_180, 'A', BUTTON }, + { SWAP, 'C', BUTTON }, + { ESC, 0x1B, BUTTON }, { VSCROLL, 0, AXIS }, { HSCROLL, 1, AXIS }, { MOUSE, 0, JOYSTICK } @@ -96,7 +96,7 @@ void *Update(void *args) while (true) { // Input CtrlPoll(&game->ctrl); - if (CtrlGet(&game->ctrl, LEFT, KEY)->button.is_down) + if (CtrlGet(&game->ctrl, LEFT, BUTTON)->button.is_down) printf("left down this frame\n"); // Game logic