diff options
Diffstat (limited to 'src/text')
-rw-r--r-- | src/text/Text.cpp | 309 | ||||
-rw-r--r-- | src/text/Text.h | 42 |
2 files changed, 300 insertions, 51 deletions
diff --git a/src/text/Text.cpp b/src/text/Text.cpp index f3324fd7..a76bc404 100644 --- a/src/text/Text.cpp +++ b/src/text/Text.cpp @@ -7,6 +7,9 @@ #include "Frontend.h" #include "Messages.h" #include "Text.h" +#include "Timer.h" + +//--MIAMI: file done static wchar WideErrorString[25]; @@ -15,22 +18,28 @@ CText TheText; CText::CText(void) { encoding = 'e'; + bHasMissionTextOffsets = false; + bIsMissionTextLoaded = false; + memset(szMissionTableName, 0, sizeof(szMissionTableName)); memset(WideErrorString, 0, sizeof(WideErrorString)); } void CText::Load(void) { - uint8 *filedata; - char filename[32], type[4]; - intptr_t offset, length; - size_t sectlen; + char filename[32]; + size_t 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){ + switch(FrontEndMenuManager.m_PrefsLanguage){ case CMenuManager::LANGUAGE_AMERICAN: sprintf(filename, "AMERICAN.GXT"); break; @@ -59,49 +68,62 @@ 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(""); } 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)); } 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] = { @@ -174,20 +196,137 @@ CText::UpperCase(wchar *s) } } +void +CText::GetNameOfLoadedMissionText(char *outName) +{ + strcpy(outName, szMissionTableName); +} + +void +CText::ReadChunkHeader(ChunkHeader *buf, int32 file, size_t *offset) +{ +#if DUMB + char *_buf = (char*)buf; + for (int i = 0; i < sizeof(ChunkHeader); i++) { + CFileMgr::Read(file, &_buf[i], 1); + (*offset)++; + } +#else + // 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); +#endif +} void -CKeyArray::Load(size_t length, uint8 *data, intptr_t *offset) +CText::LoadMissionText(char *MissionTableName) { - size_t i; - uint8 *rawbytes; + char filename[32]; + CMessages::ClearAllMessagesDisplayedByGame(); + + 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 (FrontEndMenuManager.m_PrefsLanguage) { + case CMenuManager::LANGUAGE_AMERICAN: + sprintf(filename, "AMERICAN.GXT"); + break; + case CMenuManager::LANGUAGE_FRENCH: + sprintf(filename, "FRENCH.GXT"); + break; + case CMenuManager::LANGUAGE_GERMAN: + sprintf(filename, "GERMAN.GXT"); + break; + case CMenuManager::LANGUAGE_ITALIAN: + sprintf(filename, "ITALIAN.GXT"); + break; + case CMenuManager::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) { + size_t bytes_read = 0; + ReadChunkHeader(&m_ChunkHeader, file, &bytes_read); + if (m_ChunkHeader.size != 0) { + if (strncmp(m_ChunkHeader.magic, "TKEY", 4) == 0) { + size_t bytes_read = 0; + mission_keyArray.Load(m_ChunkHeader.size, file, &bytes_read); + tkey_loaded = true; + } else if (strncmp(m_ChunkHeader.magic, "TDAT", 4) == 0) { + size_t 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; +} + + +void +CKeyArray::Load(size_t length, int file, size_t* offset) +{ + char *rawbytes; // You can make numEntries size_t if you want to exceed 32-bit boundaries, everything else should be ready. numEntries = (int)(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); + (*offset)++; + } +#else + CFileMgr::Read(file, rawbytes, length); + *offset += length; +#endif } void @@ -230,9 +369,9 @@ CKeyArray::BinarySearch(const char *key, CKeyEntry *entries, int16 low, int16 hi 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; @@ -241,33 +380,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; } - void -CData::Load(size_t length, uint8 *data, intptr_t *offset) +CData::Load(size_t length, int file, size_t * offset) { - size_t i; - uint8 *rawbytes; + char *rawbytes; // You can make numChars size_t if you want to exceed 32-bit boundaries, everything else should be ready. numChars = (int)(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); + (*offset)++; + } +#else + CFileMgr::Read(file, rawbytes, length); + *offset += length; +#endif } void @@ -278,6 +431,33 @@ CData::Unload(void) numChars = 0; } +CMissionTextOffsets::Load(size_t table_size, int file, size_t *offset, int) +{ +#if DUMB + size_t num_of_entries = table_size / sizeof(CMissionTextOffsets::Entry); + for (size_t mi = 0; mi < num_of_entries; mi++) { + for (uint32 i = 0; i < sizeof(data[mi].szMissionName); i++) { + CFileMgr::Read(file, &data[i].szMissionName[i], 1); + (*offset)++; + } + char* _buf = (char*)&data[mi].offset; + for (uint32 i = 0; i < sizeof(data[mi].offset); i++) { + CFileMgr::Read(file, &_buf[i], 1); + (*offset)++; + } + } + size = (uint16)num_of_entries; +#else + // not exact VC code but smaller and better :P + + // You can make this size_t if you want to exceed 32-bit boundaries, everything else should be ready. + size = (uint16) (table_size / sizeof(CMissionTextOffsets::Entry)); + CFileMgr::Read(file, (char*)data, sizeof(CMissionTextOffsets::Entry) * size); + *offset += sizeof(CMissionTextOffsets::Entry) * size; +#endif +} + +void char* UnicodeToAscii(wchar *src) { @@ -290,8 +470,29 @@ UnicodeToAscii(wchar *src) if(*src < 128) #endif aStr[len] = *src; - else - aStr[len] = '#'; + // convert to CP1252 + else if(*src <= 131) + aStr[len] = *src + 64; + else if (*src <= 141) + aStr[len] = *src + 66; + else if (*src <= 145) + aStr[len] = *src + 68; + else if (*src <= 149) + aStr[len] = *src + 71; + else if (*src <= 154) + aStr[len] = *src + 73; + else if (*src <= 164) + aStr[len] = *src + 75; + else if (*src <= 168) + aStr[len] = *src + 77; + else if (*src <= 204) + aStr[len] = *src + 80; + else switch (*src) { + case 205: aStr[len] = 209; break; + case 206: aStr[len] = 241; break; + case 207: aStr[len] = 191; break; + default: aStr[len] = '#'; break; + } aStr[len] = '\0'; return aStr; } @@ -325,6 +526,20 @@ UnicodeToAsciiForMemoryCard(wchar *src) } void +UnicodeMakeUpperCase(wchar *dst, wchar *src) //idk what to do with it, seems to be incorrect implementation by R* +{ + while (*src != '\0') { + if (*src < 'a' || *src > 'z') + *dst = *src; + else + *dst = *src - 32; + dst++; + src++; + } + *dst = '\0'; +} + +void TextCopy(wchar *dst, const wchar *src) { while((*dst++ = *src++) != '\0'); diff --git a/src/text/Text.h b/src/text/Text.h index 52c17e27..d18c564b 100644 --- a/src/text/Text.h +++ b/src/text/Text.h @@ -4,6 +4,7 @@ char *UnicodeToAscii(wchar *src); char *UnicodeToAsciiForSaveLoad(wchar *src); char *UnicodeToAsciiForMemoryCard(wchar *src); void TextCopy(wchar *dst, const wchar *src); +void UnicodeMakeUpperCase(wchar *dst, wchar *src); struct CKeyEntry { @@ -26,14 +27,14 @@ public: CKeyArray(void) : entries(nil), numEntries(0) {} ~CKeyArray(void) { Unload(); } - void Load(size_t length, uint8 *data, intptr_t *offset); + void Load(size_t length, int file, size_t *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 }; @@ -45,15 +46,45 @@ public: CData(void) : chars(nil), numChars(0) {} ~CData(void) { Unload(); } - void Load(size_t length, uint8 *data, intptr_t *offset); + void Load(size_t length, int file, size_t* 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; // You can make this size_t if you want to exceed 32-bit boundaries, everything else should be ready. + + CMissionTextOffsets(void) : size(0) {} + void Load(size_t table_size, int file, size_t* 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); @@ -61,6 +92,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, size_t *bytes_read); + void LoadMissionText(char *MissionTableName); }; extern CText TheText; |