Add psp
This commit is contained in:
@@ -7,9 +7,11 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
|
||||
|
||||
if(NOT DEFINED DUSK_TARGET_SYSTEM)
|
||||
set(DUSK_TARGET_SYSTEM "raylib")
|
||||
set(DUSK_TARGET_SYSTEM "linux")
|
||||
# set(DUSK_TARGET_SYSTEM "psp")
|
||||
endif()
|
||||
|
||||
# Prep cache
|
||||
@@ -35,6 +37,11 @@ set(DUSK_ASSETS "" CACHE INTERNAL ${DUSK_CACHE_TARGET})
|
||||
file(MAKE_DIRECTORY ${DUSK_GENERATED_HEADERS_DIR})
|
||||
file(MAKE_DIRECTORY ${DUSK_ASSETS_BUILD_DIR})
|
||||
|
||||
# Compilers
|
||||
if(DUSK_TARGET_SYSTEM STREQUAL "psp")
|
||||
find_package(pspsdk REQUIRED)
|
||||
endif()
|
||||
|
||||
# Init Project
|
||||
project(${DUSK_TARGET_NAME}
|
||||
VERSION 1.0.0
|
||||
@@ -55,3 +62,15 @@ target_include_directories(${DUSK_TARGET_NAME}
|
||||
PUBLIC
|
||||
${DUSK_GENERATED_HEADERS_DIR}
|
||||
)
|
||||
|
||||
# Postbuild, create PBP file for PSP.
|
||||
if(DUSK_TARGET_SYSTEM STREQUAL "psp")
|
||||
create_pbp_file(
|
||||
TARGET "${DUSK_TARGET_NAME}"
|
||||
ICON_PATH NULL
|
||||
BACKGROUND_PATH NULL
|
||||
PREVIEW_PATH NULL
|
||||
TITLE "${DUSK_TARGET_NAME}"
|
||||
VERSION 01.00
|
||||
)
|
||||
endif()
|
99
cmake/modules/Findpspsdk.cmake
Normal file
99
cmake/modules/Findpspsdk.cmake
Normal file
@@ -0,0 +1,99 @@
|
||||
# Copyright (c) 2025 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
if(NOT TARGET pspsdk)
|
||||
message(STATUS "Looking for PSPSDK...")
|
||||
|
||||
set(PSPSDK_FOUND FALSE CACHE INTERNAL "PSPSDK found")
|
||||
set(PSPSDK_DOWNLOAD_DIR "${CMAKE_BINARY_DIR}/_pspsdk")
|
||||
set(PSPSDK_SEARCH_ROOTS
|
||||
"${PSPSDK_ROOT}"
|
||||
"$ENV{PSPDEV}"
|
||||
"$ENV{HOME}/pspdev"
|
||||
"/usr/local/pspdev"
|
||||
"/opt/pspdev"
|
||||
"/usr/pspdev"
|
||||
"${PSPSDK_DOWNLOAD_DIR}/pspdev"
|
||||
)
|
||||
|
||||
foreach(root IN LISTS PSPSDK_SEARCH_ROOTS)
|
||||
list(APPEND PSPSDK_BIN_HINTS "${root}/bin")
|
||||
list(APPEND PSPSDK_INCLUDE_HINTS "${root}/include")
|
||||
list(APPEND PSPSDK_LIB_HINTS "${root}/lib")
|
||||
endforeach()
|
||||
|
||||
# Find PSP GCC
|
||||
find_program(PSPSDK_PSP_GCC NAMES psp-gcc HINTS ${PSPSDK_BIN_HINTS})
|
||||
|
||||
# If we did not find it, download it.
|
||||
if(NOT PSPSDK_PSP_GCC)
|
||||
message(STATUS "psp-gcc not found in system paths. Downloading PSPSDK tarball...")
|
||||
file(DOWNLOAD
|
||||
"https://github.com/pspdev/pspdev/releases/latest/download/pspdev-ubuntu-latest-x86_64.tar.gz"
|
||||
"${CMAKE_BINARY_DIR}/pspsdk.tar.gz"
|
||||
EXPECTED_HASH SHA256=afe338e92f6eeec21c56a64eeb65201e6b95ecbae938ae38688bbf0f17b69ead
|
||||
SHOW_PROGRESS
|
||||
)
|
||||
|
||||
# Make output dir
|
||||
file(MAKE_DIRECTORY "${PSPSDK_DOWNLOAD_DIR}")
|
||||
|
||||
# Extract the tarball
|
||||
execute_process(
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E tar xzf "${CMAKE_BINARY_DIR}/pspsdk.tar.gz"
|
||||
WORKING_DIRECTORY
|
||||
"${PSPSDK_DOWNLOAD_DIR}"
|
||||
RESULT_VARIABLE
|
||||
tar_result
|
||||
)
|
||||
if(NOT tar_result EQUAL 0)
|
||||
message(FATAL_ERROR "Failed to extract PSPSDK tarball")
|
||||
endif()
|
||||
|
||||
# Retry discovery with extracted fallback
|
||||
find_program(PSPSDK_PSP_GCC NAMES psp-gcc HINTS ${PSPSDK_BIN_HINTS})
|
||||
endif()
|
||||
|
||||
if(PSPSDK_PSP_GCC)
|
||||
get_filename_component(PSPSDK_BIN_ROOT "${PSPSDK_PSP_GCC}" DIRECTORY)
|
||||
get_filename_component(PSPSDK_ROOT "${PSPSDK_BIN_ROOT}" DIRECTORY)
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
||||
set(ENV{PSPDEV} "${PSPSDK_ROOT}")
|
||||
set(CMAKE_TOOLCHAIN_FILE "${PSPSDK_ROOT}/psp/share/pspdev.cmake")
|
||||
set(BUILD_PRX ON CACHE BOOL "Build PRX modules")
|
||||
|
||||
include("${PSPSDK_ROOT}/psp/share/pspdev.cmake")
|
||||
set(CMAKE_C_COMPILER ${PSPSDK_BIN_ROOT}/psp-gcc)
|
||||
set(CMAKE_CXX_COMPILER ${PSPSDK_BIN_ROOT}/psp-g++)
|
||||
|
||||
if(NOT DEFINED PSP)
|
||||
message(FATAL_ERROR "PSP environment variable is not set correctly.")
|
||||
endif()
|
||||
|
||||
add_library(pspsdk INTERFACE IMPORTED)
|
||||
set_target_properties(pspsdk PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${PSPSDK_INCLUDE_DIR}"
|
||||
INTERFACE_LINK_DIRECTORIES "${PSPSDK_LIB_DIR}"
|
||||
)
|
||||
target_include_directories(pspsdk
|
||||
INTERFACE
|
||||
${PSPDEV}/psp/include
|
||||
${PSPDEV}/psp/sdk/include
|
||||
)
|
||||
target_link_directories(pspsdk
|
||||
INTERFACE
|
||||
${PSPDEV}/lib
|
||||
${PSPDEV}/psp/lib
|
||||
${PSPDEV}/psp/sdk/lib
|
||||
)
|
||||
target_link_libraries(pspsdk INTERFACE
|
||||
pspdebug
|
||||
pspdisplay
|
||||
pspge
|
||||
pspctrl
|
||||
)
|
||||
endif()
|
||||
endif()
|
20
cmake/modules/Findraylib.cmake
Normal file
20
cmake/modules/Findraylib.cmake
Normal file
@@ -0,0 +1,20 @@
|
||||
# Copyright (c) 2025 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
raylib
|
||||
URL https://github.com/raysan5/raylib/archive/refs/tags/5.5.tar.gz
|
||||
URL_HASH MD5=61638c4c2c097fbca1d6a71e4da36c16
|
||||
)
|
||||
FetchContent_GetProperties(raylib)
|
||||
FetchContent_MakeAvailable(raylib)
|
||||
|
||||
# Define expected target if not already defined
|
||||
if(NOT TARGET raylib)
|
||||
set(raylib_FOUND FALSE CACHE INTERNAL "Whether raylib was found")
|
||||
else()
|
||||
set(raylib_FOUND TRUE CACHE INTERNAL "Whether raylib was found")
|
||||
endif()
|
@@ -5,6 +5,10 @@
|
||||
|
||||
add_subdirectory(dusk)
|
||||
|
||||
if(DUSK_TARGET_SYSTEM STREQUAL "raylib")
|
||||
if(DUSK_TARGET_SYSTEM STREQUAL "linux")
|
||||
add_subdirectory(duskraylib)
|
||||
elseif(DUSK_TARGET_SYSTEM STREQUAL "psp")
|
||||
add_subdirectory(duskpsp)
|
||||
else()
|
||||
message(FATAL_ERROR "Unsupported target system: ${DUSK_TARGET_SYSTEM}")
|
||||
endif()
|
@@ -10,19 +10,20 @@ target_link_libraries(${DUSK_TARGET_NAME}
|
||||
|
||||
# Includes
|
||||
target_include_directories(${DUSK_TARGET_NAME}
|
||||
PUBLIC
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
)
|
||||
|
||||
# Sources
|
||||
target_sources(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
main.c
|
||||
game.c
|
||||
input.c
|
||||
)
|
||||
|
||||
# Subdirs
|
||||
add_subdirectory(assert)
|
||||
add_subdirectory(console)
|
||||
add_subdirectory(display)
|
||||
add_subdirectory(entity)
|
||||
add_subdirectory(event)
|
||||
|
12
src/dusk/console/CMakeLists.txt
Normal file
12
src/dusk/console/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
# 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
|
||||
)
|
395
src/dusk/console/console.c
Normal file
395
src/dusk/console/console.c
Normal file
@@ -0,0 +1,395 @@
|
||||
/**
|
||||
* 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.h"
|
||||
|
||||
console_t CONSOLE;
|
||||
|
||||
void consoleInit() {
|
||||
memoryZero(&CONSOLE, sizeof(console_t));
|
||||
pthread_mutex_init(&CONSOLE.lock, NULL); // Initialize the mutex
|
||||
|
||||
// Register the get and set command.
|
||||
CONSOLE.cmdGet = consoleRegCmd("get", cmdGet);
|
||||
CONSOLE.cmdSet = consoleRegCmd("set", cmdSet);
|
||||
consoleRegCmd("echo", cmdEcho);
|
||||
|
||||
consolePrint(" = Dawn Console = ");
|
||||
}
|
||||
|
||||
consolecmd_t * consoleRegCmd(const char_t *name, consolecmdfunc_t function) {
|
||||
pthread_mutex_lock(&CONSOLE.lock); // Lock
|
||||
consolecmd_t *cmd = &CONSOLE.commands[CONSOLE.commandCount++];
|
||||
consoleCmdInit(cmd, name, function);
|
||||
pthread_mutex_unlock(&CONSOLE.lock); // Unlock
|
||||
return cmd;
|
||||
}
|
||||
|
||||
consolevar_t * consoleRegVar(
|
||||
const char_t *name,
|
||||
const char_t *value,
|
||||
consolevarchanged_t event
|
||||
) {
|
||||
pthread_mutex_lock(&CONSOLE.lock); // Lock
|
||||
consolevar_t *var = &CONSOLE.variables[CONSOLE.variableCount++];
|
||||
consoleVarInitListener(var, name, value, event);
|
||||
pthread_mutex_unlock(&CONSOLE.lock); // Unlock
|
||||
return var;
|
||||
}
|
||||
|
||||
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) {
|
||||
pthread_mutex_lock(&CONSOLE.lock); // Lock
|
||||
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;
|
||||
}
|
||||
|
||||
if(exec->cmd == NULL) {
|
||||
consolePrint("Command 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;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&CONSOLE.lock); // Unlock
|
||||
}
|
||||
|
||||
void consoleProcess() {
|
||||
pthread_mutex_lock(&CONSOLE.lock); // Lock
|
||||
for(uint32_t i = 0; i < CONSOLE.execBufferCount; i++) {
|
||||
consolecmdexec_t *exec = &CONSOLE.execBuffer[i];
|
||||
|
||||
assertNotNull(exec->cmd, "Command execution has no command.");
|
||||
|
||||
exec->cmd->function(exec);
|
||||
}
|
||||
|
||||
// Clear the exec buffer
|
||||
CONSOLE.execBufferCount = 0;
|
||||
pthread_mutex_unlock(&CONSOLE.lock); // Unlock
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
void cmdEcho(const consolecmdexec_t *exec) {
|
||||
assertTrue(
|
||||
exec->argc >= 1,
|
||||
"echo command requires 1 argument."
|
||||
);
|
||||
|
||||
consolePrint("%s", exec->argv[0]);
|
||||
}
|
||||
|
||||
// May move these later
|
||||
void consoleUpdate() {
|
||||
if(inputIsPressed(INPUT_TOGGLE_CONSOLE)) {
|
||||
CONSOLE.open = !CONSOLE.open;
|
||||
} else if(CONSOLE.open) {
|
||||
switch(INPUT.keyPressed) {
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case KEY_ENTER:
|
||||
consoleExec(CONSOLE.inputBuffer);
|
||||
CONSOLE.inputIndex = 0;
|
||||
CONSOLE.inputBuffer[0] = '\0';
|
||||
break;
|
||||
|
||||
case KEY_BACKSPACE:
|
||||
if(CONSOLE.inputIndex > 0) {
|
||||
CONSOLE.inputIndex--;
|
||||
CONSOLE.inputBuffer[CONSOLE.inputIndex] = '\0';
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if(
|
||||
INPUT.keyPressed >= 32 &&
|
||||
INPUT.keyPressed <= 126 &&
|
||||
CONSOLE.inputIndex < CONSOLE_LINE_MAX - 1
|
||||
) {
|
||||
CONSOLE.inputBuffer[CONSOLE.inputIndex++] = INPUT.charPressed;
|
||||
CONSOLE.inputBuffer[CONSOLE.inputIndex] = '\0';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
consoleProcess();
|
||||
}
|
||||
|
||||
void consoleDraw() {
|
||||
if(!CONSOLE.open) return;
|
||||
|
||||
size_t i = 0;
|
||||
char_t *line;
|
||||
int32_t fontSize = 10;
|
||||
do {
|
||||
line = CONSOLE.line[i];
|
||||
if(line[0] == '\0') {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
DrawText(line, 0, i*fontSize, fontSize, YELLOW);
|
||||
i++;
|
||||
} while(i < CONSOLE_HISTORY_MAX);
|
||||
|
||||
DrawText(
|
||||
CONSOLE.inputBuffer, 0,
|
||||
(CONSOLE_HISTORY_MAX + 1) * fontSize,
|
||||
fontSize,
|
||||
PINK
|
||||
);
|
||||
}
|
114
src/dusk/console/console.h
Normal file
114
src/dusk/console/console.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* 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 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;
|
||||
|
||||
consolecmd_t *cmdGet;
|
||||
consolecmd_t *cmdSet;
|
||||
pthread_mutex_t lock; // Mutex for thread safety
|
||||
|
||||
// May move these later
|
||||
char_t inputBuffer[CONSOLE_LINE_MAX];
|
||||
int32_t inputIndex;
|
||||
|
||||
bool_t open;
|
||||
} 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();
|
||||
|
||||
/**
|
||||
* Updates the console's input buffer and handles user input.
|
||||
*/
|
||||
void consoleUpdate();
|
||||
|
||||
/**
|
||||
* Draws the console's output.
|
||||
*/
|
||||
void consoleDraw();
|
||||
|
||||
void cmdGet(const consolecmdexec_t *exec);
|
||||
void cmdSet(const consolecmdexec_t *exec);
|
||||
void cmdEcho(const consolecmdexec_t *exec);
|
27
src/dusk/console/consolecmd.c
Normal file
27
src/dusk/console/consolecmd.c
Normal file
@@ -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;
|
||||
}
|
39
src/dusk/console/consolecmd.h
Normal file
39
src/dusk/console/consolecmd.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* 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
|
||||
);
|
21
src/dusk/console/consoledefs.h
Normal file
21
src/dusk/console/consoledefs.h
Normal file
@@ -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
|
64
src/dusk/console/consolevar.c
Normal file
64
src/dusk/console/consolevar.c
Normal file
@@ -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;
|
||||
}
|
||||
|
65
src/dusk/console/consolevar.h
Normal file
65
src/dusk/console/consolevar.h
Normal file
@@ -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];
|
||||
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);
|
@@ -27,10 +27,3 @@ void renderDraw(void);
|
||||
* Disposes of the rendering system.
|
||||
*/
|
||||
void renderDispose(void);
|
||||
|
||||
/**
|
||||
* Checks if the rendering system should exit.
|
||||
*
|
||||
* @return true if the rendering system should exit, false otherwise.
|
||||
*/
|
||||
bool_t renderShouldExit();
|
@@ -5,7 +5,7 @@
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "display/render.h"
|
||||
#include "game.h"
|
||||
#include "util/memory.h"
|
||||
#include "world/chunk.h"
|
||||
#include "display/scene.h"
|
||||
@@ -14,28 +14,23 @@
|
||||
#include "event/event.h"
|
||||
#include "ui/uitextbox.h"
|
||||
|
||||
// Press F5 to compile and run the compiled game.gb in the Emulicous Emulator/Debugger
|
||||
void main(void) {
|
||||
renderInit();
|
||||
void gameInit(void) {
|
||||
inputInit();
|
||||
eventInit();
|
||||
uiTextboxInit();
|
||||
|
||||
overworldInit();
|
||||
|
||||
SCENE_CURRENT = SCENE_OVERWORLD;
|
||||
}
|
||||
|
||||
while(!renderShouldExit()) {
|
||||
RENDER_FRAME++;
|
||||
renderDraw();
|
||||
|
||||
void gameUpdate(void) {
|
||||
overworldUpdate();
|
||||
uiTextboxUpdate();
|
||||
eventUpdate();
|
||||
|
||||
// Update input for next frame.
|
||||
inputUpdate();
|
||||
}
|
||||
|
||||
renderDispose();
|
||||
}
|
||||
|
||||
void gameDispose(void) {
|
||||
|
||||
}
|
42
src/dusk/game.h
Normal file
42
src/dusk/game.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
|
||||
/**
|
||||
* Initializes the game, this should be called before any other game functions.
|
||||
* This should be called by the parent platform at a time that it deems
|
||||
* appropriate. Any game systems cannot be used until this function has
|
||||
* been called.
|
||||
*
|
||||
* By the point this is called, we expect;
|
||||
* - Rendering has initialized and is ready to draw.
|
||||
* - Input has been initialized and is ready to be read.
|
||||
* - If your system handles time dynamically, it should be ready to be used.
|
||||
*
|
||||
* The systems called (in order) are;
|
||||
* - Input system (Not the platforms input, but the game's input system).
|
||||
* - Time system (if applicable).
|
||||
* - Event System
|
||||
* - UI Systems.
|
||||
* - Gameplay systems.
|
||||
*/
|
||||
void gameInit(void);
|
||||
|
||||
/**
|
||||
* Asks the game to update, this will not do any drawing and should be called
|
||||
* in the main loop of the system, ideally either after or before the rendering
|
||||
* has occured.
|
||||
*/
|
||||
void gameUpdate(void);
|
||||
|
||||
/**
|
||||
* Cleans up resources used by the game, rendering really should still be
|
||||
* available at this point because we want to cleanup nicely.
|
||||
*/
|
||||
void gameDispose(void);
|
@@ -8,4 +8,5 @@ target_sources(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
fixed.c
|
||||
memory.c
|
||||
string.c
|
||||
)
|
127
src/dusk/util/string.c
Normal file
127
src/dusk/util/string.c
Normal file
@@ -0,0 +1,127 @@
|
||||
/**
|
||||
* 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"
|
||||
#include "util/memory.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");
|
||||
assertTrue(destSize > 0, "destSize must be greater than 0");
|
||||
assertStrLenMax(src, destSize, "src is too long");
|
||||
memoryCopy(dest, src, strlen(src) + 1);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int32_t stringFormat(
|
||||
char_t *dest,
|
||||
const size_t destSize,
|
||||
char_t *format,
|
||||
...
|
||||
) {
|
||||
assertNotNull(dest, "dest must not be NULL");
|
||||
assertNotNull(format, "format must not be NULL");
|
||||
assertTrue(destSize > 0, "destSize must be greater than 0");
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int32_t result = stringFormatVA(dest, destSize, format, args);
|
||||
va_end(args);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t stringFormatVA(
|
||||
char_t *dest,
|
||||
const size_t destSize,
|
||||
const char_t *format,
|
||||
va_list args
|
||||
) {
|
||||
assertNotNull(dest, "dest must not be NULL");
|
||||
assertNotNull(format, "format must not be NULL");
|
||||
assertTrue(destSize > 0, "destSize must be greater than 0");
|
||||
int32_t ret = vsnprintf(dest, destSize, format, args);
|
||||
assertTrue(ret >= 0, "Failed to format string.");
|
||||
assertTrue(ret < destSize, "Formatted string is too long.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool_t stringToI32(const char_t *str, int32_t *out) {
|
||||
assertNotNull(str, "str must not be NULL");
|
||||
assertNotNull(out, "out must not be NULL");
|
||||
|
||||
char_t *endptr;
|
||||
errno = 0;
|
||||
long int result = strtol(str, &endptr, 10);
|
||||
if (errno != 0 || *endptr != '\0') {
|
||||
return false;
|
||||
}
|
||||
*out = (int32_t)result;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool_t stringToI64(const char_t *str, int64_t *out) {
|
||||
assertNotNull(str, "str must not be NULL");
|
||||
assertNotNull(out, "out must not be NULL");
|
||||
|
||||
char_t *endptr;
|
||||
errno = 0;
|
||||
long long int result = strtoll(str, &endptr, 10);
|
||||
if (errno != 0 || *endptr != '\0') {
|
||||
return false;
|
||||
}
|
||||
*out = (int64_t)result;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool_t stringToU16(const char_t *str, uint16_t *out) {
|
||||
assertNotNull(str, "str must not be NULL");
|
||||
assertNotNull(out, "out must not be NULL");
|
||||
|
||||
char_t *endptr;
|
||||
errno = 0;
|
||||
unsigned long int result = strtoul(str, &endptr, 10);
|
||||
if (errno != 0 || *endptr != '\0' || result > UINT16_MAX) {
|
||||
return false;
|
||||
}
|
||||
*out = (uint16_t)result;
|
||||
return true;
|
||||
}
|
109
src/dusk/util/string.h
Normal file
109
src/dusk/util/string.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Formats a string.
|
||||
*
|
||||
* @param dest The destination string.
|
||||
* @param destSize The size of the destination string exc. null terminator.
|
||||
* @param format The format string.
|
||||
* @param ... The arguments to format.
|
||||
* @return The number of characters written.
|
||||
*/
|
||||
int32_t stringFormat(char_t *dest, const size_t destSize, char_t *format, ...);
|
||||
|
||||
/**
|
||||
* Formats a string using a va_list.
|
||||
*
|
||||
* @param dest The destination string.
|
||||
* @param destSize The size of the destination string exc. null terminator.
|
||||
* @param format The format string.
|
||||
* @param args The va_list of arguments.
|
||||
* @return The number of characters written.
|
||||
*/
|
||||
int32_t stringFormatVA(
|
||||
char_t *dest,
|
||||
const size_t destSize,
|
||||
const char_t *format,
|
||||
va_list args
|
||||
);
|
||||
|
||||
/**
|
||||
* Converts a string to an integer.
|
||||
*
|
||||
* @param str The string to convert.
|
||||
* @param out The output integer.
|
||||
* @return TRUE if the conversion was successful, FALSE otherwise.
|
||||
*/
|
||||
bool_t stringToI32(const char_t *str, int32_t *out);
|
||||
|
||||
/**
|
||||
* Converts a string to a signed 16-bit integer.
|
||||
*
|
||||
* @param str The string to convert.
|
||||
* @param out The output signed integer.
|
||||
* @return TRUE if the conversion was successful, FALSE otherwise.
|
||||
*/
|
||||
bool_t stringToI16(const char_t *str, int16_t *out);
|
||||
|
||||
/**
|
||||
* Converts a string to an unsigned 16-bit integer.
|
||||
*
|
||||
* @param str The string to convert.
|
||||
* @param out The output unsigned integer.
|
||||
* @return TRUE if the conversion was successful, FALSE otherwise.
|
||||
*/
|
||||
bool_t stringToU16(const char_t *str, uint16_t *out);
|
29
src/duskpsp/CMakeLists.txt
Normal file
29
src/duskpsp/CMakeLists.txt
Normal file
@@ -0,0 +1,29 @@
|
||||
# Copyright (c) 2025 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Libs
|
||||
find_package(pspsdk REQUIRED)
|
||||
|
||||
target_link_libraries(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
pspsdk
|
||||
)
|
||||
|
||||
# Includes
|
||||
target_include_directories(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
)
|
||||
|
||||
# Sources
|
||||
target_sources(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
input.c
|
||||
main.c
|
||||
duskpsp.c
|
||||
)
|
||||
|
||||
# Subdirs
|
||||
add_subdirectory(display)
|
12
src/duskpsp/display/CMakeLists.txt
Normal file
12
src/duskpsp/display/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
# 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
|
||||
render.c
|
||||
)
|
||||
|
||||
# Subdirs
|
42
src/duskpsp/display/render.c
Normal file
42
src/duskpsp/display/render.c
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "render.h"
|
||||
#include "input.h"
|
||||
|
||||
void renderInit(void) {
|
||||
pspDebugScreenInit();
|
||||
}
|
||||
|
||||
void renderDraw(void) {
|
||||
sceDisplayWaitVblankStart();
|
||||
pspDebugScreenSetXY(0, 2);
|
||||
|
||||
pspDebugScreenPrintf("Checking buttons \n");
|
||||
if(inputIsDown(INPUT_BIND_UP)) {
|
||||
pspDebugScreenPrintf("Up pressed\n");
|
||||
}
|
||||
if(inputIsDown(INPUT_BIND_DOWN)) {
|
||||
pspDebugScreenPrintf("Down pressed\n");
|
||||
}
|
||||
if(inputIsDown(INPUT_BIND_LEFT)) {
|
||||
pspDebugScreenPrintf("Left pressed\n");
|
||||
}
|
||||
if(inputIsDown(INPUT_BIND_RIGHT)) {
|
||||
pspDebugScreenPrintf("Right pressed\n");
|
||||
}
|
||||
if(inputIsDown(INPUT_BIND_ACTION)) {
|
||||
pspDebugScreenPrintf("Action pressed\n");
|
||||
}
|
||||
if(inputIsDown(INPUT_BIND_CANCEL)) {
|
||||
pspDebugScreenPrintf("Cancel pressed\n");
|
||||
}
|
||||
}
|
||||
|
||||
void renderDispose(void) {
|
||||
|
||||
}
|
10
src/duskpsp/display/render.h
Normal file
10
src/duskpsp/display/render.h
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "duskpsp.h"
|
||||
#include "display/renderbase.h"
|
11
src/duskpsp/duskpsp.c
Normal file
11
src/duskpsp/duskpsp.c
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "duskpsp.h"
|
||||
|
||||
PSP_MODULE_INFO("Dusk", 0, 1, 0);
|
||||
PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER | THREAD_ATTR_VFPU);
|
13
src/duskpsp/duskpsp.h
Normal file
13
src/duskpsp/duskpsp.h
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
#include <pspkernel.h>
|
||||
#include <pspdebug.h>
|
||||
#include <pspdisplay.h>
|
||||
#include <pspctrl.h>
|
27
src/duskpsp/input.c
Normal file
27
src/duskpsp/input.c
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "duskpsp.h"
|
||||
#include "input.h"
|
||||
|
||||
uint8_t inputStateGet() {
|
||||
SceCtrlData pad;
|
||||
sceCtrlReadBufferPositive(&pad, 1);
|
||||
|
||||
if(pad.Buttons == 0) return 0;
|
||||
|
||||
uint8_t state = 0;
|
||||
if(pad.Buttons & PSP_CTRL_UP) state |= INPUT_BIND_UP;
|
||||
if(pad.Buttons & PSP_CTRL_DOWN) state |= INPUT_BIND_DOWN;
|
||||
if(pad.Buttons & PSP_CTRL_LEFT) state |= INPUT_BIND_LEFT;
|
||||
if(pad.Buttons & PSP_CTRL_RIGHT) state |= INPUT_BIND_RIGHT;
|
||||
|
||||
if(pad.Buttons & PSP_CTRL_CROSS) state |= INPUT_BIND_ACTION;
|
||||
if(pad.Buttons & PSP_CTRL_CIRCLE) state |= INPUT_BIND_CANCEL;
|
||||
|
||||
return state;
|
||||
}
|
46
src/duskpsp/main.c
Normal file
46
src/duskpsp/main.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "display/render.h"
|
||||
#include "game.h"
|
||||
|
||||
int_t exit_callback(int arg1, int arg2, void *common) {
|
||||
sceKernelExitGame();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int_t callback_thread(SceSize args, void *argp) {
|
||||
int cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
|
||||
sceKernelRegisterExitCallback(cbid);
|
||||
sceKernelSleepThreadCB();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int_t setup_callbacks(void) {
|
||||
int thid = sceKernelCreateThread("update_thread", callback_thread, 0x11, 0xFA0, 0, 0);
|
||||
if(thid >= 0) {
|
||||
sceKernelStartThread(thid, 0, 0);
|
||||
}
|
||||
return thid;
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
setup_callbacks();
|
||||
renderInit();
|
||||
gameInit();
|
||||
|
||||
sceCtrlSetSamplingCycle(0);
|
||||
sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);
|
||||
|
||||
while(true) {
|
||||
gameUpdate();
|
||||
renderDraw();
|
||||
}
|
||||
|
||||
gameDispose();
|
||||
renderDispose();
|
||||
}
|
@@ -3,15 +3,8 @@
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
# Libs
|
||||
FetchContent_Declare(
|
||||
raylib
|
||||
URL https://github.com/raysan5/raylib/archive/refs/tags/5.5.tar.gz
|
||||
URL_HASH MD5=61638c4c2c097fbca1d6a71e4da36c16
|
||||
)
|
||||
FetchContent_MakeAvailable(raylib)
|
||||
find_package(raylib REQUIRED)
|
||||
|
||||
target_link_libraries(${DUSK_TARGET_NAME}
|
||||
PUBLIC
|
||||
|
@@ -87,7 +87,3 @@ void renderDispose(void) {
|
||||
UnloadTexture(RENDER_ENTITIES_TEXTURE);
|
||||
CloseWindow();
|
||||
}
|
||||
|
||||
bool_t renderShouldExit() {
|
||||
return WindowShouldClose();
|
||||
}
|
21
src/duskraylib/main.c
Normal file
21
src/duskraylib/main.c
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "display/render.h"
|
||||
#include "game.h"
|
||||
|
||||
void main(void) {
|
||||
gameInit();
|
||||
|
||||
while(!WindowShouldClose()) {
|
||||
gameUpdate();
|
||||
renderDraw();
|
||||
}
|
||||
|
||||
gameDispose();
|
||||
renderDispose();
|
||||
}
|
Reference in New Issue
Block a user