project64/Source/JoinSettings/main.cpp

920 lines
31 KiB
C++

#include <Common/path.h>
#include <Common/IniFile.h>
#include <Common/StdString.h>
#include <Project64-core/N64System/Enhancement/EnhancementFile.h>
#include <algorithm>
#include <set>
#include <windows.h>
struct compareKeyValueItem
{
inline bool operator() (CIniFileBase::KeyValueItem & struct1, const CIniFileBase::KeyValueItem & struct2)
{
std::string a = *struct1.first;
std::string b = *struct2.first;
if (_stricmp(a.c_str(), "Name") == 0)
{
return true;
}
if (_stricmp(b.c_str(), "Name") == 0)
{
return false;
}
if (a.length() > 5 && _strnicmp(a.c_str(), "cheat", 5) == 0 &&
b.length() > 5 && _strnicmp(b.c_str(), "cheat", 5) == 0)
{
int i1 = atoi(&(*struct1.first)[5]);
int i2 = atoi(&(*struct2.first)[5]);
if (i1 != i2)
{
return i1 < i2;
}
char Buffer[40];
int number_len = strlen(_itoa(i1, Buffer, 10));
if (strlen(&a[5 + number_len]) == 0)
{
return true;
}
if (strlen(&b[5 + number_len]) == 0)
{
return false;
}
return _stricmp(&a[5 + number_len], &b[5 + number_len]) <= 0;
}
return _stricmp(a.c_str(), b.c_str()) <= 0;
}
};
void CustomSortData(CIniFileBase::KeyValueVector & data)
{
std::sort(data.begin(), data.end(), compareKeyValueItem());
}
void SplitFile(const char * FileName, const char * Target)
{
if (!CPath(Target,"").DirectoryCreate())
{
return;
}
CPath SearchDir(Target, "*.*");
if (SearchDir.FindFirst())
{
do
{
SearchDir.Delete();
} while (SearchDir.FindNext());
}
CIniFile::SectionList Sections;
CIniFile CheatIniFile(FileName);
CheatIniFile.GetVectorOfSections(Sections);
for (CIniFile::SectionList::const_iterator SectionItr = Sections.begin(); SectionItr != Sections.end(); SectionItr++)
{
const char * Section = SectionItr->c_str();
CIniFile::KeyValueData data;
CheatIniFile.GetKeyValueData(Section, data);
stdstr Name = CheatIniFile.GetString(Section, "Name", "");
Name.Trim("\t =");
if (Name.length() == 0)
{
Name = CheatIniFile.GetString(Section, "Good Name", Section);
Name.Trim("\t =");
}
Name.Replace("\\", "-");
Name.Replace("/", "-");
Name.Replace(":", " -");
if (Name.length() == 0)
{
continue;
}
CPath GameFileName(Target, stdstr_f("%s.%s", Name.c_str(), CPath(FileName).GetExtension().c_str()).c_str());
CIniFile GameIniFile(GameFileName);
if (!GameIniFile.IsFileOpen())
{
continue;
}
GameIniFile.SetAutoFlush(false);
GameIniFile.SetCustomSort(CustomSortData);
for (CIniFile::KeyValueData::const_iterator itr = data.begin(); itr != data.end(); itr++)
{
stdstr DataLine(itr->second);
DataLine.Trim("\t =");
if (strcmp(itr->first.c_str(), "Good Name") == 0)
{
GameIniFile.SaveString(Section, "Name", DataLine.c_str());
}
else
{
GameIniFile.SaveString(Section, itr->first.c_str(), DataLine.c_str());
}
}
GameIniFile.FlushChanges();
}
}
typedef std::map<std::string, std::string> Files;
void RegionSection(CFile &TargetIniFile, Files &files, const char * Region, const char * RegionCode)
{
stdstr_f LineData = stdstr_f("//--------------- %s Region cheat codes ---------------\r\n\r\n", Region);
TargetIniFile.Write(LineData.c_str(), (int)LineData.length());
bool first = true;
for (Files::const_iterator itr = files.begin(); itr != files.end(); itr++)
{
CIniFile GameIniFile(itr->second.c_str());
GameIniFile.SetCustomSort(CustomSortData);
CIniFile::SectionList Sections;
GameIniFile.GetVectorOfSections(Sections);
bool found = false;
stdstr_f searchStr(":%s", RegionCode);
for (CIniFile::SectionList::const_iterator SectionItr = Sections.begin(); SectionItr != Sections.end(); SectionItr++)
{
const char * Section = SectionItr->c_str();
const char * pos = strstr(Section, searchStr.c_str());
if (pos == nullptr)
{
continue;
}
found = true;
break;
}
if (!found)
{
continue;
}
for (CIniFile::SectionList::const_iterator SectionItr = Sections.begin(); SectionItr != Sections.end(); SectionItr++)
{
const char * Section = SectionItr->c_str();
CIniFile::KeyValueData data;
GameIniFile.GetKeyValueData(Section, data);
CIniFile::KeyValueVector data2;
for (CIniFile::KeyValueData::const_iterator DataItr = data.begin(); DataItr != data.end(); DataItr++)
{
data2.push_back(CIniFile::KeyValueItem(&DataItr->first, &DataItr->second));
}
std::sort(data2.begin(), data2.end(), compareKeyValueItem());
if (first)
{
first = false;
}
else
{
LineData = stdstr_f("\r\n//----\r\n\r\n");
TargetIniFile.Write(LineData.c_str(), (int)LineData.length());
}
LineData = stdstr_f("[%s]\r\n", Section);
TargetIniFile.Write(LineData.c_str(), (int)LineData.length());
for (CIniFile::KeyValueVector::const_iterator DataItr = data2.begin(); DataItr != data2.end(); DataItr++)
{
LineData = stdstr_f("%s=%s\r\n", DataItr->first->c_str(), DataItr->second->c_str());
TargetIniFile.Write(LineData.c_str(), (int)LineData.length());
}
}
}
}
void JoinFile(const char * Directory, const char * Target)
{
Files files;
CPath SearchDir(Directory, "*.*");
if (SearchDir.FindFirst())
{
do
{
CIniFile GameIniFile(SearchDir);
CIniFile::SectionList Sections;
GameIniFile.GetVectorOfSections(Sections);
for (CIniFile::SectionList::const_iterator SectionItr = Sections.begin(); SectionItr != Sections.end(); SectionItr++)
{
const char * Section = SectionItr->c_str();
stdstr Name = GameIniFile.GetString(Section, "Name", Section);
Name.Trim("\t =");
if (Name.size() > 0)
{
files.insert(Files::value_type(Name, SearchDir));
break;
}
}
} while (SearchDir.FindNext());
}
if (CPath(Target).Exists())
{
CPath(Target).Delete();
};
CFile TargetIniFile;
if (!TargetIniFile.Open(Target, CFileBase::modeReadWrite | CFileBase::modeCreate | CFileBase::shareDenyWrite))
{
return;
}
if (strcmp(CPath(Target).GetExtension().c_str(), "cht") == 0)
{
stdstr_f LineData = stdstr_f("// Project64 official cheat database\r\n");
TargetIniFile.Write(LineData.c_str(), (int)LineData.length());
LineData = stdstr_f("// Not for use with Project64 v1.6 or lower\r\n");
TargetIniFile.Write(LineData.c_str(), (int)LineData.length());
LineData = stdstr_f("// ----------------------------------------------------\r\n\r\n");
TargetIniFile.Write(LineData.c_str(), (int)LineData.length());
CPath MetaFileName(Directory, "Meta.cht");
CIniFile MetaIniFile(MetaFileName);
if (MetaIniFile.IsFileOpen())
{
CIniFile::KeyValueData data;
MetaIniFile.GetKeyValueData("Meta", data);
LineData = stdstr_f("[Meta]\r\n");
TargetIniFile.Write(LineData.c_str(), (int)LineData.length());
for (CIniFile::KeyValueData::const_iterator itr = data.begin(); itr != data.end(); itr++)
{
stdstr DataLine(itr->second);
DataLine.Trim("\t =");
LineData = stdstr_f("%s=%s\r\n",itr->first.c_str(), DataLine.c_str());
TargetIniFile.Write(LineData.c_str(), (int)LineData.length());
}
LineData = stdstr_f("\r\n");
TargetIniFile.Write(LineData.c_str(), (int)LineData.length());
}
}
RegionSection(TargetIniFile, files, "(J)", "4A");
RegionSection(TargetIniFile, files, "(JU)", "41");
RegionSection(TargetIniFile, files, "(U)", "45");
RegionSection(TargetIniFile, files, "PAL (E)", "50");
RegionSection(TargetIniFile, files, "PAL (A)", "55");
RegionSection(TargetIniFile, files, "PAL (F)", "46");
RegionSection(TargetIniFile, files, "PAL (G)", "44");
RegionSection(TargetIniFile, files, "PAL (I)", "49");
RegionSection(TargetIniFile, files, "PAL (S)", "53");
RegionSection(TargetIniFile, files, "PAL(FGD)", "58");
RegionSection(TargetIniFile, files, "Demo", "0");
}
void UpdateNames(const char* Directory, const char* RdbFile)
{
CIniFile RdbIni(RdbFile);
Files files;
CPath SearchDir(Directory, "*.cht");
if (SearchDir.FindFirst())
{
do
{
CIniFile CheatFile(SearchDir);
CIniFile::SectionList Sections;
CheatFile.GetVectorOfSections(Sections);
CheatFile.SetCustomSort(CustomSortData);
for (CIniFile::SectionList::const_iterator SectionItr = Sections.begin(); SectionItr != Sections.end(); SectionItr++)
{
const char * Section = SectionItr->c_str();
std::string Name = RdbIni.GetString(Section, "Good Name", "");
if (Name.empty())
{
Name = RdbIni.GetString(Section, "Internal Name", "");
}
if (Name.empty())
{
continue;
}
CheatFile.SaveString(Section, "Name", Name.c_str());
}
} while (SearchDir.FindNext());
}
}
uint32_t ConvertXP64Address(uint32_t Address)
{
uint32_t tmpAddress;
tmpAddress = (Address ^ 0x68000000) & 0xFF000000;
tmpAddress += ((Address + 0x002B0000) ^ 0x00810000) & 0x00FF0000;
tmpAddress += ((Address + 0x00002B00) ^ 0x00008200) & 0x0000FF00;
tmpAddress += ((Address + 0x0000002B) ^ 0x00000083) & 0x000000FF;
return tmpAddress;
}
uint8_t ConvertXP64ValueHi(uint8_t Value)
{
return (Value + 0x2B) ^ 0x84;
}
uint8_t ConvertXP64ValueLo(uint8_t Value)
{
return (Value + 0x2B) ^ 0x85;
}
uint16_t ConvertXP64Value(uint16_t Value)
{
uint16_t tmpValue;
tmpValue = ((Value + 0x2B00) ^ 0x8400) & 0xFF00;
tmpValue += ((Value + 0x002B) ^ 0x0085) & 0x00FF;
return tmpValue;
}
bool ConvertCheatOptions(const char * OptionValue, std::string& Options)
{
const char * ReadPos = strchr(Options.c_str(), '$');
std::string NewOptions;
if (ReadPos)
{
ReadPos += 1;
do
{
NewOptions += NewOptions.empty() ? "$" : ",$";
const char* End = strchr(ReadPos, ',');
std::string Item = End != nullptr ? std::string(ReadPos, End - ReadPos) : ReadPos;
ReadPos = strchr(ReadPos, '$');
if (ReadPos != nullptr)
{
ReadPos += 1;
}
const char* Name = strchr(Item.c_str(), ' ');
if (Name == nullptr)
{
return false;
}
Name += 1;
if (strcmp(OptionValue, "????") == 0)
{
uint16_t CodeValue = ConvertXP64Value((uint16_t)strtoul(Item.c_str(), 0, 16));
NewOptions += stdstr_f("%04X %s", CodeValue, stdstr(Name).Trim().c_str());
}
else if (strcmp(OptionValue, "??XX") == 0)
{
uint8_t CodeValue = ConvertXP64ValueHi((uint8_t)strtoul(Item.c_str(), 0, 16));
NewOptions += stdstr_f("%02X %s", CodeValue, stdstr(Name).Trim().c_str());
}
else if (strcmp(OptionValue, "XX??") == 0)
{
uint8_t CodeValue = ConvertXP64ValueLo((uint8_t)strtoul(Item.c_str(), 0, 16));
NewOptions += stdstr_f("%02X %s", CodeValue, stdstr(Name).Trim().c_str());
}
else
{
return false;
}
} while (ReadPos);
}
Options = NewOptions;
return true;
}
bool ConvertCheatEntry(std::string& CheatEntry, std::string& CheatOptions)
{
typedef std::vector<std::string> CodeEntries;
size_t StartOfName = CheatEntry.find("\"");
if (StartOfName == std::string::npos)
{
return false;
}
size_t EndOfName = CheatEntry.find("\"", StartOfName + 1);
if (EndOfName == std::string::npos)
{
return false;
}
std::string Name = stdstr(CheatEntry.substr(StartOfName + 1, EndOfName - StartOfName - 1)).Trim("\t ,");
CodeEntries Entries;
const char* CheatString = &CheatEntry.c_str()[EndOfName + 2];
const char* ReadPos = CheatString;
bool ConvertOptions = false;
std::string OptionValue;
while (ReadPos)
{
uint32_t CodeCommand = strtoul(ReadPos, 0, 16);
ReadPos = strchr(ReadPos, ' ');
if (ReadPos == nullptr)
{
break;
}
ReadPos += 1;
std::string ValueStr = ReadPos;
const char* ValuePos = ReadPos;
ReadPos = strchr(ReadPos, ',');
if (ReadPos != nullptr)
{
ValueStr.resize(ReadPos - ValuePos);
ReadPos++;
}
switch (CodeCommand & 0xFF000000)
{
case 0xE8000000:
CodeCommand = (ConvertXP64Address(CodeCommand) & 0xFFFFFF) | 0x80000000;
if (strchr(ValueStr.c_str(), '?') != nullptr)
{
if (strncmp(ValueStr.c_str(), "????", 4) == 0)
{
Entries.push_back(stdstr_f("%08X ????", CodeCommand));
if (!OptionValue.empty() && OptionValue != "????")
{
return false;
}
OptionValue = "????";
}
else if (ValueStr.length() == 4 && strncmp(&ValueStr.c_str()[2], "??", 2) == 0)
{
Entries.push_back(stdstr_f("%08X %02X??", CodeCommand, ConvertXP64ValueHi((uint8_t)strtoul(ValueStr.c_str(), 0, 16))));
if (!OptionValue.empty() && OptionValue != "XX??")
{
return false;
}
OptionValue = "XX??";
}
else
{
return false;
}
ConvertOptions = true;
}
else
{
Entries.push_back(stdstr_f("%08X %04X", CodeCommand, ConvertXP64Value((uint16_t)strtoul(ValueStr.c_str(), 0, 16))));
}
break;
case 0xE9000000:
CodeCommand = (ConvertXP64Address(CodeCommand) & 0xFFFFFF) | 0x81000000;
if (strchr(ValueStr.c_str(), '?') != nullptr)
{
if (strncmp(ValueStr.c_str(), "????", 4) == 0)
{
Entries.push_back(stdstr_f("%08X ????", CodeCommand));
if (!OptionValue.empty() && OptionValue != "????")
{
return false;
}
OptionValue = "????";
}
else if (ValueStr.length() == 4 && strncmp(&ValueStr.c_str()[2], "??", 2) == 0)
{
Entries.push_back(stdstr_f("%08X %02X??", CodeCommand, ConvertXP64ValueHi((uint8_t)strtoul(ValueStr.c_str(), 0, 16))));
if (!OptionValue.empty() && OptionValue != "XX??")
{
return false;
}
OptionValue = "XX??";
}
else if (ValueStr.length() == 4 && strncmp(&ValueStr.c_str()[0], "??", 2) == 0)
{
Entries.push_back(stdstr_f("%08X ??%02X", CodeCommand, ConvertXP64ValueLo((uint8_t)strtoul(&(ValueStr.c_str()[2]), 0, 16))));
if (!OptionValue.empty() && OptionValue != "??XX")
{
return false;
}
OptionValue = "??XX";
}
else
{
return false;
}
ConvertOptions = true;
}
else
{
Entries.push_back(stdstr_f("%08X %04X", CodeCommand, ConvertXP64Value((uint16_t)strtoul(ValueStr.c_str(), 0, 16))));
}
break;
case 0x10000000:
Entries.push_back(stdstr_f("%08X %s", (CodeCommand & 0xFFFFFF) | 0x80000000, ValueStr.c_str()));
if (strchr(ValueStr.c_str(), '?') != nullptr)
{
if (strncmp(ValueStr.c_str(), "????", 4) == 0)
{
if (!OptionValue.empty() && OptionValue != "????")
{
return false;
}
OptionValue = "????";
}
else if (ValueStr.length() == 4 && strncmp(&ValueStr.c_str()[2], "??", 2) == 0)
{
if (!OptionValue.empty() && OptionValue != "XX??")
{
return false;
}
OptionValue = "XX??";
}
else if (ValueStr.length() == 4 && strncmp(&ValueStr.c_str()[0], "??", 2) == 0)
{
if (!OptionValue.empty() && OptionValue != "??XX")
{
return false;
}
OptionValue = "??XX";
}
else
{
return false;
}
ConvertOptions = true;
}
break;
case 0x11000000:
Entries.push_back(stdstr_f("%08X %s", (CodeCommand & 0xFFFFFF) | 0x81000000, ValueStr.c_str()));
if (strchr(ValueStr.c_str(), '?') != nullptr)
{
if (strncmp(ValueStr.c_str(), "????", 4) == 0)
{
if (!OptionValue.empty() && OptionValue != "????")
{
return false;
}
OptionValue = "????";
}
else if (ValueStr.length() == 4 && strncmp(&ValueStr.c_str()[2], "??", 2) == 0)
{
if (!OptionValue.empty() && OptionValue != "XX??")
{
return false;
}
OptionValue = "XX??";
}
else if (ValueStr.length() == 4 && strncmp(&ValueStr.c_str()[0], "??", 2) == 0)
{
if (!OptionValue.empty() && OptionValue != "??XX")
{
return false;
}
OptionValue = "??XX";
}
else
{
return false;
}
ConvertOptions = true;
return false;
}
break;
case 0x80000000:
case 0x81000000:
case 0x88000000:
case 0x89000000:
case 0xA0000000:
case 0xA1000000:
case 0x50000000:
case 0xD0000000:
case 0xD1000000:
case 0xD2000000:
case 0xD3000000:
Entries.push_back(stdstr_f("%08X %s", CodeCommand, ValueStr.c_str()));
break;
default:
return false;
}
}
if (Name.length() == 0 || Entries.size() == 0)
{
return false;
}
if (ConvertOptions && !ConvertCheatOptions(OptionValue.c_str(), CheatOptions))
{
return false;
}
CheatEntry = stdstr_f("\"%s\"", Name.c_str());
for (CodeEntries::const_iterator itr = Entries.begin(); itr != Entries.end(); itr++)
{
CheatEntry += stdstr_f(",%s", itr->c_str());
}
return true;
}
void convertGS(const char* Directory)
{
enum
{
MaxCheats = 50000,
};
CPath SearchDir(Directory, "*.cht");
if (SearchDir.FindFirst())
{
do
{
CIniFile CheatFile(SearchDir);
CIniFile::SectionList Sections;
CheatFile.GetVectorOfSections(Sections);
CheatFile.SetCustomSort(CustomSortData);
for (CIniFile::SectionList::const_iterator SectionItr = Sections.begin(); SectionItr != Sections.end(); SectionItr++)
{
const char * Section = SectionItr->c_str();
for (uint32_t cheat = 0; cheat < MaxCheats; cheat++)
{
std::string CheatEntry = CheatFile.GetString(Section, stdstr_f("Cheat%d", cheat).c_str(), "");
if (CheatEntry.empty())
{
break;
}
std::string CheatOptions = CheatFile.GetString(Section, stdstr_f("Cheat%d_O", cheat).c_str(), "");
if (ConvertCheatEntry(CheatEntry, CheatOptions))
{
CheatFile.SaveString(Section, stdstr_f("Cheat%d", cheat).c_str(), CheatEntry.c_str());
if (!CheatOptions.empty())
{
CheatFile.SaveString(Section, stdstr_f("Cheat%d_O", cheat).c_str(), CheatOptions.c_str());
}
}
}
}
} while (SearchDir.FindNext());
}
}
bool ParseCheatEntry(const stdstr & CheatEntry, const stdstr& CheatOptions, CEnhancement & Enhancement)
{
size_t StartOfName = CheatEntry.find("\"");
if (StartOfName == std::string::npos)
{
return false;
}
size_t EndOfName = CheatEntry.find("\"", StartOfName + 1);
if (EndOfName == std::string::npos)
{
return false;
}
Enhancement.SetName(CheatEntry.substr(StartOfName + 1, EndOfName - StartOfName - 1).c_str());
const char * CheatString = &CheatEntry.c_str()[EndOfName + 2];
CEnhancement::CodeOptions Options;
std::string OptionValue;
CEnhancement::CodeEntries Entries;
const char * ReadPos = CheatString;
while (ReadPos)
{
uint32_t CodeCommand = strtoul(ReadPos, 0, 16);
ReadPos = strchr(ReadPos, ' ');
if (ReadPos == nullptr)
{
break;
}
ReadPos += 1;
std::string ValueStr = ReadPos;
const char * ValuePos = ReadPos;
ReadPos = strchr(ReadPos, ',');
if (ReadPos != nullptr)
{
ValueStr.resize(ReadPos - ValuePos);
ReadPos++;
}
CEnhancement::CodeEntry Entry;
Entry.Command = CodeCommand;
Entry.Value = ValueStr;
Entries.push_back(Entry);
}
Enhancement.SetEntries(Entries);
uint32_t OptionLen = Enhancement.CodeOptionSize();
if (!CheatOptions.empty())
{
ReadPos = strchr(CheatOptions.c_str(), '$');
if (ReadPos)
{
ReadPos += 1;
do
{
const char* End = strchr(ReadPos, ',');
std::string Item = End != nullptr ? std::string(ReadPos, End - ReadPos) : ReadPos;
ReadPos = strchr(ReadPos, '$');
if (ReadPos != nullptr)
{
ReadPos += 1;
}
const char* Name = strchr(Item.c_str(), ' ');
if (Name == nullptr)
{
return false;
}
if (((uint32_t)(Name - Item.c_str())) != OptionLen)
{
return false;
}
Name += 1;
CEnhancement::CodeOption Option;
Option.Name = stdstr(Name).Trim().c_str();
if (OptionLen == 4)
{
Option.Value = (uint16_t)strtoul(Item.c_str(), 0, 16);
}
else if (OptionLen == 2)
{
Option.Value = (uint8_t)strtoul(Item.c_str(), 0, 16);
}
else
{
return false;
}
Options.push_back(Option);
} while (ReadPos);
}
}
Enhancement.SetOptions(Options);
return true;
}
void ConvertNew(const char * Src, const char * Dest)
{
CPath SrcDir(Src, ""), DestDir(Dest, "");
if (SrcDir == DestDir)
{
return;
}
if (DestDir.DirectoryExists())
{
DestDir.Delete();
};
DestDir.DirectoryCreate();
CPath SearchDir(Src, "*.cht");
if (SearchDir.FindFirst())
{
do
{
CPath OutFile(Dest, SearchDir.GetNameExtension());
if (OutFile.Exists())
{
OutFile.Delete();
}
CEnhancmentFile DstEnhancmentFile(OutFile, "Cheat");
CIniFile SrcIniFile(SearchDir);
CIniFile::SectionList Sections;
SrcIniFile.GetVectorOfSections(Sections);
enum
{
MaxCheats = 50000,
};
for (CIniFile::SectionList::const_iterator SectionItr = Sections.begin(); SectionItr != Sections.end(); SectionItr++)
{
const char * Section = SectionItr->c_str();
std::string GameName = SrcIniFile.GetString(Section, "Name", "");
DstEnhancmentFile.SetName(Section, GameName.c_str());
for (uint32_t cheat = 0; cheat < MaxCheats; cheat++)
{
std::string CheatEntry = SrcIniFile.GetString(Section, stdstr_f("Cheat%d", cheat).c_str(), "");
if (CheatEntry.empty())
{
break;
}
std::string CheatOptions = SrcIniFile.GetString(Section, stdstr_f("Cheat%d_O", cheat).c_str(), "");
CEnhancement Enhancement("Cheat");
if (!ParseCheatEntry(CheatEntry, CheatOptions, Enhancement))
{
continue;
}
std::string CheatNote = SrcIniFile.GetString(Section, stdstr_f("Cheat%d_N", cheat).c_str(), "");
if (!CheatNote.empty())
{
Enhancement.SetNote(CheatNote.c_str());
}
if (!Enhancement.Valid())
{
DebugBreak();
}
DstEnhancmentFile.AddEnhancement(Section, Enhancement);
}
}
} while (SearchDir.FindNext());
}
}
void ConvertOld(const char * Src, const char * Dest)
{
CPath SrcDir(Src, ""), DestDir(Dest, "");
if (SrcDir == DestDir)
{
return;
}
if (DestDir.DirectoryExists())
{
DestDir.Delete();
};
DestDir.DirectoryCreate();
CPath SearchDir(Src, "*.cht");
if (SearchDir.FindFirst())
{
do
{
CPath OutFile(Dest, SearchDir.GetNameExtension());
if (OutFile.Exists())
{
OutFile.Delete();
}
CEnhancmentFile SrcFile(SearchDir, "Cheat");
CEnhancmentFile::SectionList Sections;
SrcFile.GetSections(Sections);
CIniFile DstIniFile(OutFile);
DstIniFile.SetCustomSort(CustomSortData);
for (CIniFile::SectionList::const_iterator SectionItr = Sections.begin(); SectionItr != Sections.end(); SectionItr++)
{
const char * Section = SectionItr->c_str();
std::string GameName;
if (SrcFile.GetName(Section, GameName))
{
DstIniFile.SaveString(Section, "Name", GameName.c_str());
}
CEnhancementList Enhancements;
if (SrcFile.GetEnhancementList(Section, Enhancements))
{
uint32_t CheatEntry = 0;
for (CEnhancementList::const_iterator itr = Enhancements.begin(); itr != Enhancements.end(); itr++)
{
const CEnhancement & Enhancement = itr->second;
if (!Enhancement.Valid())
{
continue;
}
std::string Entry = stdstr_f("\"%s\"", Enhancement.GetName().c_str());
const CEnhancement::CodeEntries & Entries = Enhancement.GetEntries();
for (size_t i = 0, n = Entries.size(); i < n; i++)
{
Entry += stdstr_f(",%X %s", Entries[i].Command, Entries[i].Value.c_str());
}
DstIniFile.SaveString(Section, stdstr_f("Cheat%d", CheatEntry).c_str(), Entry.c_str());
if (!Enhancement.GetNote().empty())
{
DstIniFile.SaveString(Section, stdstr_f("Cheat%d_N", CheatEntry).c_str(), Enhancement.GetNote().c_str());
}
const CEnhancement::CodeOptions & Options = Enhancement.GetOptions();
if (Options.size() > 0)
{
std::string OptionEntry;
for (size_t i = 0, n = Options.size(); i < n; i++)
{
if (!OptionEntry.empty())
{
OptionEntry += ",";
}
OptionEntry += stdstr_f(Enhancement.CodeOptionSize() == 2 ? "$%02X %s" : "$%04X %s", Options[i].Value, Options[i].Name.c_str());
}
DstIniFile.SaveString(Section, stdstr_f("Cheat%d_O", CheatEntry).c_str(), OptionEntry.c_str());
}
CheatEntry += 1;
}
}
}
} while (SearchDir.FindNext());
}
}
int WINAPI WinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR /*lpszArgs*/, int /*nWinMode*/)
{
if (__argc == 4 && strcmp(__argv[1], "-split") == 0 && CPath(__argv[2]).Exists())
{
SplitFile(__argv[2], __argv[3]);
}
if (__argc == 4 && strcmp(__argv[1], "-join") == 0 && CPath(__argv[2],"").DirectoryExists())
{
JoinFile(__argv[2], __argv[3]);
}
if (__argc == 4 && strcmp(__argv[1], "-updateNames") == 0 && CPath(__argv[2], "").DirectoryExists() && CPath(__argv[3]).Exists())
{
UpdateNames(__argv[2], __argv[3]);
}
if (__argc == 3 && strcmp(__argv[1], "-convertGS") == 0 && CPath(__argv[2], "").DirectoryExists())
{
convertGS(__argv[2]);
}
if (__argc == 4 && strcmp(__argv[1], "-convertNew") == 0 && CPath(__argv[2], "").DirectoryExists())
{
ConvertNew(__argv[2], __argv[3]);
}
if (__argc == 4 && strcmp(__argv[1], "-convertOld") == 0 && CPath(__argv[2], "").DirectoryExists())
{
ConvertOld(__argv[2], __argv[3]);
}
return 0;
}