From 24599197c00834d73c85875ddfeabfc8897cbf1e Mon Sep 17 00:00:00 2001 From: Julia <145168563+julia-aph@users.noreply.github.com> Date: Mon, 6 May 2024 00:52:30 -0500 Subject: [PATCH] afds asfd --- .vscode/settings.json | 4 +- source/fumoengine/fumocommon.h | 16 +++-- source/fumoengine/fumoengine.c | 10 +-- source/fumoengine/fumoengine.h | 2 +- source/fumoengine/include/ringbuffer.h | 6 +- source/fumoengine/input/ctrl.c | 5 +- source/fumoengine/input/platforms/win.c | 2 +- source/fumoengine/terminal/term.c | 82 ++++-------------------- source/fumoengine/terminal/term.h | 18 ++---- source/fumotris/fumotris.c | 12 ++-- source/fumotris/tetr.c | 4 +- test.exe | Bin 85504 -> 85669 bytes 12 files changed, 56 insertions(+), 105 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 9070c03..94cdde1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -56,6 +56,8 @@ "stdlib.h": "c", "stdio.h": "c", "platform.h": "c", - "ringbuffer.h": "c" + "ringbuffer.h": "c", + "fumoengine.h": "c", + "fumocommon.h": "c" } } \ No newline at end of file diff --git a/source/fumoengine/fumocommon.h b/source/fumoengine/fumocommon.h index 80603da..1c077c0 100644 --- a/source/fumoengine/fumocommon.h +++ b/source/fumoengine/fumocommon.h @@ -6,6 +6,10 @@ #define ONE_E_9 1000000000 +typedef size_t usize; +typedef ptrdiff_t isize; + + typedef uint8_t u8; typedef uint_fast8_t u8f; @@ -22,14 +26,14 @@ typedef uint_fast64_t u64f; typedef int8_t i8; typedef int_fast8_t i8f; -typedef int16_t i16; -typedef int_fast16_t i16f; +typedef int16_t i16; +typedef int_fast16_t i16f; -typedef int32_t i32; -typedef int_fast32_t i32f; +typedef int32_t i32; +typedef int_fast32_t i32f; -typedef int64_t i64; -typedef int_fast64_t i64f; +typedef int64_t i64; +typedef int_fast64_t i64f; typedef u64 Time; diff --git a/source/fumoengine/fumoengine.c b/source/fumoengine/fumoengine.c index 4c030d4..a1d0db7 100644 --- a/source/fumoengine/fumoengine.c +++ b/source/fumoengine/fumoengine.c @@ -2,7 +2,7 @@ #include "platform.h" -void ErrorExit(char *message) +void Panic(char *message) { printf(message); exit(1); @@ -11,16 +11,16 @@ void ErrorExit(char *message) bool FumoInit(struct FumoGame *game) { if (!PlatformInit()) - ErrorExit("Platform failed to initialize"); + Panic("Platform failed to initialize"); if (!CreateController(&game->ctrl)) - ErrorExit("Out of memory"); + Panic("Out of memory"); if (!CreateEvent(&game->update)) - ErrorExit("Out of memory"); + Panic("Out of memory"); if (!BeginInputThread(&game->input_hand)) - ErrorExit("Input handle failed to initialize"); + Panic("Input handle failed to initialize"); return 0; } \ No newline at end of file diff --git a/source/fumoengine/fumoengine.h b/source/fumoengine/fumoengine.h index 9bbc60e..59e5a2e 100644 --- a/source/fumoengine/fumoengine.h +++ b/source/fumoengine/fumoengine.h @@ -17,7 +17,7 @@ struct FumoGame { }; -void ErrorExit(char *message); +void Panic(char *message); bool FumoInit(struct FumoGame *game); diff --git a/source/fumoengine/include/ringbuffer.h b/source/fumoengine/include/ringbuffer.h index 0ceacbd..57b0dde 100644 --- a/source/fumoengine/include/ringbuffer.h +++ b/source/fumoengine/include/ringbuffer.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include #include @@ -19,7 +20,10 @@ struct RingBufferHead { #define RINGBUF_T_INIT(RBUF_STRUCT, RBUF_ITEM, RBUF_LEN) \ (&(struct RingBufferT) { \ - .OFFSET = offsetof(RBUF_STRUCT, buf), \ + .OFFSET = offsetof(struct { \ + struct RingBufferHead head; \ + RBUF_ITEM item; \ + }, item), \ .SIZE = sizeof(RBUF_ITEM), \ .LEN = RBUF_LEN \ }) \ diff --git a/source/fumoengine/input/ctrl.c b/source/fumoengine/input/ctrl.c index c7b932e..a46df95 100644 --- a/source/fumoengine/input/ctrl.c +++ b/source/fumoengine/input/ctrl.c @@ -146,13 +146,14 @@ void dispatch_update(struct InputAxis *axis, struct InputRecord *rec) 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]; axis->is_up = 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++) { struct InputRecord *rec = &recs->buf[i]; diff --git a/source/fumoengine/input/platforms/win.c b/source/fumoengine/input/platforms/win.c index e36b5bd..cfbbd15 100644 --- a/source/fumoengine/input/platforms/win.c +++ b/source/fumoengine/input/platforms/win.c @@ -161,7 +161,7 @@ bool dispatch_rec( size_t read_input(struct win_rec *buf, size_t n) { DWORD len; - if (!ReadConsoleInputW(win.input_hand, buf, n, &len)) + if (!ReadConsoleInputW(win.input_hand, (INPUT_RECORD *)buf, n, &len)) return 0; return len; diff --git a/source/fumoengine/terminal/term.c b/source/fumoengine/terminal/term.c index 682e24a..8840c31 100644 --- a/source/fumoengine/terminal/term.c +++ b/source/fumoengine/terminal/term.c @@ -1,30 +1,5 @@ -#include -#include -#include -#include -#include -#include +#include "term.h" -#include "fumocommon.h" - - -struct TChar4 { - char ch; - u8 bg : 4; - u8 fg : 4; -}; - -struct Terminal { - size_t wid; - size_t hgt; - size_t area; - struct TChar4 *blks; - - size_t buf_size; - char *buf; - - u16f refresh_rate; -}; size_t term_buf_size(size_t area, size_t hgt) { @@ -34,61 +9,30 @@ size_t term_buf_size(size_t area, size_t hgt) return reset_str_len + (max_color_str_len + 1) * area + hgt + 1; } -struct TChar4 *alloc_blks(size_t area) -{ - return calloc(area, sizeof(struct TChar4)); -} - -char *alloc_buf(size_t buf_size) -{ - return malloc(buf_size); -} - -bool NewTerm(struct Terminal *term, size_t wid, size_t hgt) +bool CreateTerminal(struct Terminal *term, size_t wid, size_t hgt) { size_t area = wid * hgt; size_t buf_size = term_buf_size(area, hgt); - struct TChar4 *blks = alloc_blks(area); - char *buf = alloc_buf(buf_size); + struct Char4 *chs = calloc(area, sizeof(struct Char4)); - if (blks == nullptr or buf == nullptr) + if (chs == nullptr) return false; *term = (struct Terminal) { .wid = wid, .hgt = hgt, .area = area, - .blks = blks, - .buf_size = buf_size, - .buf = buf, - - .refresh_rate = 60, + .chs = chs, }; + return true; } -bool ResizeTerm(struct Terminal *term, size_t wid, size_t hgt) +void FreeTerminal(struct Terminal *term) { - size_t area = wid * hgt; - size_t buf_size = term_buf_size(area, hgt); - - struct TChar4 *tchs = realloc(term->blks, area * sizeof(struct TChar4)); - char *buf = realloc(term->buf, buf_size); - - if (tchs == nullptr or buf == nullptr) - return false; - - term->blks = tchs; - term->buf = buf; - return true; -} - -void FreeTerm(struct Terminal *term) -{ - free(term->blks); - free(term->buf); + free(term->chs); } size_t u8_to_buf(char *buf, u8f x) @@ -124,7 +68,7 @@ size_t u8_to_buf(char *buf, u8f x) return len; } -size_t tch4_dif_to_buf(char *buf, struct TChar4 *dif, struct TChar4 *blk) +size_t ch4_dif_to_buf(char *buf, struct Char4 *dif, struct Char4 *blk) { size_t len = 0; @@ -159,9 +103,9 @@ size_t tch4_dif_to_buf(char *buf, struct TChar4 *dif, struct TChar4 *blk) return len; } -size_t TermOut(struct Terminal *term) +size_t TerminalPrint(char *dest, size_t n, struct Terminal *term) { - struct TChar4 dif; + struct Char4 dif; size_t len = 7; memcpy(term->buf, "\x1b[H\x1b[0m", 7); @@ -169,14 +113,14 @@ size_t TermOut(struct Terminal *term) 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->blks[i]; + struct Char4 *blk = &term->chs[i]; // DEBUG if (blk->ch == 0) blk->ch = '#'; // DEBUG - len += tch4_dif_to_buf(term->buf + len, &dif, blk); + len += ch4_dif_to_buf(term->buf + len, &dif, blk); } term->buf[len++] = '\n'; } diff --git a/source/fumoengine/terminal/term.h b/source/fumoengine/terminal/term.h index eb1b345..082f50d 100644 --- a/source/fumoengine/terminal/term.h +++ b/source/fumoengine/terminal/term.h @@ -1,16 +1,14 @@ #pragma once #include -#include #include #include #include #include -#include #include "fumocommon.h" -struct TChar4 { +struct Char4 { char ch; u8 bg : 4; u8 fg : 4; @@ -20,18 +18,12 @@ struct Terminal { size_t wid; size_t hgt; size_t area; - struct TChar4 *blks; - size_t buf_size; - char *buf; - - u16f refresh_rate; + struct Char4 *chs; }; -bool NewTerm(struct Terminal *term, size_t wid, size_t hgt); +bool CreateTerminal(struct Terminal *term, size_t wid, size_t hgt); -bool ResizeTerm(struct Terminal *term, size_t wid, size_t hgt); +void FreeTerminal(struct Terminal *term); -void FreeTerm(struct Terminal *term); - -size_t TermOut(struct Terminal *term); \ No newline at end of file +size_t TerminalPrint(char *dest, size_t n, struct Terminal *term); \ No newline at end of file diff --git a/source/fumotris/fumotris.c b/source/fumotris/fumotris.c index 06946d7..6127712 100644 --- a/source/fumotris/fumotris.c +++ b/source/fumotris/fumotris.c @@ -40,14 +40,18 @@ void Loop(struct FumoGame *game) game->time = TimeNow(); if (!InputAquire(&game->input_hand)) - ErrorExit("Aquire failed"); + Panic("Aquire failed"); - //ControllerPoll(&game->ctrl, &game->input_hand.recs); + ControllerPoll(&game->ctrl, &game->input_hand.recs); + u64 val = ControllerGet(&game->ctrl, LEFT, BUTTON)->is_down; + printf("%u\n", val); if (!InputRelease(&game->input_hand)) - ErrorExit("Release failed"); + Panic("Release failed"); - //EventInvokeUpdate(&game->update, 0); + EventInvokeUpdate(&game->update, 0); + + _sleep(100); } } diff --git a/source/fumotris/tetr.c b/source/fumotris/tetr.c index 5681afa..816d8fd 100644 --- a/source/fumotris/tetr.c +++ b/source/fumotris/tetr.c @@ -43,8 +43,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->blks[buf_i]; - struct TChar4 *b = &term->blks[buf_i + 1]; + struct Char4 *a = &term->chs[buf_i]; + struct Char4 *b = &term->chs[buf_i + 1]; if (map->blks[map_i] == 0) { a->ch = '('; diff --git a/test.exe b/test.exe index ada5cb88d40cb90acf973e401aa00269bf7013da..cbb98a9c8cba4dbfd502dcb0e818c94ebef959d8 100644 GIT binary patch delta 19296 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 delta 18868 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 K!iJ0I#eV@btU0Iv