Started asset refact

This commit is contained in:
YourWishes committed 2025-11-04 10:15:19 -06:00
1 parent 7d46b98310
commit 7c11a7e5bc
25 files changed
+361 -207

No files matched your search

+14
View File
@@ -0,0 +1,14 @@
# 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)
+139
View File
@@ -0,0 +1,139 @@
/**
* 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;
}
}
+104
View File
@@ -0,0 +1,104 @@
/**
* 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 <zip.h>
#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);
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1 -1
View File
@@ -34,7 +34,7 @@ add_subdirectory(display)
add_subdirectory(engine)
add_subdirectory(error)
add_subdirectory(input)
# add_subdirectory(locale)
add_subdirectory(locale)
add_subdirectory(rpg)
add_subdirectory(scene)
add_subdirectory(thread)
+3 -3
View File
@@ -6,9 +6,9 @@
# Sources
target_sources(${DUSK_TARGET_NAME}
PRIVATE
asset.c
assetmanager.c
# asset.c
# assetmanager.c
)
# Subdirs
add_subdirectory(type)
# add_subdirectory(type)
+28 -116
View File
@@ -6,134 +6,46 @@
*/
#include "asset.h"
#include "assetmanager.h"
#include "util/memory.h"
#include "util/string.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(void) {
memoryZero(&ASSET_MANAGER, sizeof(assetmanager_t));
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.");
// Default system path, intended to be overridden by the paltform
stringCopy(ASSET_MANAGER.systemPath, ".", FILENAME_MAX);
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
// Open zip file
char_t searchPath[FILENAME_MAX];
char_t **path = ASSET_SEARCH_PATHS;
do {
sprintf(
searchPath,
*path,
ASSET_MANAGER.systemPath,
ASSET_ASSET_FILE
);
// 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;
// Try open
ASSET.zip = zip_open(searchPath, ZIP_RDONLY, NULL);
if(ASSET.zip == NULL) continue;
break;// Found!
} while(*(++path) != NULL);
// Did we open the asset?
if(ASSET.zip == NULL) errorThrow("Failed to open asset file.");
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;
erroret_t assetLoad(const char_t *filename, void *output) {
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;
void assetDispose(void) {
if(ASSET_MANAGER.zip != NULL) {
zip_close(ASSET_MANAGER.zip);
ASSET_MANAGER.zip = NULL;
}
}
+28 -78
View File
@@ -7,98 +7,48 @@
#pragma once
#include "error/error.h"
#include "util/reflist.h"
#include <zip.h>
#include "asset/type/assetpaletteimage.h"
#include "asset/type/assetalphaimage.h"
#if ASSET_TYPE == wad
#else
#error "Unsupported ASSET_TYPE"
#endif
#define ASSET_HEADER_SIZE 3
#define ASSET_REFERENCE_COUNT_MAX 8
#define ASSET_FILE "dusk.dsk"
static const char_t *ASSET_SEARCH_PATHS[] = {
"%s/%s",
"%s",
"../%s",
"../../%s",
"data/%s",
"../data/%s",
NULL
};
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;
};
zip_t *zip;
char_t systemPath[FILENAME_MAX];
uint8_t assetCount;
} 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];
static asset_t ASSET;
/**
* 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.
* Initializes the asset system.
*/
errorret_t assetInit(asset_t *asset, const char_t *filename);
errorret_t assetInit(void);
/**
* 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.
* Loads an asset by its filename, the output type depends on the asset type.
*
* @param asset The asset to lock.
* @return A unique reference ID for the lock.
* @param filename The filename of the asset to retrieve.
* @param output The output pointer to store the loaded asset data.
* @return An error code if the asset could not be loaded.
*/
ref_t assetLock(asset_t *asset);
errorret_t assetLoad(const char_t *filename, void *output);
/**
* 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.
* Disposes/cleans up the asset system.
*/
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);
void assetDispose(void);
+2
View File
@@ -9,6 +9,7 @@
#include "util/memory.h"
#include "time/time.h"
#include "input/input.h"
#include "locale/localemanager.h"
#include "display/display.h"
#include "scene/scenemanager.h"
#include "asset/assetmanager.h"
@@ -27,6 +28,7 @@ errorret_t engineInit(void) {
// Init systems. Order is important.
timeInit();
inputInit();
localeManagerInit();
errorChain(assetManagerInit());
errorChain(displayInit());
errorChain(uiInit());
-1
View File
@@ -21,7 +21,6 @@ typedef struct {
errorstate_t *state;
} errorret_t;
static const errorcode_t ERROR_OK = 0;
static const errorcode_t ERROR_NOT_OK = 1;
+1 -1
View File
@@ -6,5 +6,5 @@
# Sources
target_sources(${DUSK_TARGET_NAME}
PRIVATE
language.c
localemanager.c
)
+15
View File
@@ -0,0 +1,15 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "localemanager.h"
#include "util/memory.h"
localemanager_t LOCALE;
void localeManagerInit() {
memoryZero(&LOCALE, sizeof(localemanager_t));
}
+20
View File
@@ -0,0 +1,20 @@
/**
* 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 *nothing;
} localemanager_t;
extern localemanager_t LOCALE;
/**
* Initialize the locale system.
*/
void localeManagerInit();
+3 -3
View File
@@ -6,7 +6,7 @@
*/
#include "engine/engine.h"
#include "asset/assetmanager.h"
#include "asset/asset.h"
#include "util/string.h"
#include "input/input.h"
@@ -23,8 +23,8 @@ int main(int argc, char **argv) {
// Setup system path on asset manager
if(argc > 0) {
stringCopy(
ASSET_MANAGER.systemPath, argv[0],
sizeof(ASSET_MANAGER.systemPath) / sizeof(char_t)
ASSET.systemPath, argv[0],
sizeof(ASSET.systemPath) / sizeof(char_t)
);
}
+1 -1
View File
@@ -7,7 +7,7 @@
#pragma once
#include "dusk.h"
#include "asset/assetmanager.h"
#include "asset/asset.h"
#include "display/tileset/tileset.h"
#include "display/camera.h"
+1 -1
View File
@@ -6,7 +6,7 @@
*/
#pragma once
#include "asset/assetmanager.h"
#include "asset/asset.h"
#include "display/tileset/tileset_minogram.h"
#define UI_TEXT_CHAR_START '!'
+1 -2
View File
@@ -36,7 +36,6 @@ def processPalette(asset):
# PSP requires that the palette size be a power of two, so we will pad the
# palette with transparent colors if needed.
# if args.platform == "psp":
def mathNextPowTwo(x):
return 1 << (x - 1).bit_length()
@@ -53,7 +52,7 @@ def processPalette(asset):
data += f"static const color_t PALETTE_{paletteIndex}_COLORS[PALETTE_{paletteIndex}_COLOR_COUNT] = {{\n"
for pixel in pixels:
data += f" {{ 0x{pixel[0]:02X}, 0x{pixel[1]:02X}, 0x{pixel[2]:02X}, 0x{pixel[3]:02X} }},\n"
data += f"}};\n\n"
data += f"}};\n"
data += f"#pragma pack(pop)\n\n"
data += f"static const palette_t PALETTE_{paletteIndex} = {{\n"
data += f" .colorCount = PALETTE_{paletteIndex}_COLOR_COUNT,\n"