Nuked console

This commit is contained in:
2025-11-03 09:22:18 -06:00
parent 3feb43fdad
commit 3ef6205ea3
53 changed files with 127 additions and 1570 deletions

View File

@@ -7,7 +7,6 @@ set(DUSK_GAME_ASSETS_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL ${DUSK_CAC
add_subdirectory(palette)# Palette asset needs to be added before any images. add_subdirectory(palette)# Palette asset needs to be added before any images.
add_subdirectory(config)
add_subdirectory(entity) add_subdirectory(entity)
add_subdirectory(map) add_subdirectory(map)
add_subdirectory(ui) add_subdirectory(ui)

View File

@@ -1,8 +0,0 @@
# Copyright (c) 2025 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
add_asset(CONFIG init.dcf)
add_asset(CONFIG init-base.dcf)
add_asset(CONFIG init-psp.dcf)

View File

@@ -1,4 +0,0 @@
echo " = Dawn Init = ";
fps 1;
scene map;

View File

@@ -1,16 +0,0 @@
exec "config/init-base";
screen backbuffer;
bind up up;
bind down down;
bind left left;
bind right right;
bind cross accept;
bind circle cancel;
bind select toggleconsole;
bind start toggleconsole;
bind lstick_negative_y up;
bind lstick_positive_y down;
bind lstick_negative_x left;
bind lstick_positive_x right;

View File

@@ -1,17 +0,0 @@
exec "config/init-base";
screen height 270;
bind ` toggleconsole;
bind w up;
bind s down;
bind a left;
bind d right;
bind up up;
bind down down;
bind left left;
bind right right;
bind e accept;
bind enter accept;
bind q cancel;
bind esc quit;

View File

@@ -29,13 +29,14 @@ target_sources(${DUSK_TARGET_NAME}
# Subdirs # Subdirs
add_subdirectory(assert) add_subdirectory(assert)
add_subdirectory(asset) add_subdirectory(asset)
add_subdirectory(console) add_subdirectory(debug)
add_subdirectory(display) add_subdirectory(display)
add_subdirectory(engine) add_subdirectory(engine)
add_subdirectory(error) add_subdirectory(error)
add_subdirectory(input) add_subdirectory(input)
# add_subdirectory(locale) # add_subdirectory(locale)
add_subdirectory(physics) add_subdirectory(physics)
add_subdirectory(platform)
add_subdirectory(rpg) add_subdirectory(rpg)
add_subdirectory(scene) add_subdirectory(scene)
add_subdirectory(thread) add_subdirectory(thread)

View File

@@ -9,7 +9,6 @@
#include "assetmanager.h" #include "assetmanager.h"
#include "util/memory.h" #include "util/memory.h"
#include "assert/assert.h" #include "assert/assert.h"
#include "console/console.h"
assetdef_t ASSET_DEFINITIONS[ASSET_TYPE_COUNT] = { assetdef_t ASSET_DEFINITIONS[ASSET_TYPE_COUNT] = {
[ASSET_TYPE_PALETTE_IMAGE] = { [ASSET_TYPE_PALETTE_IMAGE] = {
@@ -18,9 +17,6 @@ assetdef_t ASSET_DEFINITIONS[ASSET_TYPE_COUNT] = {
[ASSET_TYPE_ALPHA_IMAGE] = { [ASSET_TYPE_ALPHA_IMAGE] = {
"DAI", assetAlphaImageLoad, assetAlphaImageDispose "DAI", assetAlphaImageLoad, assetAlphaImageDispose
}, },
[ASSET_TYPE_CONFIG] = {
"DCF", assetConfigLoad, assetConfigDispose
},
}; };
errorret_t assetInit(asset_t *asset, const char_t *filename) { errorret_t assetInit(asset_t *asset, const char_t *filename) {

View File

@@ -12,7 +12,6 @@
#include "asset/type/assetpaletteimage.h" #include "asset/type/assetpaletteimage.h"
#include "asset/type/assetalphaimage.h" #include "asset/type/assetalphaimage.h"
#include "asset/type/assetconfig.h"
#define ASSET_HEADER_SIZE 3 #define ASSET_HEADER_SIZE 3
#define ASSET_REFERENCE_COUNT_MAX 8 #define ASSET_REFERENCE_COUNT_MAX 8
@@ -32,7 +31,6 @@ typedef enum {
ASSET_TYPE_UNKNOWN, ASSET_TYPE_UNKNOWN,
ASSET_TYPE_PALETTE_IMAGE, ASSET_TYPE_PALETTE_IMAGE,
ASSET_TYPE_ALPHA_IMAGE, ASSET_TYPE_ALPHA_IMAGE,
ASSET_TYPE_CONFIG,
ASSET_TYPE_COUNT ASSET_TYPE_COUNT
} assettype_t; } assettype_t;
@@ -48,7 +46,6 @@ typedef struct asset_s {
union { union {
assetpaletteimage_t paletteImage; assetpaletteimage_t paletteImage;
assetalphaimage_t alphaImage; assetalphaimage_t alphaImage;
assetconfig_t config;
}; };
} asset_t; } asset_t;

View File

@@ -7,7 +7,6 @@
#include "assetmanager.h" #include "assetmanager.h"
#include "util/memory.h" #include "util/memory.h"
#include "console/console.h"
#include "util/string.h" #include "util/string.h"
#include "assert/assert.h" #include "assert/assert.h"
@@ -17,16 +16,17 @@ assetmanager_t ASSET_MANAGER;
errorret_t assetManagerInit(void) { errorret_t assetManagerInit(void) {
memoryZero(&ASSET_MANAGER, sizeof(assetmanager_t)); memoryZero(&ASSET_MANAGER, sizeof(assetmanager_t));
// Default system path, intended to be overridden by the paltform
stringCopy(ASSET_MANAGER.systemPath, ".", FILENAME_MAX);
// Open zip file // Open zip file
char_t searchPath[FILENAME_MAX]; char_t searchPath[FILENAME_MAX];
consolevar_t *var = consoleVarGet("sys_path");
const char_t *sysPath = var ? var->value : ".";
for(int32_t i = 0; i < ASSET_MANAGER_SEARCH_PATHS_COUNT; i++) { for(int32_t i = 0; i < ASSET_MANAGER_SEARCH_PATHS_COUNT; i++) {
sprintf( sprintf(
searchPath, searchPath,
ASSET_MANAGER_SEARCH_PATHS[i], ASSET_MANAGER_SEARCH_PATHS[i],
sysPath, ASSET_MANAGER.systemPath,
ASSET_ASSET_FILE ASSET_ASSET_FILE
); );

View File

@@ -31,6 +31,7 @@ static const char_t ASSET_MANAGER_SEARCH_PATHS[][FILENAME_MAX] = {
typedef struct { typedef struct {
zip_t *zip; zip_t *zip;
asset_t assets[ASSET_MANAGER_ASSET_COUNT_MAX]; asset_t assets[ASSET_MANAGER_ASSET_COUNT_MAX];
char_t systemPath[FILENAME_MAX];
uint8_t assetCount; uint8_t assetCount;
} assetmanager_t; } assetmanager_t;

View File

@@ -7,6 +7,5 @@
target_sources(${DUSK_TARGET_NAME} target_sources(${DUSK_TARGET_NAME}
PRIVATE PRIVATE
assetalphaimage.c assetalphaimage.c
assetconfig.c
assetpaletteimage.c assetpaletteimage.c
) )

View File

@@ -1,61 +0,0 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "asset/asset.h"
#include "console/console.h"
#include "assert/assert.h"
errorret_t assetConfigLoad(asset_t *asset) {
char_t buffer[CONSOLE_LINE_MAX + 1];
// Read byte by byte.
zip_int64_t bytesRead = 0;
zip_int64_t totalBytesRead = 0;
char_t c;
while(1) {
bytesRead = zip_fread(
asset->file,
&c,
1
);
if(bytesRead < 0) errorThrow("Failed to read from config asset file");
// Is byte execute?
if(c != ';' && c != '\n' && c != '\r' && bytesRead == 1) {
// Not execute, add to buffer.
buffer[totalBytesRead] = c;
if(++totalBytesRead >= CONSOLE_LINE_MAX) {
errorThrow("Config line too long!");
}
continue;
}
// Execute buffer.
buffer[totalBytesRead] = '\0';
consoleExec(buffer);
totalBytesRead = 0;
if(bytesRead == 0) break;
}
if(totalBytesRead > 0) {
// Execute remaining buffer.
buffer[totalBytesRead] = '\0';
consoleExec(buffer);
}
errorOk();
}
errorret_t assetConfigExecute(asset_t *asset) {
errorOk();
}
errorret_t assetConfigDispose(asset_t *asset) {
errorOk();
}

View File

@@ -1,42 +0,0 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "error/error.h"
typedef struct asset_s asset_t;
typedef struct {
zip_int64_t pos;
zip_int64_t size;
} assetconfig_t;
/**
* Loads a config asset from the given asset structure. The asset must be of
* type ASSET_TYPE_CONFIG and must be loaded.
*
* @param asset The asset to load the config from.
* @return An error code.
*/
errorret_t assetConfigLoad(asset_t *asset);
/**
* Executes the config commands in the given asset. The asset must be of type
* ASSET_TYPE_CONFIG and must be loaded.
*
* @param asset The asset to execute the config from.
* @return An error code.
*/
errorret_t assetConfigExecute(asset_t *asset);
/**
* Disposes of a config asset, freeing any allocated resources.
*
* @param asset The asset to dispose of.
* @return An error code.
*/
errorret_t assetConfigDispose(asset_t *asset);

View File

@@ -1,24 +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
console.c
consolecmd.c
consolevar.c
)
# Subdirectories
add_subdirectory(cmd)
# Compiler flags.
if(DUSK_TARGET_SYSTEM STREQUAL "linux")
target_compile_definitions(${DUSK_TARGET_NAME}
PRIVATE
CONSOLE_POSIX=1
#CONSOLE_INTERACTIVE=1
)
endif()

View File

@@ -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 "console/console.h"
#include "input/input.h"
#include "util/string.h"
void cmdAlias(const consolecmdexec_t *exec) {
if(exec->argc < 1) {
consolePrint("Expected 1 argument: <name> <command>");
return;
}
if(exec->argc == 1 || strlen(exec->argv[1]) == 0) {
// Removing the alias.
for(uint32_t i = 0; i < CONSOLE.aliasCount; i++) {
if(stringCompare(CONSOLE.aliases[i].alias, exec->argv[0]) != 0) {
continue;
}
// Move all the later aliases down one.
if(CONSOLE.aliasCount - i - 1 > 0) {
memoryMove(
&CONSOLE.aliases[i],
&CONSOLE.aliases[i + 1],
(CONSOLE.aliasCount - i - 1) * sizeof(consolealias_t)
);
}
CONSOLE.aliasCount--;
return;
}
// Alias not found.
return;
}
// Add alias
if(CONSOLE.aliasCount >= CONSOLE_ALIAS_MAX) {
consolePrint("Max aliases reached");
return;
}
// Create alias
consolealias_t *alias = &CONSOLE.aliases[CONSOLE.aliasCount++];
stringCopy(alias->alias, exec->argv[0], CONSOLE_LINE_MAX);
stringCopy(alias->command, exec->argv[1], CONSOLE_LINE_MAX);
consolePrint("Added alias \"%s\" -> \"%s\"", exec->argv[0], exec->argv[1]);
}

View File

@@ -1,30 +0,0 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "console/console.h"
#include "input/input.h"
void cmdBind(const consolecmdexec_t *exec) {
if(exec->argc < 1) {
consolePrint("Expected 1 argument: <key> <command]");
return;
}
if(exec->argc == 1) {
consolePrint("TODO: Show binds");
return;
}
inputbutton_t button = inputButtonGetByName(exec->argv[0]);
if(button.type == INPUT_BUTTON_TYPE_NONE) {
consolePrint("Unknown button \"%s\"", exec->argv[0]);
return;
}
inputBind(button, exec->argv[1]);
}

View File

@@ -1,18 +0,0 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "console/console.h"
void cmdEcho(const consolecmdexec_t *exec) {
if(exec->argc < 1) {
consolePrint("Expected 1 argument: <message>");
return;
}
consolePrint("%s", exec->argv[0]);
}

View File

@@ -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 "console/console.h"
#include "asset/assetmanager.h"
void cmdExec(const consolecmdexec_t *exec) {
if(exec->argc < 1) {
consolePrint("Expected 1 argument: <filename>");
return;
}
char_t file[FILENAME_MAX];
stringCopy(file, exec->argv[0], FILENAME_MAX);
if(!stringEndsWith(file, ".dcf")) {
sprintf(
file,
"%s.dcf",
exec->argv[0]
);
}
ref_t ref;
asset_t asset;
errorret_t ret = assetInit(&asset, file);
if(ret.code != ERROR_OK) {
errorPrint(ret);
consolePrint("Failed to load asset %s", file);
return;
}
ret = assetLoad(&asset);
if(asset.type != ASSET_TYPE_CONFIG) {
consolePrint("Asset is not a config: %s", file);
assetDispose(&asset);
return;
}
assetDispose(&asset);
if(ret.code != ERROR_OK) {
errorPrint(ret);
consolePrint("Failed to load asset %s", file);
return;
}
}

View File

@@ -1,25 +0,0 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "console/console.h"
void cmdGet(const consolecmdexec_t *exec) {
assertTrue(
exec->argc >= 1,
"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[0]) != 0) continue;
consolePrint("%s", var->value);
return;
}
consolePrint("Error: Variable '%s' not found.", exec->argv[0]);
}

View File

@@ -1,14 +0,0 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "console/console.h"
#include "engine/engine.h"
void cmdQuit(const consolecmdexec_t *exec) {
ENGINE.running = false;
}

View File

@@ -1,42 +0,0 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "console/console.h"
#include "engine/engine.h"
#include "scene/scenemanager.h"
void cmdScene(const consolecmdexec_t *exec) {
if(exec->argc < 1) {
consolePrint("Usage: scene <name>");
return;
}
if(strcmp(exec->argv[0], "null") == 0) {
sceneManagerSetScene(NULL);
return;
}
scene_t *scene = sceneManagerGetSceneByName(exec->argv[0]);
if(scene == NULL) {
consolePrint("Error: Scene '%s' not found.", exec->argv[0]);
return;
}
sceneManagerSetScene(scene);
if(scene->init) {
errorret_t ret = errorPrint(scene->init(&SCENE_MANAGER.sceneData));
if(ret.code != ERROR_OK) {
errorCatch(ret);
sceneManagerSetScene(NULL);
consolePrint("Error: Failed to initialize scene '%s'.", exec->argv[0]);
return;
}
}
scene->flags |= SCENE_FLAG_INITIALIZED;
}

View File

@@ -1,100 +0,0 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "console/console.h"
#include "display/screen.h"
#include "util/string.h"
void cmdScreen(const consolecmdexec_t *exec) {
if(exec->argc < 1) {
consolePrint("Expected 1 argument: <mode> [value]");
return;
}
if(strcmp(exec->argv[0], "backbuffer") == 0) {
SCREEN.mode = SCREEN_MODE_BACKBUFFER;
return;
}
#if DISPLAY_SIZE_DYNAMIC == 1
if(strcmp(exec->argv[0], "fixed") == 0) {
if(exec->argc < 3) {
consolePrint("Expected 3 arguments: fixed <width> <height>");
return;
}
int32_t w, h;
if(!stringToI32(exec->argv[1], &w) || w <= 0) {
consolePrint("Invalid width: %s", exec->argv[1]);
return;
}
if(!stringToI32(exec->argv[2], &h) || h <= 0) {
consolePrint("Invalid height: %s", exec->argv[2]);
return;
}
SCREEN.mode = SCREEN_MODE_FIXED_SIZE;
SCREEN.fixedSize.width = w;
SCREEN.fixedSize.height = h;
return;
}
if(strcmp(exec->argv[0], "aspect") == 0) {
if(exec->argc < 2) {
consolePrint("Expected 2 arguments: aspect <size>");
return;
}
float_t r;
if(!stringToF32(exec->argv[1], &r) || r <= 0) {
consolePrint("Invalid aspect ratio: %s", exec->argv[1]);
return;
}
SCREEN.mode = SCREEN_MODE_ASPECT_RATIO;
SCREEN.aspectRatio.ratio = r;
return;
}
if(strcmp(exec->argv[0], "height") == 0) {
if(exec->argc < 2) {
consolePrint("Expected 2 arguments: height <size>");
return;
}
int32_t h;
if(!stringToI32(exec->argv[1], &h) || h <= 0) {
consolePrint("Invalid height: %s", exec->argv[1]);
return;
}
SCREEN.mode = SCREEN_MODE_FIXED_HEIGHT;
SCREEN.fixedHeight.height = h;
return;
}
if(strcmp(exec->argv[0], "width") == 0) {
if(exec->argc < 2) {
consolePrint("Expected 2 arguments: width <size>");
return;
}
int32_t w;
if(!stringToI32(exec->argv[1], &w) || w <= 0) {
consolePrint("Invalid width: %s", exec->argv[1]);
return;
}
SCREEN.mode = SCREEN_MODE_FIXED_WIDTH;
SCREEN.fixedWidth.width = w;
return;
}
#endif
consolePrint("Unknown mode: %s", exec->argv[0]);
}

View File

@@ -1,27 +0,0 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "console/console.h"
void cmdSet(const consolecmdexec_t *exec) {
assertTrue(exec->argc >= 2, "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[0]) != 0) continue;
consoleVarSetValue(var, exec->argv[1]);
// consolePrint("%s %s", var->name, var->value);
for(i = 0; i < var->eventCount; i++) {
assertNotNull(var->events[i], "Event is NULL");
var->events[i](var);
}
return;
}
consolePrint("Error: Variable '%s' not found.", exec->argv[0]);
}

View File

@@ -1,13 +0,0 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "console/console.h"
void cmdToggleConsole(const consolecmdexec_t *exec) {
CONSOLE.visible = !CONSOLE.visible;
}

View File

@@ -1,441 +0,0 @@
/**
* 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"
#include "input/input.h"
#include "console/cmd/cmdquit.h"
#include "console/cmd/cmdecho.h"
#include "console/cmd/cmdset.h"
#include "console/cmd/cmdget.h"
#include "console/cmd/cmdexec.h"
#include "console/cmd/cmdbind.h"
#include "console/cmd/cmdtoggleconsole.h"
#include "console/cmd/cmdalias.h"
#include "console/cmd/cmdscene.h"
#include "console/cmd/cmdscreen.h"
console_t CONSOLE;
void consoleInit() {
memoryZero(&CONSOLE, sizeof(console_t));
// Register vars
consoleRegVar("fps", "0", NULL);
// Register cmds
CONSOLE.cmdGet = consoleRegCmd("get", cmdGet);
CONSOLE.cmdSet = consoleRegCmd("set", cmdSet);
consoleRegCmd("quit", cmdQuit);
consoleRegCmd("echo", cmdEcho);
consoleRegCmd("exec", cmdExec);
consoleRegCmd("bind", cmdBind);
consoleRegCmd("toggleconsole", cmdToggleConsole);
consoleRegCmd("alias", cmdAlias);
consoleRegCmd("scene", cmdScene);
consoleRegCmd("screen", cmdScreen);
#if CONSOLE_POSIX
threadInit(&CONSOLE.thread, consoleInputThread);
threadMutexInit(&CONSOLE.execMutex);
threadStartRequest(&CONSOLE.thread);
#endif
}
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;
// Existing?
var = consoleVarGet(name);
if(var != NULL) return var;
assertTrue(
CONSOLE.variableCount < CONSOLE_VARIABLES_MAX,
"Too many console variables registered."
);
// Create
var = &CONSOLE.variables[CONSOLE.variableCount++];
consoleVarInitListener(var, name, value, event);
return var;
}
consolevar_t * consoleVarGet(const char_t *name) {
assertNotNull(name, "name must not be NULL");
for(uint32_t i = 0; i < CONSOLE.variableCount; i++) {
consolevar_t *var = &CONSOLE.variables[i];
if(stringCompare(var->name, name) == 0) return var;
}
return NULL;
}
void consolePrint(const char_t *message, ...) {
char_t buffer[CONSOLE_LINE_MAX];
va_list args;
va_start(args, message);
int32_t len = stringFormatVA(buffer, CONSOLE_LINE_MAX, message, args);
va_end(args);
// 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) {
#if CONSOLE_POSIX
threadMutexLock(&CONSOLE.execMutex);
#endif
assertNotNull(line, "line must not be NULL");
assertTrue(
CONSOLE.execBufferCount < CONSOLE_EXEC_BUFFER_MAX,
"Too many commands in the buffer."
);
char_t buffer[CONSOLE_LINE_MAX];
size_t i = 0, j = 0;
char_t c;
consoleexecstate_t state = CONSOLE_EXEC_STATE_INITIAL;
consolecmdexec_t *exec = NULL;
while(state != CONSOLE_EXEC_STATE_FULLY_PARSED) {
c = line[i];
switch(state) {
case CONSOLE_EXEC_STATE_INITIAL:
assertTrue(j == 0, "Buffer not empty?");
if(c == '\0') {
state = CONSOLE_EXEC_STATE_FULLY_PARSED;
break;
}
if(stringIsWhitespace(c) || c == ';') {
i++;
continue;
}
state = CONSOLE_EXEC_STATE_PARSE_CMD;
break;
case CONSOLE_EXEC_STATE_PARSE_CMD:
if(stringIsWhitespace(c) || c == '\0' || c == ';') {
state = CONSOLE_EXEC_STATE_CMD_PARSED;
continue;
}
if(c == '"') {
// Can't handle quotes within the command.
consolePrint("Invalid command");
while(c != '\0' && c != ';') c = line[++i];
continue;
}
buffer[j++] = c;
i++;
if(j >= CONSOLE_LINE_MAX) {
consolePrint("Command too long");
state = CONSOLE_EXEC_STATE_FULLY_PARSED;
continue;
}
break;
case CONSOLE_EXEC_STATE_CMD_PARSED:
if(j == 0) {
state = CONSOLE_EXEC_STATE_INITIAL;
continue;
}
// Create exec
assertNull(exec, "Existing command parsing?");
exec = &CONSOLE.execBuffer[CONSOLE.execBufferCount];
memoryZero(exec, sizeof(consolecmdexec_t));
buffer[j] = '\0';
stringCopy(exec->command, buffer, CONSOLE_LINE_MAX);
state = CONSOLE_EXEC_STATE_FIND_ARG;
j = 0;// Free up buffer
break;
case CONSOLE_EXEC_STATE_FIND_ARG:
if(c == '\0' || c == ';') {
state = CONSOLE_EXEC_STATE_CMD_FINISHED;
continue;
}
if(stringIsWhitespace(c)) {
i++;
continue;
}
if(c == '"') {
state = CONSOLE_EXEC_STATE_PARSE_ARG_QUOTED;
i++;
} else {
state = CONSOLE_EXEC_STATE_PARSE_ARG;
}
break;
case CONSOLE_EXEC_STATE_PARSE_ARG:
if(stringIsWhitespace(c) || c == '\0' || c == ';') {
state = CONSOLE_EXEC_STATE_ARG_PARSED;
continue;
}
buffer[j++] = c;
i++;
if(j >= CONSOLE_LINE_MAX) {
consolePrint("Arg too long");
state = CONSOLE_EXEC_STATE_FULLY_PARSED;
continue;
}
break;
case CONSOLE_EXEC_STATE_PARSE_ARG_QUOTED:
if(c == '"') {
state = CONSOLE_EXEC_STATE_ARG_PARSED;
i++;
continue;
}
if(c == '\0' || c == ';') {
consolePrint("Unterminated quote");
state = CONSOLE_EXEC_STATE_FULLY_PARSED;
continue;
}
if(c == '\\') {
c = line[++i];
if(c == '\0' || c == ';') {
consolePrint("Unterminated quote");
state = CONSOLE_EXEC_STATE_FULLY_PARSED;
continue;
}
}
buffer[j++] = c;
i++;
if(j >= CONSOLE_LINE_MAX) {
consolePrint("Arg too long");
state = CONSOLE_EXEC_STATE_FULLY_PARSED;
continue;
}
break;
case CONSOLE_EXEC_STATE_ARG_PARSED:
buffer[j] = '\0';
stringCopy(exec->argv[exec->argc++], buffer, CONSOLE_LINE_MAX);
state = CONSOLE_EXEC_STATE_FIND_ARG;
j = 0;// Free up buffer
break;
case CONSOLE_EXEC_STATE_CMD_FINISHED:
assertNotNull(exec, "No command found?");
// Now, is there a command that matches?
for(uint32_t k = 0; k < CONSOLE.commandCount; k++) {
consolecmd_t *cmd = &CONSOLE.commands[k];
if(stringCompare(cmd->name, exec->command) != 0) continue;
exec->cmd = cmd;
break;
}
if(exec->cmd == NULL) {
// Command wasn't found, is there a variable that matches?
for(uint32_t k = 0; k < CONSOLE.variableCount; k++) {
consolevar_t *var = &CONSOLE.variables[k];
if(stringCompare(var->name, exec->command) != 0) continue;
// Matching variable found, is this a GET or a SET?
if(exec->argc == 0) {
exec->cmd = CONSOLE.cmdGet;
stringCopy(exec->argv[0], exec->command, CONSOLE_LINE_MAX);
exec->argc = 1;
} else {
exec->cmd = CONSOLE.cmdSet;
stringCopy(exec->argv[1], exec->argv[0], CONSOLE_LINE_MAX);
stringCopy(exec->argv[0], exec->command, CONSOLE_LINE_MAX);
exec->argc = 2;
}
break;
}
// Variable not found, is there an alias that matches?
bool_t aliasFound = false;
for(uint32_t k = 0; k < CONSOLE.aliasCount; k++) {
consolealias_t *alias = &CONSOLE.aliases[k];
if(stringCompare(alias->alias, exec->command) != 0) continue;
// Matching alias found, we unlock the mutex and recursively call
// consoleExec to handle the alias command.
#if CONSOLE_POSIX
threadMutexUnlock(&CONSOLE.execMutex);
#endif
consoleExec(alias->command);
#if CONSOLE_POSIX
threadMutexLock(&CONSOLE.execMutex);
#endif
aliasFound = true;
break;
}
if(!aliasFound && exec->cmd == NULL) {
consolePrint("Command \"%s\" not found", exec->command);
exec = NULL;
state = CONSOLE_EXEC_STATE_INITIAL;
break;
}
}
// Prep for next command.
exec = NULL;
state = CONSOLE_EXEC_STATE_INITIAL;
CONSOLE.execBufferCount++;
break;
default:
assertUnreachable("Invalid state.");
break;
}
}
#if CONSOLE_POSIX
threadMutexUnlock(&CONSOLE.execMutex);
#endif
}
void consoleUpdate() {
#if CONSOLE_POSIX
threadMutexLock(&CONSOLE.execMutex);
#endif
// Toggle console
// if(inputPressed(INPUT_ACTION_CONSOLE)) {
// CONSOLE.visible = !CONSOLE.visible;
// }
// Anything to exec?
if(CONSOLE.execBufferCount == 0) {
#if CONSOLE_POSIX
threadMutexUnlock(&CONSOLE.execMutex);
#endif
return;
}
// Copy the exec buffer, this allows exec command to work
consolecmdexec_t execBuffer[CONSOLE_EXEC_BUFFER_MAX];
uint32_t execBufferCount = CONSOLE.execBufferCount;
memoryCopy(
execBuffer,
CONSOLE.execBuffer,
sizeof(consolecmdexec_t) * execBufferCount
);
// Clear the exec buffer and unlock so new commands can be added while we
// process the current ones.
CONSOLE.execBufferCount = 0;
#if CONSOLE_POSIX
threadMutexUnlock(&CONSOLE.execMutex);
#endif
// Exec pending buffer.
for(uint32_t i = 0; i < execBufferCount; i++) {
consolecmdexec_t *exec = &execBuffer[i];
assertNotNull(exec->cmd, "Command execution has no command.");
exec->cmd->function(exec);
}
}
void consoleDispose(void) {
#if CONSOLE_POSIX
threadStop(&CONSOLE.thread);
threadMutexDispose(&CONSOLE.execMutex);
#endif
}
#if CONSOLE_POSIX
void consoleInputThread(thread_t *thread) {
assertNotNull(thread, "Thread cannot be NULL.");
char_t line[CONSOLE_LINE_MAX];
size_t cap = 0;
struct pollfd pfd = {
.fd = STDIN_FILENO,
.events = POLLIN
};
while(!threadShouldStop(thread) && ENGINE.running) {
int32_t rc = poll(&pfd, 1, CONSOLE_POSIX_POLL_RATE);
if(rc == 0) continue;
if(rc < 0) {
if(errno == EINTR) continue; // Interrupted by signal, retry
assertUnreachable("poll() failed with unexpected error.");
}
// Check for errors or input
if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) break;
if (!(pfd.revents & POLLIN)) {
pfd.revents = 0;
continue;
}
// Read a line from stdin
if(!fgets(line, CONSOLE_LINE_MAX, stdin)) {
if (feof(stdin)) break;
clearerr(stdin);
continue;
}
// Did we read a full line or did it get truncated?
size_t len = strlen(line);
int32_t fullLine = len > 0 && line[len - 1] == '\n';
// Strip trailing newline/CR
while(len && (line[len - 1] == '\n' || line[len - 1] == '\r')) {
line[--len] = '\0';
}
if(len > 0) consoleExec(line);
pfd.revents = 0;
}
}
#endif

View File

@@ -1,135 +0,0 @@
/**
* 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"
#include "consolealias.h"
#if CONSOLE_POSIX
#include "thread/thread.h"
#include <poll.h>
#include <unistd.h>
#define CONSOLE_POSIX_POLL_RATE 75
#endif
typedef enum {
CONSOLE_EXEC_STATE_INITIAL,
CONSOLE_EXEC_STATE_PARSE_CMD,
CONSOLE_EXEC_STATE_CMD_PARSED,
CONSOLE_EXEC_STATE_FIND_ARG,
CONSOLE_EXEC_STATE_PARSE_ARG,
CONSOLE_EXEC_STATE_PARSE_ARG_QUOTED,
CONSOLE_EXEC_STATE_ARG_PARSED,
CONSOLE_EXEC_STATE_CMD_FINISHED,
CONSOLE_EXEC_STATE_FULLY_PARSED
} consoleexecstate_t;
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;
consolealias_t aliases[CONSOLE_ALIAS_MAX];
uint32_t aliasCount;
consolecmd_t *cmdGet;
consolecmd_t *cmdSet;
bool_t visible;
#if CONSOLE_POSIX
char_t inputBuffer[CONSOLE_LINE_MAX];
thread_t thread;
threadmutex_t execMutex;
#endif
} 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
);
/**
* Gets a console variable by name.
*
* @param name The name of the variable.
* @return The variable, or NULL if not found.
*/
consolevar_t * consoleVarGet(const char_t *name);
/**
* Prints a message to the console.
*
* @param message The message to print.
*/
void consolePrint(
const char_t *message,
...
);
/**
* Executes a console command. This method is thread safe and can be called from
* any thread.
*
* @param line The line to execute.
*/
void consoleExec(const char_t *line);
/**
* Processes the console's pending commands.
*/
void consoleUpdate();
/**
* Disposes of the console.
*/
void consoleDispose(void);
#if CONSOLE_POSIX
/**
* Input thread handler for posix input.
*
* @param thread The thread that is running.
*/
void consoleInputThread(thread_t *thread);
#endif

View File

@@ -1,14 +0,0 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "consolecmd.h"
typedef struct {
char_t command[CONSOLE_LINE_MAX];
char_t alias[CONSOLE_LINE_MAX];
} consolealias_t;

View File

@@ -1,27 +0,0 @@
/**
* 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;
}

View File

@@ -1,39 +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 "consoledefs.h"
typedef struct consolecmd_s consolecmd_t;
typedef struct {
consolecmd_t *cmd;
char_t command[CONSOLE_LINE_MAX];
char_t argv[CONSOLE_CMD_ARGC_MAX][CONSOLE_LINE_MAX];
uint32_t argc;
} consolecmdexec_t;
typedef void (*consolecmdfunc_t)(const consolecmdexec_t *exec);
typedef struct consolecmd_s {
char_t name[CONSOLE_CMD_NAME_MAX];
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
);

View File

@@ -1,22 +0,0 @@
/**
* 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 32
#define CONSOLE_VARIABLES_MAX 64
#define CONSOLE_LINE_MAX 128
#define CONSOLE_HISTORY_MAX 16
#define CONSOLE_EXEC_BUFFER_MAX 32
#define CONSOLE_ALIAS_MAX 32
#define CONSOLE_VAR_NAME_MAX 32
#define CONSOLE_VAR_VALUE_MAX 128
#define CONSOLE_VAR_EVENTS_MAX 8

View File

@@ -1,64 +0,0 @@
/**
* 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;
}

View File

@@ -1,65 +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 "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];
char_t value[CONSOLE_VAR_VALUE_MAX];
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);

View File

@@ -6,4 +6,7 @@
# Sources # Sources
target_sources(${DUSK_TARGET_NAME} target_sources(${DUSK_TARGET_NAME}
PRIVATE PRIVATE
) debug.c
)
# Subdirs

40
src/debug/debug.c Normal file
View File

@@ -0,0 +1,40 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "debug.h"
void debugPrint(const char_t *message, ...) {
// char_t buffer[CONSOLE_LINE_MAX];
// va_list args;
// va_start(args, message);
// int32_t len = stringFormatVA(buffer, CONSOLE_LINE_MAX, message, args);
// va_end(args);
// // 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);
va_list args;
va_start(args, message);
vprintf(message, args);
va_end(args);
// For the time being just use standard printing functions.
printf(message, args);
}

17
src/debug/debug.h Normal file
View File

@@ -0,0 +1,17 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "dusk.h"
/**
* Prints a debug message to the debug console.
*
* @param message The message format string.
* @param ... Additional arguments for the format string.
*/
void debugPrint(const char_t *message, ...);

View File

@@ -7,13 +7,13 @@
#include "display/display.h" #include "display/display.h"
#include "engine/engine.h" #include "engine/engine.h"
#include "console/console.h"
#include "display/framebuffer.h" #include "display/framebuffer.h"
#include "scene/scenemanager.h" #include "scene/scenemanager.h"
#include "display/spritebatch.h" #include "display/spritebatch.h"
#include "display/mesh/quad.h" #include "display/mesh/quad.h"
#include "display/screen.h" #include "display/screen.h"
#include "ui/ui.h" #include "ui/ui.h"
#include "debug/debug.h"
display_t DISPLAY; display_t DISPLAY;
@@ -129,7 +129,7 @@ errorret_t displayUpdate(void) {
GLenum err; GLenum err;
while((err = glGetError()) != GL_NO_ERROR) { while((err = glGetError()) != GL_NO_ERROR) {
consolePrint("GL Error: %d\n", err); debugPrint("GL Error: %d\n", err);
} }
// For now, we just return an OK error. // For now, we just return an OK error.

View File

@@ -9,8 +9,6 @@
#include "util/memory.h" #include "util/memory.h"
#include "assert/assert.h" #include "assert/assert.h"
#include "console/console.h"
void meshInit( void meshInit(
mesh_t *mesh, mesh_t *mesh,
const meshprimitivetype_t primitiveType, const meshprimitivetype_t primitiveType,

View File

@@ -8,7 +8,6 @@
#include "spritebatch.h" #include "spritebatch.h"
#include "assert/assert.h" #include "assert/assert.h"
#include "util/memory.h" #include "util/memory.h"
#include "console/console.h"
spritebatch_t SPRITEBATCH; spritebatch_t SPRITEBATCH;

View File

@@ -9,7 +9,6 @@
#include "util/memory.h" #include "util/memory.h"
#include "time/time.h" #include "time/time.h"
#include "input/input.h" #include "input/input.h"
#include "console/console.h"
#include "display/display.h" #include "display/display.h"
#include "scene/scenemanager.h" #include "scene/scenemanager.h"
#include "asset/assetmanager.h" #include "asset/assetmanager.h"
@@ -27,7 +26,6 @@ errorret_t engineInit(void) {
// Init systems. Order is important. // Init systems. Order is important.
timeInit(); timeInit();
consoleInit();
inputInit(); inputInit();
errorChain(assetManagerInit()); errorChain(assetManagerInit());
errorChain(displayInit()); errorChain(displayInit());
@@ -35,20 +33,12 @@ errorret_t engineInit(void) {
errorChain(rpgInit()); errorChain(rpgInit());
errorChain(sceneManagerInit()); errorChain(sceneManagerInit());
// Init scripts
#if PSP
consoleExec("exec config/init-psp.dcf");
#else
consoleExec("exec config/init.dcf");
#endif
errorOk(); errorOk();
} }
errorret_t engineUpdate(void) { errorret_t engineUpdate(void) {
timeUpdate(); timeUpdate();
inputUpdate(); inputUpdate();
consoleUpdate();
assetManagerUpdate(); assetManagerUpdate();
rpgUpdate(); rpgUpdate();
@@ -69,6 +59,5 @@ errorret_t engineDispose(void) {
uiDispose(); uiDispose();
errorChain(displayDispose()); errorChain(displayDispose());
assetManagerDispose(); assetManagerDispose();
consoleDispose();
errorOk(); errorOk();
} }

View File

@@ -59,31 +59,10 @@ void inputUpdate(void) {
cur++; cur++;
continue; continue;
} }
switch(cur->actionType) { INPUT.actions[cur->action].currentValue = mathMax(
case INPUT_BUTTON_ACTION_TYPE_NULL: { cur->curVal, INPUT.actions[cur->action].currentValue
break; );
}
case INPUT_BUTTON_ACTION_TYPE_COMMAND: {
if(cur->lastVal == 0.0f && cur->command[0] != '\0') {
consoleExec(cur->command);
}
break;
}
case INPUT_BUTTON_ACTION_TYPE_ACTION: {
INPUT.actions[cur->action].currentValue = mathMax(
cur->curVal, INPUT.actions[cur->action].currentValue
);
break;
}
default: {
assertUnreachable("Unknown input button action type");
break;
}
}
cur++; cur++;
} while(cur->name); } while(cur->name);
@@ -122,10 +101,11 @@ float_t inputAxis(const inputaction_t neg, const inputaction_t pos) {
return inputGetCurrentValue(pos) - inputGetCurrentValue(neg); return inputGetCurrentValue(pos) - inputGetCurrentValue(neg);
} }
void inputBind(const inputbutton_t button, const char_t *action) { void inputBind(const inputbutton_t button, const inputaction_t act) {
assertNotNull(action, "Input action is null"); assertTrue(
assertStrLenMin(action, 1, "Input action is empty"); act < INPUT_ACTION_COUNT,
assertStrLenMax(action, CONSOLE_LINE_MAX - 1, "Input action is too long"); "Invalid input action"
);
// Get the button data for this button. // Get the button data for this button.
inputbuttondata_t *data = INPUT_BUTTON_DATA; inputbuttondata_t *data = INPUT_BUTTON_DATA;
@@ -137,19 +117,6 @@ void inputBind(const inputbutton_t button, const char_t *action) {
} while(data->name != NULL); } while(data->name != NULL);
assertNotNull(data->name, "Input button not found"); assertNotNull(data->name, "Input button not found");
// Try find input action first. // Bind the action.
for(inputaction_t act = 0; act < INPUT_ACTION_COUNT; act++) { data->action = act;
if(stringCompareInsensitive(INPUT_ACTION_NAMES[act], action) != 0) {
continue;
}
// Action found.
data->actionType = INPUT_BUTTON_ACTION_TYPE_ACTION;
data->action = act;
return;
}
// No action found, treat as command.
data->actionType = INPUT_BUTTON_ACTION_TYPE_COMMAND;
stringCopy(data->command, action, CONSOLE_LINE_MAX);
} }

View File

@@ -99,10 +99,9 @@ bool_t inputReleased(const inputaction_t action);
float_t inputAxis(const inputaction_t neg, const inputaction_t pos); float_t inputAxis(const inputaction_t neg, const inputaction_t pos);
/** /**
* Binds an input button to an action. Will first check if a matching action * Binds an input button to an action.
* exists, otherwise it will be treated as a command.
* *
* @param button The input button to bind. * @param button The input button to bind.
* @param action The name of the input action or command to bind the button to. * @param action The input action to bind the button to.
*/ */
void inputBind(const inputbutton_t data, const char_t *action); void inputBind(const inputbutton_t button, const inputaction_t act);

View File

@@ -9,6 +9,7 @@
#include "dusk.h" #include "dusk.h"
typedef enum { typedef enum {
INPUT_ACTION_NULL,
INPUT_ACTION_UP, INPUT_ACTION_UP,
INPUT_ACTION_DOWN, INPUT_ACTION_DOWN,
INPUT_ACTION_LEFT, INPUT_ACTION_LEFT,

View File

@@ -111,6 +111,19 @@ inputbuttondata_t INPUT_BUTTON_DATA[] = {
{ .name = "f10", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F10 } }, { .name = "f10", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F10 } },
{ .name = "f11", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F11 } }, { .name = "f11", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F11 } },
{ .name = "f12", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F12 } }, { .name = "f12", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F12 } },
{ .name = "f13", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F13 } },
{ .name = "f14", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F14 } },
{ .name = "f15", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F15 } },
{ .name = "f16", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F16 } },
{ .name = "f17", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F17 } },
{ .name = "f18", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F18 } },
{ .name = "f19", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F19 } },
{ .name = "f20", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F20 } },
{ .name = "f21", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F21 } },
{ .name = "f22", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F22 } },
{ .name = "f23", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F23 } },
{ .name = "f24", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_F24 } },
{ .name = "minus", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_MINUS } }, { .name = "minus", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_MINUS } },
{ .name = "equals", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_EQUALS } }, { .name = "equals", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_EQUALS } },
@@ -124,6 +137,11 @@ inputbuttondata_t INPUT_BUTTON_DATA[] = {
{ .name = "period", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_PERIOD } }, { .name = "period", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_PERIOD } },
{ .name = "slash", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_SLASH } }, { .name = "slash", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_SLASH } },
{ .name = "caps", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_CAPSLOCK } },
{ .name = "capslock", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_CAPSLOCK } },
{ .name = "numlock", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_NUMLOCKCLEAR } },
{ .name = "scrollock", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_SCROLLLOCK } },
{ .name = "-", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_MINUS } }, { .name = "-", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_MINUS } },
{ .name = "=", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_EQUALS } }, { .name = "=", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_EQUALS } },
{ .name = "[", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_LEFTBRACKET } }, { .name = "[", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_LEFTBRACKET } },

View File

@@ -6,7 +6,6 @@
*/ */
#pragma once #pragma once
#include "console/console.h"
#include "inputaction.h" #include "inputaction.h"
#if INPUT_SDL2 == 1 #if INPUT_SDL2 == 1
@@ -62,23 +61,12 @@ typedef struct {
}; };
} inputbutton_t; } inputbutton_t;
typedef enum {
INPUT_BUTTON_ACTION_TYPE_NULL,
INPUT_BUTTON_ACTION_TYPE_COMMAND,
INPUT_BUTTON_ACTION_TYPE_ACTION,
} inputbuttonactiontype_t;
typedef struct { typedef struct {
const char_t *name; const char_t *name;
inputbutton_t button; inputbutton_t button;
float_t curVal; float_t curVal;
float_t lastVal; float_t lastVal;
inputbuttonactiontype_t actionType; inputaction_t action;
union {
char_t command[CONSOLE_LINE_MAX];
inputaction_t action;
};
} inputbuttondata_t; } inputbuttondata_t;
extern inputbuttondata_t INPUT_BUTTON_DATA[]; extern inputbuttondata_t INPUT_BUTTON_DATA[];

View File

@@ -6,23 +6,36 @@
*/ */
#include "engine/engine.h" #include "engine/engine.h"
#include "console/console.h" #include "asset/assetmanager.h"
#include "util/string.h"
#include "input/input.h"
int main(int argc, char **argv) { int main(int argc, char **argv) {
errorret_t ret; errorret_t ret;
ret = engineInit();
// Init engine
ret = engineInit();
if(ret.code != ERROR_OK) { if(ret.code != ERROR_OK) {
errorCatch(errorPrint(ret)); errorCatch(errorPrint(ret));
return ret.code; return ret.code;
} }
// Set console variable. This is commented out because at the moment; // Setup system path on asset manager
// Engine init happens, which needs to happen to init console if(argc > 0) {
// It also inits asset manager, and the problem is that asset manager stringCopy(
// needs to know where the sys_path is to find the asset file. ASSET_MANAGER.systemPath, argv[0],
// if(argc > 0) consoleRegVar("sys_path", argv[0], NULL); sizeof(ASSET_MANAGER.systemPath) / sizeof(char_t)
);
}
// Init the defaults for all the platforms
// #if PSP
// #else
// #if SDL2_KEYBOARD
// inputBind(inputButtonGetByName("")
// #endif
// Begin main loop
do { do {
ret = engineUpdate(); ret = engineUpdate();
if(ret.code != ERROR_OK) { if(ret.code != ERROR_OK) {

View File

@@ -8,7 +8,6 @@
#include "scenemanager.h" #include "scenemanager.h"
#include "util/memory.h" #include "util/memory.h"
#include "assert/assert.h" #include "assert/assert.h"
#include "console/console.h"
#include "display/framebuffer.h" #include "display/framebuffer.h"
#include "util/string.h" #include "util/string.h"

View File

@@ -10,5 +10,4 @@ target_sources(${DUSK_TARGET_NAME}
uitext.c uitext.c
uifps.c uifps.c
uiframe.c uiframe.c
uiconsole.c
) )

View File

@@ -6,7 +6,6 @@
*/ */
#include "ui.h" #include "ui.h"
#include "ui/uiconsole.h"
#include "ui/uifps.h" #include "ui/uifps.h"
#include "util/memory.h" #include "util/memory.h"
#include "display/tileset/tileset_minogram.h" #include "display/tileset/tileset_minogram.h"
@@ -38,7 +37,6 @@ void uiRender(void) {
// Render UI elements here // Render UI elements here
if(UI.font) { if(UI.font) {
uiConsoleRender(0, 0, UI.fontTileset, &UI.font->alphaImage.texture);
uiFPSRender(UI.fontTileset, &UI.font->alphaImage.texture); uiFPSRender(UI.fontTileset, &UI.font->alphaImage.texture);
} }

View File

@@ -1,35 +0,0 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "uiconsole.h"
#include "uitext.h"
#include "console/console.h"
void uiConsoleRender(
const float_t x,
const float_t y,
const tileset_t *tileset,
texture_t *texture
) {
if(!CONSOLE.visible) return;
int32_t i = CONSOLE_HISTORY_MAX - 1;
char_t *line;
do {
line = CONSOLE.line[i];
if(line[0] == '\0') {
i--;
continue;
}
uiTextDraw(
x, y + (i * tileset->tileHeight),
line, COLOR_WHITE,
tileset, texture
);
i--;
} while(i > 0);
}

View File

@@ -1,25 +0,0 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "display/tileset/tileset.h"
#include "display/texture.h"
/**
* Renders the console UI.
*
* @param x The x-coordinate to start rendering the console.
* @param y The y-coordinate to start rendering the console.
* @param tileset The tileset to use for rendering text.
* @param texture The texture associated with the tileset.
*/
void uiConsoleRender(
const float_t x,
const float_t y,
const tileset_t *tileset,
texture_t *texture
);

View File

@@ -7,16 +7,15 @@
#include "uifps.h" #include "uifps.h"
#include "time/time.h" #include "time/time.h"
#include "console/console.h"
#include "util/string.h" #include "util/string.h"
#include "ui/uitext.h" #include "ui/uitext.h"
#include "display/screen.h" #include "display/screen.h"
#include "display/spritebatch.h" #include "display/spritebatch.h"
bool_t UI_FPS_DRAW = true;
void uiFPSRender(const tileset_t *tileset, texture_t *texture) { void uiFPSRender(const tileset_t *tileset, texture_t *texture) {
if(stringCompare(consoleVarGet("fps")->value, "0") == 0) { if(!UI_FPS_DRAW) return;
return;
}
float_t fps = TIME.delta > 0.0f ? (1.0f / TIME.delta) : 0.0f; float_t fps = TIME.delta > 0.0f ? (1.0f / TIME.delta) : 0.0f;
char_t buffer[64]; char_t buffer[64];

View File

@@ -2,7 +2,6 @@ import sys
# from processtileset import processTileset # from processtileset import processTileset
from processimage import processImage from processimage import processImage
from processpalette import processPalette from processpalette import processPalette
from processconfig import processConfig
from processtileset import processTileset from processtileset import processTileset
from processmap import processMap from processmap import processMap
@@ -19,8 +18,6 @@ def processAsset(asset):
return processPalette(asset) return processPalette(asset)
elif t == 'image': elif t == 'image':
return processImage(asset) return processImage(asset)
elif t == 'config':
return processConfig(asset)
elif t == 'tileset': elif t == 'tileset':
return processTileset(asset) return processTileset(asset)
elif t == 'map': elif t == 'map':

View File

@@ -1,49 +0,0 @@
import os
import sys
from args import args
from assethelpers import getAssetRelativePath
from assetcache import assetGetCache, assetCache
def processConfig(asset):
assetPath = asset['path']
cache = assetGetCache(assetPath)
if cache is not None:
return cache
print(f"Processing config: {assetPath}")
# Takes each line, seperates it by either semicolon or newline,
# trims whitespace. Then outputs it to a file.
with open(assetPath, "r") as f:
lines = f.read().replace('\r', '').split('\n')
commands = []
for line in lines:
lineCommands = line.split(';')
for command in lineCommands:
command = command.strip()
if command != '':
commands.append(command)
data = bytearray()
data.extend(b"DCF") # Dusk Config File
for command in commands:
# Convert to string and seperate each command with semicolon
data.extend(command.encode('utf-8'))
data.append(0x3B) # Semicolon
if len(commands) > 0:
data.pop() # Remove last semicolon
relative = getAssetRelativePath(assetPath)
fileNameWithoutExt = os.path.splitext(os.path.basename(assetPath))[0]
outputFileRelative = os.path.join(os.path.dirname(relative), f"{fileNameWithoutExt}.dcf")
outputFilePath = os.path.join(args.output_assets, outputFileRelative)
os.makedirs(os.path.dirname(outputFilePath), exist_ok=True)
with open(outputFilePath, "wb") as f:
f.write(data)
outConfig = {
"files": [ outputFilePath ],
}
return assetCache(assetPath, outConfig)