kjjkkjl
fuck
This commit is contained in:
parent
ef7362c5d9
commit
21c89ae7f9
45
source/game/event.c
Normal file
45
source/game/event.c
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#include <iso646.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "fumotris.h"
|
||||||
|
|
||||||
|
struct Delegate {
|
||||||
|
size_t len;
|
||||||
|
size_t capacity;
|
||||||
|
void (**events)(void *args);
|
||||||
|
};
|
||||||
|
|
||||||
|
inline size_t delegate_size(size_t capacity)
|
||||||
|
{
|
||||||
|
return sizeof(void(*)(void *)) * capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Delegate NewDelegate(size_t capacity)
|
||||||
|
{
|
||||||
|
return (struct Delegate) {
|
||||||
|
.len = 0,
|
||||||
|
.capacity = capacity,
|
||||||
|
.events = malloc(delegate_size(capacity))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void Subscribe(struct Delegate *d, void (*event)(void *args))
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Call(struct Delegate *d, void *args)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < d->len; i++) {
|
||||||
|
d->events[i](args);
|
||||||
|
}
|
||||||
|
}
|
20
source/game/event.h
Normal file
20
source/game/event.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#pragma once
|
||||||
|
#include <iso646.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "fumotris.h"
|
||||||
|
|
||||||
|
struct Delegate {
|
||||||
|
size_t len;
|
||||||
|
size_t capacity;
|
||||||
|
void (**events)(void *args);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Delegate NewDelegate(size_t capacity);
|
||||||
|
|
||||||
|
void Subscribe(struct Delegate *d, void (*event)(void *args));
|
||||||
|
|
||||||
|
void Call(struct Delegate *d, void *args);
|
|
@ -33,7 +33,7 @@ struct TetrMap NewTetrMap(u8 *blks, size_t wid, size_t hgt)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void TetrMapToTermBuf(struct TetrMap *map, struct TermBuf *term)
|
void TetrMapToTermBuf(struct TetrMap *map, struct Terminal *term)
|
||||||
{
|
{
|
||||||
static const u8f blk_colors[8] = { 8, 14, 11, 13, 10, 9, 12, 3 };
|
static const u8f blk_colors[8] = { 8, 14, 11, 13, 10, 9, 12, 3 };
|
||||||
|
|
||||||
|
@ -42,8 +42,8 @@ void TetrMapToTermBuf(struct TetrMap *map, struct TermBuf *term)
|
||||||
size_t map_i = y * map->wid + x;
|
size_t map_i = y * map->wid + x;
|
||||||
size_t buf_i = (y + map->y) * term->wid + (x + map->x) * 2;
|
size_t buf_i = (y + map->y) * term->wid + (x + map->x) * 2;
|
||||||
|
|
||||||
struct CharBlk4 *a = &term->blks[buf_i];
|
struct TChar4 *a = &term->blks[buf_i];
|
||||||
struct CharBlk4 *b = &term->blks[buf_i + 1];
|
struct TChar4 *b = &term->blks[buf_i + 1];
|
||||||
|
|
||||||
if (map->blks[map_i] == 0) {
|
if (map->blks[map_i] == 0) {
|
||||||
a->ch = '(';
|
a->ch = '(';
|
||||||
|
|
|
@ -23,6 +23,6 @@ struct TetrMap {
|
||||||
|
|
||||||
struct TetrMap NewTetrMap(u8 *blks, size_t wid, size_t hgt);
|
struct TetrMap NewTetrMap(u8 *blks, size_t wid, size_t hgt);
|
||||||
|
|
||||||
void TetrMapToTermBuf(struct TetrMap *map, struct TermBuf *term);
|
void TetrMapToTermBuf(struct TetrMap *map, struct Terminal *term);
|
||||||
|
|
||||||
bool TetrCollisionCheck(struct TetrMap *board, struct TetrMap *piece, int dx, int dy);
|
bool TetrCollisionCheck(struct TetrMap *board, struct TetrMap *piece, int dx, int dy);
|
110
source/io/ctrl.c
110
source/io/ctrl.c
|
@ -88,64 +88,83 @@ hashtype Hash(void *item, size_t size)
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ident {
|
|
||||||
u16 id;
|
|
||||||
u8 type;
|
|
||||||
};
|
|
||||||
|
|
||||||
hashtype hash_ident(u16f value, u8f type)
|
hashtype hash_ident(u16f value, u8f type)
|
||||||
{
|
{
|
||||||
struct ident id = { value, type };
|
struct id {
|
||||||
return Hash(&id, sizeof(struct ident));
|
u16 id;
|
||||||
|
u8 type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct id id = { value, type };
|
||||||
|
return Hash(&id, sizeof(struct id));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bkt {
|
struct ctrl_bkt {
|
||||||
hashtype hash;
|
hashtype hash;
|
||||||
u16 value;
|
u16 value;
|
||||||
u8 type;
|
u8 type;
|
||||||
struct Axis *axis;
|
struct Axis *axis;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dict {
|
struct ctrl_dict {
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
size_t filled;
|
size_t filled;
|
||||||
struct bkt *bkts;
|
struct ctrl_bkt *bkts;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ctrl {
|
struct Ctrl {
|
||||||
struct dict codes;
|
struct ctrl_dict codes;
|
||||||
struct dict binds;
|
struct ctrl_dict binds;
|
||||||
|
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
};
|
};
|
||||||
typedef struct Ctrl Ctrl;
|
|
||||||
|
|
||||||
Ctrl NewCtrl(struct dict *codes, struct dict *binds, struct Axis *axes)
|
struct Ctrl NewCtrl()
|
||||||
{
|
{
|
||||||
memset(codes->bkts, 0, sizeof(struct bkt) * codes->capacity);
|
struct Ctrl ctrl = (struct Ctrl) {
|
||||||
memset(binds->bkts, 0, sizeof(struct bkt) * binds->capacity);
|
.codes = (struct ctrl_dict) {
|
||||||
memset(axes, 0, sizeof(struct Axis) * codes->capacity);
|
.capacity = 0,
|
||||||
|
.filled = 0,
|
||||||
for (size_t i = 0; i < codes->capacity; i++) {
|
.bkts = nullptr
|
||||||
codes->bkts[i].axis = &axes[i];
|
},
|
||||||
}
|
.binds = (struct ctrl_dict) {
|
||||||
|
.capacity = 0,
|
||||||
Ctrl ctrl;
|
.filled = 0,
|
||||||
ctrl.codes = *codes;
|
.bkts = nullptr
|
||||||
ctrl.binds = *binds;
|
},
|
||||||
ctrl.mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
|
|
||||||
|
.mutex = PTHREAD_MUTEX_INITIALIZER
|
||||||
|
};
|
||||||
return ctrl;
|
return ctrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bkt *get_bkt(struct dict *dict, size_t i)
|
void CtrlSet(
|
||||||
|
struct Ctrl *ctrl,
|
||||||
|
struct ctrl_bkt *code_bkts,
|
||||||
|
struct ctrl_bkt *bind_bkts,
|
||||||
|
struct Axis *axes,
|
||||||
|
size_t c_len,
|
||||||
|
size_t b_len
|
||||||
|
) {
|
||||||
|
ctrl->codes.capacity = c_len;
|
||||||
|
ctrl->codes.bkts = code_bkts;
|
||||||
|
memset(code_bkts, 0, sizeof(struct ctrl_bkt) * c_len);
|
||||||
|
|
||||||
|
ctrl->binds.capacity = b_len;
|
||||||
|
ctrl->binds.bkts = bind_bkts;
|
||||||
|
memset(bind_bkts, 0, sizeof(struct ctrl_bkt) * b_len);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ctrl_bkt *get_bkt(struct ctrl_dict *dict, size_t i)
|
||||||
{
|
{
|
||||||
assert(i < dict->capacity);
|
assert(i < dict->capacity);
|
||||||
return &dict->bkts[i];
|
return &dict->bkts[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_bkt(struct bkt *bkt, hashtype hash, u16f value, u8f type)
|
void set_bkt(struct ctrl_bkt *bkt, hashtype hash, u16f value, u8f type)
|
||||||
{
|
{
|
||||||
bkt->hash = hash;
|
bkt->hash = hash;
|
||||||
bkt->value = value;
|
bkt->value = value;
|
||||||
|
@ -157,14 +176,14 @@ size_t wrap(size_t x, size_t wrap)
|
||||||
return x % (SIZE_MAX - wrap + 1);
|
return x % (SIZE_MAX - wrap + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool find_or_set(struct dict *dict, struct bkt **out, u16f value, u8f type)
|
bool find_or_set(struct ctrl_dict *dict, struct ctrl_bkt **out, u16f value, u8f type)
|
||||||
{
|
{
|
||||||
hashtype hash = hash_ident(value, type);
|
hashtype hash = hash_ident(value, type);
|
||||||
const size_t index = hash % dict->capacity;
|
const size_t index = hash % dict->capacity;
|
||||||
|
|
||||||
size_t i = index;
|
size_t i = index;
|
||||||
while (i != wrap(index - 1, dict->capacity)) {
|
while (i != wrap(index - 1, dict->capacity)) {
|
||||||
struct bkt *bkt = get_bkt(dict, i);
|
struct ctrl_bkt *bkt = get_bkt(dict, i);
|
||||||
|
|
||||||
if (bkt->hash == 0) {
|
if (bkt->hash == 0) {
|
||||||
set_bkt(bkt, hash, value, type);
|
set_bkt(bkt, hash, value, type);
|
||||||
|
@ -185,14 +204,14 @@ bool find_or_set(struct dict *dict, struct bkt **out, u16f value, u8f type)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bkt *find(struct dict *dict, u16f value, u8f type)
|
struct ctrl_bkt *find(struct ctrl_dict *dict, u16f value, u8f type)
|
||||||
{
|
{
|
||||||
hashtype hash = hash_ident(value, type);
|
hashtype hash = hash_ident(value, type);
|
||||||
const size_t index = hash % dict->capacity;
|
const size_t index = hash % dict->capacity;
|
||||||
|
|
||||||
size_t i = index;
|
size_t i = index;
|
||||||
while (i != wrap(index - 1, dict->capacity)) {
|
while (i != wrap(index - 1, dict->capacity)) {
|
||||||
struct bkt *bkt = get_bkt(dict, i);
|
struct ctrl_bkt *bkt = get_bkt(dict, i);
|
||||||
if (bkt->hash == 0)
|
if (bkt->hash == 0)
|
||||||
goto next;
|
goto next;
|
||||||
|
|
||||||
|
@ -206,25 +225,25 @@ next:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Axis *find_axis(struct dict *dict, u16f value, u8f type)
|
struct Axis *find_axis(struct ctrl_dict *dict, u16f value, u8f type)
|
||||||
{
|
{
|
||||||
struct bkt *bkt = find(dict, value, type);
|
struct ctrl_bkt *bkt = find(dict, value, type);
|
||||||
if (bkt == nullptr)
|
if (bkt == nullptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return bkt->axis;
|
return bkt->axis;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CtrlMap(Ctrl *ctrl, u16f code, u16f bind, u8f type)
|
bool CtrlMap(struct Ctrl *ctrl, u16f code, u16f bind, u8f type)
|
||||||
{
|
{
|
||||||
assert(ctrl->codes.filled < ctrl->codes.capacity);
|
assert(ctrl->codes.filled < ctrl->codes.capacity);
|
||||||
assert(ctrl->binds.filled < ctrl->binds.capacity);
|
assert(ctrl->binds.filled < ctrl->binds.capacity);
|
||||||
|
|
||||||
struct bkt *code_bkt;
|
struct ctrl_bkt *code_bkt;
|
||||||
find_or_set(&ctrl->codes, &code_bkt, code, type);
|
find_or_set(&ctrl->codes, &code_bkt, code, type);
|
||||||
assert(code_bkt != nullptr);
|
assert(code_bkt != nullptr);
|
||||||
|
|
||||||
struct bkt *bind_bkt;
|
struct ctrl_bkt *bind_bkt;
|
||||||
bool bind_existed = find_or_set(&ctrl->binds, &bind_bkt, bind, type);
|
bool bind_existed = find_or_set(&ctrl->binds, &bind_bkt, bind, type);
|
||||||
assert(bind_bkt != nullptr);
|
assert(bind_bkt != nullptr);
|
||||||
|
|
||||||
|
@ -235,9 +254,9 @@ bool CtrlMap(Ctrl *ctrl, u16f code, u16f bind, u8f type)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Axis *CtrlGet(Ctrl *ctrl, u16f code, u8f type)
|
struct Axis *CtrlGet(struct Ctrl *ctrl, u16f code, u8f type)
|
||||||
{
|
{
|
||||||
struct 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)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -267,13 +286,10 @@ void update_joystick(struct Axis *axis, struct CtrlRecord *record)
|
||||||
axis->last_pressed = record->timestamp;
|
axis->last_pressed = record->timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CtrlPoll(Ctrl *ctrl, struct RecordBuffer *buf)
|
bool CtrlPoll(struct Ctrl *ctrl, struct RecordBuffer *rec_buf)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&buf->mutex);
|
for (size_t i = 0; i < rec_buf->count; i++) {
|
||||||
pthread_mutex_lock(&ctrl->mutex);
|
struct CtrlRecord *rec = &rec_buf->records[i];
|
||||||
|
|
||||||
for (size_t i = 0; i < buf->count; i++) {
|
|
||||||
struct CtrlRecord *rec = &buf->records[i];
|
|
||||||
|
|
||||||
struct Axis *axis = find_axis(&ctrl->binds, rec->id, rec->type);
|
struct Axis *axis = find_axis(&ctrl->binds, rec->id, rec->type);
|
||||||
if (axis == nullptr)
|
if (axis == nullptr)
|
||||||
|
@ -294,8 +310,6 @@ bool CtrlPoll(Ctrl *ctrl, struct RecordBuffer *buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buf->count = 0;
|
rec_buf->count = 0;
|
||||||
pthread_mutex_unlock(&buf->mutex);
|
|
||||||
pthread_mutex_unlock(&ctrl->mutex);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
|
@ -84,32 +84,31 @@ enum CtrlCode {
|
||||||
|
|
||||||
typedef u32 hashtype;
|
typedef u32 hashtype;
|
||||||
|
|
||||||
struct bkt {
|
struct ctrl_bkt {
|
||||||
hashtype hash;
|
hashtype hash;
|
||||||
u16 value;
|
u16 value;
|
||||||
u8 type;
|
u8 type;
|
||||||
struct Axis *axis;
|
struct Axis *axis;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dict {
|
struct ctrl_dict {
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
size_t filled;
|
size_t filled;
|
||||||
struct bkt *bkts;
|
struct ctrl_bkt *bkts;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ctrl {
|
struct Ctrl {
|
||||||
struct dict codes;
|
struct ctrl_dict codes;
|
||||||
struct dict binds;
|
struct ctrl_dict binds;
|
||||||
|
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
};
|
};
|
||||||
typedef struct Ctrl Ctrl;
|
|
||||||
|
|
||||||
Ctrl NewCtrl(struct dict *codes, struct dict *binds, struct Axis *axes);
|
struct Ctrl NewCtrl(struct ctrl_dict *codes, struct ctrl_dict *binds, struct Axis *axes);
|
||||||
|
|
||||||
bool CtrlMap(Ctrl *ctrl, u16f code, u16f bind, u8f type);
|
bool CtrlMap(struct Ctrl *ctrl, u16f code, u16f bind, u8f type);
|
||||||
|
|
||||||
struct Axis *CtrlGet(Ctrl *ctrl, u16f code, u8f type);
|
struct Axis *CtrlGet(struct Ctrl *ctrl, u16f code, u8f type);
|
||||||
|
|
||||||
bool CtrlPoll(Ctrl *ctrl, struct RecordBuffer *buf);
|
bool CtrlPoll(struct Ctrl *ctrl, struct RecordBuffer *buf);
|
|
@ -1,16 +0,0 @@
|
||||||
#include <iso646.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "fumotris.h"
|
|
||||||
|
|
||||||
struct Window {
|
|
||||||
size_t x;
|
|
||||||
size_t y;
|
|
||||||
|
|
||||||
u16f fps;
|
|
||||||
};
|
|
|
@ -1,17 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <iso646.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "fumotris.h"
|
|
||||||
|
|
||||||
struct Window {
|
|
||||||
size_t x;
|
|
||||||
size_t y;
|
|
||||||
|
|
||||||
u16f fps;
|
|
||||||
};
|
|
|
@ -3,23 +3,23 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "instance.h"
|
|
||||||
#include "winhandler.h"
|
#include "winhandler.h"
|
||||||
|
#include "term.h"
|
||||||
|
|
||||||
bool WindowsInit(struct Window *window)
|
bool WindowsInit(struct Terminal *term)
|
||||||
{
|
{
|
||||||
if (!WinInitInputHandle())
|
if (!WinInitHandles())
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!WinInitTimer())
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!WinInitConsole())
|
if (!WinInitConsole())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (!WinGetRefreshRate(&term->refresh_rate))
|
||||||
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -31,5 +31,10 @@ bool WindowsBlockInput(struct RecordBuffer *buf)
|
||||||
|
|
||||||
bool WindowsWait(double seconds)
|
bool WindowsWait(double seconds)
|
||||||
{
|
{
|
||||||
return WinWait(seconds);
|
struct timespec duration = {
|
||||||
|
.tv_sec = seconds,
|
||||||
|
.tv_nsec = fmod(seconds, 1) * 1e9
|
||||||
|
};
|
||||||
|
|
||||||
|
return WinWait(duration);
|
||||||
}
|
}
|
|
@ -10,7 +10,7 @@
|
||||||
#include "fumotris.h"
|
#include "fumotris.h"
|
||||||
#include "gametime.h"
|
#include "gametime.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "instance.h"
|
#include "term.h"
|
||||||
|
|
||||||
struct Windows {
|
struct Windows {
|
||||||
HANDLE input_handle;
|
HANDLE input_handle;
|
||||||
|
@ -54,7 +54,7 @@ bool WinInitConsole()
|
||||||
return SetConsoleMode(windows.input_handle, mode);
|
return SetConsoleMode(windows.input_handle, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WinGetRefreshRate(struct Window *window)
|
bool WinGetRefreshRate(u32f *out)
|
||||||
{
|
{
|
||||||
LPDEVMODE mode;
|
LPDEVMODE mode;
|
||||||
if(!EnumDisplaySettingsA(
|
if(!EnumDisplaySettingsA(
|
||||||
|
@ -64,7 +64,7 @@ bool WinGetRefreshRate(struct Window *window)
|
||||||
))
|
))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
window->fps = mode->dmDisplayFrequency;
|
*out = mode->dmDisplayFrequency;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,19 +147,17 @@ bool WinBlockInput(struct RecordBuffer *buf)
|
||||||
if (!include)
|
if (!include)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
buf->records[buf->count] = record;
|
buf->records[buf->count++] = record;
|
||||||
buf->count += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&buf->mutex);
|
pthread_mutex_unlock(&buf->mutex);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WinWait(struct timespec duration)
|
bool WinWait(struct timespec relative)
|
||||||
{
|
{
|
||||||
LARGE_INTEGER duration;
|
LARGE_INTEGER duration;
|
||||||
duration.QuadPart = (u64)(-10000000.0 * seconds);
|
duration.QuadPart = -10000000 * relative.tv_sec - relative.tv_nsec / 100;
|
||||||
|
|
||||||
|
|
||||||
if (!SetWaitableTimer(
|
if (!SetWaitableTimer(
|
||||||
windows.draw_handles[0], // Timer
|
windows.draw_handles[0], // Timer
|
||||||
|
|
|
@ -11,6 +11,8 @@ bool WinInitHandles();
|
||||||
|
|
||||||
bool WinInitConsole();
|
bool WinInitConsole();
|
||||||
|
|
||||||
|
bool WinGetRefreshRate(u32f *out);
|
||||||
|
|
||||||
bool WinBlockInput(struct RecordBuffer *buf);
|
bool WinBlockInput(struct RecordBuffer *buf);
|
||||||
|
|
||||||
bool WinWait(double seconds);
|
bool WinWait(struct timespec relative);
|
103
source/main.c
103
source/main.c
|
@ -10,11 +10,22 @@
|
||||||
#include "fumotris.h"
|
#include "fumotris.h"
|
||||||
#include "term.h"
|
#include "term.h"
|
||||||
#include "tetr.h"
|
#include "tetr.h"
|
||||||
|
#include "event.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include "win.h"
|
#include "win.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct Instance {
|
||||||
|
struct Terminal term;
|
||||||
|
struct Ctrl ctrl;
|
||||||
|
struct RecordBuffer rec_buf;
|
||||||
|
|
||||||
|
struct Delegate on_start;
|
||||||
|
struct Delegate on_draw;
|
||||||
|
struct Delegate on_update;
|
||||||
|
};
|
||||||
|
|
||||||
const u8 I[16] = {
|
const u8 I[16] = {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
|
@ -79,39 +90,61 @@ const struct CtrlBind ctrl_binds[12] = {
|
||||||
{ MOUSE, 0, JOYSTICK }
|
{ MOUSE, 0, JOYSTICK }
|
||||||
};
|
};
|
||||||
|
|
||||||
void Update(Ctrl *ctrl)
|
void Draw(struct Terminal *term)
|
||||||
{
|
{
|
||||||
|
pthread_mutex_lock(&term->mutex);
|
||||||
|
|
||||||
|
struct TChar4 term_blks[term->area];
|
||||||
|
|
||||||
|
pthread_cond_signal(&term->is_initialized);
|
||||||
|
pthread_mutex_unlock(&term->mutex);
|
||||||
|
|
||||||
|
size_t buf_size = TermBufSize(term);
|
||||||
|
char buf[buf_size];
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
pthread_mutex_lock(&term->mutex);
|
||||||
|
pthread_cond_wait(&term->draw_ready, &term->mutex);
|
||||||
|
|
||||||
|
TermOut(term, buf, buf_size);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&term->mutex);
|
||||||
|
|
||||||
|
puts(buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Loop(Ctrl *ctrl, struct RecordBuffer *in_buf)
|
void Update(struct Terminal *term, struct Ctrl *ctrl, struct RecordBuffer *rec_buf)
|
||||||
{
|
{
|
||||||
struct CharBlk4 term_blks[20 * 20];
|
pthread_mutex_lock(&term->mutex);
|
||||||
struct TermBuf term = NewTermBuf(term_blks, 20, 20);
|
pthread_cond_wait(&term->is_initialized, &term->mutex);
|
||||||
|
pthread_mutex_unlock(&term->mutex);
|
||||||
|
|
||||||
size_t out_max = TermMaxChars(&term);
|
while (true) {
|
||||||
char out[out_max];
|
// Input
|
||||||
|
pthread_mutex_lock(&rec_buf->mutex);
|
||||||
|
CtrlPoll(ctrl, rec_buf);
|
||||||
|
pthread_mutex_unlock(&rec_buf->mutex);
|
||||||
|
|
||||||
u8 board_blks[10 * 20];
|
// Game logic
|
||||||
struct TetrMap board = NewTetrMap(board_blks, 10, 20);
|
|
||||||
|
|
||||||
u8 falling_blks[4 * 4];
|
// Draw
|
||||||
struct TetrMap falling = NewTetrMap(falling_blks, 4, 4);
|
pthread_mutex_lock(&term->mutex);
|
||||||
memcpy(falling_blks, I, falling.area);
|
pthread_cond_signal(&term->draw_ready);
|
||||||
|
pthread_mutex_unlock(&term->mutex);
|
||||||
for (int i = 0; i < 7779997; i++) {
|
|
||||||
CtrlPoll(ctrl, in_buf);
|
|
||||||
|
|
||||||
TetrMapToTermBuf(&board, &term);
|
|
||||||
TetrMapToTermBuf(&falling, &term);
|
|
||||||
|
|
||||||
TermBufToChars(&term, out, out_max);
|
|
||||||
puts(out);
|
|
||||||
|
|
||||||
WindowsWait(1.0/30);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Loop(struct Ctrl *ctrl, struct RecordBuffer *rec_buf)
|
||||||
|
{
|
||||||
|
pthread_t draw_thread;
|
||||||
|
pthread_create(&draw_thread, nullptr, Draw, &term);
|
||||||
|
|
||||||
|
pthread_t update_thread;
|
||||||
|
pthread_create(&update_thread, nullptr, Update, &term);
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -119,33 +152,43 @@ int main()
|
||||||
exit(1);
|
exit(1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct bkt code_bkts[code_count];
|
struct ctrl_bkt code_bkts[code_count];
|
||||||
struct dict codes = {
|
struct ctrl_dict codes = {
|
||||||
.capacity = code_count,
|
.capacity = code_count,
|
||||||
.filled = 0,
|
.filled = 0,
|
||||||
.bkts = code_bkts
|
.bkts = code_bkts
|
||||||
};
|
};
|
||||||
struct bkt bind_bkts[code_count];
|
struct ctrl_bkt bind_bkts[code_count];
|
||||||
struct dict binds = {
|
struct ctrl_dict binds = {
|
||||||
.capacity = code_count,
|
.capacity = code_count,
|
||||||
.filled = 0,
|
.filled = 0,
|
||||||
.bkts = bind_bkts
|
.bkts = bind_bkts
|
||||||
};
|
};
|
||||||
struct Axis axes[code_count];
|
struct Axis axes[code_count];
|
||||||
Ctrl ctrl = NewCtrl(&codes, &binds, axes);
|
struct Ctrl ctrl = NewCtrl(&codes, &binds, axes);
|
||||||
|
|
||||||
for (size_t i = 0; i < code_count; i++) {
|
for (size_t i = 0; i < code_count; i++) {
|
||||||
const struct CtrlBind *bind = &ctrl_binds[i];
|
const struct CtrlBind *bind = &ctrl_binds[i];
|
||||||
CtrlMap(&ctrl, bind->code, bind->bind, bind->type);
|
CtrlMap(&ctrl, bind->code, bind->bind, bind->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RecordBuffer in_buf = {
|
struct RecordBuffer rec_buf = {
|
||||||
.count = 0,
|
.count = 0,
|
||||||
.mutex = PTHREAD_MUTEX_INITIALIZER
|
.mutex = PTHREAD_MUTEX_INITIALIZER
|
||||||
};
|
};
|
||||||
|
|
||||||
StartInput(&ctrl, &in_buf);
|
struct Instance game = {
|
||||||
Loop(&ctrl, &in_buf);
|
.term = NewTerm(nullptr, 20, 20),
|
||||||
|
.ctrl = NewCtrl(),
|
||||||
|
|
||||||
|
.on_start = NewDelegate(16),
|
||||||
|
.on_draw = NewDelegate(16),
|
||||||
|
.on_update = NewDelegate(16)
|
||||||
|
};
|
||||||
|
|
||||||
|
StartInput(&ctrl, &rec_buf);
|
||||||
|
Loop(&ctrl, &rec_buf);
|
||||||
|
|
||||||
JoinInput(&ctrl);
|
JoinInput(&ctrl);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -5,33 +5,47 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
#include "fumotris.h"
|
#include "fumotris.h"
|
||||||
|
|
||||||
struct CharBlk4 {
|
struct TChar4 {
|
||||||
char ch;
|
char ch;
|
||||||
u8 bg : 4;
|
u8 bg : 4;
|
||||||
u8 fg : 4;
|
u8 fg : 4;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TermBuf {
|
struct Terminal {
|
||||||
size_t wid;
|
size_t wid;
|
||||||
size_t hgt;
|
size_t hgt;
|
||||||
size_t area;
|
size_t area;
|
||||||
struct CharBlk4 *blks;
|
u16f refresh_rate;
|
||||||
|
struct TChar4 *blks;
|
||||||
|
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
pthread_cond_t is_initialized;
|
||||||
|
pthread_cond_t draw_ready;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TermBuf NewTermBuf(struct CharBlk4 *blks, size_t wid, size_t hgt)
|
struct Terminal NewTerm(struct TChar4 *blks, size_t wid, size_t hgt)
|
||||||
{
|
{
|
||||||
size_t area = wid * hgt;
|
size_t area = wid * hgt;
|
||||||
memset(blks, 0, sizeof(struct CharBlk4) * area);
|
memset(blks, 0, sizeof(struct TChar4) * area);
|
||||||
|
|
||||||
return (struct TermBuf) {
|
return (struct Terminal) {
|
||||||
wid, hgt, area, blks
|
.wid = wid,
|
||||||
|
.hgt = hgt,
|
||||||
|
.area = area,
|
||||||
|
.refresh_rate = 60,
|
||||||
|
.blks = blks,
|
||||||
|
|
||||||
|
.mutex = PTHREAD_MUTEX_INITIALIZER,
|
||||||
|
.is_initialized = PTHREAD_COND_INITIALIZER,
|
||||||
|
.draw_ready = PTHREAD_COND_INITIALIZER
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t TermMaxChars(struct TermBuf *term)
|
size_t TermBufSize(struct Terminal *term)
|
||||||
{
|
{
|
||||||
static const size_t max_color_str_len = 10;
|
static const size_t max_color_str_len = 10;
|
||||||
static const size_t reset_str_len = 7;
|
static const size_t reset_str_len = 7;
|
||||||
|
@ -52,7 +66,7 @@ size_t printcol4(char *buf, size_t at, size_t max, u8f col, char ch)
|
||||||
return snprintf(buf + at, max - at, "\x1b[%um%c", col, ch);
|
return snprintf(buf + at, max - at, "\x1b[%um%c", col, ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t printblk4(char *buf, size_t at, size_t max, struct CharBlk4 *blk)
|
size_t printblk4(char *buf, size_t at, size_t max, struct TChar4 *blk)
|
||||||
{
|
{
|
||||||
u8f bg;
|
u8f bg;
|
||||||
if (blk->bg < 8)
|
if (blk->bg < 8)
|
||||||
|
@ -69,17 +83,17 @@ size_t printblk4(char *buf, size_t at, size_t max, struct CharBlk4 *blk)
|
||||||
return snprintf(buf + at, max - at, "\x1b[%u;%um%c", bg, fg, blk->ch);
|
return snprintf(buf + at, max - at, "\x1b[%u;%um%c", bg, fg, blk->ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t TermBufToChars(struct TermBuf *term, char *buf, size_t max_chars)
|
size_t TermOut(struct Terminal *term, char *buf, size_t n)
|
||||||
{
|
{
|
||||||
u8f last_bg = 0;
|
u8f last_bg = 0;
|
||||||
u8f last_fg = 0;
|
u8f last_fg = 0;
|
||||||
|
|
||||||
size_t filled = snprintf(buf, max_chars, "\x1b[H\x1b[0m");
|
size_t filled = snprintf(buf, n, "\x1b[H\x1b[0m");
|
||||||
|
|
||||||
for(size_t y = 0; y < term->hgt; y++) {
|
for(size_t y = 0; y < term->hgt; y++) {
|
||||||
for(size_t x = 0; x < term->wid; x++) {
|
for(size_t x = 0; x < term->wid; x++) {
|
||||||
size_t i = y * term->wid + x;
|
size_t i = y * term->wid + x;
|
||||||
struct CharBlk4 *blk = &term->blks[i];
|
struct TChar4 *blk = &term->blks[i];
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
if (blk->ch == 0)
|
if (blk->ch == 0)
|
||||||
|
@ -89,13 +103,13 @@ size_t TermBufToChars(struct TermBuf *term, char *buf, size_t max_chars)
|
||||||
if (blk->bg != 0 and blk->bg != last_bg) {
|
if (blk->bg != 0 and blk->bg != last_bg) {
|
||||||
last_bg = blk->bg;
|
last_bg = blk->bg;
|
||||||
if (blk->fg != 0 and blk->fg != last_fg) {
|
if (blk->fg != 0 and blk->fg != last_fg) {
|
||||||
filled += printblk4(buf, filled, max_chars, blk);
|
filled += printblk4(buf, filled, n, blk);
|
||||||
last_fg = blk->fg;
|
last_fg = blk->fg;
|
||||||
} else {
|
} else {
|
||||||
filled += printcol4(buf, filled, max_chars, blk->bg, blk->ch);
|
filled += printcol4(buf, filled, n, blk->bg, blk->ch);
|
||||||
}
|
}
|
||||||
} else if (blk->fg != 0 and blk->fg != last_fg) {
|
} else if (blk->fg != 0 and blk->fg != last_fg) {
|
||||||
filled += printcol4(buf, filled, max_chars, blk->fg, blk->ch);
|
filled += printcol4(buf, filled, n, blk->fg, blk->ch);
|
||||||
last_fg = blk->fg;
|
last_fg = blk->fg;
|
||||||
} else {
|
} else {
|
||||||
buf[filled] = blk->ch;
|
buf[filled] = blk->ch;
|
||||||
|
|
|
@ -6,24 +6,30 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
#include "fumotris.h"
|
#include "fumotris.h"
|
||||||
|
|
||||||
struct CharBlk4 {
|
struct TChar4 {
|
||||||
char ch;
|
char ch;
|
||||||
u8 bg : 4;
|
u8 bg : 4;
|
||||||
u8 fg : 4;
|
u8 fg : 4;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TermBuf {
|
struct Terminal {
|
||||||
size_t wid;
|
size_t wid;
|
||||||
size_t hgt;
|
size_t hgt;
|
||||||
size_t area;
|
size_t area;
|
||||||
struct CharBlk4 *blks;
|
u16f refresh_rate;
|
||||||
|
struct TChar4 *blks;
|
||||||
|
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
pthread_cond_t is_initialized;
|
||||||
|
pthread_cond_t draw_ready;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TermBuf NewTermBuf(struct CharBlk4 *blks, size_t wid, size_t hgt);
|
struct Terminal NewTerm(struct TChar4 *blks, size_t wid, size_t hgt);
|
||||||
|
|
||||||
size_t TermMaxChars(struct TermBuf *term);
|
size_t TermBufSize(struct Terminal *term);
|
||||||
|
|
||||||
size_t TermBufToChars(struct TermBuf *term, char *buf, size_t max_chars);
|
size_t TermOut(struct Terminal *term, char *buf, size_t max_chars);
|
Loading…
Reference in a new issue