Change the handling of the cheat format

This commit is contained in:
zilmar 2020-12-30 09:14:04 +10:30
parent 003205f254
commit 7de3fc3348
40 changed files with 1963 additions and 2846 deletions

View File

@ -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

View File

@ -127,4 +127,4 @@ protected:
CFileStorage m_FileObject;
};
typedef CIniFileT<CFile> CIniFile;
typedef CIniFileT<CFile> CIniFile;

View File

@ -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)

View File

@ -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;
}

View File

@ -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();

View File

@ -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();
}

View File

@ -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);
};

View File

@ -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;
};

View File

@ -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());
}
}

View File

@ -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;
};

View File

@ -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;
}
}

View File

@ -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;
};

View File

@ -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;*/
}

View File

@ -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);
};

View File

@ -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;
}

View File

@ -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;
};

View File

@ -0,0 +1 @@
#include "../stdafx.h"

View File

@ -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))

View File

@ -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); }
}

View File

@ -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

View File

@ -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>

View File

@ -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;

View File

@ -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;

View File

@ -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>

View File

@ -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" />

View File

@ -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>

View File

@ -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);

View File

@ -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();

View File

@ -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;
}

View File

@ -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);
};

View File

@ -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;

View File

@ -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,

View File

@ -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" />

View File

@ -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>

View File

@ -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"

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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);