sdfkjfsd
aaaaa
This commit is contained in:
parent
1d5c402f19
commit
ba654dbcb7
|
@ -37,7 +37,7 @@ void Subscribe(struct Delegate *d, void (*event)(void *args))
|
||||||
d->len += 1;
|
d->len += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Call(struct Delegate *d, void *args)
|
void Invoke(struct Delegate *d, void *args)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < d->len; i++) {
|
for (size_t i = 0; i < d->len; i++) {
|
||||||
d->events[i](args);
|
d->events[i](args);
|
||||||
|
|
|
@ -17,4 +17,4 @@ struct Delegate NewDelegate(size_t capacity);
|
||||||
|
|
||||||
void Subscribe(struct Delegate *d, void (*event)(void *args));
|
void Subscribe(struct Delegate *d, void (*event)(void *args));
|
||||||
|
|
||||||
void Call(struct Delegate *d, void *args);
|
void Invoke(struct Delegate *d, void *args);
|
|
@ -42,8 +42,8 @@ void TetrMapToTermBuf(struct TetrMap *map, struct Terminal *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 TChar4 *a = &term->blks[buf_i];
|
struct TChar4 *a = &term->bufs[buf_i];
|
||||||
struct TChar4 *b = &term->blks[buf_i + 1];
|
struct TChar4 *b = &term->bufs[buf_i + 1];
|
||||||
|
|
||||||
if (map->blks[map_i] == 0) {
|
if (map->blks[map_i] == 0) {
|
||||||
a->ch = '(';
|
a->ch = '(';
|
||||||
|
|
|
@ -146,8 +146,6 @@ void CtrlSet(
|
||||||
ctrl->binds.capacity = b_len;
|
ctrl->binds.capacity = b_len;
|
||||||
ctrl->binds.bkts = bind_bkts;
|
ctrl->binds.bkts = bind_bkts;
|
||||||
memset(bind_bkts, 0, sizeof(struct ctrl_bkt) * b_len);
|
memset(bind_bkts, 0, sizeof(struct ctrl_bkt) * b_len);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ctrl_bkt *get_bkt(struct ctrl_dict *dict, size_t i)
|
struct ctrl_bkt *get_bkt(struct ctrl_dict *dict, size_t i)
|
||||||
|
|
|
@ -90,19 +90,60 @@ const struct CtrlBind ctrl_binds[12] = {
|
||||||
{ MOUSE, 0, JOYSTICK }
|
{ MOUSE, 0, JOYSTICK }
|
||||||
};
|
};
|
||||||
|
|
||||||
void Draw(struct Instance *game)
|
bool DrawUpdate(struct Terminal *term, struct Instance *game, char *buf)
|
||||||
{
|
{
|
||||||
while (true) {
|
bool is_update;
|
||||||
Call(&game->on_draw, game);
|
|
||||||
|
TermLock(term);
|
||||||
|
{
|
||||||
|
is_update = TermWaitUpdate(term);
|
||||||
|
if(is_update) {
|
||||||
|
Invoke(&game->on_draw, game);
|
||||||
|
TermOut(term, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
TermUnlock(term);
|
||||||
|
|
||||||
|
return is_update;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Draw(struct Terminal *term, struct Instance *game)
|
||||||
|
{
|
||||||
|
struct TChar4 buf0[term->area];
|
||||||
|
struct TChar4 buf1[term->area];
|
||||||
|
|
||||||
|
TermLock(term);
|
||||||
|
{
|
||||||
|
TermSetBufs(term, buf0, buf1);
|
||||||
|
}
|
||||||
|
TermUnlock(term);
|
||||||
|
TermSignalSafe(term);
|
||||||
|
|
||||||
|
char buf[term->buf_size];
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (!DrawUpdate(term, game, buf))
|
||||||
|
break;
|
||||||
|
|
||||||
|
puts(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void Update(struct Instance *game)
|
void Update(struct Instance *game)
|
||||||
{
|
{
|
||||||
|
WaitSafeTerm(&game->term);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
Call(&game->on_update, game);
|
// Input
|
||||||
|
CtrlPoll(&game->ctrl, &game->rec_buf);
|
||||||
|
|
||||||
|
// Game logic
|
||||||
|
Invoke(&game->on_update, game);
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
UpdateTerm(&game->term);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,41 +18,138 @@ struct TChar4 {
|
||||||
struct Terminal {
|
struct Terminal {
|
||||||
size_t wid;
|
size_t wid;
|
||||||
size_t hgt;
|
size_t hgt;
|
||||||
size_t area;
|
|
||||||
u16f refresh_rate;
|
u16f refresh_rate;
|
||||||
struct TChar4 *blks;
|
|
||||||
|
size_t area;
|
||||||
|
size_t buf_size;
|
||||||
|
|
||||||
|
struct TChar4 *bufs[2];
|
||||||
|
u8f switch_read;
|
||||||
|
u8f switch_write;
|
||||||
|
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
pthread_cond_t is_initialized;
|
pthread_cond_t update;
|
||||||
pthread_cond_t draw_ready;
|
|
||||||
|
struct {
|
||||||
|
u8f is_writing : 1;
|
||||||
|
u8f resize : 1;
|
||||||
|
} flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Terminal NewTerm(size_t wid, size_t hgt)
|
size_t buf_size(size_t area, size_t hgt)
|
||||||
{
|
|
||||||
return (struct Terminal) {
|
|
||||||
.wid = wid,
|
|
||||||
.hgt = hgt,
|
|
||||||
.area = wid * hgt,
|
|
||||||
.refresh_rate = 60,
|
|
||||||
.blks = nullptr,
|
|
||||||
|
|
||||||
.mutex = PTHREAD_MUTEX_INITIALIZER,
|
|
||||||
.is_initialized = PTHREAD_COND_INITIALIZER,
|
|
||||||
.draw_ready = PTHREAD_COND_INITIALIZER
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
return reset_str_len
|
return reset_str_len
|
||||||
+ (max_color_str_len + 1) * term->area
|
+ (max_color_str_len + 1) * area
|
||||||
+ (term->hgt - 1)
|
+ (hgt - 1)
|
||||||
+ 1;
|
+ 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Terminal NewTerm(size_t wid, size_t hgt)
|
||||||
|
{
|
||||||
|
size_t area = wid * hgt;
|
||||||
|
|
||||||
|
return (struct Terminal) {
|
||||||
|
.wid = wid,
|
||||||
|
.hgt = hgt,
|
||||||
|
.refresh_rate = 60,
|
||||||
|
|
||||||
|
.area = area,
|
||||||
|
.buf_size = 0,
|
||||||
|
|
||||||
|
.bufs = nullptr,
|
||||||
|
.switch_read = 0,
|
||||||
|
.switch_write = 0,
|
||||||
|
|
||||||
|
.mutex = PTHREAD_MUTEX_INITIALIZER,
|
||||||
|
.update = PTHREAD_COND_INITIALIZER,
|
||||||
|
|
||||||
|
.flags.is_writing = true,
|
||||||
|
.flags.resize = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void TermSetBufs(struct Terminal *term, struct TChar4 *buf0, struct TChar4 *buf1)
|
||||||
|
{
|
||||||
|
term->buf_size = buf_size(term->area, term->hgt);
|
||||||
|
term->bufs[0] = buf0;
|
||||||
|
term->bufs[1] = buf1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TermResize(struct Terminal *term, size_t wid, size_t hgt)
|
||||||
|
{
|
||||||
|
size_t area = wid * hgt;
|
||||||
|
size_t buf_size = term_buf_size(area, hgt);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&term->mutex);
|
||||||
|
{
|
||||||
|
term->wid = wid;
|
||||||
|
term->hgt = hgt;
|
||||||
|
|
||||||
|
term->area = area;
|
||||||
|
term->buf_size = buf_size;
|
||||||
|
|
||||||
|
term->flags.resize = true;
|
||||||
|
|
||||||
|
pthread_cond_signal(&term->update);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&term->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateTerm(struct Terminal *term)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&term->mutex);
|
||||||
|
{
|
||||||
|
term->switch_read = term->switch_write;
|
||||||
|
term->switch_write = (term->switch_write + 1) % 2;
|
||||||
|
|
||||||
|
term->flags.is_writing = false;
|
||||||
|
|
||||||
|
pthread_cond_signal(&term->update);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&term->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TermWaitUpdate(struct Terminal *term)
|
||||||
|
{
|
||||||
|
while (term->flags.is_writing) {
|
||||||
|
pthread_cond_wait(&term->update, &term->mutex);
|
||||||
|
|
||||||
|
if (term->flags.resize) {
|
||||||
|
term->flags.resize = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TermSignalSafe(struct Terminal *term)
|
||||||
|
{
|
||||||
|
pthread_cond_signal(&term->update);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaitSafeTerm(struct Terminal *term)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&term->mutex);
|
||||||
|
while (term->bufs == nullptr) {
|
||||||
|
pthread_cond_wait(&term->update, &term->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&term->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TermLock(struct Terminal *term)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&term->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TermUnlock(struct Terminal *term)
|
||||||
|
{
|
||||||
|
pthread_mutex_unlock(&term->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
size_t printcol4(char *buf, size_t at, size_t max, u8f col, char ch)
|
size_t printcol4(char *buf, size_t at, size_t max, u8f col, char ch)
|
||||||
{
|
{
|
||||||
if (col < 8)
|
if (col < 8)
|
||||||
|
@ -80,17 +177,17 @@ size_t printblk4(char *buf, size_t at, size_t max, struct TChar4 *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 TermOut(struct Terminal *term, char *buf, size_t n)
|
size_t TermOut(struct Terminal *term, char *buf)
|
||||||
{
|
{
|
||||||
u8f last_bg = 0;
|
u8f last_bg = 0;
|
||||||
u8f last_fg = 0;
|
u8f last_fg = 0;
|
||||||
|
|
||||||
size_t filled = snprintf(buf, n, "\x1b[H\x1b[0m");
|
size_t filled = snprintf(buf, term->buf_size, "\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 TChar4 *blk = &term->blks[i];
|
struct TChar4 *blk = &term->bufs[i];
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
if (blk->ch == 0)
|
if (blk->ch == 0)
|
||||||
|
@ -100,13 +197,13 @@ size_t TermOut(struct Terminal *term, char *buf, size_t n)
|
||||||
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, n, blk);
|
filled += printblk4(buf, filled, term->buf_size, blk);
|
||||||
last_fg = blk->fg;
|
last_fg = blk->fg;
|
||||||
} else {
|
} else {
|
||||||
filled += printcol4(buf, filled, n, blk->bg, blk->ch);
|
filled += printcol4(buf, filled, term->buf_size, 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, n, blk->fg, blk->ch);
|
filled += printcol4(buf, filled, term->buf_size, blk->fg, blk->ch);
|
||||||
last_fg = blk->fg;
|
last_fg = blk->fg;
|
||||||
} else {
|
} else {
|
||||||
buf[filled] = blk->ch;
|
buf[filled] = blk->ch;
|
||||||
|
|
|
@ -21,15 +21,34 @@ struct Terminal {
|
||||||
size_t hgt;
|
size_t hgt;
|
||||||
size_t area;
|
size_t area;
|
||||||
u16f refresh_rate;
|
u16f refresh_rate;
|
||||||
struct TChar4 *blks;
|
|
||||||
|
struct TChar4 *bufs[2];
|
||||||
|
size_t buf_size;
|
||||||
|
u8f switch_read;
|
||||||
|
u8f switch_write;
|
||||||
|
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
pthread_cond_t is_initialized;
|
pthread_cond_t update;
|
||||||
pthread_cond_t draw_ready;
|
|
||||||
|
struct {
|
||||||
|
u8f is_writing : 1;
|
||||||
|
u8f resize : 1;
|
||||||
|
} flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Terminal NewTerm(size_t wid, size_t hgt);
|
struct Terminal NewTerm(size_t wid, size_t hgt);
|
||||||
|
|
||||||
size_t TermBufSize(struct Terminal *term);
|
void TermSetBufs(struct Terminal *term, struct TChar4 *buf0, struct TChar4 *buf1);
|
||||||
|
|
||||||
size_t TermOut(struct Terminal *term, char *buf, size_t max_chars);
|
void TermResize(struct Terminal *term, size_t wid, size_t hgt);
|
||||||
|
|
||||||
|
void UpdateTerm(struct Terminal *term);
|
||||||
|
bool TermWaitUpdate(struct Terminal *term);
|
||||||
|
|
||||||
|
void TermSignalSafe(struct Terminal *term);
|
||||||
|
void WaitSafeTerm(struct Terminal *term);
|
||||||
|
|
||||||
|
void TermLock(struct Terminal *term);
|
||||||
|
void TermUnlock(struct Terminal *term);
|
||||||
|
|
||||||
|
size_t TermOut(struct Terminal *term, char *buf);
|
Loading…
Reference in a new issue