Language finished.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Language: us\n"
|
"Language: en_US\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ errorret_t assetLoad(const char_t *filename, void *output) {
|
|||||||
.zipFile = file,
|
.zipFile = file,
|
||||||
.output = output
|
.output = output
|
||||||
};
|
};
|
||||||
errorChain(def->custom(&customData));
|
errorChain(def->custom(customData));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ typedef struct {
|
|||||||
const assetloadstrat_t loadStrategy;
|
const assetloadstrat_t loadStrategy;
|
||||||
union {
|
union {
|
||||||
errorret_t (*entire)(void *data, void *output);
|
errorret_t (*entire)(void *data, void *output);
|
||||||
errorret_t (*custom)(assetcustom_t *custom);
|
errorret_t (*custom)(assetcustom_t custom);
|
||||||
};
|
};
|
||||||
} assettypedef_t;
|
} assettypedef_t;
|
||||||
|
|
||||||
@@ -61,6 +61,6 @@ static const assettypedef_t ASSET_TYPE_DEFINITIONS[ASSET_TYPE_COUNT] = {
|
|||||||
[ASSET_TYPE_LANGUAGE] = {
|
[ASSET_TYPE_LANGUAGE] = {
|
||||||
.header = "DLF",
|
.header = "DLF",
|
||||||
.loadStrategy = ASSET_LOAD_STRAT_CUSTOM,
|
.loadStrategy = ASSET_LOAD_STRAT_CUSTOM,
|
||||||
.custom = assetLanguageInit
|
.custom = assetLanguageHandler
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -6,9 +6,108 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "asset/asset.h"
|
#include "asset/asset.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "locale/localemanager.h"
|
||||||
|
|
||||||
errorret_t assetLanguageInit(assetcustom_t *custom) {
|
errorret_t assetLanguageHandler(assetcustom_t custom) {
|
||||||
zip_fclose(custom->zipFile);
|
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();
|
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");
|
||||||
}
|
}
|
||||||
@@ -6,10 +6,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "error/error.h"
|
|
||||||
#include "locale/language/keys.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_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)
|
#pragma pack(push, 1)
|
||||||
typedef char assetlanguagechunk_t[ASSET_LANG_CHUNK_CHAR_COUNT];
|
typedef char assetlanguagechunk_t[ASSET_LANG_CHUNK_CHAR_COUNT];
|
||||||
@@ -29,12 +31,57 @@ typedef struct {
|
|||||||
} assetlanguageheader_t;
|
} assetlanguageheader_t;
|
||||||
#pragma pack(pop)
|
#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;
|
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.
|
* @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);
|
||||||
@@ -54,6 +54,7 @@ void engineExit(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
errorret_t engineDispose(void) {
|
errorret_t engineDispose(void) {
|
||||||
|
localeManagerDispose();
|
||||||
sceneManagerDispose();
|
sceneManagerDispose();
|
||||||
rpgDispose();
|
rpgDispose();
|
||||||
uiDispose();
|
uiDispose();
|
||||||
|
|||||||
@@ -8,12 +8,29 @@
|
|||||||
#include "localemanager.h"
|
#include "localemanager.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
#include "asset/asset.h"
|
#include "asset/asset.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
|
||||||
localemanager_t LOCALE;
|
localemanager_t LOCALE;
|
||||||
|
|
||||||
errorret_t localeManagerInit() {
|
errorret_t localeManagerInit() {
|
||||||
memoryZero(&LOCALE, sizeof(localemanager_t));
|
memoryZero(&LOCALE, sizeof(localemanager_t));
|
||||||
|
errorChain(localeManagerSetLocale(DUSK_LOCALE_EN_US));
|
||||||
errorChain(assetLoad("language/us.dlf", &LOCALE));
|
|
||||||
errorOk();
|
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);
|
||||||
}
|
}
|
||||||
@@ -6,12 +6,30 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "error/error.h"
|
#include "asset/asset.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DUSK_LOCALE_EN_US,
|
||||||
|
|
||||||
|
DUSK_LOCALE_COUNT
|
||||||
|
} dusklocale_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *nothing;
|
dusklocale_t locale;
|
||||||
|
assetlanguage_t language;
|
||||||
} localemanager_t;
|
} 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;
|
extern localemanager_t LOCALE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -19,4 +37,17 @@ extern localemanager_t LOCALE;
|
|||||||
*
|
*
|
||||||
* @return An error code if a failure occurs.
|
* @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();
|
||||||
@@ -60,6 +60,8 @@ def processLanguageList():
|
|||||||
|
|
||||||
# Now we can generate the language string chunks.
|
# Now we can generate the language string chunks.
|
||||||
nextChunkIndex = max(desiredChunkGroups.values()) + 1
|
nextChunkIndex = max(desiredChunkGroups.values()) + 1
|
||||||
|
files = []
|
||||||
|
|
||||||
for lang in LANGUAGE_DATA:
|
for lang in LANGUAGE_DATA:
|
||||||
langData = LANGUAGE_DATA[lang]
|
langData = LANGUAGE_DATA[lang]
|
||||||
|
|
||||||
@@ -102,7 +104,6 @@ def processLanguageList():
|
|||||||
|
|
||||||
# We have now chunked all the keys for this language!
|
# We have now chunked all the keys for this language!
|
||||||
langBuffer = b""
|
langBuffer = b""
|
||||||
files = []
|
|
||||||
|
|
||||||
# Write header info
|
# Write header info
|
||||||
langBuffer += b'DLF' # Dusk Language File
|
langBuffer += b'DLF' # Dusk Language File
|
||||||
@@ -127,6 +128,12 @@ def processLanguageList():
|
|||||||
strData = langData[key].encode('utf-8')
|
strData = langData[key].encode('utf-8')
|
||||||
langBuffer += strData
|
langBuffer += strData
|
||||||
|
|
||||||
|
# Now pad the chunk to full size
|
||||||
|
curLen = chunkInfo['len']
|
||||||
|
if curLen < LANGUAGE_CHUNK_CHAR_COUNT:
|
||||||
|
padSize = LANGUAGE_CHUNK_CHAR_COUNT - curLen
|
||||||
|
langBuffer += b'\0' * padSize
|
||||||
|
|
||||||
# Write out the language data file
|
# Write out the language data file
|
||||||
outputFile = os.path.join(args.output_assets, "language", f"{lang}.dlf")
|
outputFile = os.path.join(args.output_assets, "language", f"{lang}.dlf")
|
||||||
files.append(outputFile)
|
files.append(outputFile)
|
||||||
|
|||||||
Reference in New Issue
Block a user