From 6c11096fd25e2f0b02877aae71f90f19743a88a3 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Wed, 27 Aug 2025 19:59:55 -0500 Subject: [PATCH] Palette loading done. --- src/asset/CMakeLists.txt | 2 ++ src/asset/asset.c | 20 ++++++++++++++++++-- src/asset/asset.h | 29 +++++++++++++++++++++++++---- src/asset/assetpalette.c | 18 ++++++++++++++++++ src/asset/assetpalette.h | 7 ++++++- src/asset/assettileset.c | 12 ++++++++++++ src/asset/assettileset.h | 7 ++++++- src/engine/engine.c | 11 ++++++++--- src/scene/test/scenetest.c | 10 +++++----- src/scene/test/scenetest.h | 3 +++ tools/assetstool/processimage.py | 18 +++++++----------- 11 files changed, 110 insertions(+), 27 deletions(-) create mode 100644 src/asset/assetpalette.c create mode 100644 src/asset/assettileset.c diff --git a/src/asset/CMakeLists.txt b/src/asset/CMakeLists.txt index 4236828..b3ca339 100644 --- a/src/asset/CMakeLists.txt +++ b/src/asset/CMakeLists.txt @@ -7,6 +7,8 @@ target_sources(${DUSK_TARGET_NAME} PRIVATE asset.c + assetpalette.c + assettileset.c ) # Compile definitions diff --git a/src/asset/asset.c b/src/asset/asset.c index b8ee780..1a6fe82 100644 --- a/src/asset/asset.c +++ b/src/asset/asset.c @@ -55,7 +55,11 @@ errorret_t assetInit(void) { errorOk(); } -void assetLoad(const char_t *filename) { +void assetLoad( + const char_t *filename, + void (*callback)(void* data), + void *data +) { assertNotNull(filename, "Filename cannot be NULL."); assertTrue(strlen(filename) < ASSET_FILENAME_MAX, "Filename too long."); assertTrue(strlen(filename) > 0, "Filename cannot be empty."); @@ -74,6 +78,8 @@ void assetLoad(const char_t *filename) { assertNotNull(expected->extension, "Unknown asset type."); // Pass off to the thread to begin loading. + ASSET.callback = callback; + ASSET.callbackData = data; ASSET.errorState = ERROR_STATE_INIT; ASSET.state = ASSET_STATE_LOADING; stringCopy(ASSET.filename, filename, ASSET_FILENAME_MAX); @@ -88,6 +94,7 @@ void assetLoad(const char_t *filename) { "Failed to open asset: %s", filename ); + if(ASSET.callback) ASSET.callback(ASSET.callbackData); return; } @@ -101,11 +108,13 @@ void assetLoad(const char_t *filename) { "Failed to stat asset: %s", filename ); + if(ASSET.callback) ASSET.callback(ASSET.callbackData); return; } if(st.size > sizeof(ASSET.data.palette)) { zip_fclose(file); + ASSET.state = ASSET_STATE_ERROR; ASSET.error = errorCreate( &ASSET.errorState, "Asset size mismatch: %s (got %d, expected %d)", @@ -113,11 +122,12 @@ void assetLoad(const char_t *filename) { (int)st.size, (int)sizeof(ASSET.data.palette) ); + if(ASSET.callback) ASSET.callback(ASSET.callbackData); return; } // Read entire file into the asset data. - zip_fread(file, &ASSET.data, st.size); + zip_fread(file, &ASSET.data, st.size); zip_fclose(file); ASSET.state = ASSET_STATE_LOADED; @@ -136,10 +146,16 @@ void assetLoad(const char_t *filename) { expected->header[1], expected->header[2] ); + if(ASSET.callback) ASSET.callback(ASSET.callbackData); return; } + // Parse the asset. + assertNotNull(expected->parser, "Asset parser cannot be NULL."); + expected->parser(); + printf("Loaded asset: %s\n", filename); + if(ASSET.callback) ASSET.callback(ASSET.callbackData); } void assetDispose(void) { diff --git a/src/asset/asset.h b/src/asset/asset.h index 86f3ca6..d6a03a7 100644 --- a/src/asset/asset.h +++ b/src/asset/asset.h @@ -11,6 +11,7 @@ #include "assettileset.h" #include "error/error.h" #include +#include "display/texture/texture.h" #define ASSET_COUNT_MAX 128 #define ASSET_FILENAME_MAX 128 @@ -21,6 +22,7 @@ #error "Unsupported ASSET_TYPE" #endif +#pragma pack(push, 1) typedef struct { char_t header[ASSET_HEADER_LENGTH]; union { @@ -28,6 +30,14 @@ typedef struct { assettileset_t tileset; }; } assetdata_t; +#pragma pack(pop) + +typedef struct { + union { + texture_t palette; + assettileset_t *tileset; + }; +} assetloaded_t; typedef enum { ASSET_STATE_NONE, @@ -46,11 +56,16 @@ typedef struct { assetstate_t state; char_t filename[ASSET_FILENAME_MAX]; assetdata_t data; + assetloaded_t loaded; + + void (*callback)(void* data); + void *callbackData; } asset_t; typedef struct { const char_t *header; const char_t *extension; + void (*parser)(); } assetmap_t; static const char_t ASSET_SEARCH_PATHS[][FILENAME_MAX] = { @@ -63,9 +78,9 @@ static const char_t ASSET_SEARCH_PATHS[][FILENAME_MAX] = { }; static const assetmap_t ASSET_MAP[] = { - { "DPF", "test.palette.dpf" }, - { "DPT", "test.tileset.dpt" }, - { NULL, NULL } + { "DPF", ".dpf", assetParsePalette }, + { "DPT", ".dpt", assetParseTileset }, + { NULL, NULL, NULL } }; #define ASSET_SEARCH_PATHS_COUNT (\ @@ -83,9 +98,15 @@ errorret_t assetInit(void); * Gets an asset by filename, does not load it. * * @param filename The filename of the asset to get. + * @param callback The callback to call when the asset is loaded. + * @param data The data for the callback function. * @return The asset. */ -void assetLoad(const char_t *filename); +void assetLoad( + const char_t *filename, + void (*callback)(void* data), + void *data +); /** * Disposes/cleans up the asset system. diff --git a/src/asset/assetpalette.c b/src/asset/assetpalette.c new file mode 100644 index 0000000..6b47abe --- /dev/null +++ b/src/asset/assetpalette.c @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "asset.h" + +void assetParsePalette() { + textureInit( + &ASSET.loaded.palette, + ASSET.data.palette.colorCount, + 1, + TEXTURE_FORMAT_RGBA, + ASSET.data.palette.colors + ); +} \ No newline at end of file diff --git a/src/asset/assetpalette.h b/src/asset/assetpalette.h index 2fe8e5c..ff2c9fb 100644 --- a/src/asset/assetpalette.h +++ b/src/asset/assetpalette.h @@ -14,4 +14,9 @@ typedef struct { int32_t colorCount; color4b_t colors[ASSET_PALETTE_COLOR_COUNT_MAX]; -} assetpalette_t; \ No newline at end of file +} assetpalette_t; + +/** + * Parse the palette from the loaded raw data. + */ +void assetParsePalette(); \ No newline at end of file diff --git a/src/asset/assettileset.c b/src/asset/assettileset.c new file mode 100644 index 0000000..4955d25 --- /dev/null +++ b/src/asset/assettileset.c @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "asset.h" + +void assetParseTileset() { + ASSET.loaded.tileset = &ASSET.data.tileset; +} \ No newline at end of file diff --git a/src/asset/assettileset.h b/src/asset/assettileset.h index 848d38a..2f957d1 100644 --- a/src/asset/assettileset.h +++ b/src/asset/assettileset.h @@ -16,4 +16,9 @@ typedef struct { int32_t tileCount; int32_t columns; char_t tilesetName[256]; -} assettileset_t; \ No newline at end of file +} assettileset_t; + +/** + * Parse the tileset from the loaded raw data. + */ +void assetParseTileset(); \ No newline at end of file diff --git a/src/engine/engine.c b/src/engine/engine.c index 4b03637..dcba17a 100644 --- a/src/engine/engine.c +++ b/src/engine/engine.c @@ -18,6 +18,12 @@ engine_t ENGINE; +void assetLoadCallback(void *data) { + consolePrint("Asset load callback called!"); + test = ASSET.loaded.palette; + consolePrint("Loaded palette with %d colors", ASSET.data.palette.colorCount); +} + errorret_t engineInit(void) { memoryZero(&ENGINE, sizeof(engine_t)); ENGINE.running = true; @@ -28,9 +34,8 @@ errorret_t engineInit(void) { ecsSystemInit(); errorChain(assetInit()); errorChain(displayInit()); - - // assetLoad("test.palette.dp123123"); - assetLoad("test.palette.dpf"); + + assetLoad("test.palette.dpf", assetLoadCallback, NULL); if(ASSET.state == ASSET_STATE_ERROR) errorChain(ASSET.error); sceneTestAdd(); diff --git a/src/scene/test/scenetest.c b/src/scene/test/scenetest.c index 7ff0eee..1ff59f9 100644 --- a/src/scene/test/scenetest.c +++ b/src/scene/test/scenetest.c @@ -28,11 +28,11 @@ void sceneTestAdd(void) { ); nodeMatrixSet(camera, lookAt); - color4b_t pixels[4] = { - COLOR_RED, COLOR_GREEN, - COLOR_BLUE, COLOR_WHITE - }; - textureInit(&test, 2, 2, TEXTURE_FORMAT_RGBA, pixels); + // color4b_t pixels[4] = { + // COLOR_RED, COLOR_GREEN, + // COLOR_BLUE, COLOR_WHITE + // }; + // textureInit(&test, 2, 2, TEXTURE_FORMAT_RGBA, pixels); // Test cube ecsid_t cube = ecsEntityAdd(); diff --git a/src/scene/test/scenetest.h b/src/scene/test/scenetest.h index 2f9fb91..52b264d 100644 --- a/src/scene/test/scenetest.h +++ b/src/scene/test/scenetest.h @@ -7,5 +7,8 @@ #pragma once #include "ecs/ecssystem.h" +#include "display/texture/texture.h" + +extern texture_t test; void sceneTestAdd(void); \ No newline at end of file diff --git a/tools/assetstool/processimage.py b/tools/assetstool/processimage.py index 5a3fbfa..7771b3c 100644 --- a/tools/assetstool/processimage.py +++ b/tools/assetstool/processimage.py @@ -1,6 +1,7 @@ import os from args import args from PIL import Image +import struct def extractPaletteFromImage(image): # goes through and finds all unique colors in the image @@ -14,19 +15,14 @@ def extractPaletteFromImage(image): return uniqueColors def savePalette(pixels, outputFilePath): - # Pixels is a list of (R, G, B, A) tuples - data = "DPF" # Header for Dusk Palette Format - - # Count of colors (int32_t) colorCount = len(pixels) - data += colorCount.to_bytes(4, byteorder='little').decode('latin1') - - for r, g, b, a in pixels: - data += bytes([r, g, b, a]).decode('latin1') - + buf = bytearray(b"DPF") + buf += struct.pack("