f
This commit is contained in:
Julia 2024-05-02 17:17:37 -05:00
parent 1dcea1a2cf
commit 118e832a21
15 changed files with 253 additions and 207 deletions

View file

@ -88,7 +88,7 @@ def build(source_path, obj_path, out_path, recompile = False):
os.system(f"gcc -c {path} -I {' -I '.join(subdirs)} -o {obj_path}\\{name}.o -pthread -Wall -std=c17 -pedantic") os.system(f"gcc -c {path} -I {' -I '.join(subdirs)} -o {obj_path}\\{name}.o -pthread -Wall -std=c17 -pedantic")
write_checksum_file(checksums_now) write_checksum_file(checksums_now)
print(os.system(f"gcc {obj_path}\\*.o -o {out_path} -pthread -Wall -std=c17 -pedantic")) print(os.system(f"gcc {obj_path}\\*.o -o {out_path} -pthread -Wall -std=c17 -pedantic -g"))
build(sys.argv[1], sys.argv[2], sys.argv[3], True) build(sys.argv[1], sys.argv[2], sys.argv[3], True)

BIN
hi.exe

Binary file not shown.

View file

@ -1,7 +1,5 @@
#include "ctrl.h" #include "fumoengine.h"
#include "platform.h"
#include "event.h"
#include "fumocommon.h"
void ErrorExit(char *message) void ErrorExit(char *message)
@ -10,43 +8,19 @@ void ErrorExit(char *message)
exit(1); exit(1);
} }
struct FumoGame { bool FumoInit(struct FumoGame *game)
struct Controller ctrl;
struct InputHandle input_hand;
struct Event start;
struct Event draw;
struct Event update;
Time time;
};
bool FumoEngineInit(struct FumoGame *game)
{ {
if (!PlatformInit()) if (!PlatformInit())
ErrorExit("Platform failed to initialize"); ErrorExit("Platform failed to initialize");
if (!CreateCtrl(&game->ctrl)) if (!CreateController(&game->ctrl))
ErrorExit("Out of memory"); ErrorExit("Out of memory");
//CtrlMap(&ctrl, 0, BUTTON, 'A'); if (!CreateEvent(&game->update))
ErrorExit("Out of memory");
CreateEvent(&game->update); if (!BeginInputThread(&game->input_hand))
if (!BeginInputThread(&game->input_hand, &game->input_hand.recs, &ctrl.str))
ErrorExit("Input handle failed to initialize"); ErrorExit("Input handle failed to initialize");
while (true) {
if (!InputAquire(&input_hand))
ErrorExit("Aquire failed");
CtrlPoll(&ctrl);
if (!InputRelease(&input_hand))
ErrorExit("Release failed");
EventInvokeUpdate(&game.update, 0);
}
return 0; return 0;
} }

View file

@ -0,0 +1,23 @@
#pragma once
#include "ctrl.h"
#include "event.h"
#include "fumocommon.h"
#include "input.h"
struct FumoGame {
struct Controller ctrl;
struct InputHandle input_hand;
struct Event start;
struct Event draw;
struct Event update;
Time time;
};
void ErrorExit(char *message);
bool FumoInit(struct FumoGame *game);

View file

