Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions cheat_cmd.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
#include <inttypes.h>

#include "cheats.h"
#include "cheat_cmd.h"

static const char *skip_space(const char *s)
{
while (*s && isspace((unsigned char)*s)) s++;
return s;
}

static bool parse_token(const char **cmd, char *token, size_t token_size)
{
const char *s = skip_space(*cmd);
size_t len = 0;

while (s[len] && !isspace((unsigned char)s[len])) len++;
if (!len || len >= token_size) return false;

memcpy(token, s, len);
token[len] = 0;
*cmd = s + len;
return true;
}

static const char *cheat_cmd_status(int status)
{
switch (status)
{
case CHEATS_CMD_OK: return "ok";
case CHEATS_CMD_NO_CHEATS: return "no cheats loaded";
case CHEATS_CMD_NOT_FOUND: return "not found";
case CHEATS_CMD_LOAD_FAILED: return "load failed";
case CHEATS_CMD_NO_ROOM: return "no room";
default: return "error";
}
}

void cheat_cmd(const char *cmd)
{
char action[16];

if (!parse_token(&cmd, action, sizeof(action)))
{
printf("MiSTer_cmd cheat: missing command\n");
return;
}

if (!strcmp(action, "clear"))
{
int status = cheats_clear_enabled();
printf("MiSTer_cmd cheat clear: %s\n", cheat_cmd_status(status));
return;
}

const char *name = skip_space(cmd);
if (!*name)
{
printf("MiSTer_cmd cheat %s: missing name\n", action);
return;
}

int status;
if (!strcmp(action, "on")) status = cheats_set_enabled_by_name(name, true);
else if (!strcmp(action, "off")) status = cheats_set_enabled_by_name(name, false);
else if (!strcmp(action, "toggle")) status = cheats_toggle_by_name(name);
else
{
printf("MiSTer_cmd cheat: unknown command '%s'\n", action);
return;
}

printf("MiSTer_cmd cheat %s '%s': %s\n", action, name, cheat_cmd_status(status));
}
6 changes: 6 additions & 0 deletions cheat_cmd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef CHEAT_CMD_H
#define CHEAT_CMD_H

void cheat_cmd(const char *cmd);

#endif
119 changes: 119 additions & 0 deletions cheats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ void cheats_print()
static void cheats_send()
{
static uint8_t buff[CHEAT_SIZE];
memset(buff, 0, sizeof(buff));
int pos = 0;

for (int i = 0; i < cheats_available(); i++)
Expand Down Expand Up @@ -459,6 +460,124 @@ void cheats_toggle()
}
}

static int cheats_find_by_name(const char *name)
{
if (!name || !*name) return -1;

for (int i = 0; i < cheats_available(); i++)
{
if (!strcmp(cheats[i].name, name)) return i;
}

return -1;
}

static int cheats_external_load_entry(int idx)
{
if (idx < 0 || idx >= cheats_available()) return CHEATS_CMD_NOT_FOUND;
if (cheats[idx].cheatData) return CHEATS_CMD_OK;
if (!cheat_zip[0]) return CHEATS_CMD_LOAD_FAILED;

static char filename[1024];
fileTYPE f = {};
snprintf(filename, sizeof(filename), "%s/%s", cheat_zip, cheats[idx].name);
if (!FileOpen(&f, filename))
{
printf("Cannot open cheat file %s.\n", filename);
return CHEATS_CMD_LOAD_FAILED;
}

int res = CHEATS_CMD_LOAD_FAILED;
int len = f.size;
if (!len || (len % cheat_unit_size))
{
printf("Cheat file %s has incorrect length %d -> skipping.\n", filename, len);
}
else if (((len / cheat_unit_size) + cheats_loaded()) <= cheat_max_active)
{
cheats[idx].cheatData = new char[len];
if (cheats[idx].cheatData)
{
if (FileReadAdv(&f, cheats[idx].cheatData, len) == len)
{
cheats[idx].cheatSize = len;
res = CHEATS_CMD_OK;
}
else
{
printf("Cannot read cheat file %s.\n", filename);
delete[] cheats[idx].cheatData;
cheats[idx].cheatData = NULL;
cheats[idx].cheatSize = 0;
}
}
else
{
printf("Could not allocate required memory (%d) for cheat file %s.\n", len, filename);
}
}
else
{
printf("No more room in current selection for cheat file %s.\n", filename);
res = CHEATS_CMD_NO_ROOM;
}

FileClose(&f);
return res;
}

