diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..4fa3689 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,21 @@ +{ + "configurations": [ + { + "name": "Win32", + "includePath": [ + "${workspaceFolder}/**" + ], + "defines": [ + "_DEBUG", + "UNICODE", + "_UNICODE" + ], + "windowsSdkVersion": "10.0.22000.0", + "compilerPath": "C:/mingw64/bin/gcc.exe", + "cStandard": "c17", + "cppStandard": "c++17", + "intelliSenseMode": "windows-gcc-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..3aef1c1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "files.associations": { + "compare": "c", + "concepts": "c", + "cstdlib": "c", + "type_traits": "c", + "cmath": "c", + "limits": "c", + "new": "c" + } +} \ No newline at end of file diff --git a/build.py b/build.py index 3cbd166..21802c3 100644 --- a/build.py +++ b/build.py @@ -11,7 +11,7 @@ ARGS = "-fdiagnostics-color -pthread -Wall -std=c17 -pedantic -g" SOURCE_DIR = Path("source/") OBJECT_DIR = Path("objects/") -OUTPUT = Path("build/debug") +OUTPUT = Path("debug") SRC_CHECKSUMS_TXT = Path("build/src_checksums.txt") diff --git a/build/debug.exe b/build/debug.exe deleted file mode 100644 index eda6b15..0000000 Binary files a/build/debug.exe and /dev/null differ diff --git a/build/errors.txt b/build/errors.txt index 9dde9e6..c099047 100644 --- a/build/errors.txt +++ b/build/errors.txt @@ -1 +1 @@ -{"tetr": "", "ringbuffer": "", "event": "", "ctrl": "", "terminal": "", "fumoengine": "", "parseinput": "", "dictionary": "", "fumocommon": "", "win": "", "input": "", "fumotris": "", "vector": ""} \ No newline at end of file +{"ringbuffer": "", "event": "", "ctrl": "", "terminal": "", "fumoengine": "", "parseinput": "", "dictionary": "", "fumocommon": "", "win": "", "input": "", "fumotris": "", "vector": "", "tetra": ""} \ No newline at end of file diff --git a/build/hdr_checksums.txt b/build/hdr_checksums.txt index ed1b7c8..37d3502 100644 --- a/build/hdr_checksums.txt +++ b/build/hdr_checksums.txt @@ -1 +1 @@ -["0d7597ffd48812c52d3f02731cbf693f", "6669fc7fcffc77563f1315cb7710ec82", "fbccab3d5cd1838cbf8ad1d4e2a7c03b", "1d6bdf7e8de4ac751252b67027e5d57e", "330b6f9493d091e7c340c1434b6f80b4", "a3dca3fbce775b791384bec8abc3f0c3", "f61af2abe56cd6881a830ae6222483e9", "1cdcae043579aa6406b9823b5f52aedd", "088145536b04ef82517eb93630888dff", "1420f33d62a8ed8429c8f1a96f1ab33e", "e38bd5ea2b554a21849158242a2add8e", "9df90eabc8908cac60aa774d335a106c", "333c7211bb2c72ad321495f53d11bff0", "dc6df72158812bc9f6ed484a4cfb046b"] \ No newline at end of file +["1d6bdf7e8de4ac751252b67027e5d57e", "9df90eabc8908cac60aa774d335a106c", "1420f33d62a8ed8429c8f1a96f1ab33e", "dc6df72158812bc9f6ed484a4cfb046b", "6669fc7fcffc77563f1315cb7710ec82", "333c7211bb2c72ad321495f53d11bff0", "088145536b04ef82517eb93630888dff", "f61af2abe56cd6881a830ae6222483e9", "e09059d1f20c982c6c42a61a0754c102", "fbccab3d5cd1838cbf8ad1d4e2a7c03b", "330b6f9493d091e7c340c1434b6f80b4", "e38bd5ea2b554a21849158242a2add8e"] \ No newline at end of file diff --git a/debug.exe b/debug.exe new file mode 100644 index 0000000..dda63fa Binary files /dev/null and b/debug.exe differ diff --git a/objects/ctrl.o b/objects/ctrl.o index 25339a9..9638d8e 100644 Binary files a/objects/ctrl.o and b/objects/ctrl.o differ diff --git a/objects/dictionary.o b/objects/dictionary.o index 763d6d4..5aa83ba 100644 Binary files a/objects/dictionary.o and b/objects/dictionary.o differ diff --git a/objects/event.o b/objects/event.o index 95dd92c..68654a0 100644 Binary files a/objects/event.o and b/objects/event.o differ diff --git a/objects/fumocommon.o b/objects/fumocommon.o index ce43889..bb3f424 100644 Binary files a/objects/fumocommon.o and b/objects/fumocommon.o differ diff --git a/objects/fumoengine.o b/objects/fumoengine.o index 71fbb76..9b15b8a 100644 Binary files a/objects/fumoengine.o and b/objects/fumoengine.o differ diff --git a/objects/fumotris.o b/objects/fumotris.o index 479d292..3268eb1 100644 Binary files a/objects/fumotris.o and b/objects/fumotris.o differ diff --git a/objects/input.o b/objects/input.o index 481c498..b9a14eb 100644 Binary files a/objects/input.o and b/objects/input.o differ diff --git a/objects/parseinput.o b/objects/parseinput.o index d82f6db..3353ca8 100644 Binary files a/objects/parseinput.o and b/objects/parseinput.o differ diff --git a/objects/ringbuffer.o b/objects/ringbuffer.o index 0c42d27..550bf82 100644 Binary files a/objects/ringbuffer.o and b/objects/ringbuffer.o differ diff --git a/objects/terminal.o b/objects/terminal.o index 15f1c79..7c54a21 100644 Binary files a/objects/terminal.o and b/objects/terminal.o differ diff --git a/objects/tetr.o b/objects/tetr.o index 4966281..df3f43e 100644 Binary files a/objects/tetr.o and b/objects/tetr.o differ diff --git a/objects/tetra.o b/objects/tetra.o new file mode 100644 index 0000000..871a9ab Binary files /dev/null and b/objects/tetra.o differ diff --git a/objects/vector.o b/objects/vector.o index 573ad7c..932cde8 100644 Binary files a/objects/vector.o and b/objects/vector.o differ diff --git a/objects/win.o b/objects/win.o index 97ef881..f9b8c56 100644 Binary files a/objects/win.o and b/objects/win.o differ diff --git a/source/fumoengine/fumocommon.h b/source/fumoengine/fumocommon.h index f1739d6..132da2e 100644 --- a/source/fumoengine/fumocommon.h +++ b/source/fumoengine/fumocommon.h @@ -9,7 +9,6 @@ typedef size_t usize; -typedef ptrdiff_t isize; typedef uint8_t u8; diff --git a/source/fumoengine/fumoengine.c b/source/fumoengine/fumoengine.c index 72c6e69..1217379 100644 --- a/source/fumoengine/fumoengine.c +++ b/source/fumoengine/fumoengine.c @@ -51,8 +51,9 @@ bool FumoInstanceRun(struct FumoInstance *inst) nsec now = TimeNow(); inst->frametime = now - inst->time; - EventInvoke(&inst->on_update, inst); inst->time = now; + + EventInvoke(&inst->on_update, inst); TerminalPrint(&inst->term, buf, buf_n); puts(buf); diff --git a/source/fumoengine/include/dictionary.c b/source/fumoengine/include/dictionary.c index 7f63491..2e69e08 100644 --- a/source/fumoengine/include/dictionary.c +++ b/source/fumoengine/include/dictionary.c @@ -1,4 +1,5 @@ #include "dictionary.h" +#include #include #include @@ -74,7 +75,11 @@ void *DictionaryFind(DictT T, struct Dictionary *dict, u32 key) { usize index = key % dict->capacity; - return probe_bkt(T, dict, index, key); + void *bkt = probe_bkt(T, dict, index, key); + if (bkt == nullptr) + return false; + + return get_val(T, bkt); } void *DictionarySet(DictT T, struct Dictionary *dict, u32 key, void *val) @@ -82,6 +87,7 @@ void *DictionarySet(DictT T, struct Dictionary *dict, u32 key, void *val) usize index = key % dict->capacity; void *bkt = probe_empty_bkt(T, dict, index, key); + if (*get_key(T, bkt) == 0) set_bkt(T, bkt, key, val); diff --git a/source/fumoengine/input/ctrl.c b/source/fumoengine/input/ctrl.c index deba581..fba729f 100644 --- a/source/fumoengine/input/ctrl.c +++ b/source/fumoengine/input/ctrl.c @@ -10,18 +10,15 @@ DictT BIND_T = DICT_T(struct InputAxis *); bool CreateController(struct Controller *ctrl) { struct InputAxis *axes = calloc(16, sizeof(struct InputAxis)); - if (axes == nullptr) return false; if (!CreateDictionary(BIND_T, &ctrl->binds)) return false; - *ctrl = (struct Controller) { - .pending_len = 0, - .axes = axes, - .axes_len = 0 - }; + ctrl->pending_len = 0; + ctrl->axes = axes; + ctrl->axes_len = 0; return true; } @@ -42,13 +39,11 @@ bool ControllerBind(struct Controller *ctrl, u16 control, u16 code, u16 type) u32 hash = hash_bind(code, type); struct InputAxis *axis = &ctrl->axes[control]; - struct InputAxis **bind = DictionarySet(BIND_T, &ctrl->binds, hash, axis); + struct InputAxis **bind = DictionarySet(BIND_T, &ctrl->binds, hash, &axis); if (bind == nullptr) return false; - *bind = axis; - return true; } @@ -97,13 +92,13 @@ void ControllerPoll(struct Controller *ctrl, struct RecordBuffer *recs) struct InputRecord *rec = recs->buf + i; u32 hash = hash_bind(rec->code, rec->type); - struct InputAxis *axis = DictionaryFind(BIND_T, &ctrl->binds, hash); + struct InputAxis **axis = DictionaryFind(BIND_T, &ctrl->binds, hash); if (axis == nullptr) continue; - dispatch_update(axis, rec); - ctrl->pending[ctrl->pending_len++] = axis; + dispatch_update(*axis, rec); + ctrl->pending[ctrl->pending_len++] = *axis; } recs->head.len = 0; diff --git a/source/fumoengine/terminal/terminal.c b/source/fumoengine/terminal/terminal.c index ddae341..3ae0e8b 100644 --- a/source/fumoengine/terminal/terminal.c +++ b/source/fumoengine/terminal/terminal.c @@ -114,9 +114,9 @@ usize TerminalPrint(struct Terminal *term, char *out, usize n) usize len = 7; memcpy(out, "\x1b[H\x1b[0m", 7); + usize i = 0; for (usize y = 0; y < term->hgt; y++) { - for (usize x = 0; x < term->wid; x++) { - usize i = y * term->wid + x; + for (usize x = 0; x < term->wid; x++, i++) { struct Char4 *ch4 = &term->buf[i]; // DEBUG diff --git a/source/fumotris/fumotris.c b/source/fumotris/fumotris.c index ef7cfcc..3a91d4b 100644 --- a/source/fumotris/fumotris.c +++ b/source/fumotris/fumotris.c @@ -2,36 +2,69 @@ struct Fumotris { - struct TetrMap board; - struct TetrMap piece; + struct Tetra board; + struct Tetra piece; + nsec timer; + bool is_ground; }; -void FumotrisStart(void *inst_arg, void *game_arg) +void FumotrisStart(struct FumoInstance *inst, struct Fumotris *fumo) { - struct FumoInstance *inst = inst_arg; - struct Fumotris *game = game_arg; - ControllerBindMulti(&inst->ctrl, BINDS_N, controls_g, codes_g, types_g); - CreateTetrMap(&game->board, 10, 10); - CreateTetrMap(&game->piece, 3, 3); - game->piece.blks = T; + CreateTetra(&fumo->board, 10, 10); + SetTetra(&fumo->piece, T, 3, 3, 0, 0); + fumo->timer = 0; + fumo->is_ground = false; } -void FumotrisUpdate(void *inst_arg, void *game_arg) +void FumotrisUpdate(struct FumoInstance *inst, struct Fumotris *fumo) { - struct FumoInstance *inst = inst_arg; - struct Fumotris *game = game_arg; - + i16 horizontal = 0; if (inst->ctrl.axes[LEFT].is_down) - game->piece.x -= 1; - + horizontal -= 1; if (inst->ctrl.axes[RIGHT].is_down) - game->piece.x += 1; + horizontal += 1; + TetraMove(&fumo->piece, &fumo->board, horizontal, 0); - TetrMapDraw(&game->board, &inst->term); - TetrMapDraw(&game->piece, &inst->term); + + if (inst->ctrl.axes[SOFT_DROP].is_down) + TetraMove(&fumo->piece, &fumo->board, 0, 1); + + + if (inst->ctrl.axes[HARD_DROP].is_down) { + while (TetraMove(&fumo->piece, &fumo->board, 0, 1)); + + fumo->timer = 0; + TetraOverlay(&fumo->piece, &fumo->board); + SetTetra(&fumo->piece, I, 4, 4, 0, 0); + + return; + } + + fumo->timer += inst->frametime; + while (fumo->timer > 5e8) { + fumo->timer -= 5e8; + + if (!TetraMove(&fumo->piece, &fumo->board, 0, 1)) { + if (!fumo->is_ground) { + fumo->is_ground = true; + } else { + TetraOverlay(&fumo->piece, &fumo->board); + SetTetra(&fumo->piece, I, 4, 4, 0, 0); + + fumo->is_ground = false; + } + } + } +} + +void FumotrisDraw(struct FumoInstance *inst, struct Fumotris *fumo) +{ + TetraTerminalClear(&fumo->board, &inst->term); + TetraTerminalDraw(&fumo->board, &inst->term); + TetraTerminalDraw(&fumo->piece, &inst->term); } int main() diff --git a/source/fumotris/fumotris.h b/source/fumotris/fumotris.h index de2d6f8..9b5a9e2 100644 --- a/source/fumotris/fumotris.h +++ b/source/fumotris/fumotris.h @@ -1,6 +1,6 @@ #include "fumocommon.h" #include "fumoengine.h" -#include "tetr.h" +#include "tetra.h" #define BINDS_N 12 @@ -22,6 +22,12 @@ enum FumotrisControls { MOUSE }; +struct TetraTemplate { + u8 *blks; + u16 wid; + u16 hgt; +}; + u16 controls_g[BINDS_N] = { LEFT, @@ -74,44 +80,72 @@ u16 types_g[BINDS_N] = { JOYSTICK }; -u8 I[16] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 1, 1, 1, 1, - 0, 0, 0, 0 +struct TetraTemplate I = { + .blks = &(u8) { + 0, 0, 0, 0, + 0, 0, 0, 0, + 1, 1, 1, 1, + 0, 0, 0, 0 + }, + .wid = 4, + .hgt = 4 }; -u8 O[4] = { - 1, 1, - 1, 1 +struct TetraTemplate O = { + .blks = &(u8) { + 1, 1, + 1, 1 + }, + .wid = 2, + .hgt = 2 }; -u8 T[9] = { - 0, 1, 0, - 1, 1, 1, - 0, 0, 0 +struct TetraTemplate T = { + .blks = &(u8) { + 0, 1, 0, + 1, 1, 1, + 0, 0, 0 + }, + .wid = 3, + .hgt = 3 }; -u8 S[9] = { - 0, 1, 1, - 1, 1, 0, - 0, 0, 0 +struct TetraTemplate S = { + .blks = &(u8) { + 0, 1, 1, + 1, 1, 0, + 0, 0, 0 + }, + .wid = 3, + .hgt = 3 }; -u8 Z[9] = { - 1, 1, 0, - 0, 1, 1, - 0, 0, 0 +struct TetraTemplate Z = { + .blks = &(u8) { + 1, 1, 0, + 0, 1, 1, + 0, 0, 0 + }, + .wid = 3, + .hgt = 3 }; -u8 J[9] = { - 1, 0, 0, - 1, 1, 1, - 0, 0, 0 +struct TetraTemplate J = { + .blks = &(u8) { + 1, 0, 0, + 1, 1, 1, + 0, 0, 0 + }, + .wid = 3, + .hgt = 3 }; -u8 L[9] = { - 0, 0, 1, - 1, 1, 1, - 0, 0, 0 +struct TetraTemplate L = { + .blks = &(u8) { + 0, 0, 1, + 1, 1, 1, + 0, 0, 0 + }, + .wid = 3, + .hgt = 3 }; \ No newline at end of file diff --git a/source/fumotris/tetr.c b/source/fumotris/tetr.c deleted file mode 100644 index e9c514f..0000000 --- a/source/fumotris/tetr.c +++ /dev/null @@ -1,77 +0,0 @@ -#include "tetr.h" - - -bool CreateTetrMap(struct TetrMap *map, usize wid, usize hgt) -{ - u8 *blks = calloc(wid * hgt, sizeof(u8)); - - if (blks == nullptr) - return false; - - *map = (struct TetrMap) { - .wid = wid, - .hgt = hgt, - - .x = 0, - .y = 0, - - .rot = 0, - - .blks = blks - }; - - return true; -} - -void FreeTetrMap(struct TetrMap *map) -{ - free(map->blks); -} - -void TetrMapDraw(struct TetrMap *map, struct Terminal *term) -{ - static const u8f blk_colors[8] = { 8, 14, 11, 13, 10, 9, 12, 3 }; - - for (usize y = 0; y < map->hgt; y++) { - for (usize x = 0; x < map->wid; x++) { - usize map_i = y * map->wid + x; - usize term_i = (y + map->y) * term->wid + (x + map->x) * 2; - - struct Char4 *block = term->buf + term_i; - - if (map->blks[map_i] == 0) { - block[0].ch = '('; - block[1].ch = ')'; - } else { - block[0].ch = '['; - block[1].ch = ']'; - } - - u8 fg = blk_colors[map->blks[map_i]]; - block[0].color.fg = fg; - block[1].color.fg = fg; - } - } -} - -bool TetrCollisionCheck(struct TetrMap *board, struct TetrMap *piece, int dx, int dy) -{ - size_t i = 0; - for (size_t y = piece->y + dy; y < piece->y + piece->hgt + dy; y++) { - for (size_t x = piece->x + dx; x < piece->x + piece->wid + dx; x++) { - if(piece->blks[i] == 0) - goto next; - - if(y >= board->hgt or x >= board->wid) - return false; - - size_t board_i = y * board->wid + x; - if(board->blks[board_i] != 0) - return false; - -next: - i++; - } - } - return true; -} \ No newline at end of file diff --git a/source/fumotris/tetr.h b/source/fumotris/tetr.h deleted file mode 100644 index 419f990..0000000 --- a/source/fumotris/tetr.h +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include - -#include "fumocommon.h" -#include "terminal.h" - - -struct TetrMap { - usize wid; - usize hgt; - - int x; - int y; - - u8f rot; - - u8 *blks; -}; - -bool CreateTetrMap(struct TetrMap *map, usize wid, usize hgt); - -void FreeTetrMap(struct TetrMap *map); - -void TetrMapDraw(struct TetrMap *map, struct Terminal *term); - -bool TetrCollisionCheck(struct TetrMap *board, struct TetrMap *piece, int dx, int dy); \ No newline at end of file diff --git a/source/fumotris/tetra.c b/source/fumotris/tetra.c new file mode 100644 index 0000000..cd823fc --- /dev/null +++ b/source/fumotris/tetra.c @@ -0,0 +1,115 @@ +#include "tetra.h" + + +bool CreateTetra(struct Tetra *map, u16 wid, u16 hgt) +{ + u8 *blks = calloc(wid * hgt, sizeof(u8)); + + if (blks == nullptr) + return false; + + map->blks = blks; + map->wid = wid; + map->hgt = hgt; + + map->x = 0; + map->y = 0; + map->rot = 0; + + return true; +} + +void FreeTetra(struct Tetra *tetra) +{ + free(tetra->blks); +} + +void SetTetra(struct Tetra *map, u8 *blks, u16 wid, u16 hgt, i16 x, i16 y) +{ + map->blks = blks; + map->wid = wid; + map->hgt = hgt; + + map->x = x; + map->y = y; + map->rot = 0; +} + +bool TetraMove(struct Tetra *piece, struct Tetra *board, i16 dx, i16 dy) +{ + if (TetraIsCollision(piece, board, dx, dy)) + return false; + + piece->x += dx; + piece->y += dy; + + return true; +} + +bool TetraIsCollision(struct Tetra *piece, struct Tetra *board, i16 dx, i16 dy) +{ + i16 x_start = piece->x + dx; + i16 y_start = piece->y + dy; + + usize i = 0; + for (i16 y = y_start; y < y_start + piece->hgt; y++) { + for (i16 x = x_start; x < x_start + piece->wid; x++, i++) { + if(piece->blks[i] == 0) + continue; + + if(x < 0 or x >= board->wid or y < 0 or y >= board->hgt) + return true; + + if(board->blks[board->wid * y + x] != 0) + return true; + } + } + + return false; +} + +void TetraTerminalClear(struct Tetra *board, struct Terminal *term) +{ + for (usize i = 0; i < board->wid * board->hgt; i++) { + struct Char4 *block = term->buf + i * 2; + + block[0] = (struct Char4) { .ch = '(', .color.fg = 8 }; + block[1] = (struct Char4) { .ch = ')', .color.fg = 8 }; + } +} + +void TetraTerminalDraw(struct Tetra *tetra, struct Terminal *term) +{ + static const u8f blk_colors[8] = { 8, 14, 11, 13, 10, 9, 12, 3 }; + + usize i = 0; + for (usize y = 0; y < tetra->hgt; y++) { + for (usize x = 0; x < tetra->wid; x++, i++) { + if (tetra->blks[i] == 0) + continue; + + usize term_i = (y + tetra->y) * term->wid + (x + tetra->x) * 2; + struct Char4 *block = term->buf + term_i; + + u8 fg = blk_colors[tetra->blks[i]]; + block[0] = (struct Char4) { .ch = '[', .color.fg = fg }; + block[1] = (struct Char4) { .ch = ']', .color.fg = fg }; + } + } +} + +void TetraOverlay(struct Tetra *piece, struct Tetra *board) +{ + usize i = 0; + for (usize y = piece->y; y < piece->y + piece->hgt; y++) { + for (usize x = piece->x; x < piece->x + piece->wid; x++, i++) { + if(piece->blks[i] == 0) + continue; + + if(x < 0 or x >= board->wid or y < 0 or y >= board->hgt) + continue; + + board->blks[board->wid * y + x] = piece->blks[i]; + } + } +} \ No newline at end of file diff --git a/source/fumotris/tetra.h b/source/fumotris/tetra.h new file mode 100644 index 0000000..800bbd3 --- /dev/null +++ b/source/fumotris/tetra.h @@ -0,0 +1,33 @@ +#include +#include +#include "fumocommon.h" +#include "terminal.h" + + +struct Tetra { + u8 *blks; + + u16 wid; + u16 hgt; + + i16 x; + i16 y; + + u8f rot; +}; + +bool CreateTetra(struct Tetra *map, u16 wid, u16 hgt); + +void FreeTetra(struct Tetra *map); + +void SetTetra(struct Tetra *map, u8 *blks, u16 wid, u16 hgt, i16 x, i16 y); + +void TetraTerminalClear(struct Tetra *board, struct Terminal *term); + +void TetraTerminalDraw(struct Tetra *map, struct Terminal *term); + +bool TetraMove(struct Tetra *piece, struct Tetra *board, i16 dx, i16 dy); + +bool TetraIsCollision(struct Tetra *piece, struct Tetra *board, i16 dx, i16 dy); + +void TetraOverlay(struct Tetra *piece, struct Tetra *board); \ No newline at end of file