diff --git a/src/asset/asset.c b/src/asset/asset.c index 86ddc68..38d63a0 100644 --- a/src/asset/asset.c +++ b/src/asset/asset.c @@ -62,9 +62,10 @@ errorret_t assetLoad(const char_t *filename, void *output) { // 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]; + const assettypedef_t *cmp = &ASSET_TYPE_DEFINITIONS[i]; + if(cmp->header == NULL) continue; + if(strcmp(header.header, cmp->header) != 0) continue; + def = cmp; break; } if(def == NULL) { @@ -73,22 +74,33 @@ errorret_t assetLoad(const char_t *filename, void *output) { } // 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); + switch(def->loadStrategy) { + case ASSET_LOAD_STRAT_ENTIRE: + assertNotNull(def->entire, "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->entire(data, output); + memoryFree(data); + errorChain(ret); + break; + + case ASSET_LOAD_STRAT_TEST: + assertUnreachable("Asset load strategy not implemented yet."); + + default: + assertUnreachable("Unknown asset load strategy."); } - // 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(); } diff --git a/src/asset/assettype.h b/src/asset/assettype.h index dd9026d..4c1b27c 100644 --- a/src/asset/assettype.h +++ b/src/asset/assettype.h @@ -13,18 +13,25 @@ typedef enum { ASSET_TYPE_NULL, ASSET_TYPE_PALETTE_IMAGE, ASSET_TYPE_ALPHA_IMAGE, + ASSET_TYPE_LANGUAGE, ASSET_TYPE_COUNT, } assettype_t; typedef enum { ASSET_LOAD_STRAT_ENTIRE, + ASSET_LOAD_STRAT_TEST } assetloadstrat_t; typedef struct { const char_t *header; const size_t dataSize; const assetloadstrat_t loadStrategy; - errorret_t (*load)(void *data, void *output); + union { + errorret_t (*entire)(void *data, void *output); + struct { + void *test; + } test; + }; } assettypedef_t; static const assettypedef_t ASSET_TYPE_DEFINITIONS[ASSET_TYPE_COUNT] = { @@ -36,13 +43,22 @@ static const assettypedef_t ASSET_TYPE_DEFINITIONS[ASSET_TYPE_COUNT] = { .header = "DPI", .loadStrategy = ASSET_LOAD_STRAT_ENTIRE, .dataSize = sizeof(assetpaletteimage_t), - .load = assetPaletteImageLoad + .entire = assetPaletteImageLoad }, [ASSET_TYPE_ALPHA_IMAGE] = { .header = "DAI", .loadStrategy = ASSET_LOAD_STRAT_ENTIRE, .dataSize = sizeof(assetalphaimage_t), - .load = assetAlphaImageLoad + .entire = assetAlphaImageLoad }, + + [ASSET_TYPE_LANGUAGE] = { + .header = "DLF", + .loadStrategy = ASSET_LOAD_STRAT_TEST, + .dataSize = 0, // Variable size + .test = { + .test = NULL + } + } }; \ No newline at end of file diff --git a/src/asset/type/assetlanguage.c b/src/asset/type/assetlanguage.c new file mode 100644 index 0000000..e692be1 --- /dev/null +++ b/src/asset/type/assetlanguage.c @@ -0,0 +1,8 @@ +/** + * Copyright (c) 2025 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "assetlanguage.h" \ No newline at end of file diff --git a/src/asset/type/assetlanguage.h b/src/asset/type/assetlanguage.h index 63bc9e3..451eb7b 100644 --- a/src/asset/type/assetlanguage.h +++ b/src/asset/type/assetlanguage.h @@ -8,6 +8,12 @@ #pragma once #include "locale/language/keys.h" +#define ASSET_LANG_CHUNK_CHAR_COUNT 6 * 1024 // 6 KB per chunk + +#pragma pack(push, 1) +typedef char assetlanguagechunk_t[ASSET_LANG_CHUNK_CHAR_COUNT]; +#pragma pack(pop) + #pragma pack(push, 1) typedef struct { uint32_t chunk; diff --git a/src/engine/engine.c b/src/engine/engine.c index febfa35..c90ddf6 100644 --- a/src/engine/engine.c +++ b/src/engine/engine.c @@ -25,8 +25,8 @@ errorret_t engineInit(void) { // Init systems. Order is important. timeInit(); inputInit(); - localeManagerInit(); errorChain(assetInit()); + errorChain(localeManagerInit()); errorChain(displayInit()); errorChain(uiInit()); errorChain(rpgInit()); diff --git a/src/locale/language/languagechunk.h b/src/locale/language/languagechunk.h deleted file mode 100644 index 102ea33..0000000 --- a/src/locale/language/languagechunk.h +++ /dev/null @@ -1,15 +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" - -#define LANG_CHUNK_CHAR_COUNT 6 * 1024 // 6 KB per chunk - -#pragma pack(push, 1) -typedef char languagechunkdata_t[LANG_CHUNK_CHAR_COUNT]; -#pragma pack(pop) \ No newline at end of file diff --git a/src/locale/localemanager.c b/src/locale/localemanager.c index 45a78d8..9a9fa85 100644 --- a/src/locale/localemanager.c +++ b/src/locale/localemanager.c @@ -7,9 +7,13 @@ #include "localemanager.h" #include "util/memory.h" +#include "asset/asset.h" localemanager_t LOCALE; -void localeManagerInit() { +errorret_t localeManagerInit() { memoryZero(&LOCALE, sizeof(localemanager_t)); + + errorChain(assetLoad("language/us.dlf", &LOCALE)); + errorOk(); } \ No newline at end of file diff --git a/src/locale/localemanager.h b/src/locale/localemanager.h index 557fc90..4969ec1 100644 --- a/src/locale/localemanager.h +++ b/src/locale/localemanager.h @@ -6,7 +6,7 @@ */ #pragma once -#include "dusk.h" +#include "error/error.h" typedef struct { void *nothing; @@ -16,5 +16,7 @@ extern localemanager_t LOCALE; /** * Initialize the locale system. + * + * @return An error code if a failure occurs. */ -void localeManagerInit(); \ No newline at end of file +errorret_t localeManagerInit(); \ No newline at end of file diff --git a/tools/assetstool/main.py b/tools/assetstool/main.py index ec96699..2207202 100644 --- a/tools/assetstool/main.py +++ b/tools/assetstool/main.py @@ -21,6 +21,8 @@ for asset in inputAssets: asset = processAsset(asset) files.extend(asset['files']) +files.extend(processLanguageList()['files']) + # Take assets and add to a zip archive. outputFileName = args.output_file print(f"Creating output file: {outputFileName}") @@ -32,7 +34,6 @@ with zipfile.ZipFile(outputFileName, 'w') as zipf: # Generate additional headers. processPaletteList() processTilesetList() -processLanguageList() # Finalize build if args.build_type == 'header': diff --git a/tools/assetstool/processlanguage.py b/tools/assetstool/processlanguage.py index 6dc5b01..e322de8 100644 --- a/tools/assetstool/processlanguage.py +++ b/tools/assetstool/processlanguage.py @@ -102,6 +102,7 @@ def processLanguageList(): # We have now chunked all the keys for this language! langBuffer = b"" + files = [] # Write header info langBuffer += b'DLF' # Dusk Language File @@ -128,6 +129,7 @@ def processLanguageList(): # Write out the language data file outputFile = os.path.join(args.output_assets, "language", f"{lang}.dlf") + files.append(outputFile) os.makedirs(os.path.dirname(outputFile), exist_ok=True) with open(outputFile, "wb") as f: f.write(langBuffer) @@ -139,6 +141,10 @@ def processLanguageList(): with open(outputFile, "w") as f: f.write(headerKeys) + return { + 'files': files + } + def getLanguageVariableName(languageKey): # Take the language key, prepend LANG_, uppercase, replace any non symbols # with _