diff --git a/archive/asset/CMakeLists.txt b/archive/asset/CMakeLists.txt deleted file mode 100644 index 709261f..0000000 --- a/archive/asset/CMakeLists.txt +++ /dev/null @@ -1,14 +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 - asset.c - assetmanager.c -) - -# Subdirs -add_subdirectory(type) \ No newline at end of file diff --git a/archive/asset/asset.c b/archive/asset/asset.c deleted file mode 100644 index 217584f..0000000 --- a/archive/asset/asset.c +++ /dev/null @@ -1,139 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "asset.h" -#include "assetmanager.h" -#include "util/memory.h" -#include "assert/assert.h" - -assetdef_t ASSET_DEFINITIONS[ASSET_TYPE_COUNT] = { - [ASSET_TYPE_PALETTE_IMAGE] = { - "DPI", assetPaletteImageLoad, assetPaletteImageDispose - }, - [ASSET_TYPE_ALPHA_IMAGE] = { - "DAI", assetAlphaImageLoad, assetAlphaImageDispose - }, -}; - -errorret_t assetInit(asset_t *asset, const char_t *filename) { - assertNotNull(asset, "Asset cannot be NULL."); - assertNotNull(filename, "Filename cannot be NULL."); - assertTrue(strlen(filename) < FILENAME_MAX, "Filename too long."); - assertTrue(strlen(filename) > 0, "Filename cannot be empty."); - - memoryZero(asset, sizeof(asset_t)); - memoryCopy(asset->filename, filename, strlen(filename) + 1); - - // Initialze the reference list. - refListInit( - &asset->refList, - asset->refListArray, - ASSET_REFERENCE_COUNT_MAX - ); - - // Test the file can be opened. In future I may make the handle stay open for - // a while to see if it increases performance and stops disk thrashing. - asset->file = zip_fopen(ASSET_MANAGER.zip, filename, 0); - if(asset->file == NULL) errorThrow("Failed to open asset file: %s", filename); - zip_fclose(asset->file); - asset->file = NULL; - errorOk(); -} - -ref_t assetLock(asset_t *asset) { - assertNotNull(asset, "Asset cannot be NULL."); - - return refListLock(&asset->refList); -} - -void assetUnlock(asset_t *asset, const ref_t ref) { - assertNotNull(asset, "Asset cannot be NULL."); - - // Just unlock the reference in the reference list. - refListUnlock(&asset->refList, ref); -} - -errorret_t assetLoad(asset_t *asset) { - assertNotNull(asset, "Asset cannot be NULL."); - assertTrue( - asset->state == ASSET_STATE_NOT_LOADED, - "Asset is already loaded or loading." - ); - - // Mark as loading. - asset->state = ASSET_STATE_LOADING; - - // Open the file. - if(asset->file == NULL) { - asset->file = zip_fopen(ASSET_MANAGER.zip, asset->filename, 0); - if(asset->file == NULL) { - asset->state = ASSET_STATE_ERROR; - errorThrow("Failed to open asset file: %s", asset->filename); - } - } - - // Read header. - char_t header[ASSET_HEADER_SIZE + 1]; - memoryZero(header, ASSET_HEADER_SIZE + 1); - zip_int64_t bytesRead = zip_fread(asset->file, header, ASSET_HEADER_SIZE); - if(bytesRead != ASSET_HEADER_SIZE) { - asset->state = ASSET_STATE_ERROR; - zip_fclose(asset->file); - asset->file = NULL; - errorThrow("Failed to read asset header for: %s", asset->filename); - } - - // Check header. - if(strlen(header) != ASSET_HEADER_SIZE) { - asset->state = ASSET_STATE_ERROR; - zip_fclose(asset->file); - asset->file = NULL; - errorThrow("Invalid asset header for: %s", asset->filename); - } - - // Get the asset definition based on the header. - assetdef_t *def; - for(uint_fast8_t i = 0; i < ASSET_TYPE_COUNT; i++) { - if(strcmp(header, ASSET_DEFINITIONS[i].header) == 0) { - def = &ASSET_DEFINITIONS[i]; - asset->type = i; - break; - } - } - assertNotNull(def, "Failed to find asset definition for header."); - - // Load the asset - errorret_t ret = def->load(asset); - if(ret.code != ERROR_OK) { - asset->state = ASSET_STATE_ERROR; - zip_fclose(asset->file); - asset->file = NULL; - errorChain(ret); - } - - // Finished loading. - asset->state = ASSET_STATE_LOADED; - zip_fclose(asset->file); - asset->file = NULL; - errorOk(); -} - -errorret_t assetDispose(asset_t *asset) { - assertNotNull(asset, "Asset cannot be NULL."); - - if(asset->state == ASSET_STATE_LOADED) { - // Dispose of the asset based on its type. - assetdef_t *def = &ASSET_DEFINITIONS[asset->type]; - if(def->dispose) errorChain(def->dispose(asset)); - asset->state = ASSET_STATE_NOT_LOADED; - } - - if(asset->file) { - zip_fclose(asset->file); - asset->file = NULL; - } -} \ No newline at end of file diff --git a/archive/asset/asset.h b/archive/asset/asset.h deleted file mode 100644 index 1e43cef..0000000 --- a/archive/asset/asset.h +++ /dev/null @@ -1,104 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "error/error.h" -#include "util/reflist.h" -#include - -#include "asset/type/assetpaletteimage.h" -#include "asset/type/assetalphaimage.h" - -#define ASSET_HEADER_SIZE 3 -#define ASSET_REFERENCE_COUNT_MAX 8 - -typedef struct { - void (*load)(); -} assetcallback_t; - -typedef enum { - ASSET_STATE_NOT_LOADED, - ASSET_STATE_LOADING, - ASSET_STATE_LOADED, - ASSET_STATE_ERROR, -} assetstate_t; - -typedef enum { - ASSET_TYPE_UNKNOWN, - ASSET_TYPE_PALETTE_IMAGE, - ASSET_TYPE_ALPHA_IMAGE, - - ASSET_TYPE_COUNT -} assettype_t; - -typedef struct asset_s { - char_t filename[FILENAME_MAX]; - ref_t refListArray[ASSET_REFERENCE_COUNT_MAX]; - reflist_t refList; - assetstate_t state; - assettype_t type; - zip_file_t *file; - - union { - assetpaletteimage_t paletteImage; - assetalphaimage_t alphaImage; - }; -} asset_t; - -typedef struct { - const char_t header[ASSET_HEADER_SIZE + 1]; - errorret_t (*load)(asset_t *asset); - errorret_t (*dispose)(asset_t *asset); -} assetdef_t; - -extern assetdef_t ASSET_DEFINITIONS[ASSET_TYPE_COUNT]; - -/** - * Initializes an asset structure. This should be called by the asset manager - * only. - * - * @param asset The asset structure to initialize. - * @param filename The filename of the asset. - * @return An error code. - */ -errorret_t assetInit(asset_t *asset, const char_t *filename); - -/** - * Requests a lock on the given asset. This will increase the reference count - * of the asset, and prevent it from being unloaded until all locks are - * released. - * - * @param asset The asset to lock. - * @return A unique reference ID for the lock. - */ -ref_t assetLock(asset_t *asset); - -/** - * Releases a lock on the given asset. This will decrease the reference count - * of the asset, and allow it to be unloaded if there are no more locks. - * - * @param asset The asset to unlock. - * @param ref The reference ID of the lock to release. - */ -void assetUnlock(asset_t *asset, const ref_t ref); - -/** - * Permission has been granted to load the asset data from disk. This should - * only be called by the asset manager. - * - * @param asset The asset to load. - * @return An error code. - */ -errorret_t assetLoad(asset_t *asset); - -/** - * Disposes of the asset, freeing any allocated memory and closing any open - * file handles. This should only be called by the asset manager. - * - * @param asset The asset to dispose of. - */ -errorret_t assetDispose(asset_t *asset); \ No newline at end of file diff --git a/archive/asset/assetmanager.c b/archive/asset/assetmanager.c deleted file mode 100644 index ff19d6c..0000000 --- a/archive/asset/assetmanager.c +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "assetmanager.h" -#include "util/memory.h" -#include "util/string.h" -#include "assert/assert.h" - -#define ASSET_ASSET_FILE "dusk.dsk" - -assetmanager_t ASSET_MANAGER; - -errorret_t assetManagerInit(void) { - memoryZero(&ASSET_MANAGER, sizeof(assetmanager_t)); - - // Default system path, intended to be overridden by the paltform - stringCopy(ASSET_MANAGER.systemPath, ".", FILENAME_MAX); - - // Open zip file - char_t searchPath[FILENAME_MAX]; - for(int32_t i = 0; i < ASSET_MANAGER_SEARCH_PATHS_COUNT; i++) { - sprintf( - searchPath, - ASSET_MANAGER_SEARCH_PATHS[i], - ASSET_MANAGER.systemPath, - ASSET_ASSET_FILE - ); - - // Try open - ASSET_MANAGER.zip = zip_open(searchPath, ZIP_RDONLY, NULL); - if(ASSET_MANAGER.zip == NULL) continue; - break; - } - - // Did we open the asset? - if(ASSET_MANAGER.zip == NULL) errorThrow("Failed to open asset file."); - - errorOk(); -} - -void assetManagerUpdate(void) { - // Update all assets - asset_t *asset = ASSET_MANAGER.assets; - while(asset < &ASSET_MANAGER.assets[ASSET_MANAGER.assetCount]) { - if(asset->state == ASSET_STATE_LOADING) { - // Check if the asset is loaded - if(asset->file != NULL) { - asset->state = ASSET_STATE_LOADED; - } - } - ++asset; - } -} - -errorret_t assetManagerGetAsset(const char_t *filename, asset_t **outAsset) { - assertNotNull(outAsset, "Output asset pointer cannot be null."); - assertNotNull(filename, "Filename cannot be null."); - assertStrLenMin(filename, 1, "Filename cannot be empty."); - assertStrLenMax(filename, FILENAME_MAX - 1, "Filename is too long."); - - // Is this asset already in memory? - asset_t *asset = ASSET_MANAGER.assets; - while(asset < &ASSET_MANAGER.assets[ASSET_MANAGER.assetCount]) { - if(stringCompare(asset->filename, filename) == 0) { - *outAsset = asset; - errorOk(); - } - ++asset; - } - - // Asset not in memory, can we load it? - if(ASSET_MANAGER.assetCount >= ASSET_MANAGER_ASSET_COUNT_MAX) { - *outAsset = NULL; - errorThrow("Asset limit reached."); - } - - // Pop an asset off the struct - asset = &ASSET_MANAGER.assets[ASSET_MANAGER.assetCount++]; - *outAsset = asset; - errorChain(assetInit(asset, filename)); - errorOk(); -} - -errorret_t assetManagerLoadAsset( - const char_t *filename, - asset_t **outAsset, - ref_t *outRef -) { - assertNotNull(outRef, "Output reference pointer cannot be null."); - errorChain(assetManagerGetAsset(filename, outAsset)); - ref_t ref = assetLock(*outAsset); - errorChain(assetLoad(*outAsset)); - *outRef = ref; - errorOk(); -} - -void assetManagerDispose(void) { - asset_t *asset = ASSET_MANAGER.assets; - while(asset < &ASSET_MANAGER.assets[ASSET_MANAGER.assetCount]) { - assetDispose(asset); - ++asset; - } - - if(ASSET_MANAGER.zip != NULL) { - zip_close(ASSET_MANAGER.zip); - ASSET_MANAGER.zip = NULL; - } -} \ No newline at end of file diff --git a/archive/asset/assetmanager.h b/archive/asset/assetmanager.h deleted file mode 100644 index c0f6b03..0000000 --- a/archive/asset/assetmanager.h +++ /dev/null @@ -1,79 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "asset.h" - -#define ASSET_MANAGER_ASSET_COUNT_MAX 32 - -#if ASSET_TYPE == wad -#else - #error "Unsupported ASSET_TYPE" -#endif - -static const char_t ASSET_MANAGER_SEARCH_PATHS[][FILENAME_MAX] = { - "%s/%s", - "%s", - "../%s", - "../../%s", - "data/%s", - "../data/%s", -}; - -#define ASSET_MANAGER_SEARCH_PATHS_COUNT (\ - sizeof(ASSET_MANAGER_SEARCH_PATHS) / FILENAME_MAX\ -) - -typedef struct { - zip_t *zip; - asset_t assets[ASSET_MANAGER_ASSET_COUNT_MAX]; - char_t systemPath[FILENAME_MAX]; - uint8_t assetCount; -} assetmanager_t; - -extern assetmanager_t ASSET_MANAGER; - -/** - * Initializes the asset system. - */ -errorret_t assetManagerInit(void); - -/** - * Update the asset manager. This should be called once per frame. - */ -void assetManagerUpdate(void); - -/** - * Get an asset by filename. This will return NULL if the asset does not exist. - * This will not lock the asset, you must do that separately. If you do not - * lock the asset there is no guarantee the asset pointer will remain valid. - * - * @param filename The filename of the asset to get. - * @param outAsset The output asset pointer. - * @return An error code. - */ -errorret_t assetManagerGetAsset(const char_t *filename, asset_t **outAsset); - -/** - * Gets, locks and loads an asset. This is all blocking so only use if you - * really need to. - * - * @param filename The filename of the asset to get. - * @param outAsset The output asset pointer. - * @param outRef The output asset reference pointer. - * @return An error code if something goes wrong. - */ -errorret_t assetManagerLoadAsset( - const char_t *filename, - asset_t **outAsset, - ref_t *outRef -); - -/** - * Disposes/cleans up the asset system. - */ -void assetManagerDispose(void); \ No newline at end of file diff --git a/archive/asset/type/assetalphaimage.c b/archive/asset/type/assetalphaimage.c deleted file mode 100644 index 0589837..0000000 --- a/archive/asset/type/assetalphaimage.c +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "asset/asset.h" - -errorret_t assetAlphaImageLoad(asset_t *asset) { - // Read entire alpha image. - assetalphaimageraw_t raw; - zip_int64_t bytesRead = zip_fread(asset->file, &raw, sizeof(raw)); - - if(bytesRead < sizeof(raw.width) + sizeof(raw.height)) { - errorThrow("Failed to read alpha image dimensions."); - } - - if(raw.width <= 0 || raw.width > ASSET_ALPHA_IMAGE_WIDTH_MAX) { - errorThrow("Invalid alpha image width."); - } - - if(raw.height <= 0 || raw.height > ASSET_ALPHA_IMAGE_HEIGHT_MAX) { - errorThrow("Invalid alpha image height."); - } - - zip_int64_t expecting = ( - sizeof(raw.width) + - sizeof(raw.height) + - (raw.width * raw.height * sizeof(uint8_t)) - ); - if(bytesRead != expecting) { - errorThrow("Incorrect alpha filesize."); - } - - textureInit( - &asset->alphaImage.texture, - (int32_t)raw.width, - (int32_t)raw.height, - TEXTURE_FORMAT_ALPHA, - (texturedata_t){ - .alpha = { - .data = raw.pixels - } - } - ); - - errorOk(); -} - -errorret_t assetAlphaImageDispose(asset_t *asset) { - textureDispose(&asset->alphaImage.texture); - errorOk(); -} \ No newline at end of file diff --git a/archive/asset/type/assetpaletteimage.c b/archive/asset/type/assetpaletteimage.c deleted file mode 100644 index 588b9c1..0000000 --- a/archive/asset/type/assetpaletteimage.c +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "asset/asset.h" -#include "display/palette/palettelist.h" - -errorret_t assetPaletteImageLoad(asset_t *asset) { - // Read entire palettized image. - assetpaletteimageraw_t raw; - zip_int64_t bytesRead = zip_fread(asset->file, &raw, sizeof(raw)); - - if(bytesRead < sizeof(raw.width) + sizeof(raw.height)) { - errorThrow("Failed to read palette image dimensions."); - } - - if(raw.width <= 0 || raw.width > ASSET_PALETTE_IMAGE_WIDTH_MAX) { - errorThrow("Invalid palette image width."); - } - - if(raw.height <= 0 || raw.height > ASSET_PALETTE_IMAGE_HEIGHT_MAX) { - errorThrow("Invalid palette image height."); - } - - if(raw.paletteIndex >= PALETTE_LIST_COUNT) { - errorThrow("Invalid palette index."); - } - - zip_int64_t expecting = ( - sizeof(raw.width) + - sizeof(raw.height) + - sizeof(raw.paletteIndex) + - (raw.width * raw.height * sizeof(uint8_t)) - ); - if(bytesRead != expecting) { - errorThrow("Incorrect palette filesize."); - } - - textureInit( - &asset->paletteImage.texture, - (int32_t)raw.width, - (int32_t)raw.height, - TEXTURE_FORMAT_PALETTE, - (texturedata_t){ - .palette = { - .palette = raw.paletteIndex, - .data = raw.palette - } - } - ); - - errorOk(); -} - -errorret_t assetPaletteImageDispose(asset_t *asset) { - textureDispose(&asset->paletteImage.texture); - errorOk(); -} \ No newline at end of file diff --git a/archive/language.c b/archive/language.c deleted file mode 100644 index 2c70fd1..0000000 --- a/archive/language.c +++ /dev/null @@ -1,145 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "language.h" -#include "assert/assert.h" - -language_t LANGUAGE; - -void languageInit(void) { - LANGUAGE.current = LANGUAGE_EN; -} - -const char_t * languageGet(const char_t *key) { - assertNotNull(key, "Key cannot be NULL"); - assertTrue(LANGUAGE.current < LANGUAGE_COUNT, "Invalid language index"); - - int16_t keyIndex = -1; - for(uint16_t i = 0; i < LANGUAGE_COUNTS[LANGUAGE.current]; i++) { - if(strcmp(LANGUAGE_KEYS[LANGUAGE.current][i], key) != 0) continue; - keyIndex = i; - break; - } - assertTrue(keyIndex != -1, "Key not found in language"); - return LANGUAGE_VALUES[LANGUAGE.current][keyIndex]; -} - -uint16_t langaugeGetLength(const char_t *key) { - assertNotNull(key, "Key cannot be NULL"); - assertTrue(LANGUAGE.current < LANGUAGE_COUNT, "Invalid language index"); - - int16_t keyIndex = -1; - for(uint16_t i = 0; i < LANGUAGE_COUNTS[LANGUAGE.current]; i++) { - if(strcmp(LANGUAGE_KEYS[LANGUAGE.current][i], key) != 0) continue; - keyIndex = i; - break; - } - assertTrue(keyIndex != -1, "Key not found in language"); - return strlen(LANGUAGE_VALUES[LANGUAGE.current][keyIndex]); -} - -uint16_t languageFormat( - const char_t *key, - char_t *buffer, - uint16_t buffSize, - const char_t **keys, - const char_t **values, - const uint16_t valueCount -) { - if(buffer != NULL) { - assertTrue(buffSize > 0, "Buffer size must be greater than 0"); - } else { - assertTrue(buffSize == 0, "Buffer size must be 0 if buffer is NULL"); - } - - assertNotNull(key, "Key cannot be NULL"); - assertNotNull(keys, "Keys cannot be NULL"); - assertNotNull(values, "Values cannot be NULL"); - - const char_t *val = languageGet(key); - assertNotNull(val, "Value for key cannot be NULL"); - - char_t c; - uint16_t i = 0; - uint16_t j = 0; - uint8_t k = 0; - bool_t inBraces = false; - char_t braceBuffer[64] = {0}; - - #define bufferChar(c) ( \ - (buffer ? (buffer[j++] = c) : (j++)), \ - assertTrue(buffer ? j < buffSize : true, "Buffer overflow") \ - ) - - while((c = val[i++]) != '\0') { - if(c == '{' && val[i] == '{') { - goto startBraces; - } else if(c == '}' && val[i] == '}') { - goto endBraces; - } else if(inBraces) { - goto braceBuffering; - } else { - goto character; - } - - character: { - bufferChar(c); - continue; - } - - braceBuffering: { - assertFalse(val[i] == '\0', "Unexpected end of string."); - braceBuffer[k++] = c; - assertTrue(k < sizeof(braceBuffer), "Brace buffer overflow"); - if(val[i] == ' ') i++; - continue; - } - - startBraces: { - assertFalse(inBraces, "Nested braces are not allowed"); - - inBraces = true; - i++; - k = 0; - assertFalse(val[i] == '\0', "Unexpected end of string."); - if(val[i] == ' ') i++; - continue; - } - - endBraces: { - assertTrue(inBraces, "Unmatched closing brace found"); - - inBraces = false; - i++; - braceBuffer[k] = '\0'; - - uint16_t l; - for(l = 0; l < valueCount; l++) { - if(strcmp(braceBuffer, keys[l]) != 0) { - continue; - } - const char_t *replacement = values[l]; - - uint16_t r = 0; - while((c = replacement[r++]) != '\0') { - bufferChar(c); - } - break; - } - assertTrue(l < valueCount, "No string replacement found!"); - continue; - } - } - - if(buffer){ - assertTrue(j < buffSize, "Buffer overflow"); - buffer[j] = '\0'; - } - - assertFalse(inBraces, "Unmatched opening brace found"); - return j; -} \ No newline at end of file diff --git a/archive/language.h b/archive/language.h deleted file mode 100644 index d80d925..0000000 --- a/archive/language.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "locale/language/languages.h" - -typedef struct { - uint8_t current; -} language_t; - -extern language_t LANGUAGE; - -/** - * Initializes the language system. - * - * This function sets up the language system, loading the default language - * and preparing any necessary resources for language handling. - */ -void languageInit(void); - -/** - * Gets a language string by its key. - * - * @param key The key for the language string. - * @return The language string associated with the key. - */ -const char_t * languageGet(const char_t *key); - -/** - * Gets the length of a language string by its key. - * - * @param key The key for the language string. - * @return The length of the language string associated with the key. - */ -uint16_t langaugeGetLength(const char_t *key); - -/** - * Formats a language string with given keys and values. - * - * This function replaces placeholders in the language string with the provided - * values based on the keys. - * - * If buffer is NULL, the function will instead calculate the length of the - * formatted string. - * - * @param key The key for the language string to format. - * @param buffer The buffer to store the formatted string. - * @param buffSize The size of the buffer. - * @param keys An array of keys to replace in the language string. - * @param values An array of values corresponding to the keys. - * @param valueCount The number of key-value pairs. - * @return The number of characters written to the buffer. - */ -uint16_t languageFormat( - const char_t *key, - char_t *buffer, - uint16_t buffSize, - const char_t **keys, - const char_t **values, - const uint16_t valueCount -); \ No newline at end of file diff --git a/src/asset/CMakeLists.txt b/src/asset/CMakeLists.txt index cb7cd1f..399ef34 100644 --- a/src/asset/CMakeLists.txt +++ b/src/asset/CMakeLists.txt @@ -6,9 +6,8 @@ # Sources target_sources(${DUSK_TARGET_NAME} PRIVATE - # asset.c - # assetmanager.c + asset.c ) # Subdirs -# add_subdirectory(type) \ No newline at end of file +add_subdirectory(type) \ No newline at end of file diff --git a/src/asset/asset.c b/src/asset/asset.c index 5fae8ea..86ddc68 100644 --- a/src/asset/asset.c +++ b/src/asset/asset.c @@ -9,22 +9,23 @@ #include "util/memory.h" #include "util/string.h" #include "assert/assert.h" +#include "asset/assettype.h" errorret_t assetInit(void) { - memoryZero(&ASSET_MANAGER, sizeof(assetmanager_t)); - - // Default system path, intended to be overridden by the paltform - stringCopy(ASSET_MANAGER.systemPath, ".", FILENAME_MAX); + memoryZero(&ASSET, sizeof(asset_t)); + + // Default system path, intended to be overridden by the platform + stringCopy(ASSET.systemPath, ".", FILENAME_MAX); // Open zip file char_t searchPath[FILENAME_MAX]; - char_t **path = ASSET_SEARCH_PATHS; + const char_t **path = ASSET_SEARCH_PATHS; do { sprintf( searchPath, *path, - ASSET_MANAGER.systemPath, - ASSET_ASSET_FILE + ASSET.systemPath, + ASSET_FILE ); // Try open @@ -39,13 +40,61 @@ errorret_t assetInit(void) { errorOk(); } -erroret_t assetLoad(const char_t *filename, void *output) { +errorret_t assetLoad(const char_t *filename, void *output) { + assertStrLenMax(filename, FILENAME_MAX, "Filename too long."); + assertNotNull(output, "Output pointer cannot be NULL."); + + // Try to open the file + zip_file_t *file = zip_fopen(ASSET.zip, filename, 0); + if(file == NULL) { + errorThrow("Failed to open asset file: %s", filename); + } + + // Read the header. + assetheader_t header; + memoryZero(&header, sizeof(assetheader_t)); + zip_int64_t bytesRead = zip_fread(file, &header, sizeof(assetheader_t)); + if(bytesRead != sizeof(assetheader_t)) { + zip_fclose(file); + errorThrow("Failed to read asset header for: %s", filename); + } + + // Find the asset type based on the header + const assettypedef_t *def = NULL; + for(uint_fast8_t i = 0; i < ASSET_TYPE_COUNT; i++) { + if(ASSET_TYPE_DEFINITIONS[i].header == NULL) continue; + if(strcmp(header.header, ASSET_TYPE_DEFINITIONS[i].header) != 0) continue; + def = &ASSET_TYPE_DEFINITIONS[i]; + break; + } + if(def == NULL) { + zip_fclose(file); + errorThrow("Unknown asset type for file: %s", filename); + } + + // We found the asset type, now load the asset data + assertNotNull(def->load, "Asset load function cannot be NULL."); + void *data = memoryAllocate(def->dataSize); + bytesRead = zip_fread(file, data, def->dataSize); + if(bytesRead == 0 || bytesRead > def->dataSize) { + memoryFree(data); + zip_fclose(file); + errorThrow("Failed to read asset data for file: %s", filename); + } + + // Close the file now we have the data + zip_fclose(file); + + // Pass to the asset type loader + errorret_t ret = def->load(data, output); + memoryFree(data); + errorChain(ret); errorOk(); } void assetDispose(void) { - if(ASSET_MANAGER.zip != NULL) { - zip_close(ASSET_MANAGER.zip); - ASSET_MANAGER.zip = NULL; + if(ASSET.zip != NULL) { + zip_close(ASSET.zip); + ASSET.zip = NULL; } } \ No newline at end of file diff --git a/src/asset/asset.h b/src/asset/asset.h index 8f5be42..1469af2 100644 --- a/src/asset/asset.h +++ b/src/asset/asset.h @@ -26,6 +26,12 @@ static const char_t *ASSET_SEARCH_PATHS[] = { NULL }; +#pragma pack(push, 1) +typedef struct { + char_t header[3]; +} assetheader_t; +#pragma pack(pop) + typedef struct { zip_t *zip; char_t systemPath[FILENAME_MAX]; diff --git a/src/asset/assettype.h b/src/asset/assettype.h new file mode 100644 index 0000000..dfccc10 --- /dev/null +++ b/src/asset/assettype.h @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "type/assetpaletteimage.h" +#include "type/assetalphaimage.h" + +typedef enum { + ASSET_TYPE_NULL, + ASSET_TYPE_PALETTE_IMAGE, + ASSET_TYPE_ALPHA_IMAGE, + ASSET_TYPE_COUNT, +} assettype_t; + +typedef struct { + const char_t *header; + const size_t dataSize; + errorret_t (*load)(void *data, void *output); +} assettypedef_t; + +static const assettypedef_t ASSET_TYPE_DEFINITIONS[ASSET_TYPE_COUNT] = { + [ASSET_TYPE_NULL] = { + 0 + }, + + [ASSET_TYPE_PALETTE_IMAGE] = { + .header = "DPI", + .dataSize = sizeof(assetpaletteimage_t), + .load = assetPaletteImageLoad + }, + + [ASSET_TYPE_ALPHA_IMAGE] = { + .header = "DAI", + .dataSize = sizeof(assetalphaimage_t), + .load = assetAlphaImageLoad + }, +}; \ No newline at end of file diff --git a/archive/asset/type/CMakeLists.txt b/src/asset/type/CMakeLists.txt similarity index 100% rename from archive/asset/type/CMakeLists.txt rename to src/asset/type/CMakeLists.txt diff --git a/src/asset/type/assetalphaimage.c b/src/asset/type/assetalphaimage.c new file mode 100644 index 0000000..475a354 --- /dev/null +++ b/src/asset/type/assetalphaimage.c @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "assetalphaimage.h" +#include "assert/assert.h" +#include "display/texture.h" + +errorret_t assetAlphaImageLoad(void *data, void *output) { + assertNotNull(data, "Data pointer cannot be NULL."); + assertNotNull(output, "Output pointer cannot be NULL."); + + assetalphaimage_t *dataPtr = (assetalphaimage_t *)data; + texture_t *outputPtr = (texture_t *)output; + + textureInit( + outputPtr, + dataPtr->width, + dataPtr->height, + TEXTURE_FORMAT_ALPHA, + (texturedata_t){ .alpha = { .data = dataPtr->pixels } } + ); + + errorOk(); +} \ No newline at end of file diff --git a/archive/asset/type/assetalphaimage.h b/src/asset/type/assetalphaimage.h similarity index 66% rename from archive/asset/type/assetalphaimage.h rename to src/asset/type/assetalphaimage.h index f3af5ba..c197c82 100644 --- a/archive/asset/type/assetalphaimage.h +++ b/src/asset/type/assetalphaimage.h @@ -7,7 +7,6 @@ #pragma once #include "error/error.h" -#include "display/texture.h" #define ASSET_ALPHA_IMAGE_WIDTH_MAX 256 #define ASSET_ALPHA_IMAGE_HEIGHT_MAX 256 @@ -15,19 +14,13 @@ ASSET_ALPHA_IMAGE_WIDTH_MAX * ASSET_ALPHA_IMAGE_HEIGHT_MAX \ ) -typedef struct asset_s asset_t; - #pragma pack(push, 1) typedef struct { uint32_t width; uint32_t height; uint8_t pixels[ASSET_ALPHA_IMAGE_SIZE_MAX]; -} assetalphaimageraw_t; -#pragma pack(pop) - -typedef struct { - texture_t texture; } assetalphaimage_t; +#pragma pack(pop) /** * Loads an alpha image asset from the given asset structure. The asset must @@ -36,12 +29,4 @@ typedef struct { * @param asset The asset to load the alpha image from. * @return An error code. */ -errorret_t assetAlphaImageLoad(asset_t *asset); - -/** - * Disposes of an alpha image asset, freeing any allocated resources. - * - * @param asset The asset to dispose of. - * @return An error code. - */ -errorret_t assetAlphaImageDispose(asset_t *asset); \ No newline at end of file +errorret_t assetAlphaImageLoad(void *data, void *output); \ No newline at end of file diff --git a/src/asset/type/assetpaletteimage.c b/src/asset/type/assetpaletteimage.c new file mode 100644 index 0000000..6ff0eba --- /dev/null +++ b/src/asset/type/assetpaletteimage.c @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "assetpaletteimage.h" +#include "assert/assert.h" +#include "display/texture.h" + +errorret_t assetPaletteImageLoad(void *data, void *output) { + assertNotNull(data, "Data pointer cannot be NULL."); + assertNotNull(output, "Output pointer cannot be NULL."); + + assetpaletteimage_t *assetData = (assetpaletteimage_t *)data; + texture_t *texture = (texture_t *)output; + + textureInit( + texture, + assetData->width, + assetData->height, + TEXTURE_FORMAT_PALETTE, + (texturedata_t){ + .palette = { + .palette = assetData->paletteIndex, + .data = assetData->palette + } + } + ); + + errorOk(); +} \ No newline at end of file diff --git a/archive/asset/type/assetpaletteimage.h b/src/asset/type/assetpaletteimage.h similarity index 50% rename from archive/asset/type/assetpaletteimage.h rename to src/asset/type/assetpaletteimage.h index ebb754e..2254d07 100644 --- a/archive/asset/type/assetpaletteimage.h +++ b/src/asset/type/assetpaletteimage.h @@ -7,7 +7,6 @@ #pragma once #include "error/error.h" -#include "display/texture.h" #define ASSET_PALETTE_IMAGE_WIDTH_MAX 128 #define ASSET_PALETTE_IMAGE_HEIGHT_MAX 128 @@ -15,34 +14,21 @@ ASSET_PALETTE_IMAGE_WIDTH_MAX * ASSET_PALETTE_IMAGE_HEIGHT_MAX \ ) -typedef struct asset_s asset_t; - #pragma pack(push, 1) typedef struct { uint32_t width; uint32_t height; uint8_t paletteIndex; uint8_t palette[ASSET_PALETTE_IMAGE_SIZE_MAX]; -} assetpaletteimageraw_t; +} assetpaletteimage_t; #pragma pack(pop) -typedef struct { - texture_t texture; -} assetpaletteimage_t; - /** - * Loads a palette image asset from the given asset structure. The asset must - * be of type ASSET_TYPE_PALETTE_IMAGE and must be loaded. - * - * @param asset The asset to load the palette image from. + * Loads a palette image asset from the given data pointer into the output + * texture. + * + * @param data Pointer to the raw assetpaletteimage_t data. + * @param output Pointer to the texture_t to load the image into. * @return An error code. */ -errorret_t assetPaletteImageLoad(asset_t *asset); - -/** - * Disposes of a palette image asset, freeing any allocated resources. - * - * @param asset The asset to dispose of. - * @return An error code. - */ -errorret_t assetPaletteImageDispose(asset_t *asset); \ No newline at end of file +errorret_t assetPaletteImageLoad(void *data, void *output); \ No newline at end of file diff --git a/src/engine/engine.c b/src/engine/engine.c index a226644..febfa35 100644 --- a/src/engine/engine.c +++ b/src/engine/engine.c @@ -12,15 +12,12 @@ #include "locale/localemanager.h" #include "display/display.h" #include "scene/scenemanager.h" -#include "asset/assetmanager.h" +#include "asset/asset.h" #include "ui/ui.h" #include "rpg/rpg.h" engine_t ENGINE; -asset_t *outAsset; -ref_t outRef; - errorret_t engineInit(void) { memoryZero(&ENGINE, sizeof(engine_t)); ENGINE.running = true; @@ -29,7 +26,7 @@ errorret_t engineInit(void) { timeInit(); inputInit(); localeManagerInit(); - errorChain(assetManagerInit()); + errorChain(assetInit()); errorChain(displayInit()); errorChain(uiInit()); errorChain(rpgInit()); @@ -41,7 +38,6 @@ errorret_t engineInit(void) { errorret_t engineUpdate(void) { timeUpdate(); inputUpdate(); - assetManagerUpdate(); rpgUpdate(); uiUpdate(); @@ -62,6 +58,6 @@ errorret_t engineDispose(void) { rpgDispose(); uiDispose(); errorChain(displayDispose()); - assetManagerDispose(); + assetDispose(); errorOk(); } \ No newline at end of file diff --git a/src/ui/ui.c b/src/ui/ui.c index 42ff076..6ef2c6e 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -6,6 +6,7 @@ */ #include "ui.h" +#include "assert/assert.h" #include "ui/uifps.h" #include "util/memory.h" #include "display/tileset/tileset_minogram.h" @@ -36,26 +37,29 @@ void uiRender(void) { cameraPushMatrix(&UI.camera); // Render UI elements here - if(UI.font) { - uiFPSRender(UI.fontTileset, &UI.font->alphaImage.texture); + if(UI.fontTexture.width > 0) { + uiFPSRender(UI.fontTileset, &UI.fontTexture); } cameraPopMatrix(); } errorret_t uiSetFont(const tileset_t *fontTileset) { - if(UI.font) { - assetUnlock(UI.font, UI.fontRef); - UI.font = NULL; + if(UI.fontTexture.width > 0) { + textureDispose(&UI.fontTexture); + UI.fontTexture.width = -1; } + + assertNotNull(fontTileset, "Font tileset cannot be NULL."); UI.fontTileset = fontTileset; - assetManagerLoadAsset(fontTileset->image, &UI.font, &UI.fontRef); + errorChain(assetLoad(UI.fontTileset->image, &UI.fontTexture)); + errorOk(); } void uiDispose(void) { - if(UI.font) { - assetUnlock(UI.font, UI.fontRef); - UI.font = NULL; + if(UI.fontTexture.width > 0) { + textureDispose(&UI.fontTexture); + UI.fontTexture.width = -1; } } \ No newline at end of file diff --git a/src/ui/ui.h b/src/ui/ui.h index ccc55de..93a364d 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -6,16 +6,14 @@ */ #pragma once -#include "dusk.h" #include "asset/asset.h" +#include "display/texture.h" #include "display/tileset/tileset.h" #include "display/camera.h" typedef struct { camera_t camera; - - ref_t fontRef; - asset_t *font; + texture_t fontTexture; const tileset_t *fontTileset; } ui_t; diff --git a/src/ui/uitext.c b/src/ui/uitext.c index de062a4..2b43a2b 100644 --- a/src/ui/uitext.c +++ b/src/ui/uitext.c @@ -6,7 +6,6 @@ // */ #include "uitext.h" -#include "asset/assetmanager.h" #include "assert/assert.h" #include "util/memory.h" #include "display/spritebatch.h" diff --git a/src/ui/uitext.h b/src/ui/uitext.h index 70a25e6..210f051 100644 --- a/src/ui/uitext.h +++ b/src/ui/uitext.h @@ -7,6 +7,7 @@ #pragma once #include "asset/asset.h" +#include "display/texture.h" #include "display/tileset/tileset_minogram.h" #define UI_TEXT_CHAR_START '!' diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 3782c3a..75b1187 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -9,5 +9,4 @@ target_sources(${DUSK_TARGET_NAME} memory.c string.c math.c - reflist.c ) \ No newline at end of file diff --git a/src/util/reflist.c b/src/util/reflist.c deleted file mode 100644 index 95ba58a..0000000 --- a/src/util/reflist.c +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "reflist.h" -#include "util/memory.h" -#include "assert/assert.h" - -void refListInit( - reflist_t *list, - ref_t *array, - const uint_fast16_t max -) { - assertNotNull(list, "Reference list cannot be NULL"); - assertNotNull(array, "Reference array cannot be NULL"); - assertTrue(max > 0, "Reference list max must be greater than 0"); - assertTrue(max <= UINT16_MAX, "Reference list too large"); - - memoryZero(list, sizeof(reflist_t)); - memoryZero(array, sizeof(ref_t) * max); - - list->array = array; - list->max = max; -} - -ref_t refListLock(reflist_t *list) { - assertFalse(refListIsFull(list), "Reference list is full"); - - ref_t ref = list->refNext++; - assertTrue(ref >= 0, "Reference ID overflow"); - assertTrue(ref < UINT16_MAX, "Reference ID too large."); - - bool_t empty = list->onNotEmpty && refListIsEmpty(list); - - list->array[list->count++] = ref; - - if(empty) list->onNotEmpty(list); - if(list->onAdd) list->onAdd(list, ref); - if(list->onFull && refListIsFull(list)) list->onFull(list); - - return ref; -} - -void refListUnlock(reflist_t *list, const ref_t ref) { - assertFalse(refListIsEmpty(list), "Reference list is empty"); - - ref_t *slot = list->array; - ref_t *end = list->array + list->count; - - do { - if(*slot == ref) break; - ++slot; - } while(slot < end); - - assertTrue(slot < end, "Reference not found in list"); - - // Can't move if list only has one ref - if(list->count > 1) { - memoryMove(slot, slot + 1, (end - slot - 1) * sizeof(ref_t)); - } - - list->count--; - if(list->onRemove) list->onRemove(list, ref); - if(list->onEmpty && refListIsEmpty(list)) list->onEmpty(list); -} - -bool_t refListIsFull(const reflist_t *list) { - assertNotNull(list, "Reference list cannot be NULL"); - assertNotNull(list->array, "Reference list array cannot be NULL"); - assertTrue(list->max > 0, "Reference list max must be greater than 0"); - assertTrue(list->max <= UINT16_MAX, "Reference list too large"); - - return (list->count >= list->max); -} - -bool_t refListIsEmpty(const reflist_t *list) { - assertNotNull(list, "Reference list cannot be NULL"); - assertNotNull(list->array, "Reference list array cannot be NULL"); - assertTrue(list->max > 0, "Reference list max must be greater than 0"); - assertTrue(list->max <= UINT16_MAX, "Reference list too large"); - - return (list->count == 0); -} \ No newline at end of file diff --git a/src/util/reflist.h b/src/util/reflist.h deleted file mode 100644 index 824e21b..0000000 --- a/src/util/reflist.h +++ /dev/null @@ -1,77 +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 uint_fast16_t ref_t; - -typedef struct reflist_s reflist_t; - -typedef struct reflist_s { - ref_t *array; - uint_fast16_t max; - uint_fast16_t count; - ref_t refNext; - - void *user; - - void (*onNotEmpty)(reflist_t *list); - void (*onFull)(reflist_t *list); - void (*onAdd)(reflist_t *list, const ref_t ref); - void (*onRemove)(reflist_t *list, const ref_t ref); - void (*onEmpty)(reflist_t *list); -} reflist_t; - -/** - * Initialize a reference list. Reference lists just hold a list of references - * that are "holding on to" a given object/resource. - * - * @param list The reference list to initialize. - * @param array The array to use as backing storage for the list. - * @param max The maximum number of references the list can hold. - */ -void refListInit( - reflist_t *list, - ref_t *array, - const uint_fast16_t max -); - - -/** - * Lock a reference in the list. This will return a new reference ID that can be - * used to access the locked reference. - * - * @param list The reference list to lock a reference in. - * @return The locked reference ID, or 0 if the list is full. - */ -ref_t refListLock(reflist_t *list); - -/** - * Unlock a reference in the list. This will free up the reference ID for - * reuse. - * - * @param list The reference list to unlock a reference in. - * @param ref The reference ID to unlock. - */ -void refListUnlock(reflist_t *list, const ref_t ref); - -/** - * Checks if the reference list is full. - * - * @param list The reference list to check. - * @return true if the list is full, false otherwise. - */ -bool_t refListIsFull(const reflist_t *list); - -/** - * Checks if the reference list is empty. - * - * @param list The reference list to check. - * @return true if the list is empty, false otherwise. - */ -bool_t refListIsEmpty(const reflist_t *list); \ No newline at end of file