More changes to how we handle text encoding, fixing up the code so it compiles now

This commit is contained in:
Aruki 2018-12-23 21:44:31 -07:00
parent e92a9fc6b0
commit 0ae7b8686e
16 changed files with 163 additions and 139 deletions

2
externals/LibCommon vendored

@ -1 +1 @@
Subproject commit 6557c54f799c3bbb16900d2d98a75e9533a6f80d Subproject commit 057d2b817dc0299759e8a1c46774fbd875358166

View File

@ -585,7 +585,7 @@ void GenerateAssetNames(CGameProject *pProj)
TString String; TString String;
for (uint32 iStr = 0; iStr < pString->NumStrings() && String.IsEmpty(); iStr++) for (uint32 iStr = 0; iStr < pString->NumStrings() && String.IsEmpty(); iStr++)
String = CStringTable::StripFormatting( pString->String("ENGL", iStr) ).Trimmed(); String = CStringTable::StripFormatting( pString->GetString(ELanguage::English, iStr) ).Trimmed();
if (!String.IsEmpty()) if (!String.IsEmpty())
{ {

View File

@ -198,16 +198,16 @@ bool CGameExporter::ExtractDiscData()
if (IsWii) if (IsWii)
{ {
// Extract crypto files // Extract crypto files
if (!pDataPartition->extractCryptoFiles(*AbsDiscDir.ToUTF16(), Context)) if (!pDataPartition->extractCryptoFiles(ToWChar(AbsDiscDir), Context))
return false; return false;
// Extract disc header files // Extract disc header files
if (!mpDisc->extractDiscHeaderFiles(*AbsDiscDir.ToUTF16(), Context)) if (!mpDisc->extractDiscHeaderFiles(ToWChar(AbsDiscDir), Context))
return false; return false;
} }
// Extract system files // Extract system files
if (!pDataPartition->extractSysFiles(*AbsDiscDir.ToUTF16(), Context)) if (!pDataPartition->extractSysFiles(ToWChar(AbsDiscDir), Context))
return false; return false;
return true; return true;
@ -226,7 +226,7 @@ bool CGameExporter::ExtractDiscNodeRecursive(const nod::Node *pkNode, const TStr
if (Iter->getKind() == nod::Node::Kind::File) if (Iter->getKind() == nod::Node::Kind::File)
{ {
TString FilePath = rkDir + Iter->getName().data(); TString FilePath = rkDir + Iter->getName().data();
bool Success = Iter->extractToDirectory(*rkDir.ToUTF16(), rkContext); bool Success = Iter->extractToDirectory(ToWChar(rkDir), rkContext);
if (!Success) return false; if (!Success) return false;
if (FilePath.GetFileExtension().CaseInsensitiveCompare("pak")) if (FilePath.GetFileExtension().CaseInsensitiveCompare("pak"))

View File

@ -83,21 +83,21 @@ bool CGameProject::BuildISO(const TString& rkIsoPath, IProgressNotifier *pProgre
auto ProgressCallback = [&](float ProgressPercent, const nod::SystemStringView& rkInfoString, size_t) auto ProgressCallback = [&](float ProgressPercent, const nod::SystemStringView& rkInfoString, size_t)
{ {
pProgress->Report((int) (ProgressPercent * 10000), 10000, TWideString(rkInfoString.data()).ToUTF8()); pProgress->Report((int) (ProgressPercent * 10000), 10000, nod::SystemUTF8Conv(rkInfoString).c_str());
}; };
pProgress->SetTask(0, "Building " + rkIsoPath.GetFileName()); pProgress->SetTask(0, "Building " + rkIsoPath.GetFileName());
TWideString DiscRoot = DiscDir(false).ToUTF16(); TString DiscRoot = DiscDir(false);
if (!IsWiiBuild()) if (!IsWiiBuild())
{ {
nod::DiscBuilderGCN Builder(*rkIsoPath.ToUTF16(), ProgressCallback); nod::DiscBuilderGCN Builder(ToWChar(rkIsoPath), ProgressCallback);
return Builder.buildFromDirectory(*DiscRoot) == nod::EBuildResult::Success; return Builder.buildFromDirectory(ToWChar(DiscRoot)) == nod::EBuildResult::Success;
} }
else else
{ {
nod::DiscBuilderWii Builder(*rkIsoPath.ToUTF16(), IsTrilogy(), ProgressCallback); nod::DiscBuilderWii Builder(ToWChar(rkIsoPath), IsTrilogy(), ProgressCallback);
return Builder.buildFromDirectory(*DiscRoot) == nod::EBuildResult::Success; return Builder.buildFromDirectory(ToWChar(DiscRoot)) == nod::EBuildResult::Success;
} }
} }
@ -109,15 +109,15 @@ bool CGameProject::MergeISO(const TString& rkIsoPath, nod::DiscWii *pOriginalIso
auto ProgressCallback = [&](float ProgressPercent, const nod::SystemStringView& rkInfoString, size_t) auto ProgressCallback = [&](float ProgressPercent, const nod::SystemStringView& rkInfoString, size_t)
{ {
pProgress->Report((int) (ProgressPercent * 10000), 10000, TWideString(rkInfoString.data()).ToUTF8()); pProgress->Report((int) (ProgressPercent * 10000), 10000, nod::SystemUTF8Conv(rkInfoString).c_str());
}; };
pProgress->SetTask(0, "Building " + rkIsoPath.GetFileName()); pProgress->SetTask(0, "Building " + rkIsoPath.GetFileName());
TWideString DiscRoot = DiscFilesystemRoot(false).ToUTF16(); TString DiscRoot = DiscFilesystemRoot(false);
nod::DiscMergerWii Merger(*rkIsoPath.ToUTF16(), *pOriginalIso, IsTrilogy(), ProgressCallback); nod::DiscMergerWii Merger(ToWChar(rkIsoPath), *pOriginalIso, IsTrilogy(), ProgressCallback);
return Merger.mergeFromDirectory(*DiscRoot) == nod::EBuildResult::Success; return Merger.mergeFromDirectory(ToWChar(DiscRoot)) == nod::EBuildResult::Success;
} }
void CGameProject::GetWorldList(std::list<CAssetID>& rOut) const void CGameProject::GetWorldList(std::list<CAssetID>& rOut) const

View File

@ -30,7 +30,7 @@ TString COpeningBanner::EnglishGameName() const
Banner.ReadBytes(NameBuffer.data(), MaxLen * CharSize); Banner.ReadBytes(NameBuffer.data(), MaxLen * CharSize);
Banner.SetData(NameBuffer.data(), NameBuffer.size(), EEndian::BigEndian); Banner.SetData(NameBuffer.data(), NameBuffer.size(), EEndian::BigEndian);
return mWii ? Banner.ReadWString().ToUTF8() : Banner.ReadString(); return mWii ? Banner.Read16String().ToUTF8() : Banner.ReadString();
} }
void COpeningBanner::SetEnglishGameName(const TString& rkName) void COpeningBanner::SetEnglishGameName(const TString& rkName)
@ -44,7 +44,7 @@ void COpeningBanner::SetEnglishGameName(const TString& rkName)
if (mWii) if (mWii)
{ {
Banner.GoTo(0xB0); Banner.GoTo(0xB0);
Banner.WriteWString(rkName.ToUTF16(), -1, false); Banner.Write16String(rkName.ToUTF16(), -1, false);
PadCount = (MaxLen - rkName.Size()) * 2; PadCount = (MaxLen - rkName.Size()) * 2;
} }
else else

View File

@ -63,7 +63,7 @@ void CWorld::SetAreaLayerInfo(CGameArea *pArea)
TString CWorld::InGameName() const TString CWorld::InGameName() const
{ {
if (mpWorldName) if (mpWorldName)
return mpWorldName->String("ENGL", 0); return mpWorldName->GetString(ELanguage::English, 0);
else else
return Entry()->Name(); return Entry()->Name();
} }
@ -73,7 +73,7 @@ TString CWorld::AreaInGameName(uint32 AreaIndex) const
const SArea& rkArea = mAreas[AreaIndex]; const SArea& rkArea = mAreas[AreaIndex];
if (rkArea.pAreaName) if (rkArea.pAreaName)
return rkArea.pAreaName->String("ENGL", 0); return rkArea.pAreaName->GetString(ELanguage::English, 0);
else else
return "!!" + rkArea.InternalName; return "!!" + rkArea.InternalName;
} }

