th j
This commit is contained in:
Julia 2024-04-22 17:13:13 -05:00
parent 599c41ef1b
commit 8ad3bf1f22
12 changed files with 146 additions and 116 deletions

View file

@ -1,51 +1,58 @@
#include <iso646.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "event.h"
#include "fumotris.h"
#define INIT_CAPACITY 16
struct Delegate {
size_t len;
size_t capacity;
void (**events)(void *args);
};
size_t delegate_size(size_t capacity)
{
return sizeof(void(*)(void *)) * capacity;
size_t clbks_size(size_t capacity) {
return sizeof(union func) * capacity;
}
bool NewDelegate(struct Delegate *d, size_t capacity)
bool CreateEvent(struct Event *event)
{
void (**events)(void *args) = malloc(delegate_size(capacity));
union func *callbacks = malloc(clbks_size(INIT_CAPACITY));
if (events == nullptr)
if (callbacks == nullptr)
return false;
*d = (struct Delegate) {
*event = (struct Event) {
.clbks = callbacks,
.len = 0,
.capacity = capacity,
.events = malloc(delegate_size(capacity))
.capacity = INIT_CAPACITY,
};
return true;
}
void Subscribe(struct Delegate *d, void (*event)(void *args))
void FreeEvent(struct Event *event)
{
if (d->len == d->capacity) {
d->capacity *= 2;
d->events = realloc(d->events, delegate_size(d->capacity));
}
d->events[d->len] = event;
d->len += 1;
free(event->clbks);
}
void Invoke(struct Delegate *d, void *args)
bool EventSubscribe(struct Event *event, union func callback)
{
for (size_t i = 0; i < d->len; i++) {
d->events[i](args);
if (event->len == event->capacity) {
size_t new_cap = event->capacity * 2;
union func *new_clbks = realloc(event->clbks, clbks_size(new_cap));
if (new_clbks == nullptr)
return false;
event->clbks = new_clbks;
event->capacity = new_cap;
}
event->clbks[event->len++] = callback;
return true;
}
void EventInvoke(struct Event *event, void *arg)
{
for (size_t i = 0; i < event->len; i++) {
event->clbks[i].generic(arg);
}
}
void EventInvokeUpdate(struct Event *event, u64 dt)
{
for (size_t i = 0; i < event->len; i++) {
event->clbks[i].update(dt);
}
}

View file

@ -6,15 +6,23 @@
#include <stdlib.h>
#include "fumotris.h"
#include "gametime.h"
struct Delegate {
size_t len;
size_t capacity;
void (**events)(void *args);
union func {
void (*generic)(void *arg);
void (*update)(Time dt);
};
bool NewDelegate(struct Delegate *d, size_t capacity);
struct Event {
union func *clbks;
size_t len;
size_t capacity;
};
void Subscribe(struct Delegate *d, void (*event)(void *args));
bool CreateEvent(struct Event *event);
void Invoke(struct Delegate *d, void *args);
bool EventSubscribe(struct Event *event, union func callback);
void EventInvoke(struct Event *event, void *arg);
void EventInvokeUpdate(struct Event *event, Time dt);

View file

@ -1,24 +1,17 @@
#include "gametime.h"
#include <time.h>
#include <stdbool.h>
#ifdef _WIN32
#include "win.h"
#endif
#define ONE_E_9 1000000000
struct Time {
u32 sec;
u32 nsec;
};
struct Time TimeNow()
Time TimeNow()
{
struct timespec ts;
// Need to check for failiure
timespec_get(&ts, TIME_UTC);
return (struct Time) { ts.tv_sec, ts.tv_nsec };
return ts.tv_nsec + ts.tv_sec * ONE_E_9;
}
double TimeNowDouble()
double TimeNowD()
{
struct timespec ts;
timespec_get(&ts, TIME_UTC);

View file

@ -1,11 +1,11 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
struct Time {
u32 sec;
u32 nsec;
};
#include "fumotris.h"
struct Time TimeNow();
typedef u64 Time;
double TimeNowDouble();
Time TimeNow();
double TimeNowD();

View file

@ -1,5 +1,7 @@
#include "ctrl.h"
#include <pthread.h>
#define INIT_SIZE 16
bool CreateCtrl(struct Controller *ctrl)
@ -142,7 +144,7 @@ void dispatch_update(struct InputAxis *axis, struct InputRecord *rec)
axis->data = rec->data;
}
bool CtrlPoll(struct Controller *ctrl)
bool read_input_buf(struct Controller *ctrl)
{
for (size_t i = 0; i < ctrl->pending_buf.len; i++) {
struct InputAxis *axis = ctrl->pending_buf.axes[i];
@ -150,22 +152,38 @@ bool CtrlPoll(struct Controller *ctrl)
axis->is_up = false;
axis->is_down = false;
}
ctrl->pending_buf.len = ctrl->buf.len;
ctrl->pending_buf.len = 0;
for (size_t i = 0; i < ctrl->buf.len; i++) {
struct InputRecord *rec = &ctrl->buf.recs[i];
union InputID rec_id = to_id(rec->bind, rec->type);
struct InputAxis *axis = find_axis(&ctrl->binds, rec_id);
if (axis == nullptr)
continue;
dispatch_update(axis, rec);
ctrl->pending_buf.axes[i] = axis;
ctrl->pending_buf.axes[ctrl->pending_buf.len++] = axis;
}
ctrl->buf.len = 0;
ctrl->buf.len = 0;
return true;
}
bool CtrlPoll(struct Controller *ctrl, struct InputThreadHandle *hand)
{
if (pthread_mutex_lock(&hand->mutex) != 0)
return false;
read_input_buf(ctrl);
if (pthread_cond_signal(&hand->buf_read) != 0)
return false;
if (pthread_mutex_unlock(&hand->mutex) != 0)
return false;
return true;
}

View file

@ -1,6 +1,5 @@
#pragma once
#include <iso646.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
@ -11,8 +10,8 @@
#include "input.h"
struct InputAxis {
struct Time last_pressed;
struct Time last_released;
Time last_pressed;
Time last_released;
union {
struct Button but;
@ -46,15 +45,18 @@ struct ctrl_axis_vec {
struct Controller {
struct InputBuffer buf;
struct {
struct InputAxis *axes[IO_BUF_SIZE];
u16f len;
} pending_buf;
struct InputAxis *pending_axes[IO_BUF_SIZE];
char string_input[IO_BUF_SIZE];
u8f pending_axes_len;
u8f string_input_len;
struct ctrl_axis_vec axis_vec;
struct ctrl_dict codes;
struct ctrl_dict binds;
};
size_t a = sizeof(struct Controller);
bool CreateCtrl(struct Controller *ctrl);
@ -64,7 +66,7 @@ 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);
bool CtrlPoll(struct Controller *ctrl, struct InputThreadHandle *hand);
enum ControlCode {
LEFT,

View file

@ -6,13 +6,13 @@ struct InputRecord *buf_get(struct InputBuffer *buf, size_t i) {
return buf->recs + (buf->start + i) % IO_BUF_SIZE;
}
size_t max_size(size_t a, size_t b) {
return a > b ? a : b;
size_t min_size(size_t a, size_t b) {
return a < b ? a : b;
}
void InputBufferTransfer(struct InputBuffer *dest, struct InputBuffer *src)
{
size_t copy_amt = IO_BUF_SIZE - max_size(dest->len, src->len);
size_t copy_amt = min_size(IO_BUF_SIZE - dest->len, src->len);
for (size_t i = 0; i < copy_amt; i++)
*buf_get(dest, dest->len + i) = *buf_get(src, i);
@ -35,7 +35,6 @@ void *input_thread_loop(void *arg)
struct InputBuffer tmp_buf = { .len = 0, .start = 0 };
while (!hand->is_terminating) {
printf("\tinput cycle");
if (!PlatformReadInput(&tmp_buf)) {
hand->err = true;
return nullptr;
@ -45,7 +44,13 @@ void *input_thread_loop(void *arg)
if (hand->err)
return nullptr;
InputBufferTransfer(&tmp_buf, hand->buf);
while (tmp_buf.len == IO_BUF_SIZE) {
hand->err = pthread_cond_wait(&hand->buf_read, &hand->mutex);
if (hand->err)
return nullptr;
}
InputBufferTransfer(hand->buf, &tmp_buf);
hand->err = pthread_mutex_unlock(&hand->mutex);
if (hand->err)
@ -57,7 +62,11 @@ void *input_thread_loop(void *arg)
bool BeginInputThread(struct InputThreadHandle *hand, struct InputBuffer *buf)
{
hand->buf = buf;
hand->mutex = PTHREAD_MUTEX_INITIALIZER;
hand->buf_read = PTHREAD_COND_INITIALIZER;
hand->err = 0;
return pthread_create(&hand->thread, nullptr, input_thread_loop, hand) == 0;
}

View file

@ -48,7 +48,7 @@ union InputData {
};
struct InputRecord {
struct Time time;
Time time;
union {
struct Button but;
@ -76,6 +76,7 @@ struct InputThreadHandle {
pthread_t thread;
pthread_mutex_t mutex;
pthread_cond_t buf_read;
int err;
bool is_terminating;

View file

@ -20,4 +20,4 @@ bool PlatformReadInput(struct InputBuffer *buf);
bool PlatformStopInput();
bool PlatformWait(struct Time relative);
bool PlatformWait(Time duration);

View file

@ -6,13 +6,7 @@
#include "input.h"
struct windows {
union {
HANDLE input_hands[2];
struct {
HANDLE input_hand;
HANDLE early_exit_hand;
};
};
HANDLE input_hand;
HANDLE timer;
} win;
@ -26,10 +20,6 @@ bool init_handles()
if (win.timer == NULL)
return false;
win.early_exit_hand = CreateEventW(NULL, FALSE, FALSE, NULL);
if (win.early_exit_hand == NULL)
return false;
return true;
}
@ -68,7 +58,7 @@ bool PlatformGetRefreshRate(u16f *out)
return true;
}
void copy_key_event(struct InputRecord *rec, KEY_EVENT_RECORD *win_key)
void read_key_event(struct InputRecord *rec, KEY_EVENT_RECORD *win_key)
{
rec->type = BUTTON;
rec->bind = win_key->wVirtualKeyCode;
@ -77,7 +67,7 @@ void copy_key_event(struct InputRecord *rec, KEY_EVENT_RECORD *win_key)
rec->is_up = !win_key->bKeyDown;
}
bool copy_mouse_event(struct InputRecord *rec, MOUSE_EVENT_RECORD *win_mouse)
bool read_mouse_event(struct InputRecord *rec, MOUSE_EVENT_RECORD *win_mouse)
{
if (win_mouse->dwEventFlags == MOUSE_MOVED) {
rec->type = JOYSTICK;
@ -99,15 +89,15 @@ bool copy_mouse_event(struct InputRecord *rec, MOUSE_EVENT_RECORD *win_mouse)
return false;
}
bool copy_rec(struct InputRecord *rec, INPUT_RECORD *win_rec)
bool read_rec(struct InputRecord *rec, INPUT_RECORD *win_rec)
{
switch (win_rec->EventType) {
case KEY_EVENT:
copy_key_event(rec, &win_rec->Event.KeyEvent);
read_key_event(rec, &win_rec->Event.KeyEvent);
return true;
case MOUSE_EVENT:
return copy_mouse_event(rec, &win_rec->Event.MouseEvent);
return read_mouse_event(rec, &win_rec->Event.MouseEvent);
case WINDOW_BUFFER_SIZE_EVENT:
return false;
@ -120,22 +110,17 @@ bool copy_rec(struct InputRecord *rec, INPUT_RECORD *win_rec)
bool PlatformReadInput(struct InputBuffer *buf)
{
DWORD wait_status = WaitForMultipleObjects(2, win.input_hands, FALSE, 0);
if (wait_status != 0)
return wait_status == 1;
DWORD max_records = IO_BUF_SIZE - buf->len;
INPUT_RECORD win_buf[max_records];
DWORD filled;
if (!ReadConsoleInputW(win.input_hand, win_buf, max_records, &filled))
return false;
struct InputRecord rec = { .time = TimeNow() };
for (size_t i = 0; i < filled; i++) {
if (!copy_rec(&rec, win_buf + i))
if (!read_rec(&rec, win_buf + i))
continue;
InputBufferAdd(buf, &rec);
@ -146,15 +131,15 @@ bool PlatformReadInput(struct InputBuffer *buf)
bool PlatformStopInput()
{
return SetEvent(win.early_exit_hand) == 0;
return CancelSynchronousIo(win.input_hand);
}
bool PlatformWait(struct Time relative)
bool PlatformWait(Time duration)
{
LARGE_INTEGER duration;
duration.QuadPart = -10000000 * relative.sec - relative.nsec / 100;
LARGE_INTEGER nsec_div_100;
nsec_div_100.QuadPart = -duration / 100;
if (!SetWaitableTimer(win.timer, &duration, 0, NULL, NULL, FALSE))
if (!SetWaitableTimer(win.timer, &nsec_div_100, 0, NULL, NULL, FALSE))
return false;
DWORD result = WaitForSingleObject(win.timer, INFINITE);

View file

@ -10,7 +10,6 @@
#include "input.h"
#include "fumotris.h"
#include "term.h"
#include "tetr.h"
#include "event.h"
#include "platform.h"
@ -20,6 +19,14 @@ void ErrorExit(char *message)
exit(1);
}
struct Game {
struct Event Start;
struct Event Draw;
struct Event Update;
Time time;
};
int main()
{
if (!PlatformInit())
@ -29,20 +36,20 @@ int main()
if (!CreateCtrl(&ctrl))
ErrorExit("Out of memory");
struct InputThreadHandle input;
if (!BeginInputThread(&input, &ctrl.buf))
struct Game game;
CreateEvent(&game.Update);
struct InputThreadHandle input_hand;
if (!BeginInputThread(&input_hand, &ctrl.buf))
ErrorExit("Input handle failed to initialize");
CtrlMap(&ctrl, 0, BUTTON, 'A');
while (true) {
bool poll = CtrlPoll(&ctrl);
printf("poll: %u\n", poll);
if(!CtrlPoll(&ctrl, &input_hand))
ErrorExit("Poll failed");
struct InputAxis *a = CtrlGet(&ctrl, 0, BUTTON);
printf("get: %llu\n", a);
printf("val: %u\n", a->but.value);
EventInvokeUpdate(&game.Update, nullptr);
}
return 0;

BIN
test.exe

Binary file not shown.