summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Frontend.cpp1
-rw-r--r--src/Frontend.h10
-rw-r--r--src/Messages.cpp1
-rw-r--r--src/Messages.h1
-rw-r--r--src/Text.cpp201
-rw-r--r--src/Text.h47
6 files changed, 260 insertions, 1 deletions
diff --git a/src/Frontend.cpp b/src/Frontend.cpp
index a96b6623..e1738172 100644
--- a/src/Frontend.cpp
+++ b/src/Frontend.cpp
@@ -3,6 +3,7 @@
#include "Frontend.h"
int &CMenuManager::m_PrefsBrightness = *(int*)0x5F2E50;
+int &CMenuManager::m_PrefsLanguage = *(int*)0x941238;
CMenuManager &FrontEndMenuManager = *(CMenuManager*)0x8F59D8;
WRAPPER void CMenuManager::DrawFrontEnd(void) { EAXJMP(0x47A540); }
diff --git a/src/Frontend.h b/src/Frontend.h
index 3d7b6914..838139df 100644
--- a/src/Frontend.h
+++ b/src/Frontend.h
@@ -2,6 +2,14 @@
#include "Sprite2d.h"
+enum {
+ LANGUAGE_AMERICAN,
+ LANGUAGE_FRENCH,
+ LANGUAGE_GERMAN,
+ LANGUAGE_ITALIAN,
+ LANGUAGE_SPANISH,
+};
+
struct tSkinInfo
{
int field_0;
@@ -11,7 +19,6 @@ struct tSkinInfo
int field_304;
};
-
class CMenuManager
{
public:
@@ -77,6 +84,7 @@ public:
int m_nScreenChangeDelayTimer;
static int &m_PrefsBrightness;
+ static int &m_PrefsLanguage;
void DrawFrontEnd(void);
};
diff --git a/src/Messages.cpp b/src/Messages.cpp
index 6754c9ae..e29300f4 100644
--- a/src/Messages.cpp
+++ b/src/Messages.cpp
@@ -3,3 +3,4 @@
#include "Messages.h"
WRAPPER void CMessages::Display(void) { EAXJMP(0x529800); }
+WRAPPER void CMessages::ClearAllMessagesDisplayedByGame(void) { EAXJMP(0x52B670); }
diff --git a/src/Messages.h b/src/Messages.h
index f7f90087..711427f1 100644
--- a/src/Messages.h
+++ b/src/Messages.h
@@ -4,4 +4,5 @@ class CMessages
{
public:
static void Display(void);
+ static void ClearAllMessagesDisplayedByGame(void);
};
diff --git a/src/Text.cpp b/src/Text.cpp
new file mode 100644
index 00000000..0281043d
--- /dev/null
+++ b/src/Text.cpp
@@ -0,0 +1,201 @@
+#include "common.h"
+#include "patcher.h"
+#include "FileMgr.h"
+#include "Frontend.h"
+#include "Messages.h"
+#include "Text.h"
+
+static wchar_t WideErrorString[25];
+
+CText &TheText = *(CText*)0x941520;
+
+CText::CText(void)
+{
+ keyArray.entries = nil;
+ keyArray.numEntries = 0;
+ data.chars = nil;
+ data.numChars = 0;
+ unknown = 101; // What's this? version number?
+ memset(WideErrorString, 0, sizeof(WideErrorString));
+}
+
+CText::~CText(void)
+{
+ data.Unload();
+ keyArray.Unload();
+}
+
+void
+CText::Load(void)
+{
+ uint8 *filedata;
+ char filename[32], type[4];
+ int length;
+ int offset, sectlen;
+
+ Unload();
+ filedata = new uint8[0x40000];
+
+ CFileMgr::SetDir("TEXT");
+ switch(CMenuManager::m_PrefsLanguage){
+ case LANGUAGE_AMERICAN:
+ sprintf(filename, "AMERICAN.GXT");
+ break;
+ case LANGUAGE_FRENCH:
+ sprintf(filename, "FRENCH.GXT");
+ break;
+ case LANGUAGE_GERMAN:
+ sprintf(filename, "GERMAN.GXT");
+ break;
+ case LANGUAGE_ITALIAN:
+ sprintf(filename, "ITALIAN.GXT");
+ break;
+ case LANGUAGE_SPANISH:
+ sprintf(filename, "SPANISH.GXT");
+ break;
+ }
+
+ length = CFileMgr::LoadFile(filename, filedata, 0x40000, "rb");
+ CFileMgr::SetDir("");
+
+ offset = 0;
+ while(offset < length){
+ type[0] = filedata[offset++];
+ type[1] = filedata[offset++];
+ type[2] = filedata[offset++];
+ type[3] = filedata[offset++];
+ sectlen = (int)filedata[offset+3]<<24 | (int)filedata[offset+2]<<16 |
+ (int)filedata[offset+1]<<8 | (int)filedata[offset+0];
+ offset += 4;
+ if(sectlen != 0){
+ if(strncmp(type, "TKEY", 4) == 0)
+ keyArray.Load(sectlen, filedata, &offset);
+ else if(strncmp(type, "TDAT", 4) == 0)
+ data.Load(sectlen, filedata, &offset);
+ else
+ offset += sectlen;
+ }
+ }
+
+ keyArray.Update(data.chars);
+
+ delete[] filedata;
+}
+
+void
+CText::Unload(void)
+{
+ CMessages::ClearAllMessagesDisplayedByGame();
+ data.Unload();
+ keyArray.Unload();
+}
+
+wchar_t*
+CText::Get(const char *key)
+{
+ return keyArray.Search(key);
+}
+
+void
+CKeyArray::Load(uint32 length, uint8 *data, int *offset)
+{
+ uint32 i;
+ uint8 *rawbytes;
+
+ numEntries = length / sizeof(CKeyEntry);
+ entries = new CKeyEntry[numEntries];
+ rawbytes = (uint8*)entries;
+
+ for(i = 0; i < length; i++)
+ rawbytes[i] = data[(*offset)++];
+}
+
+void
+CKeyArray::Unload(void)
+{
+ delete[] entries;
+ entries = nil;
+ numEntries = 0;
+}
+
+void
+CKeyArray::Update(wchar_t *chars)
+{
+ int i;
+ for(i = 0; i < numEntries; i++)
+ entries[i].value = (wchar_t*)((uint8*)chars + (uintptr)entries[i].value);
+}
+
+CKeyEntry*
+CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high)
+{
+ int mid;
+ int diff;
+
+ if(low > high)
+ return nil;
+
+ mid = (low + high)/2;
+ diff = strcmp(key, entries[mid].key);
+ if(diff == 0)
+ return &entries[mid];
+ if(diff < 0)
+ return BinarySearch(key, entries, low, mid-1);
+ if(diff > 0)
+ return BinarySearch(key, entries, mid+1, high);
+ return nil;
+}
+
+wchar_t*
+CKeyArray::Search(const char *key)
+{
+ CKeyEntry *found;
+ char errstr[25];
+ int i;
+
+ found = BinarySearch(key, entries, 0, numEntries-1);
+ if(found)
+ return found->value;
+ sprintf(errstr, "%s missing", key);
+ for(i = 0; i < 25; i++)
+ WideErrorString[i] = errstr[i];
+ return WideErrorString;
+}
+
+
+void
+CData::Load(uint32 length, uint8 *data, int *offset)
+{
+ uint32 i;
+ uint8 *rawbytes;
+
+ numChars = length / sizeof(wchar_t);
+ chars = new wchar_t[numChars];
+ rawbytes = (uint8*)chars;
+
+ for(i = 0; i < length; i++)
+ rawbytes[i] = data[(*offset)++];
+}
+
+void
+CData::Unload(void)
+{
+ delete[] chars;
+ chars = nil;
+ numChars = 0;
+}
+
+STARTPATCHES
+ InjectHook(0x52C3C0, &CText::Load, PATCH_JUMP);
+ InjectHook(0x52C580, &CText::Unload, PATCH_JUMP);
+ InjectHook(0x52C5A0, &CText::Get, PATCH_JUMP);
+
+ InjectHook(0x52BE70, &CKeyArray::Load, PATCH_JUMP);
+ InjectHook(0x52BF60, &CKeyArray::Unload, PATCH_JUMP);
+ InjectHook(0x52BF80, &CKeyArray::Update, PATCH_JUMP);
+ InjectHook(0x52C060, &CKeyArray::BinarySearch, PATCH_JUMP);
+ InjectHook(0x52BFB0, &CKeyArray::Search, PATCH_JUMP);
+
+ InjectHook(0x52C120, &CData::Load, PATCH_JUMP);
+ InjectHook(0x52C200, &CData::Unload, PATCH_JUMP);
+ENDPATCHES
diff --git a/src/Text.h b/src/Text.h
new file mode 100644
index 00000000..c8d4e8b7
--- /dev/null
+++ b/src/Text.h
@@ -0,0 +1,47 @@
+#pragma once
+
+struct CKeyEntry
+{
+ wchar_t *value;
+ char key[8];
+};
+// If this fails, CKeyArray::Load will have to be fixed
+static_assert(sizeof(CKeyEntry) == 12, "CKeyEntry: error");
+
+class CKeyArray
+{
+public:
+ CKeyEntry *entries;
+ int numEntries;
+
+ void Load(uint32 length, uint8 *data, int *offset);
+ void Unload(void);
+ void Update(wchar_t *chars);
+ CKeyEntry *BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high);
+ wchar_t *Search(const char *key);
+};
+
+class CData
+{
+public:
+ wchar_t *chars;
+ int numChars;
+
+ void Load(uint32 length, uint8 *data, int *offset);
+ void Unload(void);
+};
+
+class CText
+{
+ CKeyArray keyArray;
+ CData data;
+ int8 unknown;
+public:
+ CText(void);
+ ~CText(void);
+ void Load(void);
+ void Unload(void);
+ wchar_t *Get(const char *key);
+};
+
+extern CText &TheText;