Added option "Enable cheats" to dolphin config and some AR code changes.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@952 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
omegadox 2008-10-25 10:11:35 +00:00
parent 6a9f238b92
commit 81a6259fd1
5 changed files with 94 additions and 71 deletions

View File

@ -32,11 +32,11 @@
#include "IniFile.h" #include "IniFile.h"
#include "HW/Memmap.h" #include "HW/Memmap.h"
#include "ActionReplay.h" #include "ActionReplay.h"
#include "Core.h"
namespace { namespace {
// These should be turned into locals in RunActionReplayCode, and passed as parameters to the others. // These should be turned into locals in RunActionReplayCode, and passed as parameters to the others.
static u32 cmd_addr;
static u8 cmd; static u8 cmd;
static u32 addr; static u32 addr;
static u32 data; static u32 data;
@ -46,6 +46,7 @@ static u8 type;
static u8 zcode; static u8 zcode;
static bool doFillNSlide = false; static bool doFillNSlide = false;
static bool doMemoryCopy = false; static bool doMemoryCopy = false;
static bool fail = false;
static u32 addr_last; static u32 addr_last;
static u32 val_last; static u32 val_last;
static std::vector<AREntry>::const_iterator iter; static std::vector<AREntry>::const_iterator iter;
@ -66,6 +67,9 @@ void DoARZeroCode_MemoryCopy();
// Parses the Action Replay section of a game ini file. // Parses the Action Replay section of a game ini file.
void LoadActionReplayCodes(IniFile &ini) void LoadActionReplayCodes(IniFile &ini)
{ {
if (!Core::GetStartupParameter().bEnableCheats)
return; // If cheats are off, do not load them
std::vector<std::string> lines; std::vector<std::string> lines;
ARCode currentCode; ARCode currentCode;
arCodes.clear(); arCodes.clear();
@ -76,16 +80,33 @@ void LoadActionReplayCodes(IniFile &ini)
for (std::vector<std::string>::const_iterator it = lines.begin(); it != lines.end(); ++it) for (std::vector<std::string>::const_iterator it = lines.begin(); it != lines.end(); ++it)
{ {
std::string line = *it; std::string line = *it;
std::vector<std::string> pieces; std::vector<std::string> pieces;
// Check if the line is a name of the code
if (line[0] == '+' || line[0] == '$') {
if (currentCode.ops.size() > 0) {
arCodes.push_back(currentCode);
currentCode.ops.clear();
}
currentCode.name = line;
if (line[0] == '+') currentCode.active = true;
else currentCode.active = false;
continue;
}
SplitString(line, " ", pieces); SplitString(line, " ", pieces);
// Check if the AR code is decrypted
if (pieces.size() == 2 && pieces[0].size() == 8 && pieces[1].size() == 8) if (pieces.size() == 2 && pieces[0].size() == 8 && pieces[1].size() == 8)
{ {
// Smells like a decrypted Action Replay code, great! Decode!
AREntry op; AREntry op;
bool success = TryParseUInt(std::string("0x") + pieces[0], &op.cmd_addr); bool success_addr = TryParseUInt(std::string("0x") + pieces[0], &op.cmd_addr);
success |= TryParseUInt(std::string("0x") + pieces[1], &op.value); bool success_val = TryParseUInt(std::string("0x") + pieces[1], &op.value);
if (!success) if (!(success_addr | success_val)) {
PanicAlert("Invalid AR code line: %s", line.c_str()); PanicAlert("Action Replay Error: invalid AR code line: %s", line.c_str());
if (!success_addr) PanicAlert("The address is invalid");
if (!success_val) PanicAlert("The value is invalid");
}
else else
currentCode.ops.push_back(op); currentCode.ops.push_back(op);
} }
@ -97,28 +118,6 @@ void LoadActionReplayCodes(IniFile &ini)
// Encrypted AR code // Encrypted AR code
PanicAlert("Dolphin does not yet support encrypted AR codes."); PanicAlert("Dolphin does not yet support encrypted AR codes.");
} }
else if (line.size() > 1)
{
// OK, name line. This is the start of a new code. Push the old one, prepare the new one.
if (currentCode.ops.size())
arCodes.push_back(currentCode);
currentCode.name = "(invalid)";
currentCode.ops.clear();
if (line[0] == '+')
{
// Active code - name line.
line = StripSpaces(line.substr(1));
currentCode.name = line;
currentCode.active = true;
}
else
{
// Inactive code.
currentCode.name = line;
currentCode.active = false;
}
}
} }
} }
@ -129,26 +128,28 @@ void LoadActionReplayCodes(IniFile &ini)
void ActionReplayRunAllActive() void ActionReplayRunAllActive()
{ {
for (std::vector<ARCode>::const_iterator iter = arCodes.begin(); iter != arCodes.end(); ++iter) if (Core::GetStartupParameter().bEnableCheats && !fail) {
if (iter->active) for (std::vector<ARCode>::const_iterator iter = arCodes.begin(); iter != arCodes.end(); ++iter)
RunActionReplayCode(*iter, false); if (iter->active)
RunActionReplayCode(*iter, false);
}
} }
// The mechanism is slightly different than what the real AR uses, so there may be compatibility problems. // The mechanism is slightly different than what the real AR uses, so there may be compatibility problems.
// For example, some authors have created codes that add features to AR. Hacks for popular ones can be added here, // For example, some authors have created codes that add features to AR. Hacks for popular ones can be added here,
// but the problem is not generally solvable. // but the problem is not generally solvable.
// TODO: what is "nowIsBootup" for?
void RunActionReplayCode(const ARCode &arcode, bool nowIsBootup) { void RunActionReplayCode(const ARCode &arcode, bool nowIsBootup) {
code = arcode; code = arcode;
for (iter = code.ops.begin(); iter != code.ops.end(); ++iter) for (iter = code.ops.begin(); iter != code.ops.end(); ++iter)
{ {
cmd_addr = iter->cmd_addr;
cmd = iter->cmd_addr >> 24; cmd = iter->cmd_addr >> 24;
addr = iter->cmd_addr; addr = iter->cmd_addr;
data = iter->value; data = iter->value;
subtype = ((cmd_addr >> 30) & 0x03); subtype = ((addr >> 30) & 0x03);
w = (cmd & 0x07); w = (cmd & 0x07);
type = ((cmd_addr >> 27) & 0x07); type = ((addr >> 27) & 0x07);
zcode = ((data >> 29) & 0x07); zcode = ((data >> 29) & 0x07);
// Do Fill & Slide // Do Fill & Slide
@ -166,11 +167,12 @@ void RunActionReplayCode(const ARCode &arcode, bool nowIsBootup) {
// ActionReplay program self modification codes // ActionReplay program self modification codes
if (addr >= 0x00002000 && addr < 0x00003000) { if (addr >= 0x00002000 && addr < 0x00003000) {
PanicAlert("This action replay simulator does not support codes that modify Action Replay itself."); PanicAlert("This action replay simulator does not support codes that modify Action Replay itself.");
fail = true;
return; return;
} }
// skip these weird init lines // skip these weird init lines
if (iter == code.ops.begin() && cmd == 1) continue; if (iter == code.ops.begin() && cmd == 1) continue;
// Zero codes // Zero codes
if (addr == 0x0) // Check if the code is a zero code if (addr == 0x0) // Check if the code is a zero code
@ -184,8 +186,9 @@ void RunActionReplayCode(const ARCode &arcode, bool nowIsBootup) {
break; break;
case 0x03: // Executes all codes in the same row case 0x03: // Executes all codes in the same row
// Todo: Set register 1BB4 to 1 // Todo: Set register 1BB4 to 1
PanicAlert("Zero code 3 is not supported"); PanicAlert("Zero 3 code not supported");
continue; fail = true;
return;
case 0x04: // Fill & Slide or Memory Copy case 0x04: // Fill & Slide or Memory Copy
if (((addr >> 25) & 0x03) == 0x3) { if (((addr >> 25) & 0x03) == 0x3) {
doMemoryCopy = true; doMemoryCopy = true;
@ -199,7 +202,8 @@ void RunActionReplayCode(const ARCode &arcode, bool nowIsBootup) {
continue; continue;
default: default:
PanicAlert("Zero code unknown to dolphin: %08x",zcode); PanicAlert("Zero code unknown to dolphin: %08x",zcode);
continue; fail = true;
return;
} }
} }
@ -229,7 +233,7 @@ void DoARSubtype_RamWriteAndFill()
{ {
if (w < 0x8) // Check the value W in 0xZWXXXXXXX if (w < 0x8) // Check the value W in 0xZWXXXXXXX
{ {
u32 new_addr = ( (addr & 0x01FFFFFF) | 0x80000000); u32 new_addr = ((addr & 0x01FFFFFF) | 0x80000000);
switch ((addr >> 25) & 0x03) switch ((addr >> 25) & 0x03)
{ {
case 0x00: // Byte write case 0x00: // Byte write
@ -254,7 +258,9 @@ void DoARSubtype_RamWriteAndFill()
Memory::Write_U32(data, new_addr); Memory::Write_U32(data, new_addr);
break; break;
default: default:
break; // TODO(Omega): maybe add a PanicAlert here? PanicAlert("Action Replay Error: Invalid size in Ram Write And Fill (%s)",code.name.c_str());
fail = true;
return;
} }
} }
} }
@ -264,7 +270,7 @@ void DoARSubtype_WriteToPointer()
{ {
if (w < 0x8) if (w < 0x8)
{ {
u32 new_addr = ( addr | 0x80000000); u32 new_addr = ((addr & 0x01FFFFFF) | 0x80000000);
switch ((addr >> 25) & 0x03) switch ((addr >> 25) & 0x03)
{ {
case 0x00: // Byte write to pointer [40] case 0x00: // Byte write to pointer [40]
@ -290,8 +296,9 @@ void DoARSubtype_WriteToPointer()
break; break;
default: default:
PanicAlert("AR Method Error (Write To Pointer): w = %08x, addr = %08x", w, addr); PanicAlert("Action Replay Error: Invalid size in Write To Pointer (%s)",code.name.c_str());
break; fail = true;
return;
} }
} }
} }
@ -300,8 +307,8 @@ void DoARSubtype_AddCode()
{ {
if (w < 0x8) if (w < 0x8)
{ {
u32 new_addr = ( addr & 0x81FFFFFF); u32 new_addr = (addr & 0x81FFFFFF);
switch ((addr >> 25) & 0x03) switch ((new_addr >> 25) & 0x03)
{ {
case 0x0: // Byte add case 0x0: // Byte add
Memory::Write_U8(Memory::Read_U8(new_addr) + (data & 0xFF), new_addr); Memory::Write_U8(Memory::Read_U8(new_addr) + (data & 0xFF), new_addr);
@ -322,7 +329,9 @@ void DoARSubtype_AddCode()
break; break;
} }
default: default:
break; PanicAlert("Action Replay Error: Invalid size in Add Code (%s)",code.name.c_str());
fail = true;
return;
} }
} }
} }
@ -330,20 +339,12 @@ void DoARSubtype_AddCode()
void DoARSubtype_MasterCodeAndWriteToCCXXXXXX() void DoARSubtype_MasterCodeAndWriteToCCXXXXXX()
{ {
// code not yet implemented - TODO // code not yet implemented - TODO
PanicAlert("Action Replay Error: Master Code and Write To CCXXXXXX not implemented (%s)",code.name.c_str());
//if (w < 0x8) fail = true;
//{ return;
// u32 new_addr = (addr | 0x80000000);
// switch ((new_addr >> 25) & 0x03)
// {
// case 0x2:
// {
// }
// }
//}
} }
// TODO(Omega): I think this needs cleanup, there might be a better way to code this part
void DoARSubtype_Other() void DoARSubtype_Other()
{ {
switch (cmd & 0xFE) switch (cmd & 0xFE)
@ -407,15 +408,16 @@ void DoARSubtype_Other()
break; break;
} }
default: default:
PanicAlert("Unknown Action Replay command %02x (%08x %08x)", cmd, iter->cmd_addr, iter->value); PanicAlert("Action Replay Error: Unknown Action Replay command %02x (%08x %08x)(%s)", cmd, iter->cmd_addr, iter->value, code.name.c_str());
break; fail = true;
return;
} }
} }
void DoARZeroCode_FillAndSlide() void DoARZeroCode_FillAndSlide()
{ {
u32 new_addr = (addr_last & 0x81FFFFFF); u32 new_addr = (addr_last & 0x81FFFFFF);
u8 size = ((new_addr >> 25) & 0x03); u8 size = ((new_addr >> 25) & 0x03);
u32 addr_incr; int addr_incr;
u32 val = addr; u32 val = addr;
int val_incr; int val_incr;
u8 write_num = ((data & 0x78000) >> 16); // Z2 u8 write_num = ((data & 0x78000) >> 16); // Z2
@ -449,8 +451,7 @@ void DoARZeroCode_FillAndSlide()
Memory::Write_U8(val & 0xFF, new_addr + j); Memory::Write_U8(val & 0xFF, new_addr + j);
} }
val += val_incr; val += val_incr;
if (val_incr < 0) curr_addr -= addr_incr; curr_addr += addr_incr;
else curr_addr += addr_incr;
} break; } break;
case 0x1: // Halfword case 0x1: // Halfword
for(int i=0; i < write_num; i++) { for(int i=0; i < write_num; i++) {
@ -459,17 +460,19 @@ void DoARZeroCode_FillAndSlide()
Memory::Write_U8(val & 0xFFFF, new_addr + j * 2); Memory::Write_U8(val & 0xFFFF, new_addr + j * 2);
} }
val += val_incr; val += val_incr;
if (val_incr < 0) curr_addr -= addr_incr; curr_addr += addr_incr;
else curr_addr += addr_incr;
} break; } break;
case 0x2: // Word case 0x2: // Word
for(int i=0; i < write_num; i++) { for(int i=0; i < write_num; i++) {
Memory::Write_U16(val, new_addr); Memory::Write_U16(val, new_addr);
val += val_incr; val += val_incr;
if (val_incr < 0) curr_addr -= addr_incr; curr_addr += addr_incr;
else curr_addr += addr_incr;
} break; } break;
default: break; default:
PanicAlert("Action Replay Error: Invalid size in Fill and Slide (%s)",code.name.c_str());
doFillNSlide = false;
fail = true;
return;
} }
doFillNSlide = false; doFillNSlide = false;
return; return;
@ -492,4 +495,9 @@ void DoARZeroCode_MemoryCopy()
} return; } return;
} }
} }
else {
PanicAlert("Action Replay Error: Invalid value (&08x) in Memory Copy (%s)", (data & ~0x7FFF), code.name.c_str());
fail = true;
return;
}
} }

