aboutsummaryrefslogtreecommitdiffstats
path: root/src/text
diff options
context:
space:
mode:
authorSergeanur <s.anureev@yandex.ua>2020-05-18 01:28:40 +0300
committerSergeanur <s.anureev@yandex.ua>2020-05-18 01:28:40 +0300
commitaf22bb1495dca506e635bf4805d1469f95f92c69 (patch)
tree265e9ac59c0ca7e51b9596ef6114778b396ea010 /src/text
parent37480fb617a4b8ecd7203af53a1711aa5cdda19d (diff)
CText
Diffstat (limited to 'src/text')
-rw-r--r--src/text/Text.cpp250
-rw-r--r--src/text/Text.h41
2 files changed, 243 insertions, 48 deletions
diff --git a/src/text/Text.cpp b/src/text/Text.cpp
index 1e58fcd1..74f53f80 100644
--- a/src/text/Text.cpp
+++ b/src/text/Text.cpp
@@ -7,27 +7,36 @@
#include "Frontend.h"
#include "Messages.h"
#include "Text.h"
+#include "Timer.h"
static wchar WideErrorString[25];
CText TheText;
+//--MIAMI: DONE
CText::CText(void)
{
encoding = 'e';
+ bHasMissionTextOffsets = false;
+ bIsMissionTextLoaded = false;
+ memset(szMissionTableName, 0, sizeof(szMissionTableName));
memset(WideErrorString, 0, sizeof(WideErrorString));
}
+//--MIAMI: DONE
void
CText::Load(void)
{
- uint8 *filedata;
- char filename[32], type[4];
- int length;
- int offset, sectlen;
+ char filename[32];
+ uint32 offset;
+ int file;
+ bool tkey_loaded = false, tdat_loaded = false;
+ ChunkHeader m_ChunkHeader;
+
+ bIsMissionTextLoaded = false;
+ bHasMissionTextOffsets = false;
Unload();
- filedata = new uint8[0x40000];
CFileMgr::SetDir("TEXT");
switch(CMenuManager::m_PrefsLanguage){
@@ -59,49 +68,64 @@ CText::Load(void)
#endif
}
- length = CFileMgr::LoadFile(filename, filedata, 0x40000, "rb");
- CFileMgr::SetDir("");
+ file = CFileMgr::OpenFile(filename, "rb");
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;
+ while (!tkey_loaded || !tdat_loaded) {
+ ReadChunkHeader(&m_ChunkHeader, file, &offset);
+ if (m_ChunkHeader.size != 0) {
+ if (strncmp(m_ChunkHeader.magic, "TABL", 4) == 0) {
+ MissionTextOffsets.Load(m_ChunkHeader.size, file, &offset, 0x58000);
+ bHasMissionTextOffsets = true;
+ } else if (strncmp(m_ChunkHeader.magic, "TKEY", 4) == 0) {
+ this->keyArray.Load(m_ChunkHeader.size, file, &offset);
+ tkey_loaded = true;
+ } else if (strncmp(m_ChunkHeader.magic, "TDAT", 4) == 0) {
+ this->data.Load(m_ChunkHeader.size, file, &offset);
+ tdat_loaded = true;
+ } else {
+ CFileMgr::Seek(file, m_ChunkHeader.size, SEEK_CUR);
+ offset += m_ChunkHeader.size;
+ }
}
}
keyArray.Update(data.chars);
-
- delete[] filedata;
+ CFileMgr::CloseFile(file);
+ CFileMgr::SetDir("");
}
+//--MIAMI: DONE
void
CText::Unload(void)
{
CMessages::ClearAllMessagesDisplayedByGame();
- data.Unload();
keyArray.Unload();
+ data.Unload();
+ mission_keyArray.Unload();
+ mission_data.Unload();
+ bIsMissionTextLoaded = false;
+ memset(szMissionTableName, 0, sizeof(szMissionTableName));
}
+//--MIAMI: DONE
wchar*
CText::Get(const char *key)
{
+ uint8 result = false;
+#ifdef FIX_BUGS
+ wchar *outstr = keyArray.Search(key, data.chars, &result);
+#else
+ wchar *outstr = keyArray.Search(key, &result);
+#endif
+
+ if (!result && bHasMissionTextOffsets && bIsMissionTextLoaded)
#ifdef FIX_BUGS
- return keyArray.Search(key, data.chars);
+ outstr = mission_keyArray.Search(key, mission_data.chars, &result);
#else
- return keyArray.Search(key);
+ outstr = mission_keyArray.Search(key, &result);
#endif
+ return outstr;
}
wchar UpperCaseTable[128] = {
@@ -134,6 +158,7 @@ wchar FrenchUpperCaseTable[128] = {
253, 254, 255
};
+//--MIAMI: TODO (check tables)
wchar
CText::GetUpperCase(wchar c)
{
@@ -165,6 +190,7 @@ CText::GetUpperCase(wchar c)
return c;
}
+//--MIAMI: DONE
void
CText::UpperCase(wchar *s)
{
@@ -174,21 +200,131 @@ CText::UpperCase(wchar *s)
}
}
+//--MIAMI: DONE
+void
+CText::GetNameOfLoadedMissionText(char *outName)
+{
+ strcpy(outName, szMissionTableName);
+}
+
+//--MIAMI: DONE
+void
+CText::ReadChunkHeader(ChunkHeader *buf, int32 file, uint32 *offset)
+{
+ // original code loops 8 times to read 1 byte with CFileMgr::Read, that's retarded
+ CFileMgr::Read(file, (char*)buf, sizeof(ChunkHeader));
+ *offset += sizeof(ChunkHeader);
+}
+
+//--MIAMI: DONE
+void
+CText::LoadMissionText(char *MissionTableName)
+{
+ char filename[32];
+
+ mission_keyArray.Unload();
+ mission_data.Unload();
+
+ bool search_result = false;
+ int missionTableId = 0;
+
+ for (missionTableId = 0; missionTableId < MissionTextOffsets.size; missionTableId++) {
+ if (strncmp(MissionTextOffsets.data[missionTableId].szMissionName, MissionTableName, strlen(MissionTextOffsets.data[missionTableId].szMissionName)) == 0) {
+ search_result = true;
+ break;
+ }
+ }
+
+ if (!search_result) {
+ printf("CText::LoadMissionText - couldn't find %s", MissionTableName);
+ return;
+ }
+
+ 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;
+#ifdef MORE_LANGUAGES
+ case LANGUAGE_POLISH:
+ sprintf(filename, "POLISH.GXT");
+ break;
+ case LANGUAGE_RUSSIAN:
+ sprintf(filename, "RUSSIAN.GXT");
+ break;
+ case LANGUAGE_JAPANESE:
+ sprintf(filename, "JAPANESE.GXT");
+ break;
+#endif
+ }
+ CTimer::Suspend();
+ int file = CFileMgr::OpenFile(filename, "rb");
+ CFileMgr::Seek(file, MissionTextOffsets.data[missionTableId].offset, SEEK_SET);
+
+ char TableCheck[8];
+ CFileMgr::Read(file, TableCheck, 8);
+ if (strncmp(TableCheck, MissionTableName, 8) != 0)
+ printf("CText::LoadMissionText - expected to find %s in the text file", MissionTableName);
+
+ bool tkey_loaded = false, tdat_loaded = false;
+ ChunkHeader m_ChunkHeader;
+ while (!tkey_loaded || !tdat_loaded) {
+ uint32 bytes_read = 0;
+ ReadChunkHeader(&m_ChunkHeader, file, &bytes_read);
+ if (m_ChunkHeader.size != 0) {
+ if (strncmp(m_ChunkHeader.magic, "TKEY", 4) == 0) {
+ uint32 bytes_read = 0;
+ mission_keyArray.Load(m_ChunkHeader.size, file, &bytes_read);
+ tkey_loaded = true;
+ } else if (strncmp(m_ChunkHeader.magic, "TDAT", 4) == 0) {
+ uint32 bytes_read = 0;
+ mission_data.Load(m_ChunkHeader.size, file, &bytes_read);
+ tdat_loaded = true;
+ } else
+ CFileMgr::Seek(file, m_ChunkHeader.size, SEEK_CUR);
+ }
+ }
+
+ mission_keyArray.Update(mission_data.chars);
+ CFileMgr::CloseFile(file);
+ CTimer::Resume();
+ CFileMgr::SetDir("");
+ strcpy(szMissionTableName, MissionTableName);
+ bIsMissionTextLoaded = true;
+}
+
+//--MIAMI: DONE
void
-CKeyArray::Load(uint32 length, uint8 *data, int *offset)
+CKeyArray::Load(uint32 length, int file, uint32 *offset)
{
- uint32 i;
- uint8 *rawbytes;
+ char *rawbytes;
numEntries = length / sizeof(CKeyEntry);
entries = new CKeyEntry[numEntries];
- rawbytes = (uint8*)entries;
+ rawbytes = (char*)entries;
- for(i = 0; i < length; i++)
- rawbytes[i] = data[(*offset)++];
+#if DUMB
+ for (uint32 i = 0; i < length; i++)
+ CFileMgr::Read(file, &rawbytes[i], 1);
+#else
+ CFileMgr::Read(file, rawbytes, length);
+#endif
}
+//--MIAMI: DONE
void
CKeyArray::Unload(void)
{
@@ -197,6 +333,7 @@ CKeyArray::Unload(void)
numEntries = 0;
}
+//--MIAMI: DONE
void
CKeyArray::Update(wchar *chars)
{
@@ -207,6 +344,7 @@ CKeyArray::Update(wchar *chars)
#endif
}
+//--MIAMI: DONE
CKeyEntry*
CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high)
{
@@ -227,11 +365,12 @@ CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 hi
return nil;
}
+//--MIAMI: DONE
wchar*
#ifdef FIX_BUGS
-CKeyArray::Search(const char *key, wchar *data)
+CKeyArray::Search(const char *key, wchar *data, uint8 *result)
#else
-CKeyArray::Search(const char *key)
+CKeyArray::Search(const char *key, uint8 *result)
#endif
{
CKeyEntry *found;
@@ -240,34 +379,47 @@ CKeyArray::Search(const char *key)
#ifdef FIX_BUGS
found = BinarySearch(key, entries, 0, numEntries-1);
- if(found)
+ if (found) {
+ *result = true;
return (wchar*)((uint8*)data + found->valueOffset);
+ }
#else
found = BinarySearch(key, entries, 0, numEntries-1);
- if(found)
+ if (found) {
+ *result = true;
return found->value;
+ }
#endif
+ *result = false;
+#ifdef MASTER
+ sprintf(errstr, "%");
+#else
sprintf(errstr, "%s missing", key);
+#endif // MASTER
for(i = 0; i < 25; i++)
WideErrorString[i] = errstr[i];
return WideErrorString;
}
-
+//--MIAMI: DONE
void
-CData::Load(uint32 length, uint8 *data, int *offset)
+CData::Load(uint32 length, int file, uint32 *offset)
{
- uint32 i;
- uint8 *rawbytes;
+ char *rawbytes;
numChars = length / sizeof(wchar);
chars = new wchar[numChars];
- rawbytes = (uint8*)chars;
+ rawbytes = (char*)chars;
- for(i = 0; i < length; i++)
- rawbytes[i] = data[(*offset)++];
+#if DUMB
+ for(uint32 i = 0; i < length; i++)
+ CFileMgr::Read(file, &rawbytes[i], 1);
+#else
+ CFileMgr::Read(file, rawbytes, length);
+#endif
}
+//--MIAMI: DONE
void
CData::Unload(void)
{
@@ -276,6 +428,16 @@ CData::Unload(void)
numChars = 0;
}
+//--MIAMI: DONE
+void
+CMissionTextOffsets::Load(uint32 table_size, int file, uint32 *offset, int)
+{
+ // not exact VC code but smaller and better :P
+ size = table_size / sizeof(CMissionTextOffsets::Entry);
+ CFileMgr::Read(file, (char*)data, sizeof(CMissionTextOffsets::Entry) * size);
+ *offset += sizeof(CMissionTextOffsets::Entry) * size;
+}
+
void
AsciiToUnicode(const char *src, wchar *dst)
{
diff --git a/src/text/Text.h b/src/text/Text.h
index 18a904bc..dcffccbf 100644
--- a/src/text/Text.h
+++ b/src/text/Text.h
@@ -28,14 +28,14 @@ public:
CKeyArray(void) : entries(nil), numEntries(0) {}
~CKeyArray(void) { Unload(); }
- void Load(uint32 length, uint8 *data, int *offset);
+ void Load(uint32 length, int file, uint32 *offset);
void Unload(void);
void Update(wchar *chars);
CKeyEntry *BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 high);
#ifdef FIX_BUGS
- wchar *Search(const char *key, wchar *data);
+ wchar *Search(const char *key, wchar *data, uint8 *result);
#else
- wchar *Search(const char *key);
+ wchar *Search(const char *key, uint8* result);
#endif
};
@@ -47,15 +47,45 @@ public:
CData(void) : chars(nil), numChars(0) {}
~CData(void) { Unload(); }
- void Load(uint32 length, uint8 *data, int *offset);
+ void Load(uint32 length, int file, uint32 *offset);
void Unload(void);
};
+class CMissionTextOffsets
+{
+public:
+ struct Entry
+ {
+ char szMissionName[8];
+ uint32 offset;
+ };
+
+ enum {MAX_MISSION_TEXTS = 90}; // beware that LCS has more
+
+ Entry data[MAX_MISSION_TEXTS];
+ uint16 size;
+
+ CMissionTextOffsets(void) : size(0) {}
+ void Load(uint32 table_size, int file, uint32* bytes_read, int);
+};
+
+struct ChunkHeader
+{
+ char magic[4];
+ int size;
+};
+
class CText
{
CKeyArray keyArray;
CData data;
+ CKeyArray mission_keyArray;
+ CData mission_data;
char encoding;
+ bool bHasMissionTextOffsets;
+ bool bIsMissionTextLoaded;
+ char szMissionTableName[8];
+ CMissionTextOffsets MissionTextOffsets;
public:
CText(void);
void Load(void);
@@ -63,6 +93,9 @@ public:
wchar *Get(const char *key);
wchar GetUpperCase(wchar c);
void UpperCase(wchar *s);
+ void GetNameOfLoadedMissionText(char *outName);
+ void ReadChunkHeader(ChunkHeader *buf, int32 file, uint32 *bytes_read);
+ void LoadMissionText(char *MissionTableName);
};
extern CText TheText;