Add project to join multiple cheats together

This commit is contained in:
zilmar 2019-04-18 16:57:20 +09:30
parent f0e1b13776
commit 57a0ddcef4
6 changed files with 447 additions and 47 deletions

View File

@ -64,6 +64,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Project64-audio", "Source\P
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UpdateVersion", "Source\UpdateVersion\UpdateVersion.vcxproj", "{1968162C-0793-491D-91A1-81645A24D399}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JoinSettings", "Source\JoinSettings\JoinSettings.vcxproj", "{B2E592F2-F416-4049-BD22-9CA9090242BB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@ -207,6 +209,14 @@ Global
{1968162C-0793-491D-91A1-81645A24D399}.Release|Win32.Build.0 = Release|Win32
{1968162C-0793-491D-91A1-81645A24D399}.Release|x64.ActiveCfg = Release|x64
{1968162C-0793-491D-91A1-81645A24D399}.Release|x64.Build.0 = Release|x64
{B2E592F2-F416-4049-BD22-9CA9090242BB}.Debug|Win32.ActiveCfg = Debug|Win32
{B2E592F2-F416-4049-BD22-9CA9090242BB}.Debug|Win32.Build.0 = Debug|Win32
{B2E592F2-F416-4049-BD22-9CA9090242BB}.Debug|x64.ActiveCfg = Debug|x64
{B2E592F2-F416-4049-BD22-9CA9090242BB}.Debug|x64.Build.0 = Debug|x64
{B2E592F2-F416-4049-BD22-9CA9090242BB}.Release|Win32.ActiveCfg = Release|Win32
{B2E592F2-F416-4049-BD22-9CA9090242BB}.Release|Win32.Build.0 = Release|Win32
{B2E592F2-F416-4049-BD22-9CA9090242BB}.Release|x64.ActiveCfg = Release|x64
{B2E592F2-F416-4049-BD22-9CA9090242BB}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -9,7 +9,8 @@ CIniFileBase::CIniFileBase(CFileBase & FileObject, const char * FileName) :
m_InstantFlush(true),
m_File(FileObject),
m_FileName(FileName),
m_CurrentSectionDirty(false)
m_CurrentSectionDirty(false),
m_SortFunction(NULL)
{
}
@ -243,16 +244,40 @@ void CIniFileBase::SaveCurrentSection(void)
AUTO_PTR<char> LineData(NULL);
int len = 0;
for (KeyValueList::iterator iter = m_CurrentSectionData.begin(); iter != m_CurrentSectionData.end(); iter++)
if (m_SortFunction != NULL)
{
int newLen = (int)iter->first.length() + (int)iter->second.length() + lineFeedLen + 5;
if (newLen > len)
KeyValueVector data;
for (KeyValueList::iterator iter = m_CurrentSectionData.begin(); iter != m_CurrentSectionData.end(); iter++)
{
LineData.reset(new char[newLen]);
len = newLen;
data.push_back(KeyValueItem(&iter->first, &iter->second));
}
m_SortFunction(data);
for (size_t i = 0, n = data.size(); i < n; i++)
{
KeyValueItem & item = data[i];
int newLen = (int)(item.first->length()) + (int)item.second->length() + lineFeedLen + 5;
if (newLen > len)
{
LineData.reset(new char[newLen]);
len = newLen;
}
sprintf(LineData.get(), "%s=%s%s", item.first->c_str(), item.second->c_str(), m_LineFeed);
m_File.Write(LineData.get(), (int)strlen(LineData.get()));
}
}
else
{
for (KeyValueList::iterator iter = m_CurrentSectionData.begin(); iter != m_CurrentSectionData.end(); iter++)
{
int newLen = (int)iter->first.length() + (int)iter->second.length() + lineFeedLen + 5;
if (newLen > len)
{
LineData.reset(new char[newLen]);
len = newLen;
}
sprintf(LineData.get(), "%s=%s%s", iter->first.c_str(), iter->second.c_str(), m_LineFeed);
m_File.Write(LineData.get(), (int)strlen(LineData.get()));
}
sprintf(LineData.get(), "%s=%s%s", iter->first.c_str(), iter->second.c_str(), m_LineFeed);
m_File.Write(LineData.get(), (int)strlen(LineData.get()));
}
}
m_File.Flush();
@ -808,6 +833,12 @@ void CIniFileBase::GetKeyValueData(const char * lpSectionName, KeyValueData & Li
} while (result >= 0);
}
void CIniFileBase::SetCustomSort(SortData SortFunction)
{
CGuard Guard(m_CS);
m_SortFunction = SortFunction;
}
void CIniFileBase::ClearSectionPosList(long FilePos)
{
if (FilePos <= 0)

View File

@ -16,6 +16,47 @@
class CIniFileBase
{
public:
typedef std::map<std::string, std::string> KeyValueData;
typedef std::vector<std::string> SectionList;
typedef std::list<std::string> strlist;
typedef std::pair<const std::string *, const std::string *> KeyValueItem;
typedef std::vector<KeyValueItem> KeyValueVector;
typedef void(*SortData)(KeyValueVector &);
CIniFileBase(CFileBase & FileObject, const char * FileName);
virtual ~CIniFileBase(void);
bool IsEmpty();
bool IsFileOpen(void);
bool DeleteSection(const char * lpSectionName);
bool GetString(const char * lpSectionName, const char * lpKeyName, const char * lpDefault, std::string & Value);
std::string GetString(const char * lpSectionName, const char * lpKeyName, const char * lpDefault);
uint32_t GetString(const char * lpSectionName, const char * lpKeyName, const char * lpDefault, char * lpReturnedString, uint32_t nSize);
uint32_t GetNumber(const char * lpSectionName, const char * lpKeyName, uint32_t nDefault);
bool GetNumber(const char * lpSectionName, const char * lpKeyName, uint32_t nDefault, uint32_t & Value);
virtual void SaveString(const char * lpSectionName, const char * lpKeyName, const char * lpString);
virtual void SaveNumber(const char * lpSectionName, const char * lpKeyName, uint32_t Value);
void SetAutoFlush(bool AutoFlush);
void FlushChanges(void);
bool EntryExists(const char * lpSectionName, const char * lpKeyName);
void GetKeyList(const char * lpSectionName, strlist &List);
void GetKeyValueData(const char * lpSectionName, KeyValueData & List);
void SetCustomSort(SortData SortFunction);
void GetVectorOfSections(SectionList & sections);
const std::string &GetFileName() { return m_FileName; }
protected:
void OpenIniFileReadOnly();
void OpenIniFile(bool bCreate = true);
void SaveCurrentSection(void);
CFileBase & m_File;
std::string m_FileName;
private:
struct insensitive_compare
{
bool operator() (const std::string & a, const std::string & b) const
@ -28,16 +69,6 @@ class CIniFileBase
typedef FILELOC::iterator FILELOC_ITR;
typedef std::map<std::string, std::string, insensitive_compare> KeyValueList;
public:
typedef std::map<std::string, std::string> KeyValueData;
typedef std::vector<std::string> SectionList;
typedef std::list<std::string> strlist;
protected:
CFileBase & m_File;
std::string m_FileName;
private:
std::string m_CurrentSection;
bool m_CurrentSectionDirty;
int m_CurrentSectionFilePos; // Where in the file is the current Section
@ -51,6 +82,7 @@ private:
CriticalSection m_CS;
FILELOC m_SectionsPos;
SortData m_SortFunction;
void fInsertSpaces(int Pos, int NoOfSpaces);
int GetStringFromFile(char * & String, AUTO_PTR<char> &Data, int & MaxDataSize, int & DataSize, int & ReadPos);
@ -58,34 +90,6 @@ private:
const char * CleanLine(char * Line);
void ClearSectionPosList(long FilePos);
protected:
void OpenIniFileReadOnly();
void OpenIniFile(bool bCreate = true);
void SaveCurrentSection(void);
public:
CIniFileBase(CFileBase & FileObject, const char * FileName);
virtual ~CIniFileBase(void);
bool IsEmpty();
bool IsFileOpen(void);
bool DeleteSection(const char * lpSectionName);
bool GetString(const char * lpSectionName, const char * lpKeyName, const char * lpDefault, std::string & Value);
std::string GetString(const char * lpSectionName, const char * lpKeyName, const char * lpDefault);
uint32_t GetString(const char * lpSectionName, const char * lpKeyName, const char * lpDefault, char * lpReturnedString, uint32_t nSize);
uint32_t GetNumber(const char * lpSectionName, const char * lpKeyName, uint32_t nDefault);
bool GetNumber(const char * lpSectionName, const char * lpKeyName, uint32_t nDefault, uint32_t & Value);
virtual void SaveString(const char * lpSectionName, const char * lpKeyName, const char * lpString);
virtual void SaveNumber(const char * lpSectionName, const char * lpKeyName, uint32_t Value);
void SetAutoFlush(bool AutoFlush);
void FlushChanges(void);
bool EntryExists(const char * lpSectionName, const char * lpKeyName);
void GetKeyList(const char * lpSectionName, strlist &List);
void GetKeyValueData(const char * lpSectionName, KeyValueData & List);
void GetVectorOfSections(SectionList & sections);
const std::string &GetFileName() { return m_FileName; }
};
template <class CFileStorage>

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B2E592F2-F416-4049-BD22-9CA9090242BB}</ProjectGuid>
<RootNamespace>JoinSettings</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<ImportGroup Label="PropertySheets">
<Import Project="$(SolutionDir)PropertySheets\Platform.$(Configuration).props" />
</ImportGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ItemDefinitionGroup>
<Link>
<SubSystem>Windows</SubSystem>
</Link>
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Common\Common.vcxproj">
<Project>{b4a4b994-9111-42b1-93c2-6f1ca8bc4421}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -0,0 +1,280 @@
#include <Common/path.h>
#include <Common/IniFileClass.h>
#include <Common/StdString.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 (size_t i = 0, n = Sections.size(); i < n; i++)
{
const char * Section = Sections[i].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("/", "-");
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 (size_t i = 0, n = Sections.size(); i < n; i++)
{
const char * Section = Sections[i].c_str();
const char * pos = strstr(Section, searchStr.c_str());
if (pos == NULL)
{
continue;
}
found = true;
break;
}
if (!found)
{
continue;
}
for (size_t i = 0, n = Sections.size(); i < n; i++)
{
const char * Section = Sections[i].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 (size_t i = 0, n = Sections.size(); i < n; i++)
{
const char * Section = Sections[i].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 Cheats Database\r\n");
TargetIniFile.Write(LineData.c_str(), (int)LineData.length());
LineData = stdstr_f("// Not for use with PJ64 v1.6 or previous\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");
}
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]);
}
return 0;
}