View File

@ -50,6 +50,7 @@ struct SCoreStartupParameter
bool bUseFastMem; bool bUseFastMem;
bool bLockThreads; bool bLockThreads;
bool bOptimizeQuantizers; bool bOptimizeQuantizers;
bool bEnableCheats;
bool bRunCompareServer; bool bRunCompareServer;
bool bRunCompareClient; bool bRunCompareClient;

View File

@ -72,6 +72,7 @@ void SConfig::SaveSettings()
ini.Set("Core", "DefaultGCM", m_LocalCoreStartupParameter.m_strDefaultGCM); ini.Set("Core", "DefaultGCM", m_LocalCoreStartupParameter.m_strDefaultGCM);
ini.Set("Core", "DVDRoot", m_LocalCoreStartupParameter.m_strDVDRoot); ini.Set("Core", "DVDRoot", m_LocalCoreStartupParameter.m_strDVDRoot);
ini.Set("Core", "OptimizeQuantizers", m_LocalCoreStartupParameter.bOptimizeQuantizers); ini.Set("Core", "OptimizeQuantizers", m_LocalCoreStartupParameter.bOptimizeQuantizers);
ini.Set("Core", "EnableCheats", m_LocalCoreStartupParameter.bEnableCheats);
ini.Set("Core", "SelectedLanguage", m_LocalCoreStartupParameter.SelectedLanguage); ini.Set("Core", "SelectedLanguage", m_LocalCoreStartupParameter.SelectedLanguage);
ini.Set("Core", "RunCompareServer", m_LocalCoreStartupParameter.bRunCompareServer); ini.Set("Core", "RunCompareServer", m_LocalCoreStartupParameter.bRunCompareServer);
ini.Set("Core", "RunCompareClient", m_LocalCoreStartupParameter.bRunCompareClient); ini.Set("Core", "RunCompareClient", m_LocalCoreStartupParameter.bRunCompareClient);
@ -128,6 +129,7 @@ void SConfig::LoadSettings()
ini.Get("Core", "DefaultGCM", &m_LocalCoreStartupParameter.m_strDefaultGCM); ini.Get("Core", "DefaultGCM", &m_LocalCoreStartupParameter.m_strDefaultGCM);
ini.Get("Core", "DVDRoot", &m_LocalCoreStartupParameter.m_strDVDRoot); ini.Get("Core", "DVDRoot", &m_LocalCoreStartupParameter.m_strDVDRoot);
ini.Get("Core", "OptimizeQuantizers", &m_LocalCoreStartupParameter.bOptimizeQuantizers, true); ini.Get("Core", "OptimizeQuantizers", &m_LocalCoreStartupParameter.bOptimizeQuantizers, true);
ini.Get("Core", "EnableCheats", &m_LocalCoreStartupParameter.bEnableCheats, false);
ini.Get("Core", "SelectedLanguage", &m_LocalCoreStartupParameter.SelectedLanguage, 0); ini.Get("Core", "SelectedLanguage", &m_LocalCoreStartupParameter.SelectedLanguage, 0);
ini.Get("Core", "RunCompareServer", &m_LocalCoreStartupParameter.bRunCompareServer, false); ini.Get("Core", "RunCompareServer", &m_LocalCoreStartupParameter.bRunCompareServer, false);
ini.Get("Core", "RunCompareClient", &m_LocalCoreStartupParameter.bRunCompareClient, false); ini.Get("Core", "RunCompareClient", &m_LocalCoreStartupParameter.bRunCompareClient, false);