static int cheats_external_set_enabled(int idx, bool enabled)
{
if (!cheats_available()) return CHEATS_CMD_NO_CHEATS;
if (idx < 0 || idx >= cheats_available()) return CHEATS_CMD_NOT_FOUND;
if (cheats[idx].enabled == enabled) return CHEATS_CMD_OK;

if (enabled)
{
int res = cheats_external_load_entry(idx);
if (res != CHEATS_CMD_OK) return res;
if (((cheats[idx].cheatSize / cheat_unit_size) + cheats_loaded()) > cheat_max_active) return CHEATS_CMD_NO_ROOM;
}

cheats[idx].enabled = enabled;
cheats_send();
return CHEATS_CMD_OK;
}

int cheats_set_enabled_by_name(const char *name, bool enabled)
{
if (!cheats_available()) return CHEATS_CMD_NO_CHEATS;
return cheats_external_set_enabled(cheats_find_by_name(name), enabled);
}

int cheats_toggle_by_name(const char *name)
{
if (!cheats_available()) return CHEATS_CMD_NO_CHEATS;

int idx = cheats_find_by_name(name);
if (idx < 0) return CHEATS_CMD_NOT_FOUND;

return cheats_external_set_enabled(idx, !cheats[idx].enabled);
}

int cheats_clear_enabled()
{
if (!cheats_available()) return CHEATS_CMD_NO_CHEATS;

bool changedCheats = false;
for (int i = 0; i < cheats_available(); i++)
{
if (cheats[i].enabled)
{
cheats[i].enabled = false;
changedCheats = true;
}
}

if (changedCheats) cheats_send();
return CHEATS_CMD_OK;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift

Move this new backend command-control block into a new file and keep this upstream file to a hook-level change.

Lines 463-579 introduce substantial new functionality directly in cheats.cpp. Please extract this logic into a new .cpp/.h pair and keep upstream cheats.cpp edits minimal (bridge/hook only).

As per coding guidelines, “Put new functionality in new .cpp/.h files wherever possible rather than modifying upstream source files…” and “When touching upstream source files, make only surgical edits: add a single #include, a single function call, or a single hook point.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cheats.cpp` around lines 463 - 579, Extract the entire new backend
command-control logic (functions cheats_find_by_name,
cheats_external_load_entry, cheats_external_set_enabled,
cheats_set_enabled_by_name, cheats_toggle_by_name, cheats_clear_enabled and any
static helpers/locals they use) into a new module (e.g., cheats_backend.cpp +
cheats_backend.h), keep their signatures public in the header, and move any
static file-scope state they require into that new module; then reduce
cheats.cpp to a surgical hook: add a single `#include` of the new header and
replace the moved implementations with minimal forwarding calls (or a single
call/site that delegates to the new API) so cheats.cpp only contains the
hook/include while the full logic lives in the new files. Ensure you preserve
symbol names and behavior, and update compilation units to compile the new
files.


int cheats_loaded()
{
return loaded;
Expand Down
13 changes: 13 additions & 0 deletions cheats.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,19 @@ void cheats_print();
void cheats_toggle();
int cheats_loaded();

enum
{
CHEATS_CMD_OK = 0,
CHEATS_CMD_NO_CHEATS = -1,
CHEATS_CMD_NOT_FOUND = -2,
CHEATS_CMD_LOAD_FAILED = -3,
CHEATS_CMD_NO_ROOM = -4
};

int cheats_set_enabled_by_name(const char *name, bool enabled);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
int cheats_toggle_by_name(const char *name);
int cheats_clear_enabled();

void cheats_init_arcade(int unit_size, int max_active);
void cheats_add_arcade(const char *name, const char *cheatData, int cheatSize);
void cheats_finalize_arcade();
Expand Down
2 changes: 2 additions & 0 deletions input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "frame_timer.h"
#include "scaler.h"
#include "file_io.h"
#include "cheat_cmd.h"
#include "support/zaparoo/alt_launcher.h"

#define NUMDEV 30
Expand Down Expand Up @@ -6238,6 +6239,7 @@ int input_test(int getchar)
printf("MiSTer_cmd: %s\n", cmd);
if (!strncmp(cmd, "fb_cmd", 6)) video_cmd(cmd);
else if (!strncmp(cmd, "video_mode ", 11)) video_mode_cmd(cmd + 11);
else if (!strncmp(cmd, "cheat ", 6)) cheat_cmd(cmd + 6);
else if (!strncmp(cmd, "load_core ", 10))
{
if(isXmlName(cmd)) xml_load(cmd + 10);
Expand Down