cheats: heap-allocate the editor code scratch on first use

The cheat manager state carried a sixteen-kilobyte code-editing
scratch buffer resident in every binary, used only when the cheat
editor runs. It is now a pointer allocated by an ensure helper with
two choke points: the editor entry in copy-idx-to-working, and the
cheat settings builder just before the rows that bind the scratch's
address - necessary since under the lazy settings cache that
builder can run at any moment a lookup first needs it. The scratch
is deliberately never freed once allocated: menu rows hold its
address across content sessions, exactly as they held the old
static array; freeing with the manager would dangle them. The
sizeof at the two binding sites becomes the scratch-size constant
it always meant. Both dumps byte-identical - the settings dump
prints the cheat rows through the ensured buffer.
This commit is contained in:
libretroadmin authored and libretroadmin committed 2026-07-07 16:56:42 +02:00
1 parent e0efc61ab7
commit 90f1d285bd
3 files changed
+26 -4

No files matched your search

+13 -1
View File
@@ -260,12 +260,23 @@ bool cheat_manager_save(
return ret;
}
bool cheat_manager_working_code_ensure(void)
{
cheat_manager_t *cheat_st = &cheat_manager_state;
if (!cheat_st->working_code)
cheat_st->working_code = (char*)calloc(1, CHEAT_CODE_SCRATCH_SIZE);
return cheat_st->working_code != NULL;
}
bool cheat_manager_copy_idx_to_working(unsigned idx)
{
cheat_manager_t *cheat_st = &cheat_manager_state;
if (!cheat_st->cheats || (cheat_st->size < idx + 1))
return false;
if (!cheat_manager_working_code_ensure())
return false;
memcpy(&cheat_st->working_cheat,
&cheat_st->cheats[idx], sizeof(struct item_cheat));
@@ -343,7 +354,8 @@ bool cheat_manager_copy_working_to_idx(unsigned idx)
if (cheat_st->cheats[idx].code)
free(cheat_st->cheats[idx].code);
cheat_st->cheats[idx].code = strdup(cheat_st->working_code);
cheat_st->cheats[idx].code = strdup(
cheat_st->working_code ? cheat_st->working_code : "");
return true;
}
+8 -1
View File
@@ -181,7 +181,12 @@ struct cheat_manager
unsigned num_matches;
unsigned browse_address;
char working_desc[CHEAT_DESC_SCRATCH_SIZE];
char working_code[CHEAT_CODE_SCRATCH_SIZE];
/* Sixteen kilobytes of cheat-editor scratch; allocated on first
* use and deliberately never freed: menu rows bind its address
* and outlive any one content session, exactly as they did the
* old static array. cheat_manager_working_code_ensure() must run
* before any use. */
char *working_code;
bool big_endian;
bool memory_initialized;
bool memory_search_initialized;
@@ -238,6 +243,8 @@ void cheat_manager_alloc_if_empty(void);
bool cheat_manager_copy_idx_to_working(unsigned idx);
bool cheat_manager_working_code_ensure(void);
bool cheat_manager_copy_working_to_idx(unsigned idx);
void cheat_manager_load_game_specific_cheats(const char *path_cheat_database);
+5 -2
View File
@@ -13728,10 +13728,13 @@ static void settings_build_cheat_details(
SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_ALLOW_INPUT);
SETTINGS_ACTION_SET(start, &(*list)[list_info->index - 1], setting_generic_action_start_default)
/* The editor scratch is heap-allocated on demand; the rows
* below bind its address, so it must exist before they build. */
cheat_manager_working_code_ensure();
CONFIG_STRING(
list, list_info,
cheat_manager_state.working_code,
sizeof(cheat_manager_state.working_code),
CHEAT_CODE_SCRATCH_SIZE,
MENU_ENUM_LABEL_CHEAT_CODE,
MENU_ENUM_LABEL_VALUE_CHEAT_CODE,
"",
@@ -13753,7 +13756,7 @@ static void settings_build_cheat_details(
CONFIG_STRING(
list, list_info,
cheat_manager_state.working_code,
sizeof(cheat_manager_state.working_code),
CHEAT_CODE_SCRATCH_SIZE,
MENU_ENUM_LABEL_CHEAT_CODE,
MENU_ENUM_LABEL_VALUE_CHEAT_CODE,
"",