View File

@ -37,6 +37,7 @@ EVT_CHECKBOX(ID_USEDUALCORE, CConfigMain::UseDualCoreCheck)
EVT_CHECKBOX(ID_LOCKTHREADS, CConfigMain::LockThreadsCheck) EVT_CHECKBOX(ID_LOCKTHREADS, CConfigMain::LockThreadsCheck)
EVT_CHECKBOX(ID_OPTIMIZEQUANTIZERS, CConfigMain::OptimizeQuantizersCheck) EVT_CHECKBOX(ID_OPTIMIZEQUANTIZERS, CConfigMain::OptimizeQuantizersCheck)
EVT_CHECKBOX(ID_IDLESKIP, CConfigMain::SkipIdleCheck) EVT_CHECKBOX(ID_IDLESKIP, CConfigMain::SkipIdleCheck)
EVT_CHECKBOX(ID_ENABLECHEATS, CConfigMain::EnableCheatsCheck)
EVT_CHOICE(ID_CONSOLELANG, CConfigMain::ConsoleLangChanged) EVT_CHOICE(ID_CONSOLELANG, CConfigMain::ConsoleLangChanged)
EVT_LISTBOX(ID_ISOPATHS, CConfigMain::ISOPathsSelectionChanged) EVT_LISTBOX(ID_ISOPATHS, CConfigMain::ISOPathsSelectionChanged)
EVT_BUTTON(ID_ADDISOPATH, CConfigMain::AddRemoveISOPaths) EVT_BUTTON(ID_ADDISOPATH, CConfigMain::AddRemoveISOPaths)
@ -109,6 +110,8 @@ void CConfigMain::CreateGUIControls()
OptimizeQuantizers->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bOptimizeQuantizers); OptimizeQuantizers->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bOptimizeQuantizers);
SkipIdle = new wxCheckBox(GeneralPage, ID_IDLESKIP, wxT("Use idle skipping"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); SkipIdle = new wxCheckBox(GeneralPage, ID_IDLESKIP, wxT("Use idle skipping"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
SkipIdle->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle); SkipIdle->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle);
EnableCheats = new wxCheckBox(GeneralPage, ID_ENABLECHEATS, wxT("Enable cheats"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
EnableCheats->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats);
wxArrayString arrayStringFor_ConsoleLang; wxArrayString arrayStringFor_ConsoleLang;
arrayStringFor_ConsoleLang.Add(wxT("English")); arrayStringFor_ConsoleLang.Add(wxT("English"));
arrayStringFor_ConsoleLang.Add(wxT("German")); arrayStringFor_ConsoleLang.Add(wxT("German"));
@ -127,8 +130,9 @@ void CConfigMain::CreateGUIControls()
sGeneral->Add(LockThreads, wxGBPosition(3, 0), wxGBSpan(1, 2), wxALL, 5); sGeneral->Add(LockThreads, wxGBPosition(3, 0), wxGBSpan(1, 2), wxALL, 5);
sGeneral->Add(OptimizeQuantizers, wxGBPosition(4, 0), wxGBSpan(1, 2), wxALL, 5); sGeneral->Add(OptimizeQuantizers, wxGBPosition(4, 0), wxGBSpan(1, 2), wxALL, 5);
sGeneral->Add(SkipIdle, wxGBPosition(5, 0), wxGBSpan(1, 2), wxALL, 5); sGeneral->Add(SkipIdle, wxGBPosition(5, 0), wxGBSpan(1, 2), wxALL, 5);
sGeneral->Add(ConsoleLangText, wxGBPosition(6, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5); sGeneral->Add(EnableCheats, wxGBPosition(6, 0), wxGBSpan(1, 2), wxALL, 5);
sGeneral->Add(ConsoleLang, wxGBPosition(6, 1), wxGBSpan(1, 1), wxALL, 5); sGeneral->Add(ConsoleLangText, wxGBPosition(7, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5);
sGeneral->Add(ConsoleLang, wxGBPosition(7, 1), wxGBSpan(1, 1), wxALL, 5);
GeneralPage->SetSizer(sGeneral); GeneralPage->SetSizer(sGeneral);
sGeneral->Layout(); sGeneral->Layout();
@ -272,6 +276,11 @@ void CConfigMain::SkipIdleCheck(wxCommandEvent& WXUNUSED (event))
SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle = SkipIdle->IsChecked(); SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle = SkipIdle->IsChecked();
} }
void CConfigMain::EnableCheatsCheck(wxCommandEvent& WXUNUSED (event))
{
SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats = EnableCheats->IsChecked();
}
void CConfigMain::ConsoleLangChanged(wxCommandEvent& WXUNUSED (event)) void CConfigMain::ConsoleLangChanged(wxCommandEvent& WXUNUSED (event))
{ {
SConfig::GetInstance().m_LocalCoreStartupParameter.SelectedLanguage = ConsoleLang->GetSelection(); SConfig::GetInstance().m_LocalCoreStartupParameter.SelectedLanguage = ConsoleLang->GetSelection();

View File

@ -65,6 +65,7 @@ class CConfigMain
wxCheckBox* LockThreads; wxCheckBox* LockThreads;
wxCheckBox* OptimizeQuantizers; wxCheckBox* OptimizeQuantizers;
wxCheckBox* SkipIdle; wxCheckBox* SkipIdle;
wxCheckBox* EnableCheats;
wxStaticText* ConsoleLangText; wxStaticText* ConsoleLangText;
wxChoice* ConsoleLang; wxChoice* ConsoleLang;
@ -105,6 +106,7 @@ class CConfigMain
ID_LOCKTHREADS, ID_LOCKTHREADS,
ID_OPTIMIZEQUANTIZERS, ID_OPTIMIZEQUANTIZERS,
ID_IDLESKIP, ID_IDLESKIP,
ID_ENABLECHEATS,
ID_CONSOLELANG_TEXT, ID_CONSOLELANG_TEXT,
ID_CONSOLELANG, ID_CONSOLELANG,
ID_ISOPATHS, ID_ISOPATHS,
@ -142,6 +144,7 @@ class CConfigMain
void LockThreadsCheck(wxCommandEvent& event); void LockThreadsCheck(wxCommandEvent& event);
void OptimizeQuantizersCheck(wxCommandEvent& event); void OptimizeQuantizersCheck(wxCommandEvent& event);
void SkipIdleCheck(wxCommandEvent& event); void SkipIdleCheck(wxCommandEvent& event);
void EnableCheatsCheck(wxCommandEvent& event);
void ConsoleLangChanged(wxCommandEvent& event); void ConsoleLangChanged(wxCommandEvent& event);
void ISOPathsSelectionChanged(wxCommandEvent& event); void ISOPathsSelectionChanged(wxCommandEvent& event);
void AddRemoveISOPaths(wxCommandEvent& event); void AddRemoveISOPaths(wxCommandEvent& event);