iuno
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@ -88,4 +88,7 @@ assets/borrowed
|
|||||||
|
|
||||||
*~
|
*~
|
||||||
|
|
||||||
/dist
|
/dist
|
||||||
|
|
||||||
|
/archive0
|
||||||
|
/archive1
|
@ -5,45 +5,10 @@
|
|||||||
|
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
# GLFW
|
# RayLib
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
glfw
|
raylib
|
||||||
GIT_REPOSITORY https://github.com/glfw/glfw
|
GIT_REPOSITORY https://github.com/raysan5/raylib
|
||||||
GIT_TAG 3.4
|
GIT_TAG 5.5
|
||||||
)
|
)
|
||||||
FetchContent_MakeAvailable(glfw)
|
FetchContent_MakeAvailable(raylib)
|
||||||
|
|
||||||
# GLAD (For GLFW)
|
|
||||||
add_subdirectory(glad)
|
|
||||||
|
|
||||||
# CGLM
|
|
||||||
FetchContent_Declare(
|
|
||||||
cglm
|
|
||||||
GIT_REPOSITORY https://github.com/recp/cglm
|
|
||||||
GIT_TAG v0.9.4
|
|
||||||
)
|
|
||||||
FetchContent_MakeAvailable(cglm)
|
|
||||||
|
|
||||||
#LibArchive
|
|
||||||
FetchContent_Declare(
|
|
||||||
libarchive
|
|
||||||
GIT_REPOSITORY https://github.com/libarchive/libarchive
|
|
||||||
GIT_TAG v3.7.6
|
|
||||||
)
|
|
||||||
FetchContent_MakeAvailable(libarchive)
|
|
||||||
|
|
||||||
#libspng
|
|
||||||
FetchContent_Declare(
|
|
||||||
libspng
|
|
||||||
GIT_REPOSITORY https://github.com/randy408/libspng
|
|
||||||
GIT_TAG v0.7.4
|
|
||||||
)
|
|
||||||
FetchContent_MakeAvailable(libspng)
|
|
||||||
|
|
||||||
# SDL2
|
|
||||||
# FetchContent_Declare(
|
|
||||||
# SDL2
|
|
||||||
# GIT_REPOSITORY https://github.com/libsdl-org/SDL
|
|
||||||
# GIT_TAG release-2.0.14
|
|
||||||
# )
|
|
||||||
# FetchContent_MakeAvailable(SDL2)
|
|
@ -1,12 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.11)
|
|
||||||
project(glad)
|
|
||||||
set(CMAKE_C_STANDARD 99)
|
|
||||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
|
||||||
|
|
||||||
add_library(${PROJECT_NAME}
|
|
||||||
src/glad.c
|
|
||||||
)
|
|
||||||
target_include_directories(${PROJECT_NAME}
|
|
||||||
PUBLIC
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
|
||||||
)
|
|
@ -1,311 +0,0 @@
|
|||||||
#ifndef __khrplatform_h_
|
|
||||||
#define __khrplatform_h_
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Copyright (c) 2008-2018 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
** copy of this software and/or associated documentation files (the
|
|
||||||
** "Materials"), to deal in the Materials without restriction, including
|
|
||||||
** without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
|
||||||
** permit persons to whom the Materials are furnished to do so, subject to
|
|
||||||
** the following conditions:
|
|
||||||
**
|
|
||||||
** The above copyright notice and this permission notice shall be included
|
|
||||||
** in all copies or substantial portions of the Materials.
|
|
||||||
**
|
|
||||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Khronos platform-specific types and definitions.
|
|
||||||
*
|
|
||||||
* The master copy of khrplatform.h is maintained in the Khronos EGL
|
|
||||||
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
|
|
||||||
* The last semantic modification to khrplatform.h was at commit ID:
|
|
||||||
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692
|
|
||||||
*
|
|
||||||
* Adopters may modify this file to suit their platform. Adopters are
|
|
||||||
* encouraged to submit platform specific modifications to the Khronos
|
|
||||||
* group so that they can be included in future versions of this file.
|
|
||||||
* Please submit changes by filing pull requests or issues on
|
|
||||||
* the EGL Registry repository linked above.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the Implementer's Guidelines for information about where this file
|
|
||||||
* should be located on your system and for more details of its use:
|
|
||||||
* http://www.khronos.org/registry/implementers_guide.pdf
|
|
||||||
*
|
|
||||||
* This file should be included as
|
|
||||||
* #include <KHR/khrplatform.h>
|
|
||||||
* by Khronos client API header files that use its types and defines.
|
|
||||||
*
|
|
||||||
* The types in khrplatform.h should only be used to define API-specific types.
|
|
||||||
*
|
|
||||||
* Types defined in khrplatform.h:
|
|
||||||
* khronos_int8_t signed 8 bit
|
|
||||||
* khronos_uint8_t unsigned 8 bit
|
|
||||||
* khronos_int16_t signed 16 bit
|
|
||||||
* khronos_uint16_t unsigned 16 bit
|
|
||||||
* khronos_int32_t signed 32 bit
|
|
||||||
* khronos_uint32_t unsigned 32 bit
|
|
||||||
* khronos_int64_t signed 64 bit
|
|
||||||
* khronos_uint64_t unsigned 64 bit
|
|
||||||
* khronos_intptr_t signed same number of bits as a pointer
|
|
||||||
* khronos_uintptr_t unsigned same number of bits as a pointer
|
|
||||||
* khronos_ssize_t signed size
|
|
||||||
* khronos_usize_t unsigned size
|
|
||||||
* khronos_float_t signed 32 bit floating point
|
|
||||||
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
|
|
||||||
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
|
|
||||||
* nanoseconds
|
|
||||||
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
|
|
||||||
* khronos_boolean_enum_t enumerated boolean type. This should
|
|
||||||
* only be used as a base type when a client API's boolean type is
|
|
||||||
* an enum. Client APIs which use an integer or other type for
|
|
||||||
* booleans cannot use this as the base type for their boolean.
|
|
||||||
*
|
|
||||||
* Tokens defined in khrplatform.h:
|
|
||||||
*
|
|
||||||
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
|
|
||||||
*
|
|
||||||
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
|
|
||||||
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
|
|
||||||
*
|
|
||||||
* Calling convention macros defined in this file:
|
|
||||||
* KHRONOS_APICALL
|
|
||||||
* KHRONOS_APIENTRY
|
|
||||||
* KHRONOS_APIATTRIBUTES
|
|
||||||
*
|
|
||||||
* These may be used in function prototypes as:
|
|
||||||
*
|
|
||||||
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
|
|
||||||
* int arg1,
|
|
||||||
* int arg2) KHRONOS_APIATTRIBUTES;
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
|
|
||||||
# define KHRONOS_STATIC 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
|
||||||
* Definition of KHRONOS_APICALL
|
|
||||||
*-------------------------------------------------------------------------
|
|
||||||
* This precedes the return type of the function in the function prototype.
|
|
||||||
*/
|
|
||||||
#if defined(KHRONOS_STATIC)
|
|
||||||
/* If the preprocessor constant KHRONOS_STATIC is defined, make the
|
|
||||||
* header compatible with static linking. */
|
|
||||||
# define KHRONOS_APICALL
|
|
||||||
#elif defined(_WIN32)
|
|
||||||
# define KHRONOS_APICALL __declspec(dllimport)
|
|
||||||
#elif defined (__SYMBIAN32__)
|
|
||||||
# define KHRONOS_APICALL IMPORT_C
|
|
||||||
#elif defined(__ANDROID__)
|
|
||||||
# define KHRONOS_APICALL __attribute__((visibility("default")))
|
|
||||||
#else
|
|
||||||
# define KHRONOS_APICALL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
|
||||||
* Definition of KHRONOS_APIENTRY
|
|
||||||
*-------------------------------------------------------------------------
|
|
||||||
* This follows the return type of the function and precedes the function
|
|
||||||
* name in the function prototype.
|
|
||||||
*/
|
|
||||||
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
|
|
||||||
/* Win32 but not WinCE */
|
|
||||||
# define KHRONOS_APIENTRY __stdcall
|
|
||||||
#else
|
|
||||||
# define KHRONOS_APIENTRY
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
|
||||||
* Definition of KHRONOS_APIATTRIBUTES
|
|
||||||
*-------------------------------------------------------------------------
|
|
||||||
* This follows the closing parenthesis of the function prototype arguments.
|
|
||||||
*/
|
|
||||||
#if defined (__ARMCC_2__)
|
|
||||||
#define KHRONOS_APIATTRIBUTES __softfp
|
|
||||||
#else
|
|
||||||
#define KHRONOS_APIATTRIBUTES
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
|
||||||
* basic type definitions
|
|
||||||
*-----------------------------------------------------------------------*/
|
|
||||||
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Using <stdint.h>
|
|
||||||
*/
|
|
||||||
#include <stdint.h>
|
|
||||||
typedef int32_t khronos_int32_t;
|
|
||||||
typedef uint32_t khronos_uint32_t;
|
|
||||||
typedef int64_t khronos_int64_t;
|
|
||||||
typedef uint64_t khronos_uint64_t;
|
|
||||||
#define KHRONOS_SUPPORT_INT64 1
|
|
||||||
#define KHRONOS_SUPPORT_FLOAT 1
|
|
||||||
/*
|
|
||||||
* To support platform where unsigned long cannot be used interchangeably with
|
|
||||||
* inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t.
|
|
||||||
* Ideally, we could just use (u)intptr_t everywhere, but this could result in
|
|
||||||
* ABI breakage if khronos_uintptr_t is changed from unsigned long to
|
|
||||||
* unsigned long long or similar (this results in different C++ name mangling).
|
|
||||||
* To avoid changes for existing platforms, we restrict usage of intptr_t to
|
|
||||||
* platforms where the size of a pointer is larger than the size of long.
|
|
||||||
*/
|
|
||||||
#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__)
|
|
||||||
#if __SIZEOF_POINTER__ > __SIZEOF_LONG__
|
|
||||||
#define KHRONOS_USE_INTPTR_T
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#elif defined(__VMS ) || defined(__sgi)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Using <inttypes.h>
|
|
||||||
*/
|
|
||||||
#include <inttypes.h>
|
|
||||||
typedef int32_t khronos_int32_t;
|
|
||||||
typedef uint32_t khronos_uint32_t;
|
|
||||||
typedef int64_t khronos_int64_t;
|
|
||||||
typedef uint64_t khronos_uint64_t;
|
|
||||||
#define KHRONOS_SUPPORT_INT64 1
|
|
||||||
#define KHRONOS_SUPPORT_FLOAT 1
|
|
||||||
|
|
||||||
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Win32
|
|
||||||
*/
|
|
||||||
typedef __int32 khronos_int32_t;
|
|
||||||
typedef unsigned __int32 khronos_uint32_t;
|
|
||||||
typedef __int64 khronos_int64_t;
|
|
||||||
typedef unsigned __int64 khronos_uint64_t;
|
|
||||||
#define KHRONOS_SUPPORT_INT64 1
|
|
||||||
#define KHRONOS_SUPPORT_FLOAT 1
|
|
||||||
|
|
||||||
#elif defined(__sun__) || defined(__digital__)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sun or Digital
|
|
||||||
*/
|
|
||||||
typedef int khronos_int32_t;
|
|
||||||
typedef unsigned int khronos_uint32_t;
|
|
||||||
#if defined(__arch64__) || defined(_LP64)
|
|
||||||
typedef long int khronos_int64_t;
|
|
||||||
typedef unsigned long int khronos_uint64_t;
|
|
||||||
#else
|
|
||||||
typedef long long int khronos_int64_t;
|
|
||||||
typedef unsigned long long int khronos_uint64_t;
|
|
||||||
#endif /* __arch64__ */
|
|
||||||
#define KHRONOS_SUPPORT_INT64 1
|
|
||||||
#define KHRONOS_SUPPORT_FLOAT 1
|
|
||||||
|
|
||||||
#elif 0
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Hypothetical platform with no float or int64 support
|
|
||||||
*/
|
|
||||||
typedef int khronos_int32_t;
|
|
||||||
typedef unsigned int khronos_uint32_t;
|
|
||||||
#define KHRONOS_SUPPORT_INT64 0
|
|
||||||
#define KHRONOS_SUPPORT_FLOAT 0
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Generic fallback
|
|
||||||
*/
|
|
||||||
#include <stdint.h>
|
|
||||||
typedef int32_t khronos_int32_t;
|
|
||||||
typedef uint32_t khronos_uint32_t;
|
|
||||||
typedef int64_t khronos_int64_t;
|
|
||||||
typedef uint64_t khronos_uint64_t;
|
|
||||||
#define KHRONOS_SUPPORT_INT64 1
|
|
||||||
#define KHRONOS_SUPPORT_FLOAT 1
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Types that are (so far) the same on all platforms
|
|
||||||
*/
|
|
||||||
typedef signed char khronos_int8_t;
|
|
||||||
typedef unsigned char khronos_uint8_t;
|
|
||||||
typedef signed short int khronos_int16_t;
|
|
||||||
typedef unsigned short int khronos_uint16_t;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Types that differ between LLP64 and LP64 architectures - in LLP64,
|
|
||||||
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
|
|
||||||
* to be the only LLP64 architecture in current use.
|
|
||||||
*/
|
|
||||||
#ifdef KHRONOS_USE_INTPTR_T
|
|
||||||
typedef intptr_t khronos_intptr_t;
|
|
||||||
typedef uintptr_t khronos_uintptr_t;
|
|
||||||
#elif defined(_WIN64)
|
|
||||||
typedef signed long long int khronos_intptr_t;
|
|
||||||
typedef unsigned long long int khronos_uintptr_t;
|
|
||||||
#else
|
|
||||||
typedef signed long int khronos_intptr_t;
|
|
||||||
typedef unsigned long int khronos_uintptr_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_WIN64)
|
|
||||||
typedef signed long long int khronos_ssize_t;
|
|
||||||
typedef unsigned long long int khronos_usize_t;
|
|
||||||
#else
|
|
||||||
typedef signed long int khronos_ssize_t;
|
|
||||||
typedef unsigned long int khronos_usize_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if KHRONOS_SUPPORT_FLOAT
|
|
||||||
/*
|
|
||||||
* Float type
|
|
||||||
*/
|
|
||||||
typedef float khronos_float_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if KHRONOS_SUPPORT_INT64
|
|
||||||
/* Time types
|
|
||||||
*
|
|
||||||
* These types can be used to represent a time interval in nanoseconds or
|
|
||||||
* an absolute Unadjusted System Time. Unadjusted System Time is the number
|
|
||||||
* of nanoseconds since some arbitrary system event (e.g. since the last
|
|
||||||
* time the system booted). The Unadjusted System Time is an unsigned
|
|
||||||
* 64 bit value that wraps back to 0 every 584 years. Time intervals
|
|
||||||
* may be either signed or unsigned.
|
|
||||||
*/
|
|
||||||
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
|
|
||||||
typedef khronos_int64_t khronos_stime_nanoseconds_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Dummy value used to pad enum types to 32 bits.
|
|
||||||
*/
|
|
||||||
#ifndef KHRONOS_MAX_ENUM
|
|
||||||
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Enumerated boolean type
|
|
||||||
*
|
|
||||||
* Values other than zero should be considered to be true. Therefore
|
|
||||||
* comparisons should not be made against KHRONOS_TRUE.
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
KHRONOS_FALSE = 0,
|
|
||||||
KHRONOS_TRUE = 1,
|
|
||||||
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
|
|
||||||
} khronos_boolean_enum_t;
|
|
||||||
|
|
||||||
#endif /* __khrplatform_h_ */
|
|
File diff suppressed because it is too large
Load Diff
1833
lib/glad/src/glad.c
1833
lib/glad/src/glad.c
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,30 @@
|
|||||||
# Copyright (c) 2025 Dominic Masters
|
# Copyright (c) 2025 Dominic Masters
|
||||||
#
|
#
|
||||||
# This software is released under the MIT License.
|
# This software is released under the MIT License.
|
||||||
# https://opensource.org/licenses/MIT
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
add_subdirectory(dusktest)
|
# Libs
|
||||||
add_subdirectory(dusk)
|
target_link_libraries(${DUSK_TARGET_NAME}
|
||||||
|
PUBLIC
|
||||||
|
m
|
||||||
|
raylib
|
||||||
|
)
|
||||||
|
|
||||||
|
# Includes
|
||||||
|
target_include_directories(${DUSK_TARGET_NAME}
|
||||||
|
PUBLIC
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Sources
|
||||||
|
target_sources(${DUSK_TARGET_NAME}
|
||||||
|
PRIVATE
|
||||||
|
main.c
|
||||||
|
)
|
||||||
|
|
||||||
|
# Subdirs
|
||||||
|
add_subdirectory(assert)
|
||||||
|
add_subdirectory(console)
|
||||||
|
add_subdirectory(error)
|
||||||
|
add_subdirectory(server)
|
||||||
|
add_subdirectory(util)
|
@ -303,15 +303,17 @@ void cmdGet(const consolecmdexec_t *exec) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void cmdSet(const consolecmdexec_t *exec) {
|
void cmdSet(const consolecmdexec_t *exec) {
|
||||||
assertTrue(
|
assertTrue(exec->argc >= 2, "set command requires 2 arguments.");
|
||||||
exec->argc >= 2,
|
|
||||||
"set command requires 2 arguments."
|
|
||||||
);
|
|
||||||
|
|
||||||
for(uint32_t i = 0; i < CONSOLE.variableCount; i++) {
|
for(uint32_t i = 0; i < CONSOLE.variableCount; i++) {
|
||||||
consolevar_t *var = &CONSOLE.variables[i];
|
consolevar_t *var = &CONSOLE.variables[i];
|
||||||
if(stringCompare(var->name, exec->argv[0]) != 0) continue;
|
if(stringCompare(var->name, exec->argv[0]) != 0) continue;
|
||||||
consoleVarSetValue(var, exec->argv[1]);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,4 +327,58 @@ void cmdEcho(const consolecmdexec_t *exec) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
consolePrint("%s", exec->argv[0]);
|
consolePrint("%s", exec->argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// May move these later
|
||||||
|
void consoleUpdate() {
|
||||||
|
int32_t key = GetKeyPressed();
|
||||||
|
|
||||||
|
switch(key) {
|
||||||
|
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(key >= 32 && key <= 126 && CONSOLE.inputIndex < CONSOLE_LINE_MAX - 1) {
|
||||||
|
CONSOLE.inputBuffer[CONSOLE.inputIndex++] = (char_t)GetCharPressed();
|
||||||
|
CONSOLE.inputBuffer[CONSOLE.inputIndex] = '\0';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
consoleProcess();
|
||||||
|
}
|
||||||
|
|
||||||
|
void consoleDraw() {
|
||||||
|
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, BLACK);
|
||||||
|
i++;
|
||||||
|
} while(i < CONSOLE_HISTORY_MAX);
|
||||||
|
|
||||||
|
DrawText(
|
||||||
|
CONSOLE.inputBuffer, 0,
|
||||||
|
(CONSOLE_HISTORY_MAX + 1) * fontSize,
|
||||||
|
fontSize,
|
||||||
|
BLACK
|
||||||
|
);
|
||||||
}
|
}
|
@ -38,6 +38,10 @@ typedef struct {
|
|||||||
consolecmd_t *cmdGet;
|
consolecmd_t *cmdGet;
|
||||||
consolecmd_t *cmdSet;
|
consolecmd_t *cmdSet;
|
||||||
pthread_mutex_t lock; // Mutex for thread safety
|
pthread_mutex_t lock; // Mutex for thread safety
|
||||||
|
|
||||||
|
// May move these later
|
||||||
|
char_t inputBuffer[CONSOLE_LINE_MAX];
|
||||||
|
int32_t inputIndex;
|
||||||
} console_t;
|
} console_t;
|
||||||
|
|
||||||
extern console_t CONSOLE;
|
extern console_t CONSOLE;
|
||||||
@ -93,6 +97,16 @@ void consoleExec(const char_t *line);
|
|||||||
*/
|
*/
|
||||||
void consoleProcess();
|
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 cmdGet(const consolecmdexec_t *exec);
|
||||||
void cmdSet(const consolecmdexec_t *exec);
|
void cmdSet(const consolecmdexec_t *exec);
|
||||||
void cmdEcho(const consolecmdexec_t *exec);
|
void cmdEcho(const consolecmdexec_t *exec);
|
@ -16,7 +16,12 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <raylib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
typedef bool bool_t;
|
typedef bool bool_t;
|
||||||
typedef char char_t;
|
typedef char char_t;
|
||||||
|
|
||||||
|
#define DUSK_NAME "Dusk"
|
||||||
#define DUSK_VERSION "1.0.0"
|
#define DUSK_VERSION "1.0.0"
|
@ -1,26 +0,0 @@
|
|||||||
# Copyright (c) 2025 Dominic Masters
|
|
||||||
#
|
|
||||||
# This software is released under the MIT License.
|
|
||||||
# https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
# Libs
|
|
||||||
target_link_libraries(${DUSK_TARGET_NAME}
|
|
||||||
PUBLIC
|
|
||||||
)
|
|
||||||
|
|
||||||
# Includes
|
|
||||||
target_include_directories(${DUSK_TARGET_NAME}
|
|
||||||
PUBLIC
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Sources
|
|
||||||
target_sources(${DUSK_TARGET_NAME}
|
|
||||||
PRIVATE
|
|
||||||
)
|
|
||||||
|
|
||||||
# Subdirs
|
|
||||||
add_subdirectory(assert)
|
|
||||||
add_subdirectory(console)
|
|
||||||
add_subdirectory(error)
|
|
||||||
add_subdirectory(util)
|
|
@ -1,19 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "dusk.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
|
|
||||||
} server_t;
|
|
||||||
|
|
||||||
extern server_t SERVER;
|
|
||||||
|
|
||||||
void serverInit();
|
|
||||||
void serverStart();
|
|
||||||
void serverDispose();
|
|
@ -1,33 +0,0 @@
|
|||||||
# Copyright (c) 2025 Dominic Masters
|
|
||||||
#
|
|
||||||
# This software is released under the MIT License.
|
|
||||||
# https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
# Libs
|
|
||||||
target_link_libraries(${DUSK_TARGET_NAME}
|
|
||||||
PUBLIC
|
|
||||||
archive_static
|
|
||||||
m
|
|
||||||
spng_static
|
|
||||||
cglm
|
|
||||||
)
|
|
||||||
|
|
||||||
# Includes
|
|
||||||
target_include_directories(${DUSK_TARGET_NAME}
|
|
||||||
PUBLIC
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Sources
|
|
||||||
target_sources(${DUSK_TARGET_NAME}
|
|
||||||
PRIVATE
|
|
||||||
asset.c
|
|
||||||
)
|
|
||||||
|
|
||||||
# Subdirs
|
|
||||||
add_subdirectory(assert)
|
|
||||||
add_subdirectory(display)
|
|
||||||
add_subdirectory(overworld)
|
|
||||||
|
|
||||||
# Assets
|
|
||||||
copytool("textures/8x8.png")
|
|
@ -1,69 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2023 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "assert/assertgl.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
#include "util/memory.h"
|
|
||||||
|
|
||||||
void assertNotGLErrorCheck(const char_t *file, const int32_t line) {
|
|
||||||
assertNotNull(file, "File is an invlaid string");
|
|
||||||
assertTrue(line > 0, "assertNotGLErrorCheck: line is invalid");
|
|
||||||
|
|
||||||
char_t *buffer;
|
|
||||||
GLenum errorCode;
|
|
||||||
int32_t errorCount = 0;
|
|
||||||
|
|
||||||
while((errorCode = glGetError()) != GL_NO_ERROR) {
|
|
||||||
if(errorCount == 0) {
|
|
||||||
buffer = memoryAllocate(sizeof(char_t) * 4096);
|
|
||||||
sprintf(buffer, "assertNotGLErrorCheck: %s:%d\n", file, line);
|
|
||||||
}
|
|
||||||
|
|
||||||
errorCount++;
|
|
||||||
|
|
||||||
switch (errorCode) {
|
|
||||||
case GL_INVALID_ENUM:
|
|
||||||
sprintf(buffer, "%s\nINVALID_ENUM", buffer);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GL_INVALID_VALUE:
|
|
||||||
sprintf(buffer, "%s\nINVALID_ENUM", buffer);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GL_INVALID_OPERATION:
|
|
||||||
sprintf(buffer, "%s\nINVALID_OPERATION", buffer);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// case GL_INVALID_FRAMEBUFFER_OPERATION:
|
|
||||||
// sprintf(buffer, "%s\nINVALID_FRAMEBUFFER_OPERATION", buffer);
|
|
||||||
// break;
|
|
||||||
|
|
||||||
case GL_OUT_OF_MEMORY:
|
|
||||||
sprintf(buffer, "%s\nOUT_OF_MEMORY", buffer);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GL_STACK_UNDERFLOW:
|
|
||||||
sprintf(buffer, "%s\nSTACK_UNDERFLOW", buffer);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GL_STACK_OVERFLOW:
|
|
||||||
sprintf(buffer, "%s\nSTACK_OVERFLOW", buffer);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
sprintf(buffer, "%s\nUNKNOWN_ERROR", buffer);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf(buffer, "%s (%i)\n", buffer, errorCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(errorCount > 0) {
|
|
||||||
assertUnreachable(buffer);
|
|
||||||
free(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "duskgl.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Asserts that there are no OpenGL errors.
|
|
||||||
*
|
|
||||||
* @param file The file the assertion is being made in.
|
|
||||||
* @param line The line the assertion is being made in.
|
|
||||||
*/
|
|
||||||
void assertNotGLErrorCheck(const char_t *file, const int32_t line);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Asserts that there are no OpenGL errors.
|
|
||||||
*/
|
|
||||||
#define assertNoGLError() assertNotGLErrorCheck(__FILE__, __LINE__)
|
|
@ -1,223 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2024 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "asset.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
#include "util/math.h"
|
|
||||||
#include "util/memory.h"
|
|
||||||
|
|
||||||
asset_t ASSET;
|
|
||||||
|
|
||||||
void assetInit() {
|
|
||||||
const char_t *assetFilename = "dusk.tar";
|
|
||||||
char_t assetPath[FILENAME_MAX];
|
|
||||||
const char_t* scanLocations[] = {
|
|
||||||
EXECUTABLE_DIRECTORY
|
|
||||||
};
|
|
||||||
|
|
||||||
memoryZero(&ASSET, sizeof(asset_t));
|
|
||||||
|
|
||||||
// Try and find the asset file.
|
|
||||||
for(int32_t i = 0; i < sizeof(scanLocations) / sizeof(char_t*); i++) {
|
|
||||||
sprintf(assetPath, "%s/%s", scanLocations[i], assetFilename);
|
|
||||||
|
|
||||||
FILE *file = fopen(assetPath, "rb");
|
|
||||||
if(file == NULL) continue;
|
|
||||||
|
|
||||||
// File found.
|
|
||||||
ASSET.file = file;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure we found it.
|
|
||||||
assertNotNull(ASSET.file, "Failed to find asset file!");
|
|
||||||
}
|
|
||||||
|
|
||||||
void assetOpen(const char_t *path) {
|
|
||||||
assertNotNull(path, "Path is not valid!");
|
|
||||||
assertStrLen(path, FILENAME_MAX, "Path is too long!");
|
|
||||||
assertStrLenMin(path, 1, "Path is empty!");
|
|
||||||
|
|
||||||
// Make sure things are clean
|
|
||||||
assertNull(ASSET.archive, "Archive is not NULL!");
|
|
||||||
assertNull(ASSET.entry, "Entry is not NULL!");
|
|
||||||
assertNotNull(ASSET.file, "File is NULL!");
|
|
||||||
|
|
||||||
// Store path
|
|
||||||
strcpy(ASSET.path, path);
|
|
||||||
|
|
||||||
// Prepare data
|
|
||||||
ASSET.archive = archive_read_new();
|
|
||||||
assertNotNull(ASSET.archive, "Failed to init archive reader");
|
|
||||||
|
|
||||||
// Set up the reader
|
|
||||||
// archive_read_support_filter_bzip2(ASSET_ARCHIVE);
|
|
||||||
archive_read_support_format_tar(ASSET.archive);
|
|
||||||
|
|
||||||
// Set the archive reader callbacks
|
|
||||||
archive_read_set_open_callback(ASSET.archive, &assetArchiveOpen);
|
|
||||||
archive_read_set_read_callback(ASSET.archive, &assetArchiveRead);
|
|
||||||
archive_read_set_seek_callback(ASSET.archive, &assetArchiveSeek);
|
|
||||||
archive_read_set_close_callback(ASSET.archive, &assetArchiveClose);
|
|
||||||
archive_read_set_callback_data(ASSET.archive, ASSET.buffer);// TODO: Not needed?
|
|
||||||
|
|
||||||
// Open the archive
|
|
||||||
int32_t ret = archive_read_open1(ASSET.archive);
|
|
||||||
assertTrue(ret == ARCHIVE_OK, "Failed to open archive!");
|
|
||||||
|
|
||||||
// Iterate over each file.
|
|
||||||
while(archive_read_next_header(ASSET.archive, &ASSET.entry) == ARCHIVE_OK) {
|
|
||||||
// What file is at this position?
|
|
||||||
const char_t *headerFile = (char_t*)archive_entry_pathname(ASSET.entry);
|
|
||||||
|
|
||||||
// Compare if this is the file we are looking for, if it is just exit the
|
|
||||||
// function
|
|
||||||
if(strcmp(headerFile, ASSET.path) == 0) return;
|
|
||||||
|
|
||||||
// It is not, skip it.
|
|
||||||
int32_t ret = archive_read_data_skip(ASSET.archive);
|
|
||||||
assertTrue(ret == ARCHIVE_OK, "Failed to skip data!");
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we get here we did not find the find in the archive.
|
|
||||||
assertUnreachable("Failed to find file!");
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t assetGetSize() {
|
|
||||||
assertNotNull(ASSET.archive, "Archive is NULL!");
|
|
||||||
assertNotNull(ASSET.entry, "Entry is NULL!");
|
|
||||||
assertTrue(archive_entry_size_is_set(ASSET.entry), "Entry size is not set!");
|
|
||||||
return archive_entry_size(ASSET.entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t assetRead(
|
|
||||||
uint8_t *buffer,
|
|
||||||
const size_t bufferSize
|
|
||||||
) {
|
|
||||||
assertNotNull(ASSET.archive, "Archive is NULL!");
|
|
||||||
assertNotNull(ASSET.entry, "Entry is NULL!");
|
|
||||||
assertNotNull(buffer, "Buffer is NULL!");
|
|
||||||
assertTrue(bufferSize > 0, "Buffer size must be greater than 0!");
|
|
||||||
|
|
||||||
ssize_t read = archive_read_data(ASSET.archive, buffer, bufferSize);
|
|
||||||
if(read == ARCHIVE_FATAL) {
|
|
||||||
assertUnreachable(archive_error_string(ASSET.archive));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
assertTrue(read != ARCHIVE_RETRY, "Failed to read data (RETRY)!");
|
|
||||||
assertTrue(read != ARCHIVE_WARN, "Failed to read data (WARN)!");
|
|
||||||
|
|
||||||
return read;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t assetReadUntil(
|
|
||||||
uint8_t *buffer,
|
|
||||||
const char_t c,
|
|
||||||
const size_t maxLength
|
|
||||||
) {
|
|
||||||
if(buffer == NULL) {
|
|
||||||
assertTrue(
|
|
||||||
maxLength == -1, "If no buffer is provided, maxLength must be -1."
|
|
||||||
);
|
|
||||||
uint8_t tBuffer[1];
|
|
||||||
size_t read = 0;
|
|
||||||
while(assetRead(tBuffer, 1) == 1 && (char_t)tBuffer[0] != c) read++;
|
|
||||||
return read;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t read = 0;
|
|
||||||
while(read < maxLength) {
|
|
||||||
// TODO: Read more than 1 char at a time.
|
|
||||||
read += assetRead(buffer + read, 1);
|
|
||||||
if((char_t)buffer[read-1] == c) return read - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void assetSkip(const size_t length) {
|
|
||||||
assertNotNull(ASSET.archive, "Archive is NULL!");
|
|
||||||
assertNotNull(ASSET.entry, "Entry is NULL!");
|
|
||||||
|
|
||||||
// Asset archive does not support skipping, so we have to read and discard.
|
|
||||||
uint8_t buffer[ASSET_BUFFER_SIZE];
|
|
||||||
size_t remaining = length;
|
|
||||||
do {
|
|
||||||
size_t toRead = mathMin(remaining, ASSET_BUFFER_SIZE);
|
|
||||||
size_t read = assetRead(buffer, toRead);
|
|
||||||
assertTrue(read == toRead, "Failed to skip data! (overskip?)");
|
|
||||||
remaining -= read;
|
|
||||||
} while(remaining > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void assetClose() {
|
|
||||||
if(ASSET.archive == NULL) return;
|
|
||||||
|
|
||||||
assertNotNull(ASSET.archive, "Archive is NULL!");
|
|
||||||
assertNotNull(ASSET.entry, "Entry is NULL!");
|
|
||||||
|
|
||||||
int32_t ret = archive_read_free(ASSET.archive);
|
|
||||||
assertTrue(ret == ARCHIVE_OK, "Failed to close archive!");
|
|
||||||
|
|
||||||
assertNull(ASSET.archive, "Archive is not NULL? Cleanup incorrect.");
|
|
||||||
}
|
|
||||||
|
|
||||||
void assetDispose() {
|
|
||||||
assertNull(ASSET.archive, "Asset disposing but asset is currently open?");
|
|
||||||
assertNull(ASSET.entry, "Asset disposing but entry is currently open?");
|
|
||||||
assertNotNull(ASSET.file, "Asset disposing but file is NULL?");
|
|
||||||
|
|
||||||
fclose(ASSET.file);
|
|
||||||
memoryZero(&ASSET, sizeof(asset_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Libarchive callbacks
|
|
||||||
|
|
||||||
ssize_t assetArchiveRead(
|
|
||||||
struct archive *archive,
|
|
||||||
void *data,
|
|
||||||
const void **buffer
|
|
||||||
) {
|
|
||||||
assertNotNull(archive, "Archive is NULL!");
|
|
||||||
assertNotNull(data, "Data is NULL!");
|
|
||||||
assertNotNull(buffer, "Buffer is NULL!");
|
|
||||||
|
|
||||||
*buffer = data;
|
|
||||||
size_t read = fread(data, 1, ASSET_BUFFER_SIZE, ASSET.file);
|
|
||||||
if(ferror(ASSET.file)) return ARCHIVE_FATAL;
|
|
||||||
return read;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t assetArchiveSeek(
|
|
||||||
struct archive *archive,
|
|
||||||
void *data,
|
|
||||||
int64_t offset,
|
|
||||||
int32_t whence
|
|
||||||
) {
|
|
||||||
assertNotNull(archive, "Archive is NULL!");
|
|
||||||
assertNotNull(data, "Data is NULL!");
|
|
||||||
assertTrue(offset > 0, "Offset must be greater than 0!");
|
|
||||||
assertNotNull(ASSET.file, "File is NULL!");
|
|
||||||
int32_t ret = fseek(ASSET.file, offset, whence);
|
|
||||||
assertTrue(ret == 0, "Failed to seek!");
|
|
||||||
return ftell(ASSET.file);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t assetArchiveOpen(struct archive *a, void *data) {
|
|
||||||
int32_t ret = fseek(ASSET.file, 0, SEEK_SET);
|
|
||||||
assertTrue(ret == 0, "Failed to seek to start of file!");
|
|
||||||
return ARCHIVE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t assetArchiveClose(struct archive *a, void *data) {
|
|
||||||
assertNotNull(ASSET.file, "File is NULL!");
|
|
||||||
|
|
||||||
ASSET.archive = NULL;
|
|
||||||
ASSET.entry = NULL;
|
|
||||||
|
|
||||||
return ARCHIVE_OK;
|
|
||||||
}
|
|
@ -1,137 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "duskgl.h"
|
|
||||||
#include <archive.h>
|
|
||||||
#include <archive_entry.h>
|
|
||||||
|
|
||||||
#define ASSET_BUFFER_SIZE 32768
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
FILE *file;
|
|
||||||
struct archive *archive;
|
|
||||||
struct archive_entry *entry;
|
|
||||||
uint8_t buffer[ASSET_BUFFER_SIZE];
|
|
||||||
|
|
||||||
// ?
|
|
||||||
char_t path[FILENAME_MAX];
|
|
||||||
} asset_t;
|
|
||||||
|
|
||||||
extern asset_t ASSET;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the asset manager.
|
|
||||||
*/
|
|
||||||
void assetInit();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Opens an asset by its filename (within the asset archive). Asset paths should
|
|
||||||
* always use the unix forward slash '/' as a path separator.
|
|
||||||
*
|
|
||||||
* @param path The path to the asset within the archive.
|
|
||||||
*/
|
|
||||||
void assetOpen(const char *path);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the size of the asset.
|
|
||||||
*
|
|
||||||
* @return The size of the asset.
|
|
||||||
*/
|
|
||||||
size_t assetGetSize();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the asset into the buffer.
|
|
||||||
*
|
|
||||||
* @param buffer The buffer to read the asset into.
|
|
||||||
* @param bufferSize The size of the buffer.
|
|
||||||
* @return The amount of data read.
|
|
||||||
*/
|
|
||||||
size_t assetRead(uint8_t *buffer, const size_t bufferSize);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads ahead in the buffer until either the end of the buffer, or the
|
|
||||||
* specified character is found. Return value will be -1 if the character was
|
|
||||||
* not found.
|
|
||||||
*
|
|
||||||
* Buffer can be NULL if you just want to skip ahead.
|
|
||||||
*
|
|
||||||
* Returned value will be either the amount of data read into the buffer, which
|
|
||||||
* excludes the extra 1 character that was read from the asset. If the character
|
|
||||||
* was not found, -1 will be returned.
|
|
||||||
*
|
|
||||||
* @param buffer Buffer to read into.
|
|
||||||
* @param c Character to read until.
|
|
||||||
* @param maxLength Maximum length to read.
|
|
||||||
* @return -1 if the character was not found, otherwise the amount of data read.
|
|
||||||
*/
|
|
||||||
size_t assetReadUntil(uint8_t *buffer, const char c, const size_t maxLength);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Skips ahead in the buffer by the specified length.
|
|
||||||
*
|
|
||||||
* @param length The length to skip ahead by.
|
|
||||||
*/
|
|
||||||
void assetSkip(const size_t length);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the asset.
|
|
||||||
*/
|
|
||||||
void assetClose();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys and cleans up the asset manager.
|
|
||||||
*/
|
|
||||||
void assetDispose();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal read method provided to libarchive api.
|
|
||||||
*
|
|
||||||
* @param archive The archive to read from.
|
|
||||||
* @param data The data to read into.
|
|
||||||
* @param buffer The buffer to read from.
|
|
||||||
* @return The amount of data read.
|
|
||||||
*/
|
|
||||||
ssize_t assetArchiveRead(
|
|
||||||
struct archive *archive,
|
|
||||||
void *data,
|
|
||||||
const void **buffer
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal seek method provided to libarchive api.
|
|
||||||
*
|
|
||||||
* @param archive The archive to seek in.
|
|
||||||
* @param data The data to seek in.
|
|
||||||
* @param offset Offset bytes to seek.
|
|
||||||
* @param whence Relative to whence to seek.
|
|
||||||
* @return The new position.
|
|
||||||
*/
|
|
||||||
int64_t assetArchiveSeek(
|
|
||||||
struct archive *archive,
|
|
||||||
void *data,
|
|
||||||
int64_t offset,
|
|
||||||
int32_t whence
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal open method provided to libarchive api.
|
|
||||||
*
|
|
||||||
* @param archive The archive to open.
|
|
||||||
* @param data The data to open.
|
|
||||||
* @return The result of the open.
|
|
||||||
*/
|
|
||||||
int32_t assetArchiveOpen(struct archive *a, void *data);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal close method provided to libarchive api.
|
|
||||||
*
|
|
||||||
* @param archive The archive to close.
|
|
||||||
* @param data The data to close.
|
|
||||||
* @return The result of the close.
|
|
||||||
*/
|
|
||||||
int32_t assetArchiveClose(struct archive *a, void *data);
|
|
@ -1,16 +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
|
|
||||||
render.c
|
|
||||||
quad.c
|
|
||||||
texture.c
|
|
||||||
tilesetgl.c
|
|
||||||
)
|
|
||||||
|
|
||||||
# Subdirs
|
|
||||||
add_subdirectory(shader)
|
|
@ -1,130 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "framebuffer.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
#include "assert/assertgl.h"
|
|
||||||
#include "display/window.h"
|
|
||||||
|
|
||||||
framebuffer_t FRAMEBUFFER;
|
|
||||||
|
|
||||||
void frameBufferInit(const int32_t width, const int32_t height) {
|
|
||||||
assertTrue(width > 0, "Width must be greater than 0");
|
|
||||||
assertTrue(height > 0, "Height must be greater than 0");
|
|
||||||
|
|
||||||
FRAMEBUFFER.id = -1;
|
|
||||||
FRAMEBUFFER.width = -1;
|
|
||||||
FRAMEBUFFER.height = -1;
|
|
||||||
FRAMEBUFFER.texture = -1;
|
|
||||||
|
|
||||||
frameBufferSetSize(width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
void frameBufferSetSize(const int32_t width, const int32_t height) {
|
|
||||||
assertTrue(width > 0, "Width must be greater than 0");
|
|
||||||
assertTrue(height > 0, "Height must be greater than 0");
|
|
||||||
|
|
||||||
if(FRAMEBUFFER.width == width && FRAMEBUFFER.height == height) return;
|
|
||||||
|
|
||||||
FRAMEBUFFER.width = width;
|
|
||||||
FRAMEBUFFER.height = height;
|
|
||||||
|
|
||||||
frameBufferUnbind();
|
|
||||||
|
|
||||||
// Delete old texture and depth buffer
|
|
||||||
if(FRAMEBUFFER.texture != -1) {
|
|
||||||
glDeleteTextures(1, &FRAMEBUFFER.texture);
|
|
||||||
assertNoGLError();
|
|
||||||
FRAMEBUFFER.texture = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(FRAMEBUFFER.id != -1) {
|
|
||||||
glDeleteFramebuffers(1, &FRAMEBUFFER.id);
|
|
||||||
assertNoGLError();
|
|
||||||
FRAMEBUFFER.id = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate framebuffer
|
|
||||||
glGenFramebuffers(1, &FRAMEBUFFER.id);
|
|
||||||
assertNoGLError();
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, FRAMEBUFFER.id);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
// Create new texture
|
|
||||||
glGenTextures(1, &FRAMEBUFFER.texture);
|
|
||||||
assertNoGLError();
|
|
||||||
glBindTexture(GL_TEXTURE_2D, FRAMEBUFFER.texture);
|
|
||||||
assertNoGLError();
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
assertNoGLError();
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
assertNoGLError();
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
assertNoGLError();
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
assertNoGLError();
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
assertNoGLError();
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, FRAMEBUFFER.texture, 0);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
// Check framebuffer completeness
|
|
||||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
|
||||||
assertNoGLError();
|
|
||||||
assertTrue(status == GL_FRAMEBUFFER_COMPLETE, "Framebuffer is not complete");
|
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
||||||
assertNoGLError();
|
|
||||||
}
|
|
||||||
|
|
||||||
void frameBufferBind() {
|
|
||||||
if(FRAMEBUFFER.id == -1) return;
|
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, FRAMEBUFFER.id);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glViewport(0, 0, FRAMEBUFFER.width, FRAMEBUFFER.height);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
assertNoGLError();
|
|
||||||
}
|
|
||||||
|
|
||||||
void frameBufferTextureBind(const GLuint slot) {
|
|
||||||
if(FRAMEBUFFER.texture == -1) return;
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0 + slot);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, FRAMEBUFFER.texture);
|
|
||||||
assertNoGLError();
|
|
||||||
}
|
|
||||||
|
|
||||||
void frameBufferUnbind() {
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glClearColor(0.05f, 0.05f, 0.05f, 1.0f);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
assertNoGLError();
|
|
||||||
}
|
|
||||||
|
|
||||||
void frameBufferDispose() {
|
|
||||||
glDeleteFramebuffers(1, &FRAMEBUFFER.id);
|
|
||||||
glDeleteTextures(1, &FRAMEBUFFER.texture);
|
|
||||||
|
|
||||||
FRAMEBUFFER.id = -1;
|
|
||||||
FRAMEBUFFER.texture = -1;
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "duskgl.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
GLuint id;
|
|
||||||
GLuint texture;
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
} framebuffer_t;
|
|
||||||
|
|
||||||
extern framebuffer_t FRAMEBUFFER;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the framebuffer.
|
|
||||||
*
|
|
||||||
* @param width The width of the framebuffer.
|
|
||||||
* @param height The height of the framebuffer.
|
|
||||||
*/
|
|
||||||
void frameBufferInit(const int32_t width, const int32_t height);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the size of the framebuffer.
|
|
||||||
*
|
|
||||||
* @param width The width of the framebuffer.
|
|
||||||
* @param height The height of the framebuffer.
|
|
||||||
*/
|
|
||||||
void frameBufferSetSize(const int32_t width, const int32_t height);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Binds the framebuffer.
|
|
||||||
*/
|
|
||||||
void frameBufferBind();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unbinds the framebuffer.
|
|
||||||
*/
|
|
||||||
void frameBufferUnbind();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Binds the framebuffer texture to a slot.
|
|
||||||
*
|
|
||||||
* @param slot The slot to bind the texture to.
|
|
||||||
*/
|
|
||||||
void frameBufferTextureBind(const GLuint slot);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unbinds the framebuffer.
|
|
||||||
*/
|
|
||||||
void frameBufferDispose();
|
|
@ -1,108 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "assert/assertgl.h"
|
|
||||||
#include "quad.h"
|
|
||||||
|
|
||||||
duskquad_t QUAD;
|
|
||||||
|
|
||||||
void quadInit() {
|
|
||||||
// Create the single quad.
|
|
||||||
const float quadPositions[] = {
|
|
||||||
0.0f, 0.0f, 0.0f, // Bottom-left corner
|
|
||||||
1.0f, 0.0f, 0.0f, // Bottom-right corner
|
|
||||||
1.0f, 1.0f, 0.0f, // Top-right corner
|
|
||||||
0.0f, 1.0f, 0.0f // Top-left corner
|
|
||||||
};
|
|
||||||
|
|
||||||
const float quadUVs[] = {
|
|
||||||
0.0f, 0.0f,
|
|
||||||
1.0f, 0.0f,
|
|
||||||
1.0f, 1.0f,
|
|
||||||
0.0f, 1.0f
|
|
||||||
};
|
|
||||||
|
|
||||||
const uint32_t quadIndices[] = {
|
|
||||||
0, 1, 2,
|
|
||||||
2, 3, 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
glGenVertexArrays(1, &QUAD.quadVAO);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glBindVertexArray(QUAD.quadVAO);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
// Positions
|
|
||||||
glGenBuffers(1, &QUAD.quadVBO);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, QUAD.quadVBO);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glBufferData(
|
|
||||||
GL_ARRAY_BUFFER, sizeof(quadPositions), quadPositions, GL_STATIC_DRAW
|
|
||||||
);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glEnableVertexAttribArray(0);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
// UVs
|
|
||||||
glGenBuffers(1, &QUAD.quadUVVBO);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, QUAD.quadUVVBO);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(quadUVs), quadUVs, GL_STATIC_DRAW);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glEnableVertexAttribArray(1);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
// Indices
|
|
||||||
glGenBuffers(1, &QUAD.quadEBO);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, QUAD.quadEBO);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glBufferData(
|
|
||||||
GL_ELEMENT_ARRAY_BUFFER, sizeof(quadIndices), quadIndices, GL_STATIC_DRAW
|
|
||||||
);
|
|
||||||
assertNoGLError();
|
|
||||||
}
|
|
||||||
|
|
||||||
void quadRender(const int32_t count) {
|
|
||||||
glBindVertexArray(QUAD.quadVAO);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glDrawElementsInstanced(
|
|
||||||
GL_TRIANGLES, 6,
|
|
||||||
GL_UNSIGNED_INT, 0,
|
|
||||||
count
|
|
||||||
);
|
|
||||||
assertNoGLError();
|
|
||||||
}
|
|
||||||
|
|
||||||
void quadDispose() {
|
|
||||||
glDeleteBuffers(1, &QUAD.quadVBO);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glDeleteBuffers(1, &QUAD.quadEBO);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glDeleteVertexArrays(1, &QUAD.quadVAO);
|
|
||||||
assertNoGLError();
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "duskgl.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
GLuint quadVBO;
|
|
||||||
GLuint quadUVVBO;
|
|
||||||
GLuint quadVAO;
|
|
||||||
GLuint quadEBO;
|
|
||||||
} duskquad_t;
|
|
||||||
|
|
||||||
extern duskquad_t QUAD;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the quad.
|
|
||||||
*/
|
|
||||||
void quadInit();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders quads.
|
|
||||||
*
|
|
||||||
* @param count The number of quads to render.
|
|
||||||
*/
|
|
||||||
void quadRender(const int32_t count);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disposes of the quad.
|
|
||||||
*/
|
|
||||||
void quadDispose();
|
|
@ -1,52 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "assert/assertgl.h"
|
|
||||||
#include "util/memory.h"
|
|
||||||
#include "render.h"
|
|
||||||
#include "display/scene.h"
|
|
||||||
#include "display/shader/shadermanager.h"
|
|
||||||
#include "display/quad.h"
|
|
||||||
#include "display/window.h"
|
|
||||||
#include "display/tilesetgl.h"
|
|
||||||
|
|
||||||
render_t RENDER;
|
|
||||||
|
|
||||||
void renderInit() {
|
|
||||||
memoryZero(&RENDER, sizeof(render_t));
|
|
||||||
|
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glEnable(GL_BLEND);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
shaderManagerInit();
|
|
||||||
quadInit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderUpdate() {
|
|
||||||
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
|
|
||||||
assertNoGLError();
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
// Update rendering data
|
|
||||||
shaderManagerUpdate();
|
|
||||||
tilesetGLBind();
|
|
||||||
|
|
||||||
// Hand off to the scene to do its rendering.
|
|
||||||
sceneRender();
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderDispose() {
|
|
||||||
quadDispose();
|
|
||||||
shaderManagerDispose();
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "duskgl.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t nothing;
|
|
||||||
} render_t;
|
|
||||||
|
|
||||||
extern render_t RENDER;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the render system.
|
|
||||||
*/
|
|
||||||
void renderInit();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the render system.
|
|
||||||
*/
|
|
||||||
void renderUpdate();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders the overworld scene.
|
|
||||||
*/
|
|
||||||
void renderOverworld();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disposes of the render system.
|
|
||||||
*/
|
|
||||||
void renderDispose();
|
|
@ -1,18 +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
|
|
||||||
shadermanager.c
|
|
||||||
shader.c
|
|
||||||
shaderbuffer.c
|
|
||||||
)
|
|
||||||
|
|
||||||
# Subdirs
|
|
||||||
add_subdirectory(data)
|
|
||||||
add_subdirectory(entityshader)
|
|
||||||
add_subdirectory(mapshader)
|
|
||||||
add_subdirectory(fragments)
|
|
@ -1,13 +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
|
|
||||||
transforms.c
|
|
||||||
entities.c
|
|
||||||
mapshaderdata.c
|
|
||||||
tilesetshaderdata.c
|
|
||||||
)
|
|
@ -1,42 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "entities.h"
|
|
||||||
#include "overworld/overworld.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
#include "util/memory.h"
|
|
||||||
|
|
||||||
shaderbuffer_t ENTITIES_BUFFER;
|
|
||||||
entitiesdata_t ENTITIES_DATA;
|
|
||||||
|
|
||||||
void entitiesInit() {
|
|
||||||
memoryZero(&ENTITIES_DATA, sizeof(entitiesdata_t));
|
|
||||||
shaderBufferInit(&ENTITIES_BUFFER, sizeof(entitiesdata_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
void entitiesUpdate() {
|
|
||||||
for(uint8_t i = 0; i < OVERWORLD.entityCount; i++) {
|
|
||||||
// Pack the entity data into the buffer
|
|
||||||
entity_t *src = &OVERWORLD.entities[i];
|
|
||||||
entitiesdataent_t *dst = &ENTITIES_DATA.entities[i];
|
|
||||||
|
|
||||||
// Copy position data.
|
|
||||||
memoryCopyRangeSafe(
|
|
||||||
&dst->position,
|
|
||||||
&src->x,
|
|
||||||
&src->frame + sizeof(uint8_t),
|
|
||||||
sizeof(uint8_t) * 5
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
shaderBufferBind(&ENTITIES_BUFFER);
|
|
||||||
shaderBufferSetData(&ENTITIES_BUFFER, &ENTITIES_DATA);
|
|
||||||
}
|
|
||||||
|
|
||||||
void entitiesDispose() {
|
|
||||||
shaderBufferDispose(&ENTITIES_BUFFER);
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
// Copyright (c) 2025 Dominic Masters
|
|
||||||
//
|
|
||||||
// This software is released under the MIT License.
|
|
||||||
// https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
#include "../../../../dusk/overworld/overworlddefs.h"
|
|
||||||
#include "../fragments/packed.glsl"
|
|
||||||
#include "../fragments/quad.glsl"
|
|
||||||
#include "../data/tilesets.glsl"
|
|
||||||
|
|
||||||
struct Entity {
|
|
||||||
uvec4 position;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(std140) uniform b_Entities {
|
|
||||||
Entity entities[OVERWORLD_ENTITY_COUNT_MAX];
|
|
||||||
};
|
|
||||||
|
|
||||||
vec2 entityGetSize() {
|
|
||||||
return vec2(float(OVERWORLD_ENTITY_WIDTH), float(OVERWORLD_ENTITY_HEIGHT));
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 entityGetVertice(uint instanceIndex, uint indiceIndex) {
|
|
||||||
// Get base quad vertice
|
|
||||||
vec2 vert = quadGetVertice(indiceIndex);
|
|
||||||
|
|
||||||
uint x = packedGetU8(0u, entities[instanceIndex].position);
|
|
||||||
uint y = packedGetU8(1u, entities[instanceIndex].position);
|
|
||||||
int subX = packedGetI8(2u, entities[instanceIndex].position);
|
|
||||||
int subY = packedGetI8(3u, entities[instanceIndex].position);
|
|
||||||
|
|
||||||
vert.x += float(x);
|
|
||||||
vert.y += float(y);
|
|
||||||
|
|
||||||
vert *= entityGetSize();
|
|
||||||
|
|
||||||
vert.x += float(subX);
|
|
||||||
vert.y += float(subY);
|
|
||||||
|
|
||||||
return vert;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 entityGetUV(uint instanceIndex, uint indiceIndex) {
|
|
||||||
uint frame = packedGetU8(4u, entities[instanceIndex].position);
|
|
||||||
vec4 tilesetUVs = tilesetGetUVsByIndex(uint(TILESET_SLOT_ENTITIES), frame);
|
|
||||||
vec2 uv = quadGetTextureCoordinate(indiceIndex, tilesetUVs);
|
|
||||||
return uv;
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "display/shader/shaderbuffer.h"
|
|
||||||
#include "overworld/overworld.h"
|
|
||||||
|
|
||||||
#define ENTITIES_BLOCK_NAME "b_Entities"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uvec4_t position;
|
|
||||||
} entitiesdataent_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
entitiesdataent_t entities[OVERWORLD_ENTITY_COUNT_MAX];
|
|
||||||
} entitiesdata_t;
|
|
||||||
|
|
||||||
extern shaderbuffer_t ENTITIES_BUFFER;
|
|
||||||
extern entitiesdata_t ENTITIES_DATA;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the entities buffer and data.
|
|
||||||
*/
|
|
||||||
void entitiesInit();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the entities buffer with the current data.
|
|
||||||
*/
|
|
||||||
void entitiesUpdate();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys the entities buffer.
|
|
||||||
*/
|
|
||||||
void entitiesDispose();
|
|
@ -1,48 +0,0 @@
|
|||||||
// Copyright (c) 2025 Dominic Masters
|
|
||||||
//
|
|
||||||
// This software is released under the MIT License.
|
|
||||||
// https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
#include "../../../../dusk/overworld/overworlddefs.h"
|
|
||||||
#include "../fragments/packed.glsl"
|
|
||||||
#include "../fragments/quad.glsl"
|
|
||||||
|
|
||||||
#define MAP_TILE_PACKED_SIZE 16
|
|
||||||
|
|
||||||
layout(std140) uniform b_Map {
|
|
||||||
uvec4 mapTileIds[OVERWORLD_TILE_COUNT_MAX / MAP_TILE_PACKED_SIZE];
|
|
||||||
uvec4 mapSize;
|
|
||||||
};
|
|
||||||
|
|
||||||
vec2 mapTileGetSize() {
|
|
||||||
return vec2(float(OVERWORLD_TILE_WIDTH), float(OVERWORLD_TILE_HEIGHT));
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 mapGetVertice(uint instanceIndex, uint indiceIndex) {
|
|
||||||
vec2 quad = quadGetVertice(indiceIndex);
|
|
||||||
|
|
||||||
uint mapWidth = packedGetU8(0u, mapSize);
|
|
||||||
uint mapHeight = packedGetU8(1u, mapSize);
|
|
||||||
uint mapLayerCount = packedGetU8(2u, mapSize);
|
|
||||||
|
|
||||||
// Get x and y within layer
|
|
||||||
uint x = instanceIndex % mapWidth;
|
|
||||||
uint y = (instanceIndex / mapWidth) % mapHeight;
|
|
||||||
|
|
||||||
// Get quad position, consider layer count
|
|
||||||
quad += vec2(x, y);
|
|
||||||
quad *= mapTileGetSize();
|
|
||||||
|
|
||||||
return quad;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint mapGetLayer(uint instanceIndex) {
|
|
||||||
uint mapWidth = packedGetU8(0u, mapSize);
|
|
||||||
uint mapHeight = packedGetU8(1u, mapSize);
|
|
||||||
return instanceIndex / (mapWidth * mapHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint mapGetTileId(uint instanceIndex) {
|
|
||||||
uvec4 v4 = mapTileIds[packedArrayGetU8IndexFromUVEC4Array(instanceIndex)];
|
|
||||||
return packedArrayGetU8FromUVEC4ArrayValue(instanceIndex, v4);
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "mapshaderdata.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
#include "util/memory.h"
|
|
||||||
|
|
||||||
shaderbuffer_t MAP_SHADER_DATA_BUFFER;
|
|
||||||
mapshaderdata_t MAP_SHADER_DATA_DATA;
|
|
||||||
|
|
||||||
void mapShaderDataInit() {
|
|
||||||
memoryZero(&MAP_SHADER_DATA_DATA, sizeof(mapshaderdata_t));
|
|
||||||
shaderBufferInit(&MAP_SHADER_DATA_BUFFER, sizeof(mapshaderdata_t));
|
|
||||||
|
|
||||||
assertTrue(
|
|
||||||
sizeof(MAP_SHADER_DATA_DATA.tileIds) == sizeof(OVERWORLD.map.tileIds),
|
|
||||||
"Map shader tile data and Overworld tile data are not the same size."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mapShaderDataUpdate() {
|
|
||||||
// Copy tile ids.
|
|
||||||
memoryCopyRangeSafe(
|
|
||||||
MAP_SHADER_DATA_DATA.tileIds,
|
|
||||||
OVERWORLD.map.tileIds,
|
|
||||||
&OVERWORLD.map.tileIds[
|
|
||||||
OVERWORLD.map.width * OVERWORLD.map.height * OVERWORLD.map.layerCount
|
|
||||||
],
|
|
||||||
sizeof(MAP_SHADER_DATA_DATA.tileIds)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Copy map size.
|
|
||||||
memoryCopyRangeSafe(
|
|
||||||
&MAP_SHADER_DATA_DATA.mapSize,
|
|
||||||
&OVERWORLD.map.width,
|
|
||||||
&OVERWORLD.map.layerCount + sizeof(uint8_t),
|
|
||||||
sizeof(uint8_t) * 3
|
|
||||||
);
|
|
||||||
|
|
||||||
shaderBufferBind(&MAP_SHADER_DATA_BUFFER);
|
|
||||||
shaderBufferSetData(&MAP_SHADER_DATA_BUFFER, &MAP_SHADER_DATA_DATA);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mapShaderDataDispose() {
|
|
||||||
shaderBufferDispose(&MAP_SHADER_DATA_BUFFER);
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma ocne
|
|
||||||
#include "display/shader/shaderbuffer.h"
|
|
||||||
#include "overworld/overworld.h"
|
|
||||||
|
|
||||||
#define MAP_BLOCK_NAME "b_Map"
|
|
||||||
#define MAP_TILE_PACK_SIZE sizeof(uvec4_t) / sizeof(tileid_t)
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uvec4_t tileIds[OVERWORLD_TILE_COUNT_MAX / MAP_TILE_PACK_SIZE];
|
|
||||||
uvec4_t mapSize;
|
|
||||||
} mapshaderdata_t;
|
|
||||||
|
|
||||||
extern shaderbuffer_t MAP_SHADER_DATA_BUFFER;
|
|
||||||
extern mapshaderdata_t MAP_SHADER_DATA_DATA;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the map buffer and data.
|
|
||||||
*/
|
|
||||||
void mapShaderDataInit();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the map buffer with the current data.
|
|
||||||
*/
|
|
||||||
void mapShaderDataUpdate();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys the map buffer.
|
|
||||||
*/
|
|
||||||
void mapShaderDataDispose();
|
|
@ -1,64 +0,0 @@
|
|||||||
// Copyright (c) 2025 Dominic Masters
|
|
||||||
//
|
|
||||||
// This software is released under the MIT License.
|
|
||||||
// https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
#include "../../../../dusk/display/tilesetdefs.h"
|
|
||||||
#include "../fragments/packed.glsl"
|
|
||||||
|
|
||||||
struct Tileset {
|
|
||||||
uvec4 tileset;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(std140) uniform b_Tilesets {
|
|
||||||
Tileset tilesets[TILESET_SLOT_COUNT];
|
|
||||||
};
|
|
||||||
|
|
||||||
uniform sampler2D u_TilesetTextures[TILESET_SLOT_COUNT];
|
|
||||||
|
|
||||||
uint tilesetGetColumns(uint tilesetIndex) {
|
|
||||||
return packedGetU32(0u, tilesets[tilesetIndex].tileset);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint tilesetGetRows(uint tilesetIndex) {
|
|
||||||
return packedGetU32(1u, tilesets[tilesetIndex].tileset);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint tilesetGetWidth(uint tilesetIndex) {
|
|
||||||
return packedGetU32(2u, tilesets[tilesetIndex].tileset);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint tilesetGetHeight(uint tilesetIndex) {
|
|
||||||
return packedGetU32(3u, tilesets[tilesetIndex].tileset);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 tilesetGetUVs(uint tilesetIndex, uint col, uint row) {
|
|
||||||
Tileset tileset = tilesets[tilesetIndex];
|
|
||||||
float segWidth = 1.0 / float(tilesetGetColumns(tilesetIndex));
|
|
||||||
float segHeight = 1.0 / float(tilesetGetRows(tilesetIndex));
|
|
||||||
float x = float(col) * segWidth;
|
|
||||||
float y = float(row) * segHeight;
|
|
||||||
return vec4(x, y, x + segWidth, y + segHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 tilesetGetUVsByIndex(uint tilesetIndex, uint index) {
|
|
||||||
Tileset tileset = tilesets[tilesetIndex];
|
|
||||||
uint col = index % tilesetGetColumns(tilesetIndex);
|
|
||||||
uint row = index / tilesetGetColumns(tilesetIndex);
|
|
||||||
return tilesetGetUVs(tilesetIndex, col, row);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 tilesetGetColor(uint tilesetIndex, vec2 coord) {
|
|
||||||
switch(tilesetIndex) {
|
|
||||||
case 0u:
|
|
||||||
return texture(u_TilesetTextures[0], coord);
|
|
||||||
case 1u:
|
|
||||||
return texture(u_TilesetTextures[1], coord);
|
|
||||||
case 2u:
|
|
||||||
return texture(u_TilesetTextures[2], coord);
|
|
||||||
case 3u:
|
|
||||||
return texture(u_TilesetTextures[3], coord);
|
|
||||||
default:
|
|
||||||
return vec4(1, 1, 1, 1);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "tilesetshaderdata.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
#include "util/memory.h"
|
|
||||||
#include "display/shader/shader.h"
|
|
||||||
|
|
||||||
shaderbuffer_t TILESET_SHADER_DATA_BUFFER;
|
|
||||||
tilesetshaderdata_t TILESET_SHADER_DATA_DATA;
|
|
||||||
GLuint TILESET_SHADER_DATA_TEXTURES[TILESET_SLOT_COUNT];
|
|
||||||
|
|
||||||
void tilesetShaderDataInit() {
|
|
||||||
memoryZero(&TILESET_SHADER_DATA_DATA, sizeof(tilesetshaderdata_t));
|
|
||||||
shaderBufferInit(&TILESET_SHADER_DATA_BUFFER, sizeof(tilesetshaderdata_t));
|
|
||||||
|
|
||||||
assertTrue(
|
|
||||||
sizeof(tilesetshaderdata_t) == sizeof(uvec4_t) * TILESET_SLOT_COUNT,
|
|
||||||
"Tileset Shader Data size mismatch"
|
|
||||||
);
|
|
||||||
|
|
||||||
uint8_t i = 0;
|
|
||||||
do {
|
|
||||||
TILESET_SHADER_DATA_TEXTURES[i] = i;
|
|
||||||
} while(++i < TILESET_SLOT_COUNT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tilesetShaderDataUpdate() {
|
|
||||||
uint8_t i = 0;
|
|
||||||
do {
|
|
||||||
tilesetid_t id = TILESET_SLOTS[i];
|
|
||||||
if(id == TILESET_NULL) continue;
|
|
||||||
tileset_t *tileset = &TILESETS[id];
|
|
||||||
texture_t *texture = &TILESET_GL_TEXTURES[i];
|
|
||||||
tilesetshaderdatatileset_t *dest = &TILESET_SHADER_DATA_DATA.tilesets[i];
|
|
||||||
|
|
||||||
dest->columns = tileset->columns;
|
|
||||||
dest->rows = tileset->rows;
|
|
||||||
dest->width = texture->width;
|
|
||||||
dest->height = texture->height;
|
|
||||||
} while(++i < TILESET_SLOT_COUNT);
|
|
||||||
|
|
||||||
shaderBufferBind(&TILESET_SHADER_DATA_BUFFER);
|
|
||||||
shaderBufferSetData(&TILESET_SHADER_DATA_BUFFER, &TILESET_SHADER_DATA_DATA);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tilesetShaderTexturesBind(const GLuint uniform) {
|
|
||||||
shaderSetTextures(uniform, TILESET_SHADER_DATA_TEXTURES, TILESET_SLOT_COUNT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tilesetShaderDataDispose() {
|
|
||||||
shaderBufferDispose(&TILESET_SHADER_DATA_BUFFER);
|
|
||||||
}
|
|
@ -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 "display/shader/shaderbuffer.h"
|
|
||||||
#include "display/tilesetgl.h"
|
|
||||||
|
|
||||||
#define TILESET_SHADER_DATA_BLOCK_NAME "b_Tilesets"
|
|
||||||
#define TILESET_UNIFORM_TEXTURES_NAME "u_TilesetTextures"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t columns;
|
|
||||||
uint32_t rows;
|
|
||||||
uint32_t width;
|
|
||||||
uint32_t height;
|
|
||||||
} tilesetshaderdatatileset_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
tilesetshaderdatatileset_t tilesets[TILESET_SLOT_COUNT];
|
|
||||||
} tilesetshaderdata_t;
|
|
||||||
|
|
||||||
extern shaderbuffer_t TILESET_SHADER_DATA_BUFFER;
|
|
||||||
extern tilesetshaderdata_t TILESET_SHADER_DATA_DATA;
|
|
||||||
extern GLuint TILESET_SHADER_DATA_TEXTURES[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the tileset buffer and data.
|
|
||||||
*/
|
|
||||||
void tilesetShaderDataInit();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the tileset buffer with the current data.
|
|
||||||
*/
|
|
||||||
void tilesetShaderDataUpdate();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Binds the tileset textures to the given uniform.
|
|
||||||
*
|
|
||||||
* @param uniform The uniform to bind the textures to.
|
|
||||||
*/
|
|
||||||
void tilesetShaderTexturesBind(const GLuint uniform);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys the tileset buffer.
|
|
||||||
*/
|
|
||||||
void tilesetShaderDataDispose();
|
|
@ -1,50 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "transforms.h"
|
|
||||||
#include "display/window.h"
|
|
||||||
|
|
||||||
shaderbuffer_t TRANSFORMS_BUFFER;
|
|
||||||
transformsdata_t TRANSFORMS_DATA;
|
|
||||||
|
|
||||||
void transformsInit() {
|
|
||||||
memset(&TRANSFORMS_DATA, 0, sizeof(transformsdata_t));
|
|
||||||
shaderBufferInit(&TRANSFORMS_BUFFER, sizeof(transformsdata_t));
|
|
||||||
|
|
||||||
glm_mat4_identity(TRANSFORMS_DATA.projection);
|
|
||||||
glm_mat4_identity(TRANSFORMS_DATA.view);
|
|
||||||
|
|
||||||
TRANSFORMS_DATA.resolution[0] = WINDOW_WIDTH;
|
|
||||||
TRANSFORMS_DATA.resolution[1] = WINDOW_HEIGHT;
|
|
||||||
}
|
|
||||||
|
|
||||||
void transformsUpdate() {
|
|
||||||
TRANSFORMS_DATA.resolution[0] = WINDOW_WIDTH;
|
|
||||||
TRANSFORMS_DATA.resolution[1] = WINDOW_HEIGHT;
|
|
||||||
|
|
||||||
glm_perspective(
|
|
||||||
glm_rad(45.0f),
|
|
||||||
TRANSFORMS_DATA.resolution[0] / TRANSFORMS_DATA.resolution[1],
|
|
||||||
0.5f,
|
|
||||||
1000.0f,
|
|
||||||
TRANSFORMS_DATA.projection
|
|
||||||
);
|
|
||||||
|
|
||||||
glm_lookat(
|
|
||||||
(vec3){ 0, 0, 300 },
|
|
||||||
(vec3){ 0, 32, 0 },
|
|
||||||
(vec3){ 0, 1, 0 },
|
|
||||||
TRANSFORMS_DATA.view
|
|
||||||
);
|
|
||||||
|
|
||||||
shaderBufferBind(&TRANSFORMS_BUFFER);
|
|
||||||
shaderBufferSetData(&TRANSFORMS_BUFFER, &TRANSFORMS_DATA);
|
|
||||||
}
|
|
||||||
|
|
||||||
void transformsDispose() {
|
|
||||||
shaderBufferDispose(&TRANSFORMS_BUFFER);
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
// Copyright (c) 2025 Dominic Masters
|
|
||||||
//
|
|
||||||
// This software is released under the MIT License.
|
|
||||||
// https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
#include "../../../../dusk/display/displaydefs.h"
|
|
||||||
|
|
||||||
struct Transform {
|
|
||||||
mat4 projection;
|
|
||||||
mat4 view;
|
|
||||||
vec2 resolution;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(std140) uniform b_Transforms {
|
|
||||||
Transform transforms;
|
|
||||||
};
|
|
||||||
|
|
||||||
vec2 transformDisplayGetSize() {
|
|
||||||
return vec2(SCREEN_WIDTH, SCREEN_HEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
float transformDisplayGetAspectRatio() {
|
|
||||||
return (float(SCREEN_WIDTH) / float(SCREEN_HEIGHT));
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 transformResolutionGetSize() {
|
|
||||||
return transforms.resolution;
|
|
||||||
}
|
|
||||||
|
|
||||||
float transformResolutionGetAspectRatio() {
|
|
||||||
return (transforms.resolution.x / transforms.resolution.y);
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "display/shader/shaderbuffer.h"
|
|
||||||
|
|
||||||
#define TRANSFORMS_BLOCK_NAME "b_Transforms"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
mat4 projection;
|
|
||||||
mat4 view;
|
|
||||||
vec2 resolution;
|
|
||||||
} transformsdata_t;
|
|
||||||
|
|
||||||
extern shaderbuffer_t TRANSFORMS_BUFFER;
|
|
||||||
extern transformsdata_t TRANSFORMS_DATA;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the transforms buffer and data.
|
|
||||||
*/
|
|
||||||
void transformsInit();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the transforms buffer with the current data.
|
|
||||||
*/
|
|
||||||
void transformsUpdate();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys the transforms buffer.
|
|
||||||
*/
|
|
||||||
void transformsDispose();
|
|
@ -1,14 +0,0 @@
|
|||||||
# Copyright (c) 2025 Dominic Masters
|
|
||||||
#
|
|
||||||
# This software is released under the MIT License.
|
|
||||||
# https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
# Shaders
|
|
||||||
glsltool(entity_vert.glsl)
|
|
||||||
glsltool(entity_frag.glsl)
|
|
||||||
|
|
||||||
# Sources
|
|
||||||
target_sources(${DUSK_TARGET_NAME}
|
|
||||||
PRIVATE
|
|
||||||
entityshader.c
|
|
||||||
)
|
|
@ -1,21 +0,0 @@
|
|||||||
// Copyright (c) 2025 Dominic Masters
|
|
||||||
//
|
|
||||||
// This software is released under the MIT License.
|
|
||||||
// https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
#include "../fragments/header.glsl"
|
|
||||||
#include "../data/entities.glsl"
|
|
||||||
#include "../data/tilesets.glsl"
|
|
||||||
|
|
||||||
// Inputs from vertex shader
|
|
||||||
in vec2 v_TextureCoord;
|
|
||||||
|
|
||||||
// Frag pixel color
|
|
||||||
out vec4 FragColor;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec4 tColor = tilesetGetColor(uint(TILESET_SLOT_ENTITIES), v_TextureCoord);
|
|
||||||
if(tColor.a == 0.0) discard;
|
|
||||||
if(tColor.r == 0.0) discard;
|
|
||||||
FragColor = vec4(1, 1, 1, 1) * tColor;
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
// Copyright (c) 2025 Dominic Masters
|
|
||||||
//
|
|
||||||
// This software is released under the MIT License.
|
|
||||||
// https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
#include "../fragments/header.glsl"
|
|
||||||
#include "../data/transforms.glsl"
|
|
||||||
#include "../data/entities.glsl"
|
|
||||||
|
|
||||||
// Outputs to fragment shader
|
|
||||||
out vec2 v_TextureCoord;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
uint instanceIndex = uint(gl_InstanceID);
|
|
||||||
uint indiceIndex = quadGetIndiceIndex(gl_VertexID);
|
|
||||||
|
|
||||||
vec2 vert = entityGetVertice(instanceIndex, indiceIndex);
|
|
||||||
vec2 uv = entityGetUV(instanceIndex, indiceIndex);
|
|
||||||
|
|
||||||
gl_Position = transforms.projection * transforms.view * vec4(vert, 0.0, 1.0);
|
|
||||||
v_TextureCoord = uv;
|
|
||||||
}
|
|
@ -1,64 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "assert/assert.h"
|
|
||||||
#include "assert/assertgl.h"
|
|
||||||
#include "util/memory.h"
|
|
||||||
#include "entityshader.h"
|
|
||||||
#include "entity_vert.glsl.h"
|
|
||||||
#include "entity_frag.glsl.h"
|
|
||||||
#include "display/shader/data/transforms.h"
|
|
||||||
#include "display/shader/data/entities.h"
|
|
||||||
#include "display/shader/data/tilesetshaderdata.h"
|
|
||||||
|
|
||||||
entityshader_t ENTITY_SHADER;
|
|
||||||
|
|
||||||
void entityShaderInit() {
|
|
||||||
memoryZero(&ENTITY_SHADER, sizeof(entityshader_t));
|
|
||||||
|
|
||||||
shaderInit(
|
|
||||||
&ENTITY_SHADER.shader,
|
|
||||||
entity_vertShaderSource,
|
|
||||||
entity_fragShaderSource
|
|
||||||
);
|
|
||||||
|
|
||||||
// Uniform buffers
|
|
||||||
ENTITY_SHADER.transformsBlock = shaderGetBlock(
|
|
||||||
&ENTITY_SHADER.shader,
|
|
||||||
TRANSFORMS_BLOCK_NAME
|
|
||||||
);
|
|
||||||
|
|
||||||
ENTITY_SHADER.entitiesBlock = shaderGetBlock(
|
|
||||||
&ENTITY_SHADER.shader,
|
|
||||||
ENTITIES_BLOCK_NAME
|
|
||||||
);
|
|
||||||
|
|
||||||
ENTITY_SHADER.tilesetsBlock = shaderGetBlock(
|
|
||||||
&ENTITY_SHADER.shader,
|
|
||||||
TILESET_SHADER_DATA_BLOCK_NAME
|
|
||||||
);
|
|
||||||
|
|
||||||
// Uniforms
|
|
||||||
ENTITY_SHADER.tilesetTexturesUniform = shaderGetUniform(
|
|
||||||
&ENTITY_SHADER.shader,
|
|
||||||
TILESET_UNIFORM_TEXTURES_NAME
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void entityShaderUse() {
|
|
||||||
shaderUse(&ENTITY_SHADER.shader);
|
|
||||||
shaderBufferBindToBlock(&TRANSFORMS_BUFFER, ENTITY_SHADER.transformsBlock);
|
|
||||||
shaderBufferBindToBlock(&ENTITIES_BUFFER, ENTITY_SHADER.entitiesBlock);
|
|
||||||
shaderBufferBindToBlock(
|
|
||||||
&TILESET_SHADER_DATA_BUFFER, ENTITY_SHADER.tilesetsBlock
|
|
||||||
);
|
|
||||||
tilesetShaderTexturesBind(ENTITY_SHADER.tilesetTexturesUniform);
|
|
||||||
}
|
|
||||||
|
|
||||||
void entityShaderDispose() {
|
|
||||||
shaderDispose(&ENTITY_SHADER.shader);
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "display/shader/shader.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
shader_t shader;
|
|
||||||
|
|
||||||
GLuint entitiesBlock;
|
|
||||||
GLuint transformsBlock;
|
|
||||||
GLuint tilesetsBlock;
|
|
||||||
|
|
||||||
GLuint tilesetTexturesUniform;
|
|
||||||
} entityshader_t;
|
|
||||||
|
|
||||||
extern entityshader_t ENTITY_SHADER;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the entity shader.
|
|
||||||
*/
|
|
||||||
void entityShaderInit();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uses the entity shader.
|
|
||||||
*/
|
|
||||||
void entityShaderUse();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disposes of the entity shader.
|
|
||||||
*/
|
|
||||||
void entityShaderDispose();
|
|
@ -1,9 +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
|
|
||||||
)
|
|
@ -1,6 +0,0 @@
|
|||||||
// Copyright (c) 2025 Dominic Masters
|
|
||||||
//
|
|
||||||
// This software is released under the MIT License.
|
|
||||||
// https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
#version 330 core
|
|
@ -1,39 +0,0 @@
|
|||||||
// Copyright (c) 2025 Dominic Masters
|
|
||||||
//
|
|
||||||
// This software is released under the MIT License.
|
|
||||||
// https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
#define PACKED_U8_PER_UI 4
|
|
||||||
#define PACKED_U8_PER_UVEC4 PACKED_U8_PER_UI * 4
|
|
||||||
|
|
||||||
uint packedGetU8(uint position, uvec4 data) {
|
|
||||||
uint subData = data[position / 4u];
|
|
||||||
return (subData >> (position * 8u)) & 0xFFu;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint packedGetU32(uint position, uvec4 data) {
|
|
||||||
return data[position];
|
|
||||||
}
|
|
||||||
|
|
||||||
int packedGetI8(uint position, uvec4 data) {
|
|
||||||
uint subData = data[position / 4u];
|
|
||||||
|
|
||||||
int shift = int(position * 8u);
|
|
||||||
return int(subData << (24 - shift)) >> 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint packedArrayGetU8IndexFromUVEC4Array(uint u8ArrayIndex) {
|
|
||||||
// Given a uint8_t array is uploaded, this will return the index to get the
|
|
||||||
// appropriate uvec4 from a uvec4 array that will be at the right index.
|
|
||||||
return u8ArrayIndex / uint(PACKED_U8_PER_UVEC4);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint packedArrayGetU8FromUVEC4ArrayValue(uint u8ArrayIndex, uvec4 data) {
|
|
||||||
// Given a value from a uint8_t array, this will return the value at the
|
|
||||||
// appropriate index. You must first get the uvec4 from the array using
|
|
||||||
// packedArrayGetU8IndexFromUVEC4Array.
|
|
||||||
uint subIndex = (u8ArrayIndex % uint(PACKED_U8_PER_UVEC4)) / uint(PACKED_U8_PER_UI);
|
|
||||||
uint shiftAmount = (u8ArrayIndex % uint(PACKED_U8_PER_UI)) * 8u;
|
|
||||||
uint value = (data[subIndex] >> shiftAmount) & 0xFFu;
|
|
||||||
return value;
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
// Copyright (c) 2025 Dominic Masters
|
|
||||||
//
|
|
||||||
// This software is released under the MIT License.
|
|
||||||
// https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
uint quadGetIndiceIndex(uint vertexId) {
|
|
||||||
return vertexId % 6u;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint quadGetIndiceIndex(int vertexId) {
|
|
||||||
return quadGetIndiceIndex(uint(vertexId));
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 quadGetVertice(uint indiceIndex) {
|
|
||||||
vec2 vert = vec2(0, 0);
|
|
||||||
|
|
||||||
/*if(indiceIndex == 0u || indiceIndex == 4u) {
|
|
||||||
// vert = vec2(0, 0);
|
|
||||||
} else*/ if(indiceIndex == 1u) {
|
|
||||||
vert = vec2(1, 0);
|
|
||||||
} else if(indiceIndex == 2u || indiceIndex == 5u) {
|
|
||||||
vert = vec2(1, 1);
|
|
||||||
} else if(indiceIndex == 3u) {
|
|
||||||
vert = vec2(0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return vert;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 quadGetTextureCoordinate(uint indiceIndex) {
|
|
||||||
vec2 vert = quadGetVertice(indiceIndex);
|
|
||||||
return vert;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 quadGetTextureCoordinate(uint indiceIndex, vec4 uv) {
|
|
||||||
vec2 vert = quadGetVertice(indiceIndex);
|
|
||||||
vert.y = 1.0 - vert.y;
|
|
||||||
return vec2(uv.x + (uv.z - uv.x) * vert.x, uv.y + (uv.w - uv.y) * vert.y);
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
# Copyright (c) 2025 Dominic Masters
|
|
||||||
#
|
|
||||||
# This software is released under the MIT License.
|
|
||||||
# https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
# Shaders
|
|
||||||
glsltool(map_vert.glsl)
|
|
||||||
glsltool(map_frag.glsl)
|
|
||||||
|
|
||||||
# Sources
|
|
||||||
target_sources(${DUSK_TARGET_NAME}
|
|
||||||
PRIVATE
|
|
||||||
mapshader.c
|
|
||||||
)
|
|
@ -1,28 +0,0 @@
|
|||||||
// Copyright (c) 2025 Dominic Masters
|
|
||||||
//
|
|
||||||
// This software is released under the MIT License.
|
|
||||||
// https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
#include "../fragments/header.glsl"
|
|
||||||
#include "../data/map.glsl"
|
|
||||||
|
|
||||||
// Inputs from vertex shader
|
|
||||||
in vec2 v_TextureCoord;
|
|
||||||
flat in uint v_InstanceIndex;
|
|
||||||
flat in uint v_IndiceIndex;
|
|
||||||
|
|
||||||
// Frag pixel color
|
|
||||||
out vec4 FragColor;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
uint layer = mapGetLayer(v_InstanceIndex);
|
|
||||||
uint tileId = mapGetTileId(v_InstanceIndex);
|
|
||||||
|
|
||||||
if(tileId == 0u) {
|
|
||||||
FragColor = vec4(1, 0, 0, 1);
|
|
||||||
} else if(tileId == 1u) {
|
|
||||||
FragColor = vec4(0, 1, 0, 1);
|
|
||||||
} else {
|
|
||||||
FragColor = vec4(0, 0, 1, 1);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
// Copyright (c) 2025 Dominic Masters
|
|
||||||
//
|
|
||||||
// This software is released under the MIT License.
|
|
||||||
// https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
#include "../fragments/header.glsl"
|
|
||||||
#include "../data/transforms.glsl"
|
|
||||||
#include "../data/map.glsl"
|
|
||||||
|
|
||||||
// Outputs to fragment shader
|
|
||||||
out vec2 v_TextureCoord;
|
|
||||||
flat out uint v_InstanceIndex;
|
|
||||||
flat out uint v_IndiceIndex;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
uint instanceIndex = uint(gl_InstanceID);
|
|
||||||
uint indiceIndex = quadGetIndiceIndex(gl_VertexID);
|
|
||||||
|
|
||||||
uint layer = mapGetLayer(instanceIndex);
|
|
||||||
vec2 vert = mapGetVertice(instanceIndex, indiceIndex);
|
|
||||||
vec2 uv = quadGetTextureCoordinate(indiceIndex);
|
|
||||||
|
|
||||||
gl_Position = transforms.projection * transforms.view * vec4(vert, float(layer) * 64.0, 1.0);
|
|
||||||
|
|
||||||
v_TextureCoord = uv;
|
|
||||||
v_InstanceIndex = instanceIndex;
|
|
||||||
v_IndiceIndex = indiceIndex;
|
|
||||||
}
|
|
@ -1,46 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "mapshader.h"
|
|
||||||
#include "util/memory.h"
|
|
||||||
#include "display/shader/data/mapshaderdata.h"
|
|
||||||
#include "display/shader/data/transforms.h"
|
|
||||||
#include "map_vert.glsl.h"
|
|
||||||
#include "map_frag.glsl.h"
|
|
||||||
|
|
||||||
mapshader_t MAP_SHADER;
|
|
||||||
|
|
||||||
void mapShaderInit() {
|
|
||||||
memoryZero(&MAP_SHADER, sizeof(mapshader_t));
|
|
||||||
|
|
||||||
shaderInit(
|
|
||||||
&MAP_SHADER.shader,
|
|
||||||
map_vertShaderSource,
|
|
||||||
map_fragShaderSource
|
|
||||||
);
|
|
||||||
|
|
||||||
// Uniform blocks
|
|
||||||
MAP_SHADER.mapBlock = shaderGetBlock(
|
|
||||||
&MAP_SHADER.shader,
|
|
||||||
MAP_BLOCK_NAME
|
|
||||||
);
|
|
||||||
|
|
||||||
MAP_SHADER.transformsBlock = shaderGetBlock(
|
|
||||||
&MAP_SHADER.shader,
|
|
||||||
TRANSFORMS_BLOCK_NAME
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mapShaderUse() {
|
|
||||||
shaderUse(&MAP_SHADER.shader);
|
|
||||||
shaderBufferBindToBlock(&MAP_SHADER_DATA_BUFFER, MAP_SHADER.mapBlock);
|
|
||||||
shaderBufferBindToBlock(&TRANSFORMS_BUFFER, MAP_SHADER.transformsBlock);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mapShaderDispose() {
|
|
||||||
shaderDispose(&MAP_SHADER.shader);
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "display/shader/shader.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
shader_t shader;
|
|
||||||
GLuint mapBlock;
|
|
||||||
GLuint transformsBlock;
|
|
||||||
} mapshader_t;
|
|
||||||
|
|
||||||
extern mapshader_t MAP_SHADER;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the map shader.
|
|
||||||
*/
|
|
||||||
void mapShaderInit();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uses the map shader.
|
|
||||||
*/
|
|
||||||
void mapShaderUse();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys the map shader.
|
|
||||||
*/
|
|
||||||
void mapShaderDispose();
|
|
@ -1,146 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "shader.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
#include "assert/assertgl.h"
|
|
||||||
|
|
||||||
void shaderInit(
|
|
||||||
shader_t *shader,
|
|
||||||
const char *vertexSource,
|
|
||||||
const char *fragmentSource
|
|
||||||
) {
|
|
||||||
assertNotNull(shader, "shader must not be NULL");
|
|
||||||
assertNotNull(vertexSource, "vertexSource must not be NULL");
|
|
||||||
assertNotNull(fragmentSource, "fragmentSource must not be NULL");
|
|
||||||
|
|
||||||
int32_t success;
|
|
||||||
char infoLog[SHADER_LOG_LENGTH];
|
|
||||||
|
|
||||||
// Create vertex shader
|
|
||||||
shader->vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glShaderSource(shader->vertexShader, 1, &vertexSource, NULL);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glCompileShader(shader->vertexShader);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glGetShaderiv(shader->vertexShader, GL_COMPILE_STATUS, &success);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
if(!success) {
|
|
||||||
glGetShaderInfoLog(
|
|
||||||
shader->vertexShader, SHADER_LOG_LENGTH, NULL, infoLog
|
|
||||||
);
|
|
||||||
assertNoGLError();
|
|
||||||
assertUnreachable(infoLog);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create fragment shader
|
|
||||||
shader->fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glShaderSource(shader->fragmentShader, 1, &fragmentSource, NULL);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glCompileShader(shader->fragmentShader);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glGetShaderiv(shader->fragmentShader, GL_COMPILE_STATUS, &success);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
if(!success) {
|
|
||||||
glGetShaderInfoLog(
|
|
||||||
shader->fragmentShader, SHADER_LOG_LENGTH, NULL, infoLog
|
|
||||||
);
|
|
||||||
assertNoGLError();
|
|
||||||
assertUnreachable(infoLog);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create shader program
|
|
||||||
shader->shaderProgram = glCreateProgram();
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glAttachShader(shader->shaderProgram, shader->vertexShader);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glAttachShader(shader->shaderProgram, shader->fragmentShader);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glLinkProgram(shader->shaderProgram);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glGetProgramiv(shader->shaderProgram, GL_LINK_STATUS, &success);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
if(!success) {
|
|
||||||
glGetProgramInfoLog(shader->shaderProgram, SHADER_LOG_LENGTH, NULL, infoLog);
|
|
||||||
assertNoGLError();
|
|
||||||
assertUnreachable(infoLog);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void shaderUse(const shader_t *shader) {
|
|
||||||
assertNotNull(shader, "shader must not be NULL");
|
|
||||||
|
|
||||||
glUseProgram(shader->shaderProgram);
|
|
||||||
assertNoGLError();
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint shaderGetUniform(const shader_t *shader, const char_t *name) {
|
|
||||||
assertNotNull(shader, "shader must not be NULL");
|
|
||||||
assertNotNull(name, "name must not be NULL");
|
|
||||||
|
|
||||||
GLuint uniform = glGetUniformLocation(shader->shaderProgram, name);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
return uniform;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint shaderGetBlock(const shader_t *shader, const char *name) {
|
|
||||||
assertNotNull(shader, "shader must not be NULL");
|
|
||||||
assertNotNull(name, "name must not be NULL");
|
|
||||||
|
|
||||||
GLuint blockIndex = glGetUniformBlockIndex(shader->shaderProgram, name);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
// TODO: I really don't think this should be here at all.
|
|
||||||
glUniformBlockBinding(shader->shaderProgram, blockIndex, blockIndex);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
return blockIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
void shaderSetTextures(
|
|
||||||
const GLuint uniform,
|
|
||||||
const GLuint *textures,
|
|
||||||
const uint8_t count
|
|
||||||
) {
|
|
||||||
assertNotNull(textures, "textures must not be NULL");
|
|
||||||
assertTrue(count > 0, "count must be greater than 0");
|
|
||||||
|
|
||||||
glUniform1iv(uniform, count, textures);
|
|
||||||
assertNoGLError();
|
|
||||||
}
|
|
||||||
|
|
||||||
void shaderDispose(shader_t *shader) {
|
|
||||||
assertNotNull(shader, "shader must not be NULL");
|
|
||||||
|
|
||||||
glDeleteProgram(shader->shaderProgram);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glDeleteShader(shader->vertexShader);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glDeleteShader(shader->fragmentShader);
|
|
||||||
assertNoGLError();
|
|
||||||
}
|
|
@ -1,75 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "duskgl.h"
|
|
||||||
|
|
||||||
#define SHADER_LOG_LENGTH 512
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
GLuint shaderProgram;
|
|
||||||
GLuint vertexShader;
|
|
||||||
GLuint fragmentShader;
|
|
||||||
} shader_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes a shader.
|
|
||||||
*
|
|
||||||
* @param shader The shader to initialize.
|
|
||||||
* @param vertexSource The vertex shader source.
|
|
||||||
* @param fragmentSource The fragment shader source.
|
|
||||||
*/
|
|
||||||
void shaderInit(
|
|
||||||
shader_t *shader,
|
|
||||||
const char_t *vertexSource,
|
|
||||||
const char_t *fragmentSource
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uses a shader.
|
|
||||||
*
|
|
||||||
* @param shader The shader to use.
|
|
||||||
*/
|
|
||||||
void shaderUse(const shader_t *shader);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a uniform from a shader.
|
|
||||||
*
|
|
||||||
* @param shader The shader to get the uniform from.
|
|
||||||
* @param name The name of the uniform.
|
|
||||||
* @return The uniform.
|
|
||||||
*/
|
|
||||||
GLuint shaderGetUniform(const shader_t *shader, const char_t *name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a block id from a shader.
|
|
||||||
*
|
|
||||||
* @param shader The shader to get the block from.
|
|
||||||
* @param name The name of the block.
|
|
||||||
* @return The block index/identifier.
|
|
||||||
*/
|
|
||||||
GLuint shaderGetBlock(const shader_t *shader, const char_t *name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets texture uniforms to a shader.
|
|
||||||
*
|
|
||||||
* @param uniform The uniform to set.
|
|
||||||
* @param textures The textures to set.
|
|
||||||
* @param count The number of textures to set.
|
|
||||||
*/
|
|
||||||
void shaderSetTextures(
|
|
||||||
const GLuint uniform,
|
|
||||||
const GLuint *textures,
|
|
||||||
const uint8_t count
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disposes of a shader.
|
|
||||||
*
|
|
||||||
* @param shader The shader to dispose of.
|
|
||||||
*/
|
|
||||||
void shaderDispose(shader_t *shader);
|
|
@ -1,55 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "assert/assert.h"
|
|
||||||
#include "shaderbuffer.h"
|
|
||||||
#include "assert/assertgl.h"
|
|
||||||
|
|
||||||
void shaderBufferInit(shaderbuffer_t *shaderBuffer, const size_t size) {
|
|
||||||
assertNotNull(shaderBuffer, "shaderBuffer cannot be NULL.");
|
|
||||||
assertTrue(size > 0, "size must be greater than 0.");
|
|
||||||
|
|
||||||
shaderBuffer->size = size;
|
|
||||||
|
|
||||||
glGenBuffers(1, &shaderBuffer->id);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
shaderBufferBind(shaderBuffer);
|
|
||||||
|
|
||||||
glBufferData(GL_UNIFORM_BUFFER, size, NULL, GL_STATIC_DRAW);
|
|
||||||
}
|
|
||||||
|
|
||||||
void shaderBufferBind(shaderbuffer_t *shaderBuffer) {
|
|
||||||
assertNotNull(shaderBuffer, "shaderBuffer cannot be NULL.");
|
|
||||||
|
|
||||||
glBindBuffer(GL_UNIFORM_BUFFER, shaderBuffer->id);
|
|
||||||
assertNoGLError();
|
|
||||||
}
|
|
||||||
|
|
||||||
void shaderBufferSetData(shaderbuffer_t *shaderBuffer, const void *data) {
|
|
||||||
assertNotNull(shaderBuffer, "shaderBuffer cannot be NULL.");
|
|
||||||
assertNotNull(data, "data cannot be NULL.");
|
|
||||||
|
|
||||||
glBufferData(GL_UNIFORM_BUFFER, shaderBuffer->size, data, GL_STATIC_DRAW);
|
|
||||||
assertNoGLError();
|
|
||||||
}
|
|
||||||
|
|
||||||
void shaderBufferBindToBlock(
|
|
||||||
shaderbuffer_t *shaderBuffer,
|
|
||||||
const GLuint blockIndex
|
|
||||||
) {
|
|
||||||
assertNotNull(shaderBuffer, "shaderBuffer cannot be NULL.");
|
|
||||||
|
|
||||||
glBindBufferBase(GL_UNIFORM_BUFFER, blockIndex, shaderBuffer->id);
|
|
||||||
assertNoGLError();
|
|
||||||
}
|
|
||||||
|
|
||||||
void shaderBufferDispose(shaderbuffer_t *shaderBuffer) {
|
|
||||||
assertNotNull(shaderBuffer, "shaderBuffer cannot be NULL.");
|
|
||||||
glDeleteBuffers(1, &shaderBuffer->id);
|
|
||||||
assertNoGLError();
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "duskgl.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
GLuint id;
|
|
||||||
size_t size;
|
|
||||||
} shaderbuffer_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes a shader buffer.
|
|
||||||
*
|
|
||||||
* @param shaderBuffer The shader buffer to initialize.
|
|
||||||
* @param size The size of the buffer.
|
|
||||||
*/
|
|
||||||
void shaderBufferInit(
|
|
||||||
shaderbuffer_t *shaderBuffer,
|
|
||||||
const size_t size
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Binds a shader buffer.
|
|
||||||
*
|
|
||||||
* @param shaderBuffer The shader buffer to bind.
|
|
||||||
*/
|
|
||||||
void shaderBufferBind(shaderbuffer_t *shaderBuffer);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the data of a shader buffer.
|
|
||||||
*
|
|
||||||
* @param shaderBuffer The shader buffer to set the data of.
|
|
||||||
* @param data The data to set.
|
|
||||||
*/
|
|
||||||
void shaderBufferSetData(
|
|
||||||
shaderbuffer_t *shaderBuffer,
|
|
||||||
const void *data
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Binds a shader buffer to a block.
|
|
||||||
*
|
|
||||||
* @param shaderBuffer The shader buffer to bind.
|
|
||||||
* @param blockIndex The block index to bind to.
|
|
||||||
*/
|
|
||||||
void shaderBufferBindToBlock(
|
|
||||||
shaderbuffer_t *shaderBuffer,
|
|
||||||
const GLuint blockIndex
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disposes of a shader buffer.
|
|
||||||
*
|
|
||||||
* @param shaderBuffer The shader buffer to dispose of.
|
|
||||||
*/
|
|
||||||
void shaderBufferDispose(shaderbuffer_t *shaderBuffer);
|
|
@ -1,109 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "shadermanager.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
#include "display/shader/data/transforms.h"
|
|
||||||
#include "display/shader/data/entities.h"
|
|
||||||
#include "display/shader/data/mapshaderdata.h"
|
|
||||||
#include "display/shader/data/tilesetshaderdata.h"
|
|
||||||
#include "display/shader/entityshader/entityshader.h"
|
|
||||||
#include "display/shader/mapshader/mapshader.h"
|
|
||||||
|
|
||||||
shadermanagerdatacallback_t SHADER_MANAGER_DATA_CALLBACKS[] = {
|
|
||||||
{ transformsInit, transformsUpdate, transformsDispose },
|
|
||||||
{ entitiesInit, entitiesUpdate, entitiesDispose },
|
|
||||||
{ mapShaderDataInit, mapShaderDataUpdate, mapShaderDataDispose },
|
|
||||||
{ tilesetShaderDataInit, tilesetShaderDataUpdate, tilesetShaderDataDispose }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
shadermanagershadercallback_t SHADER_MANAGER_SHADER_CALLBACKS[] = {
|
|
||||||
{ entityShaderInit, entityShaderDispose },
|
|
||||||
{ mapShaderInit, mapShaderDispose }
|
|
||||||
};
|
|
||||||
|
|
||||||
void shaderManagerInit() {
|
|
||||||
size_t i;
|
|
||||||
assertTrue(
|
|
||||||
SHADER_MANAGER_SHADER_CALLBACKS_SIZE > 0,
|
|
||||||
"No Shader Callbacks Defined"
|
|
||||||
);
|
|
||||||
assertTrue(
|
|
||||||
SHADER_MANAGER_DATA_CALLBACKS_SIZE > 0,
|
|
||||||
"No Data Callbacks Defined"
|
|
||||||
);
|
|
||||||
|
|
||||||
// Init Shader Datas (before the shaders)
|
|
||||||
i = 0;
|
|
||||||
do {
|
|
||||||
assertNotNull(
|
|
||||||
SHADER_MANAGER_DATA_CALLBACKS[i].init,
|
|
||||||
"Data Callback is NULL"
|
|
||||||
);
|
|
||||||
SHADER_MANAGER_DATA_CALLBACKS[i++].init();
|
|
||||||
} while(i < SHADER_MANAGER_DATA_CALLBACKS_SIZE);
|
|
||||||
|
|
||||||
// Init the shaders
|
|
||||||
i = 0;
|
|
||||||
do {
|
|
||||||
assertNotNull(
|
|
||||||
SHADER_MANAGER_SHADER_CALLBACKS[i].init,
|
|
||||||
"Shader Callback is NULL"
|
|
||||||
);
|
|
||||||
SHADER_MANAGER_SHADER_CALLBACKS[i++].init();
|
|
||||||
} while(i < SHADER_MANAGER_SHADER_CALLBACKS_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void shaderManagerUpdate() {
|
|
||||||
assertTrue(
|
|
||||||
SHADER_MANAGER_DATA_CALLBACKS_SIZE > 0,
|
|
||||||
"No Data Callbacks Defined"
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
// Update all the data
|
|
||||||
size_t i = 0;
|
|
||||||
do {
|
|
||||||
assertNotNull(
|
|
||||||
SHADER_MANAGER_DATA_CALLBACKS[i].update,
|
|
||||||
"Data Callback is NULL"
|
|
||||||
);
|
|
||||||
SHADER_MANAGER_DATA_CALLBACKS[i++].update();
|
|
||||||
} while(i < SHADER_MANAGER_DATA_CALLBACKS_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void shaderManagerDispose() {
|
|
||||||
assertTrue(
|
|
||||||
SHADER_MANAGER_SHADER_CALLBACKS_SIZE > 0,
|
|
||||||
"No Shader Callbacks Defined"
|
|
||||||
);
|
|
||||||
assertTrue(
|
|
||||||
SHADER_MANAGER_DATA_CALLBACKS_SIZE > 0,
|
|
||||||
"No Data Callbacks Defined"
|
|
||||||
);
|
|
||||||
|
|
||||||
// Cleanup the shaders
|
|
||||||
size_t i = 0;
|
|
||||||
do {
|
|
||||||
assertNotNull(
|
|
||||||
SHADER_MANAGER_SHADER_CALLBACKS[i].dispose,
|
|
||||||
"Shader Callback is NULL"
|
|
||||||
);
|
|
||||||
SHADER_MANAGER_SHADER_CALLBACKS[i++].dispose();
|
|
||||||
} while(i < SHADER_MANAGER_SHADER_CALLBACKS_SIZE);
|
|
||||||
|
|
||||||
// Cleanup the data
|
|
||||||
i = 0;
|
|
||||||
do {
|
|
||||||
assertNotNull(
|
|
||||||
SHADER_MANAGER_DATA_CALLBACKS[i].dispose,
|
|
||||||
"Data Callback is NULL"
|
|
||||||
);
|
|
||||||
SHADER_MANAGER_DATA_CALLBACKS[i++].dispose();
|
|
||||||
} while(i < SHADER_MANAGER_DATA_CALLBACKS_SIZE);
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "dusk.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
void (*init)();
|
|
||||||
void (*update)();
|
|
||||||
void (*dispose)();
|
|
||||||
} shadermanagerdatacallback_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
void (*init)();
|
|
||||||
void (*dispose)();
|
|
||||||
} shadermanagershadercallback_t;
|
|
||||||
|
|
||||||
extern shadermanagerdatacallback_t SHADER_MANAGER_DATA_CALLBACKS[];
|
|
||||||
extern shadermanagershadercallback_t SHADER_MANAGER_SHADER_CALLBACKS[];
|
|
||||||
|
|
||||||
#define SHADER_MANAGER_DATA_CALLBACKS_SIZE ( \
|
|
||||||
sizeof(SHADER_MANAGER_DATA_CALLBACKS) / sizeof(shadermanagerdatacallback_t) \
|
|
||||||
)
|
|
||||||
|
|
||||||
#define SHADER_MANAGER_SHADER_CALLBACKS_SIZE ( \
|
|
||||||
sizeof(SHADER_MANAGER_SHADER_CALLBACKS) / \
|
|
||||||
sizeof(shadermanagershadercallback_t) \
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the Shader Manager
|
|
||||||
*/
|
|
||||||
void shaderManagerInit();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the Shader Manager
|
|
||||||
*/
|
|
||||||
void shaderManagerUpdate();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disposes of the Shader Manager
|
|
||||||
*/
|
|
||||||
void shaderManagerDispose();
|
|
@ -1,103 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2023 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "texture.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
#include "assert/assertgl.h"
|
|
||||||
#include "asset.h"
|
|
||||||
#include "util/math.h"
|
|
||||||
#include "util/memory.h"
|
|
||||||
|
|
||||||
#define TEXTURE_BUFFER_SIZE 32768
|
|
||||||
|
|
||||||
int32_t TEXTURE_ACTIVE_COUNT;
|
|
||||||
|
|
||||||
void textureLoad(
|
|
||||||
texture_t *texture,
|
|
||||||
const char_t *path
|
|
||||||
) {
|
|
||||||
assertNotNull(texture, "Texture is null.");
|
|
||||||
assertNotNull(path, "Path is null.");
|
|
||||||
|
|
||||||
// Open asset
|
|
||||||
assetOpen(path);
|
|
||||||
|
|
||||||
// Setup spng
|
|
||||||
spng_ctx *ctx = spng_ctx_new(0);
|
|
||||||
spng_set_png_stream(ctx, &textureSPNGBuffer, NULL);
|
|
||||||
|
|
||||||
// Get image info
|
|
||||||
struct spng_ihdr ihdr;
|
|
||||||
spng_get_ihdr(ctx, &ihdr);
|
|
||||||
texture->width = ihdr.width;
|
|
||||||
texture->height = ihdr.height;
|
|
||||||
|
|
||||||
// Decode the image. I can probably stream this in the future.
|
|
||||||
size_t dataSize = ihdr.width * ihdr.height * 4;// 4 for RGBA
|
|
||||||
uint8_t *data = (uint8_t *)memoryAllocate(dataSize);
|
|
||||||
assertNotNull(data, "Failed to allocate memory for texture data.");
|
|
||||||
spng_decode_image(ctx, data, dataSize, SPNG_FMT_RGBA8, 0);
|
|
||||||
|
|
||||||
// Finish decoding
|
|
||||||
spng_ctx_free(ctx);
|
|
||||||
assetClose();
|
|
||||||
|
|
||||||
// Create texture
|
|
||||||
glGenTextures(1, &texture->id);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texture->id);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
// Buffer then cleanup
|
|
||||||
glTexImage2D(
|
|
||||||
GL_TEXTURE_2D, 0, GL_RGBA,
|
|
||||||
texture->width, texture->height,
|
|
||||||
0, GL_RGBA, GL_UNSIGNED_BYTE, data
|
|
||||||
);
|
|
||||||
assertNoGLError();
|
|
||||||
memoryFree(data);
|
|
||||||
|
|
||||||
// Setup texture parameters
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
assertNoGLError();
|
|
||||||
}
|
|
||||||
|
|
||||||
void textureBind(
|
|
||||||
const texture_t *texture,
|
|
||||||
const GLuint slot
|
|
||||||
) {
|
|
||||||
assertNotNull(texture, "Texture is null.");
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0 + slot);
|
|
||||||
assertNoGLError();
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texture->id);
|
|
||||||
assertNoGLError();
|
|
||||||
}
|
|
||||||
|
|
||||||
void textureDispose(texture_t *texture) {
|
|
||||||
glDeleteTextures(1, &texture->id);
|
|
||||||
assertNoGLError();
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t textureSPNGBuffer(
|
|
||||||
spng_ctx *ctx,
|
|
||||||
void *user,
|
|
||||||
void *destination,
|
|
||||||
size_t length
|
|
||||||
) {
|
|
||||||
size_t read = assetRead(destination, length);
|
|
||||||
if(read == 0) return SPNG_IO_EOF;
|
|
||||||
return SPNG_OK;
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2023 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "duskgl.h"
|
|
||||||
#include <spng.h>
|
|
||||||
|
|
||||||
extern int32_t TEXTURE_ACTIVE_COUNT;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t width;
|
|
||||||
uint32_t height;
|
|
||||||
GLuint id;
|
|
||||||
} texture_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes a texture to be read to be used.
|
|
||||||
*
|
|
||||||
* @param texture Texture to initialize.
|
|
||||||
* @param path Path of the file to load.
|
|
||||||
*/
|
|
||||||
void textureLoad(
|
|
||||||
texture_t *texture,
|
|
||||||
const char_t *path
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Binds the texture to the given slot (for use by the shaders).
|
|
||||||
*
|
|
||||||
* @param texture Texture to bind.
|
|
||||||
* @param slot Slot to bind to.
|
|
||||||
*/
|
|
||||||
void textureBind(
|
|
||||||
const texture_t *texture,
|
|
||||||
const GLuint slot
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unloads a previously initialized texture.
|
|
||||||
*
|
|
||||||
* @param texture Texture to destroy.
|
|
||||||
*/
|
|
||||||
void textureDispose(texture_t *texture);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback function for libspng to read from the asset.
|
|
||||||
*
|
|
||||||
* @param ctx The spng context.
|
|
||||||
* @param user User data.
|
|
||||||
* @param destination Destination buffer.
|
|
||||||
* @param length Length of the buffer.
|
|
||||||
* @return The amount of data read.
|
|
||||||
*/
|
|
||||||
int32_t textureSPNGBuffer(
|
|
||||||
spng_ctx *ctx,
|
|
||||||
void *user,
|
|
||||||
void *destination,
|
|
||||||
size_t length
|
|
||||||
);
|
|
@ -1,32 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "tilesetgl.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
|
|
||||||
const char* TILESET_GL_TEXTURES_PATHS[TILESET_COUNT] = {
|
|
||||||
NULL,
|
|
||||||
"textures/8x8.png"
|
|
||||||
};
|
|
||||||
|
|
||||||
texture_t TILESET_GL_TEXTURES[TILESET_SLOT_COUNT];
|
|
||||||
|
|
||||||
void tilesetGLBind() {
|
|
||||||
uint8_t i;
|
|
||||||
do {
|
|
||||||
if(TILESET_SLOTS[i] == TILESET_NULL) continue;
|
|
||||||
textureBind(TILESET_GL_TEXTURES + i, i);
|
|
||||||
} while(++i < TILESET_SLOT_COUNT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tilesetBind(const tilesetid_t id, const uint8_t slot) {
|
|
||||||
assertTrue(slot < TILESET_SLOT_COUNT, "Invalid slot");
|
|
||||||
assertTrue(id < TILESET_COUNT, "Invalid tileset id");
|
|
||||||
|
|
||||||
TILESET_SLOTS[slot] = id;
|
|
||||||
textureLoad(TILESET_GL_TEXTURES + slot, TILESET_GL_TEXTURES_PATHS[id]);
|
|
||||||
}
|
|
@ -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 "texture.h"
|
|
||||||
#include "display/tileset.h"
|
|
||||||
|
|
||||||
extern const char* TILESET_GL_TEXTURES_PATHS[];
|
|
||||||
extern texture_t TILESET_GL_TEXTURES[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Binds the tileset to the OpenGL context.
|
|
||||||
*/
|
|
||||||
void tilesetGLBind();
|
|
@ -1,24 +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 "duskglimpl.h"
|
|
||||||
|
|
||||||
#include <libgen.h>
|
|
||||||
#include <cglm/cglm.h>
|
|
||||||
#include <float.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
typedef float float_t;
|
|
||||||
typedef double double_t;
|
|
||||||
|
|
||||||
extern char_t EXECUTABLE_PATH[];
|
|
||||||
extern char_t EXECUTABLE_DIRECTORY[];
|
|
||||||
|
|
||||||
typedef uint32_t uvec4_t[4];
|
|
@ -1,12 +0,0 @@
|
|||||||
# Copyright (c) 2025 Dominic Masters
|
|
||||||
#
|
|
||||||
# This software is released under the MIT License.
|
|
||||||
# https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
# Sources
|
|
||||||
target_sources(${DUSK_TARGET_NAME}
|
|
||||||
PRIVATE
|
|
||||||
overworld.c
|
|
||||||
)
|
|
||||||
|
|
||||||
# Subdirs
|
|
@ -1,21 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "overworld/overworld.h"
|
|
||||||
#include "display/quad.h"
|
|
||||||
#include "display/shader/entityshader/entityshader.h"
|
|
||||||
#include "display/shader/mapshader/mapshader.h"
|
|
||||||
|
|
||||||
void overworldRender() {
|
|
||||||
mapShaderUse();
|
|
||||||
quadRender(
|
|
||||||
OVERWORLD.map.width * OVERWORLD.map.height * OVERWORLD.map.layerCount
|
|
||||||
);
|
|
||||||
|
|
||||||
entityShaderUse();
|
|
||||||
quadRender(OVERWORLD.entityCount);
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
# Copyright (c) 2025 Dominic Masters
|
|
||||||
#
|
|
||||||
# This software is released under the MIT License.
|
|
||||||
# https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
# Libs
|
|
||||||
target_link_libraries(${DUSK_TARGET_NAME}
|
|
||||||
PUBLIC
|
|
||||||
glfw
|
|
||||||
glad
|
|
||||||
)
|
|
||||||
|
|
||||||
# Includes
|
|
||||||
target_include_directories(${DUSK_TARGET_NAME}
|
|
||||||
PUBLIC
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Sources
|
|
||||||
target_sources(${DUSK_TARGET_NAME}
|
|
||||||
PRIVATE
|
|
||||||
main.c
|
|
||||||
input.c
|
|
||||||
)
|
|
||||||
|
|
||||||
# Subdirs
|
|
||||||
add_subdirectory(display)
|
|
@ -1,10 +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
|
|
||||||
window.c
|
|
||||||
)
|
|
@ -1,79 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "window.h"
|
|
||||||
|
|
||||||
GLFWwindow* window;
|
|
||||||
uint32_t WINDOW_WIDTH;
|
|
||||||
uint32_t WINDOW_HEIGHT;
|
|
||||||
|
|
||||||
int32_t windowInit() {
|
|
||||||
// Initialize GLFW
|
|
||||||
if(!glfwInit()) {
|
|
||||||
const char* description;
|
|
||||||
int code = glfwGetError(&description);
|
|
||||||
if (description) {
|
|
||||||
printf("GLFW Error %d: %s\n", code, description);
|
|
||||||
} else {
|
|
||||||
printf("GLFW Error: Unknown error\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a windowed mode window and its OpenGL contex
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
|
||||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
|
||||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
|
|
||||||
glfwWindowHint(GLFW_MAXIMIZED, GLFW_FALSE);
|
|
||||||
glfwWindowHint(GLFW_VISIBLE, GLFW_TRUE);
|
|
||||||
glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE);
|
|
||||||
|
|
||||||
window = glfwCreateWindow(
|
|
||||||
WINDOW_WIDTH_DEFAULT, WINDOW_HEIGHT_DEFAULT,
|
|
||||||
"Dusk",
|
|
||||||
NULL, NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
WINDOW_WIDTH = WINDOW_WIDTH_DEFAULT;
|
|
||||||
WINDOW_HEIGHT = WINDOW_HEIGHT_DEFAULT;
|
|
||||||
|
|
||||||
if(!window) {
|
|
||||||
glfwTerminate();
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make the window's context current
|
|
||||||
glfwMakeContextCurrent(window);
|
|
||||||
glfwSwapInterval(1);
|
|
||||||
|
|
||||||
// Get initial framebuffer sizeglfwCreateWindow
|
|
||||||
glfwGetFramebufferSize(window, &WINDOW_WIDTH, &WINDOW_HEIGHT);
|
|
||||||
|
|
||||||
// Load OpenGL functions using glad or another loader here if necessary
|
|
||||||
if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) return -3;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool_t windowShouldClose() {
|
|
||||||
return glfwWindowShouldClose(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void windowUpdate() {
|
|
||||||
glfwSwapBuffers(window);
|
|
||||||
glfwPollEvents();
|
|
||||||
|
|
||||||
glfwGetFramebufferSize(window, &WINDOW_WIDTH, &WINDOW_HEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void windowDispose() {
|
|
||||||
glfwDestroyWindow(window);
|
|
||||||
glfwTerminate();
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "duskglfw.h"
|
|
||||||
#include "display/displaydefs.h"
|
|
||||||
|
|
||||||
#define WINDOW_WIDTH_DEFAULT SCREEN_WIDTH*3
|
|
||||||
#define WINDOW_HEIGHT_DEFAULT SCREEN_HEIGHT*3
|
|
||||||
|
|
||||||
extern GLFWwindow* window;
|
|
||||||
extern uint32_t WINDOW_WIDTH;
|
|
||||||
extern uint32_t WINDOW_HEIGHT;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the game render window.
|
|
||||||
*
|
|
||||||
* @return 0 on success, any other value on failure.
|
|
||||||
*/
|
|
||||||
int32_t windowInit();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the window should close.
|
|
||||||
*
|
|
||||||
* @return true if the window should close, false otherwise.
|
|
||||||
*/
|
|
||||||
bool_t windowShouldClose();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the window subsystem.
|
|
||||||
*/
|
|
||||||
void windowUpdate();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disposes of the window.
|
|
||||||
*/
|
|
||||||
void windowDispose();
|
|
@ -1,9 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include "duskgl.h"
|
|
@ -1,11 +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 <glad/glad.h>
|
|
||||||
#include <GLFW/glfw3.h>
|
|
@ -1,56 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "input.h"
|
|
||||||
#include "display/window.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint16_t glfw;
|
|
||||||
inputstate_t bind;
|
|
||||||
} glfwkeybindmap_t;
|
|
||||||
|
|
||||||
glfwkeybindmap_t GLFW_KEY_BIND_MAP[] = {
|
|
||||||
{GLFW_KEY_W, INPUT_UP},
|
|
||||||
{GLFW_KEY_UP, INPUT_UP},
|
|
||||||
|
|
||||||
{GLFW_KEY_S, INPUT_DOWN},
|
|
||||||
{GLFW_KEY_DOWN, INPUT_DOWN},
|
|
||||||
|
|
||||||
{GLFW_KEY_A, INPUT_LEFT},
|
|
||||||
{GLFW_KEY_LEFT, INPUT_LEFT},
|
|
||||||
|
|
||||||
{GLFW_KEY_D, INPUT_RIGHT},
|
|
||||||
{GLFW_KEY_RIGHT, INPUT_RIGHT},
|
|
||||||
|
|
||||||
{GLFW_KEY_ENTER, INPUT_ACCEPT},
|
|
||||||
{GLFW_KEY_E, INPUT_ACCEPT},
|
|
||||||
{GLFW_KEY_SPACE, INPUT_ACCEPT},
|
|
||||||
|
|
||||||
{GLFW_KEY_BACKSPACE, INPUT_BACK},
|
|
||||||
{GLFW_KEY_Q, INPUT_BACK},
|
|
||||||
|
|
||||||
{GLFW_KEY_ESCAPE, INPUT_MENU},
|
|
||||||
|
|
||||||
{0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
inputstate_t inputPlatformState() {
|
|
||||||
inputstate_t state = 0;
|
|
||||||
|
|
||||||
// Handle keybinds
|
|
||||||
glfwkeybindmap_t *map = GLFW_KEY_BIND_MAP;
|
|
||||||
do {
|
|
||||||
if(glfwGetKey(window, map->glfw) != GLFW_PRESS) {
|
|
||||||
map++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
state |= map->bind;
|
|
||||||
map++;
|
|
||||||
} while(map->glfw != 0);
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
@ -1,70 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "assert/assert.h"
|
|
||||||
#include "display/window.h"
|
|
||||||
#include "display/render.h"
|
|
||||||
#include "game.h"
|
|
||||||
#include "asset.h"
|
|
||||||
|
|
||||||
char_t EXECUTABLE_PATH[FILENAME_MAX];
|
|
||||||
char_t EXECUTABLE_DIRECTORY[FILENAME_MAX];
|
|
||||||
|
|
||||||
int32_t main(int32_t argc, char_t **argv) {
|
|
||||||
// Get launch args
|
|
||||||
assertTrue(argc > 0, "argc is not valid!");
|
|
||||||
assertNotNull(argv, "argv is not valid!");
|
|
||||||
assertNotNull(argv[0], "argv[0] is not valid!");
|
|
||||||
assertStrLen(argv[0], FILENAME_MAX, "argv[0] is too long!");
|
|
||||||
assertStrLenMin(argv[0], 1, "argv[0] is empty!");
|
|
||||||
|
|
||||||
// Store the executable path and directory.
|
|
||||||
strcpy(EXECUTABLE_PATH, argv[0]);
|
|
||||||
strcpy(EXECUTABLE_DIRECTORY, dirname(EXECUTABLE_PATH));
|
|
||||||
|
|
||||||
// Init systems
|
|
||||||
int32_t ret;
|
|
||||||
if((ret = windowInit()) != 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
gameInit();
|
|
||||||
|
|
||||||
// Init asset and render systems.
|
|
||||||
assetInit();
|
|
||||||
renderInit();
|
|
||||||
|
|
||||||
// Prepare for time tracking
|
|
||||||
double_t time, newTime;
|
|
||||||
float_t fDelta, fTimeSinceLastFrame = 1.0f;
|
|
||||||
int32_t updateResult;
|
|
||||||
|
|
||||||
// Main loop
|
|
||||||
while(!windowShouldClose()) {
|
|
||||||
// Determine the delta.
|
|
||||||
newTime = glfwGetTime();
|
|
||||||
fDelta = (float_t)(newTime - time);
|
|
||||||
time = newTime;
|
|
||||||
fTimeSinceLastFrame += fDelta;
|
|
||||||
|
|
||||||
// Tick according to the game tick rate.
|
|
||||||
if(fTimeSinceLastFrame >= (1.0f / GAME_TICK_RATE)) {
|
|
||||||
gameUpdate();
|
|
||||||
fTimeSinceLastFrame = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw. In future may be tick based.
|
|
||||||
renderUpdate();
|
|
||||||
windowUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
renderDispose();
|
|
||||||
windowDispose();
|
|
||||||
assetDispose();
|
|
||||||
gameDispose();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
# Copyright (c) 2025 Dominic Masters
|
|
||||||
#
|
|
||||||
# This software is released under the MIT License.
|
|
||||||
# https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
# Libs
|
|
||||||
target_link_libraries(${DUSK_TARGET_NAME}
|
|
||||||
PUBLIC
|
|
||||||
)
|
|
||||||
|
|
||||||
# Includes
|
|
||||||
target_include_directories(${DUSK_TARGET_NAME}
|
|
||||||
PUBLIC
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Sources
|
|
||||||
target_sources(${DUSK_TARGET_NAME}
|
|
||||||
PRIVATE
|
|
||||||
main.c
|
|
||||||
)
|
|
||||||
|
|
||||||
# Subdirs
|
|
@ -1,39 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Dominic Masters
|
|
||||||
*
|
|
||||||
* This software is released under the MIT License.
|
|
||||||
* https://opensource.org/licenses/MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "dusk.h"
|
|
||||||
#include "error/error.h"
|
|
||||||
#include "console/console.h"
|
|
||||||
#include "util/string.h"
|
|
||||||
|
|
||||||
bool_t exitRequested = false;
|
|
||||||
|
|
||||||
void cmdExit(const consolecmdexec_t *exec) {
|
|
||||||
exitRequested = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void testChange(const consolevar_t *var) {
|
|
||||||
consolePrint("Variable '%s' changed to '%s'.", var->name, var->value);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
consoleInit();
|
|
||||||
|
|
||||||
consoleRegCmd("exit", cmdExit);
|
|
||||||
consoleRegVar("test", "Hello", testChange);
|
|
||||||
consolePrint(" = Dusk Console = ");
|
|
||||||
|
|
||||||
char_t buffer[CONSOLE_LINE_MAX * 10];
|
|
||||||
while(fgets(buffer, sizeof(buffer), stdin)) {
|
|
||||||
consoleExec(buffer);
|
|
||||||
consoleProcess();
|
|
||||||
if(exitRequested) break;
|
|
||||||
}
|
|
||||||
printf("Goodbye!\n");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -35,11 +35,21 @@ bool_t errorCheck() {
|
|||||||
return ERROR_STACK.code != ERROR_OK;
|
return ERROR_STACK.code != ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
errorret_t errorPrint() {
|
const char_t * errorString() {
|
||||||
if(ERROR_STACK.code == ERROR_OK) return ERROR_OK;
|
if(!errorCheck()) return NULL;
|
||||||
|
return ERROR_STACK.message;
|
||||||
|
}
|
||||||
|
|
||||||
printf("Error: %s\n", ERROR_STACK.message);
|
void errorFlush() {
|
||||||
errorret_t code = ERROR_STACK.code;
|
if(!errorCheck()) return;
|
||||||
ERROR_STACK.code = ERROR_OK;
|
ERROR_STACK.code = ERROR_OK;
|
||||||
|
ERROR_STACK.message[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t errorPrint() {
|
||||||
|
if(!errorCheck()) return ERROR_OK;
|
||||||
|
printf("Error: %s\n", errorString());
|
||||||
|
errorret_t code = ERROR_STACK.code;
|
||||||
|
errorFlush();
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
@ -44,6 +44,16 @@ errorret_t errorCode(const errorret_t code, const char_t *message, ...);
|
|||||||
*/
|
*/
|
||||||
bool_t errorCheck();
|
bool_t errorCheck();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the error message from the error stack.
|
||||||
|
*/
|
||||||
|
const char_t * errorString();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the error stack.
|
||||||
|
*/
|
||||||
|
void errorFlush();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints the error stack to the console. This also clears the error stack.
|
* Prints the error stack to the console. This also clears the error stack.
|
||||||
*/
|
*/
|
48
src/main.c
Normal file
48
src/main.c
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "console/console.h"
|
||||||
|
#include "server/server.h"
|
||||||
|
|
||||||
|
void cmdExit(const consolecmdexec_t *exec) {
|
||||||
|
CloseWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmdServe(const consolecmdexec_t *exec) {
|
||||||
|
serverStart(3030);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmdClose(const consolecmdexec_t *exec) {
|
||||||
|
serverStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
consoleInit();
|
||||||
|
serverInit();
|
||||||
|
|
||||||
|
consoleRegCmd("exit", cmdExit);
|
||||||
|
consoleRegCmd("serve", cmdServe);
|
||||||
|
consoleRegCmd("close", cmdClose);
|
||||||
|
|
||||||
|
InitWindow(1280, 720, DUSK_NAME);
|
||||||
|
|
||||||
|
while(!WindowShouldClose()) {
|
||||||
|
consoleUpdate();
|
||||||
|
|
||||||
|
BeginDrawing();
|
||||||
|
ClearBackground(RAYWHITE);
|
||||||
|
|
||||||
|
consoleDraw();
|
||||||
|
|
||||||
|
EndDrawing();
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseWindow();
|
||||||
|
serverDispose();
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
@ -6,5 +6,6 @@
|
|||||||
# Sources
|
# Sources
|
||||||
target_sources(${DUSK_TARGET_NAME}
|
target_sources(${DUSK_TARGET_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
assertgl.c
|
server.c
|
||||||
|
serverclient.c
|
||||||
)
|
)
|
192
src/server/server.c
Normal file
192
src/server/server.c
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "server.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "console/console.h"
|
||||||
|
|
||||||
|
server_t SERVER;
|
||||||
|
|
||||||
|
void serverInit() {
|
||||||
|
memoryZero(&SERVER, sizeof(server_t));
|
||||||
|
pthread_mutex_init(&SERVER.startMutex, NULL);
|
||||||
|
pthread_cond_init(&SERVER.startCond, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t serverStart(uint16_t port) {
|
||||||
|
assertFalse(SERVER.isRunning, "Server is already running?");
|
||||||
|
consolePrint("Starting server on port %d...\n", port);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&SERVER.startMutex);
|
||||||
|
SERVER.threadReady = false;
|
||||||
|
|
||||||
|
// Initialize the server socket
|
||||||
|
SERVER.serverSocket = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if(SERVER.serverSocket < 0) {
|
||||||
|
pthread_mutex_unlock(&SERVER.startMutex);
|
||||||
|
return error("Failed to create socket");
|
||||||
|
}
|
||||||
|
SERVER.serverAddress.sin_family = AF_INET;
|
||||||
|
SERVER.serverAddress.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
SERVER.serverAddress.sin_port = htons(port);
|
||||||
|
|
||||||
|
// Bind the socket to the address and port
|
||||||
|
int32_t res = bind(
|
||||||
|
SERVER.serverSocket,
|
||||||
|
(struct sockaddr *)&SERVER.serverAddress,
|
||||||
|
sizeof(SERVER.serverAddress)
|
||||||
|
);
|
||||||
|
if(res < 0) {
|
||||||
|
close(SERVER.serverSocket);
|
||||||
|
pthread_mutex_unlock(&SERVER.startMutex);
|
||||||
|
return error("Failed to bind socket");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the socket to listen for incoming connections
|
||||||
|
res = listen(SERVER.serverSocket, SERVER_MAX_CLIENTS);
|
||||||
|
if(res < 0) {
|
||||||
|
close(SERVER.serverSocket);
|
||||||
|
pthread_mutex_unlock(&SERVER.startMutex);
|
||||||
|
return error("Failed to listen on socket");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the server thread
|
||||||
|
SERVER.isRunning = true;
|
||||||
|
if(pthread_create(&SERVER.thread, NULL, serverThread, NULL) != 0) {
|
||||||
|
perror("Failed to create server thread");
|
||||||
|
serverStop();
|
||||||
|
pthread_mutex_unlock(&SERVER.startMutex);
|
||||||
|
return error("Failed to create server thread");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for the server thread to be ready
|
||||||
|
while(!SERVER.threadReady) {
|
||||||
|
pthread_cond_wait(&SERVER.startCond, &SERVER.startMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&SERVER.startMutex);
|
||||||
|
consolePrint("Server started.");
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void * serverThread(void *arg) {
|
||||||
|
struct timeval timeout;
|
||||||
|
fd_set readfds;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&SERVER.startMutex);
|
||||||
|
SERVER.threadReady = true;
|
||||||
|
pthread_cond_signal(&SERVER.startCond);
|
||||||
|
pthread_mutex_unlock(&SERVER.startMutex);
|
||||||
|
|
||||||
|
while(SERVER.isRunning) {
|
||||||
|
usleep(SERVER_TIMEOUT * 1000);
|
||||||
|
|
||||||
|
FD_ZERO(&readfds);
|
||||||
|
FD_SET(SERVER.serverSocket, &readfds);
|
||||||
|
|
||||||
|
timeout.tv_usec = SERVER_TIMEOUT * 1000;
|
||||||
|
|
||||||
|
// Wait for
|
||||||
|
int32_t activity = select(
|
||||||
|
SERVER.serverSocket + 1,
|
||||||
|
&readfds,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&timeout
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check for errors
|
||||||
|
if(activity < 0) {
|
||||||
|
consolePrint("Error in select");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timeout
|
||||||
|
if(activity == 0) continue;
|
||||||
|
|
||||||
|
// Check if there is a new connection
|
||||||
|
if(!FD_ISSET(SERVER.serverSocket, &readfds)) continue;
|
||||||
|
|
||||||
|
// Accept new connection
|
||||||
|
int32_t clientSocket = accept(SERVER.serverSocket, NULL, NULL);
|
||||||
|
if(clientSocket < 0) {
|
||||||
|
consolePrint("Failed to accept connection");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Initialize the client
|
||||||
|
serverclient_t *client = NULL;
|
||||||
|
uint8_t i = 0;
|
||||||
|
do {
|
||||||
|
if(SERVER.clients[i].state != SERVER_CLIENT_STATE_DISCONNECTED) {
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
client = &SERVER.clients[i];
|
||||||
|
break;
|
||||||
|
} while(i < SERVER_MAX_CLIENTS);
|
||||||
|
|
||||||
|
// Can we receive this client?
|
||||||
|
if(!client) {
|
||||||
|
const char_t *errMsg = "ERR|Server full";
|
||||||
|
send(clientSocket, errMsg, strlen(errMsg), 0);
|
||||||
|
consolePrint("Server full, closing connection.");
|
||||||
|
close(clientSocket);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t ret = serverClientAccept(client, clientSocket);
|
||||||
|
if(ret != ERROR_OK) {
|
||||||
|
consolePrint("Failed to accept client connection", errorString());
|
||||||
|
errorFlush();
|
||||||
|
close(clientSocket);
|
||||||
|
}
|
||||||
|
|
||||||
|
usleep(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Server thread exiting.\n");
|
||||||
|
assertFalse(
|
||||||
|
SERVER.isRunning, "Server thread exiting while server is running?"
|
||||||
|
);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t serverGetClientCount() {
|
||||||
|
uint8_t i = 0, clientCount = 0;
|
||||||
|
do {
|
||||||
|
if(SERVER.clients[i].state == SERVER_CLIENT_STATE_DISCONNECTED) continue;
|
||||||
|
clientCount++;
|
||||||
|
} while(i < SERVER_MAX_CLIENTS);
|
||||||
|
return clientCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serverStop() {
|
||||||
|
consolePrint("Stopping server...");
|
||||||
|
|
||||||
|
SERVER.isRunning = false;
|
||||||
|
if(SERVER.serverSocket >= 0) {
|
||||||
|
close(SERVER.serverSocket);
|
||||||
|
SERVER.serverSocket = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(SERVER.thread) {
|
||||||
|
pthread_join(SERVER.thread, NULL);
|
||||||
|
SERVER.thread = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_destroy(&SERVER.startMutex);
|
||||||
|
pthread_cond_destroy(&SERVER.startCond);
|
||||||
|
|
||||||
|
consolePrint("Server stopped.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void serverDispose() {
|
||||||
|
serverStop();
|
||||||
|
}
|
81
src/server/server.h
Normal file
81
src/server/server.h
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "serverclient.h"
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#define SERVER_MAX_CLIENTS 32
|
||||||
|
#define SERVER_MAX_CHANNELS 2
|
||||||
|
#define SERVER_TIMEOUT 200
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool_t isRunning;
|
||||||
|
pthread_t thread;
|
||||||
|
int serverSocket;
|
||||||
|
struct sockaddr_in serverAddress;
|
||||||
|
pthread_mutex_t startMutex;
|
||||||
|
pthread_cond_t startCond;
|
||||||
|
bool_t threadReady;
|
||||||
|
serverclient_t clients[SERVER_MAX_CLIENTS];
|
||||||
|
} server_t;
|
||||||
|
|
||||||
|
extern server_t SERVER;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the server
|
||||||
|
*
|
||||||
|
* This function initializes the server by setting up the ENet library and
|
||||||
|
* creating a server host.
|
||||||
|
*/
|
||||||
|
void serverInit();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the server
|
||||||
|
*
|
||||||
|
* This function starts the server by creating a host, binding it to the
|
||||||
|
* specified address and port, and starting the server thread.
|
||||||
|
*
|
||||||
|
* @param port The port number to bind the server to.
|
||||||
|
* @return Returns an error code if the server fails to start.
|
||||||
|
*/
|
||||||
|
errorret_t serverStart(uint16_t port);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server thread function
|
||||||
|
*
|
||||||
|
* This function runs in a separate thread and handles incoming connections,
|
||||||
|
* messages, and disconnections.
|
||||||
|
*
|
||||||
|
* @param arg Pointer to the argument passed to the thread.
|
||||||
|
*/
|
||||||
|
void * serverThread(void *arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the client count
|
||||||
|
*
|
||||||
|
* This function returns the number of connected clients to the server.
|
||||||
|
*
|
||||||
|
* @return The number of connected clients.
|
||||||
|
*/
|
||||||
|
uint8_t serverGetClientCount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop the server
|
||||||
|
*
|
||||||
|
* This function stops the server by destroying the host and cleaning up
|
||||||
|
* resources.
|
||||||
|
*/
|
||||||
|
void serverStop();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispose of the server
|
||||||
|
*
|
||||||
|
* This function disposes of the server by deinitializing the ENet library.
|
||||||
|
*/
|
||||||
|
void serverDispose();
|
109
src/server/serverclient.c
Normal file
109
src/server/serverclient.c
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "serverclient.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include "console/console.h"
|
||||||
|
|
||||||
|
errorret_t serverClientAccept(
|
||||||
|
serverclient_t *client,
|
||||||
|
const int32_t socket
|
||||||
|
) {
|
||||||
|
memoryZero(client, sizeof(serverclient_t));
|
||||||
|
client->socket = socket;
|
||||||
|
client->state = SERVER_CLIENT_STATE_ACCEPTING;
|
||||||
|
|
||||||
|
// Set timeout to 20 seconds
|
||||||
|
client->timeout.tv_usec = SERVER_CLIENT_TIMEOUT * 1000;
|
||||||
|
|
||||||
|
// Create a thread for the client
|
||||||
|
if(pthread_create(&client->thread, NULL, serverClientThread, client) != 0) {
|
||||||
|
client->state = SERVER_CLIENT_STATE_DISCONNECTED;
|
||||||
|
return error("Failed to create client thread");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t serverClientSend(
|
||||||
|
serverclient_t * client,
|
||||||
|
const uint8_t *data,
|
||||||
|
const size_t len
|
||||||
|
) {
|
||||||
|
if(client->state != SERVER_CLIENT_STATE_ACCEPTING) {
|
||||||
|
return error("Client is not accepting");
|
||||||
|
}
|
||||||
|
ssize_t sent = send(client->socket, data, len, 0);
|
||||||
|
if(sent < 0) return error("Failed to send data");
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t serverClientSendString(
|
||||||
|
serverclient_t * client,
|
||||||
|
const char_t *data
|
||||||
|
) {
|
||||||
|
return serverClientSend(client, (const uint8_t *)data, strlen(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t serverClientReceive(
|
||||||
|
serverclient_t * client,
|
||||||
|
uint8_t *buffer,
|
||||||
|
const size_t len
|
||||||
|
) {
|
||||||
|
if(client->state != SERVER_CLIENT_STATE_ACCEPTING) return -1;
|
||||||
|
ssize_t received = recv(client->socket, buffer, len, 0);
|
||||||
|
if(received < 0) return received;
|
||||||
|
return received;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serverClientClose(serverclient_t *client) {
|
||||||
|
client->state = SERVER_CLIENT_STATE_DISCONNECTED;
|
||||||
|
close(client->socket);
|
||||||
|
pthread_join(client->thread, NULL);
|
||||||
|
client->thread = 0;
|
||||||
|
client->socket = -1;
|
||||||
|
consolePrint("Client disconnected.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void *serverClientThread(void *arg) {
|
||||||
|
serverclient_t *client = (serverclient_t *)arg;
|
||||||
|
char_t buffer[1024];
|
||||||
|
ssize_t read;
|
||||||
|
|
||||||
|
printf("Client thread started for socket %d.\n", client->socket);
|
||||||
|
|
||||||
|
// Set socket timeout
|
||||||
|
setsockopt(
|
||||||
|
client->socket,
|
||||||
|
SOL_SOCKET,
|
||||||
|
SO_RCVTIMEO,
|
||||||
|
&client->timeout,
|
||||||
|
sizeof(client->timeout)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Send welcome message
|
||||||
|
serverClientSendString(client, "DUSK|"DUSK_VERSION);
|
||||||
|
|
||||||
|
// Receive version from client
|
||||||
|
read = serverClientReceive(client, buffer, sizeof(buffer));
|
||||||
|
|
||||||
|
// First 5 bytes should be "DUSK|"
|
||||||
|
if(read < 5 || strncmp(buffer, "DUSK|", 5) != 0) {
|
||||||
|
serverClientSendString(client, "ERR|Invalid version (0)");
|
||||||
|
serverClientClose(client);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next (up to X bytes where X is the length of the version string)
|
||||||
|
// should be the version string
|
||||||
|
buffer[read] = '\0'; // Null-terminate the string
|
||||||
|
|
||||||
|
|
||||||
|
printf("Received version: %s\n", buffer);
|
||||||
|
|
||||||
|
serverClientClose(client);
|
||||||
|
return NULL;
|
||||||
|
}
|
85
src/server/serverclient.h
Normal file
85
src/server/serverclient.h
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "error/error.h"
|
||||||
|
|
||||||
|
#define SERVER_CLIENT_TIMEOUT 20000 // 20 seconds
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SERVER_CLIENT_STATE_DISCONNECTED,
|
||||||
|
SERVER_CLIENT_STATE_ACCEPTING,
|
||||||
|
} serverclientstate_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int32_t socket;
|
||||||
|
serverclientstate_t state;
|
||||||
|
pthread_t thread; // Add thread field
|
||||||
|
struct timeval timeout; // Add timeout field
|
||||||
|
} serverclient_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accepts an incoming connection from a server client.
|
||||||
|
*/
|
||||||
|
errorret_t serverClientAccept(
|
||||||
|
serverclient_t *client,
|
||||||
|
const int32_t socket
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends data to a server client.
|
||||||
|
*
|
||||||
|
* @param client Pointer to the server client structure.
|
||||||
|
* @param data Pointer to the data to send.
|
||||||
|
* @param len Length of the data to send.
|
||||||
|
* @return Error code indicating success or failure.
|
||||||
|
*/
|
||||||
|
errorret_t serverClientSend(
|
||||||
|
serverclient_t * client,
|
||||||
|
const uint8_t *data,
|
||||||
|
const size_t len
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a string to a server client.
|
||||||
|
*
|
||||||
|
* @param client Pointer to the server client structure.
|
||||||
|
* @param data Pointer to the string to send.
|
||||||
|
* @return Error code indicating success or failure.
|
||||||
|
*/
|
||||||
|
errorret_t serverClientSendString(
|
||||||
|
serverclient_t * client,
|
||||||
|
const char_t *data
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receives data from a server client.
|
||||||
|
*
|
||||||
|
* @param client Pointer to the server client structure.
|
||||||
|
* @param buffer Pointer to the buffer to store received data.
|
||||||
|
* @param len Max length of the buffer.
|
||||||
|
* @return Number of bytes received. 0 or less indicates an error.
|
||||||
|
*/
|
||||||
|
ssize_t serverClientReceive(
|
||||||
|
serverclient_t * client,
|
||||||
|
uint8_t *buffer,
|
||||||
|
const size_t len
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the connection to a server client.
|
||||||
|
*/
|
||||||
|
void serverClientClose(
|
||||||
|
serverclient_t *client
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread function for handling a server client.
|
||||||
|
*
|
||||||
|
* @param arg Pointer to the server client structure.
|
||||||
|
*/
|
||||||
|
void *serverClientThread(void *arg);
|
Reference in New Issue
Block a user