@ -50,7 +50,7 @@ void EventInvoke(struct Event *event, void *arg)
} }
} }
void EventInvokeUpdate(struct Event *event, u64 dt) void EventInvokeUpdate(struct Event *event, Time dt)
{ {
for (size_t i = 0; i < event->len; i++) { for (size_t i = 0; i < event->len; i++) {
event->clbks[i].update(dt); event->clbks[i].update(dt);

View file

@ -17,6 +17,13 @@ struct RingBufferHead {
size_t start; size_t start;
}; };
#define RINGBUF_T_INIT(RBUF_STRUCT, RBUF_ITEM, RBUF_LEN) \
(&(struct RingBufferT) { \
.OFFSET = offsetof(RBUF_STRUCT, buf), \
.SIZE = sizeof(RBUF_ITEM), \
.LEN = RBUF_LEN \
}) \
#define RINGBUF_HEAD_INIT ((struct RingBufferHead) { 0, 0 }) #define RINGBUF_HEAD_INIT ((struct RingBufferHead) { 0, 0 })
size_t RingBufferEmpty(RingBufferT T, struct RingBufferHead *head); size_t RingBufferEmpty(RingBufferT T, struct RingBufferHead *head);

View file

@ -5,7 +5,7 @@
#define INIT_SIZE 16 #define INIT_SIZE 16
bool CreateCtrl(struct Controller *ctrl) bool CreateController(struct Controller *ctrl)
{ {
struct ctrl_bkt *code_bkts = calloc(INIT_SIZE, sizeof(struct ctrl_bkt)); struct ctrl_bkt *code_bkts = calloc(INIT_SIZE, sizeof(struct ctrl_bkt));
struct ctrl_bkt *bind_bkts = calloc(INIT_SIZE, sizeof(struct ctrl_bkt)); struct ctrl_bkt *bind_bkts = calloc(INIT_SIZE, sizeof(struct ctrl_bkt));
@ -36,7 +36,7 @@ bool CreateCtrl(struct Controller *ctrl)
return true; return true;
} }
void FreeCtrl(struct Controller *ctrl) void FreeController(struct Controller *ctrl)
{ {
free(ctrl->codes.bkts); free(ctrl->codes.bkts);
free(ctrl->binds.bkts); free(ctrl->binds.bkts);
@ -105,7 +105,7 @@ union InputID as_id(u16f value, u16f type) {
return (union InputID) { .value = value, .type = type }; return (union InputID) { .value = value, .type = type };
} }
bool CtrlMap(struct Controller *ctrl, u16f code, u16f type, u16f bind) bool ControllerMap(struct Controller *ctrl, u16f code, u16f bind, u16f type)
{ {
struct ctrl_bkt *code_bkt = find_set(&ctrl->codes, as_id(code, 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)); struct ctrl_bkt *bind_bkt = find_set(&ctrl->binds, as_id(bind, type));
@ -120,7 +120,7 @@ bool CtrlMap(struct Controller *ctrl, u16f code, u16f type, u16f bind)
return true; return true;
} }
struct InputAxis *CtrlGet(struct Controller *ctrl, u16f code, u16f type) struct InputAxis *ControllerGet(struct Controller *ctrl, u16f code, u16f type)
{ {
struct ctrl_bkt *code_bkt = find(&ctrl->codes, as_id(code, type)); struct ctrl_bkt *code_bkt = find(&ctrl->codes, as_id(code, type));
if (code_bkt == nullptr) if (code_bkt == nullptr)
@ -144,15 +144,15 @@ void dispatch_update(struct InputAxis *axis, struct InputRecord *rec)
axis->data = rec->data; axis->data = rec->data;
} }
void CtrlPoll(struct Controller *ctrl, struct InputRecordBuf *recs) void ControllerPoll(struct Controller *ctrl, struct RecordBuffer *recs)
{ {
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 InputAxis *axis = ctrl->pending_buf.axes[i];
axis->is_up = false; axis->is_up = false;
axis->is_down = false; axis->is_down = false;
} }
ctrl->pending_buf.len = 0; ctrl->pending_buf.len = 0;*/
for (size_t i = 0; i < recs->head.len; i++) { for (size_t i = 0; i < recs->head.len; i++) {
struct InputRecord *rec = &recs->buf[i]; struct InputRecord *rec = &recs->buf[i];
@ -171,31 +171,37 @@ void CtrlPoll(struct Controller *ctrl, struct InputRecordBuf *recs)
/*int main() /*int main()
{ {
struct Controller ctrl; struct Controller ctrl;
if (!CreateCtrl(&ctrl)) if (!CreateController(&ctrl))
return 1; return 1;
CtrlMap(&ctrl, 123, BUTTON, 111); ControllerMap(&ctrl, 123, 111, BUTTON);
CtrlMap(&ctrl, 0, BUTTON, 8); ControllerMap(&ctrl, 0, 8, BUTTON);
struct RecordBuffer recs = { .head.len = 0, .head.start = 0 };
recs.buf[recs.head.len++] = (struct InputRecord) {
.but.value = 69,
ctrl.buf.recs[ctrl.buf.len++] = (struct InputRecord) {
.bind = 111,
.type = BUTTON,
.is_down = true, .is_down = true,
.but.value = 69
.id.bind = 111,
.id.type = BUTTON
}; };
ctrl.buf.recs[ctrl.buf.len++] = (struct InputRecord) { recs.buf[recs.head.len++] = (struct InputRecord) {
.bind = 8, .but.value = 1000,
.type = BUTTON,
.is_down = true, .is_down = true,
.but.value = 1000
.id.bind = 8,
.id.type = BUTTON
}; };
CtrlPoll(&ctrl); ControllerPoll(&ctrl, &recs);
struct InputAxis *a = CtrlGet(&ctrl, 123, BUTTON); struct InputAxis *a = ControllerGet(&ctrl, 123, BUTTON);
printf("%u\n", a->but.value); printf("%u\n", a->but.value);
struct InputAxis *b = CtrlGet(&ctrl, 0, BUTTON); struct InputAxis *b = ControllerGet(&ctrl, 0, BUTTON);
printf("%u\n", b->but.value); printf("%u\n", b->but.value);
printf("success"); printf("success");

View file

@ -57,49 +57,19 @@ struct Controller {
struct ctrl_dict binds; struct ctrl_dict binds;
}; };
bool CreateCtrl(struct Controller *ctrl);
void FreeCtrl(struct Controller *ctrl);
bool CtrlMap(struct Controller *ctrl, u16f code, u16f type, u16f bind);
struct InputAxis *CtrlGet(struct Controller *ctrl, u16f code, u16f type);
void CtrlPoll(struct Controller *ctrl, struct InputRecordBuf *recs);
enum ControlCode {
LEFT,
RIGHT,
SOFT_DROP,
HARD_DROP,
ROTATE_CCW,
ROTATE_CW,
ROTATE_180,
SWAP,
ESC,
VSCROLL,
HSCROLL,
MOUSE
};
struct ControlBind { struct ControlBind {
enum ControlCode code; int code;
u16 bind; u16 bind;
u8 type; u16 type;
}; };
#define CODE_COUNT 12
/*const struct ControlBind ctrl_binds[12] = { bool CreateController(struct Controller *ctrl);
{ LEFT, 0x25, BUTTON }, void FreeController(struct Controller *ctrl);
{ RIGHT, 0x27, BUTTON },
{ SOFT_DROP, 0x28, BUTTON }, bool ControllerMap(struct Controller *ctrl, u16f code, u16f bind, u16f type);
{ HARD_DROP, 0x20, BUTTON },
{ ROTATE_CCW, 'Z', BUTTON }, struct InputAxis *ControllerGet(struct Controller *ctrl, u16f code, u16f type);
{ ROTATE_CW, 'X', BUTTON },
{ ROTATE_180, 'A', BUTTON }, void ControllerPoll(struct Controller *ctrl, struct RecordBuffer *recs);
{ SWAP, 'C', BUTTON },
{ ESC, 0x1B, BUTTON },
{ VSCROLL, 0, AXIS },
{ HSCROLL, 1, AXIS },
{ MOUSE, 0, JOYSTICK }
};*/

View file

@ -4,25 +4,25 @@
#include "platform.h" #include "platform.h"
const struct RingBufferT IO_BUF_T = { RingBufferT IO_BUF_T = RINGBUF_T_INIT(
.OFFSET = offsetof(struct InputRecordBuf, buf), struct RecordBuffer,
.SIZE = sizeof(struct InputRecord), struct InputRecord,
.LEN = IO_BUF_SIZE IO_BUF_SIZE
}; );
const struct RingBufferT STR_BUF_T = { RingBufferT STR_BUF_T = RINGBUF_T_INIT(
.OFFSET = offsetof(struct InputStringBuf, buf), struct StringBuffer,
.SIZE = sizeof(char), char,
.LEN = STR_BUF_SIZE STR_BUF_SIZE
}; );
void *input_worker(void *arg) void *input_worker(void *arg)
{ {
struct InputHandle *hand = arg; struct InputHandle *hand = arg;
struct InputRecordBuf tmp_recs = { .head.len = 0, .head.start = 0 }; struct RecordBuffer tmp_recs = { .head.len = 0, .head.start = 0 };
struct InputStringBuf tmp_str = { .head.len = 0, .head.start = 0 }; struct StringBuffer tmp_str = { .head.len = 0, .head.start = 0 };
while (!hand->is_terminating) { while (!hand->is_terminating) {
if (!PlatformReadInput(&tmp_recs, &tmp_str)) { if (!PlatformReadInput(&tmp_recs, &tmp_str)) {
@ -42,8 +42,8 @@ void *input_worker(void *arg)
} }
} }
RingBufferTransfer(&IO_BUF_T, &hand->recs->head, &tmp_recs.head); RingBufferTransfer(IO_BUF_T, &hand->recs.head, &tmp_recs.head);
RingBufferTransfer(&STR_BUF_T, &hand->str->head, &tmp_str.head); RingBufferTransfer(STR_BUF_T, &hand->str.head, &tmp_str.head);
if (pthread_mutex_unlock(&hand->mutex) != 0) { if (pthread_mutex_unlock(&hand->mutex) != 0) {
hand->err = true; hand->err = true;
@ -54,14 +54,11 @@ void *input_worker(void *arg)
return nullptr; return nullptr;
} }
bool BeginInputThread( bool BeginInputThread(struct InputHandle *hand)
struct InputHandle *hand, {
struct InputRecordBuf *in,
struct InputStringBuf *str
) {
*hand = (struct InputHandle) { *hand = (struct InputHandle) {
.recs = in, .recs.head = RINGBUF_HEAD_INIT,
.str = str, .str.head = RINGBUF_HEAD_INIT,
.err = 0, .err = 0,
.is_terminating = false, .is_terminating = false,
@ -114,7 +111,7 @@ bool InputRelease(struct InputHandle *hand)
return true; return true;
} }
size_t InputString(struct InputStringBuf *str, size_t n, char *buf) size_t InputString(struct InputHandle *hand, size_t n, char *buf)
{ {
return RingBufferOut(&STR_BUF_T, n, buf, &str->head); return RingBufferOut(STR_BUF_T, n, buf, &hand->str.head);
} }

View file

@ -13,8 +13,8 @@
#define STR_BUF_SIZE (IO_BUF_SIZE * 4) #define STR_BUF_SIZE (IO_BUF_SIZE * 4)
extern const struct RingBufferT IO_BUF_T; extern RingBufferT IO_BUF_T;
extern const struct RingBufferT STR_BUF_T; extern RingBufferT STR_BUF_T;
enum InputType { enum InputType {
@ -25,15 +25,17 @@ enum InputType {
}; };
union InputID { union InputID {
u32 hash;
struct { struct {
union { union {
u16 code; u16 code;
u16 bind; u16 bind;
u16 value; u16 value;
}; };
u16 type; u16 type;
}; };
u32 hash;
}; };
@ -76,20 +78,19 @@ struct InputRecord {
}; };
}; };
struct InputBuffer { struct RecordBuffer {
struct { struct RingBufferHead head;
struct RingBufferHead head; struct InputRecord buf[IO_BUF_SIZE];
struct InputRecord buf[IO_BUF_SIZE]; };
} recs;
struct { struct StringBuffer {
struct RingBufferHead head; struct RingBufferHead head;
char buf[STR_BUF_SIZE]; char buf[STR_BUF_SIZE];
} str;
}; };
struct InputHandle { struct InputHandle {
struct InputBuffer in; struct RecordBuffer recs;
struct StringBuffer str;
pthread_t thread; pthread_t thread;
pthread_mutex_t mutex; pthread_mutex_t mutex;
@ -99,10 +100,7 @@ struct InputHandle {
bool is_terminating; bool is_terminating;
}; };
bool BeginInputThread( bool BeginInputThread(struct InputHandle *hand);
struct InputHandle *hand,
struct InputBuffer *in,
);
bool EndInputThread(struct InputHandle *hand); bool EndInputThread(struct InputHandle *hand);
@ -110,4 +108,4 @@ bool InputAquire(struct InputHandle *hand);
bool InputRelease(struct InputHandle *hand); bool InputRelease(struct InputHandle *hand);
size_t InputString(struct Controller *ctrl, size_t n, char *buf); size_t InputString(struct InputHandle *hand, size_t n, char *buf);

View file

@ -16,7 +16,7 @@ bool PlatformInit();
bool PlatformGetRefreshRate(u16f *out); bool PlatformGetRefreshRate(u16f *out);
bool PlatformReadInput(struct InputRecordBuf *in, struct InputStringBuf *str); bool PlatformReadInput(struct RecordBuffer *recs, struct StringBuffer *str);
bool PlatformStopInput(); bool PlatformStopInput();

View file

@ -69,11 +69,6 @@ struct win_rec {
}; };
}; };
union record {
struct win_rec native;
INPUT_RECORD win;
};
bool init_handles() bool init_handles()
{ {
win.input_hand = GetStdHandle(STD_INPUT_HANDLE); win.input_hand = GetStdHandle(STD_INPUT_HANDLE);
@ -123,33 +118,33 @@ bool PlatformGetRefreshRate(u16f *out)
} }
bool dispatch_rec( bool dispatch_rec(
struct InputRecord *out, struct InputRecord *rec,
struct InputStringBuf *str, struct StringBuffer *str,
struct win_rec *rec struct win_rec *win
) { ) {
u8f type = rec->type | (rec->is_mouse & rec->mouse.flags); u8f type = win->type | (win->is_mouse & win->mouse.flags);
switch (type) { switch (type) {
case KEY_EVENT: { case KEY_EVENT: {
ReadButton(out, rec->key.vk_code, rec->key.is_down); ReadButton(rec, win->key.vk_code, win->key.is_down);
if (rec->key.is_down) if (win->key.is_down)
str->head.len += UCS2ToUTF8(str->buf, rec->key.ucs2_char); str->head.len += UCS2ToUTF8(str->buf, win->key.ucs2_char);
return true; return true;
} }
case MOUSE_MOVE: { case MOUSE_MOVE: {
ReadJoystick(out, 0, rec->mouse.pos.x, rec->mouse.pos.y); ReadJoystick(rec, 0, win->mouse.pos.x, win->mouse.pos.y);
return true; return true;
} }
case MOUSE_VWHEEL: { case MOUSE_VWHEEL: {
ReadAxis(out, 0, rec->mouse.but); ReadAxis(rec, 0, win->mouse.but);
return true; return true;
} }
case MOUSE_HWHEEL: { case MOUSE_HWHEEL: {
ReadAxis(out, 1, rec->mouse.but); ReadAxis(rec, 1, win->mouse.but);
return true; return true;
} }
@ -163,21 +158,30 @@ bool dispatch_rec(
return false; return false;
} }
bool PlatformReadInput(struct InputRecordBuf *recs, struct InputStringBuf *str) size_t read_input(struct win_rec *buf, size_t n)
{ {
DWORD read_max = RingBufferEmpty(&IO_BUF_T, &recs->head); DWORD len;
union record win_buf[read_max]; if (!ReadConsoleInputW(win.input_hand, buf, n, &len))
DWORD filled; return 0;
if (!ReadConsoleInputW(win.input_hand, &win_buf->win, read_max, &filled)) return len;
}
bool PlatformReadInput(struct RecordBuffer *recs, struct StringBuffer *str)
{
size_t n = RingBufferEmpty(IO_BUF_T, &recs->head);
struct win_rec buf[n];
size_t len = read_input(buf, n);
if (len == 0)
return false; return false;
Time now = TimeNow(); Time now = TimeNow();
for (size_t i = 0; i < filled; i++) { for (size_t i = 0; i < len; i++) {
struct InputRecord *rec = RingBufferNext(&IO_BUF_T, &recs->head); struct InputRecord *rec = RingBufferNext(IO_BUF_T, &recs->head);
if (dispatch_rec(rec, str, &win_buf->native + i)) { if (dispatch_rec(rec, str, &buf[i])) {
rec->time = now; rec->time = now;
recs->head.len += 1; recs->head.len += 1;
} }

View file

@ -1,43 +0,0 @@
/*const u8 I[16] = {
0, 0, 0, 0,
0, 0, 0, 0,
1, 1, 1, 1,
0, 0, 0, 0
};
const u8 O[4] = {
1, 1,
1, 1
};
const u8 T[9] = {
0, 1, 0,
1, 1, 1,
0, 0, 0
};
const u8 S[9] = {
0, 1, 1,
1, 1, 0,
0, 0, 0
};
const u8 Z[9] = {
1, 1, 0,
0, 1, 1,
0, 0, 0
};
const u8 J[9] = {
1, 0, 0,
1, 1, 1,
0, 0, 0
};
const u8 L[9] = {
0, 0, 1,
1, 1, 1,
0, 0, 0
};*/

110
source/fumotris/fumotris.c Normal file
View file

@ -0,0 +1,110 @@
#include "fumocommon.h"
#include "fumoengine.h"
enum ControlCode {
LEFT,
RIGHT,
SOFT_DROP,
HARD_DROP,
ROTATE_CCW,
ROTATE_CW,
ROTATE_180,
SWAP,
ESC,
VSCROLL,
HSCROLL,
MOUSE
};
#define CODE_COUNT 12
const struct ControlBind ctrl_binds[12] = {
{ 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 }
};
void Loop(struct FumoGame *game)
{
while (true) {
game->time = TimeNow();
if (!InputAquire(&game->input_hand))
ErrorExit("Aquire failed");
//ControllerPoll(&game->ctrl, &game->input_hand.recs);
if (!InputRelease(&game->input_hand))
ErrorExit("Release failed");
//EventInvokeUpdate(&game->update, 0);
}
}
int main()
{
struct FumoGame game;
FumoInit(&game);
for (size_t i = 0; i < CODE_COUNT; i++) {
const struct ControlBind *bind = &ctrl_binds[i];
ControllerMap(&game.ctrl, bind->code, bind->bind, bind->type);
}
Loop(&game);
return 0;
}
/*const u8 I[16] = {
0, 0, 0, 0,
0, 0, 0, 0,
1, 1, 1, 1,
0, 0, 0, 0
};
const u8 O[4] = {
1, 1,
1, 1
};
const u8 T[9] = {
0, 1, 0,
1, 1, 1,
0, 0, 0
};
const u8 S[9] = {
0, 1, 1,
1, 1, 0,
0, 0, 0
};
const u8 Z[9] = {
1, 1, 0,
0, 1, 1,
0, 0, 0
};
const u8 J[9] = {
1, 0, 0,
1, 1, 1,
0, 0, 0
};
const u8 L[9] = {
0, 0, 1,
1, 1, 1,
0, 0, 0
};*/

BIN
test.exe

Binary file not shown.