From 2135217843b66da2b96f1be45c0ea5fa402a8b58 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Fri, 28 Mar 2025 11:23:13 -0500 Subject: [PATCH] New basic console --- src/CMakeLists.txt | 5 +- src/dusk/CMakeLists.txt | 6 +- src/dusk/assert/assert.h | 2 +- src/dusk/{display => console}/CMakeLists.txt | 9 +- src/dusk/console/console.c | 224 ++++++++++++++++++ src/dusk/console/console.h | 95 ++++++++ src/dusk/console/consolecmd.c | 27 +++ src/dusk/console/consolecmd.h | 38 +++ src/dusk/console/consoledefs.h | 21 ++ src/dusk/console/consolevar.c | 64 +++++ src/dusk/console/consolevar.h | 65 +++++ src/dusk/display/displaydefs.h | 9 - src/dusk/display/scene.c | 65 ----- src/dusk/display/scene.h | 58 ----- src/dusk/display/tileset.c | 34 --- src/dusk/display/tileset.h | 53 ----- src/dusk/display/tilesetdefs.h | 17 -- src/dusk/dusk.h | 1 + .../{overworld/map => error}/CMakeLists.txt | 7 +- src/dusk/error/error.c | 45 ++++ src/dusk/error/error.h | 50 ++++ src/dusk/game.c | 31 --- src/dusk/game.h | 35 --- src/dusk/input.c | 37 --- src/dusk/input.h | 71 ------ src/dusk/overworld/CMakeLists.txt | 14 -- src/dusk/overworld/entity/entity.c | 150 ------------ src/dusk/overworld/entity/entity.h | 89 ------- src/dusk/overworld/entity/facing.c | 65 ----- src/dusk/overworld/entity/facing.h | 50 ---- src/dusk/overworld/entity/npc.c | 19 -- src/dusk/overworld/entity/npc.h | 37 --- src/dusk/overworld/entity/player.c | 33 --- src/dusk/overworld/entity/player.h | 29 --- src/dusk/overworld/map/map.c | 69 ------ src/dusk/overworld/map/map.h | 82 ------- src/dusk/overworld/map/tile.c | 19 -- src/dusk/overworld/map/tile.h | 26 -- src/dusk/overworld/overworld.c | 49 ---- src/dusk/overworld/overworld.h | 57 ----- src/dusk/overworld/overworlddefs.h | 16 -- src/dusk/server/server.h | 19 ++ src/dusk/ui/uimenu.c | 55 ----- src/dusk/ui/uimenu.h | 69 ------ src/dusk/util/CMakeLists.txt | 7 +- src/dusk/util/math.c | 24 -- src/dusk/util/math.h | 48 ---- src/dusk/util/memory.c | 8 + src/dusk/util/memory.h | 11 +- src/dusk/util/random.c | 26 -- src/dusk/util/random.h | 32 --- src/dusk/util/string.c | 50 ++++ src/dusk/util/string.h | 55 +++++ .../entity => dusktest}/CMakeLists.txt | 18 +- src/dusktest/main.c | 39 +++ 55 files changed, 838 insertions(+), 1496 deletions(-) rename src/dusk/{display => console}/CMakeLists.txt (79%) create mode 100644 src/dusk/console/console.c create mode 100644 src/dusk/console/console.h create mode 100644 src/dusk/console/consolecmd.c create mode 100644 src/dusk/console/consolecmd.h create mode 100644 src/dusk/console/consoledefs.h create mode 100644 src/dusk/console/consolevar.c create mode 100644 src/dusk/console/consolevar.h delete mode 100644 src/dusk/display/displaydefs.h delete mode 100644 src/dusk/display/scene.c delete mode 100644 src/dusk/display/scene.h delete mode 100644 src/dusk/display/tileset.c delete mode 100644 src/dusk/display/tileset.h delete mode 100644 src/dusk/display/tilesetdefs.h rename src/dusk/{overworld/map => error}/CMakeLists.txt (84%) create mode 100644 src/dusk/error/error.c create mode 100644 src/dusk/error/error.h delete mode 100644 src/dusk/game.c delete mode 100644 src/dusk/game.h delete mode 100644 src/dusk/input.c delete mode 100644 src/dusk/input.h delete mode 100644 src/dusk/overworld/CMakeLists.txt delete mode 100644 src/dusk/overworld/entity/entity.c delete mode 100644 src/dusk/overworld/entity/entity.h delete mode 100644 src/dusk/overworld/entity/facing.c delete mode 100644 src/dusk/overworld/entity/facing.h delete mode 100644 src/dusk/overworld/entity/npc.c delete mode 100644 src/dusk/overworld/entity/npc.h delete mode 100644 src/dusk/overworld/entity/player.c delete mode 100644 src/dusk/overworld/entity/player.h delete mode 100644 src/dusk/overworld/map/map.c delete mode 100644 src/dusk/overworld/map/map.h delete mode 100644 src/dusk/overworld/map/tile.c delete mode 100644 src/dusk/overworld/map/tile.h delete mode 100644 src/dusk/overworld/overworld.c delete mode 100644 src/dusk/overworld/overworld.h delete mode 100644 src/dusk/overworld/overworlddefs.h create mode 100644 src/dusk/server/server.h delete mode 100644 src/dusk/ui/uimenu.c delete mode 100644 src/dusk/ui/uimenu.h delete mode 100644 src/dusk/util/math.c delete mode 100644 src/dusk/util/math.h delete mode 100644 src/dusk/util/random.c delete mode 100644 src/dusk/util/random.h create mode 100644 src/dusk/util/string.c create mode 100644 src/dusk/util/string.h rename src/{dusk/overworld/entity => dusktest}/CMakeLists.txt (52%) create mode 100644 src/dusktest/main.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 668a002..84aeb03 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,6 +3,5 @@ # This software is released under the MIT License. # https://opensource.org/licenses/MIT -add_subdirectory(dusk) -add_subdirectory(duskgl) -add_subdirectory(duskglfw) \ No newline at end of file +add_subdirectory(dusktest) +add_subdirectory(dusk) \ No newline at end of file diff --git a/src/dusk/CMakeLists.txt b/src/dusk/CMakeLists.txt index 24e5194..bdb3144 100644 --- a/src/dusk/CMakeLists.txt +++ b/src/dusk/CMakeLists.txt @@ -17,12 +17,10 @@ target_include_directories(${DUSK_TARGET_NAME} # Sources target_sources(${DUSK_TARGET_NAME} PRIVATE - game.c - input.c ) # Subdirs add_subdirectory(assert) -add_subdirectory(display) -add_subdirectory(overworld) +add_subdirectory(console) +add_subdirectory(error) add_subdirectory(util) \ No newline at end of file diff --git a/src/dusk/assert/assert.h b/src/dusk/assert/assert.h index 090d38f..b7d9cf8 100644 --- a/src/dusk/assert/assert.h +++ b/src/dusk/assert/assert.h @@ -122,7 +122,7 @@ void assertMemoryRangeMatchesImpl( #define assertDeprecated(message) \ assertDeprecatedImpl(__FILE__, __LINE__, message) -#define assertStrLen(str, len, message) \ +#define assertStrLenMax(str, len, message) \ assertTrue(strlen(str) <= len, message) #define assertStrLenMin(str, len, message) \ diff --git a/src/dusk/display/CMakeLists.txt b/src/dusk/console/CMakeLists.txt similarity index 79% rename from src/dusk/display/CMakeLists.txt rename to src/dusk/console/CMakeLists.txt index 4f9d20f..c4da6c5 100644 --- a/src/dusk/display/CMakeLists.txt +++ b/src/dusk/console/CMakeLists.txt @@ -6,8 +6,7 @@ # Sources target_sources(${DUSK_TARGET_NAME} PRIVATE - scene.c - tileset.c -) - -# Subdirs \ No newline at end of file + console.c + consolecmd.c + consolevar.c +) \ No newline at end of file diff --git a/src/dusk/console/console.c b/src/dusk/console/console.c new file mode 100644 index 0000000..0141f59 --- /dev/null +++ b/src/dusk/console/console.c @@ -0,0 +1,224 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "console.h" +#include "assert/assert.h" +#include "util/memory.h" +#include "util/string.h" + +console_t CONSOLE; + +void consoleInit() { + memoryZero(&CONSOLE, sizeof(console_t)); + + // Register the get and set command. + CONSOLE.cmdGet = consoleRegCmd("get", consoleCmdGet); + CONSOLE.cmdSet = consoleRegCmd("set", consoleCmdSet); +} + +consolecmd_t * consoleRegCmd(const char_t *name, consolecmdfunc_t function) { + consolecmd_t *cmd = &CONSOLE.commands[CONSOLE.commandCount++]; + consoleCmdInit(cmd, name, function); + return cmd; +} + +consolevar_t * consoleRegVar( + const char_t *name, + const char_t *value, + consolevarchanged_t event +) { + consolevar_t *var = &CONSOLE.variables[CONSOLE.variableCount++]; + consoleVarInitListener(var, name, value, event); + return var; +} + +void consolePrint(const char_t *message, ...) { + char_t buffer[CONSOLE_LINE_MAX]; + va_list args; + va_start(args, message); + size_t len = vsnprintf(buffer, CONSOLE_LINE_MAX, message, args); + va_end(args); + + assertTrue(len < CONSOLE_LINE_MAX, "Message is too long."); + + // Move all lines back + memoryMove( + CONSOLE.line[0], + CONSOLE.line[1], + (CONSOLE_HISTORY_MAX - 1) * CONSOLE_LINE_MAX + ); + + // Copy the new line + memoryCopy( + CONSOLE.line[CONSOLE_HISTORY_MAX - 1], + buffer, + len + 1 + ); + printf("%s\n", buffer); +} + +void consoleExec(const char_t *line) { + assertNotNull(line, "line must not be NULL"); + assertTrue( + CONSOLE.execBufferCount < CONSOLE_EXEC_BUFFER_MAX, + "Too many commands in the buffer." + ); + + if(line[0] == '\0') return; + + char_t buffer[CONSOLE_LINE_MAX + 1]; + size_t i = 0, j = 0; + char_t c; + + do { + c = line[i++]; + + // Handle command separation by semicolon or end of line + if(c == ';' || c == '\0') { + // Null-terminate the current command and trim whitespace + buffer[j] = '\0'; + stringTrim(buffer); + + // Skip empty commands + if(buffer[0] == '\0') { + j = 0; + continue; + } + + // Ensure the exec buffer is not full + assertTrue( + CONSOLE.execBufferCount < CONSOLE_EXEC_BUFFER_MAX, + "Too many commands in the buffer." + ); + + // Create a new command execution + consolecmdexec_t *exec = &CONSOLE.execBuffer[CONSOLE.execBufferCount++]; + memoryZero(exec, sizeof(consolecmdexec_t)); + + // Parse command and arguments + char_t *token = strtok(buffer, " "); + while(token != NULL) { + assertTrue( + exec->argc < CONSOLE_CMD_ARGC_MAX, + "Too many arguments in the command." + ); + stringCopy(exec->argv[exec->argc++], token, CONSOLE_LINE_MAX); + token = strtok(NULL, " "); + } + + // First, see if there's a matching command. + for(uint32_t k = 0; k < CONSOLE.commandCount; k++) { + if(stringCompare(CONSOLE.commands[k].name, exec->argv[0]) != 0) { + continue; + } + exec->cmd = &CONSOLE.commands[k]; + } + + // If match found continue + if(exec->cmd != NULL) { + j = 0; + continue; + } + + // If no match found, see if there's a matching variable. + consolevar_t *var = NULL; + + for(uint32_t k = 0; k < CONSOLE.variableCount; k++) { + if(stringCompare(CONSOLE.variables[k].name, exec->argv[0]) != 0) { + continue; + } + + var = &CONSOLE.variables[k]; + break; + } + + // If no variable found, error out. + if(!var) { + consolePrint("Error: Command/Variable '%s' not found.", exec->argv[0]); + CONSOLE.execBufferCount--; + j = 0; + continue; + } + + // Found a matching variable, we basically change this entire command + // to a get or a set. Arguments are reversed so they aren't stepped over + if(exec->argc == 1) { + exec->cmd = CONSOLE.cmdGet; + exec->argc = 2; + stringCopy(exec->argv[1], var->name, CONSOLE_LINE_MAX); + stringCopy(exec->argv[0], CONSOLE.cmdGet->name, CONSOLE_LINE_MAX); + } else { + exec->cmd = CONSOLE.cmdSet; + exec->argc = 3; + stringCopy(exec->argv[2], exec->argv[1], CONSOLE_LINE_MAX); + stringCopy(exec->argv[1], var->name, CONSOLE_LINE_MAX); + stringCopy(exec->argv[0], CONSOLE.cmdSet->name, CONSOLE_LINE_MAX); + } + + j = 0; + continue; + } + + if(j >= CONSOLE_LINE_MAX) { + assertTrue(false, "Command exceeds maximum length."); + } + + buffer[j++] = c; // Accumulate characters into the buffer + } while(c != '\0'); +} + +void consoleProcess() { + for(uint32_t i = 0; i < CONSOLE.execBufferCount; i++) { + consolecmdexec_t *exec = &CONSOLE.execBuffer[i]; + + assertTrue( + exec->argc > 0, + "Command execution has no arguments." + ); + assertNotNull( + exec->cmd, + "Command execution has no command." + ); + + exec->cmd->function(exec); + } + + // Clear the exec buffer + CONSOLE.execBufferCount = 0; +} + +void consoleCmdGet(const consolecmdexec_t *exec) { + assertTrue( + exec->argc >= 2, + "get command requires 1 argument." + ); + + for(uint32_t i = 0; i < CONSOLE.variableCount; i++) { + consolevar_t *var = &CONSOLE.variables[i]; + if(stringCompare(var->name, exec->argv[1]) != 0) continue; + consolePrint("%s", var->value); + return; + } + + consolePrint("Error: Variable '%s' not found.", exec->argv[1]); +} + +void consoleCmdSet(const consolecmdexec_t *exec) { + assertTrue( + exec->argc >= 3, + "set command requires 2 arguments." + ); + + for(uint32_t i = 0; i < CONSOLE.variableCount; i++) { + consolevar_t *var = &CONSOLE.variables[i]; + if(stringCompare(var->name, exec->argv[1]) != 0) continue; + consoleVarSetValue(var, exec->argv[2]); + return; + } + + consolePrint("Error: Variable '%s' not found.", exec->argv[1]); +} \ No newline at end of file diff --git a/src/dusk/console/console.h b/src/dusk/console/console.h new file mode 100644 index 0000000..55875dd --- /dev/null +++ b/src/dusk/console/console.h @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "consolevar.h" +#include "consolecmd.h" + +typedef struct { + consolecmd_t commands[CONSOLE_COMMANDS_MAX]; + uint32_t commandCount; + + consolevar_t variables[CONSOLE_VARIABLES_MAX]; + uint32_t variableCount; + + char_t line[CONSOLE_HISTORY_MAX][CONSOLE_LINE_MAX]; + + consolecmdexec_t execBuffer[CONSOLE_EXEC_BUFFER_MAX]; + uint32_t execBufferCount; + + consolecmd_t *cmdGet; + consolecmd_t *cmdSet; +} console_t; + +extern console_t CONSOLE; + +/** + * Initializes the console. + */ +void consoleInit(); + +/** + * Registers a console command. + * + * @param name The name of the command. + * @param function The function to execute when the command is called. + * @return The registered command. + */ +consolecmd_t * consoleRegCmd(const char_t *name, consolecmdfunc_t function); + +/** + * Registers a console variable. + * + * @param name The name of the variable. + * @param value The initial value of the variable. + * @param event The event to register. + * @return The registered variable. + */ +consolevar_t * consoleRegVar( + const char_t *name, + const char_t *value, + consolevarchanged_t event +); + +/** + * Sets the value of a console variable. + * + * @param name The name of the variable. + * @param value The new value of the variable. + */ +void consolePrint( + const char_t *message, + ... +); + +/** + * Executes a console command. + * + * @param line The line to execute. + */ +void consoleExec(const char_t *line); + +/** + * Processes the console's pending commands. + */ +void consoleProcess(); + +/** + * Gets the value of a console variable. + * + * @param name The name of the variable. + * @return The value of the variable. + */ +void consoleCmdGet(const consolecmdexec_t *exec); + +/** + * Sets the value of a console variable. + * + * @param name The name of the variable. + * @param value The new value of the variable. + */ +void consoleCmdSet(const consolecmdexec_t *exec); \ No newline at end of file diff --git a/src/dusk/console/consolecmd.c b/src/dusk/console/consolecmd.c new file mode 100644 index 0000000..f2923b9 --- /dev/null +++ b/src/dusk/console/consolecmd.c @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "consolecmd.h" +#include "assert/assert.h" +#include "util/memory.h" +#include "util/string.h" + +void consoleCmdInit( + consolecmd_t *cmd, + const char_t *name, + consolecmdfunc_t function +) { + assertNotNull(cmd, "Command is NULL."); + assertNotNull(name, "Name is NULL."); + assertNotNull(function, "Function is NULL."); + assertStrLenMin(name, 1, "Name is empty."); + assertStrLenMax(name, CONSOLE_CMD_NAME_MAX, "Name is too long."); + + memoryZero(cmd, sizeof(consolecmd_t)); + stringCopy(cmd->name, name, CONSOLE_CMD_NAME_MAX); + cmd->function = function; +} \ No newline at end of file diff --git a/src/dusk/console/consolecmd.h b/src/dusk/console/consolecmd.h new file mode 100644 index 0000000..04ec31c --- /dev/null +++ b/src/dusk/console/consolecmd.h @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" +#include "consoledefs.h" + +typedef struct consolecmd_s consolecmd_t; + +typedef struct { + const consolecmd_t *cmd; + uint32_t argc; + char_t argv[CONSOLE_CMD_ARGC_MAX][CONSOLE_LINE_MAX]; +} consolecmdexec_t; + +typedef void (*consolecmdfunc_t)(const consolecmdexec_t *exec); + +typedef struct consolecmd_s { + char_t name[CONSOLE_CMD_NAME_MAX + 1]; + consolecmdfunc_t function; +} consolecmd_t; + +/** + * Initializes a console command. + * + * @param cmd Pointer to the console command. + * @param name The name of the command. + * @param function The function to execute when the command is called. + */ +void consoleCmdInit( + consolecmd_t *cmd, + const char_t *name, + consolecmdfunc_t function +); \ No newline at end of file diff --git a/src/dusk/console/consoledefs.h b/src/dusk/console/consoledefs.h new file mode 100644 index 0000000..6e6df0d --- /dev/null +++ b/src/dusk/console/consoledefs.h @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once + +#define CONSOLE_CMD_NAME_MAX 32 +#define CONSOLE_CMD_ARGC_MAX 16 + +#define CONSOLE_COMMANDS_MAX 128 +#define CONSOLE_VARIABLES_MAX 128 +#define CONSOLE_LINE_MAX 256 +#define CONSOLE_HISTORY_MAX 32 +#define CONSOLE_EXEC_BUFFER_MAX 16 + +#define CONSOLE_VAR_NAME_MAX 32 +#define CONSOLE_VAR_VALUE_MAX 128 +#define CONSOLE_VAR_EVENTS_MAX 8 \ No newline at end of file diff --git a/src/dusk/console/consolevar.c b/src/dusk/console/consolevar.c new file mode 100644 index 0000000..e126c89 --- /dev/null +++ b/src/dusk/console/consolevar.c @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "consolevar.h" +#include "assert/assert.h" +#include "util/memory.h" +#include "util/string.h" + +void consoleVarInit( + consolevar_t *var, + const char_t *name, + const char_t *value +) { + assertNotNull(var, "var must not be NULL"); + assertNotNull(name, "name must not be NULL"); + assertNotNull(value, "value must not be NULL"); + + assertStrLenMin(name, 1, "name must not be empty"); + assertStrLenMax(name, CONSOLE_VAR_NAME_MAX, "name is too long"); + assertStrLenMax(value, CONSOLE_VAR_VALUE_MAX, "value is too long"); + + memoryZero(var, sizeof(consolevar_t)); + stringCopy(var->name, name, CONSOLE_VAR_NAME_MAX); + stringCopy(var->value, value, CONSOLE_VAR_VALUE_MAX); +} + +void consoleVarInitListener( + consolevar_t *var, + const char_t *name, + const char_t *value, + consolevarchanged_t event +) { + consoleVarInit(var, name, value); + if(event) consoleVarListen(var, event); +} + +void consoleVarSetValue(consolevar_t *var, const char_t *value) { + assertNotNull(var, "var must not be NULL"); + assertNotNull(value, "value must not be NULL"); + assertStrLenMax(value, CONSOLE_VAR_VALUE_MAX, "value is too long"); + + stringCopy(var->value, value, CONSOLE_VAR_VALUE_MAX); + + uint8_t i = 0; + while (i < var->eventCount) { + var->events[i](var); + i++; + } +} + +void consoleVarListen(consolevar_t *var, consolevarchanged_t event) { + assertNotNull(var, "var must not be NULL"); + assertNotNull(event, "event must not be NULL"); + assertTrue( + var->eventCount < CONSOLE_VAR_EVENTS_MAX, + "Event count is too high" + ); + var->events[var->eventCount++] = event; +} + diff --git a/src/dusk/console/consolevar.h b/src/dusk/console/consolevar.h new file mode 100644 index 0000000..de8ccdd --- /dev/null +++ b/src/dusk/console/consolevar.h @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" +#include "consoledefs.h" + +typedef struct consolevar_s consolevar_t; + +typedef void (*consolevarchanged_t)(const consolevar_t *var); + +typedef struct consolevar_s { + char_t name[CONSOLE_VAR_NAME_MAX + 1]; + char_t value[CONSOLE_VAR_VALUE_MAX + 1]; + consolevarchanged_t events[CONSOLE_VAR_EVENTS_MAX]; + uint8_t eventCount; +} consolevar_t; + +/** + * Initializes a console variable. + * + * @param var Pointer to the console variable. + * @param name The name of the variable. + * @param value The initial value of the variable. + */ +void consoleVarInit( + consolevar_t *var, + const char_t *name, + const char_t *value +); + +/** + * Initializes a console variable with a listener. + * + * @param var Pointer to the console variable. + * @param name The name of the variable. + * @param value The initial value of the variable. + * @param event The event to register. + */ +void consoleVarInitListener( + consolevar_t *var, + const char_t *name, + const char_t *value, + consolevarchanged_t event +); + +/** + * Sets the value of a console variable. + * + * @param var Pointer to the console variable. + * @param value The new value of the variable. + */ +void consoleVarSetValue(consolevar_t *var, const char_t *value); + +/** + * Registers an event to be called when the value of a console variable changes. + * + * @param var Pointer to the console variable. + * @param event The event to register. + */ +void consoleVarListen(consolevar_t *var, consolevarchanged_t event); \ No newline at end of file diff --git a/src/dusk/display/displaydefs.h b/src/dusk/display/displaydefs.h deleted file mode 100644 index df4906e..0000000 --- a/src/dusk/display/displaydefs.h +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#define SCREEN_WIDTH 320 -#define SCREEN_HEIGHT 240 \ No newline at end of file diff --git a/src/dusk/display/scene.c b/src/dusk/display/scene.c deleted file mode 100644 index 6a37a55..0000000 --- a/src/dusk/display/scene.c +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "scene.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "overworld/overworld.h" - -scenetypecallback_t SCENE_CALLBACKS[] = { - // SCENE_TYPE_INITIAL - { NULL, NULL, NULL, NULL, NULL }, - - // SCENE_TYPE_OVERWORLD - { - overworldInit, - overworldSceneInit, - overworldSceneDeinit, - overworldUpdate, - overworldRender - }, -}; - -scene_t SCENE; - -void sceneInit() { - memoryZero(&SCENE, sizeof(scene_t)); - - for(uint8_t i = 0; i < SCENE_TYPE_COUNT; i++) { - if(SCENE_CALLBACKS[i].onInit) SCENE_CALLBACKS[i].onInit(); - } - - sceneSet(SCENE_TYPE_OVERWORLD);// Testing -} - -void sceneUpdate() { - assertTrue(SCENE.current < SCENE_TYPE_COUNT, "Invalid Scene Type"); - - if(SCENE.next != SCENE.current) { - SCENE.current = SCENE.next; - if(SCENE_CALLBACKS[SCENE.current].onActive) { - SCENE_CALLBACKS[SCENE.current].onActive(); - } - } - - if(SCENE_CALLBACKS[SCENE.current].onUpdate) { - SCENE_CALLBACKS[SCENE.current].onUpdate(); - } -} - -void sceneRender() { - assertTrue(SCENE.current < SCENE_TYPE_COUNT, "Invalid Scene Type"); - - if(SCENE_CALLBACKS[SCENE.current].onRender) { - SCENE_CALLBACKS[SCENE.current].onRender(); - } -} - -void sceneSet(const scenetype_t scene) { - assertTrue(SCENE.next < SCENE_TYPE_COUNT, "Invalid Scene Type"); - SCENE.next = scene; -} \ No newline at end of file diff --git a/src/dusk/display/scene.h b/src/dusk/display/scene.h deleted file mode 100644 index b277503..0000000 --- a/src/dusk/display/scene.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef enum { - SCENE_TYPE_INITIAL, - SCENE_TYPE_OVERWORLD, -} scenetype_t; - -#define SCENE_TYPE_COUNT 2 - -typedef struct { - scenetype_t current; - scenetype_t next; -} scene_t; - -typedef struct { - void (*onInit)(); - void (*onActive)(); - void (*onInactive)(); - void (*onUpdate)(); - void (*onRender)(); -} scenetypecallback_t; - -extern scene_t SCENE; - -/** - * Initializes the scene system. - */ -void sceneInit(); - -/** - * Updates the scene system. - */ -void sceneUpdate(); - -/** - * Renders the scene system. - * - * Scene rendering is really just an abstraction meant to simplify things for - * the render host. It is not REQUIRED to be called at all and is not actually - * implemented in the dusk dir itself, it is overriden somewhere within the - * render host. - */ -void sceneRender(); - -/** - * Sets the current scene. This will happen at the start of the next tick. - * - * @param scene The scene to set. - */ -void sceneSet(const scenetype_t scene); \ No newline at end of file diff --git a/src/dusk/display/tileset.c b/src/dusk/display/tileset.c deleted file mode 100644 index 2db646c..0000000 --- a/src/dusk/display/tileset.c +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "tileset.h" - -tileset_t TILESETS[TILESET_COUNT] = { - // TILESET_NULL - { 0, 0 }, - // TILESET_FONT - { 16, 14 } -}; - -tilesetid_t TILESET_SLOTS[TILESET_SLOT_COUNT] = { - TILESET_NULL, - TILESET_NULL, - TILESET_NULL, - TILESET_NULL -}; - -uint8_t tilesetGetSlot(const tilesetid_t id) { - uint8_t i = 0; - do { - if(TILESET_SLOTS[i] == id) return i; - } while(++i < TILESET_SLOT_COUNT); - return 0xFF; -} - -bool_t tilesetIsBound(const tilesetid_t id) { - return tilesetGetSlot(id) != 0xFF; -} \ No newline at end of file diff --git a/src/dusk/display/tileset.h b/src/dusk/display/tileset.h deleted file mode 100644 index 0cfbe5f..0000000 --- a/src/dusk/display/tileset.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" -#include "tilesetdefs.h" - -typedef enum { - TILESET_NULL, - TILESET_FONT -} tilesetid_t; - -#define TILESET_COUNT 2 - -typedef struct { - uint8_t columns; - uint8_t rows; -} tileset_t; - -extern tileset_t TILESETS[]; -extern tilesetid_t TILESET_SLOTS[]; - -/** - * Binds a tileset to a slot. The host can also use this to say load a texture, - * or upload to VRAM. - * - * This does not guarantee anything on the game side, rendering is responsible - * for handling anything visual. - * - * @param id The tileset to bind. - * @param slot The slot to bind the tileset to. - */ -void tilesetBind(const tilesetid_t id, const uint8_t slot); - -/** - * Gets the slot that a tileset is bound to, or 0xFF if not bound. - * - * @param id The tileset to check. - * @return The slot the tileset is bound to, or 0xFF if not bound. - */ -uint8_t tilesetGetSlot(const tilesetid_t id); - -/** - * Checks if a tileset is bound to a slot. - * - * @param id The tileset to check. - * @return TRUE if the tileset is bound, FALSE otherwise. - */ -bool_t tilesetIsBound(const tilesetid_t id); \ No newline at end of file diff --git a/src/dusk/display/tilesetdefs.h b/src/dusk/display/tilesetdefs.h deleted file mode 100644 index ac47d3c..0000000 --- a/src/dusk/display/tilesetdefs.h +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#define TILESET_SLOT_0 0 -#define TILESET_SLOT_1 1 -#define TILESET_SLOT_2 2 -#define TILESET_SLOT_3 3 - -#define TILESET_SLOT_UI TILESET_SLOT_0 -#define TILESET_SLOT_ENTITIES TILESET_SLOT_1 -#define TILESET_SLOT_MAP TILESET_SLOT_2 - -#define TILESET_SLOT_COUNT 4 \ No newline at end of file diff --git a/src/dusk/dusk.h b/src/dusk/dusk.h index b4e1857..ca6cdd6 100644 --- a/src/dusk/dusk.h +++ b/src/dusk/dusk.h @@ -14,6 +14,7 @@ #include #include #include +#include typedef bool bool_t; typedef char char_t; diff --git a/src/dusk/overworld/map/CMakeLists.txt b/src/dusk/error/CMakeLists.txt similarity index 84% rename from src/dusk/overworld/map/CMakeLists.txt rename to src/dusk/error/CMakeLists.txt index 6a46430..b246fdb 100644 --- a/src/dusk/overworld/map/CMakeLists.txt +++ b/src/dusk/error/CMakeLists.txt @@ -6,8 +6,5 @@ # Sources target_sources(${DUSK_TARGET_NAME} PRIVATE - tile.c - map.c -) - -# Subdirs \ No newline at end of file + error.c +) \ No newline at end of file diff --git a/src/dusk/error/error.c b/src/dusk/error/error.c new file mode 100644 index 0000000..f5193f1 --- /dev/null +++ b/src/dusk/error/error.c @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "error.h" + +errorstack_t ERROR_STACK; + +errorret_t error(const char_t *message, ...) { + return errorCode(1, message); +} + +errorret_t errorCode(const errorret_t code, const char_t *message, ...) { + if(ERROR_STACK.code != ERROR_OK) { + snprintf( + ERROR_STACK.message, + ERROR_STACK_SIZE, + "Multiple errors encountered." + ); + errorPrint(); + } + + va_list args; + va_start(args, message); + vsnprintf(ERROR_STACK.message, ERROR_STACK_SIZE, message, args); + va_end(args); + + return ERROR_STACK.code = code; +} + +bool_t errorCheck() { + return ERROR_STACK.code != ERROR_OK; +} + +errorret_t errorPrint() { + if(ERROR_STACK.code == ERROR_OK) return ERROR_OK; + + printf("Error: %s\n", ERROR_STACK.message); + errorret_t code = ERROR_STACK.code; + ERROR_STACK.code = ERROR_OK; + return code; +} \ No newline at end of file diff --git a/src/dusk/error/error.h b/src/dusk/error/error.h new file mode 100644 index 0000000..9901c4b --- /dev/null +++ b/src/dusk/error/error.h @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +typedef int32_t errorret_t; +#define ERROR_OK 0 + +#define ERROR_STACK_SIZE 256 + +typedef struct { + char_t message[ERROR_STACK_SIZE + 1]; + errorret_t code; +} errorstack_t; + +extern errorstack_t ERROR_STACK; + +/** + * Pushes an error message to the error stack. + * + * @param message Message to push to the error stack. + * @param ... Arguments to format the message with. + */ +errorret_t error(const char_t *message, ...); + +/** + * Pushes an error message to the error stack with a given error code. + * + * @param code Error code to push to the error stack. + * @param message Message to push to the error stack. + * @param ... Arguments to format the message with. + */ +errorret_t errorCode(const errorret_t code, const char_t *message, ...); + +/** + * Checks if an error has been pushed to the error stack. + * + * @return True if an error has been pushed to the error stack. + */ +bool_t errorCheck(); + +/** + * Prints the error stack to the console. This also clears the error stack. + */ +errorret_t errorPrint(); \ No newline at end of file diff --git a/src/dusk/game.c b/src/dusk/game.c deleted file mode 100644 index a57acf3..0000000 --- a/src/dusk/game.c +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "game.h" -#include "input.h" -#include "display/scene.h" -#include "util/memory.h" - -game_t GAME; - -void gameInit() { - memoryZero(&GAME, sizeof(game_t)); - - inputInit(); - sceneInit(); -} - -void gameUpdate() { - GAME.tick++; - - inputUpdate(); - sceneUpdate(); -} - -void gameDispose() { - -} \ No newline at end of file diff --git a/src/dusk/game.h b/src/dusk/game.h deleted file mode 100644 index 94b8b50..0000000 --- a/src/dusk/game.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -#define GAME_TICK_RATE 60 - -typedef struct { - uint32_t tick; -} game_t; - -extern game_t GAME; - -/** - * Initializes the game. - */ -void gameInit(); - -/** - * Updates the game. The game is setup to handle "frames", aka 1/60th of a - * second. Typically more modern engines would use floats to tick game engine - * by a semi random delta time, but this engine is intended to work on really - * weak machines so we take the simple approach. - */ -void gameUpdate(); - -/** - * Disposes the game. - */ -void gameDispose(); \ No newline at end of file diff --git a/src/dusk/input.c b/src/dusk/input.c deleted file mode 100644 index b773f5d..0000000 --- a/src/dusk/input.c +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "input.h" - -inputstate_t INPUT_CURRENT; -inputstate_t INPUT_LAST_FRAME; - -void inputInit() { - INPUT_CURRENT = 0; - INPUT_LAST_FRAME = 0; -} - -void inputUpdate() { - INPUT_LAST_FRAME = INPUT_CURRENT; - INPUT_CURRENT = inputPlatformState(); -} - -bool_t inputWasPressed(const inputstate_t state) { - return (INPUT_LAST_FRAME & state) == 0 && (INPUT_CURRENT & state) != 0; -} - -bool_t inputWasReleased(const inputstate_t state) { - return (INPUT_LAST_FRAME & state) != 0 && (INPUT_CURRENT & state) == 0; -} - -bool_t inputIsDown(const inputstate_t state) { - return (INPUT_CURRENT & state) != 0; -} - -bool_t inputIsUp(const inputstate_t state) { - return (INPUT_CURRENT & state) == 0; -} \ No newline at end of file diff --git a/src/dusk/input.h b/src/dusk/input.h deleted file mode 100644 index 9682ae0..0000000 --- a/src/dusk/input.h +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef uint16_t inputstate_t; - -#define INPUT_MENU (1 << 0) -#define INPUT_UP (1 << 1) -#define INPUT_DOWN (1 << 2) -#define INPUT_LEFT (1 << 3) -#define INPUT_RIGHT (1 << 4) -#define INPUT_ACCEPT (1 << 5) -#define INPUT_BACK (1 << 6) - -extern inputstate_t INPUT_CURRENT; -extern inputstate_t INPUT_LAST_FRAME; - -/** - * Initializes the input system - */ -void inputInit(); - -/** - * Updates the input system for this tick. - */ -void inputUpdate(); - -/** - * Requests the platform let us know the current state of each input. - * - * @return Current input state. - */ -inputstate_t inputPlatformState(); - -/** - * Returns true if the input was pressed this frame, but not last frame. - * - * @param state Inputs to check, typically a single input. - * @return True if input was pressed this frame but not last frame. - */ -bool_t inputWasPressed(const inputstate_t state); - -/** - * Returns true if the input was released this frame, but pressed last frame. - * - * @param state Inputs to check, typically a single input. - * @return True if input was released this frame but was pressed last frame. - */ -bool_t inputWasReleased(const inputstate_t state); - -/** - * Returns true if the input is currently pressed. - * - * @param state Inputs to check, typically a single input. - * @return True if input is currently pressed. - */ -bool_t inputIsDown(const inputstate_t state); - -/** - * Returns true if the input is currently released. - * - * @param state Inputs to check, typically a single input. - * @return True if input is currently released. - */ -bool_t inputIsUp(const inputstate_t state); \ No newline at end of file diff --git a/src/dusk/overworld/CMakeLists.txt b/src/dusk/overworld/CMakeLists.txt deleted file mode 100644 index 06f242b..0000000 --- a/src/dusk/overworld/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2025 Dominic Masters -# -# This software is released under the MIT License. -# https://opensource.org/licenses/MIT - -# Sources -target_sources(${DUSK_TARGET_NAME} - PRIVATE - overworld.c -) - -# Subdirs -add_subdirectory(entity) -add_subdirectory(map) \ No newline at end of file diff --git a/src/dusk/overworld/entity/entity.c b/src/dusk/overworld/entity/entity.c deleted file mode 100644 index 8f669fc..0000000 --- a/src/dusk/overworld/entity/entity.c +++ /dev/null @@ -1,150 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "entity.h" -#include "assert/assert.h" -#include "util/memory.h" -#include "overworld/overworld.h" - -entitycallback_t ENTITY_CALLBACKS[ENTITY_TYPE_COUNT] = { - { NULL, NULL, NULL }, - { playerInit, playerUpdate, NULL }, - { npcInit, npcUpdate, npcInteract } -}; - -entity_t ENTITY_TEST; - -void entityInit( - entity_t *ent, - const entitytype_t type -) { - assertNotNull(ent, "Entity cannot be NULL"); - assertTrue(type < ENTITY_TYPE_COUNT, "Invalid entity type"); - - // Init values - memoryZero(ent, sizeof(entity_t)); - ent->type = type; - - // Call init - assertNotNull(ENTITY_CALLBACKS[type].init, "Entity type init callback err."); - ENTITY_CALLBACKS[type].init(ent); - - entityTurn(ent, FACING_DIRECTION_SOUTH); -} - -void entityUpdate(entity_t *ent) { - assertNotNull(ent, "Entity cannot be NULL"); - assertTrue(ent->type < ENTITY_TYPE_COUNT, "Invalid entity type"); - assertNotNull(ENTITY_CALLBACKS[ent->type].update, "Entity type update err."); - ENTITY_CALLBACKS[ent->type].update(ent); - - // Handle moving - if(ent->subX > 0) { - ent->subX -= ENTITY_MOVE_SPEED; - if(ent->subX < 0) ent->subX = 0; - } else if(ent->subX < 0) { - ent->subX += ENTITY_MOVE_SPEED; - if(ent->subX > 0) ent->subX = 0; - } else if(ent->subY > 0) { - ent->subY -= ENTITY_MOVE_SPEED; - if(ent->subY < 0) ent->subY = 0; - } else if(ent->subY < 0) { - ent->subY += ENTITY_MOVE_SPEED; - if(ent->subY > 0) ent->subY = 0; - } -} - -void entityTurn(entity_t *ent, const facingdir_t dir) { - assertNotNull(ent, "Entity cannot be NULL"); - assertTrue(dir < FACING_DIRECTION_COUNT, "Invalid facing direction"); - - ent->direction = dir; - switch(dir) { - case FACING_DIRECTION_SOUTH: - ent->frame = 25; - break; - case FACING_DIRECTION_NORTH: - ent->frame = 24; - break; - case FACING_DIRECTION_EAST: - ent->frame = 26; - break; - case FACING_DIRECTION_WEST: - ent->frame = 27; - break; - } -} - -void entityMove(entity_t *ent, const facingdir_t dir) { - assertNotNull(ent, "Entity cannot be NULL"); - if(entityIsMoving(ent)) return; - - entityTurn(ent, dir); - - uint8_t targetX = ent->x, targetY = ent->y; - facingDirAdd(ent->direction, &targetX, &targetY); - - // Check oob - if(targetX < 0 || targetX >= OVERWORLD.map.width) return; - if(targetY < 0 || targetY >= OVERWORLD.map.height) return; - - // Check tile at target - uint8_t i = 0; - tileid_t tileId; - for(i = 0; i < OVERWORLD.map.layerCount; i++) { - tileId = mapGetTileIdAtPosition(&OVERWORLD.map, i, targetX, targetY); - if(tileIsSolid(tileId)) return; - } - - // Check for entity at target - entity_t *atPos = overworldEntityGetAtPosition(targetX, targetY); - if(atPos != NULL) return; - - // Commit to move - ent->x = targetX; - ent->y = targetY; - - switch(dir) { - case FACING_DIRECTION_EAST: - ent->subX = -OVERWORLD_ENTITY_WIDTH; - break; - case FACING_DIRECTION_WEST: - ent->subX = OVERWORLD_ENTITY_WIDTH; - break; - case FACING_DIRECTION_NORTH: - ent->subY = -OVERWORLD_ENTITY_HEIGHT; - break; - case FACING_DIRECTION_SOUTH: - ent->subY = OVERWORLD_ENTITY_HEIGHT; - break; - } -} - -bool_t entityIsMoving(const entity_t *ent) { - assertNotNull(ent, "Entity cannot be NULL"); - return ent->subX != 0 || ent->subY != 0; -} - -bool_t entityInteract(entity_t *ent) { - assertNotNull(ent, "Entity cannot be NULL."); - assertTrue(ent->type == ENTITY_TYPE_PLAYER, "Entity should be player."); - if(entityIsMoving(ent)) return false; - - uint8_t targetX = ent->x, targetY = ent->y; - facingDirAdd(ent->direction, &targetX, &targetY); - - entity_t *target = overworldEntityGetAtPosition(targetX, targetY); - assertFalse(target == ent, "Cannot interact with self."); - - if(target == NULL) return false; - assertTrue(target->type < ENTITY_TYPE_COUNT, "Invalid entity type."); - - if(ENTITY_CALLBACKS[target->type].interact == NULL) return false; - ENTITY_CALLBACKS[target->type].interact(ent, target); - - return true; -} \ No newline at end of file diff --git a/src/dusk/overworld/entity/entity.h b/src/dusk/overworld/entity/entity.h deleted file mode 100644 index 52bd52c..0000000 --- a/src/dusk/overworld/entity/entity.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "facing.h" -#include "player.h" -#include "npc.h" - -typedef enum { - ENTITY_TYPE_NULL, - ENTITY_TYPE_PLAYER, - ENTITY_TYPE_NPC -} entitytype_t; - -#define ENTITY_TYPE_COUNT 3 - -typedef struct { - void (*init)(entity_t *); - void (*update)(entity_t *); - void (*interact)(entity_t *, entity_t *); -} entitycallback_t; - -typedef struct _entity_t { - uint8_t x, y; - int8_t subX, subY; - uint8_t frame; - facingdir_t direction; - entitytype_t type; - - union { - player_t player; - }; -} entity_t; - -#define ENTITY_MOVE_SPEED 3 - -/** - * Initializes an entity. - * - * @param entity The entity to initialize. - * @param type The type of entity to initialize. - */ -void entityInit( - entity_t *entity, - const entitytype_t type -); - -/** - * Updates an entity. - * - * @param entity The entity to update. - */ -void entityUpdate(entity_t *entity); - -/** - * Turns an entity in a given direction. - * - * @param entity The entity to turn. - * @param dir The direction to turn the entity. - */ -void entityTurn(entity_t *entity, const facingdir_t dir); - -/** - * Moves an entity in a given direction. - * - * @param entity The entity to move. - * @param dir The direction to move the entity. - */ -void entityMove(entity_t *entity, const facingdir_t dir); - -/** - * Checks if an entity is moving. - * - * @param entity The entity to check. - * @return TRUE if the entity is moving, FALSE otherwise. - */ -bool_t entityIsMoving(const entity_t *entity); - -/** - * Make this entity attempt to interact with the world. - * - * @param entity The entity that is doing the interaction. - * @return TRUE if an entity was interacted with, FALSE otherwise. - */ -bool_t entityInteract(entity_t *entity); \ No newline at end of file diff --git a/src/dusk/overworld/entity/facing.c b/src/dusk/overworld/entity/facing.c deleted file mode 100644 index 3b0cfce..0000000 --- a/src/dusk/overworld/entity/facing.c +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "facing.h" -#include "assert/assert.h" - -void facingDirGetRelative(const facingdir_t dir, int8_t *x, int8_t *y) { - assertNotNull(x, "X cannot be NULL"); - assertNotNull(y, "Y cannot be NULL"); - - switch(dir) { - case FACING_DIRECTION_SOUTH: - *x = 0; - *y = -1; - break; - - case FACING_DIRECTION_EAST: - *x = 1; - *y = 0; - break; - - case FACING_DIRECTION_NORTH: - *x = 0; - *y = 1; - break; - - case FACING_DIRECTION_WEST: - *x = -1; - *y = 0; - break; - - default: - assertUnreachable("Invalid facing direction."); - } -} - -void facingDirAdd(const facingdir_t dir, uint8_t *x, uint8_t *y) { - assertNotNull(x, "X cannot be NULL"); - assertNotNull(y, "Y cannot be NULL"); - - int8_t dx, dy; - facingDirGetRelative(dir, &dx, &dy); - - *x += dx; - *y += dy; -} - -facingdir_t facingDirFace( - const uint8_t x1, const uint8_t y1, - const uint8_t x2, const uint8_t y2 -) { - if(x1 == x2) { - if(y1 < y2) return FACING_DIRECTION_SOUTH; - if(y1 > y2) return FACING_DIRECTION_NORTH; - } else if(y1 == y2) { - if(x1 < x2) return FACING_DIRECTION_WEST; - if(x1 > x2) return FACING_DIRECTION_EAST; - } - - return FACING_DIRECTION_SOUTH; -} \ No newline at end of file diff --git a/src/dusk/overworld/entity/facing.h b/src/dusk/overworld/entity/facing.h deleted file mode 100644 index ce845c9..0000000 --- a/src/dusk/overworld/entity/facing.h +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef enum { - FACING_DIRECTION_SOUTH, - FACING_DIRECTION_EAST, - FACING_DIRECTION_NORTH, - FACING_DIRECTION_WEST -} facingdir_t; - -#define FACING_DIRECTION_COUNT 4 - -/** - * Converts a facing direction to a directional vector. - * - * @param dir The direction to convert. - * @param x The x component of the vector. - * @param y The y component of the vector. - */ -void facingDirGetRelative(const facingdir_t dir, int8_t *x, int8_t *y); - -/** - * Adds a facing direction to a position. - * - * @param dir The direction to add. - * @param x The x position to add to. - * @param y The y position to add to. - */ -void facingDirAdd(const facingdir_t dir, uint8_t *x, uint8_t *y); - -/** - * Returns the facing direction to face from one position to another. - * - * @param x1 The x position to face from. - * @param y1 The y position to face from. - * @param x2 The x position to face to. - * @param y2 The y position to face to. - * @return The facing direction to face from one position to another. - */ -facingdir_t facingDirFace( - const uint8_t x1, const uint8_t y1, - const uint8_t x2, const uint8_t y2 -); \ No newline at end of file diff --git a/src/dusk/overworld/entity/npc.c b/src/dusk/overworld/entity/npc.c deleted file mode 100644 index 882b814..0000000 --- a/src/dusk/overworld/entity/npc.c +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "entity.h" - -void npcInit(entity_t *ent) { -} - -void npcUpdate(entity_t *ent) { -} - -void npcInteract(entity_t *player, entity_t *ent) { - printf("Interact\n"); - entityTurn(ent, facingDirFace(player->x, player->y, ent->x, ent->y)); -} \ No newline at end of file diff --git a/src/dusk/overworld/entity/npc.h b/src/dusk/overworld/entity/npc.h deleted file mode 100644 index f5290a8..0000000 --- a/src/dusk/overworld/entity/npc.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef struct _entity_t entity_t; - -typedef struct { - int32_t nothing; -} npc_t; - -/** - * Handles initialization of an NPC. - * - * @param ent The entity to initialize as an NPC. - */ -void npcInit(entity_t *ent); - -/** - * Handles updating an NPC. - * - * @param ent The entity to update as an NPC. - */ -void npcUpdate(entity_t *ent); - -/** - * Handles interaction with an NPC. - * - * @param player The player entity interacting. - * @param ent The entity to interact with. - */ -void npcInteract(entity_t *player, entity_t *ent); \ No newline at end of file diff --git a/src/dusk/overworld/entity/player.c b/src/dusk/overworld/entity/player.c deleted file mode 100644 index 42aac7e..0000000 --- a/src/dusk/overworld/entity/player.c +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "overworld/overworld.h" -#include "assert/assert.h" -#include "input.h" - -void playerInit(entity_t *ent) { - assertNotNull(ent, "Entity cannot be NULL"); - - printf("Initializing player entity\n"); -} - -void playerUpdate(entity_t *ent) { - assertNotNull(ent, "Entity cannot be NULL"); - - if(inputIsDown(INPUT_RIGHT)) { - entityMove(ent, FACING_DIRECTION_EAST); - } else if(inputIsDown(INPUT_LEFT)) { - entityMove(ent, FACING_DIRECTION_WEST); - } else if(inputIsDown(INPUT_UP)) { - entityMove(ent, FACING_DIRECTION_NORTH); - } else if(inputIsDown(INPUT_DOWN)) { - entityMove(ent, FACING_DIRECTION_SOUTH); - } else if(inputWasPressed(INPUT_ACCEPT)) { - entityInteract(ent); - } - -} \ No newline at end of file diff --git a/src/dusk/overworld/entity/player.h b/src/dusk/overworld/entity/player.h deleted file mode 100644 index 2082f57..0000000 --- a/src/dusk/overworld/entity/player.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef struct _entity_t entity_t; - -typedef struct { - int32_t nothing; -} player_t; - -/** - * Handles initialization of the player. - * - * @param ent The entity to initialize as a player. - */ -void playerInit(entity_t *ent); - -/** - * Handles updating the player. - * - * @param ent The entity to update as a player. - */ -void playerUpdate(entity_t *ent); \ No newline at end of file diff --git a/src/dusk/overworld/map/map.c b/src/dusk/overworld/map/map.c deleted file mode 100644 index a2a1f3e..0000000 --- a/src/dusk/overworld/map/map.c +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "map.h" -#include "assert/assert.h" -#include "util/memory.h" - -void mapInit(map_t *map) { - memoryZero(map, sizeof(map_t)); - - // Test - map->width = 16; - map->height = 16; - map->layerCount = 1; - memorySet(&map->tileIds, 0x01, sizeof(map->tileIds)); - - // Test size - assertTrue( - (map->width * map->height * map->layerCount) <= OVERWORLD_TILE_COUNT_MAX, - "Map size exceeds tile count." - ); -} - -uint32_t mapGetTileIndex( - const map_t *map, - const uint8_t layer, - const uint8_t x, - const uint8_t y -) { - assertNotNull(map, "Map cannot be NULL"); - assertTrue(layer < map->layerCount, "Invalid layer"); - assertTrue(x < map->width, "Invalid x"); - assertTrue(y < map->height, "Invalid y"); - - return (layer * map->width * map->height) + (y * map->width) + x; -} - -tileid_t mapGetTileId( - const map_t *map, - const uint32_t tileIndex -) { - assertNotNull(map, "Map cannot be NULL"); - assertMapIndexValid(map, tileIndex); - - return map->tileIds[tileIndex]; -} - -tileid_t mapGetTileIdAtPosition( - const map_t *map, - const uint8_t layer, - const uint8_t x, - const uint8_t y -) { - return mapGetTileId(map, mapGetTileIndex(map, layer, x, y)); -} - -tiledata_t mapGetTileData( - const map_t *map, - const uint32_t tileIndex -) { - assertNotNull(map, "Map cannot be NULL"); - assertMapIndexValid(map, tileIndex); - - return map->tileData[tileIndex]; -} \ No newline at end of file diff --git a/src/dusk/overworld/map/map.h b/src/dusk/overworld/map/map.h deleted file mode 100644 index 120a1df..0000000 --- a/src/dusk/overworld/map/map.h +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "tile.h" -#include "overworld/overworlddefs.h" -#include "assert/assert.h" - -#define assertMapIndexValid(map, index) \ - assertTrue( \ - index < (map->layerCount * map->width * map->height), \ - "Invalid tile index" \ - ); - -typedef struct { - tileid_t tileIds[OVERWORLD_TILE_COUNT_MAX]; - tiledata_t tileData[OVERWORLD_TILE_COUNT_MAX]; - uint8_t width, height, layerCount; -} map_t; - -void mapInit(map_t *map); - -/** - * Returns the index of the tile at the given position. - * - * @param map The map to get the tile index from. - * @param layer The layer to get the tile from. - * @param x The x position of the tile. - * @param y The y position of the tile. - * @return The index of the tile at the given position. - */ -uint32_t mapGetTileIndex( - const map_t *map, - const uint8_t layer, - const uint8_t x, - const uint8_t y -); - -/** - * Returns the tile ID at the given index. - * - * @param map The map to get the tile ID from. - * @param tileIndex The index of the tile to get. - * @return The tile ID at the given index. - */ -tileid_t mapGetTileId( - const map_t *map, - const uint32_t tileIndex -); - -/** - * Returns the tile ID at the given position. Shorthand for both getting the - * map index and the tile ID. - * - * @param map The map to get the tile ID from. - * @param layer The layer to get the tile from. - * @param x The x position of the tile. - * @param y The y position of the tile. - * @return The tile ID at the given position. - */ -tileid_t mapGetTileIdAtPosition( - const map_t *map, - const uint8_t layer, - const uint8_t x, - const uint8_t y -); - -/** - * Returns the tile data at the given index. - * - * @param map The map to get the tile data from. - * @param tileIndex The index of the tile to get. - * @return The tile data at the given index. - */ -tiledata_t mapGetTileData( - const map_t *map, - const uint32_t tileIndex -); \ No newline at end of file diff --git a/src/dusk/overworld/map/tile.c b/src/dusk/overworld/map/tile.c deleted file mode 100644 index 2b5a548..0000000 --- a/src/dusk/overworld/map/tile.c +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "tile.h" - -bool_t tileIsSolid(const tileid_t id) { - switch(id) { - case TILE_ID_NULL: - case TILE_ID_GRASS: - return false; - - default: - return true; - } -} \ No newline at end of file diff --git a/src/dusk/overworld/map/tile.h b/src/dusk/overworld/map/tile.h deleted file mode 100644 index d49c546..0000000 --- a/src/dusk/overworld/map/tile.h +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef uint8_t tileid_t; - -typedef struct { - uint32_t nothing; -} tiledata_t; - -#define TILE_ID_NULL 0 -#define TILE_ID_GRASS 1 - -/** - * Returns whether or not the tile is solid. - * - * @param id The tile id to check. - * @return Whether or not the tile is solid. - */ -bool_t tileIsSolid(const tileid_t id); \ No newline at end of file diff --git a/src/dusk/overworld/overworld.c b/src/dusk/overworld/overworld.c deleted file mode 100644 index eb81fe9..0000000 --- a/src/dusk/overworld/overworld.c +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "overworld.h" -#include "util/memory.h" -#include "assert/assert.h" -#include "display/tileset.h" - -overworld_t OVERWORLD; - -void overworldInit() { - memoryZero(&OVERWORLD, sizeof(overworld_t)); - - mapInit(&OVERWORLD.map); - - entityInit(OVERWORLD.entities + OVERWORLD.entityCount++, ENTITY_TYPE_PLAYER); - - entityInit(OVERWORLD.entities + OVERWORLD.entityCount++, ENTITY_TYPE_NPC); - OVERWORLD.entities[1].x = 2; - OVERWORLD.entities[1].y = 2; -} - -void overworldSceneInit() { - tilesetBind(TILESET_FONT, TILESET_SLOT_ENTITIES); -} - -void overworldSceneDeinit() { - -} - -void overworldUpdate() { - uint8_t i = 0; - while(i < OVERWORLD.entityCount) { - entityUpdate(OVERWORLD.entities + i++); - } -} - -entity_t * overworldEntityGetAtPosition(const uint8_t x, const uint8_t y) { - uint8_t i = 0; - while(i < OVERWORLD.entityCount) { - entity_t * entity = OVERWORLD.entities + i++; - if(entity->x == x && entity->y == y) return entity; - } - return NULL; -} \ No newline at end of file diff --git a/src/dusk/overworld/overworld.h b/src/dusk/overworld/overworld.h deleted file mode 100644 index 2185ed8..0000000 --- a/src/dusk/overworld/overworld.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "overworlddefs.h" -#include "overworld/entity/entity.h" -#include "overworld/map/map.h" - -typedef struct { - entity_t entities[OVERWORLD_ENTITY_COUNT_MAX]; - uint8_t entityCount; - map_t map; -} overworld_t; - -extern overworld_t OVERWORLD; - -/** - * Initializes the overworld. - */ -void overworldInit(); - -/** - * Called by the scene system when the overworld scene is made to be the - * active scene. - */ -void overworldSceneInit(); - -/** - * Called by the scene system when the overworld scene is made to be inactive. - */ -void overworldSceneDeinit(); - -/** - * Called by the scene system when the overworld scene is to perform a tick. - */ -void overworldUpdate(); - -/** - * Platform level render method. Refer to sceneRender for information. - */ -void overworldRender(); - -/** - * Returns the entity at the given position. - * - * @param x The x position of the entity. - * @param y The y position of the entity. - * @return The entity at the given position. - */ -entity_t * overworldEntityGetAtPosition( - const uint8_t x, - const uint8_t y -); \ No newline at end of file diff --git a/src/dusk/overworld/overworlddefs.h b/src/dusk/overworld/overworlddefs.h deleted file mode 100644 index 8608033..0000000 --- a/src/dusk/overworld/overworlddefs.h +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#define OVERWORLD_ENTITY_COUNT_MAX 8 -#define OVERWORLD_ENTITY_WIDTH 32 -#define OVERWORLD_ENTITY_HEIGHT 32 - -#define OVERWORLD_TILE_LAYER_COUNT_MAX 2 -#define OVERWORLD_TILE_COUNT_PER_LAYER 256 -#define OVERWORLD_TILE_COUNT_MAX (OVERWORLD_TILE_COUNT_PER_LAYER * OVERWORLD_TILE_LAYER_COUNT_MAX) -#define OVERWORLD_TILE_WIDTH OVERWORLD_ENTITY_WIDTH -#define OVERWORLD_TILE_HEIGHT OVERWORLD_ENTITY_HEIGHT \ No newline at end of file diff --git a/src/dusk/server/server.h b/src/dusk/server/server.h new file mode 100644 index 0000000..f07e182 --- /dev/null +++ b/src/dusk/server/server.h @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +typedef struct { + +} server_t; + +extern server_t SERVER; + +void serverInit(); +void serverStart(); +void serverDispose(); \ No newline at end of file diff --git a/src/dusk/ui/uimenu.c b/src/dusk/ui/uimenu.c deleted file mode 100644 index 510ba54..0000000 --- a/src/dusk/ui/uimenu.c +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "uimenu.h" -#include "util/memory.h" -#include "assert/assert.h" -#include "input.h" - -void uiMenuInit( - uimenu_t *menu, - const uint8_t columns, - const uint8_t rows -) { - assertNotNull(menu, "Menu cannot be NULL."); - - memoryZero(menu, sizeof(uimenu_t)); - - menu->columns = columns; - menu->rows = rows; -} - -void uiMenuSetCursor( - uimenu_t *menu, - const uint8_t x, - const uint8_t y -) { - assertNotNull(menu, "Menu cannot be NULL."); - assert(x < menu->columns, "X position out of bounds."); - assert(y < menu->rows, "Y position out of bounds."); - - menu->x = x; - menu->y = y; -} - -void uiMenuMoveCursor( - uimenu_t *menu, - const int8_t x, - const int8_t y -) { - assertNotNull(menu, "Menu cannot be NULL."); - uiMenuSetCursor( - menu, - (menu->x + x) % menu->columns, - (menu->y + y) % menu->rows - ); -} - -uimenuaction_t uiMenuUpdate(uimenu_t *menu) { - assertNotNull(menu, "Menu cannot be NULL."); - -} \ No newline at end of file diff --git a/src/dusk/ui/uimenu.h b/src/dusk/ui/uimenu.h deleted file mode 100644 index 9188f54..0000000 --- a/src/dusk/ui/uimenu.h +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -typedef enum { - UI_MENU_ACTION_NOTHING, - UI_MENU_ACTION_CURSOR_MOVE, - UI_MENU_ACTION_CURSOR_ACCEPT, - UI_MENU_ACTION_CURSOR_CANCEL -} uimenuaction_t; - -typedef struct { - uint8_t columns; - uint8_t rows; - uint8_t x; - uint8_t y; -} uimenu_t; - -/** - * Initializes a menu. - * - * @param menu The menu to initialize. - * @param columns The amount of columns in the menu. - * @param rows The amount of rows in the menu. - */ -void uiMenuInit( - uimenu_t *menu, - const uint8_t columns, - const uint8_t rows -); - -/** - * Sets the cursor of a menu. - * - * @param menu The menu to set the cursor of. - * @param x The x position of the cursor. - * @param y The y position of the cursor. - */ -void uiMenuSetCursor( - uimenu_t *menu, - const uint8_t x, - const uint8_t y -); - -/** - * Moves the cursor of a menu. - * - * @param menu The menu to move the cursor of. - * @param x The amount to move the cursor on the x axis. - * @param y The amount to move the cursor on the y axis. - */ -void uiMenuMoveCursor( - uimenu_t *menu, - const int8_t x, - const int8_t y -); - -/** - * Handles updating of a menu, this will accept input basically. - * - * @param menu The menu to update. - */ -uimenuaction_t uiMenuUpdate(uimenu_t *menu); \ No newline at end of file diff --git a/src/dusk/util/CMakeLists.txt b/src/dusk/util/CMakeLists.txt index 524bbb1..915d256 100644 --- a/src/dusk/util/CMakeLists.txt +++ b/src/dusk/util/CMakeLists.txt @@ -1,12 +1,11 @@ -# Copyright (c) 2023 Dominic Masters +# Copyright (c) 2025 Dominic Masters # # This software is released under the MIT License. -# https:#opensource.org/licenses/MIT +# https://opensource.org/licenses/MIT # Sources target_sources(${DUSK_TARGET_NAME} PRIVATE - math.c - random.c memory.c + string.c ) \ No newline at end of file diff --git a/src/dusk/util/math.c b/src/dusk/util/math.c deleted file mode 100644 index fd4d01b..0000000 --- a/src/dusk/util/math.c +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) 2023 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "math.h" -#include "assert/assert.h" - -int32_t mathClampi32( - const int32_t value, - const int32_t min, - const int32_t max -) { - assertTrue(max >= min, "mathClampi32: Max must be >= Min"); - if(value < min) return min; - if(value > max) return max; - return value; -} - -int32_t mathModi32(int32_t value, int32_t modulo) { - return ((value % modulo) + modulo) % modulo; -} \ No newline at end of file diff --git a/src/dusk/util/math.h b/src/dusk/util/math.h deleted file mode 100644 index 01e9d56..0000000 --- a/src/dusk/util/math.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Copyright (c) 2023 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -/** - * Returns the minimum of two values. - * @param a First value. - * @param b Second value. - * @return The minimum of the two values. - */ -#define mathMin(a, b) ((a) < (b) ? (a) : (b)) - -/** - * Returns the maximum of two values. - * @param a First value. - * @param b Second value. - * @return The maximum of the two values. - */ -#define mathMax(a, b) ((a) > (b) ? (a) : (b)) - -/** - * Clamps a value between a min and max. - * - * @param value Value to clamp. - * @param min Minimum value to clamp value to. - * @param max Maximum value to clamp value to. - * @return The clamped value. - */ -int32_t mathClampi32( - const int32_t value, - const int32_t min, - const int32_t max -); - -/** - * Returns the modulo of a value. For 32 bit integers. - * - * @param value Value to modulo. - * @param modulo Modulo value. - * @return The modulo of the value. - */ -int32_t mathModi32(int32_t value, int32_t modulo); \ No newline at end of file diff --git a/src/dusk/util/memory.c b/src/dusk/util/memory.c index 736c1b6..78c5b26 100644 --- a/src/dusk/util/memory.c +++ b/src/dusk/util/memory.c @@ -49,4 +49,12 @@ void memoryCopyRangeSafe( size_t copy = (size_t)end - (size_t)start; assertTrue(copy <= sizeMax, "Size of memory to copy is too large."); memoryCopy(dest, start, copy); +} + +void memoryMove(void *dest, const void *src, const size_t size) { + assertNotNull(dest, "Cannot move to NULL memory."); + assertNotNull(src, "Cannot move from NULL memory."); + assertTrue(size > 0, "Cannot move 0 bytes of memory."); + assertTrue(dest != src, "Cannot move memory to itself."); + memmove(dest, src, size); } \ No newline at end of file diff --git a/src/dusk/util/memory.h b/src/dusk/util/memory.h index 142c85e..153a463 100644 --- a/src/dusk/util/memory.h +++ b/src/dusk/util/memory.h @@ -64,4 +64,13 @@ void memoryCopyRangeSafe( const void *start, const void *end, const size_t sizeMax -); \ No newline at end of file +); + +/** + * Moves memory. + * + * @param dest The destination to move to. + * @param src The source to move from. + * @param size The size of the memory to move. + */ +void memoryMove(void *dest, const void *src, const size_t size); \ No newline at end of file diff --git a/src/dusk/util/random.c b/src/dusk/util/random.c deleted file mode 100644 index 0c420ce..0000000 --- a/src/dusk/util/random.c +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright (c) 2024 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "random.h" -#include "assert/assert.h" - -bool_t RANDOM_IS_INITIALIZED = false; - -void randomInit() { - assertFalse(RANDOM_IS_INITIALIZED, "Random already initialized."); - srand(1234567890); - RANDOM_IS_INITIALIZED = true; -} - -int32_t randomInt32() { - assertTrue(RANDOM_IS_INITIALIZED, "Random not initialized."); - return rand(); -} - -int32_t randomInt32Range(int32_t min, int32_t max) { - return min + (rand() % (max - min)); -} \ No newline at end of file diff --git a/src/dusk/util/random.h b/src/dusk/util/random.h deleted file mode 100644 index b732d17..0000000 --- a/src/dusk/util/random.h +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) 2024 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "dusk.h" - -extern bool_t RANDOM_IS_INITIALIZED; - -/** - * Initializes the random number generator, and seeds it. - */ -void randomInit(); - -/** - * Returns a random 32-bit integer. - * - * @return Random 32-bit integer. - */ -int32_t randomInt32(); - -/** - * Returns a random 32-bit integer within a given range. - * - * @param min Minimum value. - * @param max Maximum value (exclusive). - * @return Random 32-bit integer within the given range. - */ -int32_t randomInt32Range(int32_t min, int32_t max); \ No newline at end of file diff --git a/src/dusk/util/string.c b/src/dusk/util/string.c new file mode 100644 index 0000000..b13a076 --- /dev/null +++ b/src/dusk/util/string.c @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "string.h" +#include "assert/assert.h" + +bool_t stringIsWhitespace(const char_t c) { + return isspace(c); +} + +void stringCopy(char_t *dest, const char_t *src, const size_t destSize) { + assertNotNull(dest, "dest must not be NULL"); + assertNotNull(src, "src must not be NULL"); + assertStrLenMax(src, destSize, "src is too long"); + strncpy(dest, src, destSize); +} + +int stringCompare(const char_t *str1, const char_t *str2) { + assertNotNull(str1, "str1 must not be NULL"); + assertNotNull(str2, "str2 must not be NULL"); + return strcmp(str1, str2); +} + +void stringTrim(char_t *str) { + assertNotNull(str, "str must not be NULL"); + + // Trim leading whitespace + char_t *start = str; + while(stringIsWhitespace(*start)) start++; + + // Trim trailing whitespace + char_t *end = start + strlen(start) - 1; + while (end >= start && stringIsWhitespace(*end)) end--; + + // Null-terminate the string + *(end + 1) = '\0'; + + // Move trimmed string to the original buffer + if (start != str) memmove(str, start, end - start + 2); +} + +char_t * stringToken(char_t *str, const char_t *delim) { + assertNotNull(str, "str must not be NULL"); + assertNotNull(delim, "delim must not be NULL"); + return strtok(str, delim); +} \ No newline at end of file diff --git a/src/dusk/util/string.h b/src/dusk/util/string.h new file mode 100644 index 0000000..d881605 --- /dev/null +++ b/src/dusk/util/string.h @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +/** + * Determines if a character is whitespace. + * + * @param c The character to check. + * @return TRUE if the character is whitespace, FALSE otherwise. + */ +bool_t stringIsWhitespace(const char_t c); + +/** + * Copies a string from src to dest, ensuring the dest string is null-terminated + * and does not exceed the specified size. + * + * @param dest The destination string. + * @param src The source string. + * @param destSize The size of the destination string exc. null terminator. + */ +void stringCopy(char_t *dest, const char_t *src, const size_t destSize); + +/** + * Compares two strings. + * + * @param str1 The first string. + * @param str2 The second string. + * @return 0 if the strings are equal, -1 if str1 is less than str2, 1 if str1 + * is greater than str2. + */ +int stringCompare(const char_t *str1, const char_t *str2); + +/** + * Trims whitespace from the beginning and end of a string. + * + * @param str The string to trim. + */ +void stringTrim(char_t *str); + +/** + * Gets the next token in a string using a delimiter. + * e.g. input: "Hello, World, Happy Monday!" with stringToken(input, ",") will + * return "Hello" then " World" then " Happy Monday!" on each subsequent call. + * + * @param str The string to split. + * @param delim The delimiter to split by. + * @return A pointer to the next token in the string. + */ +char_t * stringToken(char_t *str, const char_t *delim); \ No newline at end of file diff --git a/src/dusk/overworld/entity/CMakeLists.txt b/src/dusktest/CMakeLists.txt similarity index 52% rename from src/dusk/overworld/entity/CMakeLists.txt rename to src/dusktest/CMakeLists.txt index f0dac1f..93a162d 100644 --- a/src/dusk/overworld/entity/CMakeLists.txt +++ b/src/dusktest/CMakeLists.txt @@ -1,15 +1,23 @@ # Copyright (c) 2025 Dominic Masters -# +# # This software is released under the MIT License. # https://opensource.org/licenses/MIT +# Libs +target_link_libraries(${DUSK_TARGET_NAME} + PUBLIC +) + +# Includes +target_include_directories(${DUSK_TARGET_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR} +) + # Sources target_sources(${DUSK_TARGET_NAME} PRIVATE - entity.c - facing.c - player.c - npc.c + main.c ) # Subdirs \ No newline at end of file diff --git a/src/dusktest/main.c b/src/dusktest/main.c new file mode 100644 index 0000000..9ebeeb6 --- /dev/null +++ b/src/dusktest/main.c @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "dusk.h" +#include "error/error.h" +#include "console/console.h" +#include "util/string.h" + +bool_t exitRequested = false; + +void cmdExit(const consolecmdexec_t *exec) { + exitRequested = true; +} + +void testChange(const consolevar_t *var) { + consolePrint("Variable '%s' changed to '%s'.", var->name, var->value); +} + +int main() { + consoleInit(); + + consoleRegCmd("exit", cmdExit); + consoleRegVar("test", "Hello", testChange); + consolePrint(" = Dusk Console = "); + + char_t buffer[CONSOLE_LINE_MAX]; + while(fgets(buffer, sizeof(buffer), stdin)) { + consoleExec(buffer); + consoleProcess(); + if(exitRequested) break; + } + printf("Goodbye!\n"); + + return 0; +} \ No newline at end of file