From 2e39f2f477b3daf20eab5e99264fd98c86e9937f Mon Sep 17 00:00:00 2001 From: BearOso Date: Tue, 10 May 2022 20:47:12 -0500 Subject: [PATCH] Modernize cheat stuff. --- cheats.cpp | 106 -------- cheats.h | 38 ++- cheats2.cpp | 576 +++++++++++++++++++++--------------------- cpu.cpp | 4 +- gtk/src/gtk_cheat.cpp | 99 +++----- gtk/src/gtk_file.cpp | 2 +- msu1.cpp | 1 - snes9x.cpp | 4 +- 8 files changed, 350 insertions(+), 480 deletions(-) diff --git a/cheats.cpp b/cheats.cpp index 0b54a0f7..46347c16 100644 --- a/cheats.cpp +++ b/cheats.cpp @@ -37,112 +37,6 @@ (s) == S9X_24_BITS ? (((int32) ((*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16)) << 8)) >> 8): \ ((int32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24)))) -static bool8 S9xAllHex (const char *, int); - - -static bool8 S9xAllHex (const char *code, int len) -{ - for (int i = 0; i < len; i++) - if ((code[i] < '0' || code[i] > '9') && (code[i] < 'a' || code[i] > 'f') && (code[i] < 'A' || code[i] > 'F')) - return (FALSE); - - return (TRUE); -} - -const char * S9xProActionReplayToRaw (const char *code, uint32 &address, uint8 &byte) -{ - uint32 data = 0; - - if (strlen(code) != 8 || !S9xAllHex(code, 8) || sscanf(code, "%x", &data) != 1) - return ("Invalid Pro Action Replay code - should be 8 hex digits in length."); - - address = data >> 8; - byte = (uint8) data; - - return (NULL); -} - -const char * S9xGoldFingerToRaw (const char *code, uint32 &address, bool8 &sram, uint8 &num_bytes, uint8 bytes[3]) -{ - char tmp[15]; - int i; - - if (strlen(code) != 14) - return ("Invalid Gold Finger code - should be 14 hex digits in length."); - - strncpy(tmp, code, 5); - tmp[5] = 0; - if (sscanf(tmp, "%x", &address) != 1) - return ("Invalid Gold Finger code."); - - // Correct GoldFinger Address - address = (address & 0x7FFF) | ((address & 0x7F8000) << 1) | 0x8000; - - for (i = 0; i < 3; i++) - { - unsigned int byte; - - strncpy(tmp, code + 5 + i * 2, 2); - tmp[2] = 0; - if (sscanf(tmp, "%x", &byte) != 1) - break; - bytes[i] = (uint8) byte; - } - - num_bytes = i; - sram = code[13] == '1'; - - return (NULL); -} - -const char * S9xGameGenieToRaw (const char *code, uint32 &address, uint8 &byte) -{ - char new_code[12]; - - if (strlen(code) != 9 || *(code + 4) != '-' || !S9xAllHex(code, 4) || !S9xAllHex(code + 5, 4)) - return ("Invalid Game Genie(tm) code - should be 'xxxx-xxxx'."); - - strcpy(new_code, "0x"); - strncpy(new_code + 2, code, 4); - strcpy(new_code + 6, code + 5); - - static const char *real_hex = "0123456789ABCDEF"; - static const char *genie_hex = "DF4709156BC8A23E"; - - for (int i = 2; i < 10; i++) - { - if (islower(new_code[i])) - new_code[i] = toupper(new_code[i]); - - int j; - for (j = 0; j < 16; j++) - { - if (new_code[i] == genie_hex[j]) - { - new_code[i] = real_hex[j]; - break; - } - } - - if (j == 16) - return ("Invalid hex-character in Game Genie(tm) code."); - } - - uint32 data = 0; - sscanf(new_code, "%x", &data); - byte = (uint8) (data >> 24); - address = data & 0xffffff; - address = ((address & 0x003c00) << 10) + - ((address & 0x00003c) << 14) + - ((address & 0xf00000) >> 8) + - ((address & 0x000003) << 10) + - ((address & 0x00c000) >> 6) + - ((address & 0x0f0000) >> 12) + - ((address & 0x0003c0) >> 6); - - return (NULL); -} - void S9xStartCheatSearch (SCheatData *d) { memmove(d->CWRAM, d->RAM, 0x20000); diff --git a/cheats.h b/cheats.h index 7fbabd75..fbc15982 100644 --- a/cheats.h +++ b/cheats.h @@ -23,14 +23,14 @@ struct SCheat struct SCheatGroup { - char *name; + std::string name; bool8 enabled; - std::vector c; + std::vector cheat; }; struct SCheatData { - std::vector g; + std::vector group; bool8 enabled; uint8 CWRAM[0x20000]; uint8 CSRAM[0x80000]; @@ -73,20 +73,20 @@ typedef enum extern SCheatData Cheat; extern Watch watches[16]; -int S9xAddCheatGroup (const char *name, const char *cheat); -int S9xModifyCheatGroup (uint32 index, const char *name, const char *cheat); -void S9xEnableCheatGroup (uint32 index); -void S9xDisableCheatGroup (uint32 index); -void S9xDeleteCheats (void); -char *S9xCheatGroupToText (uint32 index); -void S9xDeleteCheatGroup (uint32 index); -bool8 S9xLoadCheatFile (const char *filename); -bool8 S9xSaveCheatFile (const char *filename); -void S9xUpdateCheatsInMemory (void); -int S9xImportCheatsFromDatabase(const char *filename); -void S9xCheatsDisable (void); -void S9xCheatsEnable (void); -char *S9xCheatValidate (const char *cheat); +int S9xAddCheatGroup(const std::string &name, const std::string &cheat); +int S9xModifyCheatGroup(uint32 index, const std::string &name, const std::string &cheat); +void S9xEnableCheatGroup(uint32 index); +void S9xDisableCheatGroup(uint32 index); +void S9xDeleteCheats(void); +std::string S9xCheatGroupToText(uint32 index); +void S9xDeleteCheatGroup(uint32 index); +bool8 S9xLoadCheatFile(const std::string &filename); +bool8 S9xSaveCheatFile(const std::string &filename); +void S9xUpdateCheatsInMemory(void); +int S9xImportCheatsFromDatabase(const std::string &filename); +void S9xCheatsDisable(void); +void S9xCheatsEnable(void); +std::string S9xCheatValidate(const std::string &cheat); void S9xInitCheatData (void); void S9xInitWatchedAddress (void); @@ -96,8 +96,4 @@ void S9xSearchForValue (SCheatData *, S9xCheatComparisonType, S9xCheatDataSize, void S9xSearchForAddress (SCheatData *, S9xCheatComparisonType, S9xCheatDataSize, uint32, bool8); void S9xOutputCheatSearchResults (SCheatData *); -const char * S9xGameGenieToRaw (const char *, uint32 &, uint8 &); -const char * S9xProActionReplayToRaw (const char *, uint32 &, uint8 &); -const char * S9xGoldFingerToRaw (const char *, uint32 &, bool8 &, uint8 &, uint8 bytes[3]); - #endif diff --git a/cheats2.cpp b/cheats2.cpp index 83a29693..c58e2b6a 100644 --- a/cheats2.cpp +++ b/cheats2.cpp @@ -4,37 +4,25 @@ For further information, consult the LICENSE file in the root directory. \*****************************************************************************/ -#include - +#include "bml.h" +#include "cheats.h" +#include "fmt/format.h" #include "snes9x.h" #include "memmap.h" -#include "cheats.h" -#include "bml.h" -static inline char *trim (char *string) +static inline uint8 S9xGetByteFree(uint32 Address) { - int start; - int end; - - for (start = 0; string[start] && isspace (string[start]); start++) {} - for (end = start; string[end] && !isspace (string[end]); end++) {} - string[end] = '\0'; - return &string[start]; -} - -static inline uint8 S9xGetByteFree (uint32 Address) -{ - int block = (Address & 0xffffff) >> MEMMAP_SHIFT; + int block = (Address & 0xffffff) >> MEMMAP_SHIFT; uint8 *GetAddress = Memory.Map[block]; uint8 byte; - if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + if (GetAddress >= (uint8 *)CMemory::MAP_LAST) { byte = *(GetAddress + (Address & 0xffff)); return (byte); } - switch ((pint) GetAddress) + switch ((pint)GetAddress) { case CMemory::MAP_CPU: byte = S9xGetCPU(Address & 0xffff); @@ -108,18 +96,18 @@ static inline uint8 S9xGetByteFree (uint32 Address) } } -static inline void S9xSetByteFree (uint8 Byte, uint32 Address) +static inline void S9xSetByteFree(uint8 Byte, uint32 Address) { int block = (Address & 0xffffff) >> MEMMAP_SHIFT; uint8 *SetAddress = Memory.Map[block]; - if (SetAddress >= (uint8 *) CMemory::MAP_LAST) + if (SetAddress >= (uint8 *)CMemory::MAP_LAST) { *(SetAddress + (Address & 0xffff)) = Byte; return; } - switch ((pint) SetAddress) + switch ((pint)SetAddress) { case CMemory::MAP_CPU: S9xSetCPU(Byte, Address & 0xffff); @@ -197,165 +185,229 @@ static inline void S9xSetByteFree (uint8 Byte, uint32 Address) } } -void S9xInitWatchedAddress (void) +void S9xInitWatchedAddress(void) { for (unsigned int i = 0; i < sizeof(watches) / sizeof(watches[0]); i++) watches[i].on = false; } -void S9xInitCheatData (void) +void S9xInitCheatData(void) { Cheat.RAM = Memory.RAM; Cheat.SRAM = Memory.SRAM; Cheat.FillRAM = Memory.FillRAM; } +static inline std::string trim(const std::string &&string) +{ + auto start = string.find_first_not_of(" \t\n\r"); + auto end = string.find_last_not_of(" \t\n\r"); + if (start != std::string::npos && end != std::string::npos) + return string.substr(start, end - start + 1); + return ""; +} -void S9xUpdateCheatInMemory (SCheat *c) +void S9xUpdateCheatInMemory(SCheat &c) { uint8 byte; - if (!c->enabled) + if (!c.enabled) return; - byte = S9xGetByteFree (c->address); + byte = S9xGetByteFree(c.address); - if (byte != c->byte) + if (byte != c.byte) { /* The game wrote a different byte to the address, update saved_byte */ - c->saved_byte = byte; + c.saved_byte = byte; - if (c->conditional) + if (c.conditional) { - if (c->saved_byte != c->cond_byte && c->cond_true) + if (c.saved_byte != c.cond_byte && c.cond_true) { /* Condition is now false, let the byte stand */ - c->cond_true = false; + c.cond_true = false; } - else if (c->saved_byte == c->cond_byte && !c->cond_true) + else if (c.saved_byte == c.cond_byte && !c.cond_true) { - c->cond_true = true; - S9xSetByteFree (c->byte, c->address); + c.cond_true = true; + S9xSetByteFree(c.byte, c.address); } } else - S9xSetByteFree (c->byte, c->address); + S9xSetByteFree(c.byte, c.address); } - else if (c->conditional) + else if (c.conditional) { - if (byte == c->cond_byte) + if (byte == c.cond_byte) { - c->cond_true = true; - c->saved_byte = byte; - S9xSetByteFree (c->byte, c->address); + c.cond_true = true; + c.saved_byte = byte; + S9xSetByteFree(c.byte, c.address); } } } -void S9xDisableCheat (SCheat *c) +void S9xDisableCheat(SCheat &c) { - if (!c->enabled) + if (!c.enabled) return; if (!Cheat.enabled) { - c->enabled = false; + c.enabled = false; return; } /* Make sure we restore the up-to-date written byte */ - S9xUpdateCheatInMemory (c); - c->enabled = false; + S9xUpdateCheatInMemory(c); + c.enabled = false; - if (c->conditional && !c->cond_true) + if (c.conditional && !c.cond_true) return; - S9xSetByteFree (c->saved_byte, c->address); - c->cond_true = false; + S9xSetByteFree (c.saved_byte, c.address); + c.cond_true = false; } -void S9xDeleteCheatGroup (uint32 g) +void S9xDeleteCheatGroup(uint32 g) { unsigned int i; - if (g >= Cheat.g.size ()) + if (g >= Cheat.group.size()) return; - for (i = 0; i < Cheat.g[g].c.size (); i++) + for (i = 0; i < Cheat.group[g].cheat.size(); i++) { - S9xDisableCheat (&Cheat.g[g].c[i]); + S9xDisableCheat(Cheat.group[g].cheat[i]); } - delete[] Cheat.g[g].name; - - Cheat.g.erase (Cheat.g.begin () + g); + Cheat.group.erase(Cheat.group.begin() + g); } -void S9xDeleteCheats (void) +void S9xDeleteCheats(void) { - unsigned int i; - - for (i = 0; i < Cheat.g.size (); i++) + for (size_t i = 0; i < Cheat.group.size(); i++) { - S9xDisableCheatGroup (i); - - delete[] Cheat.g[i].name; + S9xDisableCheatGroup(i); } - Cheat.g.clear (); + Cheat.group.clear(); } -void S9xEnableCheat (SCheat *c) +void S9xEnableCheat(SCheat &c) { uint8 byte; - if (c->enabled) + if (c.enabled) return; - c->enabled = true; + c.enabled = true; if (!Cheat.enabled) return; - byte = S9xGetByteFree(c->address); + byte = S9xGetByteFree(c.address); - if (c->conditional) + if (c.conditional) { - if (byte != c->cond_byte) + if (byte != c.cond_byte) return; - c->cond_true = true; + c.cond_true = true; } - c->saved_byte = byte; - S9xSetByteFree (c->byte, c->address); + c.saved_byte = byte; + S9xSetByteFree(c.byte, c.address); } -void S9xEnableCheatGroup (uint32 num) +void S9xEnableCheatGroup(uint32 num) { - unsigned int i; + for (auto &c : Cheat.group[num].cheat) + S9xEnableCheat(c); - for (i = 0; i < Cheat.g[num].c.size (); i++) - { - S9xEnableCheat (&Cheat.g[num].c[i]); - } - - Cheat.g[num].enabled = true; + Cheat.group[num].enabled = true; } -void S9xDisableCheatGroup (uint32 num) +void S9xDisableCheatGroup(uint32 num) { - unsigned int i; + for (auto &c : Cheat.group[num].cheat) + S9xDisableCheat(c); - for (i = 0; i < Cheat.g[num].c.size (); i++) - { - S9xDisableCheat (&Cheat.g[num].c[i]); - } - - Cheat.g[num].enabled = false; + Cheat.group[num].enabled = false; } -SCheat S9xTextToCheat (char *text) +static bool is_all_hex(const std::string &code) +{ + for (const auto &c : code) + { + if ((c < '0' || c > '9') && + (c < 'a' || c > 'f') && + (c < 'A' || c > 'F')) + return false; + } + + return true; +} + +bool S9xProActionReplayToRaw(const std::string &code, uint32 &address, uint8 &byte) +{ + if (code.length() != 8 || !is_all_hex(code)) + return false; + + uint32 data = std::strtoul(code.c_str(), nullptr, 16); + + address = data >> 8; + byte = (uint8)data; + + return true; +} + +bool S9xGameGenieToRaw(const std::string &code, uint32 &address, uint8 &byte) +{ + if (code.length() != 9) + return false; + if (code[4] != '-') + return false; + if (!is_all_hex(code.substr(0, 4))) + return false; + if (!is_all_hex(code.substr(5, 4))) + return false; + + auto new_code = code.substr(0, 4) + code.substr(5, 4); + + static const char *real_hex = "0123456789ABCDEF"; + static const char *genie_hex = "DF4709156BC8A23E"; + + for (auto &c : new_code) + { + c = toupper(c); + + for (int i = 0; i < 16; i++) + { + if (genie_hex[i] == c) + { + c = real_hex[i]; + break; + } + } + } + + uint32 data = strtoul(new_code.c_str(), nullptr, 16); + byte = (uint8)(data >> 24); + address = data & 0xffffff; + address = ((address & 0x003c00) << 10) + + ((address & 0x00003c) << 14) + + ((address & 0xf00000) >> 8) + + ((address & 0x000003) << 10) + + ((address & 0x00c000) >> 6) + + ((address & 0x0f0000) >> 12) + + ((address & 0x0003c0) >> 6); + + return true; +} + +SCheat S9xTextToCheat(const std::string &text) { SCheat c; unsigned int byte = 0; @@ -364,34 +416,28 @@ SCheat S9xTextToCheat (char *text) c.enabled = false; c.conditional = false; - if (!S9xGameGenieToRaw (text, c.address, c.byte)) + if (S9xGameGenieToRaw(text, c.address, c.byte)) { byte = c.byte; } - - else if (!S9xProActionReplayToRaw (text, c.address, c.byte)) + else if (S9xProActionReplayToRaw(text, c.address, c.byte)) { byte = c.byte; } - - else if (sscanf (text, "%x = %x ? %x", &c.address, &cond_byte, &byte) == 3) + else if (sscanf(text.c_str(), "%x = %x ? %x", &c.address, &cond_byte, &byte) == 3) { c.conditional = true; } - - else if (sscanf (text, "%x = %x", &c.address, &byte) == 2) + else if (sscanf(text.c_str(), "%x = %x", &c.address, &byte) == 2) { } - - else if (sscanf (text, "%x / %x / %x", &c.address, &cond_byte, &byte) == 3) + else if (sscanf(text.c_str(), "%x / %x / %x", &c.address, &cond_byte, &byte) == 3) { c.conditional = true; } - - else if (sscanf (text, "%x / %x", &c.address, &byte) == 2) + else if (sscanf(text.c_str(), "%x / %x", &c.address, &byte) == 2) { } - else { c.address = 0; @@ -404,313 +450,282 @@ SCheat S9xTextToCheat (char *text) return c; } -SCheatGroup S9xCreateCheatGroup (const char *name, const char *cheat) +std::vector split_string(const std::string &str, unsigned char delim) { - SCheatGroup g; - char *code_string = strdup (cheat); - char *code_ptr = code_string; - int len; + std::vector tokens; + size_t pos = 0; + size_t index; - g.name = strdup (name); - g.enabled = false; - - for (len = strcspn (code_ptr, "+"); len; len = strcspn (code_ptr, "+")) + while (pos < str.length()) { - char *code = code_ptr; - code_ptr += len + (code_ptr[len] == '\0' ? 0 : 1); - code[len] = '\0'; - code = trim (code); + index = str.find(delim, pos); + if (index == std::string::npos) + { + if (pos < str.length()) + { + tokens.push_back(trim(str.substr(pos))); + } - SCheat c = S9xTextToCheat (code); - if (c.address) - g.c.push_back (c); + break; + } + else if (index > pos) + { + tokens.push_back(trim(str.substr(pos, index - pos))); + } + + pos = index + 1; } - free(code_string); + return tokens; +} + +SCheatGroup S9xCreateCheatGroup(const std::string &name, const std::string &cheat) +{ + SCheatGroup g; + + g.name = name; + g.enabled = false; + + auto cheats = split_string(cheat, '+'); + for (const auto &c : cheats) + { + SCheat new_cheat = S9xTextToCheat(c); + if (new_cheat.address) + g.cheat.push_back(new_cheat); + } return g; } -int S9xAddCheatGroup (const char *name, const char *cheat) +int S9xAddCheatGroup(const std::string &name, const std::string &cheat) { - SCheatGroup g = S9xCreateCheatGroup (name, cheat); - if (g.c.size () == 0) + SCheatGroup g = S9xCreateCheatGroup(name, cheat); + if (g.cheat.size() == 0) return -1; - Cheat.g.push_back (g); + Cheat.group.push_back(g); - return Cheat.g.size () - 1; + return Cheat.group.size() - 1; } -int S9xModifyCheatGroup (uint32 num, const char *name, const char *cheat) +int S9xModifyCheatGroup(uint32 num, const std::string &name, const std::string &cheat) { - if (num >= Cheat.g.size()) + if (num >= Cheat.group.size()) return -1; - S9xDisableCheatGroup (num); - delete[] Cheat.g[num].name; + S9xDisableCheatGroup(num); - Cheat.g[num] = S9xCreateCheatGroup (name, cheat); + Cheat.group[num] = S9xCreateCheatGroup(name, cheat); return num; } -char *S9xCheatToText (SCheat *c) +std::string S9xCheatToText(const SCheat &c) { - int size = 10; /* 6 address, 1 =, 2 byte, 1 NUL */ - char *text; + if (c.conditional) + return fmt::format("{:06x}={:02x}?{:02x}", c.address, c.cond_byte, c.byte); - if (c->conditional) - size += 3; /* additional 2 byte, 1 ? */ + return fmt::format("{:06x}={:02x}", c.address, c.byte); +} - text = new char[size]; +std::string S9xCheatGroupToText(SCheatGroup &g) +{ + std::string text = ""; - if (c->conditional) - snprintf (text, size, "%06x=%02x?%02x", c->address, c->cond_byte, c->byte); - else - snprintf (text, size, "%06x=%02x", c->address, c->byte); + for (size_t i = 0; i < g.cheat.size(); i++) + { + text += S9xCheatToText(g.cheat[i]); + if (i != g.cheat.size() - 1) + text += "+"; + } return text; } -char *S9xCheatGroupToText (SCheatGroup *g) +std::string S9xCheatValidate(const std::string &code_string) { - std::string text = ""; - unsigned int i; + SCheatGroup g = S9xCreateCheatGroup("temp", code_string); - if (g->c.size () == 0) - return NULL; - - for (i = 0; i < g->c.size (); i++) + if (g.cheat.size() > 0) { - char *tmp = S9xCheatToText (&g->c[i]); - if (i != 0) - text += " + "; - text += tmp; - delete[] tmp; + return S9xCheatGroupToText(g); } - return strdup (text.c_str ()); + return ""; } -char *S9xCheatValidate (const char *code_string) +std::string S9xCheatGroupToText(uint32 num) { - SCheatGroup g = S9xCreateCheatGroup ("temp", code_string); + if (num >= Cheat.group.size()) + return ""; - delete[] g.name; - - if (g.c.size() > 0) - { - return S9xCheatGroupToText (&g); - } - - return NULL; + return S9xCheatGroupToText(Cheat.group[num]); } -char *S9xCheatGroupToText (uint32 num) +void S9xUpdateCheatsInMemory(void) { - if (num >= Cheat.g.size ()) - return NULL; - - return S9xCheatGroupToText (&Cheat.g[num]); -} - -void S9xUpdateCheatsInMemory (void) -{ - unsigned int i; - unsigned int j; - if (!Cheat.enabled) return; - for (i = 0; i < Cheat.g.size (); i++) - { - for (j = 0; j < Cheat.g[i].c.size (); j++) - { - S9xUpdateCheatInMemory (&Cheat.g[i].c[j]); - } - } + for (auto &group : Cheat.group) + for (auto &cheat : group.cheat) + S9xUpdateCheatInMemory(cheat); } -static int S9xCheatIsDuplicate (const char *name, const char *code) +static bool S9xCheatIsDuplicate(const std::string &name, const std::string &code) { - unsigned int i; - - for (i = 0; i < Cheat.g.size(); i++) + for (size_t i = 0; i < Cheat.group.size(); i++) { - if (!strcmp (name, Cheat.g[i].name)) + if (Cheat.group[i].name == name) { - char *code_string = S9xCheatGroupToText (i); - char *validated = S9xCheatValidate (code); + auto code_string = S9xCheatGroupToText(i); + auto validated_string = S9xCheatValidate(code); - if (validated && !strcmp (code_string, validated)) - { - free (code_string); - free (validated); - return TRUE; - } - - free (code_string); - free (validated); + if (validated_string == code_string) + return true; } } - return FALSE; + return false; } -static void S9xLoadCheatsFromBMLNode (bml_node *n) +static void S9xLoadCheatsFromBMLNode(bml_node &n) { - unsigned int i; - - for (i = 0; i < n->child.size (); i++) + for (auto &c : n.child) { - if (!strcasecmp (n->child[i].name.c_str(), "cheat")) - { - const char *desc = NULL; - const char *code = NULL; - bool8 enabled = false; + if (strcasecmp(c.name.c_str(), "cheat")) + continue; - bml_node *c = &n->child[i]; - bml_node *tmp = NULL; + auto subnode = c.find_subnode("code"); + if (!subnode) + continue; + std::string code = subnode->data; - tmp = c->find_subnode("name"); - if (!tmp) - desc = (char *) ""; - else - desc = tmp->data.c_str(); + std::string name; + subnode = c.find_subnode("name"); + if (subnode) + name = subnode->data; - tmp = c->find_subnode("code"); - if (tmp) - code = tmp->data.c_str(); + bool enable = false; + if (c.find_subnode("enable")) + enable = true; - if (c->find_subnode("enable")) - enabled = true; + if (S9xCheatIsDuplicate(name, code)) + continue; - if (code && !S9xCheatIsDuplicate (desc, code)) - { - int index = S9xAddCheatGroup (desc, code); - - if (enabled) - S9xEnableCheatGroup (index); - } - } + auto index = S9xAddCheatGroup(name, code); + if (enable) + S9xEnableCheatGroup(index); } return; } -static bool8 S9xLoadCheatFileClassic (const char *filename) +static bool8 S9xLoadCheatFileClassic(const std::string &filename) { FILE *fs; uint8 data[28]; - fs = fopen(filename, "rb"); + fs = fopen(filename.c_str(), "rb"); if (!fs) return (FALSE); - while (fread ((void *) data, 1, 28, fs) == 28) + while (fread(data, 1, 28, fs) == 28) { SCheat c; - char name[21]; - char cheat[10]; c.enabled = (data[0] & 4) == 0; c.byte = data[1]; - c.address = data[2] | (data[3] << 8) | (data[4] << 16); - memcpy (name, &data[8], 20); - name[20] = 0; + c.address = data[2] | (data[3] << 8) | (data[4] << 16); - snprintf (cheat, 10, "%x=%x", c.address, c.byte); - S9xAddCheatGroup (name, cheat); + std::string name((const char *)&data[8], 20); + auto cheat = fmt::format("{:x}={:x}", c.address, c.byte); + + S9xAddCheatGroup(name, cheat); if (c.enabled) - S9xEnableCheatGroup (Cheat.g.size () - 1); + S9xEnableCheatGroup(Cheat.group.size() - 1); } fclose(fs); - return (TRUE); + return TRUE; } -bool8 S9xLoadCheatFile (const char *filename) +bool8 S9xLoadCheatFile(const std::string &filename) { bml_node bml; if (!bml.parse_file(filename)) { - return S9xLoadCheatFileClassic (filename); + return S9xLoadCheatFileClassic(filename); } bml_node *n = bml.find_subnode("cheat"); if (n) { - S9xLoadCheatsFromBMLNode (&bml); + S9xLoadCheatsFromBMLNode(bml); } if (!n) { - return S9xLoadCheatFileClassic (filename); + return S9xLoadCheatFileClassic(filename); } return (TRUE); } -bool8 S9xSaveCheatFile (const char *filename) +bool8 S9xSaveCheatFile(const std::string &filename) { unsigned int i; FILE *file = NULL; - if (Cheat.g.size () == 0) + if (Cheat.group.size() == 0) { - remove (filename); + remove(filename.c_str()); return TRUE; } - file = fopen (filename, "w"); + file = fopen(filename.c_str(), "w"); if (!file) return FALSE; - for (i = 0; i < Cheat.g.size (); i++) + for (i = 0; i < Cheat.group.size(); i++) { - char *txt = S9xCheatGroupToText (i); - - fprintf (file, - "cheat\n" - " name: %s\n" - " code: %s\n" - "%s\n", - Cheat.g[i].name ? Cheat.g[i].name : "", - txt, - Cheat.g[i].enabled ? " enable\n" : "" - ); - - delete[] txt; + fmt::print(file, + "cheat\n" + " name: {}\n" + " code: {}\n" + "{}\n", + Cheat.group[i].name, + S9xCheatGroupToText(i), + Cheat.group[i].enabled ? " enable\n" : ""); } - fclose (file); + fclose(file); return TRUE; } -void S9xCheatsDisable (void) +void S9xCheatsDisable(void) { unsigned int i; if (!Cheat.enabled) return; - for (i = 0; i < Cheat.g.size (); i++) + for (i = 0; i < Cheat.group.size(); i++) { - if (Cheat.g[i].enabled) + if (Cheat.group[i].enabled) { - S9xDisableCheatGroup (i); - Cheat.g[i].enabled = TRUE; + S9xDisableCheatGroup(i); + Cheat.group[i].enabled = TRUE; } } Cheat.enabled = FALSE; } -void S9xCheatsEnable (void) +void S9xCheatsEnable(void) { unsigned int i; @@ -719,17 +734,17 @@ void S9xCheatsEnable (void) Cheat.enabled = TRUE; - for (i = 0; i < Cheat.g.size (); i++) + for (i = 0; i < Cheat.group.size(); i++) { - if (Cheat.g[i].enabled) + if (Cheat.group[i].enabled) { - Cheat.g[i].enabled = FALSE; - S9xEnableCheatGroup (i); + Cheat.group[i].enabled = FALSE; + S9xEnableCheatGroup(i); } } } -int S9xImportCheatsFromDatabase (const char *filename) +int S9xImportCheatsFromDatabase(const std::string &filename) { char sha256_txt[65]; char hextable[] = "0123456789abcdef"; @@ -746,19 +761,16 @@ int S9xImportCheatsFromDatabase (const char *filename) } sha256_txt[64] = '\0'; - for (i = 0; i < bml.child.size (); i++) + for (auto &c : bml.child) { - if (!strcasecmp (bml.child[i].name.c_str(), "cartridge")) + if (!strcasecmp(c.name.c_str(), "cartridge")) { - bml_node *n; + auto n = c.find_subnode("sha256"); - if ((n = bml.child[i].find_subnode ("sha256"))) + if (n && !strcasecmp(n->data.c_str(), sha256_txt)) { - if (!strcasecmp (n->data.c_str(), sha256_txt)) - { - S9xLoadCheatsFromBMLNode (&bml.child[i]); - return 0; - } + S9xLoadCheatsFromBMLNode(c); + return 0; } } } diff --git a/cpu.cpp b/cpu.cpp index 4187496f..bcc4adf9 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -99,8 +99,8 @@ void S9xReset (void) { S9xResetSaveTimer(FALSE); - memset(Memory.RAM, 0x55, 0x20000); - memset(Memory.VRAM, 0x00, 0x10000); + memset(Memory.RAM, 0x55, sizeof(Memory.RAM)); + memset(Memory.VRAM, 0x00, sizeof(Memory.VRAM)); memset(Memory.FillRAM, 0, 0x8000); S9xResetBSX(); diff --git a/gtk/src/gtk_cheat.cpp b/gtk/src/gtk_cheat.cpp index edc37a5f..0aa8bf72 100644 --- a/gtk/src/gtk_cheat.cpp +++ b/gtk/src/gtk_cheat.cpp @@ -132,20 +132,20 @@ void Snes9xCheats::show() static void cheat_move(int src, int dst) { - Cheat.g.insert(Cheat.g.begin() + dst, Cheat.g[src]); + Cheat.group.insert(Cheat.group.begin() + dst, Cheat.group[src]); if (dst < src) src++; - Cheat.g.erase(Cheat.g.begin() + src); + Cheat.group.erase(Cheat.group.begin() + src); } static void cheat_gather_enabled() { unsigned int enabled = 0; - for (unsigned int i = 0; i < Cheat.g.size(); i++) + for (unsigned int i = 0; i < Cheat.group.size(); i++) { - if (Cheat.g[i].enabled && i >= enabled) + if (Cheat.group[i].enabled && i >= enabled) { cheat_move(i, enabled); enabled++; @@ -199,22 +199,21 @@ void Snes9xCheats::refresh_tree_view() auto list_size = store->children().size(); - if (Cheat.g.size() == 0) + if (Cheat.group.size() == 0) return; - for (unsigned int i = 0; i < Cheat.g.size() - list_size; i++) + for (unsigned int i = 0; i < Cheat.group.size() - list_size; i++) store->append(); auto iter = store->children().begin(); - for (unsigned int i = 0; i < Cheat.g.size (); i++) + for (unsigned int i = 0; i < Cheat.group.size (); i++) { - char *str = S9xCheatGroupToText(i); - Glib::ustring description = Cheat.g[i].name[0] == '\0' ? "" :Cheat.g[i].name; - iter->set_value(COLUMN_ENABLED, Cheat.g[i].enabled); + auto str = S9xCheatGroupToText(i); + Glib::ustring description = Cheat.group[i].name[0] == '\0' ? "" :Cheat.group[i].name; + iter->set_value(COLUMN_ENABLED, Cheat.group[i].enabled); iter->set_value(COLUMN_DESCRIPTION, description); iter->set_value(COLUMN_CHEAT, Glib::ustring(str)); iter++; - delete[] str; } enable_dnd(true); @@ -228,15 +227,14 @@ void Snes9xCheats::add_code() if (description.empty()) description = _("No description"); - if (S9xAddCheatGroup(description.c_str(), code.c_str()) < 0) + if (S9xAddCheatGroup(description, code) < 0) { display_errorbox(_("Couldn't find any cheat codes in input.")); return; } - auto parsed_code = S9xCheatGroupToText(Cheat.g.size() - 1); + auto parsed_code = S9xCheatGroupToText(Cheat.group.size() - 1); set_entry_text("code_entry", parsed_code); - delete[] parsed_code; get_object("code_entry")->grab_focus(); @@ -247,7 +245,7 @@ void Snes9xCheats::add_code() auto selection = get_object("cheat_treeview")->get_selection(); Gtk::TreePath path; - path.push_back(Cheat.g.size() - 1); + path.push_back(Cheat.group.size() - 1); selection->select(path); auto adj = get_object("cheat_scrolledwindow")->get_vadjustment(); @@ -288,53 +286,27 @@ void Snes9xCheats::search_database() int result; int reason = 0; - filename = S9xGetDirectory(CHEAT_DIR); - filename += "/cheats.bml"; - if (!(result = S9xImportCheatsFromDatabase(filename.c_str()))) + for (const auto &dir : { S9xGetDirectory(CHEAT_DIR), + get_config_dir(), + std::string(DATADIR) }) { - refresh_tree_view(); - return; + filename = dir + "/cheats.bml"; + result = S9xImportCheatsFromDatabase(filename); + if (result == 0) + { + refresh_tree_view(); + return; + } + + if (result < reason) + reason = result; } - if (result < reason) - reason = result; - - filename = get_config_dir() + "/cheats.bml"; - if (!(result = S9xImportCheatsFromDatabase(filename.c_str()))) - { - refresh_tree_view(); - return; - } - - if (result < reason) - reason = result; - - filename = std::string(DATADIR) + "/cheats.bml"; - if (!(result = S9xImportCheatsFromDatabase(filename.c_str()))) - { - refresh_tree_view(); - return; - } - - if (result < reason) - reason = result; - - filename = S9xGetDirectory(ROM_DIR); - filename += "/cheats.bml"; - if (!(result = S9xImportCheatsFromDatabase(filename.c_str()))) - { - refresh_tree_view(); - return; - } - - if (result < reason) - reason = result; - auto dialog = Gtk::MessageDialog(*window.get(), reason == -1 ? _("Couldn't Find Cheats Database") : _("No Matching Game Found"), true); dialog.set_secondary_text(reason == -1 ? _("The database file cheats.bml was not found. It is normally installed with " "Snes9x, but you may also place a custom copy in your configuration or cheats directory.") : _("No matching game was found in the databases. If you are using a non-official " - "translation or modified copy, you may be able to find and manually enter the codes.")); + "translation or modified copy, you may be able to find and manually enter the codes."), true); dialog.run(); dialog.hide(); } @@ -348,12 +320,10 @@ void Snes9xCheats::sort_cheats() void Snes9xCheats::row_activated(const Gtk::TreeModel::Path &path, Gtk::TreeViewColumn *column) { int index = get_index_from_path(path); - char *cheat_text; - cheat_text = S9xCheatGroupToText(index); + auto cheat_text = S9xCheatGroupToText(index); set_entry_text("code_entry", cheat_text); - delete[] cheat_text; - set_entry_text("description_entry", Cheat.g[index].name); + set_entry_text("description_entry", Cheat.group[index].name); } void Snes9xCheats::toggle_code(const Glib::ustring &path) @@ -383,16 +353,15 @@ void Snes9xCheats::update_code() if (description.empty()) description = _("No description"); - auto parsed_code = S9xCheatValidate(code.c_str()); - if (!parsed_code) + auto parsed_code = S9xCheatValidate(code); + if (parsed_code.empty()) { display_errorbox(_("Couldn't find any cheat codes in input.")); return; } - S9xModifyCheatGroup(index, description.c_str(), parsed_code); + S9xModifyCheatGroup(index, description, parsed_code); set_entry_text("code_entry", parsed_code); - delete[] parsed_code; get_object("code_entry")->grab_focus(); @@ -401,9 +370,9 @@ void Snes9xCheats::update_code() void Snes9xCheats::disable_all() { - for (unsigned int i = 0; i < Cheat.g.size(); i++) + for (unsigned int i = 0; i < Cheat.group.size(); i++) { - if (Cheat.g[i].enabled) + if (Cheat.group[i].enabled) S9xDisableCheatGroup(i); } diff --git a/gtk/src/gtk_file.cpp b/gtk/src/gtk_file.cpp index eeb805fb..280a28aa 100644 --- a/gtk/src/gtk_file.cpp +++ b/gtk/src/gtk_file.cpp @@ -98,7 +98,7 @@ std::string S9xGetDirectory(enum s9x_getdirtype dirtype) } /* Anything else, use ROM filename path */ - if (dirname == "" && gui_config && gui_config->rom_loaded) + if (dirname == "" && !Memory.ROMFilename.empty()) { fs::path path(Memory.ROMFilename); diff --git a/msu1.cpp b/msu1.cpp index 71ce88a5..8af27371 100644 --- a/msu1.cpp +++ b/msu1.cpp @@ -85,7 +85,6 @@ STREAM S9xMSU1OpenFile(const char *msu_ext, bool skip_unpacked) int port = unzFindExtension(unzFile, msu_ext, true, true, true); if (port == UNZ_OK) { - printf(" in %s.\n", zip_filename.c_str()); file = new unzStream(unzFile); } else diff --git a/snes9x.cpp b/snes9x.cpp index e2886405..e50a5877 100644 --- a/snes9x.cpp +++ b/snes9x.cpp @@ -463,7 +463,7 @@ void S9xParseArgsForCheats (char **argv, int argc) } else { - S9xEnableCheatGroup (Cheat.g.size() - 1); + S9xEnableCheatGroup (Cheat.group.size() - 1); } } else @@ -647,7 +647,7 @@ char * S9xParseArgs (char **argv, int argc) } else { - S9xEnableCheatGroup (Cheat.g.size() - 1); + S9xEnableCheatGroup (Cheat.group.size() - 1); } } else