View File

@ -214,7 +214,7 @@ void CScanLoader::LoadParamsMP3(IInputStream& rSCAN, uint16 NumProperties)
switch (PropertyID) switch (PropertyID)
{ {
case 0x2F5B6423: case 0x2F5B6423:
mpScan->mpStringTable = gpResourceStore->LoadResource(rSCAN.ReadLongLong(), EResourceType::Scan); mpScan->mpStringTable = gpResourceStore->LoadResource(rSCAN.ReadLongLong(), EResourceType::StringTable);
break; break;
case 0xC308A322: case 0xC308A322:

View File

@ -1,193 +1,214 @@
#include "CStringLoader.h" #include "CStringLoader.h"
#include <Common/Log.h> #include <Common/Log.h>
#include <Common/Math/MathUtil.h>
void CStringLoader::LoadPrimeDemoSTRG(IInputStream& rSTRG) void CStringLoader::LoadPrimeDemoSTRG(IInputStream& STRG)
{ {
// This function starts at 0x4 in the file - right after the size // This function starts at 0x4 in the file - right after the size
// This STRG version only supports one language per file // This STRG version only supports one language per file
mpStringTable->mLangTables.resize(1); mpStringTable->mLanguages.resize(1);
CStringTable::SLangTable* Lang = &mpStringTable->mLangTables[1]; CStringTable::SLanguageData& Language = mpStringTable->mLanguages[0];
Lang->Language = "ENGL"; Language.Language = ELanguage::English;
uint32 TableStart = rSTRG.Tell(); uint TableStart = STRG.Tell();
// Header // Header
uint32 NumStrings = rSTRG.ReadLong(); uint NumStrings = STRG.ReadLong();
Lang->Strings.resize(NumStrings); Language.Strings.resize(NumStrings);
mpStringTable->mNumStrings = NumStrings;
// String offsets (yeah, that wasn't much of a header) // String offsets (yeah, that wasn't much of a header)
std::vector<uint32> StringOffsets(NumStrings); std::vector<uint> StringOffsets(NumStrings);
for (uint32 iOff = 0; iOff < StringOffsets.size(); iOff++) for (uint32 OffsetIdx = 0; OffsetIdx < NumStrings; OffsetIdx++)
StringOffsets[iOff] = rSTRG.ReadLong(); StringOffsets[OffsetIdx] = STRG.ReadLong();
// Strings // Strings
for (uint32 iStr = 0; iStr < NumStrings; iStr++) for (uint StringIdx = 0; StringIdx < NumStrings; StringIdx++)
{ {
rSTRG.Seek(TableStart + StringOffsets[iStr], SEEK_SET); STRG.GoTo( TableStart + StringOffsets[StringIdx] );
Lang->Strings[iStr] = rSTRG.ReadWString().ToUTF8(); Language.Strings[StringIdx] = STRG.Read16String().ToUTF8();
} }
} }
void CStringLoader::LoadPrimeSTRG(IInputStream& rSTRG) void CStringLoader::LoadPrimeSTRG(IInputStream& STRG)
{ {
// This function starts at 0x8 in the file, after magic/version // This function starts at 0x8 in the file, after magic/version
// Header // Header
uint32 NumLanguages = rSTRG.ReadLong(); uint NumLanguages = STRG.ReadLong();
uint32 NumStrings = rSTRG.ReadLong(); uint NumStrings = STRG.ReadLong();
mpStringTable->mNumStrings = NumStrings;
// Language definitions // Language definitions
mpStringTable->mLangTables.resize(NumLanguages); mpStringTable->mLanguages.resize(NumLanguages);
std::vector<uint32> LangOffsets(NumLanguages); std::vector<uint> LanguageOffsets(NumLanguages);
for (uint32 iLang = 0; iLang < NumLanguages; iLang++) for (uint LanguageIdx = 0; LanguageIdx < NumLanguages; LanguageIdx++)
{ {
mpStringTable->mLangTables[iLang].Language = CFourCC(rSTRG); mpStringTable->mLanguages[LanguageIdx].Language = (ELanguage) STRG.ReadFourCC();
LangOffsets[iLang] = rSTRG.ReadLong(); LanguageOffsets[LanguageIdx] = STRG.ReadLong();
if (mVersion == EGame::Echoes) rSTRG.Seek(0x4, SEEK_CUR); // Skipping strings size
// Skip strings size in MP2
if (mVersion >= EGame::EchoesDemo)
{
STRG.Skip(4);
}
} }
// String names // String names
if (mVersion == EGame::Echoes) if (mVersion >= EGame::EchoesDemo)
LoadNameTable(rSTRG); {
LoadNameTable(STRG);
}
// Strings // Strings
uint32 StringsStart = rSTRG.Tell(); uint StringsStart = STRG.Tell();
for (uint32 iLang = 0; iLang < NumLanguages; iLang++) for (uint32 LanguageIdx = 0; LanguageIdx < NumLanguages; LanguageIdx++)
{ {
rSTRG.Seek(StringsStart + LangOffsets[iLang], SEEK_SET); STRG.GoTo( StringsStart + LanguageOffsets[LanguageIdx] );
if (mVersion == EGame::Prime) rSTRG.Seek(0x4, SEEK_CUR); // Skipping strings size
uint32 LangStart = rSTRG.Tell(); // Skip strings size in MP1
CStringTable::SLangTable* pLang = &mpStringTable->mLangTables[iLang]; if (mVersion == EGame::Prime)
pLang->Strings.resize(NumStrings); {
STRG.Skip(4);
}
CStringTable::SLanguageData& Language = mpStringTable->mLanguages[LanguageIdx];
Language.Strings.resize(NumStrings);
// Offsets // Offsets
std::vector<uint32> StringOffsets(NumStrings); uint LanguageStart = STRG.Tell();
for (uint32 iOff = 0; iOff < NumStrings; iOff++) std::vector<uint> StringOffsets(NumStrings);
StringOffsets[iOff] = rSTRG.ReadLong();
for (uint StringIdx = 0; StringIdx < NumStrings; StringIdx++)
{
StringOffsets[StringIdx] = LanguageStart + STRG.ReadLong();
}
// The actual strings // The actual strings
for (uint32 iStr = 0; iStr < NumStrings; iStr++) for (uint StringIdx = 0; StringIdx < NumStrings; StringIdx++)
{ {
rSTRG.Seek(LangStart + StringOffsets[iStr], SEEK_SET); STRG.GoTo( StringOffsets[StringIdx] );
pLang->Strings[iStr] = rSTRG.ReadWString().ToUTF8(); Language.Strings[StringIdx] = STRG.Read16String().ToUTF8();
} }
} }
} }
void CStringLoader::LoadCorruptionSTRG(IInputStream& rSTRG) void CStringLoader::LoadCorruptionSTRG(IInputStream& STRG)
{ {
// This function starts at 0x8 in the file, after magic/version // This function starts at 0x8 in the file, after magic/version
// Header // Header
uint32 NumLanguages = rSTRG.ReadLong(); uint NumLanguages = STRG.ReadLong();
uint32 NumStrings = rSTRG.ReadLong(); uint NumStrings = STRG.ReadLong();
mpStringTable->mNumStrings = NumStrings;
// String names // String names
LoadNameTable(rSTRG); LoadNameTable(STRG);
// Language definitions // Language definitions
mpStringTable->mLangTables.resize(NumLanguages); mpStringTable->mLanguages.resize(NumLanguages);
std::vector<std::vector<uint32>> LangOffsets(NumLanguages); std::vector< std::vector<uint> > LanguageOffsets(NumLanguages);
for (uint32 iLang = 0; iLang < NumLanguages; iLang++) for (uint LanguageIdx = 0; LanguageIdx < NumLanguages; LanguageIdx++)
mpStringTable->mLangTables[iLang].Language = CFourCC(rSTRG);
for (uint32 iLang = 0; iLang < NumLanguages; iLang++)
{ {
LangOffsets[iLang].resize(NumStrings); mpStringTable->mLanguages[LanguageIdx].Language = (ELanguage) STRG.ReadFourCC();
}
rSTRG.Seek(0x4, SEEK_CUR); // Skipping total string size for (uint LanguageIdx = 0; LanguageIdx < NumLanguages; LanguageIdx++)
{
LanguageOffsets[LanguageIdx].resize(NumStrings);
STRG.Skip(4); // Skipping total string size
for (uint32 iStr = 0; iStr < NumStrings; iStr++) for (uint StringIdx = 0; StringIdx < NumStrings; StringIdx++)
LangOffsets[iLang][iStr] = rSTRG.ReadLong(); {
LanguageOffsets[LanguageIdx][StringIdx] = STRG.ReadLong();
}
} }
// Strings // Strings
uint32 StringsStart = rSTRG.Tell(); uint StringsStart = STRG.Tell();
for (uint32 iLang = 0; iLang < NumLanguages; iLang++) for (uint LanguageIdx = 0; LanguageIdx < NumLanguages; LanguageIdx++)
{ {
CStringTable::SLangTable *pLang = &mpStringTable->mLangTables[iLang]; CStringTable::SLanguageData& Language = mpStringTable->mLanguages[LanguageIdx];
pLang->Strings.resize(NumStrings); Language.Strings.resize(NumStrings);
for (uint32 iStr = 0; iStr < NumStrings; iStr++) for (uint StringIdx = 0; StringIdx < NumStrings; StringIdx++)
{ {
rSTRG.Seek(StringsStart + LangOffsets[iLang][iStr], SEEK_SET); STRG.GoTo( StringsStart + LanguageOffsets[LanguageIdx][StringIdx] );
rSTRG.Seek(0x4, SEEK_CUR); // Skipping string size STRG.Skip(4); // Skipping string size
Language.Strings[StringIdx] = STRG.ReadString();
pLang->Strings[iStr] = rSTRG.ReadString();
} }
} }
} }
void CStringLoader::LoadNameTable(IInputStream& rSTRG) void CStringLoader::LoadNameTable(IInputStream& STRG)
{ {
// Name table header // Name table header
uint32 NameCount = rSTRG.ReadLong(); uint NameCount = STRG.ReadLong();
uint32 NameTableSize = rSTRG.ReadLong(); uint NameTableSize = STRG.ReadLong();
uint32 NameTableStart = rSTRG.Tell(); uint NameTableStart = STRG.Tell();
uint32 NameTableEnd = NameTableStart + NameTableSize; uint NameTableEnd = NameTableStart + NameTableSize;
// Name definitions // Name definitions
struct SNameDef { struct SNameDef {
uint32 NameOffset, StringIndex; uint NameOffset, StringIndex;
}; };
std::vector<SNameDef> NameDefs(NameCount); std::vector<SNameDef> NameDefs(NameCount);
for (uint32 iName = 0; iName < NameCount; iName++) // Keep track of max string index so we can size the names array appropriately.
// Note that it is possible that not every string in the table has a name.
int MaxIndex = -1;
for (uint NameIdx = 0; NameIdx < NameCount; NameIdx++)
{ {
NameDefs[iName].NameOffset = rSTRG.ReadLong() + NameTableStart; NameDefs[NameIdx].NameOffset = STRG.ReadLong() + NameTableStart;
NameDefs[iName].StringIndex = rSTRG.ReadLong(); NameDefs[NameIdx].StringIndex = STRG.ReadLong();
MaxIndex = Math::Max(MaxIndex, (int) NameDefs[NameIdx].StringIndex);
} }
// Name strings // Name strings
mpStringTable->mStringNames.resize(mpStringTable->mNumStrings); mpStringTable->mStringNames.resize(MaxIndex + 1);
for (uint32 iName = 0; iName < NameCount; iName++)
for (uint NameIdx = 0; NameIdx < NameCount; NameIdx++)
{ {
SNameDef *pDef = &NameDefs[iName]; SNameDef& NameDef = NameDefs[NameIdx];
rSTRG.Seek(pDef->NameOffset, SEEK_SET); STRG.GoTo(NameDef.NameOffset);
mpStringTable->mStringNames[pDef->StringIndex] = rSTRG.ReadString(); mpStringTable->mStringNames[NameDef.StringIndex] = STRG.ReadString();
} }
rSTRG.Seek(NameTableEnd, SEEK_SET); STRG.GoTo(NameTableEnd);
} }
// ************ STATIC ************ // ************ STATIC ************
CStringTable* CStringLoader::LoadSTRG(IInputStream& rSTRG, CResourceEntry *pEntry) CStringTable* CStringLoader::LoadSTRG(IInputStream& STRG, CResourceEntry* pEntry)
{ {
// Verify that this is a valid STRG if (!STRG.IsValid()) return nullptr;
if (!rSTRG.IsValid()) return nullptr;
uint32 Magic = rSTRG.ReadLong(); // Verify that this is a valid STRG
uint Magic = STRG.ReadLong();
EGame Version = EGame::Invalid; EGame Version = EGame::Invalid;
if (Magic != 0x87654321) if (Magic != 0x87654321)
{ {
// Check for MP1 Demo STRG format - no magic/version; the first value is actually the filesize // Check for MP1 Demo STRG format - no magic/version; the first value is actually the filesize
// so the best I can do is verify the first value actually points to the end of the file // so the best I can do is verify the first value actually points to the end of the file.
if (Magic <= (uint32) rSTRG.Size()) // The file can have up to 31 padding bytes at the end so we account for that
if (Magic <= (uint) STRG.Size() && Magic > STRG.Size() - 32)
{ {
rSTRG.Seek(Magic, SEEK_SET);
if ((rSTRG.EoF()) || (rSTRG.ReadShort() == 0xFFFF))
Version = EGame::PrimeDemo; Version = EGame::PrimeDemo;
} }
// If not, then we seem to have an invalid file...
if (Version != EGame::PrimeDemo) if (Version != EGame::PrimeDemo)
{ {
errorf("%s: Invalid STRG magic: 0x%08X", *rSTRG.GetSourceString(), Magic); errorf("%s: Invalid STRG magic: 0x%08X", *STRG.GetSourceString(), Magic);
return nullptr; return nullptr;
} }
} }
else else
{ {
uint32 FileVersion = rSTRG.ReadLong(); uint FileVersion = STRG.ReadLong();
Version = GetFormatVersion(FileVersion); Version = GetFormatVersion(FileVersion);
if (Version == EGame::Invalid) if (Version == EGame::Invalid)
{ {
errorf("%s: Unsupported STRG version: 0x%X", *rSTRG.GetSourceString(), FileVersion); errorf("%s: Unrecognized STRG version: 0x%X", *STRG.GetSourceString(), FileVersion);
return nullptr; return nullptr;
} }
} }
@ -197,9 +218,9 @@ CStringTable* CStringLoader::LoadSTRG(IInputStream& rSTRG, CResourceEntry *pEntr
Loader.mpStringTable = new CStringTable(pEntry); Loader.mpStringTable = new CStringTable(pEntry);
Loader.mVersion = Version; Loader.mVersion = Version;
if (Version == EGame::PrimeDemo) Loader.LoadPrimeDemoSTRG(rSTRG); if (Version == EGame::PrimeDemo) Loader.LoadPrimeDemoSTRG(STRG);
else if (Version < EGame::Corruption) Loader.LoadPrimeSTRG(rSTRG); else if (Version < EGame::Corruption) Loader.LoadPrimeSTRG(STRG);
else Loader.LoadCorruptionSTRG(rSTRG); else Loader.LoadCorruptionSTRG(STRG);
return Loader.mpStringTable; return Loader.mpStringTable;
} }

View File

@ -12,14 +12,14 @@ class CStringLoader
EGame mVersion; EGame mVersion;
CStringLoader() {} CStringLoader() {}
void LoadPrimeDemoSTRG(IInputStream& rSTRG); void LoadPrimeDemoSTRG(IInputStream& STRG);
void LoadPrimeSTRG(IInputStream& rSTRG); void LoadPrimeSTRG(IInputStream& STRG);
void LoadCorruptionSTRG(IInputStream& rSTRG); void LoadCorruptionSTRG(IInputStream& STRG);
void LoadNameTable(IInputStream& rSTRG); void LoadNameTable(IInputStream& STRG);
public: public:
static CStringTable* LoadSTRG(IInputStream &rSTRG, CResourceEntry *pEntry); static CStringTable* LoadSTRG(IInputStream& STRG, CResourceEntry* pEntry);
static EGame GetFormatVersion(uint32 Version); static EGame GetFormatVersion(uint Version);
}; };
#endif // CSTRINGLOADER_H #endif // CSTRINGLOADER_H

View File

@ -36,11 +36,11 @@ const ELanguage gkSupportedLanguagesDKCR[] =
}; };
// Utility function - retrieve the index of a given language // Utility function - retrieve the index of a given language
static int FindLanguageIndex(CStringTable* pInTable, ELanguage InLanguage) static int FindLanguageIndex(const CStringTable* pkInTable, ELanguage InLanguage)
{ {
for (uint LanguageIdx = 0; LanguageIdx < pInTable->NumLanguages(); LanguageIdx++) for (uint LanguageIdx = 0; LanguageIdx < pkInTable->NumLanguages(); LanguageIdx++)
{ {
if (pInTable->LanguageByIndex(LanguageIdx) == InLanguage) if (pkInTable->LanguageByIndex(LanguageIdx) == InLanguage)
{ {
return LanguageIdx; return LanguageIdx;
} }
@ -155,7 +155,7 @@ CDependencyTree* CStringTable::BuildDependencyTree() const
// Determine which params are textures based on image type // Determine which params are textures based on image type
TStringList Params = ParamString.Split(","); TStringList Params = ParamString.Split(",");
TString ImageType = Params.front(); TString ImageType = Params.front();
int TexturesStart = -1; uint TexturesStart = 0;
if (ImageType == "A") if (ImageType == "A")
TexturesStart = 2; TexturesStart = 2;
@ -265,7 +265,7 @@ bool CStringTable::IsLanguageSupported(ELanguage Language, EGame Game, ERegion R
pkSupportedLanguages = &gkSupportedLanguagesDKCR[0]; pkSupportedLanguages = &gkSupportedLanguagesDKCR[0];
NumLanguages = ARRAY_SIZE( gkSupportedLanguagesDKCR ); NumLanguages = ARRAY_SIZE( gkSupportedLanguagesDKCR );
} }
ASSERT(pkSupportedLangages); ASSERT(pkSupportedLanguages);
ASSERT(NumLanguages > 0); ASSERT(NumLanguages > 0);
// Check if the requested language is in the array. // Check if the requested language is in the array.

View File

@ -8,7 +8,9 @@
#include <Common/TString.h> #include <Common/TString.h>
#include <vector> #include <vector>
/** A table of localized strings from STRG assets */ /** A table of localized strings from STRG assets.
* Strings are always internally stored as UTF-8.
*/
class CStringTable : public CResource class CStringTable : public CResource
{ {
DECLARE_RESOURCE_TYPE(StringTable) DECLARE_RESOURCE_TYPE(StringTable)

View File

@ -15,7 +15,7 @@ enum class ELanguage
Italian = FOURCC('ITAL'), Italian = FOURCC('ITAL'),
Dutch = FOURCC('DUTC'), // Unused Dutch = FOURCC('DUTC'), // Unused
Japanese = FOURCC('JAPN'), Japanese = FOURCC('JAPN'),
// The rest of these languages were added in Metroid Prime 3 // The rest of these languages were added in Donkey Kong Country Returns
SimplifiedChinese = FOURCC('SCHN'), // Unused SimplifiedChinese = FOURCC('SCHN'), // Unused
TraditionalChinese = FOURCC('TCHN'), // Unused TraditionalChinese = FOURCC('TCHN'), // Unused
UKEnglish = FOURCC('UKEN'), UKEnglish = FOURCC('UKEN'),

View File

@ -33,8 +33,7 @@ CExportGameDialog::CExportGameDialog(const QString& rkIsoPath, const QString& rk
mpUI->setupUi(this); mpUI->setupUi(this);
// Set up disc // Set up disc
TWideString StrPath = TO_TWIDESTRING(rkIsoPath); mpDisc = nod::OpenDiscFromImage(TO_WCHAR(rkIsoPath)).release();
mpDisc = nod::OpenDiscFromImage(*StrPath).release();
if (ValidateGame()) if (ValidateGame())
{ {

View File

@ -164,7 +164,7 @@ void CProjectSettingsDialog::BuildISO()
// Verify this ISO matches the original // Verify this ISO matches the original
bool IsWii; bool IsWii;
pBaseDisc = nod::OpenDiscFromImage(*TO_TWIDESTRING(SourceIsoPath), IsWii); pBaseDisc = nod::OpenDiscFromImage(TO_WCHAR(SourceIsoPath), IsWii);
if (!pBaseDisc || !IsWii) if (!pBaseDisc || !IsWii)
{ {

View File

@ -32,10 +32,12 @@
// Common conversion functions // Common conversion functions
#define TO_QSTRING(Str) UICommon::ToQString(Str) #define TO_QSTRING(Str) UICommon::ToQString(Str)
#define TO_TSTRING(Str) UICommon::ToTString(Str) #define TO_TSTRING(Str) UICommon::ToTString(Str)
#define TO_TWIDESTRING(Str) UICommon::ToTWideString(Str)
#define TO_CCOLOR(Clr) CColor::Integral(Clr.red(), Clr.green(), Clr.blue(), Clr.alpha()) #define TO_CCOLOR(Clr) CColor::Integral(Clr.red(), Clr.green(), Clr.blue(), Clr.alpha())
#define TO_QCOLOR(Clr) QColor(Clr.R * 255, Clr.G * 255, Clr.B * 255, Clr.A * 255) #define TO_QCOLOR(Clr) QColor(Clr.R * 255, Clr.G * 255, Clr.B * 255, Clr.A * 255)
//@todo This name isn't ideal, too similar to ToWChar and so might cause confusion
#define TO_WCHAR(Str) ToWChar( UICommon::ToT16String(Str) )
namespace UICommon namespace UICommon
{ {
@ -47,12 +49,12 @@ bool OpenInExternalApplication(const QString& rkPath);
// TString/TWideString <-> QString // TString/TWideString <-> QString
inline QString ToQString(const TString& rkStr) inline QString ToQString(const TString& rkStr)
{ {
return QString::fromStdString(rkStr.ToStdString()); return QString::fromUtf8(*rkStr);
} }
inline QString ToQString(const TWideString& rkStr) inline QString ToQString(const T16String& rkStr)
{ {
return QString::fromStdWString(rkStr.ToStdString()); return QString::fromUtf16(*rkStr);
} }
inline TString ToTString(const QString& rkStr) inline TString ToTString(const QString& rkStr)
@ -60,9 +62,9 @@ inline TString ToTString(const QString& rkStr)
return TString(rkStr.toStdString()); return TString(rkStr.toStdString());
} }
inline TWideString ToTWideString(const QString& rkStr) inline T16String ToT16String(const QString& rkStr)
{ {
return TWideString(rkStr.toStdWString()); return T16String(rkStr.toStdU16String());
} }
// QFileDialog wrappers // QFileDialog wrappers

View File

@ -1,6 +1,6 @@
#include "WStringPreviewPanel.h" #include "WStringPreviewPanel.h"
#include "Editor/UICommon.h" #include "Editor/UICommon.h"
#include <Core/Resource/CStringTable.h> #include <Core/Resource/StringTable/CStringTable.h>
#include <QFontMetrics> #include <QFontMetrics>
#include <QTextLayout> #include <QTextLayout>
@ -41,7 +41,7 @@ void WStringPreviewPanel::SetResource(CResource *pRes)
for (uint32 iStr = 0; iStr < pString->NumStrings(); iStr++) for (uint32 iStr = 0; iStr < pString->NumStrings(); iStr++)
{ {
QString text = TO_QSTRING(pString->String("ENGL", iStr)); QString text = TO_QSTRING(pString->GetString(ELanguage::English, iStr));
QLabel *pLabel = new QLabel(text, this); QLabel *pLabel = new QLabel(text, this);
pLabel->setWordWrap(true); pLabel->setWordWrap(true);
pLabel->setFrameStyle(QFrame::Plain | QFrame::Box); pLabel->setFrameStyle(QFrame::Plain | QFrame::Box);