Change the handling of the cheat format
This commit is contained in:
parent
003205f254
commit
7de3fc3348
|
@ -248,6 +248,7 @@ Global
|
|||
{B685BB34-D700-4FCC-8503-9B6AA1A0C95D} = {0E0FCAC2-E128-4886-8EE6-1BCA84551F58}
|
||||
{593B00E6-1987-415D-A62C-26533FC3E95C} = {0E0FCAC2-E128-4886-8EE6-1BCA84551F58}
|
||||
{E8D9A652-A354-4374-B6C5-A51EE62749FD} = {AA8F7F8E-5377-4911-859D-8A8817B0DB26}
|
||||
{D233025A-231F-4A43-92B6-E87193C60ACC} = {0E0FCAC2-E128-4886-8EE6-1BCA84551F58}
|
||||
{DCC841B2-298A-40F0-84D1-ACBABD3B86E8} = {AA8F7F8E-5377-4911-859D-8A8817B0DB26}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
|
|
|
@ -127,4 +127,4 @@ protected:
|
|||
CFileStorage m_FileObject;
|
||||
};
|
||||
|
||||
typedef CIniFileT<CFile> CIniFile;
|
||||
typedef CIniFileT<CFile> CIniFile;
|
||||
|
|
|
@ -30,10 +30,11 @@ strvector stdstr::Tokenize(const char * delimiter) const
|
|||
|
||||
stdstr::size_type lastPos = find_first_not_of(delimiter, 0);
|
||||
stdstr::size_type pos = find_first_of(delimiter, lastPos);
|
||||
size_t DelLen = strlen(delimiter);
|
||||
while (stdstr::npos != pos)
|
||||
{
|
||||
tokens.push_back(substr(lastPos, pos - lastPos));
|
||||
lastPos = pos + 1;
|
||||
lastPos = pos + DelLen;
|
||||
pos = find_first_of(delimiter, lastPos);
|
||||
}
|
||||
if (stdstr::npos != lastPos)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include <Common\path.h>
|
||||
#include <Common\IniFileClass.h>
|
||||
#include <Common\StdString.h>
|
||||
#include <Project64-core\N64System\CheatFile.h>
|
||||
#include <Project64-core\N64System\Enhancement\EnhancementFile.h>
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include <windows.h>
|
||||
|
@ -642,10 +642,8 @@ void convertGS(const char* Directory)
|
|||
|
||||
}
|
||||
|
||||
bool ParseCheatEntry(const stdstr & CheatEntry, const stdstr& CheatOptions, CCheatDetails & Details)
|
||||
bool ParseCheatEntry(const stdstr & CheatEntry, const stdstr& CheatOptions, CEnhancement & Enhancement)
|
||||
{
|
||||
bool HaveOptions;
|
||||
|
||||
size_t StartOfName = CheatEntry.find("\"");
|
||||
if (StartOfName == std::string::npos)
|
||||
{
|
||||
|
@ -656,16 +654,14 @@ bool ParseCheatEntry(const stdstr & CheatEntry, const stdstr& CheatOptions, CChe
|
|||
{
|
||||
return false;
|
||||
}
|
||||
Details.SetName(CheatEntry.substr(StartOfName + 1, EndOfName - StartOfName - 1).c_str());
|
||||
Enhancement.SetName(CheatEntry.substr(StartOfName + 1, EndOfName - StartOfName - 1).c_str());
|
||||
const char * CheatString = &CheatEntry.c_str()[EndOfName + 2];
|
||||
HaveOptions = false;
|
||||
|
||||
const char * ReadPos = CheatString;
|
||||
bool FirstEntry = true;
|
||||
CCheatDetails::CodeEntries Entries;
|
||||
CCheatDetails::CodeOptions Options;
|
||||
CEnhancement::CodeOptions Options;
|
||||
std::string OptionValue;
|
||||
|
||||
CEnhancement::CodeEntries Entries;
|
||||
const char * ReadPos = CheatString;
|
||||
while (ReadPos)
|
||||
{
|
||||
uint32_t CodeCommand = strtoul(ReadPos, 0, 16);
|
||||
|
@ -684,80 +680,16 @@ bool ParseCheatEntry(const stdstr & CheatEntry, const stdstr& CheatOptions, CChe
|
|||
ReadPos++;
|
||||
}
|
||||
|
||||
//validate Code Entry
|
||||
switch (CodeCommand & 0xFF000000)
|
||||
{
|
||||
case 0x80000000:
|
||||
case 0x81000000:
|
||||
case 0x88000000:
|
||||
case 0x89000000:
|
||||
case 0xA0000000:
|
||||
case 0xA1000000:
|
||||
case 0xD0000000:
|
||||
case 0xD1000000:
|
||||
case 0xD2000000:
|
||||
case 0xD3000000:
|
||||
if (strchr(ValueStr.c_str(), '?') != NULL)
|
||||
{
|
||||
if (CheatOptions.empty())
|
||||
{
|
||||
DebugBreak();
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x50000000:
|
||||
if (strchr(ValueStr.c_str(), '?') != NULL)
|
||||
{
|
||||
DebugBreak();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DebugBreak();
|
||||
return false;
|
||||
}
|
||||
|
||||
CCheatDetails::CodeEntry Entry;
|
||||
CEnhancement::CodeEntry Entry;
|
||||
Entry.Command = CodeCommand;
|
||||
Entry.Value = ValueStr;
|
||||
Entries.push_back(Entry);
|
||||
|
||||
FirstEntry = false;
|
||||
}
|
||||
Enhancement.SetEntries(Entries);
|
||||
|
||||
if (!OptionValue.empty())
|
||||
uint32_t OptionLen = Enhancement.CodeOptionSize();
|
||||
if (!CheatOptions.empty())
|
||||
{
|
||||
uint32_t OptionLen = OptionValue == "????" ? 4 : 2;
|
||||
ReadPos = strchr(CheatOptions.c_str(), '$');
|
||||
if (ReadPos)
|
||||
{
|
||||
|
@ -778,36 +710,28 @@ bool ParseCheatEntry(const stdstr & CheatEntry, const stdstr& CheatOptions, CChe
|
|||
}
|
||||
if (((uint32_t)(Name - Item.c_str())) != OptionLen)
|
||||
{
|
||||
DebugBreak();
|
||||
return false;
|
||||
}
|
||||
Name += 1;
|
||||
CCheatDetails::CodeOption Option;
|
||||
CEnhancement::CodeOption Option;
|
||||
Option.Name = stdstr(Name).Trim().c_str();
|
||||
if (OptionValue == "????")
|
||||
if (OptionLen == 4)
|
||||
{
|
||||
Option.Value = (uint16_t)strtoul(Item.c_str(), 0, 16);
|
||||
}
|
||||
else if (OptionValue == "??XX" || OptionValue == "XX??")
|
||||
else if (OptionLen == 2)
|
||||
{
|
||||
Option.Value = (uint8_t)strtoul(Item.c_str(), 0, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugBreak();
|
||||
return false;
|
||||
}
|
||||
Options.push_back(Option);
|
||||
} while (ReadPos);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Details.SetEntries(Entries))
|
||||
{
|
||||
DebugBreak();
|
||||
return false;
|
||||
}
|
||||
Details.SetOptions(Options);
|
||||
Enhancement.SetOptions(Options);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -835,7 +759,7 @@ void ConvertNew(const char * Src, const char * Dest)
|
|||
{
|
||||
OutFile.Delete();
|
||||
}
|
||||
CCheatFile DstCheatFile(OutFile);
|
||||
CEnhancmentFile DstEnhancmentFile(OutFile, "Cheat");
|
||||
|
||||
CIniFile SrcIniFile(SearchDir);
|
||||
CIniFile::SectionList Sections;
|
||||
|
@ -850,7 +774,7 @@ void ConvertNew(const char * Src, const char * Dest)
|
|||
{
|
||||
const char * Section = SectionItr->c_str();
|
||||
std::string GameName = SrcIniFile.GetString(Section, "Name", "");
|
||||
DstCheatFile.SetName(Section, GameName.c_str());
|
||||
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(), "");
|
||||
|
@ -859,17 +783,106 @@ void ConvertNew(const char * Src, const char * Dest)
|
|||
break;
|
||||
}
|
||||
std::string CheatOptions = SrcIniFile.GetString(Section, stdstr_f("Cheat%d_O", cheat).c_str(), "");
|
||||
CCheatDetails Details;
|
||||
if (!ParseCheatEntry(CheatEntry, CheatOptions, Details))
|
||||
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())
|
||||
{
|
||||
Details.SetNote(CheatNote.c_str());
|
||||
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;
|
||||
}
|
||||
DstCheatFile.SetCode(Section, Details);
|
||||
}
|
||||
}
|
||||
} while (SearchDir.FindNext());
|
||||
|
@ -898,5 +911,9 @@ int WINAPI WinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR /
|
|||
{
|
||||
ConvertNew(__argv[2], __argv[3]);
|
||||
}
|
||||
if (__argc == 4 && strcmp(__argv[1], "-convertOld") == 0 && CPath(__argv[2], "").DirectoryExists())
|
||||
{
|
||||
ConvertOld(__argv[2], __argv[3]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <Project64-core/Plugins/PluginClass.h>
|
||||
#include <Project64-core/N64System/N64RomClass.h>
|
||||
#include <Project64-core/N64System/N64DiskClass.h>
|
||||
#include <Project64-core\N64System\Enhancement\Enhancements.h>
|
||||
#include "Settings/SettingType/SettingsType-Application.h"
|
||||
|
||||
static void FixDirectories(void);
|
||||
|
@ -257,6 +258,7 @@ bool AppInit(CNotification * Notify, const char * BaseDirectory, int argc, char
|
|||
return false;
|
||||
}
|
||||
#endif
|
||||
g_Enhancements = new CEnhancements();
|
||||
|
||||
//Create the plugin container
|
||||
WriteTrace(TraceAppInit, TraceInfo, "Create Plugins");
|
||||
|
@ -281,12 +283,13 @@ void AppCleanup(void)
|
|||
WriteTrace(TraceAppCleanup, TraceDebug, "cleaning up global objects");
|
||||
CleanupTrace();
|
||||
|
||||
if (g_Rom) { delete g_Rom; g_Rom = NULL; }
|
||||
if (g_DDRom) { delete g_DDRom; g_DDRom = NULL; }
|
||||
if (g_Disk) { delete g_Disk; g_Disk = NULL; }
|
||||
if (g_Plugins) { delete g_Plugins; g_Plugins = NULL; }
|
||||
if (g_Enhancements) { delete g_Enhancements; g_Enhancements = NULL; }
|
||||
if (g_Rom) { delete g_Rom; g_Rom = NULL; }
|
||||
if (g_DDRom) { delete g_DDRom; g_DDRom = NULL; }
|
||||
if (g_Disk) { delete g_Disk; g_Disk = NULL; }
|
||||
if (g_Plugins) { delete g_Plugins; g_Plugins = NULL; }
|
||||
if (g_Settings) { delete g_Settings; g_Settings = NULL; }
|
||||
if (g_Lang) { delete g_Lang; g_Lang = NULL; }
|
||||
if (g_Lang) { delete g_Lang; g_Lang = NULL; }
|
||||
|
||||
CMipsMemoryVM::FreeReservedMemory();
|
||||
TraceDone();
|
||||
|
|
|
@ -1,605 +0,0 @@
|
|||
/****************************************************************************
|
||||
* *
|
||||
* Project64 - A Nintendo 64 emulator. *
|
||||
* http://www.pj64-emu.com/ *
|
||||
* Copyright (C) 2012 Project64. All rights reserved. *
|
||||
* *
|
||||
* License: *
|
||||
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
||||
* *
|
||||
****************************************************************************/
|
||||
#include "stdafx.h"
|
||||
#include "CheatClass.h"
|
||||
|
||||
#include <Project64-core/Settings/SettingType/SettingsType-Cheats.h>
|
||||
#include <Project64-core/Plugins/GFXPlugin.h>
|
||||
#include <Project64-core/Plugins/AudioPlugin.h>
|
||||
#include <Project64-core/Plugins/RSPPlugin.h>
|
||||
#include <Project64-core/Plugins/ControllerPlugin.h>
|
||||
#include <Project64-core/N64System/SystemGlobals.h>
|
||||
#include <Project64-core/N64System/Recompiler/RecompilerClass.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
CCheats::CCheats(CMipsMemoryVM & MMU) :
|
||||
m_MMU(MMU)
|
||||
{
|
||||
}
|
||||
|
||||
CCheats::~CCheats()
|
||||
{
|
||||
}
|
||||
|
||||
bool CCheats::LoadCode(const stdstr & CheatEntry, SettingID ExtensionSetting, int ExtensionIndex)
|
||||
{
|
||||
//Find the start and end of the name which is surrounded in ""
|
||||
int StartOfName = CheatEntry.find("\"");
|
||||
if (StartOfName == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int EndOfName = CheatEntry.find("\"", StartOfName + 1);
|
||||
if (EndOfName == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const char * CheatString = &CheatEntry.c_str()[EndOfName + 2];
|
||||
if (!IsValid16BitCode(CheatString))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const char * ReadPos = CheatString;
|
||||
CODES Code;
|
||||
while (ReadPos)
|
||||
{
|
||||
GAMESHARK_CODE CodeEntry;
|
||||
|
||||
CodeEntry.Command = strtoul(ReadPos, 0, 16);
|
||||
ReadPos = strchr(ReadPos, ' ');
|
||||
if (ReadPos == NULL) { break; }
|
||||
ReadPos += 1;
|
||||
|
||||
if (strncmp(ReadPos, "????", 4) == 0)
|
||||
{
|
||||
stdstr Extension;
|
||||
if (!g_Settings->LoadStringIndex(ExtensionSetting, ExtensionIndex, Extension) || Extension.length() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
CodeEntry.Value = Extension[0] == '$' ? (uint16_t)strtoul(&Extension[1], 0, 16) : (uint16_t)atol(Extension.c_str());
|
||||
}
|
||||
else if (strncmp(ReadPos, "??", 2) == 0)
|
||||
{
|
||||
stdstr Extension;
|
||||
if (!g_Settings->LoadStringIndex(ExtensionSetting, ExtensionIndex, Extension) || Extension.length() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
CodeEntry.Value = (uint8_t)(strtoul(ReadPos, 0, 16));
|
||||
CodeEntry.Value |= (Extension[0] == '$' ? (uint8_t)strtoul(&Extension[1], 0, 16) : (uint8_t)atol(Extension.c_str())) << 16;
|
||||
}
|
||||
else if (strncmp(&ReadPos[2], "??", 2) == 0)
|
||||
{
|
||||
stdstr Extension;
|
||||
if (!g_Settings->LoadStringIndex(ExtensionSetting, ExtensionIndex, Extension) || Extension.length() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
CodeEntry.Value = (uint16_t)(strtoul(ReadPos, 0, 16) << 16);
|
||||
CodeEntry.Value |= Extension[0] == '$' ? (uint8_t)strtoul(&Extension[1], 0, 16) : (uint8_t)atol(Extension.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
CodeEntry.Value = (uint16_t)strtoul(ReadPos, 0, 16);
|
||||
}
|
||||
Code.push_back(CodeEntry);
|
||||
|
||||
ReadPos = strchr(ReadPos, ',');
|
||||
if (ReadPos == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ReadPos++;
|
||||
}
|
||||
if (Code.size() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_Codes.push_back(Code);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CCheats::LoadEnhancements(void)
|
||||
{
|
||||
if (!g_Settings->LoadBool(Setting_Enhancement))
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < CCheats::MaxCheats; i++)
|
||||
{
|
||||
std::string Name = g_Settings->LoadStringIndex(Enhancement_Name, i);
|
||||
if (Name.length() == 0) { break; }
|
||||
|
||||
if (!g_Settings->LoadBoolIndex(Enhancement_Gameshark, i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
std::string entry = g_Settings->LoadStringIndex(Enhancement_GamesharkCode, i);
|
||||
stdstr_f CheatEntry("\"Enhancement%d\",%s", i, entry.c_str());
|
||||
LoadCode(CheatEntry.c_str(), Default_None, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CCheats::LoadPermCheats(CPlugins * Plugins)
|
||||
{
|
||||
if (g_Settings->LoadBool(Debugger_DisableGameFixes))
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < MaxCheats; i++)
|
||||
{
|
||||
stdstr LineEntry;
|
||||
if (!g_Settings->LoadStringIndex(Rdb_GameCheatFix, i, LineEntry) || LineEntry.empty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
stdstr CheatPlugins;
|
||||
bool LoadEntry = true;
|
||||
if (g_Settings->LoadStringIndex(Rdb_GameCheatFixPlugin, i, CheatPlugins) && !CheatPlugins.empty())
|
||||
{
|
||||
LoadEntry = false;
|
||||
|
||||
strvector PluginList = CheatPlugins.Tokenize(',');
|
||||
for (size_t p = 0, n = PluginList.size(); p < n; p++)
|
||||
{
|
||||
stdstr PluginName = PluginList[p].Trim();
|
||||
if (Plugins->Gfx() != NULL && strstr(Plugins->Gfx()->PluginName(), PluginName.c_str()) != NULL)
|
||||
{
|
||||
LoadEntry = true;
|
||||
break;
|
||||
}
|
||||
if (Plugins->Audio() != NULL && strstr(Plugins->Audio()->PluginName(), PluginName.c_str()) != NULL)
|
||||
{
|
||||
LoadEntry = true;
|
||||
break;
|
||||
}
|
||||
if (Plugins->RSP() != NULL && strstr(Plugins->RSP()->PluginName(), PluginName.c_str()) != NULL)
|
||||
{
|
||||
LoadEntry = true;
|
||||
break;
|
||||
}
|
||||
if (Plugins->Control() != NULL && strstr(Plugins->Control()->PluginName(), PluginName.c_str()) != NULL)
|
||||
{
|
||||
LoadEntry = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (LoadEntry)
|
||||
{
|
||||
stdstr_f CheatEntry("\"PermCheat%d\",%s", i, LineEntry.c_str());
|
||||
LoadCode(CheatEntry.c_str(), Default_None, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CCheats::LoadCheats(bool DisableSelected, CPlugins * Plugins)
|
||||
{
|
||||
ResetCodes();
|
||||
LoadPermCheats(Plugins);
|
||||
LoadEnhancements();
|
||||
|
||||
for (int CheatNo = 0; CheatNo < MaxCheats; CheatNo++)
|
||||
{
|
||||
stdstr LineEntry = g_Settings->LoadStringIndex(Cheat_Entry, CheatNo);
|
||||
if (LineEntry.empty()) { break; }
|
||||
if (!g_Settings->LoadBoolIndex(Cheat_Active, CheatNo))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (DisableSelected)
|
||||
{
|
||||
g_Settings->SaveBoolIndex(Cheat_Active, CheatNo, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
LoadCode(LineEntry, Cheat_Extension, CheatNo);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************************************
|
||||
ConvertXP64Address
|
||||
|
||||
Purpose: Decode encoded XP64 address to physical address
|
||||
Parameters:
|
||||
Returns:
|
||||
Author: Witten
|
||||
|
||||
********************************************************************************************/
|
||||
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;
|
||||
}
|
||||
|
||||
/********************************************************************************************
|
||||
ConvertXP64Value
|
||||
|
||||
Purpose: Decode encoded XP64 value
|
||||
Parameters:
|
||||
Returns:
|
||||
Author: Witten
|
||||
|
||||
********************************************************************************************/
|
||||
uint16_t ConvertXP64Value(uint16_t Value)
|
||||
{
|
||||
uint16_t tmpValue;
|
||||
|
||||
tmpValue = ((Value + 0x2B00) ^ 0x8400) & 0xFF00;
|
||||
tmpValue += ((Value + 0x002B) ^ 0x0085) & 0x00FF;
|
||||
return tmpValue;
|
||||
}
|
||||
|
||||
void CCheats::ApplyCheats()
|
||||
{
|
||||
for (size_t CurrentCheat = 0; CurrentCheat < m_Codes.size(); CurrentCheat++)
|
||||
{
|
||||
CODES & CodeEntry = m_Codes[CurrentCheat];
|
||||
for (size_t CurrentEntry = 0; CurrentEntry < CodeEntry.size();)
|
||||
{
|
||||
ApplyCheatEntry(CodeEntry, CurrentEntry);
|
||||
CurrentEntry += EntrySize(CodeEntry, CurrentEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CCheats::ApplyGSButton()
|
||||
{
|
||||
for (size_t CurrentCheat = 0; CurrentCheat < m_Codes.size(); CurrentCheat++)
|
||||
{
|
||||
const CODES & CodeEntry = m_Codes[CurrentCheat];
|
||||
for (size_t CurrentEntry = 0; CurrentEntry < CodeEntry.size(); CurrentEntry++)
|
||||
{
|
||||
const GAMESHARK_CODE & Code = CodeEntry[CurrentEntry];
|
||||
switch (Code.Command & 0xFF000000) {
|
||||
case 0x88000000:
|
||||
ModifyMemory8(0x80000000 | (Code.Command & 0xFFFFFF), (uint8_t)Code.Value);
|
||||
break;
|
||||
case 0x89000000:
|
||||
ModifyMemory16(0x80000000 | (Code.Command & 0xFFFFFF), Code.Value);
|
||||
break;
|
||||
// Xplorer64
|
||||
case 0xA8000000:
|
||||
ModifyMemory8(0x80000000 | (ConvertXP64Address(Code.Command) & 0xFFFFFF), (uint8_t)ConvertXP64Value(Code.Value));
|
||||
break;
|
||||
case 0xA9000000:
|
||||
ModifyMemory16(0x80000000 | (ConvertXP64Address(Code.Command) & 0xFFFFFF), ConvertXP64Value(Code.Value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CCheats::IsValid16BitCode(const char * CheatString)
|
||||
{
|
||||
const char * ReadPos = CheatString;
|
||||
bool GSButtonCheat = false, FirstEntry = true;
|
||||
|
||||
while (ReadPos)
|
||||
{
|
||||
GAMESHARK_CODE CodeEntry;
|
||||
|
||||
CodeEntry.Command = strtoul(ReadPos, 0, 16);
|
||||
ReadPos = strchr(ReadPos, ' ');
|
||||
if (ReadPos == NULL) { break; }
|
||||
ReadPos += 1;
|
||||
|
||||
//validate Code Entry
|
||||
switch (CodeEntry.Command & 0xFF000000) {
|
||||
case 0x50000000:
|
||||
case 0x80000000:
|
||||
case 0xA0000000:
|
||||
case 0xD0000000:
|
||||
case 0xD2000000:
|
||||
case 0xC8000000:
|
||||
case 0xE8000000:
|
||||
case 0x10000000: // Xplorer64
|
||||
break;
|
||||
case 0x81000000:
|
||||
case 0xA1000000:
|
||||
case 0xD1000000:
|
||||
case 0xD3000000:
|
||||
if (((CodeEntry.Command & 0xFFFFFF) & 1) == 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 0x88000000:
|
||||
case 0xA8000000:
|
||||
if (FirstEntry) { GSButtonCheat = true; }
|
||||
if (!GSButtonCheat) { return false; }
|
||||
break;
|
||||
case 0x89000000:
|
||||
if (FirstEntry) { GSButtonCheat = true; }
|
||||
if (!GSButtonCheat) { return false; }
|
||||
if (((CodeEntry.Command & 0xFFFFFF) & 1) == 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 0xA9000000:
|
||||
if (FirstEntry) { GSButtonCheat = true; }
|
||||
if (!GSButtonCheat) { return false; }
|
||||
if (((ConvertXP64Address(CodeEntry.Command) & 0xFFFFFF) & 1) == 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 0x11000000: // Xplorer64
|
||||
case 0xE9000000:
|
||||
case 0xC9000000:
|
||||
if (((ConvertXP64Address(CodeEntry.Command) & 0xFFFFFF) & 1) == 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
FirstEntry = false;
|
||||
|
||||
ReadPos = strchr(ReadPos, ',');
|
||||
if (ReadPos == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ReadPos++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CCheats::ModifyMemory8(uint32_t Address, uint8_t Value)
|
||||
{
|
||||
MEM_VALUE8 OriginalValue;
|
||||
if (!m_MMU.LB_VAddr(Address, OriginalValue.Original))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (OriginalValue.Original == Value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
OriginalValue.Changed = Value;
|
||||
std::pair<ORIGINAL_VALUES8::iterator, bool> itr = m_OriginalValues8.insert(ORIGINAL_VALUES8::value_type(Address, OriginalValue));
|
||||
m_MMU.SB_VAddr(Address, OriginalValue.Changed);
|
||||
if (g_Recompiler)
|
||||
{
|
||||
g_Recompiler->ClearRecompCode_Virt(Address & ~0xFFF, 0x1000, CRecompiler::Remove_Cheats);
|
||||
}
|
||||
}
|
||||
|
||||
void CCheats::ModifyMemory16(uint32_t Address, uint16_t Value)
|
||||
{
|
||||
MEM_VALUE16 OriginalValue;
|
||||
if (!m_MMU.LH_VAddr(Address, OriginalValue.Original))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (OriginalValue.Original == Value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
OriginalValue.Changed = Value;
|
||||
std::pair<ORIGINAL_VALUES16::iterator, bool> itr = m_OriginalValues16.insert(ORIGINAL_VALUES16::value_type(Address, OriginalValue));
|
||||
m_MMU.SH_VAddr(Address, OriginalValue.Changed);
|
||||
if (g_Recompiler)
|
||||
{
|
||||
g_Recompiler->ClearRecompCode_Virt(Address & ~0xFFF, 0x1000, CRecompiler::Remove_Cheats);
|
||||
}
|
||||
}
|
||||
|
||||
void CCheats::ApplyCheatEntry(CODES & CodeEntry, int32_t CurrentEntry)
|
||||
{
|
||||
if (CurrentEntry < 0 || CurrentEntry >= (int)CodeEntry.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
GAMESHARK_CODE & Code = CodeEntry[CurrentEntry];
|
||||
uint16_t wMemory;
|
||||
uint8_t bMemory;
|
||||
|
||||
switch (Code.Command & 0xFF000000)
|
||||
{
|
||||
case 0x50000000: // Gameshark / AR
|
||||
if ((CurrentEntry + 1) >= (int)CodeEntry.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
const GAMESHARK_CODE & NextCodeEntry = CodeEntry[CurrentEntry + 1];
|
||||
int numrepeats = (Code.Command & 0x0000FF00) >> 8;
|
||||
int offset = Code.Command & 0x000000FF;
|
||||
uint32_t Address;
|
||||
int incr = Code.Value;
|
||||
int i;
|
||||
|
||||
switch (NextCodeEntry.Command & 0xFF000000) {
|
||||
case 0x10000000: // Xplorer64
|
||||
case 0x80000000:
|
||||
Address = 0x80000000 | (NextCodeEntry.Command & 0xFFFFFF);
|
||||
wMemory = NextCodeEntry.Value;
|
||||
for (i = 0; i < numrepeats; i++)
|
||||
{
|
||||
ModifyMemory8(Address, (uint8_t)wMemory);
|
||||
Address += offset;
|
||||
wMemory += (uint16_t)incr;
|
||||
}
|
||||
break;
|
||||
case 0x11000000: // Xplorer64
|
||||
case 0x81000000:
|
||||
Address = 0x80000000 | (NextCodeEntry.Command & 0xFFFFFF);
|
||||
wMemory = NextCodeEntry.Value;
|
||||
for (i = 0; i < numrepeats; i++)
|
||||
{
|
||||
ModifyMemory16(Address, wMemory);
|
||||
Address += offset;
|
||||
wMemory += (uint16_t)incr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x80000000:
|
||||
case 0x30000000:
|
||||
case 0x82000000:
|
||||
case 0x84000000:
|
||||
ModifyMemory8(0x80000000 | (Code.Command & 0xFFFFFF), (uint8_t)Code.Value);
|
||||
break;
|
||||
case 0x81000000:
|
||||
ModifyMemory16(0x80000000 | (Code.Command & 0xFFFFFF), Code.Value);
|
||||
break;
|
||||
case 0xA0000000:
|
||||
ModifyMemory8(0xA0000000 | (Code.Command & 0xFFFFFF), (uint8_t)Code.Value);
|
||||
break;
|
||||
case 0xA1000000:
|
||||
ModifyMemory16(0xA0000000 | (Code.Command & 0xFFFFFF), Code.Value);
|
||||
break;
|
||||
case 0xD0000000:
|
||||
m_MMU.LB_VAddr(0x80000000 | (Code.Command & 0xFFFFFF), bMemory);
|
||||
if (bMemory == Code.Value)
|
||||
{
|
||||
ApplyCheatEntry(CodeEntry, CurrentEntry + 1);
|
||||
}
|
||||
break;
|
||||
case 0xD1000000:
|
||||
m_MMU.LH_VAddr(0x80000000 | (Code.Command & 0xFFFFFF), wMemory);
|
||||
if (wMemory == Code.Value)
|
||||
{
|
||||
ApplyCheatEntry(CodeEntry, CurrentEntry + 1);
|
||||
}
|
||||
break;
|
||||
case 0xD2000000:
|
||||
m_MMU.LB_VAddr(0x80000000 | (Code.Command & 0xFFFFFF), bMemory);
|
||||
if (bMemory != Code.Value)
|
||||
{
|
||||
ApplyCheatEntry(CodeEntry, CurrentEntry + 1);
|
||||
}
|
||||
break;
|
||||
case 0xD3000000:
|
||||
m_MMU.LH_VAddr(0x80000000 | (Code.Command & 0xFFFFFF), wMemory);
|
||||
if (wMemory != Code.Value)
|
||||
{
|
||||
ApplyCheatEntry(CodeEntry, CurrentEntry + 1);
|
||||
}
|
||||
break;
|
||||
case 0x31000000:
|
||||
case 0x83000000:
|
||||
case 0x85000000:
|
||||
ModifyMemory16(0x80000000 | (Code.Command & 0xFFFFFF), Code.Value);
|
||||
break;
|
||||
case 0xE8000000:
|
||||
ModifyMemory8(0x80000000 | (ConvertXP64Address(Code.Command) & 0xFFFFFF), (uint8_t)ConvertXP64Value(Code.Value));
|
||||
break;
|
||||
case 0xE9000000:
|
||||
ModifyMemory16(0x80000000 | (ConvertXP64Address(Code.Command) & 0xFFFFFF), ConvertXP64Value(Code.Value));
|
||||
break;
|
||||
case 0xC8000000:
|
||||
ModifyMemory8(0xA0000000 | (ConvertXP64Address(Code.Command) & 0xFFFFFF), (uint8_t)Code.Value);
|
||||
break;
|
||||
case 0xC9000000:
|
||||
ModifyMemory16(0xA0000000 | (ConvertXP64Address(Code.Command) & 0xFFFFFF), ConvertXP64Value(Code.Value));
|
||||
break;
|
||||
case 0xB8000000:
|
||||
case 0xBA000000:
|
||||
m_MMU.LB_VAddr(0x80000000 | (ConvertXP64Address(Code.Command) & 0xFFFFFF), bMemory);
|
||||
if (bMemory == ConvertXP64Value(Code.Value))
|
||||
{
|
||||
ApplyCheatEntry(CodeEntry, CurrentEntry + 1);
|
||||
}
|
||||
break;
|
||||
case 0xB9000000:
|
||||
case 0xBB000000:
|
||||
m_MMU.LH_VAddr(0x80000000 | (ConvertXP64Address(Code.Command) & 0xFFFFFF), wMemory);
|
||||
if (wMemory == ConvertXP64Value(Code.Value))
|
||||
{
|
||||
ApplyCheatEntry(CodeEntry, CurrentEntry + 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t CCheats::EntrySize(const CODES & CodeEntry, int32_t CurrentEntry)
|
||||
{
|
||||
if (CurrentEntry < 0 || CurrentEntry >= (int)CodeEntry.size())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
const GAMESHARK_CODE & Code = CodeEntry[CurrentEntry];
|
||||
switch (Code.Command & 0xFF000000)
|
||||
{
|
||||
case 0x50000000: // Gameshark / AR
|
||||
if ((CurrentEntry + 1) >= (int)CodeEntry.size())
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (CodeEntry[CurrentEntry + 1].Command & 0xFF000000)
|
||||
{
|
||||
case 0x10000000: // Xplorer64
|
||||
case 0x80000000:
|
||||
case 0x11000000: // Xplorer64
|
||||
case 0x81000000:
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
case 0xD0000000:
|
||||
case 0xD1000000:
|
||||
case 0xD2000000:
|
||||
case 0xD3000000:
|
||||
case 0xB8000000:
|
||||
case 0xB9000000:
|
||||
case 0xBA000000:
|
||||
case 0xBB000000:
|
||||
return EntrySize(CodeEntry, CurrentEntry + 1) + 1;
|
||||
case 0:
|
||||
return MaxGSEntries;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CCheats::ResetCodes(void)
|
||||
{
|
||||
m_Codes.clear();
|
||||
for (ORIGINAL_VALUES8::iterator itr = m_OriginalValues8.begin(); itr != m_OriginalValues8.end(); itr++)
|
||||
{
|
||||
uint8_t CurrentValue;
|
||||
if (m_MMU.LB_VAddr(itr->first, CurrentValue) &&
|
||||
itr->second.Changed == CurrentValue)
|
||||
{
|
||||
m_MMU.SB_VAddr(itr->first, itr->second.Original);
|
||||
}
|
||||
}
|
||||
m_OriginalValues8.clear();
|
||||
|
||||
for (ORIGINAL_VALUES16::iterator itr = m_OriginalValues16.begin(); itr != m_OriginalValues16.end(); itr++)
|
||||
{
|
||||
uint16_t CurrentValue;
|
||||
if (m_MMU.LH_VAddr(itr->first, CurrentValue) &&
|
||||
itr->second.Changed == CurrentValue)
|
||||
{
|
||||
m_MMU.SH_VAddr(itr->first, itr->second.Original);
|
||||
}
|
||||
}
|
||||
m_OriginalValues16.clear();
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
/****************************************************************************
|
||||
* *
|
||||
* Project64 - A Nintendo 64 emulator. *
|
||||
* http://www.pj64-emu.com/ *
|
||||
* Copyright (C) 2012 Project64. All rights reserved. *
|
||||
* *
|
||||
* License: *
|
||||
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
||||
* *
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include "N64RomClass.h"
|
||||
#include <Project64-core/N64System/Mips/MemoryVirtualMem.h>
|
||||
#include <Project64-core/Plugins/PluginClass.h>
|
||||
|
||||
class CCheats
|
||||
{
|
||||
public:
|
||||
CCheats(CMipsMemoryVM & MMU);
|
||||
~CCheats(void);
|
||||
|
||||
enum
|
||||
{
|
||||
MaxCheats = 50000,
|
||||
MaxGSEntries = 100,
|
||||
};
|
||||
|
||||
void ApplyCheats();
|
||||
void ApplyGSButton();
|
||||
void LoadCheats(bool DisableSelected, CPlugins * Plugins);
|
||||
|
||||
static bool IsValid16BitCode(const char * CheatString);
|
||||
|
||||
private:
|
||||
struct GAMESHARK_CODE
|
||||
{
|
||||
uint32_t Command;
|
||||
uint16_t Value;
|
||||
};
|
||||
|
||||
struct MEM_VALUE16
|
||||
{
|
||||
uint16_t Original;
|
||||
uint16_t Changed;
|
||||
};
|
||||
|
||||
struct MEM_VALUE8
|
||||
{
|
||||
uint8_t Original;
|
||||
uint8_t Changed;
|
||||
};
|
||||
|
||||
typedef std::vector<GAMESHARK_CODE> CODES;
|
||||
typedef std::vector<CODES> CODES_ARRAY;
|
||||
typedef std::map<uint32_t, MEM_VALUE16> ORIGINAL_VALUES16;
|
||||
typedef std::map<uint32_t, MEM_VALUE8> ORIGINAL_VALUES8;
|
||||
|
||||
void LoadPermCheats(CPlugins * Plugins);
|
||||
void LoadEnhancements(void);
|
||||
int32_t EntrySize(const CODES & CodeEntry, int32_t CurrentEntry);
|
||||
|
||||
CMipsMemoryVM & m_MMU;
|
||||
CODES_ARRAY m_Codes;
|
||||
ORIGINAL_VALUES16 m_OriginalValues16;
|
||||
ORIGINAL_VALUES8 m_OriginalValues8;
|
||||
|
||||
bool LoadCode(const stdstr & CheatEntry, SettingID ExtensionSetting, int ExtensionIndex);
|
||||
void ApplyCheatEntry(CODES & CodeEntry, int32_t CurrentEntry);
|
||||
void ModifyMemory8(uint32_t Address, uint8_t Value);
|
||||
void ModifyMemory16(uint32_t Address, uint16_t Value);
|
||||
void ResetCodes(void);
|
||||
};
|
|
@ -1,103 +0,0 @@
|
|||
/****************************************************************************
|
||||
* *
|
||||
* Project64 - A Nintendo 64 emulator. *
|
||||
* http://www.pj64-emu.com/ *
|
||||
* Copyright (C) 2012 Project64. All rights reserved. *
|
||||
* *
|
||||
* License: *
|
||||
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
||||
* *
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include <Common\FileClass.h>
|
||||
#include <Common\CriticalSection.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
class CCheatDetails
|
||||
{
|
||||
public:
|
||||
struct CodeEntry
|
||||
{
|
||||
uint32_t Command;
|
||||
std::string Value;
|
||||
};
|
||||
struct CodeOption
|
||||
{
|
||||
std::string Name;
|
||||
uint16_t Value;
|
||||
};
|
||||
typedef std::vector<CodeEntry> CodeEntries;
|
||||
typedef std::vector<CodeOption> CodeOptions;
|
||||
|
||||
CCheatDetails();
|
||||
void SetName(const char * Name);
|
||||
void SetNote(const char * Note);
|
||||
bool SetEntries(const CodeEntries & Entries);
|
||||
void SetOptions(const CodeOptions & Options);
|
||||
|
||||
inline const std::string GetName(void) const { return m_Name; }
|
||||
inline const std::string GetNote(void) const { return m_Note; }
|
||||
inline const CodeEntries & GetEntries(void) const { return m_Entries; }
|
||||
inline const CodeOptions & GetOptions(void) const { return m_Options; }
|
||||
inline uint32_t CodeOptionSize(void) const { return m_CodeOptionSize; }
|
||||
inline bool Valid (void) const { return m_Valid; }
|
||||
|
||||
private:
|
||||
void CheckValid();
|
||||
|
||||
std::string m_Name;
|
||||
std::string m_Note;
|
||||
CodeEntries m_Entries;
|
||||
CodeOptions m_Options;
|
||||
std::string m_OptionValue;
|
||||
uint32_t m_CodeOptionSize;
|
||||
bool m_Valid;
|
||||
};
|
||||
|
||||
class CCheatFile
|
||||
{
|
||||
struct insensitive_compare
|
||||
{
|
||||
bool operator() (const std::string & a, const std::string & b) const
|
||||
{
|
||||
return _stricmp(a.c_str(), b.c_str()) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<std::string, CCheatDetails, insensitive_compare> KeyValueList;
|
||||
typedef std::map<std::string, long> FILELOC;
|
||||
typedef FILELOC::iterator FILELOC_ITR;
|
||||
|
||||
public:
|
||||
CCheatFile(const char * FileName);
|
||||
~CCheatFile();
|
||||
|
||||
void SetName(const char * Section, const char * Name);
|
||||
void SetCode(const char * Section, const CCheatDetails & Details);
|
||||
|
||||
private:
|
||||
CCheatFile();
|
||||
CCheatFile(const CCheatFile&);
|
||||
CCheatFile& operator=(const CCheatFile&);
|
||||
|
||||
void OpenCheatFile(void);
|
||||
bool MoveToSection(const char * lpSectionName, bool ChangeCurrentSection);
|
||||
void SaveCurrentSection(void);
|
||||
int GetStringFromFile(char * & String, std::unique_ptr<char> &Data, int & MaxDataSize, int & DataSize, int & ReadPos);
|
||||
const char * CleanLine(char * Line);
|
||||
|
||||
CriticalSection m_CS;
|
||||
std::string m_CurrentSection;
|
||||
std::string m_SectionName;
|
||||
KeyValueList m_CurrentSectionData;
|
||||
long m_lastSectionSearch;
|
||||
FILELOC m_SectionsPos;
|
||||
int m_CurrentSectionFilePos;
|
||||
bool m_CurrentSectionDirty;
|
||||
bool m_ReadOnly;
|
||||
CFile m_File;
|
||||
std::string m_FileName;
|
||||
const char * m_LineFeed;
|
||||
};
|
|
@ -0,0 +1,376 @@
|
|||
/****************************************************************************
|
||||
* *
|
||||
* Project64 - A Nintendo 64 emulator. *
|
||||
* http://www.pj64-emu.com/ *
|
||||
* Copyright (C) 2012 Project64. All rights reserved. *
|
||||
* *
|
||||
* License: *
|
||||
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
||||
* *
|
||||
****************************************************************************/
|
||||
#include "stdafx.h"
|
||||
#include <Project64-core\N64System\Enhancement\Enhancement.h>
|
||||
#include <Project64-core\Settings\SettingType\SettingsType-GameSetting.h>
|
||||
#include <Project64-core\N64System\SystemGlobals.h>
|
||||
#include <Project64-core\N64System\N64Class.h>
|
||||
|
||||
#pragma warning(disable:4996)
|
||||
|
||||
static std::string GenerateKeyName(const char * Name, const char * Ident, const char * PostIdent)
|
||||
{
|
||||
stdstr KeyName(Name);
|
||||
KeyName.Replace('\\', '_');
|
||||
KeyName.Replace(' ', '_');
|
||||
if (KeyName.empty())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return stdstr_f("%s_%s_%s", Ident, KeyName.c_str(), PostIdent);
|
||||
}
|
||||
|
||||
class CSettingEnhancementActive :
|
||||
public CSettingTypeGame
|
||||
{
|
||||
public:
|
||||
CSettingEnhancementActive(const char * Name, const char * Ident) :
|
||||
CSettingTypeGame("",false)
|
||||
{
|
||||
m_KeyNameIdex = GenerateKeyName(Name, Ident, "Active");
|
||||
}
|
||||
|
||||
bool Active()
|
||||
{
|
||||
if (m_KeyNameIdex.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool Active = false;
|
||||
if (Load(0, Active))
|
||||
{
|
||||
return Active;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetActive(bool Active)
|
||||
{
|
||||
if (m_KeyNameIdex.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
Save(0, Active);
|
||||
Flush();
|
||||
}
|
||||
|
||||
void Delete()
|
||||
{
|
||||
if (m_KeyNameIdex.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
CSettingTypeGame::Delete(0);
|
||||
Flush();
|
||||
}
|
||||
};
|
||||
|
||||
class CSettingEnhancementSelectedOption :
|
||||
public CSettingTypeGame
|
||||
{
|
||||
public:
|
||||
CSettingEnhancementSelectedOption(const char * Name, const char * Ident) :
|
||||
CSettingTypeGame("", false)
|
||||
{
|
||||
m_KeyNameIdex = GenerateKeyName(Name, Ident, "Option");
|
||||
}
|
||||
|
||||
void SetOption(uint16_t Value)
|
||||
{
|
||||
if (m_KeyNameIdex.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
Save(0, (uint32_t)Value);
|
||||
Flush();
|
||||
}
|
||||
|
||||
bool SelectedValue(uint16_t &Value)
|
||||
{
|
||||
uint32_t StoredValue = 0;
|
||||
if (!Load(0, StoredValue))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Value = (uint16_t)(StoredValue & 0xFFFF);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Delete()
|
||||
{
|
||||
if (m_KeyNameIdex.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
CSettingTypeGame::Delete(0);
|
||||
Flush();
|
||||
}
|
||||
};
|
||||
|
||||
CEnhancement::CEnhancement(const char * Ident) :
|
||||
m_Ident(Ident),
|
||||
m_CodeOptionSize(0),
|
||||
m_SelectedOption(0xFFFF0000),
|
||||
m_Active(false),
|
||||
m_Valid(false)
|
||||
{
|
||||
}
|
||||
|
||||
CEnhancement::CEnhancement(const char * Ident, const char * Entry) :
|
||||
m_Ident(Ident),
|
||||
m_CodeOptionSize(0),
|
||||
m_SelectedOption(0xFFFF0000),
|
||||
m_Active(false),
|
||||
m_Valid(false)
|
||||
{
|
||||
stdstr EntryLine(Entry);
|
||||
EntryLine.Replace("\r", "");
|
||||
strvector Lines = EntryLine.Tokenize('\n');
|
||||
if (Lines.size() == 0 || Lines[0].length() < 2 || Lines[0][0] != '$')
|
||||
{
|
||||
return;
|
||||
}
|
||||
uint32_t CurrentLine = 1;
|
||||
m_Name = &(Lines[0][CurrentLine]);
|
||||
m_NameAndExtension = m_Name;
|
||||
|
||||
//key=value
|
||||
while (CurrentLine < Lines.size())
|
||||
{
|
||||
const char * Pos = strchr(Lines[CurrentLine].c_str(), '=');
|
||||
if (Pos == nullptr)
|
||||
{
|
||||
break;
|
||||
}
|
||||
uint32_t Line = CurrentLine;
|
||||
CurrentLine += 1;
|
||||
std::string Key = Lines[Line].c_str();
|
||||
size_t Seperator = Pos - Lines[Line].c_str();
|
||||
if (Seperator >= Key.size())
|
||||
{
|
||||
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||
}
|
||||
Key.resize(Seperator);
|
||||
|
||||
if (stricmp(Key.c_str(), "Note") == 0)
|
||||
{
|
||||
m_Note = &Pos[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
//Gameshark Code
|
||||
while (CurrentLine < Lines.size())
|
||||
{
|
||||
const char * Line = Lines[CurrentLine].c_str();
|
||||
const char * Pos = strchr(Line, ' ');
|
||||
if (strlen(Line) != 13 || Pos == nullptr || (Pos - Line) != 8)
|
||||
{
|
||||
break;
|
||||
}
|
||||
CurrentLine += 1;
|
||||
|
||||
CodeEntry GSEntry;
|
||||
GSEntry.Command = strtoul(Line, 0, 16);
|
||||
GSEntry.Value = &Line[9];
|
||||
m_Entries.push_back(GSEntry);
|
||||
}
|
||||
|
||||
//Options
|
||||
uint32_t OptionSize = 0;
|
||||
while (CurrentLine < Lines.size())
|
||||
{
|
||||
const char * Line = Lines[CurrentLine].c_str();
|
||||
size_t LineLen = strlen(Line);
|
||||
if (((OptionSize != 0 && OptionSize != 2) || LineLen < 4 || Line[2] != ' ') &&
|
||||
((OptionSize != 0 && OptionSize != 4) || LineLen < 6 || Line[4] != ' '))
|
||||
{
|
||||
break;
|
||||
}
|
||||
CurrentLine += 1;
|
||||
if (OptionSize == 0)
|
||||
{
|
||||
OptionSize = Line[2] == ' ' ? 2 : 4;
|
||||
}
|
||||
CodeOption Option;
|
||||
Option.Value = (uint16_t)strtoul(Line, 0, 16);
|
||||
Option.Name = &Line[OptionSize + 1];
|
||||
m_Options.push_back(Option);
|
||||
}
|
||||
|
||||
if (CurrentLine < Lines.size())
|
||||
{
|
||||
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||
}
|
||||
m_Active = CSettingEnhancementActive(m_Name.c_str(), m_Ident.c_str()).Active();
|
||||
uint16_t SelectedValue = 0;
|
||||
if (CSettingEnhancementSelectedOption(m_Name.c_str(), m_Ident.c_str()).SelectedValue(SelectedValue))
|
||||
{
|
||||
m_SelectedOption = SelectedValue;
|
||||
}
|
||||
CheckValid();
|
||||
}
|
||||
|
||||
void CEnhancement::SetName(const char * Name)
|
||||
{
|
||||
CSettingEnhancementActive(m_Name.c_str(), m_Ident.c_str()).Delete();
|
||||
CSettingEnhancementSelectedOption(m_Name.c_str(), m_Ident.c_str()).Delete();
|
||||
m_Name = stdstr(Name != NULL ? Name : "").Trim("\t ,");
|
||||
m_NameAndExtension = m_Name;
|
||||
if (m_Active) { CSettingEnhancementActive(m_Name.c_str(), m_Ident.c_str()).SetActive(true); }
|
||||
if (OptionSelected()) { CSettingEnhancementSelectedOption(m_Name.c_str(), m_Ident.c_str()).SetOption(SelectedOption()); }
|
||||
CheckValid();
|
||||
}
|
||||
|
||||
void CEnhancement::SetNote(const char * Note)
|
||||
{
|
||||
m_Note = Note != NULL ? Note : "";
|
||||
}
|
||||
|
||||
void CEnhancement::SetEntries(const CodeEntries & Entries)
|
||||
{
|
||||
m_Entries = Entries;
|
||||
CheckValid();
|
||||
}
|
||||
|
||||
void CEnhancement::SetOptions(const CodeOptions & Options)
|
||||
{
|
||||
m_Options = Options;
|
||||
CheckValid();
|
||||
}
|
||||
|
||||
void CEnhancement::SetSelectedOption(uint16_t Value)
|
||||
{
|
||||
if (m_Name.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_SelectedOption = Value;
|
||||
CheckValid();
|
||||
CSettingEnhancementSelectedOption(m_Name.c_str(), m_Ident.c_str()).SetOption(Value);
|
||||
}
|
||||
|
||||
void CEnhancement::SetActive(bool Active)
|
||||
{
|
||||
if (m_Name.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_Active = Active;
|
||||
CSettingEnhancementActive(m_Name.c_str(), m_Ident.c_str()).SetActive(m_Active);
|
||||
}
|
||||
|
||||
void CEnhancement::CheckValid(void)
|
||||
{
|
||||
m_Valid = false;
|
||||
m_OptionValue = "";
|
||||
m_CodeOptionSize = 0;
|
||||
|
||||
if (m_Name.empty() || m_Entries.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::string OptionValue;
|
||||
uint32_t CodeOptionSize = 0;
|
||||
for (CodeEntries::const_iterator itr = m_Entries.begin(); itr != m_Entries.end(); itr++)
|
||||
{
|
||||
switch (itr->Command & 0xFF000000)
|
||||
{
|
||||
case 0x80000000:
|
||||
case 0x81000000:
|
||||
case 0x88000000:
|
||||
case 0x89000000:
|
||||
case 0xA0000000:
|
||||
case 0xA1000000:
|
||||
case 0xD0000000:
|
||||
case 0xD1000000:
|
||||
case 0xD2000000:
|
||||
case 0xD3000000:
|
||||
if (strchr(itr->Value.c_str(), '?') != NULL)
|
||||
{
|
||||
if (strncmp(itr->Value.c_str(), "????", 4) == 0)
|
||||
{
|
||||
if (!OptionValue.empty() && OptionValue != "????")
|
||||
{
|
||||
return;
|
||||
}
|
||||
OptionValue = "????";
|
||||
CodeOptionSize = 4;
|
||||
}
|
||||
else if (itr->Value.length() == 4 && strncmp(&itr->Value.c_str()[2], "??", 2) == 0)
|
||||
{
|
||||
if (!OptionValue.empty() && OptionValue != "XX??")
|
||||
{
|
||||
return;
|
||||
}
|
||||
OptionValue = "XX??";
|
||||
CodeOptionSize = 2;
|
||||
}
|
||||
else if (itr->Value.length() == 4 && strncmp(&itr->Value.c_str()[0], "??", 2) == 0)
|
||||
{
|
||||
if (!OptionValue.empty() && OptionValue != "??XX")
|
||||
{
|
||||
return;
|
||||
}
|
||||
OptionValue = "??XX";
|
||||
CodeOptionSize = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x50000000:
|
||||
if (strchr(itr->Value.c_str(), '?') != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (m_Options.size() > 0 && OptionValue.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_OptionValue = OptionValue;
|
||||
m_CodeOptionSize = CodeOptionSize;
|
||||
m_Valid = true;
|
||||
if (m_CodeOptionSize != 0)
|
||||
{
|
||||
std::string CheatValue = "??? - Not Set";
|
||||
if (OptionSelected())
|
||||
{
|
||||
bool found = false;
|
||||
for (size_t i = 0, n = m_Options.size(); i < n; i++)
|
||||
{
|
||||
if (m_Options[i].Value != SelectedOption())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
CheatValue = stdstr_f("$%02X %s", m_Options[i].Value, m_Options[i].Name.c_str());
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
m_SelectedOption = 0xFFFF0000;
|
||||
}
|
||||
}
|
||||
m_NameAndExtension = stdstr_f("%s (=>%s)", m_Name.c_str(), CheatValue.c_str());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/****************************************************************************
|
||||
* *
|
||||
* Project64 - A Nintendo 64 emulator. *
|
||||
* http://www.pj64-emu.com/ *
|
||||
* Copyright (C) 2012 Project64. All rights reserved. *
|
||||
* *
|
||||
* License: *
|
||||
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
||||
* *
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include <Common\stdtypes.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class CEnhancement
|
||||
{
|
||||
public:
|
||||
struct CodeEntry
|
||||
{
|
||||
uint32_t Command;
|
||||
std::string Value;
|
||||
};
|
||||
struct CodeOption
|
||||
{
|
||||
std::string Name;
|
||||
uint16_t Value;
|
||||
};
|
||||
typedef std::vector<CodeEntry> CodeEntries;
|
||||
typedef std::vector<CodeOption> CodeOptions;
|
||||
|
||||
CEnhancement(const char * Ident);
|
||||
CEnhancement(const char * Ident, const char * Entry);
|
||||
void SetName(const char * Name);
|
||||
void SetNote(const char * Note);
|
||||
void SetEntries(const CodeEntries & Entries);
|
||||
void SetOptions(const CodeOptions & Options);
|
||||
void SetSelectedOption(uint16_t Value);
|
||||
void SetActive(bool Active);
|
||||
|
||||
inline const std::string & GetName(void) const { return m_Name; }
|
||||
inline const std::string & GetNameAndExtension(void) const { return m_NameAndExtension; }
|
||||
inline const std::string & GetNote(void) const { return m_Note; }
|
||||
inline const CodeEntries & GetEntries(void) const { return m_Entries; }
|
||||
inline const CodeOptions & GetOptions(void) const { return m_Options; }
|
||||
inline uint32_t CodeOptionSize(void) const { return m_CodeOptionSize; }
|
||||
inline bool Valid(void) const { return m_Valid; }
|
||||
inline bool Active(void) const { return m_Active; }
|
||||
bool OptionSelected() const { return (m_SelectedOption & 0xFFFF0000) == 0; }
|
||||
uint16_t SelectedOption() const { return (uint16_t)(m_SelectedOption & 0xFFFF); }
|
||||
|
||||
private:
|
||||
CEnhancement();
|
||||
CEnhancement& operator=(const CEnhancement&);
|
||||
|
||||
void CheckValid();
|
||||
|
||||
std::string m_Ident;
|
||||
std::string m_Name;
|
||||
std::string m_NameAndExtension;
|
||||
std::string m_Note;
|
||||
CodeEntries m_Entries;
|
||||
CodeOptions m_Options;
|
||||
std::string m_OptionValue;
|
||||
uint32_t m_CodeOptionSize;
|
||||
uint32_t m_SelectedOption;
|
||||
bool m_Active;
|
||||
bool m_Valid;
|
||||
};
|
|
@ -9,120 +9,12 @@
|
|||
* *
|
||||
****************************************************************************/
|
||||
#include "stdafx.h"
|
||||
#include <Project64-core\N64System\CheatFile.h>
|
||||
#include <Project64-core\N64System\Enhancement\EnhancementFile.h>
|
||||
|
||||
#include <Windows.h> // for DebugBreak should be removed
|
||||
#pragma warning(disable:4996)
|
||||
|
||||
CCheatDetails::CCheatDetails() :
|
||||
m_CodeOptionSize(0),
|
||||
m_Valid(false)
|
||||
{
|
||||
}
|
||||
|
||||
void CCheatDetails::SetName(const char * Name)
|
||||
{
|
||||
m_Name = Name != NULL ? Name : "";
|
||||
m_Name = stdstr(m_Name).Trim("\t ,");
|
||||
CheckValid();
|
||||
}
|
||||
|
||||
void CCheatDetails::SetNote(const char * Note)
|
||||
{
|
||||
m_Note = Note != NULL ? Note : "";
|
||||
}
|
||||
|
||||
bool CCheatDetails::SetEntries(const CodeEntries & Entries)
|
||||
{
|
||||
std::string OptionValue;
|
||||
uint32_t CodeOptionSize = 0;
|
||||
for (CodeEntries::const_iterator itr = Entries.begin(); itr != Entries.end(); itr++)
|
||||
{
|
||||
switch (itr->Command & 0xFF000000)
|
||||
{
|
||||
case 0x80000000:
|
||||
case 0x81000000:
|
||||
case 0x88000000:
|
||||
case 0x89000000:
|
||||
case 0xA0000000:
|
||||
case 0xA1000000:
|
||||
case 0xD0000000:
|
||||
case 0xD1000000:
|
||||
case 0xD2000000:
|
||||
case 0xD3000000:
|
||||
if (strchr(itr->Value.c_str(), '?') != NULL)
|
||||
{
|
||||
if (strncmp(itr->Value.c_str(), "????", 4) == 0)
|
||||
{
|
||||
if (!OptionValue.empty() && OptionValue != "????")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
OptionValue = "????";
|
||||
CodeOptionSize = 4;
|
||||
}
|
||||
else if (itr->Value.length() == 4 && strncmp(&itr->Value.c_str()[2], "??", 2) == 0)
|
||||
{
|
||||
if (!OptionValue.empty() && OptionValue != "XX??")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
OptionValue = "XX??";
|
||||
CodeOptionSize = 2;
|
||||
}
|
||||
else if (itr->Value.length() == 4 && strncmp(&itr->Value.c_str()[0], "??", 2) == 0)
|
||||
{
|
||||
if (!OptionValue.empty() && OptionValue != "??XX")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
OptionValue = "??XX";
|
||||
CodeOptionSize = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x50000000:
|
||||
if (strchr(itr->Value.c_str(), '?') != NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
m_Entries = Entries;
|
||||
m_OptionValue = OptionValue;
|
||||
m_CodeOptionSize = CodeOptionSize;
|
||||
CheckValid();
|
||||
return true;
|
||||
}
|
||||
|
||||
void CCheatDetails::SetOptions(const CodeOptions & Options)
|
||||
{
|
||||
m_Options = Options;
|
||||
CheckValid();
|
||||
}
|
||||
|
||||
void CCheatDetails::CheckValid(void)
|
||||
{
|
||||
m_Valid = false;
|
||||
if (m_Name.empty() || m_Entries.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_Options.size() > 0 && m_OptionValue.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_Valid = true;
|
||||
}
|
||||
|
||||
CCheatFile::CCheatFile(const char * FileName) :
|
||||
CEnhancmentFile::CEnhancmentFile(const char * FileName, const char * Ident) :
|
||||
m_Ident(Ident),
|
||||
m_lastSectionSearch(0),
|
||||
m_CurrentSectionFilePos(0),
|
||||
m_CurrentSectionDirty(false),
|
||||
|
@ -130,15 +22,32 @@ CCheatFile::CCheatFile(const char * FileName) :
|
|||
m_FileName(FileName),
|
||||
m_LineFeed("\r\n")
|
||||
{
|
||||
OpenCheatFile();
|
||||
OpenFile();
|
||||
}
|
||||
|
||||
CCheatFile::~CCheatFile()
|
||||
CEnhancmentFile::~CEnhancmentFile()
|
||||
{
|
||||
SaveCurrentSection();
|
||||
}
|
||||
|
||||
void CCheatFile::SetName(const char * Section, const char * Name)
|
||||
void CEnhancmentFile::GetSections(SectionList & sections)
|
||||
{
|
||||
sections.clear();
|
||||
|
||||
CGuard Guard(m_CS);
|
||||
if (!m_File.IsOpen())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MoveToSection(stdstr_f("DoesNotExist%d%d%d", rand(), rand(), rand()).c_str(), false);
|
||||
for (FILELOC::const_iterator iter = m_SectionsPos.begin(); iter != m_SectionsPos.end(); iter++)
|
||||
{
|
||||
sections.insert(iter->first);
|
||||
}
|
||||
}
|
||||
|
||||
void CEnhancmentFile::SetName(const char * Section, const char * Name)
|
||||
{
|
||||
CGuard Guard(m_CS);
|
||||
if (!m_File.IsOpen())
|
||||
|
@ -146,47 +55,95 @@ void CCheatFile::SetName(const char * Section, const char * Name)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!MoveToSection(Section, true))
|
||||
{
|
||||
m_CurrentSection = Section;
|
||||
m_CurrentSectionData.clear();
|
||||
m_CurrentSectionFilePos = -1;
|
||||
}
|
||||
MoveToSection(Section, true);
|
||||
if (strcmp(m_SectionName.c_str(), Name) != 0)
|
||||
{
|
||||
m_SectionName = Name;
|
||||
m_CurrentSectionDirty = false;
|
||||
m_CurrentSectionDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CCheatFile::SetCode(const char * Section, const CCheatDetails & Details)
|
||||
bool CEnhancmentFile::AddEnhancement(const char * Section, const CEnhancement & Details)
|
||||
{
|
||||
CGuard Guard(m_CS);
|
||||
if (!m_File.IsOpen() || m_ReadOnly)
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_CurrentSectionDirty = true;
|
||||
if (!MoveToSection(Section, true))
|
||||
MoveToSection(Section, true);
|
||||
if (AddEnhancement(Details))
|
||||
{
|
||||
m_CurrentSection = Section;
|
||||
m_CurrentSectionData.clear();
|
||||
m_CurrentSectionFilePos = -1;
|
||||
}
|
||||
KeyValueList::iterator itr = m_CurrentSectionData.find(Details.GetName());
|
||||
if (itr != m_CurrentSectionData.end())
|
||||
{
|
||||
itr->second = Details;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
m_CurrentSectionData.insert(KeyValueList::value_type(Details.GetName(), Details));
|
||||
m_CurrentSectionDirty = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CCheatFile::OpenCheatFile(void)
|
||||
bool CEnhancmentFile::GetEnhancementList(const char * Section, CEnhancementList & List)
|
||||
{
|
||||
CGuard Guard(m_CS);
|
||||
if (!m_File.IsOpen())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!MoveToSection(Section, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
List = m_EnhancementList;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CEnhancmentFile::RemoveEnhancements(const char * Section)
|
||||
{
|
||||
CGuard Guard(m_CS);
|
||||
if (!m_File.IsOpen())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!MoveToSection(Section, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (m_EnhancementList.size() > 0)
|
||||
{
|
||||
m_EnhancementList.clear();
|
||||
m_CurrentSectionDirty = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CEnhancmentFile::GetName(const char * Section, std::string &Name)
|
||||
{
|
||||
CGuard Guard(m_CS);
|
||||
if (!m_File.IsOpen())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!MoveToSection(Section, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Name = m_SectionName;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CEnhancmentFile::AddEnhancement(const CEnhancement & Details)
|
||||
{
|
||||
CEnhancementList::iterator itr = m_EnhancementList.FindItem(Details.GetName());
|
||||
if (itr != m_EnhancementList.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_EnhancementList.AddItem(Details);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CEnhancmentFile::OpenFile(void)
|
||||
{
|
||||
m_ReadOnly = false;
|
||||
if (!m_File.Open(m_FileName.c_str(), CFileBase::modeReadWrite | CFileBase::shareDenyWrite))
|
||||
|
@ -206,9 +163,9 @@ void CCheatFile::OpenCheatFile(void)
|
|||
m_File.Seek(0, CFileBase::begin);
|
||||
}
|
||||
|
||||
bool CCheatFile::MoveToSection(const char * lpSectionName, bool ChangeCurrentSection)
|
||||
bool CEnhancmentFile::MoveToSection(const char * Section, bool ChangeCurrentSection)
|
||||
{
|
||||
if (strcmp(lpSectionName, m_CurrentSection.c_str()) == 0)
|
||||
if (strcmp(Section, m_CurrentSection.c_str()) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -216,13 +173,15 @@ bool CCheatFile::MoveToSection(const char * lpSectionName, bool ChangeCurrentSec
|
|||
{
|
||||
SaveCurrentSection();
|
||||
m_CurrentSection = "";
|
||||
m_SectionName.clear();
|
||||
m_EnhancementList.clear();
|
||||
}
|
||||
|
||||
std::unique_ptr<char> Data;
|
||||
char *Input = NULL;
|
||||
int MaxDataSize = 0, DataSize = 0, ReadPos = 0, result;
|
||||
|
||||
FILELOC_ITR iter = m_SectionsPos.find(std::string(lpSectionName));
|
||||
FILELOC_ITR iter = m_SectionsPos.find(std::string(Section));
|
||||
bool bFoundSection = false;
|
||||
if (iter != m_SectionsPos.end())
|
||||
{
|
||||
|
@ -267,14 +226,14 @@ bool CCheatFile::MoveToSection(const char * lpSectionName, bool ChangeCurrentSec
|
|||
m_lastSectionSearch = (m_File.GetPosition() - DataSize) + ReadPos;
|
||||
m_SectionsPos.insert(FILELOC::value_type(CurrentSection, m_lastSectionSearch));
|
||||
|
||||
if (_stricmp(lpSectionName, CurrentSection) != 0)
|
||||
if (_stricmp(Section, CurrentSection) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ChangeCurrentSection)
|
||||
{
|
||||
m_CurrentSection = lpSectionName;
|
||||
m_CurrentSection = Section;
|
||||
m_CurrentSectionFilePos = m_lastSectionSearch;
|
||||
}
|
||||
else
|
||||
|
@ -286,82 +245,103 @@ bool CCheatFile::MoveToSection(const char * lpSectionName, bool ChangeCurrentSec
|
|||
} while (result >= 0);
|
||||
}
|
||||
|
||||
if (!bFoundSection && strcmp(lpSectionName, "default") == 0)
|
||||
{
|
||||
m_SectionsPos.insert(FILELOC::value_type(lpSectionName, 0));
|
||||
if (ChangeCurrentSection)
|
||||
{
|
||||
m_CurrentSection = lpSectionName;
|
||||
m_CurrentSectionFilePos = 0;
|
||||
}
|
||||
m_File.Seek(m_lastSectionSearch, CFileBase::begin);
|
||||
bFoundSection = true;
|
||||
}
|
||||
|
||||
if (bFoundSection && ChangeCurrentSection)
|
||||
{
|
||||
m_CurrentSectionData.clear();
|
||||
/*do
|
||||
do
|
||||
{
|
||||
result = GetStringFromFile(Input, Data, MaxDataSize, DataSize, ReadPos);
|
||||
if (result <= 1) { continue; }
|
||||
if (strlen(CleanLine(Input)) <= 1) { continue; }
|
||||
if (Input[0] == '[') { break; }
|
||||
char * Pos = strchr(Input, '=');
|
||||
if (Pos == NULL) { continue; }
|
||||
char * Value = &Pos[1];
|
||||
|
||||
char * Pos1 = Pos - 1;
|
||||
while (((*Pos1 == ' ') || (*Pos1 == '\t')) && (Pos1 > Input))
|
||||
if (Input[0] == '$')
|
||||
{
|
||||
Pos1--;
|
||||
}
|
||||
Pos1[1] = 0;
|
||||
std::string Entry = Input;
|
||||
do
|
||||
{
|
||||
result = GetStringFromFile(Input, Data, MaxDataSize, DataSize, ReadPos);
|
||||
if (result <= 1 || strlen(CleanLine(Input)) <= 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
Entry += m_LineFeed;
|
||||
Entry += Input;
|
||||
}
|
||||
} while (result >= 0);
|
||||
|
||||
m_CurrentSectionData.insert(KeyValueList::value_type(Input, Value));
|
||||
} while (result >= 0);*/
|
||||
CEnhancement Enhancement(m_Ident.c_str(), Entry.c_str());
|
||||
if (Enhancement.Valid())
|
||||
{
|
||||
AddEnhancement(Enhancement);
|
||||
}
|
||||
}
|
||||
else if (Pos != nullptr)
|
||||
{
|
||||
char * Value = &Pos[1];
|
||||
|
||||
char * Pos1 = Pos - 1;
|
||||
while (((*Pos1 == ' ') || (*Pos1 == '\t')) && (Pos1 > Input))
|
||||
{
|
||||
Pos1--;
|
||||
}
|
||||
Pos1[1] = 0;
|
||||
|
||||
if (stricmp(Input, "Name") == 0)
|
||||
{
|
||||
m_SectionName = Value;
|
||||
}
|
||||
}
|
||||
} while (result >= 0);
|
||||
}
|
||||
|
||||
if (!bFoundSection && ChangeCurrentSection)
|
||||
{
|
||||
m_CurrentSection = Section;
|
||||
m_EnhancementList.clear();
|
||||
m_CurrentSectionFilePos = -1;
|
||||
}
|
||||
return bFoundSection;
|
||||
}
|
||||
|
||||
void CCheatFile::SaveCurrentSection(void)
|
||||
void CEnhancmentFile::SaveCurrentSection(void)
|
||||
{
|
||||
if (!m_CurrentSectionDirty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_CurrentSectionDirty = false;
|
||||
|
||||
std::string Section;
|
||||
if (!m_SectionName.empty())
|
||||
{
|
||||
Section = stdstr_f("Name=%s%s%s", m_SectionName.c_str(), m_LineFeed, m_LineFeed);
|
||||
}
|
||||
for (KeyValueList::iterator iter = m_CurrentSectionData.begin(); iter != m_CurrentSectionData.end(); iter++)
|
||||
for (CEnhancementList::iterator iter = m_EnhancementList.begin(); iter != m_EnhancementList.end(); iter++)
|
||||
{
|
||||
CCheatDetails & details = iter->second;
|
||||
if (details.GetName().empty())
|
||||
CEnhancement & Enhancement = iter->second;
|
||||
if (Enhancement.GetName().empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Section += stdstr_f("$%s%s", details.GetName().c_str(), m_LineFeed);
|
||||
if (!details.GetNote().empty())
|
||||
Section += stdstr_f("$%s%s", Enhancement.GetName().c_str(), m_LineFeed);
|
||||
if (!Enhancement.GetNote().empty())
|
||||
{
|
||||
Section += stdstr_f("Note=%s%s", details.GetNote().c_str(), m_LineFeed);
|
||||
Section += stdstr_f("Note=%s%s", Enhancement.GetNote().c_str(), m_LineFeed);
|
||||
}
|
||||
const CCheatDetails::CodeEntries & Entries = details.GetEntries();
|
||||
const CEnhancement::CodeEntries & Entries = Enhancement.GetEntries();
|
||||
for (size_t i = 0, n = Entries.size(); i < n; i++)
|
||||
{
|
||||
Section += stdstr_f("%08X %s%s", Entries[i].Command, Entries[i].Value.c_str(), m_LineFeed);
|
||||
}
|
||||
const CCheatDetails::CodeOptions & Options = details.GetOptions();
|
||||
const CEnhancement::CodeOptions & Options = Enhancement.GetOptions();
|
||||
for (size_t i = 0, n = Options.size(); i < n; i++)
|
||||
{
|
||||
if (details.CodeOptionSize() == 4)
|
||||
if (Enhancement.CodeOptionSize() == 4)
|
||||
{
|
||||
Section += stdstr_f("%04X %s%s", Options[i].Value, Options[i].Name.c_str(), m_LineFeed);
|
||||
}
|
||||
else if (details.CodeOptionSize() == 2)
|
||||
else if (Enhancement.CodeOptionSize() == 2)
|
||||
{
|
||||
Section += stdstr_f("%02X %s%s", Options[i].Value, Options[i].Name.c_str(), m_LineFeed);
|
||||
}
|
||||
|
@ -390,12 +370,48 @@ void CCheatFile::SaveCurrentSection(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
DebugBreak();
|
||||
int NeededBufferLen = Section.length();
|
||||
int currentLen = 0;
|
||||
|
||||
m_File.Seek(m_CurrentSectionFilePos, CFileBase::begin);
|
||||
|
||||
int MaxDataSize = 0, DataSize = 0, ReadPos = 0, result;
|
||||
std::unique_ptr<char> Data;
|
||||
char *Input = NULL;
|
||||
|
||||
//Skip first line as it is the section name
|
||||
int StartPos = m_CurrentSectionFilePos;
|
||||
int EndPos = StartPos;
|
||||
do
|
||||
{
|
||||
result = GetStringFromFile(Input, Data, MaxDataSize, DataSize, ReadPos);
|
||||
if (result <= 1) { continue; }
|
||||
if (strlen(CleanLine(Input)) <= 1 || Input[0] != '[')
|
||||
{
|
||||
EndPos = ((m_File.GetPosition() - DataSize) + ReadPos);
|
||||
|
||||
continue;
|
||||
}
|
||||
if (Input[0] == '[')
|
||||
{
|
||||
NeededBufferLen += lineFeedLen;
|
||||
}
|
||||
break;
|
||||
} while (result >= 0);
|
||||
currentLen = EndPos - StartPos;
|
||||
|
||||
if (NeededBufferLen != currentLen)
|
||||
{
|
||||
fInsertSpaces(StartPos, NeededBufferLen - currentLen);
|
||||
m_File.Flush();
|
||||
ClearSectionPosList(StartPos);
|
||||
}
|
||||
m_File.Seek(StartPos, CFileBase::begin);
|
||||
}
|
||||
m_File.Write(Section.data(), Section.length());
|
||||
}
|
||||
|
||||
int CCheatFile::GetStringFromFile(char * & String, std::unique_ptr<char> &Data, int & MaxDataSize, int & DataSize, int & ReadPos)
|
||||
int CEnhancmentFile::GetStringFromFile(char * & String, std::unique_ptr<char> & Data, int & MaxDataSize, int & DataSize, int & ReadPos)
|
||||
{
|
||||
enum { BufferIncrease = 0x2000 };
|
||||
if (MaxDataSize == 0)
|
||||
|
@ -463,7 +479,7 @@ int CCheatFile::GetStringFromFile(char * & String, std::unique_ptr<char> &Data,
|
|||
}
|
||||
}
|
||||
|
||||
const char * CCheatFile::CleanLine(char * Line)
|
||||
const char * CEnhancmentFile::CleanLine(char * Line)
|
||||
{
|
||||
char * Pos = Line;
|
||||
|
||||
|
@ -484,7 +500,9 @@ const char * CCheatFile::CleanLine(char * Line)
|
|||
Pos[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pos += 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -499,10 +517,99 @@ const char * CCheatFile::CleanLine(char * Line)
|
|||
}
|
||||
|
||||
//strip any spaces or line feeds from the end of the line
|
||||
for (int count = (int)strlen(&Line[0]) - 1; count >= 0; count--)
|
||||
for (int32_t i = (int32_t)strlen(&Line[0]) - 1; i >= 0; i--)
|
||||
{
|
||||
if (Line[count] != ' ' && Line[count] != '\r') { break; }
|
||||
Line[count] = 0;
|
||||
if (Line[i] != ' ' && Line[i] != '\r')
|
||||
{
|
||||
break;
|
||||
}
|
||||
Line[i] = 0;
|
||||
}
|
||||
return Line;
|
||||
}
|
||||
|
||||
void CEnhancmentFile::fInsertSpaces(int Pos, int NoOfSpaces)
|
||||
{
|
||||
enum { fIS_MvSize = 0x2000 };
|
||||
|
||||
unsigned char Data[fIS_MvSize + 1];
|
||||
int SizeToRead, result;
|
||||
long end, WritePos;
|
||||
|
||||
m_File.Seek(0, CFileBase::end);
|
||||
end = m_File.GetPosition();
|
||||
|
||||
if (NoOfSpaces > 0)
|
||||
{
|
||||
std::string SpaceBuffer = stdstr_f("%*c", NoOfSpaces, ' ');
|
||||
|
||||
do
|
||||
{
|
||||
SizeToRead = end - Pos;
|
||||
if (SizeToRead > fIS_MvSize) { SizeToRead = fIS_MvSize; }
|
||||
if (SizeToRead > 0)
|
||||
{
|
||||
m_File.Seek(SizeToRead * -1, CFileBase::current);
|
||||
WritePos = m_File.GetPosition();
|
||||
memset(Data, 0, sizeof(Data));
|
||||
result = m_File.Read(Data, SizeToRead);
|
||||
m_File.Seek(WritePos, CFileBase::begin);
|
||||
end = WritePos;
|
||||
|
||||
m_File.Write(SpaceBuffer.c_str(), (uint32_t)SpaceBuffer.length());
|
||||
m_File.Write(Data, result);
|
||||
m_File.Seek(WritePos, CFileBase::begin);
|
||||
}
|
||||
} while (SizeToRead > 0);
|
||||
}
|
||||
if (NoOfSpaces < 0)
|
||||
{
|
||||
int ReadPos = Pos + (NoOfSpaces * -1);
|
||||
WritePos = Pos;
|
||||
|
||||
do
|
||||
{
|
||||
SizeToRead = end - ReadPos;
|
||||
if (SizeToRead > fIS_MvSize) { SizeToRead = fIS_MvSize; }
|
||||
m_File.Seek(ReadPos, CFileBase::begin);
|
||||
m_File.Read(Data, SizeToRead);
|
||||
m_File.Seek(WritePos, CFileBase::begin);
|
||||
m_File.Write(Data, SizeToRead);
|
||||
ReadPos += SizeToRead;
|
||||
WritePos += SizeToRead;
|
||||
} while (SizeToRead > 0);
|
||||
|
||||
m_File.Seek(WritePos, CFileBase::begin);
|
||||
std::string SpaceBuffer = stdstr_f("%*c", (NoOfSpaces * -1), ' ');
|
||||
m_File.Write(SpaceBuffer.c_str(), (uint32_t)SpaceBuffer.length());
|
||||
|
||||
m_File.Seek(WritePos, CFileBase::begin);
|
||||
m_File.SetEndOfFile();
|
||||
m_File.Seek(0, CFileBase::begin);
|
||||
}
|
||||
}
|
||||
|
||||
void CEnhancmentFile::ClearSectionPosList(long FilePos)
|
||||
{
|
||||
if (FilePos <= 0)
|
||||
{
|
||||
m_SectionsPos.clear();
|
||||
m_lastSectionSearch = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
FILELOC::iterator iter = m_SectionsPos.begin();
|
||||
while (iter != m_SectionsPos.end())
|
||||
{
|
||||
FILELOC::iterator CurrentIter = iter;
|
||||
iter++;
|
||||
long TestFilePos = CurrentIter->second;
|
||||
if (TestFilePos > FilePos)
|
||||
{
|
||||
m_SectionsPos.erase(CurrentIter);
|
||||
}
|
||||
}
|
||||
m_lastSectionSearch = FilePos;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/****************************************************************************
|
||||
* *
|
||||
* Project64 - A Nintendo 64 emulator. *
|
||||
* http://www.pj64-emu.com/ *
|
||||
* Copyright (C) 2012 Project64. All rights reserved. *
|
||||
* *
|
||||
* License: *
|
||||
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
||||
* *
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include <Project64-core\N64System\Enhancement\Enhancement.h>
|
||||
#include <Project64-core\N64System\Enhancement\EnhancementList.h>
|
||||
#include <Common\FileClass.h>
|
||||
#include <Common\CriticalSection.h>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
class CEnhancmentFile
|
||||
{
|
||||
struct insensitive_compare
|
||||
{
|
||||
bool operator() (const std::string & a, const std::string & b) const
|
||||
{
|
||||
return _stricmp(a.c_str(), b.c_str()) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<std::string, long> FILELOC;
|
||||
typedef FILELOC::iterator FILELOC_ITR;
|
||||
|
||||
public:
|
||||
typedef std::set<std::string> SectionList;
|
||||
|
||||
CEnhancmentFile(const char * FileName, const char * Ident);
|
||||
~CEnhancmentFile();
|
||||
|
||||
void SetName(const char * Section, const char * Name);
|
||||
bool AddEnhancement(const char * Section, const CEnhancement & Details);
|
||||
void SaveCurrentSection(void);
|
||||
|
||||
bool GetName(const char * Section, std::string & Name);
|
||||
bool GetEnhancementList(const char * Section, CEnhancementList & List);
|
||||
bool RemoveEnhancements(const char * Section);
|
||||
|
||||
void GetSections(SectionList & sections);
|
||||
|
||||
const char * FileName(void) const { return m_FileName.c_str(); }
|
||||
|
||||
private:
|
||||
CEnhancmentFile();
|
||||
CEnhancmentFile(const CEnhancmentFile&);
|
||||
CEnhancmentFile& operator=(const CEnhancmentFile&);
|
||||
|
||||
bool AddEnhancement(const CEnhancement & Details);
|
||||
void OpenFile(void);
|
||||
bool MoveToSection(const char * Section, bool ChangeCurrentSection);
|
||||
int GetStringFromFile(char * & String, std::unique_ptr<char> & Data, int & MaxDataSize, int & DataSize, int & ReadPos);
|
||||
const char * CleanLine(char * Line);
|
||||
void fInsertSpaces(int32_t Pos, int32_t NoOfSpaces);
|
||||
void ClearSectionPosList(long FilePos);
|
||||
|
||||
CriticalSection m_CS;
|
||||
std::string m_Ident;
|
||||
std::string m_CurrentSection;
|
||||
std::string m_SectionName;
|
||||
CEnhancementList m_EnhancementList;
|
||||
FILELOC m_SectionsPos;
|
||||
int32_t m_lastSectionSearch;
|
||||
int32_t m_CurrentSectionFilePos;
|
||||
bool m_CurrentSectionDirty;
|
||||
bool m_ReadOnly;
|
||||
CFile m_File;
|
||||
std::string m_FileName;
|
||||
const char * m_LineFeed;
|
||||
};
|
|
@ -0,0 +1,36 @@
|
|||
/****************************************************************************
|
||||
* *
|
||||
* Project64 - A Nintendo 64 emulator. *
|
||||
* http://www.pj64-emu.com/ *
|
||||
* Copyright (C) 2012 Project64. All rights reserved. *
|
||||
* *
|
||||
* License: *
|
||||
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
||||
* *
|
||||
****************************************************************************/
|
||||
#include "stdafx.h"
|
||||
#include <Project64-core\N64System\Enhancement\EnhancementList.h>
|
||||
|
||||
CEnhancementList::CEnhancementList()
|
||||
{
|
||||
}
|
||||
|
||||
void CEnhancementList::AddItem(const CEnhancement & Details)
|
||||
{
|
||||
insert(value_type(Details.GetName(), Details));
|
||||
//push_back(std::pair<std::string, CEnhancement>(Details.GetName(), Details));
|
||||
}
|
||||
|
||||
CEnhancementList::iterator CEnhancementList::FindItem(const std::string & Name)
|
||||
{
|
||||
return find(Name);
|
||||
/*iterator itr = end();
|
||||
for (iterator itr2 = begin(); itr2 != end(); itr2++)
|
||||
{
|
||||
if (itr2->first == Name)
|
||||
{
|
||||
itr = itr2;
|
||||
}
|
||||
}
|
||||
return itr;*/
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/****************************************************************************
|
||||
* *
|
||||
* Project64 - A Nintendo 64 emulator. *
|
||||
* http://www.pj64-emu.com/ *
|
||||
* Copyright (C) 2012 Project64. All rights reserved. *
|
||||
* *
|
||||
* License: *
|
||||
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
||||
* *
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <Project64-core\N64System\Enhancement\Enhancement.h>
|
||||
|
||||
struct EnhancementItemList_compare
|
||||
{
|
||||
bool operator() (const std::string & a, const std::string & b) const
|
||||
{
|
||||
return _stricmp(a.c_str(), b.c_str()) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
class CEnhancementList :
|
||||
public std::map<std::string, CEnhancement, EnhancementItemList_compare>
|
||||
{
|
||||
public:
|
||||
CEnhancementList();
|
||||
|
||||
void AddItem(const CEnhancement & Details);
|
||||
iterator FindItem(const std::string & Name);
|
||||
};
|
|
@ -0,0 +1,524 @@
|
|||
/****************************************************************************
|
||||
* *
|
||||
* Project64 - A Nintendo 64 emulator. *
|
||||
* http://www.pj64-emu.com/ *
|
||||
* Copyright (C) 2012 Project64. All rights reserved. *
|
||||
* *
|
||||
* License: *
|
||||
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
||||
* *
|
||||
****************************************************************************/
|
||||
#include "stdafx.h"
|
||||
#include <Project64-core\N64System\Enhancement\Enhancements.h>
|
||||
#include <Project64-core\N64System\Enhancement\EnhancementFile.h>
|
||||
#include <Project64-core\N64System\Mips\MemoryVirtualMem.h>
|
||||
#include <Project64-core\N64System\Recompiler\RecompilerClass.h>
|
||||
#include <Project64-core\N64System\SystemGlobals.h>
|
||||
#include <Common\path.h>
|
||||
#include <Common\Util.h>
|
||||
|
||||
CEnhancements::CEnhancements() :
|
||||
m_ScanFileThread(stScanFileThread),
|
||||
m_Scan(true),
|
||||
m_Scanned(false),
|
||||
m_UpdateCheats(false)
|
||||
{
|
||||
m_ScanFileThread.Start(this);
|
||||
g_Settings->RegisterChangeCB(Game_IniKey, this, stGameChanged);
|
||||
}
|
||||
|
||||
CEnhancements::~CEnhancements()
|
||||
{
|
||||
g_Settings->UnregisterChangeCB(Game_IniKey, this, stGameChanged);
|
||||
m_Scan = false;
|
||||
WaitScanDone();
|
||||
}
|
||||
|
||||
void CEnhancements::ApplyActive(CMipsMemoryVM & MMU, bool UpdateChanges)
|
||||
{
|
||||
CGuard Guard(m_CS);
|
||||
if (m_UpdateCheats && UpdateChanges)
|
||||
{
|
||||
m_UpdateCheats = false;
|
||||
LoadCheats(&MMU);
|
||||
}
|
||||
for (size_t i = 0, n = m_ActiveCodes.size(); i < n; i++)
|
||||
{
|
||||
CODES & CodeEntry = m_ActiveCodes[i];
|
||||
for (uint32_t CurrentEntry = 0; CurrentEntry < CodeEntry.size();)
|
||||
{
|
||||
ApplyGameSharkCodes(MMU, CodeEntry, CurrentEntry);
|
||||
CurrentEntry += EntrySize(CodeEntry, CurrentEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CEnhancements::ApplyGSButton(CMipsMemoryVM & MMU, bool UpdateChanges)
|
||||
{
|
||||
for (size_t i = 0, n = m_ActiveCodes.size(); i < n; i++)
|
||||
{
|
||||
CODES & CodeEntry = m_ActiveCodes[i];
|
||||
for (size_t CurrentEntry = 0; CurrentEntry < CodeEntry.size(); CurrentEntry++)
|
||||
{
|
||||
const GAMESHARK_CODE & Code = CodeEntry[CurrentEntry];
|
||||
switch (Code.Command & 0xFF000000) {
|
||||
case 0x88000000:
|
||||
ModifyMemory8(MMU, 0x80000000 | (Code.Command & 0xFFFFFF), (uint8_t)Code.Value);
|
||||
break;
|
||||
case 0x89000000:
|
||||
ModifyMemory16(MMU, 0x80000000 | (Code.Command & 0xFFFFFF), Code.Value);
|
||||
break;
|
||||
// Xplorer64
|
||||
case 0xA8000000:
|
||||
ModifyMemory8(MMU, 0x80000000 | (ConvertXP64Address(Code.Command) & 0xFFFFFF), (uint8_t)ConvertXP64Value(Code.Value));
|
||||
break;
|
||||
case 0xA9000000:
|
||||
ModifyMemory16(MMU, 0x80000000 | (ConvertXP64Address(Code.Command) & 0xFFFFFF), ConvertXP64Value(Code.Value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CEnhancements::UpdateCheats(const CEnhancementList & Cheats)
|
||||
{
|
||||
std::string GameName = g_Settings->LoadStringVal(Rdb_GoodName);
|
||||
CPath OutFile(g_Settings->LoadStringVal(SupportFile_UserCheatDir), stdstr_f("%s.cht", GameName.c_str()).c_str());
|
||||
#ifdef _WIN32
|
||||
OutFile.NormalizePath(CPath(CPath::MODULE_DIRECTORY));
|
||||
#endif
|
||||
|
||||
CGuard Guard(m_CS);
|
||||
if (strcmp(m_CheatFile->FileName(), OutFile) != 0)
|
||||
{
|
||||
SectionFiles::const_iterator CheatFileItr = m_CheatFiles.find(m_SectionIdent);
|
||||
if (m_CheatFiles.end() != CheatFileItr)
|
||||
{
|
||||
m_CheatFiles.erase(CheatFileItr);
|
||||
}
|
||||
m_CheatFile = std::make_unique<CEnhancmentFile>(OutFile, "Cheat");
|
||||
m_CheatFiles.insert(SectionFiles::value_type(m_SectionIdent, OutFile));
|
||||
}
|
||||
|
||||
m_CheatFile->SetName(m_SectionIdent.c_str(), GameName.c_str());
|
||||
m_CheatFile->RemoveEnhancements(m_SectionIdent.c_str());
|
||||
for (CEnhancementList::const_iterator itr = Cheats.begin(); itr != Cheats.end(); itr++)
|
||||
{
|
||||
const CEnhancement & Enhancement = itr->second;
|
||||
if (!Enhancement.Valid())
|
||||
{
|
||||
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||
continue;
|
||||
}
|
||||
m_CheatFile->AddEnhancement(m_SectionIdent.c_str(), Enhancement);
|
||||
}
|
||||
m_CheatFile->SaveCurrentSection();
|
||||
m_UpdateCheats = true;
|
||||
}
|
||||
|
||||
void CEnhancements::UpdateCheats(void)
|
||||
{
|
||||
m_UpdateCheats = true;
|
||||
}
|
||||
|
||||
void CEnhancements::ResetCodes(CMipsMemoryVM * MMU)
|
||||
{
|
||||
m_ActiveCodes.clear();
|
||||
if (MMU != nullptr)
|
||||
{
|
||||
for (ORIGINAL_VALUES8::iterator itr = m_OriginalValues8.begin(); itr != m_OriginalValues8.end(); itr++)
|
||||
{
|
||||
uint8_t CurrentValue;
|
||||
if (MMU->LB_VAddr(itr->first, CurrentValue) && itr->second.Changed == CurrentValue)
|
||||
{
|
||||
MMU->SB_VAddr(itr->first, itr->second.Original);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_OriginalValues8.clear();
|
||||
|
||||
if (MMU != nullptr)
|
||||
{
|
||||
for (ORIGINAL_VALUES16::iterator itr = m_OriginalValues16.begin(); itr != m_OriginalValues16.end(); itr++)
|
||||
{
|
||||
uint16_t CurrentValue;
|
||||
if (MMU->LH_VAddr(itr->first, CurrentValue) && itr->second.Changed == CurrentValue)
|
||||
{
|
||||
MMU->SH_VAddr(itr->first, itr->second.Original);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_OriginalValues16.clear();
|
||||
}
|
||||
|
||||
void CEnhancements::LoadCheats(CMipsMemoryVM * MMU)
|
||||
{
|
||||
WaitScanDone();
|
||||
CGuard Guard(m_CS);
|
||||
SectionFiles::const_iterator CheatFileItr = m_CheatFiles.find(m_SectionIdent);
|
||||
if (CheatFileItr != m_CheatFiles.end())
|
||||
{
|
||||
CPath CheatFile(CheatFileItr->second);
|
||||
if (CheatFile.Exists())
|
||||
{
|
||||
m_CheatFile = std::make_unique<CEnhancmentFile>(CheatFile, "Cheat");
|
||||
m_CheatFile->GetEnhancementList(m_SectionIdent.c_str(), m_Cheats);
|
||||
}
|
||||
}
|
||||
|
||||
ResetCodes(MMU);
|
||||
for (CEnhancementList::const_iterator itr = m_Cheats.begin(); itr != m_Cheats.end(); itr++)
|
||||
{
|
||||
const CEnhancement & Enhancement = itr->second;
|
||||
if (!Enhancement.Valid() || !Enhancement.Active())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const CEnhancement::CodeEntries Entries = Enhancement.GetEntries();
|
||||
CODES Code;
|
||||
for (size_t i = 0, n = Entries.size(); i < n; i++)
|
||||
{
|
||||
GAMESHARK_CODE CodeEntry;
|
||||
CodeEntry.Command = Entries[i].Command;
|
||||
if (strncmp(Entries[i].Value.c_str(), "????", 4) == 0)
|
||||
{
|
||||
CodeEntry.Value = Enhancement.SelectedOption();
|
||||
}
|
||||
else if (strncmp(Entries[i].Value.c_str(), "??", 2) == 0)
|
||||
{
|
||||
CodeEntry.Value = (uint8_t)(strtoul(&(Entries[i].Value.c_str()[2]), 0, 16), 0, 16);
|
||||
CodeEntry.Value |= Enhancement.SelectedOption() << 16;
|
||||
}
|
||||
else if (strncmp(&Entries[i].Value[2], "??", 2) == 0)
|
||||
{
|
||||
CodeEntry.Value = (uint16_t)(strtoul(Entries[i].Value.c_str(), 0, 16) << 16);
|
||||
CodeEntry.Value |= Enhancement.SelectedOption();
|
||||
}
|
||||
else
|
||||
{
|
||||
CodeEntry.Value = (uint16_t)strtoul(Entries[i].Value.c_str(), 0, 16);
|
||||
}
|
||||
Code.push_back(CodeEntry);
|
||||
}
|
||||
m_ActiveCodes.push_back(Code);
|
||||
}
|
||||
}
|
||||
|
||||
void CEnhancements::ApplyGameSharkCodes(CMipsMemoryVM & MMU, CODES & CodeEntry, uint32_t CurrentEntry)
|
||||
{
|
||||
if (CurrentEntry >= CodeEntry.size())
|
||||
{
|
||||
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||
return;
|
||||
}
|
||||
GAMESHARK_CODE & Code = CodeEntry[CurrentEntry];
|
||||
uint16_t wMemory;
|
||||
uint8_t bMemory;
|
||||
|
||||
switch (Code.Command & 0xFF000000)
|
||||
{
|
||||
case 0x50000000: // Gameshark / AR
|
||||
if ((CurrentEntry + 1) >= (int)CodeEntry.size())
|
||||
{
|
||||
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
const GAMESHARK_CODE & NextCodeEntry = CodeEntry[CurrentEntry + 1];
|
||||
int numrepeats = (Code.Command & 0x0000FF00) >> 8;
|
||||
int offset = Code.Command & 0x000000FF;
|
||||
uint32_t Address;
|
||||
int incr = Code.Value;
|
||||
int i;
|
||||
|
||||
switch (NextCodeEntry.Command & 0xFF000000) {
|
||||
case 0x10000000: // Xplorer64
|
||||
case 0x80000000:
|
||||
Address = 0x80000000 | (NextCodeEntry.Command & 0xFFFFFF);
|
||||
wMemory = NextCodeEntry.Value;
|
||||
for (i = 0; i < numrepeats; i++)
|
||||
{
|
||||
ModifyMemory8(MMU, Address, (uint8_t)wMemory);
|
||||
Address += offset;
|
||||
wMemory += (uint16_t)incr;
|
||||
}
|
||||
break;
|
||||
case 0x11000000: // Xplorer64
|
||||
case 0x81000000:
|
||||
Address = 0x80000000 | (NextCodeEntry.Command & 0xFFFFFF);
|
||||
wMemory = NextCodeEntry.Value;
|
||||
for (i = 0; i < numrepeats; i++)
|
||||
{
|
||||
ModifyMemory16(MMU, Address, wMemory);
|
||||
Address += offset;
|
||||
wMemory += (uint16_t)incr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x80000000:
|
||||
case 0x30000000:
|
||||
case 0x82000000:
|
||||
case 0x84000000:
|
||||
ModifyMemory8(MMU, 0x80000000 | (Code.Command & 0xFFFFFF), (uint8_t)Code.Value);
|
||||
break;
|
||||
case 0x81000000:
|
||||
ModifyMemory16(MMU, 0x80000000 | (Code.Command & 0xFFFFFF), Code.Value);
|
||||
break;
|
||||
case 0xA0000000:
|
||||
ModifyMemory8(MMU, 0xA0000000 | (Code.Command & 0xFFFFFF), (uint8_t)Code.Value);
|
||||
break;
|
||||
case 0xA1000000:
|
||||
ModifyMemory16(MMU, 0xA0000000 | (Code.Command & 0xFFFFFF), Code.Value);
|
||||
break;
|
||||
case 0xD0000000:
|
||||
MMU.LB_VAddr(0x80000000 | (Code.Command & 0xFFFFFF), bMemory);
|
||||
if (bMemory == Code.Value)
|
||||
{
|
||||
ApplyGameSharkCodes(MMU, CodeEntry, CurrentEntry + 1);
|
||||
}
|
||||
break;
|
||||
case 0xD1000000:
|
||||
MMU.LH_VAddr(0x80000000 | (Code.Command & 0xFFFFFF), wMemory);
|
||||
if (wMemory == Code.Value)
|
||||
{
|
||||
ApplyGameSharkCodes(MMU, CodeEntry, CurrentEntry + 1);
|
||||
}
|
||||
break;
|
||||
case 0xD2000000:
|
||||
MMU.LB_VAddr(0x80000000 | (Code.Command & 0xFFFFFF), bMemory);
|
||||
if (bMemory != Code.Value)
|
||||
{
|
||||
ApplyGameSharkCodes(MMU, CodeEntry, CurrentEntry + 1);
|
||||
}
|
||||
break;
|
||||
case 0xD3000000:
|
||||
MMU.LH_VAddr(0x80000000 | (Code.Command & 0xFFFFFF), wMemory);
|
||||
if (wMemory != Code.Value)
|
||||
{
|
||||
ApplyGameSharkCodes(MMU, CodeEntry, CurrentEntry + 1);
|
||||
}
|
||||
break;
|
||||
case 0x31000000:
|
||||
case 0x83000000:
|
||||
case 0x85000000:
|
||||
ModifyMemory16(MMU, 0x80000000 | (Code.Command & 0xFFFFFF), Code.Value);
|
||||
break;
|
||||
case 0xE8000000:
|
||||
ModifyMemory8(MMU, 0x80000000 | (ConvertXP64Address(Code.Command) & 0xFFFFFF), (uint8_t)ConvertXP64Value(Code.Value));
|
||||
break;
|
||||
case 0xE9000000:
|
||||
ModifyMemory16(MMU, 0x80000000 | (ConvertXP64Address(Code.Command) & 0xFFFFFF), ConvertXP64Value(Code.Value));
|
||||
break;
|
||||
case 0xC8000000:
|
||||
ModifyMemory8(MMU, 0xA0000000 | (ConvertXP64Address(Code.Command) & 0xFFFFFF), (uint8_t)Code.Value);
|
||||
break;
|
||||
case 0xC9000000:
|
||||
ModifyMemory16(MMU, 0xA0000000 | (ConvertXP64Address(Code.Command) & 0xFFFFFF), ConvertXP64Value(Code.Value));
|
||||
break;
|
||||
case 0xB8000000:
|
||||
case 0xBA000000:
|
||||
MMU.LB_VAddr(0x80000000 | (ConvertXP64Address(Code.Command) & 0xFFFFFF), bMemory);
|
||||
if (bMemory == ConvertXP64Value(Code.Value))
|
||||
{
|
||||
ApplyGameSharkCodes(MMU, CodeEntry, CurrentEntry + 1);
|
||||
}
|
||||
break;
|
||||
case 0xB9000000:
|
||||
case 0xBB000000:
|
||||
MMU.LH_VAddr(0x80000000 | (ConvertXP64Address(Code.Command) & 0xFFFFFF), wMemory);
|
||||
if (wMemory == ConvertXP64Value(Code.Value))
|
||||
{
|
||||
ApplyGameSharkCodes(MMU, CodeEntry, CurrentEntry + 1);
|
||||
}
|
||||
break;
|
||||
case 0x88000000:
|
||||
case 0x89000000:
|
||||
case 0xA8000000:
|
||||
case 0xA9000000:
|
||||
//Ignore - GS Button
|
||||
break;
|
||||
default:
|
||||
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t CEnhancements::EntrySize(const CODES & CodeEntry, uint32_t CurrentEntry)
|
||||
{
|
||||
if (CurrentEntry < 0 || CurrentEntry >= (int)CodeEntry.size())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
const GAMESHARK_CODE & Code = CodeEntry[CurrentEntry];
|
||||
switch (Code.Command & 0xFF000000)
|
||||
{
|
||||
case 0x50000000: // Gameshark / AR
|
||||
if ((CurrentEntry + 1) >= (int)CodeEntry.size())
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (CodeEntry[CurrentEntry + 1].Command & 0xFF000000)
|
||||
{
|
||||
case 0x10000000: // Xplorer64
|
||||
case 0x80000000:
|
||||
case 0x11000000: // Xplorer64
|
||||
case 0x81000000:
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
case 0xD0000000:
|
||||
case 0xD1000000:
|
||||
case 0xD2000000:
|
||||
case 0xD3000000:
|
||||
case 0xB8000000:
|
||||
case 0xB9000000:
|
||||
case 0xBA000000:
|
||||
case 0xBB000000:
|
||||
return EntrySize(CodeEntry, CurrentEntry + 1) + 1;
|
||||
case 0:
|
||||
return MaxGSEntries;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CEnhancements::ModifyMemory8(CMipsMemoryVM & MMU, uint32_t Address, uint8_t Value)
|
||||
{
|
||||
MEM_VALUE8 OriginalValue;
|
||||
if (!MMU.LB_VAddr(Address, OriginalValue.Original))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (OriginalValue.Original == Value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
MMU.SB_VAddr(Address, Value);
|
||||
if (g_Recompiler)
|
||||
{
|
||||
g_Recompiler->ClearRecompCode_Virt(Address & ~0xFFF, 0x1000, CRecompiler::Remove_Cheats);
|
||||
}
|
||||
OriginalValue.Changed = Value;
|
||||
std::pair<ORIGINAL_VALUES8::iterator, bool> itr = m_OriginalValues8.insert(ORIGINAL_VALUES8::value_type(Address, OriginalValue));
|
||||
}
|
||||
|
||||
void CEnhancements::ModifyMemory16(CMipsMemoryVM & MMU, uint32_t Address, uint16_t Value)
|
||||
{
|
||||
MEM_VALUE16 OriginalValue;
|
||||
if (!MMU.LH_VAddr(Address, OriginalValue.Original))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (OriginalValue.Original == Value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
OriginalValue.Changed = Value;
|
||||
std::pair<ORIGINAL_VALUES16::iterator, bool> itr = m_OriginalValues16.insert(ORIGINAL_VALUES16::value_type(Address, OriginalValue));
|
||||
MMU.SH_VAddr(Address, OriginalValue.Changed);
|
||||
if (g_Recompiler)
|
||||
{
|
||||
g_Recompiler->ClearRecompCode_Virt(Address & ~0xFFF, 0x1000, CRecompiler::Remove_Cheats);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CEnhancements::ScanFileThread(void)
|
||||
{
|
||||
SectionFiles Files;
|
||||
CPath File(g_Settings->LoadStringVal(SupportFile_CheatDir), "*.cht");
|
||||
#ifdef _WIN32
|
||||
File.NormalizePath(CPath(CPath::MODULE_DIRECTORY));
|
||||
#endif
|
||||
if (File.FindFirst() && m_Scan)
|
||||
{
|
||||
do
|
||||
{
|
||||
CEnhancmentFile EnhancmentFile(File, "Cheat");
|
||||
CEnhancmentFile::SectionList Sections;
|
||||
EnhancmentFile.GetSections(Sections);
|
||||
for (CEnhancmentFile::SectionList::const_iterator itr = Sections.begin(); itr != Sections.end(); itr++)
|
||||
{
|
||||
Files.insert(SectionFiles::value_type(itr->c_str(), File));
|
||||
}
|
||||
} while (m_Scan && File.FindNext());
|
||||
}
|
||||
|
||||
File = CPath(g_Settings->LoadStringVal(SupportFile_UserCheatDir), "*.cht");
|
||||
#ifdef _WIN32
|
||||
File.NormalizePath(CPath(CPath::MODULE_DIRECTORY));
|
||||
#endif
|
||||
if (m_Scan && File.FindFirst())
|
||||
{
|
||||
do
|
||||
{
|
||||
CEnhancmentFile EnhancmentFile(File, "Cheat");
|
||||
CEnhancmentFile::SectionList Sections;
|
||||
EnhancmentFile.GetSections(Sections);
|
||||
for (CEnhancmentFile::SectionList::const_iterator itr = Sections.begin(); itr != Sections.end(); itr++)
|
||||
{
|
||||
Files[itr->c_str()] = (const char *)File;
|
||||
}
|
||||
} while (m_Scan && File.FindNext());
|
||||
}
|
||||
|
||||
{
|
||||
CGuard Guard(m_CS);
|
||||
m_CheatFiles = Files;
|
||||
m_Scanned = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CEnhancements::WaitScanDone()
|
||||
{
|
||||
for (uint32_t i = 0; i < 500; i++)
|
||||
{
|
||||
bool Scanned = false;
|
||||
{
|
||||
CGuard Guard(m_CS);
|
||||
Scanned = m_Scanned;
|
||||
}
|
||||
if (Scanned)
|
||||
{
|
||||
break;
|
||||
}
|
||||
pjutil::Sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
void CEnhancements::GameChanged(void)
|
||||
{
|
||||
m_SectionIdent = g_Settings->LoadStringVal(Game_IniKey);
|
||||
LoadCheats(nullptr);
|
||||
if (!g_Settings->LoadDword(Setting_RememberCheats) && !m_ActiveCodes.empty())
|
||||
{
|
||||
for (CEnhancementList::iterator itr = m_Cheats.begin(); itr != m_Cheats.end(); itr++)
|
||||
{
|
||||
if (!itr->second.Active())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
itr->second.SetActive(false);
|
||||
}
|
||||
m_ActiveCodes.clear();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t CEnhancements::ConvertXP64Address(uint32_t Address)
|
||||
{
|
||||
uint32_t tmpAddress = (Address ^ 0x68000000) & 0xFF000000;
|
||||
tmpAddress += ((Address + 0x002B0000) ^ 0x00810000) & 0x00FF0000;
|
||||
tmpAddress += ((Address + 0x00002B00) ^ 0x00008200) & 0x0000FF00;
|
||||
tmpAddress += ((Address + 0x0000002B) ^ 0x00000083) & 0x000000FF;
|
||||
return tmpAddress;
|
||||
}
|
||||
|
||||
uint16_t CEnhancements::ConvertXP64Value(uint16_t Value)
|
||||
{
|
||||
uint16_t tmpValue = ((Value + 0x2B00) ^ 0x8400) & 0xFF00;
|
||||
tmpValue += ((Value + 0x002B) ^ 0x0085) & 0x00FF;
|
||||
return tmpValue;
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/****************************************************************************
|
||||
* *
|
||||
* Project64 - A Nintendo 64 emulator. *
|
||||
* http://www.pj64-emu.com/ *
|
||||
* Copyright (C) 2012 Project64. All rights reserved. *
|
||||
* *
|
||||
* License: *
|
||||
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
||||
* *
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include <Project64-core\N64System\Enhancement\EnhancementFile.h>
|
||||
#include <Project64-core\N64System\Enhancement\EnhancementList.h>
|
||||
#include <Common\Thread.h>
|
||||
#include <Common\CriticalSection.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
class CMipsMemoryVM;
|
||||
|
||||
class CEnhancements
|
||||
{
|
||||
enum
|
||||
{
|
||||
MaxGSEntries = 100,
|
||||
};
|
||||
|
||||
public:
|
||||
CEnhancements();
|
||||
~CEnhancements();
|
||||
|
||||
void ApplyActive(CMipsMemoryVM & MMU, bool UpdateChanges);
|
||||
void ApplyGSButton(CMipsMemoryVM & MMU, bool UpdateChanges);
|
||||
void UpdateCheats(const CEnhancementList & Cheats );
|
||||
void UpdateCheats(void);
|
||||
|
||||
inline const CEnhancementList & Cheats(void) const { return m_Cheats; }
|
||||
|
||||
private:
|
||||
struct GAMESHARK_CODE
|
||||
{
|
||||
uint32_t Command;
|
||||
uint16_t Value;
|
||||
};
|
||||
|
||||
struct MEM_VALUE16
|
||||
{
|
||||
uint16_t Original;
|
||||
uint16_t Changed;
|
||||
};
|
||||
|
||||
struct MEM_VALUE8
|
||||
{
|
||||
uint8_t Original;
|
||||
uint8_t Changed;
|
||||
};
|
||||
|
||||
typedef std::map<std::string, std::string> SectionFiles;
|
||||
typedef std::vector<GAMESHARK_CODE> CODES;
|
||||
typedef std::vector<CODES> CODES_ARRAY;
|
||||
typedef std::map<uint32_t, MEM_VALUE16> ORIGINAL_VALUES16;
|
||||
typedef std::map<uint32_t, MEM_VALUE8> ORIGINAL_VALUES8;
|
||||
|
||||
void ResetCodes(CMipsMemoryVM * MMU);
|
||||
void LoadCheats(CMipsMemoryVM * MMU);
|
||||
void ApplyGameSharkCodes(CMipsMemoryVM & MMU, CODES & CodeEntry, uint32_t CurrentEntry);
|
||||
uint32_t EntrySize(const CODES & CodeEntry, uint32_t CurrentEntry);
|
||||
void ModifyMemory8(CMipsMemoryVM & MMU, uint32_t Address, uint8_t Value);
|
||||
void ModifyMemory16(CMipsMemoryVM & MMU, uint32_t Address, uint16_t Value);
|
||||
void ScanFileThread(void);
|
||||
void WaitScanDone(void);
|
||||
void GameChanged(void);
|
||||
|
||||
static uint32_t ConvertXP64Address(uint32_t Address);
|
||||
static uint16_t ConvertXP64Value(uint16_t Value);
|
||||
|
||||
static uint32_t stScanFileThread(void * lpThreadParameter) { ((CEnhancements *)lpThreadParameter)->ScanFileThread(); return 0; }
|
||||
static void stGameChanged(void * lpData) { ((CEnhancements *)lpData)->GameChanged(); }
|
||||
|
||||
CriticalSection m_CS;
|
||||
std::string m_SectionIdent;
|
||||
SectionFiles m_CheatFiles;
|
||||
std::unique_ptr<CEnhancmentFile> m_CheatFile;
|
||||
CEnhancementList m_Cheats;
|
||||
CODES_ARRAY m_ActiveCodes;
|
||||
CODES_ARRAY m_GSButtonCodes;
|
||||
ORIGINAL_VALUES16 m_OriginalValues16;
|
||||
ORIGINAL_VALUES8 m_OriginalValues8;
|
||||
CThread m_ScanFileThread;
|
||||
bool m_Scan;
|
||||
bool m_Scanned;
|
||||
bool m_UpdateCheats;
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
#include "../stdafx.h"
|
|
@ -180,12 +180,7 @@ void CSystemEvents::ExecuteEvents()
|
|||
g_Notify->ChangeFullScreen();
|
||||
break;
|
||||
case SysEvent_GSButtonPressed:
|
||||
if (m_System->HasCheatsSlectionChanged())
|
||||
{
|
||||
m_System->SetCheatsSlectionChanged(false);
|
||||
m_System->m_Cheats.LoadCheats(false, m_Plugins);
|
||||
}
|
||||
m_System->m_Cheats.ApplyGSButton();
|
||||
m_System->ApplyGSButton();
|
||||
break;
|
||||
case SysEvent_PauseCPU_FromMenu:
|
||||
if (!g_Settings->LoadBool(GameRunning_CPU_Paused))
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include <Project64-core/N64System/Mips/OpcodeName.h>
|
||||
#include <Project64-core/N64System/Mips/Disk.h>
|
||||
#include <Project64-core/N64System/N64DiskClass.h>
|
||||
#include <Project64-core/N64System/Enhancement/Enhancements.h>
|
||||
#include <Project64-core/N64System/N64RomClass.h>
|
||||
#include <Project64-core/ExceptionHandler.h>
|
||||
#include <Project64-core/Logging.h>
|
||||
#include <Project64-core/Debugger.h>
|
||||
|
@ -39,7 +41,7 @@ CN64System::CN64System(CPlugins * Plugins, uint32_t randomizer_seed, bool SavesR
|
|||
m_SyncCPU(NULL),
|
||||
m_SyncPlugins(NULL),
|
||||
m_MMU_VM(SavesReadOnly),
|
||||
m_Cheats(m_MMU_VM),
|
||||
//m_Cheats(m_MMU_VM),
|
||||
m_TLB(this),
|
||||
m_Reg(this, this),
|
||||
m_Recomp(NULL),
|
||||
|
@ -57,8 +59,7 @@ CN64System::CN64System(CPlugins * Plugins, uint32_t randomizer_seed, bool SavesR
|
|||
m_SyncCount(0),
|
||||
m_thread(NULL),
|
||||
m_hPauseEvent(true),
|
||||
m_CheatsSlectionChanged(false),
|
||||
m_SyncCpu(SyncSystem),
|
||||
m_SyncSystem(SyncSystem),
|
||||
m_Random(randomizer_seed)
|
||||
{
|
||||
WriteTrace(TraceN64System, TraceDebug, "Start");
|
||||
|
@ -71,7 +72,6 @@ CN64System::CN64System(CPlugins * Plugins, uint32_t randomizer_seed, bool SavesR
|
|||
}
|
||||
m_Limiter.SetHertz(gameHertz);
|
||||
g_Settings->SaveDword(GameRunning_ScreenHertz, gameHertz);
|
||||
m_Cheats.LoadCheats(!g_Settings->LoadDword(Setting_RememberCheats), Plugins);
|
||||
WriteTrace(TraceN64System, TraceDebug, "Setting up system");
|
||||
CInterpreterCPU::BuildCPU();
|
||||
|
||||
|
@ -840,6 +840,14 @@ void CN64System::PluginReset()
|
|||
#endif
|
||||
}
|
||||
|
||||
void CN64System::ApplyGSButton(void)
|
||||
{
|
||||
if ((m_Reg.STATUS_REGISTER & STATUS_IE) != 0)
|
||||
{
|
||||
g_Enhancements->ApplyGSButton(m_MMU_VM, !m_SyncSystem);
|
||||
}
|
||||
}
|
||||
|
||||
void CN64System::Reset(bool bInitReg, bool ClearMenory)
|
||||
{
|
||||
WriteTrace(TraceN64System, TraceDebug, "Start (bInitReg: %s, ClearMenory: %s)", bInitReg ? "true" : "false", ClearMenory ? "true" : "false");
|
||||
|
@ -1419,9 +1427,6 @@ void CN64System::SyncCPU(CN64System * const SecondCPU)
|
|||
m_LastSuccessSyncPC[i] = m_LastSuccessSyncPC[i - 1];
|
||||
}
|
||||
m_LastSuccessSyncPC[0] = m_Reg.m_PROGRAM_COUNTER;
|
||||
// if (PROGRAM_COUNTER == 0x8009BBD8) {
|
||||
// g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||
// }
|
||||
}
|
||||
|
||||
void CN64System::SyncSystem()
|
||||
|
@ -2432,16 +2437,7 @@ void CN64System::RefreshScreen()
|
|||
}
|
||||
if ((m_Reg.STATUS_REGISTER & STATUS_IE) != 0)
|
||||
{
|
||||
if (HasCheatsSlectionChanged())
|
||||
{
|
||||
if (this == g_BaseSystem && g_SyncSystem != NULL)
|
||||
{
|
||||
g_SyncSystem->SetCheatsSlectionChanged(true);
|
||||
}
|
||||
SetCheatsSlectionChanged(false);
|
||||
m_Cheats.LoadCheats(false, g_BaseSystem->m_Plugins);
|
||||
}
|
||||
m_Cheats.ApplyCheats();
|
||||
g_Enhancements->ApplyActive(m_MMU_VM, !m_SyncSystem);
|
||||
}
|
||||
// if (bProfiling) { m_Profile.StartTimer(ProfilingAddr != Timer_None ? ProfilingAddr : Timer_R4300); }
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include <Project64-core/Logging.h>
|
||||
|
||||
#include "Mips/TLBClass.h"
|
||||
#include "CheatClass.h"
|
||||
#include "FramePerSecondClass.h"
|
||||
#include "SpeedLimiterClass.h"
|
||||
|
||||
|
@ -52,7 +51,6 @@ public:
|
|||
CN64System(CPlugins * Plugins, uint32_t randomizer_seed, bool SavesReadOnly, bool SyncSystem);
|
||||
virtual ~CN64System(void);
|
||||
|
||||
CCheats m_Cheats;
|
||||
bool m_EndEmulation;
|
||||
SAVE_CHIP_TYPE m_SaveUsing;
|
||||
|
||||
|
@ -78,6 +76,7 @@ public:
|
|||
void Reset(bool bInitReg, bool ClearMenory);
|
||||
void GameReset();
|
||||
void PluginReset();
|
||||
void ApplyGSButton(void);
|
||||
|
||||
void Pause();
|
||||
void RunRSP();
|
||||
|
@ -87,8 +86,6 @@ public:
|
|||
|
||||
bool DmaUsed() const { return m_DMAUsed; }
|
||||
void SetDmaUsed(bool DMAUsed) { m_DMAUsed = DMAUsed; }
|
||||
void SetCheatsSlectionChanged(bool changed) { m_CheatsSlectionChanged = changed; }
|
||||
bool HasCheatsSlectionChanged(void) const { return m_CheatsSlectionChanged; }
|
||||
uint32_t GetButtons(int32_t Control) const { return m_Buttons[Control]; }
|
||||
CPlugins * GetPlugins() { return m_Plugins; }
|
||||
|
||||
|
@ -165,8 +162,7 @@ private:
|
|||
uint32_t m_TLBLoadAddress;
|
||||
uint32_t m_TLBStoreAddress;
|
||||
uint32_t m_SyncCount;
|
||||
bool m_SyncCpu;
|
||||
bool m_CheatsSlectionChanged;
|
||||
bool m_SyncSystem;
|
||||
CRandom m_Random;
|
||||
|
||||
//When Syncing cores this is the PC where it last Sync'ed correctly
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <Project64-core/N64System/Recompiler/LoopAnalysis.h>
|
||||
#include <Project64-core/N64System/Recompiler/x86/x86RecompilerOps.h>
|
||||
#include <Project64-core/N64System/N64Class.h>
|
||||
#include <Project64-core/N64System/N64RomClass.h>
|
||||
#include <Project64-core/ExceptionHandler.h>
|
||||
#include <Project64-core/Debugger.h>
|
||||
#include <stdio.h>
|
||||
|
|
|
@ -11,27 +11,28 @@
|
|||
#include "stdafx.h"
|
||||
#include "SystemGlobals.h"
|
||||
|
||||
CN64System * g_System = NULL;
|
||||
CN64System * g_BaseSystem = NULL;
|
||||
CN64System * g_SyncSystem = NULL;
|
||||
CRecompiler * g_Recompiler = NULL;
|
||||
CN64System * g_System = NULL;
|
||||
CN64System * g_BaseSystem = NULL;
|
||||
CN64System * g_SyncSystem = NULL;
|
||||
CRecompiler * g_Recompiler = NULL;
|
||||
CMipsMemoryVM * g_MMU = NULL; //Memory of the n64
|
||||
CTLB * g_TLB = NULL; //TLB Unit
|
||||
CRegisters * g_Reg = NULL; //Current Register Set attacted to the g_MMU
|
||||
CTLB * g_TLB = NULL; //TLB Unit
|
||||
CRegisters * g_Reg = NULL; //Current Register Set attacted to the g_MMU
|
||||
CNotification * g_Notify = NULL;
|
||||
CPlugins * g_Plugins = NULL;
|
||||
CN64Rom * g_Rom = NULL; //The current rom that this system is executing.. it can only execute one file at the time
|
||||
CN64Rom * g_DDRom = NULL; //64DD IPL ROM
|
||||
CN64Disk * g_Disk = NULL; //64DD DISK
|
||||
CAudio * g_Audio = NULL;
|
||||
CPlugins * g_Plugins = NULL;
|
||||
CN64Rom * g_Rom = NULL; //The current rom that this system is executing.. it can only execute one file at the time
|
||||
CN64Rom * g_DDRom = NULL; //64DD IPL ROM
|
||||
CN64Disk * g_Disk = NULL; //64DD DISK
|
||||
CAudio * g_Audio = NULL;
|
||||
CSystemTimer * g_SystemTimer = NULL;
|
||||
CTransVaddr * g_TransVaddr = NULL;
|
||||
CTransVaddr * g_TransVaddr = NULL;
|
||||
CSystemEvents * g_SystemEvents = NULL;
|
||||
uint32_t * g_TLBLoadAddress = NULL;
|
||||
uint32_t * g_TLBStoreAddress = NULL;
|
||||
CDebugger * g_Debugger = NULL;
|
||||
uint8_t ** g_RecompPos = NULL;
|
||||
CMempak * g_Mempak = NULL;
|
||||
CRandom * g_Random = NULL;
|
||||
uint32_t * g_TLBLoadAddress = NULL;
|
||||
uint32_t * g_TLBStoreAddress = NULL;
|
||||
CDebugger * g_Debugger = NULL;
|
||||
uint8_t ** g_RecompPos = NULL;
|
||||
CMempak * g_Mempak = NULL;
|
||||
CRandom * g_Random = NULL;
|
||||
CEnhancements * g_Enhancements = NULL;
|
||||
|
||||
int * g_NextTimer;
|
|
@ -11,58 +11,61 @@
|
|||
#pragma once
|
||||
|
||||
class CSettings;
|
||||
extern CSettings * g_Settings;
|
||||
extern CSettings * g_Settings;
|
||||
|
||||
class CN64System;
|
||||
extern CN64System * g_System;
|
||||
extern CN64System * g_BaseSystem;
|
||||
extern CN64System * g_SyncSystem;
|
||||
extern CN64System * g_System;
|
||||
extern CN64System * g_BaseSystem;
|
||||
extern CN64System * g_SyncSystem;
|
||||
|
||||
class CRecompiler;
|
||||
extern CRecompiler * g_Recompiler;
|
||||
extern CRecompiler * g_Recompiler;
|
||||
|
||||
class CMipsMemoryVM;
|
||||
extern CMipsMemoryVM * g_MMU; //Memory of the n64
|
||||
|
||||
class CTLB;
|
||||
extern CTLB * g_TLB; //TLB Unit
|
||||
extern CTLB * g_TLB; //TLB Unit
|
||||
|
||||
class CRegisters;
|
||||
extern CRegisters * g_Reg; //Current Register Set attached to the g_MMU
|
||||
extern CRegisters * g_Reg; //Current Register Set attached to the g_MMU
|
||||
|
||||
class CPlugins;
|
||||
extern CPlugins * g_Plugins;
|
||||
extern CPlugins * g_Plugins;
|
||||
|
||||
class CN64Rom;
|
||||
extern CN64Rom * g_Rom; //The current rom that this system is executing.. it can only execute one file at the time
|
||||
extern CN64Rom * g_DDRom; //64DD IPL ROM
|
||||
extern CN64Rom * g_Rom; //The current rom that this system is executing.. it can only execute one file at the time
|
||||
extern CN64Rom * g_DDRom; //64DD IPL ROM
|
||||
|
||||
class CN64Disk;
|
||||
extern CN64Disk * g_Disk; //64DD DISK
|
||||
extern CN64Disk * g_Disk; //64DD DISK
|
||||
|
||||
class CAudio;
|
||||
extern CAudio * g_Audio;
|
||||
extern CAudio * g_Audio;
|
||||
|
||||
class CSystemTimer;
|
||||
extern CSystemTimer * g_SystemTimer;
|
||||
extern CSystemTimer * g_SystemTimer;
|
||||
|
||||
__interface CTransVaddr;
|
||||
extern CTransVaddr * g_TransVaddr;
|
||||
extern CTransVaddr * g_TransVaddr;
|
||||
|
||||
class CSystemEvents;
|
||||
extern CSystemEvents * g_SystemEvents;
|
||||
|
||||
extern int32_t * g_NextTimer;
|
||||
extern uint32_t * g_TLBLoadAddress;
|
||||
extern uint32_t * g_TLBStoreAddress;
|
||||
extern int32_t * g_NextTimer;
|
||||
extern uint32_t * g_TLBLoadAddress;
|
||||
extern uint32_t * g_TLBStoreAddress;
|
||||
|
||||
__interface CDebugger;
|
||||
extern CDebugger * g_Debugger;
|
||||
extern CDebugger * g_Debugger;
|
||||
|
||||
extern uint8_t ** g_RecompPos;
|
||||
extern uint8_t ** g_RecompPos;
|
||||
|
||||
class CMempak;
|
||||
extern CMempak * g_Mempak;
|
||||
extern CMempak * g_Mempak;
|
||||
|
||||
class CRandom;
|
||||
extern CRandom * g_Random;
|
||||
extern CRandom * g_Random;
|
||||
|
||||
class CEnhancements;
|
||||
extern CEnhancements * g_Enhancements;
|
|
@ -14,6 +14,7 @@
|
|||
#include <Project64-core/N64System/Mips/RegisterClass.h>
|
||||
#include <Project64-core/N64System/N64Class.h>
|
||||
#include <Project64-core/N64System/N64DiskClass.h>
|
||||
#include <Project64-core/N64System/N64RomClass.h>
|
||||
#include "RSPPlugin.h"
|
||||
#include "GFXPlugin.h"
|
||||
#include <Project64-core/Plugins/AudioPlugin.h>
|
||||
|
|
|
@ -44,9 +44,11 @@
|
|||
<ClCompile Include="Logging.cpp" />
|
||||
<ClCompile Include="MemoryExceptionFilter.cpp" />
|
||||
<ClCompile Include="Multilanguage\LanguageClass.cpp" />
|
||||
<ClCompile Include="N64System\CheatClass.cpp" />
|
||||
<ClCompile Include="N64System\CheatFile.cpp" />
|
||||
<ClCompile Include="N64System\EmulationThread.cpp" />
|
||||
<ClCompile Include="N64System\Enhancement\Enhancement.cpp" />
|
||||
<ClCompile Include="N64System\Enhancement\EnhancementFile.cpp" />
|
||||
<ClCompile Include="N64System\Enhancement\EnhancementList.cpp" />
|
||||
<ClCompile Include="N64System\Enhancement\Enhancements.cpp" />
|
||||
<ClCompile Include="N64System\FramePerSecondClass.cpp" />
|
||||
<ClCompile Include="N64System\Interpreter\InterpreterCPU.cpp" />
|
||||
<ClCompile Include="N64System\Interpreter\InterpreterOps.cpp" />
|
||||
|
@ -106,7 +108,6 @@
|
|||
<ClCompile Include="Settings\SettingType\SettingsType-Application.cpp" />
|
||||
<ClCompile Include="Settings\SettingType\SettingsType-ApplicationIndex.cpp" />
|
||||
<ClCompile Include="Settings\SettingType\SettingsType-ApplicationPath.cpp" />
|
||||
<ClCompile Include="Settings\SettingType\SettingsType-Cheats.cpp" />
|
||||
<ClCompile Include="Settings\SettingType\SettingsType-Enhancements.cpp" />
|
||||
<ClCompile Include="Settings\SettingType\SettingsType-GameSetting.cpp" />
|
||||
<ClCompile Include="Settings\SettingType\SettingsType-GameSettingIndex.cpp" />
|
||||
|
@ -140,8 +141,10 @@
|
|||
<ClInclude Include="Logging.h" />
|
||||
<ClInclude Include="Multilanguage.h" />
|
||||
<ClInclude Include="Multilanguage\LanguageClass.h" />
|
||||
<ClInclude Include="N64System\CheatClass.h" />
|
||||
<ClInclude Include="N64System\CheatFile.h" />
|
||||
<ClInclude Include="N64System\Enhancement\Enhancement.h" />
|
||||
<ClInclude Include="N64System\Enhancement\EnhancementFile.h" />
|
||||
<ClInclude Include="N64System\Enhancement\EnhancementList.h" />
|
||||
<ClInclude Include="N64System\Enhancement\Enhancements.h" />
|
||||
<ClInclude Include="N64System\FramePerSecondClass.h" />
|
||||
<ClInclude Include="N64System\Interpreter\InterpreterCPU.h" />
|
||||
<ClInclude Include="N64System\Interpreter\InterpreterOps32.h" />
|
||||
|
@ -214,7 +217,6 @@
|
|||
<ClInclude Include="Settings\SettingType\SettingsType-ApplicationIndex.h" />
|
||||
<ClInclude Include="Settings\SettingType\SettingsType-ApplicationPath.h" />
|
||||
<ClInclude Include="Settings\SettingType\SettingsType-Base.h" />
|
||||
<ClInclude Include="Settings\SettingType\SettingsType-Cheats.h" />
|
||||
<ClInclude Include="Settings\SettingType\SettingsType-Enhancements.h" />
|
||||
<ClInclude Include="Settings\SettingType\SettingsType-GameSetting.h" />
|
||||
<ClInclude Include="Settings\SettingType\SettingsType-GameSettingIndex.h" />
|
||||
|
|
|
@ -88,6 +88,12 @@
|
|||
<Filter Include="Header Files\N64 System\Recompiler\Arm">
|
||||
<UniqueIdentifier>{98453fda-8903-4074-8c4c-831c3f2bd63d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\N64 System\Enhancement">
|
||||
<UniqueIdentifier>{8fb36b94-03cc-4d51-96c9-bc4c475e54fc}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\N64 System\Enhancement">
|
||||
<UniqueIdentifier>{ec73ae9e-54e8-4cbe-93fb-1d98d6755619}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
|
@ -105,9 +111,6 @@
|
|||
<ClCompile Include="Settings\SettingType\SettingsType-ApplicationPath.cpp">
|
||||
<Filter>Source Files\Settings\SettingType</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Settings\SettingType\SettingsType-Cheats.cpp">
|
||||
<Filter>Source Files\Settings\SettingType</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Settings\SettingType\SettingsType-GameSetting.cpp">
|
||||
<Filter>Source Files\Settings\SettingType</Filter>
|
||||
</ClCompile>
|
||||
|
@ -192,9 +195,6 @@
|
|||
<ClCompile Include="Plugins\RSPPlugin.cpp">
|
||||
<Filter>Source Files\Plugins</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="N64System\CheatClass.cpp">
|
||||
<Filter>Source Files\N64 System</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="N64System\EmulationThread.cpp">
|
||||
<Filter>Source Files\N64 System</Filter>
|
||||
</ClCompile>
|
||||
|
@ -342,8 +342,17 @@
|
|||
<ClCompile Include="Settings\SettingType\SettingsType-Enhancements.cpp">
|
||||
<Filter>Source Files\Settings\SettingType</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="N64System\CheatFile.cpp">
|
||||
<Filter>Source Files\N64 System</Filter>
|
||||
<ClCompile Include="N64System\Enhancement\EnhancementFile.cpp">
|
||||
<Filter>Source Files\N64 System\Enhancement</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="N64System\Enhancement\Enhancement.cpp">
|
||||
<Filter>Source Files\N64 System\Enhancement</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="N64System\Enhancement\Enhancements.cpp">
|
||||
<Filter>Source Files\N64 System\Enhancement</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="N64System\Enhancement\EnhancementList.cpp">
|
||||
<Filter>Source Files\N64 System\Enhancement</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -368,9 +377,6 @@
|
|||
<ClInclude Include="Settings\SettingType\SettingsType-Base.h">
|
||||
<Filter>Header Files\Settings\SettingType</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Settings\SettingType\SettingsType-Cheats.h">
|
||||
<Filter>Header Files\Settings\SettingType</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Settings\SettingType\SettingsType-GameSetting.h">
|
||||
<Filter>Header Files\Settings\SettingType</Filter>
|
||||
</ClInclude>
|
||||
|
@ -482,9 +488,6 @@
|
|||
<ClInclude Include="Settings\LoggingSettings.h">
|
||||
<Filter>Header Files\Settings</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="N64System\CheatClass.h">
|
||||
<Filter>Header Files\N64 System</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="N64System\FramePerSecondClass.h">
|
||||
<Filter>Header Files\N64 System</Filter>
|
||||
</ClInclude>
|
||||
|
@ -662,8 +665,17 @@
|
|||
<ClInclude Include="Settings\SettingType\SettingsType-Enhancements.h">
|
||||
<Filter>Header Files\Settings\SettingType</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="N64System\CheatFile.h">
|
||||
<Filter>Header Files\N64 System</Filter>
|
||||
<ClInclude Include="N64System\Enhancement\EnhancementFile.h">
|
||||
<Filter>Header Files\N64 System\Enhancement</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="N64System\Enhancement\Enhancement.h">
|
||||
<Filter>Header Files\N64 System\Enhancement</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="N64System\Enhancement\Enhancements.h">
|
||||
<Filter>Header Files\N64 System\Enhancement</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="N64System\Enhancement\EnhancementList.h">
|
||||
<Filter>Header Files\N64 System\Enhancement</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include "Settings/SettingType/SettingsType-Application.h"
|
||||
#include "Settings/SettingType/SettingsType-ApplicationPath.h"
|
||||
#include "Settings/SettingType/SettingsType-ApplicationIndex.h"
|
||||
#include "Settings/SettingType/SettingsType-Cheats.h"
|
||||
#include "Settings/SettingType/SettingsType-Enhancements.h"
|
||||
#include "Settings/SettingType/SettingsType-GameSetting.h"
|
||||
#include "Settings/SettingType/SettingsType-GameSettingIndex.h"
|
||||
|
@ -47,7 +46,6 @@ CSettings::~CSettings()
|
|||
CSettingTypeApplication::CleanUp();
|
||||
CSettingTypeRomDatabase::CleanUp();
|
||||
CSettingTypeGame::CleanUp();
|
||||
CSettingTypeCheats::CleanUp();
|
||||
CSettingTypeEnhancements::CleanUp();
|
||||
|
||||
for (SETTING_MAP::iterator iter = m_SettingInfo.begin(); iter != m_SettingInfo.end(); iter++)
|
||||
|
@ -436,22 +434,6 @@ void CSettings::AddHowToHandleSetting(const char * BaseDirectory)
|
|||
AddHandler(Logging_LogRomHeader, new CSettingTypeApplication("Logging", "Generate Log Files", false));
|
||||
AddHandler(Logging_LogUnknown, new CSettingTypeApplication("Logging", "Log Rom Header", false));
|
||||
|
||||
// cheats
|
||||
AddHandler(Cheat_Entry, new CSettingTypeCheats(""));
|
||||
AddHandler(Cheat_Notes, new CSettingTypeCheats("_N"));
|
||||
AddHandler(Cheat_Options, new CSettingTypeCheats("_O"));
|
||||
AddHandler(Cheat_Active, new CSettingTypeGameIndex("Cheat", "Active", false));
|
||||
AddHandler(Cheat_Extension, new CSettingTypeGameIndex("Cheat", ".exten", "??? - Not Set"));
|
||||
|
||||
// Enhancement
|
||||
AddHandler(Enhancement_Name, new CSettingTypeEnhancements(""));
|
||||
AddHandler(Enhancement_Active, new CSettingTypeGameIndex("Enhancement", "", Enhancement_OnByDefault));
|
||||
AddHandler(Enhancement_OnByDefault, new CSettingTypeEnhancements("_AO"));
|
||||
AddHandler(Enhancement_Overclock, new CSettingTypeEnhancements("_OVER"));
|
||||
AddHandler(Enhancement_OverclockValue, new CSettingTypeEnhancements("_OVERV"));
|
||||
AddHandler(Enhancement_Gameshark, new CSettingTypeEnhancements("_GS"));
|
||||
AddHandler(Enhancement_GamesharkCode, new CSettingTypeEnhancements("_GSC"));
|
||||
AddHandler(Enhancement_Notes, new CSettingTypeEnhancements("_N"));
|
||||
WriteTrace(TraceAppInit, TraceDebug, "Done");
|
||||
}
|
||||
|
||||
|
@ -519,7 +501,6 @@ uint32_t CSettings::FindSetting(CSettings * _this, const char * Name)
|
|||
|
||||
void CSettings::FlushSettings(CSettings * /*_this*/)
|
||||
{
|
||||
CSettingTypeCheats::FlushChanges();
|
||||
CSettingTypeApplication::Flush();
|
||||
}
|
||||
|
||||
|
@ -706,7 +687,6 @@ bool CSettings::Initialize(const char * BaseDirectory, const char * AppName)
|
|||
CSettingTypeApplication::Initialize();
|
||||
CSettingTypeRomDatabase::Initialize();
|
||||
CSettingTypeGame::Initialize();
|
||||
CSettingTypeCheats::Initialize();
|
||||
CSettingTypeEnhancements::Initialize();
|
||||
|
||||
g_Settings->SaveString(Setting_ApplicationName, AppName);
|
||||
|
|
|
@ -78,7 +78,7 @@ void CGameSettings::RefreshGameSettings()
|
|||
{
|
||||
m_CountPerOp = 2;
|
||||
}
|
||||
if (g_Settings->LoadBool(Setting_Enhancement))
|
||||
/*if (g_Settings->LoadBool(Setting_Enhancement))
|
||||
{
|
||||
for (int i = 0; i < CCheats::MaxCheats; i++)
|
||||
{
|
||||
|
@ -90,7 +90,7 @@ void CGameSettings::RefreshGameSettings()
|
|||
m_OverClockModifier = g_Settings->LoadDwordIndex(Enhancement_OverclockValue, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
if (m_OverClockModifier < 1) { m_OverClockModifier = 1; }
|
||||
if (m_OverClockModifier > 20) { m_OverClockModifier = 20; }
|
||||
RefreshSyncToAudio();
|
||||
|
|
|
@ -1,393 +0,0 @@
|
|||
/****************************************************************************
|
||||
* *
|
||||
* Project64 - A Nintendo 64 emulator. *
|
||||
* http://www.pj64-emu.com/ *
|
||||
* Copyright (C) 2012 Project64. All rights reserved. *
|
||||
* *
|
||||
* License: *
|
||||
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
||||
* *
|
||||
****************************************************************************/
|
||||
#include "stdafx.h"
|
||||
#include "SettingsType-Cheats.h"
|
||||
#include <Project64-core\N64System\CheatClass.h>
|
||||
#include <Common\path.h>
|
||||
#include <Common\Thread.h>
|
||||
#include <algorithm>
|
||||
|
||||
class CCheatInfo
|
||||
{
|
||||
typedef std::map<std::string, std::string> SectionFiles;
|
||||
|
||||
public:
|
||||
CCheatInfo();
|
||||
~CCheatInfo();
|
||||
|
||||
void FlushChanges (void);
|
||||
bool Load(const char * PostFix, uint32_t Index, std::string & Value) const;
|
||||
void Save(const char * PostFix, uint32_t Index, const char * Value);
|
||||
void Delete(const char * PostFix, uint32_t Index);
|
||||
|
||||
private:
|
||||
void ScanFileThread(void);
|
||||
void GameChanged(void);
|
||||
void UseUserFile();
|
||||
|
||||
static void CustomSortData(CIniFileBase::KeyValueVector & data);
|
||||
static uint32_t stScanFileThread(void * lpThreadParameter) { ((CCheatInfo *)lpThreadParameter)->ScanFileThread(); return 0; }
|
||||
static void stGameChanged(void * lpData) { ((CCheatInfo *)lpData)->GameChanged(); }
|
||||
|
||||
std::string m_SectionIdent;
|
||||
CThread m_ScanFileThread;
|
||||
SectionFiles m_SectionFiles;
|
||||
CriticalSection m_CS;
|
||||
std::unique_ptr<CIniFile> m_CheatIniFile;
|
||||
bool m_Scanned;
|
||||
bool m_UsingUserFile;
|
||||
};
|
||||
|
||||
CCheatInfo * CheatInfo = nullptr;
|
||||
|
||||
CSettingTypeCheats::CSettingTypeCheats(const char * PostFix) :
|
||||
m_PostFix(PostFix)
|
||||
{
|
||||
}
|
||||
|
||||
CSettingTypeCheats::~CSettingTypeCheats ( void )
|
||||
{
|
||||
}
|
||||
|
||||
void CSettingTypeCheats::Initialize ( void )
|
||||
{
|
||||
WriteTrace(TraceAppInit, TraceDebug, "Start");
|
||||
CheatInfo = new CCheatInfo();
|
||||
WriteTrace(TraceAppInit, TraceDebug, "Done");
|
||||
}
|
||||
|
||||
void CSettingTypeCheats::CleanUp ( void )
|
||||
{
|
||||
if (CheatInfo != nullptr)
|
||||
{
|
||||
delete CheatInfo;
|
||||
CheatInfo = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void CSettingTypeCheats::FlushChanges( void )
|
||||
{
|
||||
if (CheatInfo != nullptr)
|
||||
{
|
||||
CheatInfo->FlushChanges();
|
||||
}
|
||||
}
|
||||
|
||||
bool CSettingTypeCheats::IsSettingSet(void) const
|
||||
{
|
||||
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CSettingTypeCheats::Load (uint32_t /*Index*/, bool & /*Value*/ ) const
|
||||
{
|
||||
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CSettingTypeCheats::Load (uint32_t /*Index*/, uint32_t & /*Value*/ ) const
|
||||
{
|
||||
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CSettingTypeCheats::Load (uint32_t Index, std::string & Value ) const
|
||||
{
|
||||
if (CheatInfo != nullptr)
|
||||
{
|
||||
return CheatInfo->Load(m_PostFix.c_str(), Index, Value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CSettingTypeCheats::LoadDefault (uint32_t /*Index*/, bool & /*Value*/ ) const
|
||||
{
|
||||
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
void CSettingTypeCheats::LoadDefault (uint32_t /*Index*/, uint32_t & /*Value*/ ) const
|
||||
{
|
||||
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
void CSettingTypeCheats::LoadDefault (uint32_t /*Index*/, std::string & /*Value*/ ) const
|
||||
{
|
||||
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
void CSettingTypeCheats::Save (uint32_t /*Index*/, bool /*Value*/ )
|
||||
{
|
||||
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
void CSettingTypeCheats::Save (uint32_t /*Index*/, uint32_t /*Value*/ )
|
||||
{
|
||||
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
void CSettingTypeCheats::Save (uint32_t Index, const std::string & Value )
|
||||
{
|
||||
if (CheatInfo != nullptr)
|
||||
{
|
||||
CheatInfo->Save(m_PostFix.c_str(), Index, Value.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void CSettingTypeCheats::Save (uint32_t Index, const char * Value )
|
||||
{
|
||||
if (CheatInfo != nullptr)
|
||||
{
|
||||
CheatInfo->Save(m_PostFix.c_str(), Index, Value);
|
||||
}
|
||||
}
|
||||
|
||||
void CSettingTypeCheats::Delete (uint32_t Index )
|
||||
{
|
||||
if (CheatInfo != nullptr)
|
||||
{
|
||||
CheatInfo->Delete(m_PostFix.c_str(), Index);
|
||||
}
|
||||
}
|
||||
|
||||
CCheatInfo::CCheatInfo() :
|
||||
m_ScanFileThread(stScanFileThread),
|
||||
m_Scanned(false),
|
||||
m_UsingUserFile(false)
|
||||
{
|
||||
m_ScanFileThread.Start(this);
|
||||
g_Settings->RegisterChangeCB(Game_IniKey, this, stGameChanged);
|
||||
}
|
||||
|
||||
CCheatInfo::~CCheatInfo()
|
||||
{
|
||||
g_Settings->UnregisterChangeCB(Game_IniKey, this, stGameChanged);
|
||||
}
|
||||
|
||||
void CCheatInfo::GameChanged(void)
|
||||
{
|
||||
m_SectionIdent = g_Settings->LoadStringVal(Game_IniKey);
|
||||
|
||||
for (uint32_t i = 0; i < 500; i++)
|
||||
{
|
||||
bool Scanned = false;
|
||||
{
|
||||
CGuard Guard(m_CS);
|
||||
Scanned = m_Scanned;
|
||||
}
|
||||
if (Scanned)
|
||||
{
|
||||
break;
|
||||
}
|
||||
Sleep(100);
|
||||
}
|
||||
|
||||
CGuard Guard(m_CS);
|
||||
SectionFiles::const_iterator itr = m_SectionFiles.find(m_SectionIdent);
|
||||
if (itr != m_SectionFiles.end())
|
||||
{
|
||||
CPath CheatFile(itr->second);
|
||||
if (CheatFile.Exists())
|
||||
{
|
||||
m_CheatIniFile = std::make_unique<CIniFile>(CheatFile);
|
||||
m_CheatIniFile->SetCustomSort(CustomSortData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CCheatInfo::FlushChanges(void)
|
||||
{
|
||||
if (m_CheatIniFile.get() != nullptr)
|
||||
{
|
||||
m_CheatIniFile->FlushChanges();
|
||||
}
|
||||
}
|
||||
|
||||
bool CCheatInfo::Load(const char * PostFix, uint32_t Index, std::string & Value) const
|
||||
{
|
||||
if (m_CheatIniFile.get() == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
stdstr_f Key("Cheat%d%s", Index, PostFix);
|
||||
return m_CheatIniFile->GetString(m_SectionIdent.c_str(), Key.c_str(), "", Value);
|
||||
}
|
||||
|
||||
void CCheatInfo::Save(const char * PostFix, uint32_t Index, const char * Value)
|
||||
{
|
||||
UseUserFile();
|
||||
if (m_CheatIniFile.get() == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (strlen(Value) == 0)
|
||||
{
|
||||
if (strcmp(PostFix, "_O") == 0 || strcmp(PostFix, "_N") == 0)
|
||||
{
|
||||
Value = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
stdstr_f Key("Cheat%d%s", Index, PostFix);
|
||||
m_CheatIniFile->SaveString(m_SectionIdent.c_str(), Key.c_str(), Value);
|
||||
}
|
||||
|
||||
void CCheatInfo::Delete(const char * PostFix, uint32_t Index)
|
||||
{
|
||||
UseUserFile();
|
||||
stdstr_f Key("Cheat%d%s", Index, PostFix);
|
||||
m_CheatIniFile->SaveString(m_SectionIdent.c_str(), Key.c_str(), nullptr);
|
||||
}
|
||||
|
||||
void CCheatInfo::ScanFileThread(void)
|
||||
{
|
||||
SectionFiles Files;
|
||||
CPath CheatFile(g_Settings->LoadStringVal(SupportFile_CheatDir), "*.cht");
|
||||
#ifdef _WIN32
|
||||
CheatFile.NormalizePath(CPath(CPath::MODULE_DIRECTORY));
|
||||
#endif
|
||||
if (CheatFile.FindFirst())
|
||||
{
|
||||
do
|
||||
{
|
||||
CIniFile CheatIniFile(CheatFile);
|
||||
CIniFile::SectionList Sections;
|
||||
CheatIniFile.GetVectorOfSections(Sections);
|
||||
for (CIniFile::SectionList::const_iterator itr = Sections.begin(); itr != Sections.end(); itr++)
|
||||
{
|
||||
Files.insert(SectionFiles::value_type(itr->c_str(), CheatFile));
|
||||
}
|
||||
} while (CheatFile.FindNext());
|
||||
}
|
||||
|
||||
CheatFile = CPath(g_Settings->LoadStringVal(SupportFile_UserCheatDir), "*.cht");
|
||||
#ifdef _WIN32
|
||||
CheatFile.NormalizePath(CPath(CPath::MODULE_DIRECTORY));
|
||||
#endif
|
||||
if (CheatFile.FindFirst())
|
||||
{
|
||||
do
|
||||
{
|
||||
CIniFile CheatIniFile(CheatFile);
|
||||
CIniFile::SectionList Sections;
|
||||
CheatIniFile.GetVectorOfSections(Sections);
|
||||
for (CIniFile::SectionList::const_iterator itr = Sections.begin(); itr != Sections.end(); itr++)
|
||||
{
|
||||
Files[itr->c_str()] = (const char *)CheatFile;
|
||||
}
|
||||
} while (CheatFile.FindNext());
|
||||
}
|
||||
|
||||
{
|
||||
CGuard Guard(m_CS);
|
||||
m_SectionFiles = Files;
|
||||
m_Scanned = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CCheatInfo::CustomSortData(CIniFileBase::KeyValueVector & data)
|
||||
{
|
||||
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;
|
||||
}
|
||||
};
|
||||
std::sort(data.begin(), data.end(), compareKeyValueItem());
|
||||
}
|
||||
|
||||
void CCheatInfo::UseUserFile()
|
||||
{
|
||||
if (m_UsingUserFile)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::string UserCheatDir = g_Settings->LoadStringVal(SupportFile_UserCheatDir);
|
||||
CPath FileName(UserCheatDir.c_str(), ".cht");
|
||||
|
||||
CIniFile::strlist KeyList;
|
||||
if (m_CheatIniFile.get() != nullptr)
|
||||
{
|
||||
CPath CurrentIniFolder(m_CheatIniFile->GetFileName());
|
||||
CurrentIniFolder.SetNameExtension("");
|
||||
CPath UserCheatDirPath(UserCheatDir, "");
|
||||
|
||||
#ifdef _WIN32
|
||||
CurrentIniFolder.NormalizePath(CPath(CPath::MODULE_DIRECTORY));
|
||||
UserCheatDirPath.NormalizePath(CPath(CPath::MODULE_DIRECTORY));
|
||||
#endif
|
||||
if (CurrentIniFolder == UserCheatDirPath)
|
||||
{
|
||||
m_UsingUserFile = true;
|
||||
return;
|
||||
}
|
||||
m_CheatIniFile->GetKeyList(m_SectionIdent.c_str(), KeyList);
|
||||
FileName.SetName(CPath(m_CheatIniFile->GetFileName()).GetName().c_str());
|
||||
}
|
||||
|
||||
if (FileName.GetName().empty())
|
||||
{
|
||||
FileName.SetName(g_Settings->LoadStringVal(Rdb_GoodName).c_str());
|
||||
}
|
||||
#ifdef _WIN32
|
||||
FileName.NormalizePath(CPath(CPath::MODULE_DIRECTORY));
|
||||
#endif
|
||||
if (!FileName.DirectoryExists())
|
||||
{
|
||||
FileName.DirectoryCreate();
|
||||
}
|
||||
|
||||
std::unique_ptr<CIniFile> UserIniFile = std::make_unique<CIniFile>(FileName);
|
||||
UserIniFile->SetCustomSort(CustomSortData);
|
||||
for (CIniFile::strlist::const_iterator itr = KeyList.begin(); itr != KeyList.end(); itr++)
|
||||
{
|
||||
std::string Value = m_CheatIniFile->GetString(m_SectionIdent.c_str(), itr->c_str(), "");
|
||||
UserIniFile->SaveString(m_SectionIdent.c_str(), itr->c_str(), Value.c_str());
|
||||
}
|
||||
UserIniFile->FlushChanges();
|
||||
m_CheatIniFile.reset(UserIniFile.release());
|
||||
m_UsingUserFile = true;
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
/****************************************************************************
|
||||
* *
|
||||
* Project64 - A Nintendo 64 emulator. *
|
||||
* http://www.pj64-emu.com/ *
|
||||
* Copyright (C) 2012 Project64. All rights reserved. *
|
||||
* *
|
||||
* License: *
|
||||
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
||||
* *
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <Project64-core/Settings/SettingType/SettingsType-Base.h>
|
||||
#include <Common/IniFileClass.h>
|
||||
|
||||
class CSettingTypeCheats :
|
||||
public CSettingType
|
||||
{
|
||||
public:
|
||||
CSettingTypeCheats(const char * PostFix);
|
||||
~CSettingTypeCheats();
|
||||
|
||||
virtual bool IndexBasedSetting ( void ) const { return true; }
|
||||
virtual SettingType GetSettingType ( void ) const { return SettingType_CheatSetting; }
|
||||
virtual bool IsSettingSet ( void ) const;
|
||||
|
||||
//return the values
|
||||
virtual bool Load (uint32_t Index, bool & Value ) const;
|
||||
virtual bool Load (uint32_t Index, uint32_t & Value ) const;
|
||||
virtual bool Load (uint32_t Index, std::string & Value ) const;
|
||||
|
||||
//return the default values
|
||||
virtual void LoadDefault (uint32_t Index, bool & Value ) const;
|
||||
virtual void LoadDefault (uint32_t Index, uint32_t & Value ) const;
|
||||
virtual void LoadDefault (uint32_t Index, std::string & Value ) const;
|
||||
|
||||
//Update the settings
|
||||
virtual void Save (uint32_t Index, bool Value );
|
||||
virtual void Save (uint32_t Index, uint32_t Value );
|
||||
virtual void Save (uint32_t Index, const std::string & Value );
|
||||
virtual void Save (uint32_t Index, const char * Value );
|
||||
|
||||
// Delete the setting
|
||||
virtual void Delete (uint32_t Index );
|
||||
|
||||
// Initialize this class to use ini or registry
|
||||
static void Initialize ( void );
|
||||
static void CleanUp ( void );
|
||||
static void FlushChanges ( void );
|
||||
|
||||
protected:
|
||||
static void GameChanged(void * /*Data */);
|
||||
|
||||
//static CIniFile * m_CheatIniFile;
|
||||
static std::string * m_SectionIdent;
|
||||
std::string m_PostFix;
|
||||
|
||||
private:
|
||||
CSettingTypeCheats(void); // Disable default constructor
|
||||
CSettingTypeCheats(const CSettingTypeCheats&); // Disable copy constructor
|
||||
CSettingTypeCheats& operator=(const CSettingTypeCheats&); // Disable assignment
|
||||
|
||||
void CopyCheats(void);
|
||||
};
|
|
@ -9,6 +9,7 @@
|
|||
* *
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include <Project64-core\Settings\SettingType\SettingsType-Application.h>
|
||||
|
||||
class CSettingTypeGame :
|
||||
public CSettingTypeApplication
|
||||
|
@ -16,8 +17,8 @@ class CSettingTypeGame :
|
|||
public:
|
||||
CSettingTypeGame(const char * Name, bool DefaultValue);
|
||||
CSettingTypeGame(const char * Name, const char * DefaultValue);
|
||||
CSettingTypeGame(const char * Name, uint32_t DefaultValue );
|
||||
CSettingTypeGame(const char * Name, SettingID DefaultSetting );
|
||||
CSettingTypeGame(const char * Name, uint32_t DefaultValue);
|
||||
CSettingTypeGame(const char * Name, SettingID DefaultSetting);
|
||||
virtual ~CSettingTypeGame();
|
||||
|
||||
virtual bool IndexBasedSetting ( void ) const { return false; }
|
||||
|
@ -27,23 +28,23 @@ public:
|
|||
static void CleanUp ( void );
|
||||
|
||||
//return the values
|
||||
virtual bool Load (uint32_t Index, bool & Value ) const;
|
||||
virtual bool Load (uint32_t Index, uint32_t & Value ) const;
|
||||
virtual bool Load (uint32_t Index, std::string & Value ) const;
|
||||
virtual bool Load (uint32_t Index, bool & Value) const;
|
||||
virtual bool Load (uint32_t Index, uint32_t & Value) const;
|
||||
virtual bool Load (uint32_t Index, std::string & Value) const;
|
||||
|
||||
//return the default values
|
||||
virtual void LoadDefault (uint32_t Index, bool & Value ) const;
|
||||
virtual void LoadDefault (uint32_t Index, uint32_t & Value ) const;
|
||||
virtual void LoadDefault (uint32_t Index, std::string & Value ) const;
|
||||
virtual void LoadDefault (uint32_t Index, bool & Value) const;
|
||||
virtual void LoadDefault (uint32_t Index, uint32_t & Value) const;
|
||||
virtual void LoadDefault (uint32_t Index, std::string & Value) const;
|
||||
|
||||
//Update the settings
|
||||
virtual void Save (uint32_t Index, bool Value );
|
||||
virtual void Save (uint32_t Index, uint32_t Value );
|
||||
virtual void Save (uint32_t Index, const std::string & Value );
|
||||
virtual void Save (uint32_t Index, const char * Value );
|
||||
virtual void Save (uint32_t Index, bool Value);
|
||||
virtual void Save (uint32_t Index, uint32_t Value);
|
||||
virtual void Save (uint32_t Index, const std::string & Value);
|
||||
virtual void Save (uint32_t Index, const char * Value);
|
||||
|
||||
// Delete the setting
|
||||
virtual void Delete (uint32_t Index );
|
||||
virtual void Delete (uint32_t Index);
|
||||
|
||||
protected:
|
||||
static bool m_RdbEditor;
|
||||
|
|
|
@ -335,23 +335,6 @@ enum SettingID
|
|||
Logging_LogRomHeader,
|
||||
Logging_LogUnknown,
|
||||
|
||||
//Cheats
|
||||
Cheat_Entry,
|
||||
Cheat_Notes,
|
||||
Cheat_Options,
|
||||
Cheat_Active,
|
||||
Cheat_Extension,
|
||||
|
||||
//Enhancement
|
||||
Enhancement_Name,
|
||||
Enhancement_Active,
|
||||
Enhancement_OnByDefault,
|
||||
Enhancement_Overclock,
|
||||
Enhancement_OverclockValue,
|
||||
Enhancement_Gameshark,
|
||||
Enhancement_GamesharkCode,
|
||||
Enhancement_Notes,
|
||||
|
||||
FirstUISettings, LastUISettings = FirstUISettings + MaxPluginSetting,
|
||||
FirstRSPDefaultSet, LastRSPDefaultSet = FirstRSPDefaultSet + MaxPluginSetting,
|
||||
FirstRSPSettings, LastRSPSettings = FirstRSPSettings + MaxPluginSetting,
|
||||
|
|
|
@ -85,7 +85,6 @@
|
|||
<ClCompile Include="UserInterface\Debugger\ScriptSystem.cpp" />
|
||||
<ClCompile Include="UserInterface\Debugger\Symbols.cpp" />
|
||||
<ClCompile Include="UserInterface\DiscordRPC.cpp" />
|
||||
<ClCompile Include="UserInterface\EnhancementConfig.cpp" />
|
||||
<ClCompile Include="UserInterface\MainWindow.cpp" />
|
||||
<ClCompile Include="UserInterface\LoggingUI.cpp" />
|
||||
<ClCompile Include="UserInterface\MainMenu.cpp" />
|
||||
|
@ -159,7 +158,6 @@
|
|||
<ClInclude Include="UserInterface\Debugger\ScriptInstance.h" />
|
||||
<ClInclude Include="UserInterface\Debugger\ScriptSystem.h" />
|
||||
<ClInclude Include="UserInterface\Debugger\Symbols.h" />
|
||||
<ClInclude Include="UserInterface\EnhancementConfig.h" />
|
||||
<ClInclude Include="UserInterface\MainWindow.h" />
|
||||
<ClInclude Include="UserInterface\LoggingUI.h" />
|
||||
<ClInclude Include="UserInterface\MainMenu.h" />
|
||||
|
|
|
@ -207,9 +207,6 @@
|
|||
<ClCompile Include="UserInterface\Settings\SettingsPage-Defaults.cpp">
|
||||
<Filter>Source Files\User Interface Source\Settings Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UserInterface\EnhancementConfig.cpp">
|
||||
<Filter>Source Files\User Interface Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UserInterface\Debugger\CPULog.cpp">
|
||||
<Filter>Source Files\User Interface Source\Debugger Source</Filter>
|
||||
</ClCompile>
|
||||
|
@ -446,9 +443,6 @@
|
|||
<ClInclude Include="UserInterface\Settings\SettingsPage-Defaults.h">
|
||||
<Filter>Header Files\User Interface Headers\Settings Header</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="UserInterface\EnhancementConfig.h">
|
||||
<Filter>Header Files\User Interface Headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="UserInterface\Debugger\CPULog.h">
|
||||
<Filter>Header Files\User Interface Headers\Debugger Headers</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -26,6 +26,5 @@
|
|||
#include <Project64-core/N64System/FramePerSecondClass.h>
|
||||
#include "UserInterface/resource.h"
|
||||
#include "UserInterface/SettingsConfig.h"
|
||||
#include "UserInterface/EnhancementConfig.h"
|
||||
#include "UserInterface/CheatClassUI.h"
|
||||
#include "UserInterface/SupportWindow.h"
|
||||
|
|
|
@ -9,12 +9,11 @@
|
|||
* *
|
||||
****************************************************************************/
|
||||
#include "stdafx.h"
|
||||
#include <Project64-core/Settings/SettingType/SettingsType-Cheats.h>
|
||||
#include <Project64-core/N64System/CheatClass.h>
|
||||
#include <Project64-core\N64System\Enhancement\Enhancements.h>
|
||||
|
||||
CCheatsUI::CCheatsUI(void) :
|
||||
m_EditCheat(m_SelectCheat),
|
||||
m_SelectCheat(m_EditCheat),
|
||||
m_EditCheat(m_Cheats, m_SelectCheat),
|
||||
m_SelectCheat(m_Cheats, m_EditCheat),
|
||||
m_bModal(false)
|
||||
{
|
||||
}
|
||||
|
@ -25,6 +24,7 @@ CCheatsUI::~CCheatsUI()
|
|||
|
||||
void CCheatsUI::Display(HWND hParent, bool BlockExecution)
|
||||
{
|
||||
m_Cheats = g_Enhancements->Cheats();
|
||||
if (g_BaseSystem)
|
||||
{
|
||||
g_BaseSystem->ExternalEvent(SysEvent_PauseCPU_Cheats);
|
||||
|
@ -160,59 +160,8 @@ LRESULT CCheatsUI::OnStateChange(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWnd
|
|||
return 0;
|
||||
}
|
||||
|
||||
std::string CCheatsUI::GetCheatName(int CheatNo, bool AddExtension)
|
||||
{
|
||||
if (CheatNo > CCheats::MaxCheats) { g_Notify->BreakPoint(__FILE__, __LINE__); }
|
||||
stdstr LineEntry = g_Settings->LoadStringIndex(Cheat_Entry, CheatNo);
|
||||
if (LineEntry.length() == 0) { return LineEntry; }
|
||||
|
||||
//Find the start and end of the name which is surrounded in ""
|
||||
int StartOfName = LineEntry.find("\"");
|
||||
if (StartOfName == -1) { return ""; }
|
||||
int EndOfName = LineEntry.find("\"", StartOfName + 1);
|
||||
if (EndOfName == -1) { return ""; }
|
||||
|
||||
stdstr Name = LineEntry.substr(StartOfName + 1, EndOfName - StartOfName - 1);
|
||||
const char * CodeString = &(LineEntry.c_str())[EndOfName + 2];
|
||||
if (!CCheats::IsValid16BitCode(CodeString))
|
||||
{
|
||||
Name.Format("*** %s", Name.c_str());
|
||||
Name.Replace("\\", "\\*** ");
|
||||
}
|
||||
if (AddExtension && CheatUsesCodeExtensions(LineEntry))
|
||||
{
|
||||
stdstr CheatValue(g_Settings->LoadStringIndex(Cheat_Extension, CheatNo));
|
||||
Name.Format("%s (=>%s)", Name.c_str(), CheatValue.c_str());
|
||||
}
|
||||
return Name;
|
||||
}
|
||||
|
||||
bool CCheatsUI::CheatUsesCodeExtensions(const std::string & LineEntry)
|
||||
{
|
||||
//Find the start and end of the name which is surronded in ""
|
||||
if (LineEntry.length() == 0){ return false; }
|
||||
int StartOfName = LineEntry.find("\"");
|
||||
if (StartOfName == -1) { return false; }
|
||||
int EndOfName = LineEntry.find("\"", StartOfName + 1);
|
||||
if (EndOfName == -1) { return false; }
|
||||
|
||||
//Read through the gameshark entries till you find a ??
|
||||
const char *ReadPos = &(LineEntry.c_str())[EndOfName + 2];
|
||||
bool CodeExtension = false;
|
||||
|
||||
for (int i = 0; i < CCheats::MaxGSEntries && CodeExtension == false; i++)
|
||||
{
|
||||
if (strchr(ReadPos, ' ') == NULL) { break; }
|
||||
ReadPos = strchr(ReadPos, ' ') + 1;
|
||||
if (ReadPos[0] == '?' && ReadPos[1] == '?') { CodeExtension = true; }
|
||||
if (ReadPos[2] == '?' && ReadPos[3] == '?') { CodeExtension = true; }
|
||||
if (strchr(ReadPos, ',') == NULL) { continue; }
|
||||
ReadPos = strchr(ReadPos, ',') + 1;
|
||||
}
|
||||
return CodeExtension;
|
||||
}
|
||||
|
||||
CCheatList::CCheatList(CEditCheat & EditCheat) :
|
||||
CCheatList::CCheatList(CEnhancementList & Cheats, CEditCheat & EditCheat) :
|
||||
m_Cheats(Cheats),
|
||||
m_EditCheat(EditCheat),
|
||||
m_hSelectedItem(NULL),
|
||||
m_DeleteingEntries(false)
|
||||
|
@ -260,37 +209,28 @@ LRESULT CCheatList::OnChangeCodeExtension(UINT /*uMsg*/, WPARAM /*wParam*/, LPAR
|
|||
TVITEM item = { 0 };
|
||||
item.mask = TVIF_PARAM;
|
||||
item.hItem = m_hSelectedItem;
|
||||
if (!m_hCheatTree.GetItem(&item))
|
||||
if (!m_hCheatTree.GetItem(&item) || item.lParam == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string LineEntry = g_Settings->LoadStringIndex(Cheat_Entry, item.lParam);
|
||||
if (!CCheatsUI::CheatUsesCodeExtensions(LineEntry))
|
||||
CEnhancement * Enhancement = (CEnhancement *)item.lParam;
|
||||
if (Enhancement->CodeOptionSize() == 0 || Enhancement->GetOptions().empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string Options;
|
||||
if (g_Settings->LoadStringIndex(Cheat_Options, item.lParam, Options) && Options.length() > 0)
|
||||
CEnhancementCodeEx(Enhancement).DoModal();
|
||||
stdstr Name = Enhancement->GetNameAndExtension();
|
||||
const char * ChildName = strrchr(Name.c_str(), '\\');
|
||||
if (ChildName != nullptr)
|
||||
{
|
||||
CCheatsCodeEx(item.lParam).DoModal();
|
||||
Name = &ChildName[1];
|
||||
}
|
||||
|
||||
std::string CheatName(CCheatsUI::GetCheatName(item.lParam, true));
|
||||
const char * Cheat = strrchr(CheatName.c_str(), '\\');
|
||||
if (Cheat == NULL)
|
||||
{
|
||||
Cheat = CheatName.c_str();
|
||||
}
|
||||
else
|
||||
{
|
||||
Cheat += 1;
|
||||
}
|
||||
std::wstring wcCheat = stdstr(Cheat).ToUTF16();
|
||||
std::wstring wName = Name.ToUTF16();
|
||||
item.mask = TVIF_TEXT;
|
||||
item.pszText = (LPWSTR)wcCheat.c_str();
|
||||
item.cchTextMax = CheatName.length();
|
||||
item.pszText = (LPWSTR)wName.c_str();
|
||||
item.cchTextMax = wName.length();
|
||||
m_hCheatTree.SetItem(&item);
|
||||
return 0;
|
||||
}
|
||||
|
@ -317,9 +257,9 @@ LRESULT CCheatList::OnPopupDelete(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWn
|
|||
LRESULT CCheatList::OnUnmark(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
ChangeChildrenStatus(TVI_ROOT, false);
|
||||
if (g_BaseSystem)
|
||||
if (g_Enhancements != nullptr)
|
||||
{
|
||||
g_BaseSystem->SetCheatsSlectionChanged(true);
|
||||
g_Enhancements->UpdateCheats();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -345,12 +285,11 @@ LRESULT CCheatList::OnTreeClicked(NMHDR* lpnmh)
|
|||
TVITEM item = { 0 };
|
||||
item.mask = TVIF_PARAM;
|
||||
item.hItem = ht.hItem;
|
||||
m_hCheatTree.GetItem(&item);
|
||||
std::string LineEntry = g_Settings->LoadStringIndex(Cheat_Entry, item.lParam);
|
||||
if (CCheatsUI::CheatUsesCodeExtensions(LineEntry))
|
||||
m_hCheatTree.GetItem(&item);
|
||||
if (item.lParam != NULL)
|
||||
{
|
||||
std::string CheatExtension;
|
||||
if (!g_Settings->LoadStringIndex(Cheat_Extension, item.lParam, CheatExtension))
|
||||
CEnhancement * Enhancement = (CEnhancement *)item.lParam;
|
||||
if (Enhancement->CodeOptionSize() != 0 && Enhancement->GetOptions().size() > 0 && !Enhancement->OptionSelected())
|
||||
{
|
||||
SendMessage(UM_CHANGECODEEXTENSION, 0, (LPARAM)ht.hItem);
|
||||
TV_SetCheckState(ht.hItem, TV_STATE_CLEAR);
|
||||
|
@ -374,10 +313,10 @@ LRESULT CCheatList::OnTreeClicked(NMHDR* lpnmh)
|
|||
case TV_STATE_CLEAR: TV_SetCheckState(ht.hItem, TV_STATE_CHECKED); break;
|
||||
case TV_STATE_INDETERMINATE: TV_SetCheckState(ht.hItem, TV_STATE_CLEAR); break;
|
||||
}
|
||||
|
||||
if (g_BaseSystem)
|
||||
|
||||
if (g_Enhancements != nullptr)
|
||||
{
|
||||
g_BaseSystem->SetCheatsSlectionChanged(true);
|
||||
g_Enhancements->UpdateCheats();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -438,24 +377,23 @@ LRESULT CCheatList::OnTreeDClicked(NMHDR* lpnmh)
|
|||
LRESULT CCheatList::OnTreeSelChanged(NMHDR * /*lpnmh*/)
|
||||
{
|
||||
HTREEITEM hItem = m_hCheatTree.GetSelectedItem();
|
||||
GetDlgItem(IDC_NOTES).SetWindowText(L"");
|
||||
if (m_hCheatTree.GetChildItem(hItem) == NULL)
|
||||
{
|
||||
TVITEM item = { 0 };
|
||||
item.mask = TVIF_PARAM;
|
||||
item.hItem = hItem;
|
||||
m_hCheatTree.GetItem(&item);
|
||||
|
||||
stdstr Notes(g_Settings->LoadStringIndex(Cheat_Notes, item.lParam));
|
||||
GetDlgItem(IDC_NOTES).SetWindowText(Notes.ToUTF16().c_str());
|
||||
if (m_EditCheat.m_hWnd != NULL)
|
||||
if (item.lParam != NULL)
|
||||
{
|
||||
m_EditCheat.SendMessage(CEditCheat::WM_EDITCHEAT, item.lParam, 0);
|
||||
CEnhancement * Enhancement = (CEnhancement *)item.lParam;
|
||||
GetDlgItem(IDC_NOTES).SetWindowText(stdstr(Enhancement->GetNote()).ToUTF16().c_str());
|
||||
if (m_EditCheat.m_hWnd != NULL)
|
||||
{
|
||||
m_EditCheat.SendMessage(CEditCheat::WM_EDITCHEAT, item.lParam, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GetDlgItem(IDC_NOTES).SetWindowText(L"");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -466,22 +404,25 @@ void CCheatList::RefreshItems()
|
|||
m_DeleteingEntries = true;
|
||||
TreeView_DeleteAllItems(m_hCheatTree);
|
||||
m_DeleteingEntries = false;
|
||||
for (int i = 0; i < CCheats::MaxCheats; i++)
|
||||
{
|
||||
std::string Name = CCheatsUI::GetCheatName(i, true);
|
||||
if (Name.length() == 0) { break; }
|
||||
|
||||
AddCodeLayers(i, stdstr(Name).ToUTF16(), TVI_ROOT, g_Settings->LoadBoolIndex(Cheat_Active, i) != 0);
|
||||
for (CEnhancementList::iterator itr = m_Cheats.begin(); itr != m_Cheats.end(); itr++)
|
||||
{
|
||||
std::string Name = itr->second.GetNameAndExtension();
|
||||
if (Name.length() == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
AddCodeLayers((LPARAM)&itr->second, stdstr(Name).ToUTF16(), TVI_ROOT, itr->second.Active());
|
||||
}
|
||||
}
|
||||
|
||||
void CCheatList::AddCodeLayers(int CheatNumber, const std::wstring &CheatName, HTREEITEM hParent, bool CheatActive)
|
||||
void CCheatList::AddCodeLayers(LPARAM Enhancement, const std::wstring &Name, HTREEITEM hParent, bool CheatActive)
|
||||
{
|
||||
TV_INSERTSTRUCT tv;
|
||||
|
||||
wchar_t Text[500], Item[500];
|
||||
if (CheatName.length() > (sizeof(Text) - 5)) { g_Notify->BreakPoint(__FILE__, __LINE__); }
|
||||
wcscpy(Text, CheatName.c_str());
|
||||
if (Name.length() > (sizeof(Text) - 5)) { g_Notify->BreakPoint(__FILE__, __LINE__); }
|
||||
wcscpy(Text, Name.c_str());
|
||||
if (wcschr(Text, L'\\') > 0) { *wcschr(Text, L'\\') = 0; }
|
||||
|
||||
tv.item.mask = TVIF_TEXT;
|
||||
|
@ -500,11 +441,11 @@ void CCheatList::AddCodeLayers(int CheatNumber, const std::wstring &CheatName, H
|
|||
}
|
||||
size_t StartPos = wcslen(Text) + 1;
|
||||
std::wstring TempCheatName;
|
||||
if (StartPos < CheatName.length())
|
||||
if (StartPos < Name.length())
|
||||
{
|
||||
TempCheatName = CheatName.substr(StartPos);
|
||||
TempCheatName = Name.substr(StartPos);
|
||||
}
|
||||
AddCodeLayers(CheatNumber, TempCheatName, tv.item.hItem, CheatActive);
|
||||
AddCodeLayers(Enhancement, TempCheatName, tv.item.hItem, CheatActive);
|
||||
return;
|
||||
}
|
||||
tv.item.hItem = TreeView_GetNextSibling(m_hCheatTree, tv.item.hItem);
|
||||
|
@ -513,13 +454,13 @@ void CCheatList::AddCodeLayers(int CheatNumber, const std::wstring &CheatName, H
|
|||
tv.hInsertAfter = TVI_SORT;
|
||||
tv.item.mask = TVIF_TEXT | TVIF_PARAM;
|
||||
tv.item.pszText = Text;
|
||||
tv.item.lParam = CheatNumber;
|
||||
tv.item.lParam = Enhancement;
|
||||
tv.hParent = hParent;
|
||||
hParent = TreeView_InsertItem(m_hCheatTree, &tv);
|
||||
TV_SetCheckState(hParent, CheatActive ? TV_STATE_CHECKED : TV_STATE_CLEAR);
|
||||
|
||||
if (wcscmp(Text, CheatName.c_str()) == 0) { return; }
|
||||
AddCodeLayers(CheatNumber, CheatName.substr(wcslen(Text) + 1), hParent, CheatActive);
|
||||
if (wcscmp(Text, Name.c_str()) == 0) { return; }
|
||||
AddCodeLayers(Enhancement, Name.substr(wcslen(Text) + 1), hParent, CheatActive);
|
||||
}
|
||||
|
||||
void CCheatList::ChangeChildrenStatus(HTREEITEM hParent, bool Checked)
|
||||
|
@ -533,22 +474,18 @@ void CCheatList::ChangeChildrenStatus(HTREEITEM hParent, bool Checked)
|
|||
item.mask = TVIF_PARAM;
|
||||
item.hItem = hParent;
|
||||
m_hCheatTree.GetItem(&item);
|
||||
|
||||
if (Checked)
|
||||
if (item.lParam == NULL)
|
||||
{
|
||||
std::string LineEntry = g_Settings->LoadStringIndex(Cheat_Entry, item.lParam);
|
||||
if (CCheatsUI::CheatUsesCodeExtensions(LineEntry))
|
||||
{
|
||||
std::string CheatExten;
|
||||
if (!g_Settings->LoadStringIndex(Cheat_Extension, item.lParam, CheatExten) || CheatExten.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
CEnhancement * Enhancement = (CEnhancement *)item.lParam;
|
||||
if (Checked && Enhancement->CodeOptionSize() != 0 && Enhancement->GetOptions().size() > 0 && !Enhancement->OptionSelected())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TV_SetCheckState(hParent, Checked ? TV_STATE_CHECKED : TV_STATE_CLEAR);
|
||||
g_Settings->SaveBoolIndex(Cheat_Active, item.lParam, Checked);
|
||||
Enhancement->SetActive(Checked);
|
||||
return;
|
||||
}
|
||||
TV_CHECK_STATE state = TV_STATE_UNKNOWN;
|
||||
|
@ -596,60 +533,20 @@ void CCheatList::CheckParentStatus(HTREEITEM hParent)
|
|||
}
|
||||
}
|
||||
|
||||
void CCheatList::DeleteCheat(int Index)
|
||||
void CCheatList::DeleteCheat(LPARAM Enhancement)
|
||||
{
|
||||
for (int CheatNo = Index; CheatNo < CCheats::MaxCheats; CheatNo++)
|
||||
for (CEnhancementList::iterator itr = m_Cheats.begin(); itr != m_Cheats.end(); itr++)
|
||||
{
|
||||
stdstr LineEntry = g_Settings->LoadStringIndex(Cheat_Entry, CheatNo + 1);
|
||||
if (LineEntry.empty())
|
||||
if (Enhancement != (LPARAM)&itr->second)
|
||||
{
|
||||
g_Settings->DeleteSettingIndex(Cheat_Options, CheatNo);
|
||||
g_Settings->DeleteSettingIndex(Cheat_Notes, CheatNo);
|
||||
g_Settings->DeleteSettingIndex(Cheat_Extension, CheatNo);
|
||||
g_Settings->DeleteSettingIndex(Cheat_Entry, CheatNo);
|
||||
g_Settings->DeleteSettingIndex(Cheat_Active, CheatNo);
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
stdstr Value;
|
||||
if (g_Settings->LoadStringIndex(Cheat_Options, CheatNo + 1, Value))
|
||||
{
|
||||
g_Settings->SaveStringIndex(Cheat_Options, CheatNo, Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Settings->DeleteSettingIndex(Cheat_Options, CheatNo);
|
||||
}
|
||||
|
||||
if (g_Settings->LoadStringIndex(Cheat_Notes, CheatNo + 1, Value))
|
||||
{
|
||||
g_Settings->SaveStringIndex(Cheat_Notes, CheatNo, Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Settings->DeleteSettingIndex(Cheat_Notes, CheatNo);
|
||||
}
|
||||
|
||||
if (g_Settings->LoadStringIndex(Cheat_Extension, CheatNo + 1, Value))
|
||||
{
|
||||
g_Settings->SaveStringIndex(Cheat_Extension, CheatNo, Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Settings->DeleteSettingIndex(Cheat_Extension, CheatNo);
|
||||
}
|
||||
|
||||
bool bValue;
|
||||
if (g_Settings->LoadBoolIndex(Cheat_Active, CheatNo + 1, bValue))
|
||||
{
|
||||
g_Settings->SaveBoolIndex(Cheat_Active, CheatNo, bValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Settings->DeleteSettingIndex(Cheat_Active, CheatNo);
|
||||
}
|
||||
g_Settings->SaveStringIndex(Cheat_Entry, CheatNo, LineEntry);
|
||||
m_Cheats.erase(itr);
|
||||
g_Enhancements->UpdateCheats(m_Cheats);
|
||||
//RecordCurrentValues();
|
||||
RefreshItems();
|
||||
break;
|
||||
}
|
||||
CSettingTypeCheats::FlushChanges();
|
||||
}
|
||||
|
||||
CCheatList::TV_CHECK_STATE CCheatList::TV_GetCheckState(HTREEITEM hItem)
|
||||
|
@ -710,9 +607,10 @@ void CCheatList::MenuSetText(HMENU hMenu, int MenuPos, const wchar_t * Title, co
|
|||
SetMenuItemInfoW(hMenu, MenuPos, true, &MenuInfo);
|
||||
}
|
||||
|
||||
CEditCheat::CEditCheat(CCheatList & CheatList) :
|
||||
CEditCheat::CEditCheat(CEnhancementList & Cheats, CCheatList & CheatList) :
|
||||
m_Cheats(Cheats),
|
||||
m_CheatList(CheatList),
|
||||
m_EditCheat(-1)
|
||||
m_EditEnhancement(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -730,149 +628,126 @@ LRESULT CEditCheat::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lPar
|
|||
GetDlgItem(IDC_CHEATNOTES).SetWindowText(wGS(CHEAT_ADDCHEAT_NOTES).c_str());
|
||||
GetDlgItem(IDC_NEWCHEAT).SetWindowText(wGS(CHEAT_ADDCHEAT_NEW).c_str());
|
||||
GetDlgItem(IDC_ADD).SetWindowText(wGS(CHEAT_ADDCHEAT_ADD).c_str());
|
||||
RecordCheatValues();
|
||||
RecordCurrentValues();
|
||||
return 0;
|
||||
}
|
||||
|
||||
LRESULT CEditCheat::OnEditCheat(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
m_EditCheat = (int32_t)wParam;
|
||||
if (m_EditCheat < 0)
|
||||
if (ValuesChanged())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CheatChanged())
|
||||
m_EditEnhancement = (CEnhancement *)wParam;
|
||||
if (m_EditEnhancement == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string CheatEntryStr = g_Settings->LoadStringIndex(Cheat_Entry, m_EditCheat);
|
||||
int32_t len = strrchr(CheatEntryStr.c_str(), '"') - strchr(CheatEntryStr.c_str(), '"') - 1;
|
||||
stdstr CheatName(strchr(CheatEntryStr.c_str(), '"') + 1);
|
||||
CheatName.resize(len);
|
||||
GetDlgItem(IDC_CODE_NAME).SetWindowText(CheatName.ToUTF16().c_str());
|
||||
|
||||
const char * ReadPos = strrchr(CheatEntryStr.c_str(), '"') + 2;
|
||||
GetDlgItem(IDC_CODE_NAME).SetWindowText(stdstr(m_EditEnhancement->GetName()).ToUTF16().c_str());
|
||||
stdstr Buffer;
|
||||
do
|
||||
const CEnhancement::CodeEntries & Entries = m_EditEnhancement->GetEntries();
|
||||
for (size_t i = 0, n = Entries.size(); i < n; i++)
|
||||
{
|
||||
const char * End = strchr(ReadPos, ',');
|
||||
if (End)
|
||||
{
|
||||
Buffer.append(ReadPos, End - ReadPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
Buffer.append(ReadPos);
|
||||
}
|
||||
|
||||
ReadPos = strchr(ReadPos, ',');
|
||||
if (ReadPos != NULL)
|
||||
const CEnhancement::CodeEntry Entry = Entries[i];
|
||||
if (!Buffer.empty())
|
||||
{
|
||||
Buffer.append("\r\n");
|
||||
ReadPos += 1;
|
||||
}
|
||||
} while (ReadPos);
|
||||
Buffer += stdstr_f("%08X %s", Entry.Command, Entry.Value.c_str());
|
||||
}
|
||||
GetDlgItem(IDC_CHEAT_CODES).SetWindowText(Buffer.ToUTF16().c_str());
|
||||
|
||||
//Add option values to screen
|
||||
std::string CheatOptionStr = g_Settings->LoadStringIndex(Cheat_Options, m_EditCheat);
|
||||
ReadPos = strchr(CheatOptionStr.c_str(), '$');
|
||||
Buffer.erase();
|
||||
if (ReadPos)
|
||||
const CEnhancement::CodeOptions & Options = m_EditEnhancement->GetOptions();
|
||||
Buffer.clear();
|
||||
for (size_t i = 0, n = Options.size(); i < n; i++)
|
||||
{
|
||||
ReadPos += 1;
|
||||
do
|
||||
const CEnhancement::CodeOption Option = Options[i];
|
||||
if (!Buffer.empty())
|
||||
{
|
||||
const char * End = strchr(ReadPos, ',');
|
||||
if (End)
|
||||
{
|
||||
Buffer.append(ReadPos, End - ReadPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
Buffer.append(ReadPos);
|
||||
}
|
||||
ReadPos = strchr(ReadPos, '$');
|
||||
if (ReadPos != NULL)
|
||||
{
|
||||
Buffer.append("\r\n");
|
||||
ReadPos += 1;
|
||||
}
|
||||
} while (ReadPos);
|
||||
Buffer.append("\r\n");
|
||||
}
|
||||
Buffer += stdstr_f(m_EditEnhancement->CodeOptionSize() == 2 ? "%02X %s" : "%04X %s", Option.Value, Option.Name.c_str());
|
||||
}
|
||||
GetDlgItem(IDC_CHEAT_OPTIONS).SetWindowText(Buffer.ToUTF16().c_str());
|
||||
|
||||
stdstr CheatNotesStr = g_Settings->LoadStringIndex(Cheat_Notes, m_EditCheat);
|
||||
GetDlgItem(IDC_NOTES).SetWindowText(CheatNotesStr.ToUTF16().c_str());
|
||||
GetDlgItem(IDC_NOTES).SetWindowText(stdstr(m_EditEnhancement->GetNote()).ToUTF16().c_str());
|
||||
GetDlgItem(IDC_ADD).SetWindowTextW(wGS(CHEAT_EDITCHEAT_UPDATE).c_str());
|
||||
|
||||
SendMessage(WM_COMMAND, MAKELPARAM(IDC_CHEAT_CODES, EN_CHANGE), (LPARAM)(HWND)GetDlgItem(IDC_CHEAT_CODES));
|
||||
GetDlgItem(IDC_ADD).SetWindowTextW(wGS(CHEAT_EDITCHEAT_UPDATE).c_str());
|
||||
RecordCheatValues();
|
||||
RecordCurrentValues();
|
||||
return 0;
|
||||
}
|
||||
|
||||
LRESULT CEditCheat::OnAddCheat(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
std::string NewCheatName = GetItemText(IDC_CODE_NAME);
|
||||
int i = 0;
|
||||
for (i = 0; i < CCheats::MaxCheats; i++)
|
||||
for (CEnhancementList::const_iterator itr = m_Cheats.begin(); itr != m_Cheats.end(); itr++)
|
||||
{
|
||||
if (m_EditCheat == i)
|
||||
const CEnhancement & Enhancement = itr->second;
|
||||
if (_stricmp(Enhancement.GetName().c_str(), NewCheatName.c_str()) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
std::string CheatName = CCheatsUI::GetCheatName(i, false);
|
||||
if (CheatName.length() == 0)
|
||||
if (m_EditEnhancement == &Enhancement)
|
||||
{
|
||||
if (m_EditCheat < 0)
|
||||
{
|
||||
m_EditCheat = i;
|
||||
}
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if (_stricmp(CheatName.c_str(), NewCheatName.c_str()) == 0)
|
||||
{
|
||||
g_Notify->DisplayWarning(GS(MSG_CHEAT_NAME_IN_USE));
|
||||
GetDlgItem(IDC_CODE_NAME).SetFocus();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (m_EditCheat < 0 && i == CCheats::MaxCheats)
|
||||
{
|
||||
g_Notify->DisplayError(GS(MSG_MAX_CHEATS));
|
||||
return true;
|
||||
g_Notify->DisplayWarning(GS(MSG_CHEAT_NAME_IN_USE));
|
||||
GetDlgItem(IDC_CODE_NAME).SetFocus();
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool validcodes, validoptions, nooptions;
|
||||
|
||||
bool validcodes = false, validoptions = false, nooptions = false;
|
||||
CodeFormat Format;
|
||||
stdstr_f Cheat("\"%s\"%s", NewCheatName.c_str(), ReadCodeString(validcodes, validoptions, nooptions, Format).c_str());
|
||||
stdstr Options = ReadOptionsString(validoptions, Format);
|
||||
CEnhancement::CodeEntries Entries = ReadCodeEntries(validcodes, validoptions, nooptions, Format);
|
||||
CEnhancement::CodeOptions Options;
|
||||
if (validcodes && !nooptions)
|
||||
{
|
||||
Options = ReadOptions(validoptions, Format);
|
||||
}
|
||||
if (!validcodes || !validoptions)
|
||||
{
|
||||
g_Notify->BreakPoint(__FILE__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_Settings->SaveStringIndex(Cheat_Entry, m_EditCheat, Cheat.c_str());
|
||||
g_Settings->SaveStringIndex(Cheat_Notes, m_EditCheat, GetItemText(IDC_NOTES));
|
||||
g_Settings->SaveStringIndex(Cheat_Options, m_EditCheat, Options);
|
||||
RecordCheatValues();
|
||||
CSettingTypeCheats::FlushChanges();
|
||||
if (m_EditEnhancement != nullptr)
|
||||
{
|
||||
m_EditEnhancement->SetName(NewCheatName.c_str());
|
||||
m_EditEnhancement->SetEntries(Entries);
|
||||
m_EditEnhancement->SetOptions(Options);
|
||||
m_EditEnhancement->SetNote(GetItemText(IDC_NOTES).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
CEnhancement Enhancement("Cheat");
|
||||
Enhancement.SetName(NewCheatName.c_str());
|
||||
Enhancement.SetEntries(Entries);
|
||||
Enhancement.SetOptions(Options);
|
||||
Enhancement.SetNote(GetItemText(IDC_NOTES).c_str());
|
||||
m_Cheats.AddItem(Enhancement);
|
||||
}
|
||||
g_Enhancements->UpdateCheats(m_Cheats);
|
||||
RecordCurrentValues();
|
||||
m_CheatList.RefreshItems();
|
||||
return 0;
|
||||
}
|
||||
|
||||
LRESULT CEditCheat::OnNewCheat(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
if (CheatChanged())
|
||||
if (ValuesChanged())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
m_EditCheat = -1;
|
||||
m_EditEnhancement = nullptr;
|
||||
SetDlgItemText(IDC_CODE_NAME, L"");
|
||||
SetDlgItemText(IDC_CHEAT_CODES, L"");
|
||||
SetDlgItemText(IDC_CHEAT_OPTIONS, L"");
|
||||
SetDlgItemText(IDC_NOTES, L"");
|
||||
GetDlgItem(IDC_ADD).EnableWindow(false);
|
||||
GetDlgItem(IDC_CHEAT_OPTIONS).EnableWindow(false);
|
||||
RecordCheatValues();
|
||||
RecordCurrentValues();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -880,10 +755,10 @@ LRESULT CEditCheat::OnCodeNameChanged(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /
|
|||
{
|
||||
bool validcodes, validoptions, nooptions;
|
||||
CodeFormat Format;
|
||||
ReadCodeString(validcodes, validoptions, nooptions, Format);
|
||||
ReadCodeEntries(validcodes, validoptions, nooptions, Format);
|
||||
if (!nooptions)
|
||||
{
|
||||
ReadOptionsString(validoptions, Format);
|
||||
ReadOptions(validoptions, Format);
|
||||
}
|
||||
|
||||
bool CanAdd = validcodes && (validoptions || nooptions) && GetDlgItem(IDC_CODE_NAME).GetWindowTextLength() > 0;
|
||||
|
@ -895,7 +770,7 @@ LRESULT CEditCheat::OnCheatCodeChanged(WORD /*wNotifyCode*/, WORD /*wID*/, HWND
|
|||
{
|
||||
bool validcodes, validoptions, nooptions;
|
||||
CodeFormat Format;
|
||||
ReadCodeString(validcodes, validoptions, nooptions, Format);
|
||||
ReadCodeEntries(validcodes, validoptions, nooptions, Format);
|
||||
|
||||
if (Format > 0 && !GetDlgItem(IDC_LABEL_OPTIONS).IsWindowEnabled())
|
||||
{
|
||||
|
@ -912,7 +787,7 @@ LRESULT CEditCheat::OnCheatCodeChanged(WORD /*wNotifyCode*/, WORD /*wID*/, HWND
|
|||
|
||||
if (!nooptions)
|
||||
{
|
||||
ReadOptionsString(validoptions, Format);
|
||||
ReadOptions(validoptions, Format);
|
||||
}
|
||||
|
||||
bool CanAdd = validcodes && (validoptions || nooptions) && GetDlgItem(IDC_CODE_NAME).GetWindowTextLength() > 0;
|
||||
|
@ -924,10 +799,10 @@ LRESULT CEditCheat::OnCheatOptionsChanged(WORD /*wNotifyCode*/, WORD /*wID*/, HW
|
|||
{
|
||||
bool ValidCodes, ValidOptions, NoOptions;
|
||||
CodeFormat Format;
|
||||
ReadCodeString(ValidCodes, ValidOptions, NoOptions, Format);
|
||||
ReadCodeEntries(ValidCodes, ValidOptions, NoOptions, Format);
|
||||
if (!NoOptions)
|
||||
{
|
||||
ReadOptionsString(ValidOptions, Format);
|
||||
ReadOptions(ValidOptions, Format);
|
||||
}
|
||||
|
||||
bool CanAdd = ValidCodes && (ValidOptions || NoOptions) && GetDlgItem(IDC_CODE_NAME).GetWindowTextLength() > 0;
|
||||
|
@ -935,12 +810,13 @@ LRESULT CEditCheat::OnCheatOptionsChanged(WORD /*wNotifyCode*/, WORD /*wID*/, HW
|
|||
return 0;
|
||||
}
|
||||
|
||||
std::string CEditCheat::ReadCodeString(bool &ValidCodes, bool &ValidOptions, bool &NoOptions, CodeFormat & Format)
|
||||
CEnhancement::CodeEntries CEditCheat::ReadCodeEntries(bool &ValidCodes, bool &ValidOptions, bool &NoOptions, CodeFormat & Format)
|
||||
{
|
||||
const char * FormatNormal = "XXXXXXXX XXXX";
|
||||
const char * FormatOptionLB = "XXXXXXXX XX??";
|
||||
const char * FormatOptionW = "XXXXXXXX ????";
|
||||
|
||||
CEnhancement::CodeEntries Entries;
|
||||
ValidCodes = true;
|
||||
ValidOptions = true;
|
||||
NoOptions = true;
|
||||
|
@ -953,8 +829,6 @@ std::string CEditCheat::ReadCodeString(bool &ValidCodes, bool &ValidOptions, boo
|
|||
ValidCodes = false;
|
||||
}
|
||||
|
||||
std::string CodeString;
|
||||
int NumCodes = 0;
|
||||
for (int i = 0; i < NumLines; i++)
|
||||
{
|
||||
wchar_t wc_str[128];
|
||||
|
@ -982,11 +856,21 @@ std::string CEditCheat::ReadCodeString(bool &ValidCodes, bool &ValidOptions, boo
|
|||
}
|
||||
}
|
||||
|
||||
CEnhancement::CodeEntry Entry;
|
||||
Entry.Command = strtoul(str.c_str(), 0, 16);
|
||||
const char * ReadPos = strchr(str.c_str(), ' ');
|
||||
if (ReadPos != nullptr)
|
||||
{
|
||||
Entry.Value = ReadPos + 1;
|
||||
Entries.push_back(Entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
Entries.clear();
|
||||
break;
|
||||
}
|
||||
if (strcmp(TempFormat, FormatNormal) == 0)
|
||||
{
|
||||
CodeString += ",";
|
||||
CodeString += str.c_str();
|
||||
NumCodes += 1;
|
||||
if (Format == CodeFormat_Invalid)
|
||||
{
|
||||
Format = CodeFormat_Normal;
|
||||
|
@ -996,9 +880,6 @@ std::string CEditCheat::ReadCodeString(bool &ValidCodes, bool &ValidOptions, boo
|
|||
{
|
||||
if (Format != CodeFormat_Word)
|
||||
{
|
||||
CodeString += ",";
|
||||
CodeString += str.c_str();
|
||||
NumCodes += 1;
|
||||
Format = CodeFormat_LowerByte;
|
||||
NoOptions = false;
|
||||
ValidOptions = false;
|
||||
|
@ -1012,9 +893,6 @@ std::string CEditCheat::ReadCodeString(bool &ValidCodes, bool &ValidOptions, boo
|
|||
{
|
||||
if (Format != CodeFormat_LowerByte)
|
||||
{
|
||||
CodeString += ",";
|
||||
CodeString += str.c_str();
|
||||
NumCodes += 1;
|
||||
Format = CodeFormat_Word;
|
||||
NoOptions = false;
|
||||
ValidOptions = false;
|
||||
|
@ -1030,20 +908,20 @@ std::string CEditCheat::ReadCodeString(bool &ValidCodes, bool &ValidOptions, boo
|
|||
}
|
||||
}
|
||||
|
||||
if (CodeString.length() == 0)
|
||||
if (Entries.empty())
|
||||
{
|
||||
ValidCodes = false;
|
||||
}
|
||||
return CodeString;
|
||||
return Entries;
|
||||
}
|
||||
|
||||
std::string CEditCheat::ReadOptionsString(bool &validoptions, CodeFormat Format)
|
||||
CEnhancement::CodeOptions CEditCheat::ReadOptions(bool &validoptions, CodeFormat Format)
|
||||
{
|
||||
CEnhancement::CodeOptions Options;
|
||||
validoptions = true;
|
||||
|
||||
CEdit CheatOptions(GetDlgItem(IDC_CHEAT_OPTIONS));
|
||||
int NumLines = CheatOptions.GetLineCount();
|
||||
int NumOptions = 0;
|
||||
std::string OptionsStr;
|
||||
|
||||
for (int i = 0; i < NumLines; i++)
|
||||
|
@ -1057,6 +935,7 @@ std::string CEditCheat::ReadOptionsString(bool &validoptions, CodeFormat Format)
|
|||
wc_str[len] = 0;
|
||||
|
||||
std::string str = stdstr().FromUTF16(wc_str);
|
||||
CEnhancement::CodeOption Option;
|
||||
|
||||
switch (Format)
|
||||
{
|
||||
|
@ -1077,14 +956,9 @@ std::string CEditCheat::ReadOptionsString(bool &validoptions, CodeFormat Format)
|
|||
break;
|
||||
}
|
||||
|
||||
for (int c = 0; c < 2; c++)
|
||||
{
|
||||
str[c] = (char)toupper(str[c]);
|
||||
}
|
||||
|
||||
OptionsStr += OptionsStr.empty() ? "$" : ",$";
|
||||
OptionsStr += str.c_str();
|
||||
NumOptions += 1;
|
||||
Option.Name = &str[3];
|
||||
Option.Value = (uint16_t)strtoul(str.c_str(), 0, 16);
|
||||
Options.push_back(Option);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1109,15 +983,9 @@ std::string CEditCheat::ReadOptionsString(bool &validoptions, CodeFormat Format)
|
|||
validoptions = false;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int c = 0; c < 4; c++)
|
||||
{
|
||||
str[c] = (char)toupper(str[c]);
|
||||
}
|
||||
|
||||
OptionsStr += OptionsStr.empty() ? "$" : ",$";
|
||||
OptionsStr += str.c_str();
|
||||
NumOptions += 1;
|
||||
Option.Name = &str[5];
|
||||
Option.Value = (uint16_t)strtoul(str.c_str(), 0, 16);
|
||||
Options.push_back(Option);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1125,17 +993,20 @@ std::string CEditCheat::ReadOptionsString(bool &validoptions, CodeFormat Format)
|
|||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
validoptions = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (NumOptions < 1)
|
||||
if (Options.size() == 0)
|
||||
{
|
||||
validoptions = false;
|
||||
}
|
||||
return OptionsStr;
|
||||
return Options;
|
||||
}
|
||||
|
||||
void CEditCheat::RecordCheatValues(void)
|
||||
void CEditCheat::RecordCurrentValues(void)
|
||||
{
|
||||
m_EditName = GetItemText(IDC_CODE_NAME);
|
||||
m_EditCode = GetItemText(IDC_CHEAT_CODES);
|
||||
|
@ -1143,7 +1014,7 @@ void CEditCheat::RecordCheatValues(void)
|
|||
m_EditNotes = GetItemText(IDC_NOTES);
|
||||
}
|
||||
|
||||
bool CEditCheat::CheatChanged(void)
|
||||
bool CEditCheat::ValuesChanged(void)
|
||||
{
|
||||
bool Changed = false;
|
||||
if (m_EditName != GetItemText(IDC_CODE_NAME) ||
|
||||
|
@ -1184,48 +1055,47 @@ std::string CEditCheat::GetItemText(int nIDDlgItem)
|
|||
return stdstr().FromUTF16(Result.c_str());
|
||||
}
|
||||
|
||||
CCheatsCodeEx::CCheatsCodeEx(int EditCheat) :
|
||||
m_EditCheat(EditCheat)
|
||||
CEnhancementCodeEx::CEnhancementCodeEx(CEnhancement * Enhancement) :
|
||||
m_Enhancement(Enhancement)
|
||||
{
|
||||
}
|
||||
|
||||
LRESULT CCheatsCodeEx::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
|
||||
LRESULT CEnhancementCodeEx::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
SetWindowText(wGS(CHEAT_CODE_EXT_TITLE).c_str());
|
||||
GetDlgItem(IDC_NOTE).SetWindowText(wGS(CHEAT_CODE_EXT_TXT).c_str());
|
||||
GetDlgItem(IDOK).SetWindowText(wGS(CHEAT_OK).c_str());
|
||||
GetDlgItem(IDCANCEL).SetWindowText(wGS(CHEAT_CANCEL).c_str());
|
||||
|
||||
stdstr CheatName = CCheatsUI::GetCheatName(m_EditCheat, false);
|
||||
GetDlgItem(IDC_CHEAT_NAME).SetWindowText(CheatName.ToUTF16().c_str());
|
||||
|
||||
std::string Options(g_Settings->LoadStringIndex(Cheat_Options, m_EditCheat));
|
||||
std::string CurrentExt(g_Settings->LoadStringIndex(Cheat_Extension, m_EditCheat));
|
||||
const char * ReadPos = Options.c_str();
|
||||
GetDlgItem(IDC_CHEAT_NAME).SetWindowText(stdstr(m_Enhancement->GetName()).ToUTF16().c_str());
|
||||
|
||||
CListBox CheatList = GetDlgItem(IDC_CHEAT_LIST);
|
||||
while (*ReadPos != 0)
|
||||
CEnhancement::CodeOptions Options = m_Enhancement->GetOptions();
|
||||
bool OptionSelected = m_Enhancement->OptionSelected();
|
||||
uint16_t SelectedOption = m_Enhancement->SelectedOption();
|
||||
for (size_t i = 0, n = Options.size(); i < n; i++)
|
||||
{
|
||||
const char * NextComma = strchr(ReadPos, ',');
|
||||
int len = NextComma == NULL ? strlen(ReadPos) : NextComma - ReadPos;
|
||||
stdstr CheatExt(ReadPos);
|
||||
CheatExt.resize(len);
|
||||
int index = CheatList.AddString(CheatExt.ToUTF16().c_str());
|
||||
if (CheatExt == CurrentExt)
|
||||
stdstr_f Option(m_Enhancement->CodeOptionSize() == 2 ? "$%02X %s" : "$%04X %s", Options[i].Value, Options[i].Name.c_str());
|
||||
int index = CheatList.AddString(Option.ToUTF16().c_str());
|
||||
if (index >= 0)
|
||||
{
|
||||
CheatList.SetCurSel(index);
|
||||
CheatList.SetItemData(index, Options[i].Value);
|
||||
if (OptionSelected && SelectedOption == Options[i].Value)
|
||||
{
|
||||
CheatList.SetCurSel(index);
|
||||
}
|
||||
}
|
||||
ReadPos = NextComma ? NextComma + 1 : ReadPos + strlen(ReadPos);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
LRESULT CCheatsCodeEx::OnListDblClick(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
|
||||
LRESULT CEnhancementCodeEx::OnListDblClick(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
PostMessage(WM_COMMAND, IDOK, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LRESULT CCheatsCodeEx::OnOkCmd(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
|
||||
LRESULT CEnhancementCodeEx::OnOkCmd(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
CListBox CheatList = GetDlgItem(IDC_CHEAT_LIST);
|
||||
int index = CheatList.GetCurSel();
|
||||
|
@ -1234,21 +1104,16 @@ LRESULT CCheatsCodeEx::OnOkCmd(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCt
|
|||
index = 0;
|
||||
}
|
||||
|
||||
int length = CheatList.GetTextLen(index);
|
||||
std::wstring CheatExten;
|
||||
CheatExten.resize(length + 1);
|
||||
CheatList.GetText(index, (wchar_t *)CheatExten.c_str());
|
||||
|
||||
g_Settings->SaveStringIndex(Cheat_Extension, m_EditCheat, stdstr().FromUTF16(CheatExten.c_str()).c_str());
|
||||
if (g_BaseSystem)
|
||||
m_Enhancement->SetSelectedOption((uint16_t)(CheatList.GetItemData(index)));
|
||||
if (g_Enhancements != nullptr)
|
||||
{
|
||||
g_BaseSystem->SetCheatsSlectionChanged(true);
|
||||
g_Enhancements->UpdateCheats();
|
||||
}
|
||||
EndDialog(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LRESULT CCheatsCodeEx::OnCloseCmd(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
|
||||
LRESULT CEnhancementCodeEx::OnCloseCmd(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
EndDialog(0);
|
||||
return 0;
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
****************************************************************************/
|
||||
#pragma once
|
||||
#include <Project64\WTLApp.h>
|
||||
#include <Project64-core\N64System\Enhancement\Enhancement.h>
|
||||
#include <Project64-core\N64System\Enhancement\EnhancementList.h>
|
||||
|
||||
class CEditCheat;
|
||||
|
||||
|
@ -36,7 +38,7 @@ public:
|
|||
|
||||
enum { IDD = IDD_Cheats_List };
|
||||
|
||||
CCheatList(CEditCheat & EditCheat);
|
||||
CCheatList(CEnhancementList & Cheats, CEditCheat & EditCheat);
|
||||
~CCheatList();
|
||||
|
||||
void RefreshItems();
|
||||
|
@ -57,16 +59,17 @@ private:
|
|||
LRESULT OnTreeRClicked(NMHDR* lpnmh);
|
||||
LRESULT OnTreeDClicked(NMHDR* lpnmh);
|
||||
LRESULT OnTreeSelChanged(NMHDR* lpnmh);
|
||||
void AddCodeLayers(int CheatNumber, const std::wstring &CheatName, HTREEITEM hParent, bool CheatActive);
|
||||
void AddCodeLayers(LPARAM ListID, const std::wstring &Name, HTREEITEM hParent, bool CheatActive);
|
||||
void ChangeChildrenStatus(HTREEITEM hParent, bool Checked);
|
||||
void CheckParentStatus(HTREEITEM hParent);
|
||||
void DeleteCheat(int Index);
|
||||
void DeleteCheat(LPARAM Enhancement);
|
||||
TV_CHECK_STATE TV_GetCheckState(HTREEITEM hItem);
|
||||
bool TV_SetCheckState(HTREEITEM hItem, TV_CHECK_STATE state);
|
||||
static void MenuSetText(HMENU hMenu, int MenuPos, const wchar_t * Title, const wchar_t * ShortCut);
|
||||
|
||||
enum { IDC_MYTREE = 0x500 };
|
||||
|
||||
CEnhancementList & m_Cheats;
|
||||
CEditCheat & m_EditCheat;
|
||||
CTreeViewCtrl m_hCheatTree;
|
||||
HTREEITEM m_hSelectedItem;
|
||||
|
@ -102,7 +105,7 @@ public:
|
|||
|
||||
enum { IDD = IDD_Cheats_Add };
|
||||
|
||||
CEditCheat(CCheatList & CheatList);
|
||||
CEditCheat(CEnhancementList & Cheats, CCheatList & CheatList);
|
||||
~CEditCheat();
|
||||
|
||||
private:
|
||||
|
@ -118,26 +121,27 @@ private:
|
|||
LRESULT OnCheatCodeChanged(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
|
||||
LRESULT OnCheatOptionsChanged(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
|
||||
|
||||
std::string ReadCodeString(bool &ValidCodes, bool &ValidOptions, bool &NoOptions, CodeFormat & Format);
|
||||
std::string ReadOptionsString(bool &validoptions, CodeFormat Format);
|
||||
CEnhancement::CodeEntries ReadCodeEntries(bool &ValidCodes, bool &ValidOptions, bool &NoOptions, CodeFormat & Format);
|
||||
CEnhancement::CodeOptions ReadOptions(bool &validoptions, CodeFormat Format);
|
||||
|
||||
void RecordCheatValues(void);
|
||||
bool CheatChanged(void);
|
||||
void RecordCurrentValues(void);
|
||||
bool ValuesChanged(void);
|
||||
std::string GetItemText(int nIDDlgItem);
|
||||
|
||||
CEnhancementList & m_Cheats;
|
||||
CCheatList & m_CheatList;
|
||||
std::string m_EditName;
|
||||
std::string m_EditCode;
|
||||
std::string m_EditOptions;
|
||||
std::string m_EditNotes;
|
||||
int32_t m_EditCheat;
|
||||
CEnhancement * m_EditEnhancement;
|
||||
};
|
||||
|
||||
class CCheatsCodeEx :
|
||||
public CDialogImpl<CCheatsCodeEx>
|
||||
class CEnhancementCodeEx :
|
||||
public CDialogImpl<CEnhancementCodeEx>
|
||||
{
|
||||
public:
|
||||
BEGIN_MSG_MAP_EX(CCheatsCodeEx)
|
||||
BEGIN_MSG_MAP_EX(CEnhancementCodeEx)
|
||||
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
|
||||
COMMAND_HANDLER(IDC_CHEAT_LIST, LBN_DBLCLK, OnListDblClick)
|
||||
COMMAND_ID_HANDLER(IDOK, OnOkCmd)
|
||||
|
@ -146,19 +150,19 @@ public:
|
|||
|
||||
enum { IDD = IDD_Cheats_CodeEx };
|
||||
|
||||
CCheatsCodeEx(int EditCheat);
|
||||
CEnhancementCodeEx(CEnhancement * Enhancement);
|
||||
|
||||
private:
|
||||
CCheatsCodeEx();
|
||||
CCheatsCodeEx(const CCheatsCodeEx&);
|
||||
CCheatsCodeEx& operator=(const CCheatsCodeEx&);
|
||||
CEnhancementCodeEx();
|
||||
CEnhancementCodeEx(const CEnhancementCodeEx&);
|
||||
CEnhancementCodeEx& operator=(const CEnhancementCodeEx&);
|
||||
|
||||
LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
|
||||
LRESULT OnListDblClick(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
|
||||
LRESULT OnOkCmd(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
|
||||
LRESULT OnCloseCmd(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
|
||||
|
||||
int32_t m_EditCheat;
|
||||
CEnhancement * m_Enhancement;
|
||||
};
|
||||
|
||||
class CCheatsUI :
|
||||
|
@ -166,7 +170,7 @@ class CCheatsUI :
|
|||
{
|
||||
friend CCheatList;
|
||||
friend CEditCheat;
|
||||
friend CCheatsCodeEx;
|
||||
friend CEnhancementCodeEx;
|
||||
|
||||
public:
|
||||
BEGIN_MSG_MAP_EX(CCheatsUI)
|
||||
|
@ -189,9 +193,7 @@ private:
|
|||
LRESULT OnCloseCmd(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
|
||||
LRESULT OnStateChange(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
|
||||
|
||||
static std::string GetCheatName(int CheatNo, bool AddExtension);
|
||||
static bool CheatUsesCodeExtensions(const std::string &LineEntry);
|
||||
|
||||
CEnhancementList m_Cheats;
|
||||
CEditCheat m_EditCheat;
|
||||
CCheatList m_SelectCheat;
|
||||
CButton m_StateBtn;
|
||||
|
|
|
@ -1,745 +0,0 @@
|
|||
#include "stdafx.h"
|
||||
#include <Project64-core/Settings/SettingType/SettingsType-Enhancements.h>
|
||||
|
||||
class CEditEnhancement :
|
||||
public CDialogImpl < CEditEnhancement >
|
||||
{
|
||||
public:
|
||||
BEGIN_MSG_MAP_EX(CEditEnhancement)
|
||||
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
|
||||
COMMAND_ID_HANDLER(IDC_BTN_GAMESHARK, OnEditGameshark)
|
||||
COMMAND_ID_HANDLER(IDOK, OnOkCmd)
|
||||
COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
|
||||
END_MSG_MAP()
|
||||
|
||||
enum { IDD = IDD_Enhancement_Edit };
|
||||
|
||||
CEditEnhancement(int EditItem);
|
||||
|
||||
void Display(HWND ParentWindow);
|
||||
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
|
||||
LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
|
||||
LRESULT OnOkCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
|
||||
LRESULT OnEditGameshark(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
|
||||
|
||||
private:
|
||||
CEditEnhancement(void); // Disable default constructor
|
||||
CEditEnhancement(const CEditEnhancement&); // Disable copy constructor
|
||||
CEditEnhancement& operator=(const CEditEnhancement&); // Disable assignment
|
||||
|
||||
std::wstring GetDlgItemStr(int nIDDlgItem);
|
||||
|
||||
int m_EditItem;
|
||||
};
|
||||
|
||||
class CEditGS :
|
||||
public CDialogImpl < CEditGS >
|
||||
{
|
||||
public:
|
||||
BEGIN_MSG_MAP_EX(CEditEnhancement)
|
||||
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
|
||||
COMMAND_HANDLER(IDC_CHEAT_CODES, EN_CHANGE, OnCheatChanged)
|
||||
COMMAND_ID_HANDLER(IDOK, OnOkCmd)
|
||||
COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
|
||||
END_MSG_MAP()
|
||||
|
||||
enum { IDD = IDD_Enhancement_GS };
|
||||
|
||||
CEditGS(int EditItem);
|
||||
|
||||
void Display(HWND ParentWindow);
|
||||
|
||||
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
|
||||
LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
|
||||
LRESULT OnOkCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
|
||||
LRESULT OnCheatChanged(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
|
||||
|
||||
private:
|
||||
CEditGS(void); // Disable default constructor
|
||||
CEditGS(const CEditGS&); // Disable copy constructor
|
||||
CEditGS& operator=(const CEditGS&); // Disable assignment
|
||||
|
||||
bool CheatCode(std::string & Code);
|
||||
|
||||
int m_EditItem;
|
||||
};
|
||||
|
||||
CEnhancementConfig::CEnhancementConfig(void) :
|
||||
m_hSelectedItem(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
CEnhancementConfig::~CEnhancementConfig()
|
||||
{
|
||||
}
|
||||
|
||||
void CEnhancementConfig::Display(void * ParentWindow)
|
||||
{
|
||||
BOOL result = m_thunk.Init(NULL, NULL);
|
||||
if (result)
|
||||
{
|
||||
_AtlWinModule.AddCreateWndData(&m_thunk.cd, this);
|
||||
#ifdef _DEBUG
|
||||
m_bModal = true;
|
||||
#endif //_DEBUG
|
||||
::DialogBoxParamW(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCEW(IDD), (HWND)ParentWindow, StartDialogProc, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CEnhancementConfig::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
m_TreeList.Attach(GetDlgItem(IDC_ENHANCEMENTLIST));
|
||||
LONG Style = m_TreeList.GetWindowLong(GWL_STYLE);
|
||||
m_TreeList.SetWindowLong(GWL_STYLE, TVS_CHECKBOXES | TVS_SHOWSELALWAYS | Style);
|
||||
|
||||
HIMAGELIST hImageList = ImageList_Create(16, 16, ILC_COLOR | ILC_MASK, 40, 40);
|
||||
HBITMAP hBmp = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_TRI_STATE));
|
||||
ImageList_AddMasked(hImageList, hBmp, RGB(255, 0, 255));
|
||||
DeleteObject(hBmp);
|
||||
m_TreeList.SetImageList(hImageList, TVSIL_STATE);
|
||||
|
||||
RefreshList();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LRESULT CEnhancementConfig::OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
EndDialog(wID);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LRESULT CEnhancementConfig::OnAddEnhancement(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
CEditEnhancement(-1).Display(m_hWnd);
|
||||
RefreshList();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LRESULT CEnhancementConfig::OnEnhancementListClicked(NMHDR* pNMHDR)
|
||||
{
|
||||
SetMsgHandled(false);
|
||||
|
||||
TVHITTESTINFO ht = { 0 };
|
||||
uint32_t dwpos = GetMessagePos();
|
||||
|
||||
// include <windowsx.h> and <windows.h> header files
|
||||
ht.pt.x = GET_X_LPARAM(dwpos);
|
||||
ht.pt.y = GET_Y_LPARAM(dwpos);
|
||||
::MapWindowPoints(HWND_DESKTOP, pNMHDR->hwndFrom, &ht.pt, 1);
|
||||
|
||||
TreeView_HitTest(pNMHDR->hwndFrom, &ht);
|
||||
|
||||
if (TVHT_ONITEMSTATEICON & ht.flags)
|
||||
{
|
||||
switch (TV_GetCheckState(ht.hItem))
|
||||
{
|
||||
case TV_STATE_CLEAR:
|
||||
case TV_STATE_INDETERMINATE:
|
||||
TV_SetCheckState(ht.hItem, TV_STATE_CHECKED);
|
||||
ChangeChildrenStatus(ht.hItem, true);
|
||||
CheckParentStatus(m_TreeList.GetParentItem(ht.hItem));
|
||||
break;
|
||||
case TV_STATE_CHECKED:
|
||||
TV_SetCheckState(ht.hItem, TV_STATE_CLEAR);
|
||||
ChangeChildrenStatus(ht.hItem, false);
|
||||
CheckParentStatus(m_TreeList.GetParentItem(ht.hItem));
|
||||
break;
|
||||
}
|
||||
switch (TV_GetCheckState(ht.hItem))
|
||||
{
|
||||
case TV_STATE_CHECKED: TV_SetCheckState(ht.hItem, TV_STATE_INDETERMINATE); break;
|
||||
case TV_STATE_CLEAR: TV_SetCheckState(ht.hItem, TV_STATE_CHECKED); break;
|
||||
case TV_STATE_INDETERMINATE: TV_SetCheckState(ht.hItem, TV_STATE_CLEAR); break;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void CEnhancementConfig::CheckParentStatus(HTREEITEM hParent)
|
||||
{
|
||||
TV_CHECK_STATE CurrentState, InitialState;
|
||||
|
||||
if (!hParent) { return; }
|
||||
HTREEITEM hItem = m_TreeList.GetChildItem(hParent);
|
||||
InitialState = (TV_CHECK_STATE)TV_GetCheckState(hParent);
|
||||
CurrentState = (TV_CHECK_STATE)TV_GetCheckState(hItem);
|
||||
|
||||
while (hItem != NULL)
|
||||
{
|
||||
if (TV_GetCheckState(hItem) != CurrentState)
|
||||
{
|
||||
CurrentState = TV_STATE_INDETERMINATE;
|
||||
break;
|
||||
}
|
||||
hItem = m_TreeList.GetNextSiblingItem(hItem);
|
||||
}
|
||||
TV_SetCheckState(hParent, CurrentState);
|
||||
if (InitialState != CurrentState)
|
||||
{
|
||||
CheckParentStatus(m_TreeList.GetParentItem(hParent));
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CEnhancementConfig::OnEnhancementListRClicked(NMHDR* pNMHDR)
|
||||
{
|
||||
TVHITTESTINFO ht = { 0 };
|
||||
uint32_t dwpos = GetMessagePos();
|
||||
ht.pt.x = GET_X_LPARAM(dwpos);
|
||||
ht.pt.y = GET_Y_LPARAM(dwpos);
|
||||
::MapWindowPoints(HWND_DESKTOP, pNMHDR->hwndFrom, &ht.pt, 1);
|
||||
|
||||
TreeView_HitTest(pNMHDR->hwndFrom, &ht);
|
||||
m_hSelectedItem = ht.hItem;
|
||||
|
||||
POINT Mouse;
|
||||
GetCursorPos(&Mouse);
|
||||
HMENU hMenu = LoadMenu(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_ENHANCEMENT_MENU));
|
||||
HMENU hPopupMenu = GetSubMenu(hMenu, 0);
|
||||
|
||||
if (m_hSelectedItem == NULL)
|
||||
{
|
||||
RemoveMenu(hPopupMenu, 3, MF_BYPOSITION);
|
||||
RemoveMenu(hPopupMenu, 2, MF_BYPOSITION);
|
||||
RemoveMenu(hPopupMenu, 1, MF_BYPOSITION);
|
||||
}
|
||||
|
||||
TrackPopupMenu(hPopupMenu, 0, Mouse.x, Mouse.y, 0, m_hWnd, NULL);
|
||||
DestroyMenu(hMenu);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LRESULT CEnhancementConfig::OnEnhancementListDblClicked(NMHDR * pNMHDR)
|
||||
{
|
||||
TVHITTESTINFO ht = { 0 };
|
||||
uint32_t dwpos = GetMessagePos();
|
||||
|
||||
ht.pt.x = GET_X_LPARAM(dwpos);
|
||||
ht.pt.y = GET_Y_LPARAM(dwpos);
|
||||
::MapWindowPoints(HWND_DESKTOP, pNMHDR->hwndFrom, &ht.pt, 1);
|
||||
|
||||
TreeView_HitTest(pNMHDR->hwndFrom, &ht);
|
||||
|
||||
if (TVHT_ONITEMLABEL & ht.flags)
|
||||
{
|
||||
TVITEM item;
|
||||
|
||||
item.mask = TVIF_PARAM;
|
||||
item.hItem = ht.hItem;
|
||||
m_TreeList.GetItem(&item);
|
||||
|
||||
CEditEnhancement(item.lParam).Display(m_hWnd);
|
||||
RefreshList();
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LRESULT CEnhancementConfig::OnEnhancementListSelChanged(NMHDR * /*pNMHDR*/)
|
||||
{
|
||||
HTREEITEM hItem = m_TreeList.GetSelectedItem();
|
||||
if (m_TreeList.GetChildItem(hItem) == NULL)
|
||||
{
|
||||
TVITEM item;
|
||||
|
||||
item.mask = TVIF_PARAM;
|
||||
item.hItem = hItem;
|
||||
m_TreeList.GetItem(&item);
|
||||
|
||||
stdstr Notes(g_Settings->LoadStringIndex(Enhancement_Notes, item.lParam));
|
||||
SetDlgItemText(IDC_NOTES, Notes.ToUTF16().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
SetDlgItemText(IDC_NOTES, L"");
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LRESULT CEnhancementConfig::OnEditItem(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
if (m_hSelectedItem != NULL)
|
||||
{
|
||||
TVITEM item;
|
||||
|
||||
item.mask = TVIF_PARAM;
|
||||
item.hItem = m_hSelectedItem;
|
||||
m_TreeList.GetItem(&item);
|
||||
|
||||
CEditEnhancement(item.lParam).Display(m_hWnd);
|
||||
RefreshList();
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LRESULT CEnhancementConfig::OnDeleteItem(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
if (m_hSelectedItem == NULL)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
int Response = MessageBox(wGS(MSG_DEL_SURE).c_str(), wGS(MSG_DEL_TITLE).c_str(), MB_YESNO | MB_ICONQUESTION);
|
||||
if (Response != IDYES) { return TRUE; }
|
||||
|
||||
TVITEM item;
|
||||
item.hItem = m_hSelectedItem;
|
||||
item.mask = TVIF_PARAM;
|
||||
m_TreeList.GetItem(&item);
|
||||
|
||||
for (int i = item.lParam; i < CCheats::MaxCheats; i++)
|
||||
{
|
||||
stdstr Name = g_Settings->LoadStringIndex(Enhancement_Name, i + 1);
|
||||
if (Name.empty())
|
||||
{
|
||||
g_Settings->DeleteSettingIndex(Enhancement_Name, i);
|
||||
g_Settings->DeleteSettingIndex(Enhancement_Active, i);
|
||||
g_Settings->DeleteSettingIndex(Enhancement_OnByDefault, i);
|
||||
g_Settings->DeleteSettingIndex(Enhancement_Notes, i);
|
||||
g_Settings->DeleteSettingIndex(Enhancement_Overclock, i);
|
||||
g_Settings->DeleteSettingIndex(Enhancement_OverclockValue, i);
|
||||
g_Settings->DeleteSettingIndex(Enhancement_Gameshark, i);
|
||||
g_Settings->DeleteSettingIndex(Enhancement_GamesharkCode, i);
|
||||
break;
|
||||
}
|
||||
stdstr Value;
|
||||
if (g_Settings->LoadStringIndex(Enhancement_Gameshark, i + 1, Value))
|
||||
{
|
||||
g_Settings->SaveStringIndex(Enhancement_Gameshark, i, Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Settings->DeleteSettingIndex(Enhancement_Gameshark, i);
|
||||
}
|
||||
|
||||
if (g_Settings->LoadStringIndex(Enhancement_Notes, i + 1, Value))
|
||||
{
|
||||
g_Settings->SaveStringIndex(Enhancement_Notes, i, Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Settings->DeleteSettingIndex(Enhancement_Notes, i);
|
||||
}
|
||||
|
||||
bool bValue;
|
||||
if (g_Settings->LoadBoolIndex(Enhancement_Active, i + 1, bValue))
|
||||
{
|
||||
g_Settings->SaveBoolIndex(Enhancement_Active, i, bValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Settings->DeleteSettingIndex(Enhancement_Active, i);
|
||||
}
|
||||
|
||||
if (g_Settings->LoadBoolIndex(Enhancement_OnByDefault, i + 1, bValue))
|
||||
{
|
||||
g_Settings->SaveBoolIndex(Enhancement_OnByDefault, i, bValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Settings->DeleteSettingIndex(Enhancement_OnByDefault, i);
|
||||
}
|
||||
|
||||
if (g_Settings->LoadBoolIndex(Enhancement_Overclock, i + 1, bValue))
|
||||
{
|
||||
g_Settings->SaveBoolIndex(Enhancement_Overclock, i, bValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Settings->DeleteSettingIndex(Enhancement_Overclock, i);
|
||||
}
|
||||
|
||||
if (g_Settings->LoadBoolIndex(Enhancement_Gameshark, i + 1, bValue))
|
||||
{
|
||||
g_Settings->SaveBoolIndex(Enhancement_Gameshark, i, bValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Settings->DeleteSettingIndex(Enhancement_Gameshark, i);
|
||||
}
|
||||
|
||||
uint32_t dwValue;
|
||||
if (g_Settings->LoadDwordIndex(Enhancement_OverclockValue, i + 1, dwValue))
|
||||
{
|
||||
g_Settings->SaveDwordIndex(Enhancement_OverclockValue, i, dwValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Settings->DeleteSettingIndex(Enhancement_OverclockValue, i);
|
||||
}
|
||||
g_Settings->SaveStringIndex(Enhancement_Name, i, Name);
|
||||
}
|
||||
CSettingTypeEnhancements::FlushChanges();
|
||||
RefreshList();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void CEnhancementConfig::RefreshList()
|
||||
{
|
||||
m_TreeList.DeleteAllItems();
|
||||
for (int i = 0; i < CCheats::MaxCheats; i++)
|
||||
{
|
||||
std::string Name = g_Settings->LoadStringIndex(Enhancement_Name, i);
|
||||
if (Name.length() == 0) { break; }
|
||||
|
||||
AddCodeLayers(i, Name, TVI_ROOT, g_Settings->LoadBoolIndex(Enhancement_Active, i) != 0);
|
||||
}
|
||||
}
|
||||
|
||||
void CEnhancementConfig::AddCodeLayers(int index, const std::string & Name, HTREEITEM hParent, bool Active)
|
||||
{
|
||||
TV_INSERTSTRUCT tv;
|
||||
|
||||
//Work out text to add
|
||||
wchar_t Text[500], Item[500];
|
||||
if (Name.length() > (sizeof(Text) - 5)) { g_Notify->BreakPoint(__FILE__, __LINE__); }
|
||||
wcscpy(Text, stdstr(Name).ToUTF16().c_str());
|
||||
if (wcschr(Text, L'\\') > 0) { *wcschr(Text, '\\') = 0; }
|
||||
|
||||
//See if text is already added
|
||||
tv.item.mask = TVIF_TEXT;
|
||||
tv.item.pszText = Item;
|
||||
tv.item.cchTextMax = sizeof(Item);
|
||||
tv.item.hItem = m_TreeList.GetChildItem(hParent);
|
||||
while (tv.item.hItem)
|
||||
{
|
||||
m_TreeList.GetItem(&tv.item);
|
||||
if (wcscmp(Text, Item) == 0)
|
||||
{
|
||||
//If already exists then just use existing one
|
||||
int State = TV_GetCheckState(tv.item.hItem);
|
||||
if ((Active && State == TV_STATE_CLEAR) || (!Active && State == TV_STATE_CHECKED))
|
||||
{
|
||||
TV_SetCheckState(tv.item.hItem, TV_STATE_INDETERMINATE);
|
||||
}
|
||||
size_t StartPos = wcslen(Text) + 1;
|
||||
stdstr TempCheatName;
|
||||
if (StartPos < Name.length())
|
||||
{
|
||||
TempCheatName = Name.substr(StartPos);
|
||||
}
|
||||
AddCodeLayers(index, TempCheatName, tv.item.hItem, Active);
|
||||
return;
|
||||
}
|
||||
tv.item.hItem = TreeView_GetNextSibling(m_TreeList, tv.item.hItem);
|
||||
}
|
||||
|
||||
//Add to dialog
|
||||
tv.hInsertAfter = TVI_SORT;
|
||||
tv.item.mask = TVIF_TEXT | TVIF_PARAM;
|
||||
tv.item.pszText = Text;
|
||||
tv.item.lParam = index;
|
||||
tv.hParent = (HTREEITEM)hParent;
|
||||
hParent = m_TreeList.InsertItem(&tv);
|
||||
TV_SetCheckState(hParent, Active ? TV_STATE_CHECKED : TV_STATE_CLEAR);
|
||||
|
||||
if (wcscmp(Text, stdstr(Name).ToUTF16().c_str()) == 0) { return; }
|
||||
AddCodeLayers(index, Name.substr(wcslen(Text) + 1), hParent, Active);
|
||||
}
|
||||
|
||||
bool CEnhancementConfig::TV_SetCheckState( HTREEITEM hItem, TV_CHECK_STATE state)
|
||||
{
|
||||
TVITEM tvItem;
|
||||
|
||||
tvItem.mask = TVIF_HANDLE | TVIF_STATE;
|
||||
tvItem.hItem = hItem;
|
||||
tvItem.stateMask = TVIS_STATEIMAGEMASK;
|
||||
|
||||
/*Image 1 in the tree-view check box image list is the
|
||||
unchecked box. Image 2 is the checked box.*/
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case TV_STATE_CHECKED: tvItem.state = INDEXTOSTATEIMAGEMASK(1); break;
|
||||
case TV_STATE_CLEAR: tvItem.state = INDEXTOSTATEIMAGEMASK(2); break;
|
||||
case TV_STATE_INDETERMINATE: tvItem.state = INDEXTOSTATEIMAGEMASK(3); break;
|
||||
default: tvItem.state = INDEXTOSTATEIMAGEMASK(0); break;
|
||||
}
|
||||
return m_TreeList.SetItem(&tvItem) != 0;
|
||||
}
|
||||
|
||||
int CEnhancementConfig::TV_GetCheckState(HTREEITEM hItem)
|
||||
{
|
||||
TVITEM tvItem;
|
||||
|
||||
// Prepare to receive the desired information.
|
||||
tvItem.mask = TVIF_HANDLE | TVIF_STATE;
|
||||
tvItem.hItem = hItem;
|
||||
tvItem.stateMask = TVIS_STATEIMAGEMASK;
|
||||
|
||||
// Request the information.
|
||||
m_TreeList.GetItem(&tvItem);
|
||||
|
||||
// Return zero if it's not checked, or nonzero otherwise.
|
||||
switch (tvItem.state >> 12) {
|
||||
case 1: return TV_STATE_CHECKED;
|
||||
case 2: return TV_STATE_CLEAR;
|
||||
case 3: return TV_STATE_INDETERMINATE;
|
||||
}
|
||||
return ((int)(tvItem.state >> 12) - 1);
|
||||
}
|
||||
|
||||
void CEnhancementConfig::ChangeChildrenStatus(HTREEITEM hParent, bool Checked)
|
||||
{
|
||||
HTREEITEM hItem = m_TreeList.GetChildItem(hParent);
|
||||
if (hItem == NULL)
|
||||
{
|
||||
if (hParent == TVI_ROOT) { return; }
|
||||
|
||||
TVITEM item;
|
||||
item.mask = TVIF_PARAM;
|
||||
item.hItem = (HTREEITEM)hParent;
|
||||
m_TreeList.GetItem(&item);
|
||||
|
||||
TV_SetCheckState(hParent, Checked ? TV_STATE_CHECKED : TV_STATE_CLEAR);
|
||||
g_Settings->SaveBoolIndex(Enhancement_Active, item.lParam, Checked);
|
||||
}
|
||||
else
|
||||
{
|
||||
TV_CHECK_STATE state = TV_STATE_UNKNOWN;
|
||||
while (hItem != NULL)
|
||||
{
|
||||
TV_CHECK_STATE ChildState = (TV_CHECK_STATE)TV_GetCheckState(hItem);
|
||||
if ((ChildState != TV_STATE_CHECKED || !Checked) &&
|
||||
(ChildState != TV_STATE_CLEAR || Checked))
|
||||
{
|
||||
ChangeChildrenStatus(hItem, Checked);
|
||||
}
|
||||
ChildState = (TV_CHECK_STATE)TV_GetCheckState(hItem);
|
||||
if (state == TV_STATE_UNKNOWN) { state = ChildState; }
|
||||
if (state != ChildState) { state = TV_STATE_INDETERMINATE; }
|
||||
hItem = m_TreeList.GetNextSiblingItem(hItem);
|
||||
}
|
||||
if (state != TV_STATE_UNKNOWN)
|
||||
{
|
||||
TV_SetCheckState(hParent, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CEditEnhancement::CEditEnhancement(int EditItem) :
|
||||
m_EditItem(EditItem)
|
||||
{
|
||||
}
|
||||
|
||||
void CEditEnhancement::Display(HWND ParentWindow)
|
||||
{
|
||||
BOOL result = m_thunk.Init(NULL, NULL);
|
||||
if (result)
|
||||
{
|
||||
_AtlWinModule.AddCreateWndData(&m_thunk.cd, this);
|
||||
#ifdef _DEBUG
|
||||
m_bModal = true;
|
||||
#endif //_DEBUG
|
||||
::DialogBoxParamW(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCEW(IDD), ParentWindow, StartDialogProc, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CEditEnhancement::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
GetDlgItem(IDC_CODE_NAME).SetWindowText(stdstr(m_EditItem >= 0 ? g_Settings->LoadStringIndex(Enhancement_Name, m_EditItem) : "").ToUTF16().c_str());
|
||||
GetDlgItem(IDC_NOTES).SetWindowText(stdstr(m_EditItem >= 0 ? g_Settings->LoadStringIndex(Enhancement_Notes, m_EditItem).c_str() : "").ToUTF16().c_str());
|
||||
CButton(GetDlgItem(IDC_AUTOON)).SetCheck(g_Settings->LoadBoolIndex(Enhancement_OnByDefault, m_EditItem) ? BST_CHECKED : BST_UNCHECKED);
|
||||
CButton(GetDlgItem(IDC_OVERCLOCK)).SetCheck(g_Settings->LoadBoolIndex(Enhancement_Overclock, m_EditItem) ? BST_CHECKED : BST_UNCHECKED);
|
||||
CButton(GetDlgItem(IDC_GAMESHARK)).SetCheck(g_Settings->LoadBoolIndex(Enhancement_Gameshark, m_EditItem) ? BST_CHECKED : BST_UNCHECKED);
|
||||
GetDlgItem(IDC_OVER_CLOCK_MODIFIER).SetWindowText(stdstr(m_EditItem >= 0 ? stdstr_f("%d", g_Settings->LoadDwordIndex(Enhancement_OverclockValue, m_EditItem)).c_str() : "").ToUTF16().c_str());
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LRESULT CEditEnhancement::OnEditGameshark(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
CEditGS(m_EditItem).Display(m_hWnd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LRESULT CEditEnhancement::OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
EndDialog(wID);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LRESULT CEditEnhancement::OnOkCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
std::string NewName = stdstr().FromUTF16(GetDlgItemStr(IDC_CODE_NAME).c_str());
|
||||
|
||||
for (int i = 0; i < CCheats::MaxCheats; i++)
|
||||
{
|
||||
if (m_EditItem == i)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
std::string Name = g_Settings->LoadStringIndex(Enhancement_Name, i);
|
||||
if (Name.length() == 0)
|
||||
{
|
||||
if (m_EditItem < 0)
|
||||
{
|
||||
m_EditItem = i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (_stricmp(Name.c_str(), NewName.c_str()) == 0)
|
||||
{
|
||||
g_Notify->DisplayWarning(GS(MSG_CHEAT_NAME_IN_USE));
|
||||
GetDlgItem(IDC_CODE_NAME).SetFocus();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (m_EditItem < 0)
|
||||
{
|
||||
g_Notify->DisplayError(GS(MSG_MAX_CHEATS));
|
||||
return true;
|
||||
}
|
||||
g_Settings->SaveStringIndex(Enhancement_Name, m_EditItem, NewName);
|
||||
g_Settings->SaveStringIndex(Enhancement_Notes, m_EditItem, stdstr().FromUTF16(GetDlgItemStr(IDC_NOTES).c_str()).c_str());
|
||||
g_Settings->SaveBoolIndex(Enhancement_OnByDefault, m_EditItem, CButton(GetDlgItem(IDC_AUTOON)).GetCheck() == 1);
|
||||
g_Settings->SaveBoolIndex(Enhancement_Overclock, m_EditItem, CButton(GetDlgItem(IDC_OVERCLOCK)).GetCheck() == 1);
|
||||
g_Settings->SaveDwordIndex(Enhancement_OverclockValue, m_EditItem, _wtoi(GetDlgItemStr(IDC_OVER_CLOCK_MODIFIER).c_str()));
|
||||
g_Settings->SaveBoolIndex(Enhancement_Gameshark, m_EditItem, CButton(GetDlgItem(IDC_GAMESHARK)).GetCheck() == 1);
|
||||
CSettingTypeEnhancements::FlushChanges();
|
||||
EndDialog(wID);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
std::wstring CEditEnhancement::GetDlgItemStr(int nIDDlgItem)
|
||||
{
|
||||
CWindow DlgItem = GetDlgItem(nIDDlgItem);
|
||||
int length = DlgItem.SendMessage(WM_GETTEXTLENGTH, 0, 0);
|
||||
if (length == 0)
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
|
||||
std::wstring Result;
|
||||
Result.resize(length + 1);
|
||||
|
||||
DlgItem.GetWindowText((wchar_t *)Result.c_str(), Result.length());
|
||||
return Result;
|
||||
}
|
||||
|
||||
CEditGS::CEditGS(int EditItem) :
|
||||
m_EditItem(EditItem)
|
||||
{
|
||||
}
|
||||
|
||||
void CEditGS::Display(HWND ParentWindow)
|
||||
{
|
||||
BOOL result = m_thunk.Init(NULL, NULL);
|
||||
if (result)
|
||||
{
|
||||
_AtlWinModule.AddCreateWndData(&m_thunk.cd, this);
|
||||
#ifdef _DEBUG
|
||||
m_bModal = true;
|
||||
#endif //_DEBUG
|
||||
::DialogBoxParamW(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCEW(IDD), (HWND)ParentWindow, StartDialogProc, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CEditGS::OnCheatChanged(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
std::string code;
|
||||
GetDlgItem(IDOK).EnableWindow(CheatCode(code));
|
||||
return true;
|
||||
}
|
||||
|
||||
LRESULT CEditGS::OnOkCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
std::string code;
|
||||
if (CheatCode(code))
|
||||
{
|
||||
if (code.empty())
|
||||
{
|
||||
g_Settings->DeleteSettingIndex(Enhancement_GamesharkCode, m_EditItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Settings->SaveStringIndex(Enhancement_GamesharkCode, m_EditItem, code.c_str());
|
||||
}
|
||||
}
|
||||
EndDialog(wID);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LRESULT CEditGS::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
std::string entry = g_Settings->LoadStringIndex(Enhancement_GamesharkCode, m_EditItem);
|
||||
std::string Buffer;
|
||||
const char * ReadPos = entry.c_str();
|
||||
do
|
||||
{
|
||||
const char * End = strchr(ReadPos, ',');
|
||||
if (End)
|
||||
{
|
||||
Buffer.append(ReadPos, End - ReadPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
Buffer.append(ReadPos);
|
||||
}
|
||||
|
||||
ReadPos = strchr(ReadPos, ',');
|
||||
if (ReadPos != NULL)
|
||||
{
|
||||
Buffer.append("\r\n");
|
||||
ReadPos += 1;
|
||||
}
|
||||
} while (ReadPos);
|
||||
CWindow Code = GetDlgItem(IDC_CHEAT_CODES);
|
||||
Code.SetWindowText(stdstr(Buffer.c_str()).ToUTF16().c_str());
|
||||
Code.SetFocus();
|
||||
Code.PostMessage(EM_SETSEL, (WPARAM)-1, 0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
LRESULT CEditGS::OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
EndDialog(wID);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool CEditGS::CheatCode(std::string & Code)
|
||||
{
|
||||
Code.clear();
|
||||
|
||||
bool ValidCode = true;
|
||||
uint32_t numlines = SendDlgItemMessage(IDC_CHEAT_CODES, EM_GETLINECOUNT, 0, 0);
|
||||
|
||||
for (uint32_t line = 0; line < numlines; line++) //read line after line (bypassing limitation GetDlgItemText)
|
||||
{
|
||||
char tempformat[128] = { 0 }, str[128] = { 0 };
|
||||
const char * formatnormal = "XXXXXXXX XXXX";
|
||||
|
||||
*(LPWORD)str = sizeof(str);
|
||||
uint32_t len = SendDlgItemMessage(IDC_CHEAT_CODES, EM_GETLINE, (WPARAM)line, (LPARAM)(const char *)str);
|
||||
str[len] = 0;
|
||||
|
||||
if (len <= 0) { continue; }
|
||||
|
||||
for (uint32_t i = 0; i < sizeof(tempformat); i++)
|
||||
{
|
||||
if (isxdigit(str[i]))
|
||||
{
|
||||
tempformat[i] = 'X';
|
||||
}
|
||||
if (str[i] == ' ')
|
||||
{
|
||||
tempformat[i] = str[i];
|
||||
}
|
||||
if (str[i] == 0) { break; }
|
||||
}
|
||||
|
||||
if (strcmp(tempformat, formatnormal) == 0)
|
||||
{
|
||||
if (!Code.empty())
|
||||
{
|
||||
Code += ",";
|
||||
}
|
||||
Code += str;
|
||||
}
|
||||
else
|
||||
{
|
||||
ValidCode = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ValidCode;
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
/****************************************************************************
|
||||
* *
|
||||
* Project64 - A Nintendo 64 emulator. *
|
||||
* http://www.pj64-emu.com/ *
|
||||
* Copyright (C) 2012 Project64. All rights reserved. *
|
||||
* *
|
||||
* License: *
|
||||
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
||||
* *
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
class CEnhancementConfig :
|
||||
public CDialogImpl < CEnhancementConfig >
|
||||
{
|
||||
public:
|
||||
BEGIN_MSG_MAP_EX(CEnhancementConfig)
|
||||
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
|
||||
COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
|
||||
COMMAND_ID_HANDLER(ID_POPUP_EDIT, OnEditItem)
|
||||
COMMAND_ID_HANDLER(ID_POPUP_DELETE, OnDeleteItem)
|
||||
COMMAND_ID_HANDLER(ID_POPUP_ADDENHANCEMENT, OnAddEnhancement)
|
||||
NOTIFY_HANDLER_EX(IDC_ENHANCEMENTLIST, NM_CLICK, OnEnhancementListClicked)
|
||||
NOTIFY_HANDLER_EX(IDC_ENHANCEMENTLIST, NM_RCLICK, OnEnhancementListRClicked)
|
||||
NOTIFY_HANDLER_EX(IDC_ENHANCEMENTLIST, NM_DBLCLK, OnEnhancementListDblClicked)
|
||||
NOTIFY_HANDLER_EX(IDC_ENHANCEMENTLIST, TVN_SELCHANGED, OnEnhancementListSelChanged)
|
||||
END_MSG_MAP()
|
||||
|
||||
enum { IDD = IDD_Enhancement_Config };
|
||||
|
||||
CEnhancementConfig(void);
|
||||
~CEnhancementConfig(void);
|
||||
|
||||
void Display(void * ParentWindow);
|
||||
|
||||
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
|
||||
LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
|
||||
LRESULT OnAddEnhancement(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
|
||||
LRESULT OnEnhancementListClicked(NMHDR* pNMHDR);
|
||||
LRESULT OnEnhancementListRClicked(NMHDR* pNMHDR);
|
||||
LRESULT OnEnhancementListDblClicked(NMHDR* pNMHDR);
|
||||
LRESULT OnEnhancementListSelChanged(NMHDR* pNMHDR);
|
||||
LRESULT OnDeleteItem(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
|
||||
LRESULT OnEditItem(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
|
||||
|
||||
private:
|
||||
CEnhancementConfig(const CEnhancementConfig&); // Disable copy constructor
|
||||
CEnhancementConfig& operator=(const CEnhancementConfig&); // Disable assignment
|
||||
|
||||
enum TV_CHECK_STATE { TV_STATE_UNKNOWN, TV_STATE_CLEAR, TV_STATE_CHECKED, TV_STATE_INDETERMINATE };
|
||||
|
||||
void RefreshList(void);
|
||||
void AddCodeLayers(int index, const std::string & Name, HTREEITEM hParent, bool Active);
|
||||
void ChangeChildrenStatus(HTREEITEM hParent, bool Checked);
|
||||
void CheckParentStatus(HTREEITEM hParent);
|
||||
bool TV_SetCheckState(HTREEITEM hItem, TV_CHECK_STATE state);
|
||||
int TV_GetCheckState(HTREEITEM hItem);
|
||||
|
||||
CTreeViewCtrl m_TreeList;
|
||||
HTREEITEM m_hSelectedItem;
|
||||
};
|
|
@ -941,13 +941,9 @@ LRESULT CALLBACK CMainGui::MainGui_Proc(HWND hWnd, DWORD uMsg, DWORD wParam, DWO
|
|||
CSettingConfig SettingConfig(true);
|
||||
SettingConfig.Display(hWnd);
|
||||
}
|
||||
else if (LOWORD(wParam) == ID_POPUPMENU_CHOOSEENHANCEMENT)
|
||||
{
|
||||
CEnhancementConfig().Display(hWnd);
|
||||
}
|
||||
else if (LOWORD(wParam) == ID_POPUPMENU_EDITCHEATS)
|
||||
{
|
||||
CCheatsUI().Display(hWnd, true);
|
||||
_this->m_CheatsUI.Display(hWnd, true);
|
||||
}
|
||||
|
||||
if (g_Rom)
|
||||
|
@ -970,10 +966,6 @@ LRESULT CALLBACK CMainGui::MainGui_Proc(HWND hWnd, DWORD uMsg, DWORD wParam, DWO
|
|||
CSettingConfig SettingConfig(true);
|
||||
SettingConfig.Display(hWnd);
|
||||
}
|
||||
else if (LOWORD(wParam) == ID_POPUPMENU_CHOOSEENHANCEMENT)
|
||||
{
|
||||
CEnhancementConfig().Display(hWnd);
|
||||
}
|
||||
else if (LOWORD(wParam) == ID_POPUPMENU_EDITCHEATS)
|
||||
{
|
||||
CCheatsUI().Display(hWnd,true);
|
||||
|
|
Loading…
Reference in New Issue