Have Cheat UI validate via CEnhancement

This commit is contained in:
zilmar 2021-03-04 14:29:31 +10:30
parent 43a2081cae
commit bc81e041f8
6 changed files with 72 additions and 237 deletions

View File

@ -4,6 +4,9 @@
#include <Project64-core/N64System/SystemGlobals.h> #include <Project64-core/N64System/SystemGlobals.h>
#include <Project64-core/N64System/N64Class.h> #include <Project64-core/N64System/N64Class.h>
const char * CEnhancement::CheatIdent = "Cheat";
const char * CEnhancement::EnhancementIdent = "Enhancement";
#pragma warning(disable:4996) #pragma warning(disable:4996)
static std::string GenerateKeyName(const char * Name, const char * Ident, const char * PostIdent) static std::string GenerateKeyName(const char * Name, const char * Ident, const char * PostIdent)

View File

@ -6,6 +6,9 @@
class CEnhancement class CEnhancement
{ {
public: public:
static const char * CheatIdent;
static const char * EnhancementIdent;
struct CodeEntry struct CodeEntry
{ {
uint32_t Command; uint32_t Command;
@ -46,7 +49,6 @@ public:
private: private:
CEnhancement(); CEnhancement();
CEnhancement& operator=(const CEnhancement&);
void CheckValid(); void CheckValid();

View File

@ -94,7 +94,7 @@ void CEnhancements::UpdateCheats(const CEnhancementList & Cheats)
{ {
m_CheatFiles.erase(CheatFileItr); m_CheatFiles.erase(CheatFileItr);
} }
m_CheatFile = std::make_unique<CEnhancmentFile>(OutFile, "Cheat"); m_CheatFile = std::make_unique<CEnhancmentFile>(OutFile, CEnhancement::CheatIdent);
m_CheatFiles.insert(SectionFiles::value_type(SectionIdent, OutFile)); m_CheatFiles.insert(SectionFiles::value_type(SectionIdent, OutFile));
} }
@ -140,7 +140,7 @@ void CEnhancements::UpdateEnhancements(const CEnhancementList & Enhancements)
{ {
m_EnhancementFiles.erase(EnhancementFileItr); m_EnhancementFiles.erase(EnhancementFileItr);
} }
m_EnhancementFile = std::make_unique<CEnhancmentFile>(OutFile, "Enhancement"); m_EnhancementFile = std::make_unique<CEnhancmentFile>(OutFile, CEnhancement::EnhancementIdent);
m_EnhancementFiles.insert(SectionFiles::value_type(SectionIdent, OutFile)); m_EnhancementFiles.insert(SectionFiles::value_type(SectionIdent, OutFile));
} }
@ -248,8 +248,8 @@ void CEnhancements::Load(CMipsMemoryVM * MMU, CPlugins * Plugins)
WaitScanDone(); WaitScanDone();
CGuard Guard(m_CS); CGuard Guard(m_CS);
LoadEnhancements("Cheat", m_CheatFiles, m_CheatFile, m_Cheats); LoadEnhancements(CEnhancement::CheatIdent, m_CheatFiles, m_CheatFile, m_Cheats);
LoadEnhancements("Enhancement", m_EnhancementFiles, m_EnhancementFile, m_Enhancements); LoadEnhancements(CEnhancement::EnhancementIdent, m_EnhancementFiles, m_EnhancementFile, m_Enhancements);
ResetCodes(MMU); ResetCodes(MMU);
LoadActive(m_Cheats, nullptr); LoadActive(m_Cheats, nullptr);
@ -582,7 +582,7 @@ void CEnhancements::ScanFileThread(void)
{ {
do do
{ {
CEnhancmentFile EnhancmentFile(File, "Cheat"); CEnhancmentFile EnhancmentFile(File, CEnhancement::CheatIdent);
CEnhancmentFile::SectionList Sections; CEnhancmentFile::SectionList Sections;
EnhancmentFile.GetSections(Sections); EnhancmentFile.GetSections(Sections);
for (CEnhancmentFile::SectionList::const_iterator itr = Sections.begin(); itr != Sections.end(); itr++) for (CEnhancmentFile::SectionList::const_iterator itr = Sections.begin(); itr != Sections.end(); itr++)
@ -600,7 +600,7 @@ void CEnhancements::ScanFileThread(void)
{ {
do do
{ {
CEnhancmentFile EnhancmentFile(File, "Cheat"); CEnhancmentFile EnhancmentFile(File, CEnhancement::CheatIdent);
CEnhancmentFile::SectionList Sections; CEnhancmentFile::SectionList Sections;
EnhancmentFile.GetSections(Sections); EnhancmentFile.GetSections(Sections);
for (CEnhancmentFile::SectionList::const_iterator itr = Sections.begin(); itr != Sections.end(); itr++) for (CEnhancmentFile::SectionList::const_iterator itr = Sections.begin(); itr != Sections.end(); itr++)

View File

@ -696,35 +696,21 @@ LRESULT CEditCheat::OnAddCheat(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCt
return 0; return 0;
} }
CEnhancement Enhancement(CEnhancement::CheatIdent);
bool validcodes = false, validoptions = false, nooptions = false; if (!ReadEnhancement(Enhancement))
CodeFormat 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; return 0;
} }
if (m_EditEnhancement != nullptr) if (m_EditEnhancement != nullptr)
{ {
m_EditEnhancement->SetName(NewCheatName.c_str()); m_EditEnhancement->SetName(NewCheatName.c_str());
m_EditEnhancement->SetEntries(Entries); m_EditEnhancement->SetEntries(Enhancement.GetEntries());
m_EditEnhancement->SetOptions(Options); m_EditEnhancement->SetOptions(Enhancement.GetOptions());
m_EditEnhancement->SetNote(GetItemText(IDC_NOTES).c_str()); m_EditEnhancement->SetNote(GetItemText(IDC_NOTES).c_str());
} }
else 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); m_Cheats.AddItem(Enhancement);
} }
g_Enhancements->UpdateCheats(m_Cheats); g_Enhancements->UpdateCheats(m_Cheats);
@ -753,82 +739,31 @@ LRESULT CEditCheat::OnNewCheat(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCt
LRESULT CEditCheat::OnCodeNameChanged(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) LRESULT CEditCheat::OnCodeNameChanged(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{ {
bool validcodes, validoptions, nooptions; DetailsChanged();
CodeFormat Format;
ReadCodeEntries(validcodes, validoptions, nooptions, Format);
if (!nooptions)
{
ReadOptions(validoptions, Format);
}
bool CanAdd = validcodes && (validoptions || nooptions) && GetDlgItem(IDC_CODE_NAME).GetWindowTextLength() > 0;
GetDlgItem(IDC_ADD).EnableWindow(CanAdd);
return 0; return 0;
} }
LRESULT CEditCheat::OnCheatCodeChanged(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) LRESULT CEditCheat::OnCheatCodeChanged(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{ {
bool validcodes, validoptions, nooptions; DetailsChanged();
CodeFormat Format;
ReadCodeEntries(validcodes, validoptions, nooptions, Format);
if (Format > 0 && !GetDlgItem(IDC_LABEL_OPTIONS).IsWindowEnabled())
{
GetDlgItem(IDC_LABEL_OPTIONS).EnableWindow(true);
GetDlgItem(IDC_LABEL_OPTIONS_FORMAT).EnableWindow(true);
GetDlgItem(IDC_CHEAT_OPTIONS).EnableWindow(true);
}
if (Format <= 0 && GetDlgItem(IDC_LABEL_OPTIONS).IsWindowEnabled())
{
GetDlgItem(IDC_LABEL_OPTIONS).EnableWindow(false);
GetDlgItem(IDC_LABEL_OPTIONS_FORMAT).EnableWindow(false);
GetDlgItem(IDC_CHEAT_OPTIONS).EnableWindow(false);
}
if (!nooptions)
{
ReadOptions(validoptions, Format);
}
bool CanAdd = validcodes && (validoptions || nooptions) && GetDlgItem(IDC_CODE_NAME).GetWindowTextLength() > 0;
GetDlgItem(IDC_ADD).EnableWindow(CanAdd);
return 0; return 0;
} }
LRESULT CEditCheat::OnCheatOptionsChanged(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) LRESULT CEditCheat::OnCheatOptionsChanged(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{ {
bool ValidCodes, ValidOptions, NoOptions; DetailsChanged();
CodeFormat Format;
ReadCodeEntries(ValidCodes, ValidOptions, NoOptions, Format);
if (!NoOptions)
{
ReadOptions(ValidOptions, Format);
}
bool CanAdd = ValidCodes && (ValidOptions || NoOptions) && GetDlgItem(IDC_CODE_NAME).GetWindowTextLength() > 0;
GetDlgItem(IDC_ADD).EnableWindow(CanAdd);
return 0; return 0;
} }
CEnhancement::CodeEntries CEditCheat::ReadCodeEntries(bool &ValidCodes, bool &ValidOptions, bool &NoOptions, CodeFormat & Format) bool CEditCheat::ReadEnhancement(CEnhancement & Enhancement)
{ {
const char * FormatNormal = "XXXXXXXX XXXX"; CEnhancement TestEnhancement(CEnhancement::CheatIdent);
const char * FormatOptionLB = "XXXXXXXX XX??"; TestEnhancement.SetName(GetItemText(IDC_CODE_NAME).c_str());
const char * FormatOptionW = "XXXXXXXX ????"; TestEnhancement.SetNote(GetItemText(IDC_NOTES).c_str());
CEnhancement::CodeEntries Entries; CEnhancement::CodeEntries Entries;
ValidCodes = true;
ValidOptions = true;
NoOptions = true;
Format = CodeFormat_Invalid;
CEdit CheatCodes(GetDlgItem(IDC_CHEAT_CODES)); CEdit CheatCodes(GetDlgItem(IDC_CHEAT_CODES));
int NumLines = CheatCodes.GetLineCount(); int NumLines = CheatCodes.GetLineCount();
if (NumLines == 0)
{
ValidCodes = false;
}
for (int i = 0; i < NumLines; i++) for (int i = 0; i < NumLines; i++)
{ {
wchar_t wc_str[128]; wchar_t wc_str[128];
@ -839,23 +774,6 @@ CEnhancement::CodeEntries CEditCheat::ReadCodeEntries(bool &ValidCodes, bool &Va
} }
wc_str[len] = 0; wc_str[len] = 0;
std::string str = stdstr().FromUTF16(wc_str); std::string str = stdstr().FromUTF16(wc_str);
char TempFormat[128] = { 0 };
for (size_t c = 0; c < str.length(); c++)
{
if (isxdigit(str[c]))
{
TempFormat[c] = 'X';
}
else if ((str[c] == ' ') || (str[c] == '?'))
{
TempFormat[c] = str[c];
}
else
{
TempFormat[c] = '#';
}
}
CEnhancement::CodeEntry Entry; CEnhancement::CodeEntry Entry;
Entry.Command = strtoul(str.c_str(), 0, 16); Entry.Command = strtoul(str.c_str(), 0, 16);
const char * ReadPos = strchr(str.c_str(), ' '); const char * ReadPos = strchr(str.c_str(), ' ');
@ -866,64 +784,19 @@ CEnhancement::CodeEntries CEditCheat::ReadCodeEntries(bool &ValidCodes, bool &Va
} }
else else
{ {
Entries.clear(); return false;
break;
}
if (strcmp(TempFormat, FormatNormal) == 0)
{
if (Format == CodeFormat_Invalid)
{
Format = CodeFormat_Normal;
}
}
else if (strcmp(TempFormat, FormatOptionLB) == 0)
{
if (Format != CodeFormat_Word)
{
Format = CodeFormat_LowerByte;
NoOptions = false;
ValidOptions = false;
}
else
{
ValidCodes = false;
}
}
else if (strcmp(TempFormat, FormatOptionW) == 0)
{
if (Format != CodeFormat_LowerByte)
{
Format = CodeFormat_Word;
NoOptions = false;
ValidOptions = false;
}
else
{
ValidCodes = false;
}
}
else
{
ValidCodes = false;
} }
} }
TestEnhancement.SetEntries(Entries);
if (Entries.empty())
{
ValidCodes = false;
}
return Entries;
}
CEnhancement::CodeOptions CEditCheat::ReadOptions(bool &validoptions, CodeFormat Format)
{
CEnhancement::CodeOptions Options;
validoptions = true;
CEdit CheatOptions(GetDlgItem(IDC_CHEAT_OPTIONS)); CEdit CheatOptions(GetDlgItem(IDC_CHEAT_OPTIONS));
int NumLines = CheatOptions.GetLineCount(); NumLines = CheatOptions.GetLineCount();
std::string OptionsStr; std::string OptionsStr;
CEnhancement::CodeOptions Options;
if (NumLines > 0 && TestEnhancement.CodeOptionSize() == 0)
{
return false;
}
for (int i = 0; i < NumLines; i++) for (int i = 0; i < NumLines; i++)
{ {
wchar_t wc_str[128]; wchar_t wc_str[128];
@ -936,74 +809,47 @@ CEnhancement::CodeOptions CEditCheat::ReadOptions(bool &validoptions, CodeFormat
std::string str = stdstr().FromUTF16(wc_str); std::string str = stdstr().FromUTF16(wc_str);
CEnhancement::CodeOption Option; CEnhancement::CodeOption Option;
Option.Value = (uint16_t)strtoul(str.c_str(), 0, 16);
switch (Format) if ((uint32_t)len > TestEnhancement.CodeOptionSize() && str[TestEnhancement.CodeOptionSize()] != ' ')
{ {
case CodeFormat_LowerByte: return false;
if (len >= 2) { }
for (int c = 0; c < 2; c++) const char * ReadPos = strchr(str.c_str(), ' ');
{ if (ReadPos != nullptr)
if (!isxdigit(str[c])) {
{ Option.Name = ReadPos + 1;
validoptions = false; Options.push_back(Option);
break; }
} else
} {
return false;
if ((str[2] != ' ') && (len > 2))
{
validoptions = false;
break;
}
Option.Name = &str[3];
Option.Value = (uint16_t)strtoul(str.c_str(), 0, 16);
Options.push_back(Option);
}
else
{
validoptions = false;
break;
}
break;
case CodeFormat_Word:
if (len >= 4)
{
for (int c = 0; c < 4; c++)
{
if (!isxdigit(str[c]))
{
validoptions = false;
break;
}
}
if (str[4] != ' ' && (len > 4))
{
validoptions = false;
break;
}
Option.Name = &str[5];
Option.Value = (uint16_t)strtoul(str.c_str(), 0, 16);
Options.push_back(Option);
}
else
{
validoptions = false;
break;
}
break;
default:
validoptions = false;
break;
} }
} }
TestEnhancement.SetOptions(Options);
if (Options.size() == 0) if (!TestEnhancement.Valid())
{ {
validoptions = false; return false;
}
Enhancement = TestEnhancement;
return true;
}
void CEditCheat::DetailsChanged(void)
{
CEnhancement Enhancement(CEnhancement::CheatIdent);
if (!ReadEnhancement(Enhancement))
{
GetDlgItem(IDC_ADD).EnableWindow(false);
}
else
{
bool HasOptions = Enhancement.CodeOptionSize() > 0;
GetDlgItem(IDC_LABEL_OPTIONS).EnableWindow(HasOptions);
GetDlgItem(IDC_LABEL_OPTIONS_FORMAT).EnableWindow(HasOptions);
GetDlgItem(IDC_CHEAT_OPTIONS).EnableWindow(HasOptions);
GetDlgItem(IDC_ADD).EnableWindow(true);
} }
return Options;
} }
void CEditCheat::RecordCurrentValues(void) void CEditCheat::RecordCurrentValues(void)
@ -1038,16 +884,8 @@ bool CEditCheat::ValuesChanged(void)
} }
if (Result == IDYES) if (Result == IDYES)
{ {
bool validcodes, validoptions, nooptions; CEnhancement Enhancement(CEnhancement::CheatIdent);
CodeFormat Format; if (!ReadEnhancement(Enhancement))
ReadCodeEntries(validcodes, validoptions, nooptions, Format);
if (!nooptions)
{
ReadOptions(validoptions, Format);
}
bool CanAdd = validcodes && (validoptions || nooptions) && GetDlgItem(IDC_CODE_NAME).GetWindowTextLength() > 0;
if (CanAdd)
{ {
SendMessage(WM_COMMAND, MAKELPARAM(IDC_ADD, 0)); SendMessage(WM_COMMAND, MAKELPARAM(IDC_ADD, 0));
} }

View File

@ -78,14 +78,6 @@ public:
WM_EDITCHEAT = WM_USER + 0x120, WM_EDITCHEAT = WM_USER + 0x120,
}; };
enum CodeFormat
{
CodeFormat_Invalid = -1,
CodeFormat_Normal = 0,
CodeFormat_LowerByte = 1,
CodeFormat_Word = 2,
};
BEGIN_MSG_MAP_EX(CEditCheat) BEGIN_MSG_MAP_EX(CEditCheat)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
MESSAGE_HANDLER(WM_EDITCHEAT, OnEditCheat) MESSAGE_HANDLER(WM_EDITCHEAT, OnEditCheat)
@ -114,9 +106,9 @@ private:
LRESULT OnCheatCodeChanged(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); LRESULT OnCheatCodeChanged(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
LRESULT OnCheatOptionsChanged(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); LRESULT OnCheatOptionsChanged(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
CEnhancement::CodeEntries ReadCodeEntries(bool &ValidCodes, bool &ValidOptions, bool &NoOptions, CodeFormat & Format); bool ReadEnhancement(CEnhancement & Enhancement);
CEnhancement::CodeOptions ReadOptions(bool &validoptions, CodeFormat Format);
void DetailsChanged(void);
void RecordCurrentValues(void); void RecordCurrentValues(void);
bool ValuesChanged(void); bool ValuesChanged(void);
std::string GetItemText(int nIDDlgItem); std::string GetItemText(int nIDDlgItem);

View File

@ -540,7 +540,7 @@ LRESULT CEditEnhancement::OnOkCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl
} }
else else
{ {
CEnhancement Enhancement("Enhancement"); CEnhancement Enhancement(CEnhancement::EnhancementIdent);
Enhancement.SetName(GetCWindowText(GetDlgItem(IDC_CODE_NAME)).c_str()); Enhancement.SetName(GetCWindowText(GetDlgItem(IDC_CODE_NAME)).c_str());
Enhancement.SetOnByDefault(CButton(GetDlgItem(IDC_AUTOON)).GetCheck() == BST_CHECKED); Enhancement.SetOnByDefault(CButton(GetDlgItem(IDC_AUTOON)).GetCheck() == BST_CHECKED);
Enhancement.SetEntries(m_Entries); Enhancement.SetEntries(m_Entries);