fas
This commit is contained in:
Julia 2024-04-09 02:00:48 -05:00
parent 370ef5e0c5
commit c941f8b7fb
15 changed files with 286 additions and 308 deletions

BIN
hi.exe Normal file

Binary file not shown.

View file

@ -12,7 +12,7 @@ struct Delegate {
void (**events)(void *args); void (**events)(void *args);
}; };
inline size_t delegate_size(size_t capacity) size_t delegate_size(size_t capacity)
{ {
return sizeof(void(*)(void *)) * capacity; return sizeof(void(*)(void *)) * capacity;
} }

View file

@ -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->bufs[buf_i]; struct TChar4 *a = &term->blks[buf_i];
struct TChar4 *b = &term->bufs[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 = '(';

View file

@ -1,4 +1,3 @@
#include <assert.h>
#include <iso646.h> #include <iso646.h>
#include <pthread.h> #include <pthread.h>
#include <stdbool.h> #include <stdbool.h>
@ -68,7 +67,7 @@ struct Axis {
typedef u32 hashtype; typedef u32 hashtype;
hashtype Hash(void *item, size_t size) hashtype Hash(void *item, size_t size)
{ {
u8* data = (u8*)item; u8 *data = (u8 *)item;
u32 h = 98317; u32 h = 98317;
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
@ -80,7 +79,7 @@ hashtype Hash(void *item, size_t size)
return h; return h;
} }
hashtype hash_ident(u16f value, u8f type) hashtype hash_id(u16f value, u8f type)
{ {
struct id { struct id {
u16 id; u16 id;
@ -108,49 +107,51 @@ struct Ctrl {
struct ctrl_dict codes; struct ctrl_dict codes;
struct ctrl_dict binds; struct ctrl_dict binds;
struct RecordBuffer buf;
pthread_t thread; pthread_t thread;
pthread_mutex_t mutex;
}; };
struct Ctrl NewCtrl() bool NewCtrl(struct Ctrl *ctrl, size_t code_cap, size_t bind_cap)
{ {
struct Ctrl ctrl = (struct Ctrl) { struct ctrl_bkt *code_bkts = calloc(code_cap, sizeof(struct ctrl_bkt));
struct ctrl_bkt *bind_bkts = calloc(bind_cap, sizeof(struct ctrl_bkt));
struct Axis *axes = calloc(code_cap, sizeof(struct Axis));
if (code_bkts == nullptr or bind_bkts == nullptr or axes == nullptr)
return false;
for (size_t i = 0; i < code_cap; i++) {
code_bkts[i].axis = axes + i;
}
*ctrl = (struct Ctrl) {
.codes = (struct ctrl_dict) { .codes = (struct ctrl_dict) {
.capacity = 0, .capacity = code_cap,
.filled = 0, .filled = 0,
.bkts = nullptr .bkts = code_bkts,
}, },
.binds = (struct ctrl_dict) { .binds = (struct ctrl_dict) {
.capacity = 0, .capacity = bind_cap,
.filled = 0, .filled = 0,
.bkts = nullptr .bkts = bind_bkts,
}, },
.mutex = PTHREAD_MUTEX_INITIALIZER .buf = (struct RecordBuffer) {
.count = 0,
.mutex = PTHREAD_MUTEX_INITIALIZER,
},
}; };
return ctrl; return true;
} }
void CtrlSet( void FreeCtrl(struct Ctrl *ctrl)
struct Ctrl *ctrl, {
struct ctrl_bkt *code_bkts, free(ctrl->codes.bkts);
struct ctrl_bkt *bind_bkts, free(ctrl->binds.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) struct ctrl_bkt *get_bkt(struct ctrl_dict *dict, size_t i)
{ {
assert(i < dict->capacity);
return &dict->bkts[i]; return &dict->bkts[i];
} }
@ -161,18 +162,18 @@ void set_bkt(struct ctrl_bkt *bkt, hashtype hash, u16f value, u8f type)
bkt->type = type; bkt->type = type;
} }
size_t wrap(size_t x, size_t wrap) size_t wrap_index(size_t i, size_t max)
{ {
return x % (SIZE_MAX - wrap + 1); return i % (SIZE_MAX - max + 1);
} }
bool find_or_set(struct ctrl_dict *dict, struct ctrl_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_id(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(index - 1, dict->capacity)) {
struct ctrl_bkt *bkt = get_bkt(dict, i); struct ctrl_bkt *bkt = get_bkt(dict, i);
if (bkt->hash == 0) { if (bkt->hash == 0) {
@ -196,18 +197,18 @@ bool find_or_set(struct ctrl_dict *dict, struct ctrl_bkt **out, u16f value, u8f
struct ctrl_bkt *find(struct ctrl_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_id(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(index - 1, dict->capacity)) {
struct ctrl_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;
if (bkt->value == value and bkt->type == type) { if (bkt->value == value and bkt->type == type)
return bkt; return bkt;
}
next: next:
i = (i + 1) % dict->capacity; i = (i + 1) % dict->capacity;
}; };
@ -226,16 +227,16 @@ struct Axis *find_axis(struct ctrl_dict *dict, u16f value, u8f type)
bool CtrlMap(struct 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); if (ctrl->codes.filled >= ctrl->codes.capacity or ctrl->binds.filled >= ctrl->binds.capacity) {
assert(ctrl->binds.filled < ctrl->binds.capacity); printf("fatal error");
exit(1);
}
struct ctrl_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);
struct ctrl_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);
if(bind_existed and bind_bkt->axis == code_bkt->axis) if(bind_existed and bind_bkt->axis == code_bkt->axis)
return false; return false;
@ -276,10 +277,10 @@ void update_joystick(struct Axis *axis, struct Record *record)
axis->last_pressed = record->timestamp; axis->last_pressed = record->timestamp;
} }
bool CtrlPoll(struct Ctrl *ctrl, struct RecordBuffer *rec_buf) bool CtrlPoll(struct Ctrl *ctrl)
{ {
for (size_t i = 0; i < rec_buf->count; i++) { for (size_t i = 0; i < ctrl->buf.count; i++) {
struct Record *rec = &rec_buf->records[i]; struct Record *rec = &ctrl->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)
@ -300,6 +301,6 @@ bool CtrlPoll(struct Ctrl *ctrl, struct RecordBuffer *rec_buf)
} }
} }
rec_buf->count = 0; ctrl->buf.count = 0;
return true; return true;
} }

View file

@ -99,14 +99,16 @@ struct Ctrl {
struct ctrl_dict codes; struct ctrl_dict codes;
struct ctrl_dict binds; struct ctrl_dict binds;
struct RecordBuffer buf;
pthread_t thread; pthread_t thread;
pthread_mutex_t mutex;
}; };
struct Ctrl NewCtrl(); bool NewCtrl(struct Ctrl *ctrl, size_t code_cap, size_t bind_cap);
void FreeCtrl(struct Ctrl *ctrl);
bool CtrlMap(struct Ctrl *ctrl, u16f code, u16f bind, u8f type); bool CtrlMap(struct Ctrl *ctrl, u16f code, u16f bind, u8f type);
struct Axis *CtrlGet(struct Ctrl *ctrl, u16f code, u8f type); struct Axis *CtrlGet(struct Ctrl *ctrl, u16f code, u8f type);
bool CtrlPoll(struct Ctrl *ctrl, struct RecordBuffer *buf); bool CtrlPoll(struct Ctrl *ctrl);

View file

@ -14,13 +14,13 @@
void *block_input(void *args_ptr) void *block_input(void *args_ptr)
{ {
struct RecordBuffer *buf = args_ptr; struct RecordBuffer *rec_buf = args_ptr;
while (true) { while (true) {
bool success; bool success;
#ifdef _WIN32 #ifdef _WIN32
success = WindowsBlockInput(buf); success = WindowsBlockInput(rec_buf);
#endif #endif
if (!success) { if (!success) {
@ -32,9 +32,9 @@ void *block_input(void *args_ptr)
return nullptr; return nullptr;
} }
void StartInput(struct Ctrl *ctrl, struct RecordBuffer *buf) void StartInput(struct Ctrl *ctrl)
{ {
pthread_create(&ctrl->thread, nullptr, block_input, buf); pthread_create(&ctrl->thread, nullptr, block_input, &ctrl->buf);
} }
void JoinInput(struct Ctrl *ctrl) void JoinInput(struct Ctrl *ctrl)

View file

@ -8,6 +8,6 @@
#include "ctrl.h" #include "ctrl.h"
#include "fumotris.h" #include "fumotris.h"
void StartInput(Ctrl *ctrl, struct RecordBuffer *buf); void StartInput(struct Ctrl *ctrl);
void JoinInput(Ctrl *ctrl); void JoinInput(struct Ctrl *ctrl);

View file

@ -10,17 +10,22 @@
#include "winhandler.h" #include "winhandler.h"
#include "term.h" #include "term.h"
#include <windows.h>
bool WindowsInit(struct Terminal *term) bool WindowsInit(struct Terminal *term)
{ {
if (!WinInitHandles()) if (!WinInitHandles())
return false; return false;
printf("shid ");
if (!WinInitConsole()) if (!WinInitConsole()) {
printf("%u\n", GetLastError());
return false; return false;
}
printf("console");
if (!WinGetRefreshRate(&term->refresh_rate)) if (!WinGetRefreshRate(&term->refresh_rate))
return false; return false;
printf("???");
return true; return true;
} }

View file

@ -7,8 +7,9 @@
#include <stdlib.h> #include <stdlib.h>
#include "input.h" #include "input.h"
#include "term.h"
bool WindowsInit(); bool WindowsInit(struct Terminal *term);
bool WindowsBlockInput(struct RecordBuffer *buf); bool WindowsBlockInput(struct RecordBuffer *buf);

View file

@ -14,31 +14,22 @@
struct Windows { struct Windows {
HANDLE input_handle; HANDLE input_handle;
HANDLE draw_handles[2]; HANDLE timer;
}; };
static struct Windows windows; static struct Windows win;
bool WinInitHandles() bool WinInitHandles()
{ {
windows.input_handle = GetStdHandle(STD_INPUT_HANDLE); win.input_handle = GetStdHandle(STD_INPUT_HANDLE);
if (windows.input_handle == INVALID_HANDLE_VALUE) if (win.input_handle == INVALID_HANDLE_VALUE)
return false; return false;
windows.draw_handles[0] = CreateWaitableTimer( win.timer = CreateWaitableTimer(
NULL, // Timer attributes NULL, // Timer attributes
TRUE, // Manual reset TRUE, // Manual reset
NULL // Name NULL // Name
); );
if (!windows.draw_handles[0]) if (!win.timer)
return false;
windows.draw_handles[1] = CreateEvent(
NULL, // Event attributes
FALSE, // Manual reset
FALSE, // Initial state
NULL // Name
);
if (!windows.draw_handles[1])
return false; return false;
return true; return true;
@ -51,20 +42,23 @@ bool WinInitConsole()
| ENABLE_MOUSE_INPUT | ENABLE_MOUSE_INPUT
| ENABLE_WINDOW_INPUT | ENABLE_WINDOW_INPUT
| ENABLE_VIRTUAL_TERMINAL_PROCESSING; | ENABLE_VIRTUAL_TERMINAL_PROCESSING;
return SetConsoleMode(windows.input_handle, mode); return SetConsoleMode(win.input_handle, mode) != 0;
} }
bool WinGetRefreshRate(u32f *out) bool WinGetRefreshRate(u16f *out)
{ {
LPDEVMODE mode; DEVMODE mode;
mode.dmSize = sizeof(DEVMODE);
mode.dmDriverExtra = 0;
if(!EnumDisplaySettingsA( if(!EnumDisplaySettingsA(
NULL, // Device name (null for current) NULL, // Device name (null for current)
ENUM_CURRENT_SETTINGS, // Mode ENUM_CURRENT_SETTINGS, // Mode
&mode // Out &mode // Out
)) ))
return false; return false;
*out = mode->dmDisplayFrequency; *out = mode.dmDisplayFrequency;
return true; return true;
} }
@ -112,8 +106,8 @@ bool dispatch_record(struct Record *record, INPUT_RECORD win_record)
case MOUSE_EVENT: case MOUSE_EVENT:
return set_mouse_record(record, win_record.Event.MouseEvent); return set_mouse_record(record, win_record.Event.MouseEvent);
case WINDOW_BUFFER_SIZE_EVENT: case WINDOW_BUFFER_SIZE_EVENT:
set_window_record(record, win_record.Event.WindowBufferSizeEvent); // TODO: Handle window resizing
break; return false;
default: default:
record->type = ESCAPE; record->type = ESCAPE;
} }
@ -127,10 +121,10 @@ bool WinBlockInput(struct RecordBuffer *buf)
DWORD count; DWORD count;
if (!ReadConsoleInput( if (!ReadConsoleInput(
windows.input_handle, // Input handle win.input_handle, // Input handle
win_buf, // Record buffer win_buf, // Record buffer
win_size, // Record buffer length win_size, // Record buffer length
&count // Out number of records &count // Out number of records
)) ))
return false; return false;
@ -160,7 +154,7 @@ bool WinWait(struct timespec relative)
duration.QuadPart = -10000000 * relative.tv_sec - relative.tv_nsec / 100; duration.QuadPart = -10000000 * relative.tv_sec - relative.tv_nsec / 100;
if (!SetWaitableTimer( if (!SetWaitableTimer(
windows.draw_handles[0], // Timer win.timer, // Timer
&duration, // Duration &duration, // Duration
0, // Period 0, // Period
NULL, // Completion coroutine NULL, // Completion coroutine
@ -169,12 +163,7 @@ bool WinWait(struct timespec relative)
)) ))
return false; return false;
DWORD result = WaitForMultipleObjects( DWORD result = WaitForSingleObject(win.timer, INFINITE);
2, // Handle count
windows.draw_handles, // Handles
FALSE, // Wait for all
INFINITE // Timeout
);
if (result != WAIT_OBJECT_0) if (result != WAIT_OBJECT_0)
return false; return false;

View file

@ -11,7 +11,7 @@ bool WinInitHandles();
bool WinInitConsole(); bool WinInitConsole();
bool WinGetRefreshRate(u32f *out); bool WinGetRefreshRate(u16f *out);
bool WinBlockInput(struct RecordBuffer *buf); bool WinBlockInput(struct RecordBuffer *buf);

View file

@ -16,16 +16,6 @@
#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,
@ -68,6 +58,16 @@ const u8 L[9] = {
0, 0, 0 0, 0, 0
}; };
struct Instance {
struct Ctrl ctrl;
struct Delegate on_start;
struct Delegate on_update;
struct Delegate on_draw;
struct Terminal term;
};
struct CtrlBind { struct CtrlBind {
enum CtrlCode code; enum CtrlCode code;
u16 bind; u16 bind;
@ -90,117 +90,65 @@ const struct CtrlBind ctrl_binds[12] = {
{ MOUSE, 0, JOYSTICK } { MOUSE, 0, JOYSTICK }
}; };
bool DrawUpdate(struct Terminal *term, struct Instance *game, char *buf) void *Update(void *args)
{ {
bool is_update; struct Instance *game = args;
TermLock(term); struct TChar4 blks[game->term.area];
{ game->term.blks = blks;
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)
{
WaitSafeTerm(&game->term);
while (true) { while (true) {
// Input // Input
CtrlPoll(&game->ctrl, &game->rec_buf); CtrlPoll(&game->ctrl);
// Game logic // Game logic
Invoke(&game->on_update, game); Invoke(&game->on_update, game);
// Draw // Draw
UpdateTerm(&game->term); TermOut(&game->term);
puts(game->term.buf);
} }
} }
void Loop(struct Ctrl *ctrl, struct RecordBuffer *rec_buf) void Loop(struct Instance *game)
{ {
pthread_t draw_thread;
pthread_create(&draw_thread, nullptr, Draw, &term);
pthread_t update_thread; pthread_t update_thread;
pthread_create(&update_thread, nullptr, Update, &term); pthread_create(&update_thread, nullptr, Update, (void *)game);
}
bool Start(struct Instance *game)
{
if (!NewCtrl(&game->ctrl, code_count, code_count))
return false;
for (size_t i = 0; i < code_count; i++) {
const struct CtrlBind *bind = &ctrl_binds[i];
CtrlMap(&game->ctrl, bind->code, bind->bind, bind->type);
}
if (!NewTerm(&game->term, 20, 20))
return false;
return true;
} }
int main() int main()
{ {
struct Instance game;
Start(&game);
#ifdef _WIN32 #ifdef _WIN32
if(!WindowsInit()) if(!WindowsInit(&game.term)) {
printf("FUCK");
exit(1); exit(1);
#endif
struct ctrl_bkt code_bkts[code_count];
struct ctrl_dict codes = {
.capacity = code_count,
.filled = 0,
.bkts = code_bkts
};
struct ctrl_bkt bind_bkts[code_count];
struct ctrl_dict binds = {
.capacity = code_count,
.filled = 0,
.bkts = bind_bkts
};
struct Axis axes[code_count];
struct Ctrl ctrl = NewCtrl(&codes, &binds, axes);
for (size_t i = 0; i < code_count; i++) {
const struct CtrlBind *bind = &ctrl_binds[i];
CtrlMap(&ctrl, bind->code, bind->bind, bind->type);
} }
#endif
printf("does it work");
struct RecordBuffer rec_buf = { StartInput(&game.ctrl);
.count = 0, Loop(&game);
.mutex = PTHREAD_MUTEX_INITIALIZER
};
struct Instance game = { JoinInput(&game.ctrl);
.term = NewTerm(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);
return 0; return 0;
} }

View file

@ -18,133 +18,182 @@ struct TChar4 {
struct Terminal { struct Terminal {
size_t wid; size_t wid;
size_t hgt; size_t hgt;
u16f refresh_rate;
size_t area; size_t area;
size_t buf_size; struct TChar4 *blks;
struct TChar4 *buf; size_t buf_size;
char *buf;
u16f refresh_rate;
}; };
size_t buf_size(size_t area, size_t hgt) size_t term_buf_size(size_t area, size_t hgt)
{ {
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;
static const size_t max_color_str_len = 10;
return reset_str_len return reset_str_len + (max_color_str_len + 1) * area + hgt + 1;
+ (max_color_str_len + 1) * area
+ (hgt - 1)
+ 1;
} }
struct Terminal NewTerm(size_t wid, size_t hgt) size_t blks_size(size_t area)
{ {
size_t area = wid * hgt; return area * sizeof(struct TChar4);
return (struct Terminal) {
.wid = wid,
.hgt = hgt,
.refresh_rate = 60,
.area = area,
.buf_size = 0,
};
} }
void TermSetBufs(struct Terminal *term, struct TChar4 *buf) bool NewTerm(struct Terminal *term, size_t wid, size_t hgt)
{
term->buf_size = buf_size(term->area, term->hgt);
term->buf = buf;
}
void TermResize(struct Terminal *term, size_t wid, size_t hgt)
{ {
size_t area = wid * hgt; size_t area = wid * hgt;
size_t buf_size = term_buf_size(area, hgt); size_t buf_size = term_buf_size(area, hgt);
term->wid = wid; struct TChar4 *tchs = malloc(blks_size(area));
term->hgt = hgt; char *buf = malloc(buf_size);
term->area = area; if (tchs == nullptr or buf == nullptr)
term->buf_size = buf_size; return false;
*term = (struct Terminal) {
.wid = wid,
.hgt = hgt,
.area = area,
.blks = tchs,
.buf_size = buf_size,
.buf = buf,
.refresh_rate = 60,
};
return true;
} }
size_t printblk4(char *buf, size_t at, size_t max, struct TChar4 *blk) bool ResizeTerm(struct Terminal *term, size_t wid, size_t hgt)
{ {
u8f bg; size_t area = wid * hgt;
if (blk->bg < 8) size_t buf_size = term_buf_size(area, hgt);
bg = blk->bg + 40;
else
bg = blk->bg + 92;
u8f fg; struct TChar4 *tchs = realloc(term->blks, blks_size(area));
if (blk->fg < 8) char *buf = realloc(term->buf, buf_size);
fg = blk->fg + 30; if (tchs == nullptr or buf == nullptr)
else return false;
fg = blk->fg + 82;
return snprintf(buf + at, max - at, "\x1b[%u;%um%c", bg, fg, blk->ch); term->blks = tchs;
term->buf = buf;
return true;
}
void FreeTerm(struct Terminal *term)
{
free(term->blks);
free(term->buf);
} }
size_t u8_to_buf(char *buf, u8f x) size_t u8_to_buf(char *buf, u8f x)
{ {
size_t len = 1;
if (x > 9) {
u8f o, t;
o = x % 10;
t = x / 10;
if (x > 99) {
u8f h;
t %= 10;
h = t / 10;
len = 3;
buf[0] = h + 48;
buf[1] = t + 48;
buf[2] = o + 48;
} else {
len = 2;
buf[0] = t + 48;
buf[1] = o + 48;
}
} else {
buf[0] = x + 48;
}
return len;
} }
size_t print4(char *buf, struct TChar4 *blk) size_t tch4_dif_to_buf(char *buf, struct TChar4 *dif, struct TChar4 *blk)
{ {
u8f bg = blk->bg + (blk->bg < 8 ? 40 : 92); size_t len = 0;
u8f fg = blk->fg + (blk->fg < 8 ? 30 : 82);
memcpy(buf, "\x1b[", 2); if (dif->bg != blk->bg) {
dif->bg = blk->bg;
u8f bg = blk->bg + (blk->bg < 8 ? 40 : 92);
buf[len++] = '\x1b';
buf[len++] = '[';
len += u8_to_buf(buf + len, bg);
if (dif->fg != blk->fg) {
dif->fg = blk->fg;
u8f fg = blk->fg + (blk->fg < 8 ? 30 : 82);
buf[len++] = ';';
len += u8_to_buf(buf + len, fg);
}
buf[len++] = 'm';
} else if (dif->fg != blk->fg) {
dif->fg = blk->fg;
u8f fg = blk->fg + (blk->fg < 8 ? 30 : 82);
buf[len++] = '\x1b';
buf[len++] = '[';
len += u8_to_buf(buf + len, fg);
buf[len++] = 'm';
}
buf[len++] = blk->ch;
return len;
} }
size_t TermOut_(struct Terminal *term, char *buf) size_t TermOut(struct Terminal *term)
{ {
struct TChar4 last; struct TChar4 dif;
size_t filled = 0; size_t len = 7;
memcpy(buf, "\x1b[H\x1b[0m", 7); memcpy(term->buf, "\x1b[H\x1b[0m", 7);
} for (size_t y = 0; y < term->hgt; y++) {
for (size_t x = 0; x < term->wid; x++) {
size_t TermOut(struct Terminal *term, char *buf)
{
u8f last_bg = 0;
u8f last_fg = 0;
size_t filled = snprintf(buf, term->buf_size, "\x1b[H\x1b[0m");
for(size_t y = 0; y < term->hgt; y++) {
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->buf[i]; struct TChar4 *blk = &term->blks[i];
// DEBUG // DEBUG
if (blk->ch == 0) if (blk->ch == 0)
blk->ch = '#'; blk->ch = '#';
// DEBUG // DEBUG
if (blk->bg != 0 and blk->bg != last_bg) { len += tch4_dif_to_buf(term->buf + len, &dif, blk);
last_bg = blk->bg;
if (blk->fg != 0 and blk->fg != last_fg) {
filled += printblk4(buf, filled, term->buf_size, blk);
last_fg = blk->fg;
} else {
filled += printcol4(buf, filled, term->buf_size, blk->bg, blk->ch);
}
} else if (blk->fg != 0 and blk->fg != last_fg) {
filled += printcol4(buf, filled, term->buf_size, blk->fg, blk->ch);
last_fg = blk->fg;
} else {
buf[filled] = blk->ch;
filled += 1;
}
} }
buf[filled] = '\n'; term->buf[len++] = '\n';
filled += 1;
} }
buf[filled] = 0;
return filled; term->buf[len] = 0;
return len;
} }
/*int main()
{
struct Terminal term;
NewTerm(&term, 20, 20);
for (int i = 0; i < 20 * 20; i++) {
term.blks[i].ch = 'l';
term.blks[i].bg = 0;
term.blks[i].fg = 8;
}
size_t len = TermOut(&term);
puts(term.buf);
printf("hi");
return 0;
}*/

View file

@ -20,35 +20,18 @@ struct Terminal {
size_t wid; size_t wid;
size_t hgt; size_t hgt;
size_t area; size_t area;
u16f refresh_rate; struct TChar4 *blks;
struct TChar4 *bufs[2];
size_t buf_size; size_t buf_size;
u8f switch_read; char *buf;
u8f switch_write;
pthread_mutex_t mutex; u16f refresh_rate;
pthread_cond_t update;
struct {
u8f is_writing : 1;
u8f resize : 1;
} flags;
}; };
struct Terminal NewTerm(size_t wid, size_t hgt); bool NewTerm(struct Terminal *term, size_t wid, size_t hgt);
void TermSetBufs(struct Terminal *term, struct TChar4 *buf0, struct TChar4 *buf1); bool ResizeTerm(struct Terminal *term, size_t wid, size_t hgt);
void TermResize(struct Terminal *term, size_t wid, size_t hgt); void FreeTerm(struct Terminal *term);
void UpdateTerm(struct Terminal *term); size_t TermOut(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);

BIN
test.exe

Binary file not shown.