Merge branch 'main' into break-literally-everything

This commit is contained in:
2026-03-03 12:28:48 -06:00
47 changed files with 851 additions and 346 deletions

View File

@@ -8,6 +8,7 @@
#include "asset/asset.h"
#include "assert/assert.h"
#include "map/mapchunk.h"
#include "util/endian.h"
#pragma pack(push, 1)
typedef struct {
@@ -56,7 +57,7 @@ errorret_t assetMapChunkHandler(assetcustom_t custom) {
}
// Fix endianess if necessary
header.tileCount = le32toh(header.tileCount);
header.tileCount = endianLittleToHost32(header.tileCount);
if(header.tileCount != CHUNK_TILE_COUNT) {
zip_fclose(custom.zipFile);
@@ -111,7 +112,7 @@ errorret_t assetMapChunkHandler(assetcustom_t custom) {
}
// Fix endianess if necessary
modelHeader.vertexCount = le32toh(modelHeader.vertexCount);
modelHeader.vertexCount = endianLittleToHost32(modelHeader.vertexCount);
if(
vertexIndex + modelHeader.vertexCount >

View File

@@ -7,7 +7,7 @@
#pragma once
#include "error/error.h"
#include "display/palette/palette.h"
#include "display/texture/palette.h"
typedef struct assetentire_s assetentire_t;

View File

@@ -8,7 +8,8 @@
#include "assettexture.h"
#include "asset/assettype.h"
#include "assert/assert.h"
#include "display/texture.h"
#include "display/texture/texture.h"
#include "util/endian.h"
errorret_t assetTextureLoad(assetentire_t entire) {
assertNotNull(entire.data, "Data pointer cannot be NULL.");
@@ -32,8 +33,8 @@ errorret_t assetTextureLoad(assetentire_t entire) {
}
// Fix endian
assetData->width = le32toh(assetData->width);
assetData->height = le32toh(assetData->height);
assetData->width = endianLittleToHost32(assetData->width);
assetData->height = endianLittleToHost32(assetData->height);
// Check dimensions.
if(

View File

@@ -8,8 +8,8 @@
#pragma once
#include "error/error.h"
#define ASSET_TEXTURE_WIDTH_MAX 256
#define ASSET_TEXTURE_HEIGHT_MAX 256
#define ASSET_TEXTURE_WIDTH_MAX 2048
#define ASSET_TEXTURE_HEIGHT_MAX 2048
#define ASSET_TEXTURE_SIZE_MAX ( \
ASSET_TEXTURE_WIDTH_MAX * ASSET_TEXTURE_HEIGHT_MAX \
)
@@ -20,10 +20,8 @@ typedef struct assetentire_s assetentire_t;
typedef struct {
char_t header[3];
uint8_t version;
uint32_t width;
uint32_t height;
uint8_t paletteIndex;
uint8_t palette[ASSET_TEXTURE_SIZE_MAX];
} assettexture_t;
#pragma pack(pop)

View File

@@ -7,7 +7,9 @@
#include "asset/asset.h"
#include "assert/assert.h"
#include "display/tileset/tileset.h"
#include "display/texture/tileset.h"
#include "util/memory.h"
#include "util/endian.h"
errorret_t assetTilesetLoad(assetentire_t entire) {
assertNotNull(entire.data, "Asset data cannot be null");
@@ -28,5 +30,41 @@ errorret_t assetTilesetLoad(assetentire_t entire) {
errorThrow("Unsupported tileset version");
}
errorThrow("unfinished");
// Fix endianness
tilesetData->tileWidth = endianLittleToHost16(tilesetData->tileWidth);
tilesetData->tileHeight = endianLittleToHost16(tilesetData->tileHeight);
tilesetData->columnCount = endianLittleToHost16(tilesetData->columnCount);
tilesetData->rowCount = endianLittleToHost16(tilesetData->rowCount);
tilesetData->right = endianLittleToHost16(tilesetData->right);
tilesetData->bottom = endianLittleToHost16(tilesetData->bottom);
if(tilesetData->tileWidth == 0) {
errorThrow("Tile width cannot be 0");
}
if(tilesetData->tileHeight == 0) {
errorThrow("Tile height cannot be 0");
}
if(tilesetData->columnCount == 0) {
errorThrow("Column count cannot be 0");
}
if(tilesetData->rowCount == 0) {
errorThrow("Row count cannot be 0");
}
tilesetData->u0 = endianLittleToHostFloat(tilesetData->u0);
tilesetData->v0 = endianLittleToHostFloat(tilesetData->v0);
if(tilesetData->v0 < 0.0f || tilesetData->v0 > 1.0f) {
errorThrow("Invalid v0 value in tileset");
}
// Setup tileset
tileset->tileWidth = tilesetData->tileWidth;
tileset->tileHeight = tilesetData->tileHeight;
tileset->tileCount = tilesetData->columnCount * tilesetData->rowCount;
tileset->columns = tilesetData->columnCount;
tileset->rows = tilesetData->rowCount;
tileset->uv[0] = tilesetData->u0;
tileset->uv[1] = tilesetData->v0;
errorOk();
}

View File

@@ -12,6 +12,14 @@
typedef struct {
char_t header[3];
uint8_t version;
uint16_t tileWidth;
uint16_t tileHeight;
uint16_t columnCount;
uint16_t rowCount;
uint16_t right;
uint16_t bottom;
float_t u0;
float_t v0;
} assettileset_t;
#pragma pack(pop)

View File

@@ -7,6 +7,4 @@
target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
debug.c
)
# Subdirs
)

View File

@@ -9,7 +9,6 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
display.c
framebuffer.c
screen.c
texture.c
spritebatch.c
text.c
)
@@ -17,38 +16,9 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
# Subdirectories
add_subdirectory(camera)
add_subdirectory(mesh)
add_subdirectory(palette)
add_subdirectory(tileset)
if(DUSK_TARGET_SYSTEM STREQUAL "linux")
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
DISPLAY_SDL2=1
DISPLAY_WINDOW_WIDTH_DEFAULT=1080
DISPLAY_WINDOW_HEIGHT_DEFAULT=810
DISPLAY_SCREEN_HEIGHT_DEFAULT=270
)
elseif(DUSK_TARGET_SYSTEM STREQUAL "psp")
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
DISPLAY_SDL2=1
DISPLAY_WINDOW_WIDTH_DEFAULT=480
DISPLAY_WINDOW_HEIGHT_DEFAULT=272
DISPLAY_WIDTH=480
DISPLAY_HEIGHT=272
DISPLAY_SIZE_DYNAMIC=0
)
elseif(DUSK_TARGET_SYSTEM STREQUAL "gamecube" OR DUSK_TARGET_SYSTEM STREQUAL "wii")
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
DISPLAY_WINDOW_WIDTH_DEFAULT=640
DISPLAY_WINDOW_HEIGHT_DEFAULT=480
DISPLAY_WIDTH=640
DISPLAY_HEIGHT=480
DISPLAY_SIZE_DYNAMIC=0
)
endif()
add_subdirectory(texture)
# Color definitions
dusk_run_python(
dusk_color_defs
tools.display.color.csv

View File

@@ -88,6 +88,7 @@ errorret_t displayInit(void) {
#else
GLint mask = 0;
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
DISPLAY.usingShaderedPalettes = true;
if(mask & GL_CONTEXT_CORE_PROFILE_BIT) {
GLint numExtens = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &numExtens);
@@ -100,7 +101,7 @@ errorret_t displayInit(void) {
}
} else {
const char* ext = (const char*)glGetString(GL_EXTENSIONS);
DISPLAY.usingShaderedPalettes = (
DISPLAY.usingShaderedPalettes = !(
ext && strstr(ext, "GL_EXT_paletted_texture")
);
}

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "display/texture.h"
#include "display/texture/texture.h"
#define FRAMEBUFFER_CLEAR_COLOR (1 << 0)
#define FRAMEBUFFER_CLEAR_DEPTH (1 << 1)

View File

@@ -7,7 +7,7 @@
#pragma once
#include "display/mesh/quad.h"
#include "display/texture.h"
#include "display/texture/texture.h"
#define SPRITEBATCH_SPRITES_MAX 128
#define SPRITEBATCH_VERTEX_COUNT (SPRITEBATCH_SPRITES_MAX * QUAD_VERTEX_COUNT)

View File

@@ -21,7 +21,7 @@ errorret_t textInit(void) {
}
void textDispose(void) {
// textureDispose(&DEFAULT_FONT_TEXTURE);
textureDispose(&DEFAULT_FONT_TEXTURE);
}
void textDrawChar(
@@ -36,7 +36,6 @@ void textDrawChar(
if(tileIndex < 0 || tileIndex >= tileset->tileCount) {
tileIndex = ((int32_t)'@') - TEXT_CHAR_START;
}
assertTrue(
tileIndex >= 0 && tileIndex <= tileset->tileCount,
"Character is out of bounds for font tiles"

View File

@@ -7,8 +7,8 @@
#pragma once
#include "asset/asset.h"
#include "display/texture.h"
#include "display/tileset/tileset.h"
#include "display/texture/texture.h"
#include "display/texture/tileset.h"
#define TEXT_CHAR_START '!'

View File

@@ -6,5 +6,7 @@
# Sources
target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
tileset.c
texture.c
palette.c
)

View File

@@ -8,6 +8,18 @@
#pragma once
#include "display/color.h"
#if DISPLAY_SDL2
#if DISPLAY_SHADER == 1
#elif DISPLAY_COLOR_TABLE == 1
#else
#error "Unsupported palette mode"
#endif
#else
#error "Unsupported palette mode"
#endif
#define PALETTE_COUNT_MAX 4
#define PALETTE_COLOR_COUNT_MAX 0xFF

View File

@@ -0,0 +1,51 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "palettetexture.h"
#include "assert/assert.h"
void paletteTextureInit(
palettetexture_t *texture,
const int32_t width,
const int32_t height,
const uint8_t *data
) {
assertNotNull(texture, "Palette texture cannot be NULL");
assertTrue(width > 0 && height > 0, "width/height must be greater than 0");
assertNotNull(data, "Palette texture data cannot be NULL");
#if DISPLAY_SDL2
#if DISPLAY_SHADER == 1
// Palette textures not supported, convert to GL_RED style texture
// so shader can perform the lookup.
uint8_t formatted[width * height];
for(int32_t i = 0; i < width * height; i++) {
uint8_t index = data.paletteData[i];
formatted[i] = index * 128;
}
glTexImage2D(
GL_TEXTURE_2D, 0, GL_R8, width, height, 0,
GL_RED, GL_UNSIGNED_BYTE, (void*)formatted
);
#else
glTexImage2D(
GL_TEXTURE_2D,
0, GL_COLOR_INDEX8_EXT,
width, height,
0, GL_COLOR_INDEX8_EXT,
GL_UNSIGNED_BYTE, (void*)data.paletteData
);
// glColorTableEXT(
// GL_TEXTURE_2D, GL_RGBA, data.palette.palette->colorCount, GL_RGBA,
// GL_UNSIGNED_BYTE, (const void*)data.palette.palette->colors
// );
#endif
#else
#error "Palette textures not supported on this platform"
#endif
}

View File

@@ -0,0 +1,28 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "dusk.h"
typedef struct {
} palettetexture_t;
/**
* Initializes a palette texture.
*
* @param texture The palette texture to initialize.
* @param width The width of the texture. Must be a power of 2.
* @param height The height of the texture. Must be a power of 2.
* @param data The palette index data for the texture.
*/
void paletteTextureInit(
palettetexture_t *texture,
const int32_t width,
const int32_t height,
const uint8_t *data
);

View File

@@ -52,12 +52,13 @@ void textureInit(
uint8_t formatted[width * height];
for(int32_t i = 0; i < width * height; i++) {
uint8_t index = data.paletteData[i];
formatted[i] = index;
formatted[i] = index * 128;
}
glTexImage2D(
GL_TEXTURE_2D, 0, GL_R, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, (void*)formatted
GL_TEXTURE_2D, 0, GL_R8, width, height, 0,
GL_RED, GL_UNSIGNED_BYTE, (void*)formatted
);
} else {
glTexImage2D(
GL_TEXTURE_2D,
@@ -66,12 +67,17 @@ void textureInit(
0, GL_COLOR_INDEX8_EXT,
GL_UNSIGNED_BYTE, (void*)data.paletteData
);
// glColorTableEXT(
// GL_TEXTURE_2D, GL_RGBA, data.palette.palette->colorCount, GL_RGBA,
// GL_UNSIGNED_BYTE, (const void*)data.palette.palette->colors
// );
}
GLenum err = glGetError();
if(err != GL_NO_ERROR) {
printf("GL Error uploading palette texture: %d\n", err);
assertUnreachable("GL error uploading palette texture");
}
break;
default:

View File

@@ -8,7 +8,7 @@
#pragma once
#include "display/color.h"
#include "display/displaydefs.h"
#include "display/palette/palette.h"
#include "display/texture/palette.h"
typedef enum {
#if DISPLAY_SDL2

View File

@@ -9,14 +9,12 @@
#include "dusk.h"
typedef struct tileset_s {
const char_t *name;
const uint16_t tileWidth;
const uint16_t tileHeight;
const uint16_t tileCount;
const uint16_t columns;
const uint16_t rows;
const vec2 uv;
const char_t *image;
uint16_t tileWidth;
uint16_t tileHeight;
uint16_t tileCount;
uint16_t columns;
uint16_t rows;
vec2 uv;
} tileset_t;
/**

View File

@@ -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_LIBRARY_TARGET_NAME}
PUBLIC
tileset.c
)

View File

@@ -33,11 +33,6 @@
#include <ogcsys.h>
#include <gccore.h>
#include <malloc.h>
#include <sys/endian.h>
#else
#ifndef le32toh
#define le32toh(x) (x)
#endif
#endif
typedef bool bool_t;

View File

@@ -11,30 +11,7 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
inputaction.c
)
if(DUSK_TARGET_SYSTEM STREQUAL "linux")
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
INPUT_SDL2=1
INPUT_KEYBOARD=1
INPUT_POINTER=1
INPUT_GAMEPAD=1
)
elseif(DUSK_TARGET_SYSTEM STREQUAL "psp")
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
INPUT_SDL2=1
INPUT_GAMEPAD=1
)
elseif(DUSK_TARGET_SYSTEM STREQUAL "gamecube" OR DUSK_TARGET_SYSTEM STREQUAL "wii")
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
INPUT_GAMEPAD=1
)
endif()
# CSV
# Input Action Definitions
dusk_run_python(
dusk_input_csv_defs
tools.input.csv

View File

@@ -10,6 +10,7 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
backpack.c
)
# Item Definitions
dusk_run_python(
dusk_item_csv_defs
tools.item.csv

View File

@@ -7,7 +7,7 @@
#include "moduletexture.h"
#include "asset/asset.h"
#include "display/texture.h"
#include "display/texture/texture.h"
#include "assert/assert.h"
#include "util/memory.h"
#include "util/string.h"

View File

@@ -7,7 +7,7 @@
#include "moduletileset.h"
#include "assert/assert.h"
#include "display/tileset/tileset.h"
#include "display/texture/tileset.h"
#include "util/memory.h"
#include "util/string.h"
#include "debug/debug.h"
@@ -41,13 +41,7 @@ int moduleTilesetIndex(lua_State *l) {
tileset_t *ts = (tileset_t *)luaL_checkudata(l, 1, "tileset_mt");
assertNotNull(ts, "Tileset pointer cannot be NULL.");
if(stringCompare(key, "name") == 0) {
lua_pushstring(l, ts->name);
return 1;
} else if(stringCompare(key, "texture") == 0) {
lua_pushstring(l, ts->image);
return 1;
} else if(stringCompare(key, "tileWidth") == 0) {
if(stringCompare(key, "tileWidth") == 0) {
lua_pushnumber(l, ts->tileWidth);
return 1;
} else if(stringCompare(key, "tileHeight") == 0) {
@@ -72,7 +66,9 @@ int moduleTilesetToString(lua_State *l) {
tileset_t *ts = (tileset_t *)luaL_checkudata(l, 1, "tileset_mt");
assertNotNull(ts, "Tileset pointer cannot be NULL.");
lua_pushfstring(l, "Tileset: %s", ts->name);
lua_pushfstring(l, "Tileset: %dx%d tile, %d columns, %d rows",
ts->tileWidth, ts->tileHeight, ts->columns, ts->rows
);
return 1;
}

View File

@@ -9,6 +9,7 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
storyflag.c
)
# Story Flag Definitions
dusk_run_python(
dusk_story_defs
tools.story.csv

View File

@@ -8,21 +8,4 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
thread.c
threadmutex.c
)
# Compiler flags.
if(DUSK_TARGET_SYSTEM STREQUAL "linux")
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
THREAD_PTHREAD=1
)
elseif(DUSK_TARGET_SYSTEM STREQUAL "psp")
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
THREAD_PTHREAD=1
)
elseif(DUSK_TARGET_SYSTEM STREQUAL "gamecube" OR DUSK_TARGET_SYSTEM STREQUAL "wii")
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
)
endif()
)

View File

@@ -7,23 +7,4 @@
target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
time.c
)
# Compiler defs
if(DUSK_TARGET_SYSTEM STREQUAL "linux")
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
TIME_SDL2=1
TIME_FIXED=0
)
elseif(DUSK_TARGET_SYSTEM STREQUAL "psp")
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
TIME_FIXED=1
)
elseif(DUSK_TARGET_SYSTEM STREQUAL "gamecube" OR DUSK_TARGET_SYSTEM STREQUAL "wii")
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
TIME_FIXED=1
)
endif()
)

View File

@@ -7,6 +7,7 @@
target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
array.c
endian.c
memory.c
string.c
math.c

67
src/util/endian.c Normal file
View File

@@ -0,0 +1,67 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "util/endian.h"
#include "util/memory.h"
bool_t isHostLittleEndian(void) {
uint32_t value = ENDIAN_MAGIC;
uint8_t *bytePtr = (uint8_t *)&value;
return bytePtr[0] == 0x04;
}
uint32_t endianLittleToHost32(uint32_t value) {
if(isHostLittleEndian()) {
return value;
}
return (
((value & 0x000000FF) << 24) |
((value & 0x0000FF00) << 8) |
((value & 0x00FF0000) >> 8) |
((value & 0xFF000000) >> 24)
);
}
uint16_t endianLittleToHost16(uint16_t value) {
if(isHostLittleEndian()) {
return value;
}
return (uint16_t)(((value & 0x00FF) << 8) |
((value & 0xFF00) >> 8));
}
uint64_t endianLittleToHost64(uint64_t value) {
if(isHostLittleEndian()) {
return value;
}
return (
((value & 0x00000000000000FFULL) << 56) |
((value & 0x000000000000FF00ULL) << 40) |
((value & 0x0000000000FF0000ULL) << 24) |
((value & 0x00000000FF000000ULL) << 8) |
((value & 0x000000FF00000000ULL) >> 8) |
((value & 0x0000FF0000000000ULL) >> 24) |
((value & 0x00FF000000000000ULL) >> 40) |
((value & 0xFF00000000000000ULL) >> 56)
);
}
float_t endianLittleToHostFloat(float_t value) {
if(isHostLittleEndian()) {
return value;
}
uint32_t temp;
float_t result;
memoryCopy(&temp, &value, sizeof(uint32_t));
temp = endianLittleToHost32(temp);
memoryCopy(&result, &temp, sizeof(uint32_t));
return result;
}

48
src/util/endian.h Normal file
View File

@@ -0,0 +1,48 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "dusk.h"
static const uint32_t ENDIAN_MAGIC = 0x01020304;
/**
* Checks if the host system is little-endian.
*
* @return true if the host is little-endian, false otherwise.
*/
bool_t isHostLittleEndian(void);
/**
* Converts a 32-bit integer from little-endian to host byte order.
*
* @param value The little-endian value to convert.
* @return The value in host byte order.
*/
uint32_t endianLittleToHost32(uint32_t value);
/**
* Converts a 16-bit integer from little-endian to host byte order.
* @param value The little-endian value to convert.
* @return The value in host byte order.
*/
uint16_t endianLittleToHost16(uint16_t value);
/**
* Converts a 64-bit integer from little-endian to host byte order.
* @param value The little-endian value to convert.
* @return The value in host byte order.
*/
uint64_t endianLittleToHost64(uint64_t value);
/**
* Converts a float from little-endian to host byte order.
*
* @param value The little-endian value to convert.
* @return The value in host byte order.
*/
float_t endianLittleToHostFloat(float_t value);