From c941f8b7fbc056e8f31ea960de85267fa48bbef4 Mon Sep 17 00:00:00 2001 From: Julia <145168563+julia-aph@users.noreply.github.com> Date: Tue, 9 Apr 2024 02:00:48 -0500 Subject: [PATCH] safdasf fas --- hi.exe | Bin 0 -> 63344 bytes source/game/event.c | 2 +- source/game/tetr.c | 4 +- source/io/ctrl.c | 91 ++++++------- source/io/ctrl.h | 8 +- source/io/input.c | 8 +- source/io/input.h | 4 +- source/io/platforms/win.c | 11 +- source/io/platforms/win.h | 3 +- source/io/platforms/winhandler.c | 65 ++++----- source/io/platforms/winhandler.h | 2 +- source/main.c | 142 +++++++------------- source/term/term.c | 221 +++++++++++++++++++------------ source/term/term.h | 33 ++--- test.exe | Bin 81044 -> 82015 bytes 15 files changed, 286 insertions(+), 308 deletions(-) create mode 100644 hi.exe diff --git a/hi.exe b/hi.exe new file mode 100644 index 0000000000000000000000000000000000000000..1eb5afa7f1ea6fcb6419ec8b6e3d438944b0ccde GIT binary patch literal 63344 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 XI5wqhSB;igk;b^1fJLw|L+$?qXBvX8 literal 0 HcmV?d00001 diff --git a/source/game/event.c b/source/game/event.c index 41cec24..1365202 100644 --- a/source/game/event.c +++ b/source/game/event.c @@ -12,7 +12,7 @@ struct Delegate { void (**events)(void *args); }; -inline size_t delegate_size(size_t capacity) +size_t delegate_size(size_t capacity) { return sizeof(void(*)(void *)) * capacity; } diff --git a/source/game/tetr.c b/source/game/tetr.c index fade61d..c579f0d 100644 --- a/source/game/tetr.c +++ b/source/game/tetr.c @@ -42,8 +42,8 @@ void TetrMapToTermBuf(struct TetrMap *map, struct Terminal *term) size_t map_i = y * map->wid + x; size_t buf_i = (y + map->y) * term->wid + (x + map->x) * 2; - struct TChar4 *a = &term->bufs[buf_i]; - struct TChar4 *b = &term->bufs[buf_i + 1]; + struct TChar4 *a = &term->blks[buf_i]; + struct TChar4 *b = &term->blks[buf_i + 1]; if (map->blks[map_i] == 0) { a->ch = '('; diff --git a/source/io/ctrl.c b/source/io/ctrl.c index d55d7fd..2a851ea 100644 --- a/source/io/ctrl.c +++ b/source/io/ctrl.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -68,7 +67,7 @@ struct Axis { typedef u32 hashtype; hashtype Hash(void *item, size_t size) { - u8* data = (u8*)item; + u8 *data = (u8 *)item; u32 h = 98317; for (size_t i = 0; i < size; i++) { @@ -80,7 +79,7 @@ hashtype Hash(void *item, size_t size) return h; } -hashtype hash_ident(u16f value, u8f type) +hashtype hash_id(u16f value, u8f type) { struct id { u16 id; @@ -108,49 +107,51 @@ struct Ctrl { struct ctrl_dict codes; struct ctrl_dict binds; + struct RecordBuffer buf; 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) { - .capacity = 0, + .capacity = code_cap, .filled = 0, - .bkts = nullptr + .bkts = code_bkts, }, .binds = (struct ctrl_dict) { - .capacity = 0, + .capacity = bind_cap, .filled = 0, - .bkts = nullptr + .bkts = bind_bkts, + }, + + .buf = (struct RecordBuffer) { + .count = 0, + .mutex = PTHREAD_MUTEX_INITIALIZER, }, - - .mutex = PTHREAD_MUTEX_INITIALIZER }; - return ctrl; + return true; } -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); +void FreeCtrl(struct Ctrl *ctrl) +{ + free(ctrl->codes.bkts); + free(ctrl->binds.bkts); } struct ctrl_bkt *get_bkt(struct ctrl_dict *dict, size_t i) { - assert(i < dict->capacity); return &dict->bkts[i]; } @@ -161,18 +162,18 @@ void set_bkt(struct ctrl_bkt *bkt, hashtype hash, u16f value, u8f 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) { - hashtype hash = hash_ident(value, type); + hashtype hash = hash_id(value, type); const size_t index = hash % dict->capacity; 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); 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) { - hashtype hash = hash_ident(value, type); + hashtype hash = hash_id(value, type); const size_t index = hash % dict->capacity; 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); if (bkt->hash == 0) goto next; - if (bkt->value == value and bkt->type == type) { + if (bkt->value == value and bkt->type == type) return bkt; - } + next: 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) { - assert(ctrl->codes.filled < ctrl->codes.capacity); - assert(ctrl->binds.filled < ctrl->binds.capacity); + if (ctrl->codes.filled >= ctrl->codes.capacity or ctrl->binds.filled >= ctrl->binds.capacity) { + printf("fatal error"); + exit(1); + } struct ctrl_bkt *code_bkt; find_or_set(&ctrl->codes, &code_bkt, code, type); - assert(code_bkt != nullptr); struct ctrl_bkt *bind_bkt; 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) return false; @@ -276,10 +277,10 @@ void update_joystick(struct Axis *axis, struct Record *record) 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++) { - struct Record *rec = &rec_buf->records[i]; + for (size_t i = 0; i < ctrl->buf.count; i++) { + struct Record *rec = &ctrl->buf.records[i]; struct Axis *axis = find_axis(&ctrl->binds, rec->id, rec->type); 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; } \ No newline at end of file diff --git a/source/io/ctrl.h b/source/io/ctrl.h index f81db90..0e6635b 100644 --- a/source/io/ctrl.h +++ b/source/io/ctrl.h @@ -99,14 +99,16 @@ struct Ctrl { struct ctrl_dict codes; struct ctrl_dict binds; + struct RecordBuffer buf; 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); struct Axis *CtrlGet(struct Ctrl *ctrl, u16f code, u8f type); -bool CtrlPoll(struct Ctrl *ctrl, struct RecordBuffer *buf); \ No newline at end of file +bool CtrlPoll(struct Ctrl *ctrl); \ No newline at end of file diff --git a/source/io/input.c b/source/io/input.c index d842757..87ddc34 100644 --- a/source/io/input.c +++ b/source/io/input.c @@ -14,13 +14,13 @@ void *block_input(void *args_ptr) { - struct RecordBuffer *buf = args_ptr; + struct RecordBuffer *rec_buf = args_ptr; while (true) { bool success; #ifdef _WIN32 - success = WindowsBlockInput(buf); + success = WindowsBlockInput(rec_buf); #endif if (!success) { @@ -32,9 +32,9 @@ void *block_input(void *args_ptr) 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) diff --git a/source/io/input.h b/source/io/input.h index 08c43eb..c9b3732 100644 --- a/source/io/input.h +++ b/source/io/input.h @@ -8,6 +8,6 @@ #include "ctrl.h" #include "fumotris.h" -void StartInput(Ctrl *ctrl, struct RecordBuffer *buf); +void StartInput(struct Ctrl *ctrl); -void JoinInput(Ctrl *ctrl); \ No newline at end of file +void JoinInput(struct Ctrl *ctrl); \ No newline at end of file diff --git a/source/io/platforms/win.c b/source/io/platforms/win.c index 37944b1..18ffe6c 100644 --- a/source/io/platforms/win.c +++ b/source/io/platforms/win.c @@ -10,17 +10,22 @@ #include "winhandler.h" #include "term.h" +#include + bool WindowsInit(struct Terminal *term) { if (!WinInitHandles()) return false; + printf("shid "); - if (!WinInitConsole()) + if (!WinInitConsole()) { + printf("%u\n", GetLastError()); return false; - + } + printf("console"); if (!WinGetRefreshRate(&term->refresh_rate)) return false; - + printf("???"); return true; } diff --git a/source/io/platforms/win.h b/source/io/platforms/win.h index 57eee81..fdebbae 100644 --- a/source/io/platforms/win.h +++ b/source/io/platforms/win.h @@ -7,8 +7,9 @@ #include #include "input.h" +#include "term.h" -bool WindowsInit(); +bool WindowsInit(struct Terminal *term); bool WindowsBlockInput(struct RecordBuffer *buf); diff --git a/source/io/platforms/winhandler.c b/source/io/platforms/winhandler.c index 3dc5eac..066bf4c 100644 --- a/source/io/platforms/winhandler.c +++ b/source/io/platforms/winhandler.c @@ -14,31 +14,22 @@ struct Windows { HANDLE input_handle; - HANDLE draw_handles[2]; + HANDLE timer; }; -static struct Windows windows; +static struct Windows win; bool WinInitHandles() { - windows.input_handle = GetStdHandle(STD_INPUT_HANDLE); - if (windows.input_handle == INVALID_HANDLE_VALUE) + win.input_handle = GetStdHandle(STD_INPUT_HANDLE); + if (win.input_handle == INVALID_HANDLE_VALUE) return false; - windows.draw_handles[0] = CreateWaitableTimer( - NULL, // Timer attributes - TRUE, // Manual reset - NULL // Name + win.timer = CreateWaitableTimer( + NULL, // Timer attributes + TRUE, // Manual reset + NULL // Name ); - if (!windows.draw_handles[0]) - return false; - - windows.draw_handles[1] = CreateEvent( - NULL, // Event attributes - FALSE, // Manual reset - FALSE, // Initial state - NULL // Name - ); - if (!windows.draw_handles[1]) + if (!win.timer) return false; return true; @@ -51,20 +42,23 @@ bool WinInitConsole() | ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT | 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( - NULL, // Device name (null for current) - ENUM_CURRENT_SETTINGS, // Mode - &mode // Out + NULL, // Device name (null for current) + ENUM_CURRENT_SETTINGS, // Mode + &mode // Out )) return false; - *out = mode->dmDisplayFrequency; + *out = mode.dmDisplayFrequency; return true; } @@ -112,8 +106,8 @@ bool dispatch_record(struct Record *record, INPUT_RECORD win_record) case MOUSE_EVENT: return set_mouse_record(record, win_record.Event.MouseEvent); case WINDOW_BUFFER_SIZE_EVENT: - set_window_record(record, win_record.Event.WindowBufferSizeEvent); - break; + // TODO: Handle window resizing + return false; default: record->type = ESCAPE; } @@ -127,10 +121,10 @@ bool WinBlockInput(struct RecordBuffer *buf) DWORD count; if (!ReadConsoleInput( - windows.input_handle, // Input handle - win_buf, // Record buffer - win_size, // Record buffer length - &count // Out number of records + win.input_handle, // Input handle + win_buf, // Record buffer + win_size, // Record buffer length + &count // Out number of records )) return false; @@ -160,7 +154,7 @@ bool WinWait(struct timespec relative) duration.QuadPart = -10000000 * relative.tv_sec - relative.tv_nsec / 100; if (!SetWaitableTimer( - windows.draw_handles[0], // Timer + win.timer, // Timer &duration, // Duration 0, // Period NULL, // Completion coroutine @@ -169,12 +163,7 @@ bool WinWait(struct timespec relative) )) return false; - DWORD result = WaitForMultipleObjects( - 2, // Handle count - windows.draw_handles, // Handles - FALSE, // Wait for all - INFINITE // Timeout - ); + DWORD result = WaitForSingleObject(win.timer, INFINITE); if (result != WAIT_OBJECT_0) return false; diff --git a/source/io/platforms/winhandler.h b/source/io/platforms/winhandler.h index a123a2b..61d4fae 100644 --- a/source/io/platforms/winhandler.h +++ b/source/io/platforms/winhandler.h @@ -11,7 +11,7 @@ bool WinInitHandles(); bool WinInitConsole(); -bool WinGetRefreshRate(u32f *out); +bool WinGetRefreshRate(u16f *out); bool WinBlockInput(struct RecordBuffer *buf); diff --git a/source/main.c b/source/main.c index cd35607..77c0442 100644 --- a/source/main.c +++ b/source/main.c @@ -16,16 +16,6 @@ #include "win.h" #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] = { 0, 0, 0, 0, 0, 0, 0, 0, @@ -68,6 +58,16 @@ const u8 L[9] = { 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 { enum CtrlCode code; u16 bind; @@ -90,117 +90,65 @@ const struct CtrlBind ctrl_binds[12] = { { 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); - { - 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); + struct TChar4 blks[game->term.area]; + game->term.blks = blks; while (true) { // Input - CtrlPoll(&game->ctrl, &game->rec_buf); + CtrlPoll(&game->ctrl); // Game logic Invoke(&game->on_update, game); // 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_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() { + struct Instance game; + Start(&game); + #ifdef _WIN32 - if(!WindowsInit()) + if(!WindowsInit(&game.term)) { + printf("FUCK"); 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 = { - .count = 0, - .mutex = PTHREAD_MUTEX_INITIALIZER - }; + StartInput(&game.ctrl); + Loop(&game); - struct Instance game = { - .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); + JoinInput(&game.ctrl); return 0; } \ No newline at end of file diff --git a/source/term/term.c b/source/term/term.c index c197cd1..6f7dc38 100644 --- a/source/term/term.c +++ b/source/term/term.c @@ -18,133 +18,182 @@ struct TChar4 { struct Terminal { size_t wid; size_t hgt; - u16f refresh_rate; - size_t area; + struct TChar4 *blks; + size_t buf_size; + char *buf; - struct TChar4 *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 max_color_str_len = 10; - return reset_str_len - + (max_color_str_len + 1) * area - + (hgt - 1) - + 1; + return reset_str_len + (max_color_str_len + 1) * area + hgt + 1; } -struct Terminal NewTerm(size_t wid, size_t hgt) +size_t blks_size(size_t area) +{ + return area * sizeof(struct TChar4); +} + +bool NewTerm(struct Terminal *term, size_t wid, size_t hgt) { size_t area = wid * hgt; + size_t buf_size = term_buf_size(area, hgt); - return (struct Terminal) { + struct TChar4 *tchs = malloc(blks_size(area)); + char *buf = malloc(buf_size); + + if (tchs == nullptr or buf == nullptr) + return false; + + *term = (struct Terminal) { .wid = wid, .hgt = hgt, - .refresh_rate = 60, - .area = area, - .buf_size = 0, + .blks = tchs, + + .buf_size = buf_size, + .buf = buf, + + .refresh_rate = 60, }; + return true; } -void TermSetBufs(struct Terminal *term, struct TChar4 *buf) -{ - term->buf_size = buf_size(term->area, term->hgt); - term->buf = buf; -} - -void TermResize(struct Terminal *term, size_t wid, size_t hgt) +bool ResizeTerm(struct Terminal *term, size_t wid, size_t hgt) { size_t area = wid * hgt; size_t buf_size = term_buf_size(area, hgt); - term->wid = wid; - term->hgt = hgt; + struct TChar4 *tchs = realloc(term->blks, blks_size(area)); + char *buf = realloc(term->buf, buf_size); + if (tchs == nullptr or buf == nullptr) + return false; - term->area = area; - term->buf_size = buf_size; + term->blks = tchs; + term->buf = buf; + return true; } -size_t printblk4(char *buf, size_t at, size_t max, struct TChar4 *blk) +void FreeTerm(struct Terminal *term) { - u8f bg; - if (blk->bg < 8) - bg = blk->bg + 40; - else - bg = blk->bg + 92; - - u8f fg; - if (blk->fg < 8) - fg = blk->fg + 30; - else - fg = blk->fg + 82; - - return snprintf(buf + at, max - at, "\x1b[%u;%um%c", bg, fg, blk->ch); + free(term->blks); + free(term->buf); } 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 tch4_dif_to_buf(char *buf, struct TChar4 *dif, struct TChar4 *blk) +{ + size_t len = 0; + + 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 print4(char *buf, struct TChar4 *blk) +size_t TermOut(struct Terminal *term) { - u8f bg = blk->bg + (blk->bg < 8 ? 40 : 92); - u8f fg = blk->fg + (blk->fg < 8 ? 30 : 82); + struct TChar4 dif; - memcpy(buf, "\x1b[", 2); - -} + size_t len = 7; + memcpy(term->buf, "\x1b[H\x1b[0m", 7); -size_t TermOut_(struct Terminal *term, char *buf) -{ - struct TChar4 last; - - size_t filled = 0; - memcpy(buf, "\x1b[H\x1b[0m", 7); - -} - -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++) { + 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; - struct TChar4 *blk = &term->buf[i]; - + struct TChar4 *blk = &term->blks[i]; + // DEBUG if (blk->ch == 0) blk->ch = '#'; // DEBUG - - if (blk->bg != 0 and blk->bg != last_bg) { - 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; - } + + len += tch4_dif_to_buf(term->buf + len, &dif, blk); } - buf[filled] = '\n'; - filled += 1; + term->buf[len++] = '\n'; } - buf[filled] = 0; - return filled; -} \ No newline at end of file + + 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; +}*/ \ No newline at end of file diff --git a/source/term/term.h b/source/term/term.h index 37cf81e..7d27978 100644 --- a/source/term/term.h +++ b/source/term/term.h @@ -20,35 +20,18 @@ struct Terminal { size_t wid; size_t hgt; size_t area; - u16f refresh_rate; - - struct TChar4 *bufs[2]; + struct TChar4 *blks; + size_t buf_size; - u8f switch_read; - u8f switch_write; + char *buf; - pthread_mutex_t mutex; - pthread_cond_t update; - - struct { - u8f is_writing : 1; - u8f resize : 1; - } flags; + u16f refresh_rate; }; -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); -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); \ No newline at end of file +size_t TermOut(struct Terminal *term); \ No newline at end of file diff --git a/test.exe b/test.exe index ceedd7aa5f5fb214ba568488f621fafbed12a42f..e084d5b381f7ab23a185ab5b12253520e99d31e2 100644 GIT binary patch literal 82015 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 delta 24855 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 mzmeaYo5~A