Language finished.

This commit is contained in:
2025-11-08 11:12:04 -06:00
parent ab534bb998
commit bc4776f096
9 changed files with 218 additions and 16 deletions

View File

@@ -100,7 +100,7 @@ errorret_t assetLoad(const char_t *filename, void *output) {
.zipFile = file,
.output = output
};
errorChain(def->custom(&customData));
errorChain(def->custom(customData));
break;
default:

View File

@@ -35,7 +35,7 @@ typedef struct {
const assetloadstrat_t loadStrategy;
union {
errorret_t (*entire)(void *data, void *output);
errorret_t (*custom)(assetcustom_t *custom);
errorret_t (*custom)(assetcustom_t custom);
};
} assettypedef_t;
@@ -61,6 +61,6 @@ static const assettypedef_t ASSET_TYPE_DEFINITIONS[ASSET_TYPE_COUNT] = {
[ASSET_TYPE_LANGUAGE] = {
.header = "DLF",
.loadStrategy = ASSET_LOAD_STRAT_CUSTOM,
.custom = assetLanguageInit
.custom = assetLanguageHandler
}
};

View File

@@ -6,9 +6,108 @@
*/
#include "asset/asset.h"
#include "assert/assert.h"
#include "locale/localemanager.h"
errorret_t assetLanguageInit(assetcustom_t *custom) {
zip_fclose(custom->zipFile);
errorret_t assetLanguageHandler(assetcustom_t custom) {
assertNotNull(custom.zipFile, "Custom asset zip file cannot be NULL");
assertNotNull(custom.output, "Custom asset output cannot be NULL");
assetlanguage_t *lang = (assetlanguage_t *)custom.output;
errorChain(assetLanguageInit(lang, custom.zipFile));
errorOk();
}
errorret_t assetLanguageInit(
assetlanguage_t *lang,
zip_file_t *zipFile
) {
assertNotNull(lang, "Language asset cannot be NULL");
assertNotNull(zipFile, "Zip file cannot be NULL");
assertNull(lang->zip, "Language asset zip file must be NULL.");
assertTrue(zip_file_is_seekable(zipFile), "Language file must be seekable.");
// We now own the zip file handle.
lang->zip = zipFile;
printf("Initialized language asset.\n");
// Read in the header.
zip_int64_t bytesRead = zip_fread(
lang->zip,
&lang->header,
sizeof(assetlanguageheader_t)
);
if(bytesRead != sizeof(assetlanguageheader_t)) {
zip_fclose(lang->zip);
errorThrow("Failed to read language asset header.");
}
lang->chunksOffset = zip_ftell(lang->zip);
if(lang->chunksOffset <= 0) {
zip_fclose(lang->zip);
errorThrow("Failed to get language asset chunks offset.");
}
errorOk();
}
errorret_t assetLanguageRead(
assetlanguage_t *lang,
const uint32_t key,
char_t *buffer,
const uint32_t bufferSize,
uint32_t *outLength
) {
assertNotNull(lang, "Language asset cannot be NULL");
assertNotNull(lang->zip, "Language asset zip file cannot be NULL");
assertTrue(key < LANG_KEY_COUNT, "Language key out of bounds.");
// Find the string entry
assetlanguagestring_t *str = &lang->header.strings[LANG_MAP_TEST];
// If buffer is NULL, return the string length
if(buffer == NULL) {
assertNotNull(outLength, "Output length pointer cannot be NULL.");
*outLength = str->length;
errorOk();
}
// Ensure buffer is large enough
assertTrue(
bufferSize >= str->length + 1,
"Provided buffer is too small for language string."
);
// Determine the file position
zip_int64_t seekTo = lang->chunksOffset + (
(str->chunk * ASSET_LANG_CHUNK_CHAR_COUNT) + str->offset
);
// Seek
zip_int64_t result = zip_fseek(lang->zip, seekTo, SEEK_SET);
if(result != 0) {
errorThrow("Failed to seek to language string in asset.");
}
// Read
zip_int64_t readTest = zip_fread(lang->zip, buffer, str->length);
if(readTest != str->length) {
errorThrow("Failed to read test string from language asset.");
}
buffer[str->length] = '\0';
// Set str length if requested
if(outLength != NULL) *outLength = str->length;
errorOk();
}
void assetLanguageDispose(assetlanguage_t *lang) {
assertNotNull(lang, "Language asset cannot be NULL");
if(lang->zip) {
zip_fclose(lang->zip);
}
printf("Disposed language asset.\n");
}

View File

@@ -6,10 +6,12 @@
*/
#pragma once
#include "error/error.h"
#include "locale/language/keys.h"
#include "error/error.h"
#include <zip.h>
#define ASSET_LANG_CHUNK_CHAR_COUNT 6 * 1024 // 6 KB per chunk
#define ASSET_LANG_CHUNK_CACHE 4 // Number of chunks to cache in memory
#pragma pack(push, 1)
typedef char assetlanguagechunk_t[ASSET_LANG_CHUNK_CHAR_COUNT];
@@ -29,12 +31,57 @@ typedef struct {
} assetlanguageheader_t;
#pragma pack(pop)
typedef struct {
zip_file_t *zip;
assetlanguageheader_t header;
zip_int64_t chunksOffset;
// Chunk cache
assetlanguagechunk_t chunks[ASSET_LANG_CHUNK_CACHE];
uint32_t chunkIndices[ASSET_LANG_CHUNK_CACHE];
} assetlanguage_t;
typedef struct assetcustom_s assetcustom_t;
/**
* Receiving function from the asset manager to initialize language assets.
* Receiving function from the asset manager to handle language assets.
*
* @param custom Pointer to custom asset loading data.
* @param custom Custom asset loading data.
* @return Error code.
*/
errorret_t assetLanguageInit(assetcustom_t *custom);
errorret_t assetLanguageHandler(assetcustom_t custom);
/**
* Initializes a language asset and loads the header data into memory.
*
* @param lang Language asset to initialize.
* @param zipFile Zip file handle for the language asset.
* @return Error code.
*/
errorret_t assetLanguageInit(assetlanguage_t *lang, zip_file_t *zipFile);
/**
* Reads a string from the language asset into the provided buffer.
*
* @param lang Language asset to read from.
* @param key Language key to read.
* @param buffer Buffer to read the string into.
* @param bufferSize Size of the provided buffer.
* @param outLength Pointer to store the length of the string read.
* @return Error code.
*/
errorret_t assetLanguageRead(
assetlanguage_t *lang,
const uint32_t key,
char_t *buffer,
const uint32_t bufferSize,
uint32_t *outLength
);
/**
* Disposes of language asset resources.
*
* @param custom Custom asset loading data.
* @return Error code.
*/
void assetLanguageDispose(assetlanguage_t *lang);

View File

@@ -54,6 +54,7 @@ void engineExit(void) {
}
errorret_t engineDispose(void) {
localeManagerDispose();
sceneManagerDispose();
rpgDispose();
uiDispose();

View File

@@ -8,12 +8,29 @@
#include "localemanager.h"
#include "util/memory.h"
#include "asset/asset.h"
#include "assert/assert.h"
localemanager_t LOCALE;
errorret_t localeManagerInit() {
memoryZero(&LOCALE, sizeof(localemanager_t));
errorChain(assetLoad("language/us.dlf", &LOCALE));
errorChain(localeManagerSetLocale(DUSK_LOCALE_EN_US));
errorOk();
}
errorret_t localeManagerSetLocale(const dusklocale_t locale) {
assertTrue(locale < DUSK_LOCALE_COUNT, "Invalid locale.");
LOCALE.locale = locale;
char_t languageFile[FILENAME_MAX];
snprintf(
languageFile, FILENAME_MAX, "language/%s.dlf", LOCALE_INFOS[locale].file
);
assetLanguageDispose(&LOCALE.language);
memoryZero(&LOCALE.language, sizeof(assetlanguage_t));
errorChain(assetLoad(languageFile, &LOCALE.language));
errorOk();
}
void localeManagerDispose() {
assetLanguageDispose(&LOCALE.language);
}

View File

@@ -6,12 +6,30 @@
*/
#pragma once
#include "error/error.h"
#include "asset/asset.h"
typedef enum {
DUSK_LOCALE_EN_US,
DUSK_LOCALE_COUNT
} dusklocale_t;
typedef struct {
void *nothing;
dusklocale_t locale;
assetlanguage_t language;
} localemanager_t;
typedef struct {
const char_t *file;
} localeinfo_t;
static const localeinfo_t LOCALE_INFOS[DUSK_LOCALE_COUNT] = {
[DUSK_LOCALE_EN_US] = {
.file = "en_US"
}
};
extern localemanager_t LOCALE;
/**
@@ -19,4 +37,17 @@ extern localemanager_t LOCALE;
*
* @return An error code if a failure occurs.
*/
errorret_t localeManagerInit();
errorret_t localeManagerInit();
/**
* Set the current locale.
*
* @param locale The locale to set.
* @return An error code if a failure occurs.
*/
errorret_t localeManagerSetLocale(const dusklocale_t locale);
/**
* Dispose of the locale system.
*/
void localeManagerDispose();