From: Sandro Ronco [mailto:sandro.ronco@alice.it]

Sent: Wednesday, August 26, 2009 5:57 AM
To: submit@mamedev.org
Subject: MAME cheat search engine

This is a diff of my cheat search engine with help of Pugsy.  
This is only a first part, not has the same functions of the old search engine, but is better than nothing

I have update the search engine to support search of byte, word, dword
and qword signed and unsigned.
This commit is contained in:
Aaron Giles 2009-09-03 08:54:11 +00:00
parent 53907cc182
commit 6b159dfd11
4 changed files with 694 additions and 26 deletions

View File

@ -41,6 +41,26 @@ struct _global_entry
UINT32 size;
};
typedef struct _cheat_map cheat_map;
struct _cheat_map
{
UINT64 offset;
UINT64 first_value;
UINT64 previous_value;
UINT8 state:1;
UINT8 undo:7;
};
typedef struct _cheat_system cheat_system;
struct _cheat_system
{
char cpu;
UINT64 length;
UINT8 width;
cheat_map * cheatmap;
UINT8 undo;
UINT8 signed_cheat;
};
/***************************************************************************
@ -48,6 +68,7 @@ struct _global_entry
***************************************************************************/
static global_entry global_array[MAX_GLOBALS];
static cheat_system cheat;
@ -96,6 +117,10 @@ static void execute_wplist(running_machine *machine, int ref, int params, const
static void execute_hotspot(running_machine *machine, int ref, int params, const char **param);
static void execute_save(running_machine *machine, int ref, int params, const char **param);
static void execute_dump(running_machine *machine, int ref, int params, const char **param);
static void execute_cheatinit(running_machine *machine, int ref, int params, const char **param);
static void execute_cheatnext(running_machine *machine, int ref, int params, const char **param);
static void execute_cheatlist(running_machine *machine, int ref, int params, const char **param);
static void execute_cheatundo(running_machine *machine, int ref, int params, const char **param);
static void execute_dasm(running_machine *machine, int ref, int params, const char **param);
static void execute_find(running_machine *machine, int ref, int params, const char **param);
static void execute_trace(running_machine *machine, int ref, int params, const char **param);
@ -112,6 +137,54 @@ static void execute_hardreset(running_machine *machine, int ref, int params, con
/***************************************************************************
INLINE FUNCTIONS
***************************************************************************/
/*-------------------------------------------------
cheat_address_is_valid - return TRUE if the
given address is valid for cheating
-------------------------------------------------*/
INLINE int cheat_address_is_valid(const address_space *space, offs_t address)
{
return debug_cpu_translate(space, TRANSLATE_READ, &address) && (memory_get_write_ptr(space, address) != NULL);
}
/*-------------------------------------------------
cheat_sign_extend - sign-extend a value to
the current cheat width, if signed
-------------------------------------------------*/
INLINE UINT64 cheat_sign_extend(const cheat_system *cheatsys, UINT64 value)
{
if (cheatsys->signed_cheat)
{
switch (cheatsys->width)
{
case 1: value = (INT8)value; break;
case 2: value = (INT16)value; break;
case 4: value = (INT32)value; break;
}
}
return value;
}
/*-------------------------------------------------
cheat_read_extended - read a value from memory
in the given address space, sign-extending
if necessary
-------------------------------------------------*/
INLINE UINT64 cheat_read_extended(const cheat_system *cheatsys, const address_space *space, offs_t address)
{
return cheat_sign_extend(cheatsys, debug_read_memory(space, address, cheatsys->width, TRUE));
}
/***************************************************************************
INITIALIZATION
***************************************************************************/
@ -215,6 +288,23 @@ void debug_command_init(running_machine *machine)
debug_console_register_command(machine, "dumpd", CMDFLAG_NONE, ADDRESS_SPACE_DATA, 3, 6, execute_dump);
debug_console_register_command(machine, "dumpi", CMDFLAG_NONE, ADDRESS_SPACE_IO, 3, 6, execute_dump);
debug_console_register_command(machine, "cheatinit", CMDFLAG_NONE, 0, 0, 4, execute_cheatinit);
debug_console_register_command(machine, "ci", CMDFLAG_NONE, 0, 0, 4, execute_cheatinit);
debug_console_register_command(machine, "cheatrange",CMDFLAG_NONE, 1, 2, 2, execute_cheatinit);
debug_console_register_command(machine, "cr", CMDFLAG_NONE, 1, 2, 2, execute_cheatinit);
debug_console_register_command(machine, "cheatnext", CMDFLAG_NONE, 0, 1, 2, execute_cheatnext);
debug_console_register_command(machine, "cn", CMDFLAG_NONE, 0, 1, 2, execute_cheatnext);
debug_console_register_command(machine, "cheatnextf",CMDFLAG_NONE, 1, 1, 2, execute_cheatnext);
debug_console_register_command(machine, "cnf", CMDFLAG_NONE, 1, 1, 2, execute_cheatnext);
debug_console_register_command(machine, "cheatlist", CMDFLAG_NONE, 0, 0, 1, execute_cheatlist);
debug_console_register_command(machine, "cl", CMDFLAG_NONE, 0, 0, 1, execute_cheatlist);
debug_console_register_command(machine, "cheatundo", CMDFLAG_NONE, 0, 0, 0, execute_cheatundo);
debug_console_register_command(machine, "cu", CMDFLAG_NONE, 0, 0, 0, execute_cheatundo);
debug_console_register_command(machine, "f", CMDFLAG_KEEP_QUOTES, ADDRESS_SPACE_PROGRAM, 3, MAX_COMMAND_PARAMS, execute_find);
debug_console_register_command(machine, "find", CMDFLAG_KEEP_QUOTES, ADDRESS_SPACE_PROGRAM, 3, MAX_COMMAND_PARAMS, execute_find);
debug_console_register_command(machine, "fd", CMDFLAG_KEEP_QUOTES, ADDRESS_SPACE_DATA, 3, MAX_COMMAND_PARAMS, execute_find);
@ -273,6 +363,9 @@ static void debug_command_exit(running_machine *machine)
/* turn off all traces */
for (cpu = machine->cpu[0]; cpu != NULL; cpu = cpu->typenext)
debug_cpu_trace(cpu, NULL, 0, NULL);
if (cheat.length)
free(cheat.cheatmap);
}
@ -1655,6 +1748,403 @@ static void execute_dump(running_machine *machine, int ref, int params, const ch
}
/*-------------------------------------------------
execute_cheatinit - initialize the cheat system
-------------------------------------------------*/
static void execute_cheatinit(running_machine *machine, int ref, int params, const char *param[])
{
UINT64 offset, endoffset, length = 0, real_length = 0;
const address_space *space;
UINT32 active_cheat = 0;
UINT64 curaddr;
/* validate parameters */
if (!debug_command_parameter_cpu_space(machine, (params > 3) ? param[3] : NULL, ADDRESS_SPACE_PROGRAM, &space))
return;
if (ref == 0)
{
if (params > 0)
{
if (!strcmp(param[0], "sb"))
{
cheat.width = 1;
cheat.signed_cheat = TRUE;
}
else if (!strcmp(param[0], "sw"))
{
cheat.width = 2;
cheat.signed_cheat = TRUE;
}
else if (!strcmp(param[0], "sd"))
{
cheat.width = 4;
cheat.signed_cheat = TRUE;
}
else if (!strcmp(param[0], "sq"))
{
cheat.width = 8;
cheat.signed_cheat = TRUE;
}
else if (!strcmp(param[0], "ub"))
{
cheat.width = 1;
cheat.signed_cheat = FALSE;
}
else if (!strcmp(param[0], "uw"))
{
cheat.width = 2;
cheat.signed_cheat = FALSE;
}
else if (!strcmp(param[0], "ud"))
{
cheat.width = 4;
cheat.signed_cheat = FALSE;
}
else if (!strcmp(param[0], "uq"))
{
cheat.width = 8;
cheat.signed_cheat = FALSE;
}
else
{
debug_console_printf(machine, "Invalid type: expected ub, uw, ud, uq, sb, sw, sd or sq\n");
return;
}
}
else
{
cheat.width = 1;
cheat.signed_cheat = FALSE;
}
}
if (params > 1)
{
if (!debug_command_parameter_number(machine, param[(ref == 0) ? 1 : 0], &offset))
return;
if (!debug_command_parameter_number(machine, param[(ref == 0) ? 2 : 1], &length))
return;
}
else
{
/* initialize entire memory */
offset = 0;
length = space->bytemask + 1;
}
endoffset = memory_address_to_byte(space, offset + length - 1) & space->bytemask;
offset = memory_address_to_byte(space, offset) & space->bytemask;
/* counts the writable bytes in the area */
for (curaddr = offset; curaddr <= endoffset; curaddr += cheat.width)
if (cheat_address_is_valid(space, curaddr))
real_length++;
if (real_length == 0)
{
debug_console_printf(machine, "No writable bytes found in this area\n");
return;
}
if (ref == 0)
{
/* initialize new cheat system */
if (cheat.cheatmap != NULL)
free(cheat.cheatmap);
cheat.cheatmap = malloc(real_length * sizeof(cheat_map));
if (cheat.cheatmap == NULL)
{
debug_console_printf(machine, "Unable of allocate the necessary memory\n");
return;
}
cheat.length = real_length;
cheat.undo = 0;
cheat.cpu = (params > 3) ? *param[3] : '0';
}
else
{
/* add range to cheat system */
cheat_map * cheatmap_bak = cheat.cheatmap;
if (cheat.cpu == 0)
{
debug_console_printf(machine, "Use cheatinit before cheatrange\n");
return;
}
if (!debug_command_parameter_cpu_space(machine, &cheat.cpu, ADDRESS_SPACE_PROGRAM, &space))
return;
cheat.cheatmap = realloc(cheat.cheatmap, (cheat.length + real_length) * sizeof(cheat_map));
if (cheat.cheatmap == NULL)
{
cheat.cheatmap = cheatmap_bak;
debug_console_printf(machine, "Unable of allocate the necessary memory\n");
return;
}
active_cheat = cheat.length;
cheat.length += real_length;
}
/* initialize cheatmap in the selected space */
for (curaddr = offset; curaddr <= endoffset; curaddr += cheat.width)
if (cheat_address_is_valid(space, curaddr))
{
cheat.cheatmap[active_cheat].previous_value = cheat_read_extended(&cheat, space, curaddr);
cheat.cheatmap[active_cheat].first_value = cheat.cheatmap[active_cheat].previous_value;
cheat.cheatmap[active_cheat].offset = curaddr;
cheat.cheatmap[active_cheat].state = 1;
cheat.cheatmap[active_cheat].undo = 0;
active_cheat++;
}
debug_console_printf(machine, "%u cheat initialized\n", active_cheat);
}
/*-------------------------------------------------
execute_cheatnext - execute the search
-------------------------------------------------*/
static void execute_cheatnext(running_machine *machine, int ref, int params, const char *param[])
{
const address_space *space;
UINT64 cheatindex;
UINT32 active_cheat = 0;
UINT8 condition;
UINT64 comp_value;
enum
{
CHEAT_ALL = 0,
CHEAT_EQUAL,
CHEAT_NOTEQUAL,
CHEAT_EQUALTO,
CHEAT_NOTEQUALTO,
CHEAT_DECREASE,
CHEAT_INCREASE,
CHEAT_DECREASEOF,
CHEAT_INCREASEOF,
CHEAT_SMALLEROF,
CHEAT_GREATEROF
};
if (cheat.cpu == 0)
{
debug_console_printf(machine, "Use cheatinit before cheatnext\n");
return;
}
if (!debug_command_parameter_cpu_space(machine, &cheat.cpu, ADDRESS_SPACE_PROGRAM, &space))
return;
if (params > 1 && !debug_command_parameter_number(machine, param[1], &comp_value))
return;
comp_value = cheat_sign_extend(&cheat, comp_value);
/* decode contidion */
if (!strcmp(param[0], "all"))
condition = CHEAT_ALL;
else if (!strcmp(param[0], "equal") || !strcmp(param[0], "eq"))
condition = (params > 1) ? CHEAT_EQUALTO : CHEAT_EQUAL;
else if (!strcmp(param[0], "notequal") || !strcmp(param[0], "ne"))
condition = (params > 1) ? CHEAT_NOTEQUALTO : CHEAT_NOTEQUAL;
else if (!strcmp(param[0], "decrease") || !strcmp(param[0], "de") || !strcmp(param[0], "-"))
condition = (params > 1) ? CHEAT_DECREASEOF : CHEAT_DECREASE;
else if (!strcmp(param[0], "increase") || !strcmp(param[0], "in") || !strcmp(param[0], "+"))
condition = (params > 1) ? CHEAT_INCREASEOF : CHEAT_INCREASE;
else if (!strcmp(param[0], "smallerof") || !strcmp(param[0], "lt") || !strcmp(param[0], "<"))
condition = CHEAT_SMALLEROF;
else if (!strcmp(param[0], "greaterof") || !strcmp(param[0], "gt") || !strcmp(param[0], ">"))
condition = CHEAT_GREATEROF;
else
{
debug_console_printf(machine, "Invalid condition type\n");
return;
}
cheat.undo++;
/* execute the search */
for (cheatindex = 0; cheatindex < cheat.length; cheatindex += 1)
if (cheat.cheatmap[cheatindex].state == 1)
{
UINT64 cheat_value = cheat_read_extended(&cheat, space, cheat.cheatmap[cheatindex].offset);
UINT64 comp_byte = (ref == 0) ? cheat.cheatmap[cheatindex].previous_value : cheat.cheatmap[cheatindex].first_value;
UINT8 disable_byte = FALSE;
switch (condition)
{
case CHEAT_ALL:
break;
case CHEAT_EQUAL:
disable_byte = (cheat_value != comp_byte);
break;
case CHEAT_NOTEQUAL:
disable_byte = (cheat_value == comp_byte);
break;
case CHEAT_EQUALTO:
disable_byte = (cheat_value != comp_value);
break;
case CHEAT_NOTEQUALTO:
disable_byte = (cheat_value == comp_value);
break;
case CHEAT_DECREASE:
if (cheat.signed_cheat)
disable_byte = ((INT64)cheat_value >= (INT64)comp_byte);
else
disable_byte = ((UINT64)cheat_value >= (UINT64)comp_byte);
break;
case CHEAT_INCREASE:
if (cheat.signed_cheat)
disable_byte = ((INT64)cheat_value <= (INT64)comp_byte);
else
disable_byte = ((UINT64)cheat_value <= (UINT64)comp_byte);
break;
case CHEAT_DECREASEOF:
disable_byte = (cheat_value != comp_byte - comp_value);
break;
case CHEAT_INCREASEOF:
disable_byte = (cheat_value != comp_byte + comp_value);
break;
case CHEAT_SMALLEROF:
if (cheat.signed_cheat)
disable_byte = ((INT64)cheat_value >= (INT64)comp_value);
else
disable_byte = ((UINT64)cheat_value >= (UINT64)comp_value);
break;
case CHEAT_GREATEROF:
if (cheat.signed_cheat)
disable_byte = ((INT64)cheat_value <= (INT64)comp_value);
else
disable_byte = ((UINT64)cheat_value <= (UINT64)comp_value);
break;
}
if (disable_byte)
{
cheat.cheatmap[cheatindex].state = 0;
cheat.cheatmap[cheatindex].undo = cheat.undo;
}
else
active_cheat++;
/* update previous value */
cheat.cheatmap[cheatindex].previous_value = cheat_value;
}
if (active_cheat <= 5)
execute_cheatlist(machine, 0, 0, NULL);
debug_console_printf(machine, "%u cheats found\n", active_cheat);
}
/*-------------------------------------------------
execute_cheatlist - show a list of active cheat
-------------------------------------------------*/
static void execute_cheatlist(running_machine *machine, int ref, int params, const char *param[])
{
char spaceletter, sizeletter;
const address_space *space;
UINT32 active_cheat = 0;
UINT64 cheatindex;
UINT64 sizemask;
FILE *f = NULL;
if (!debug_command_parameter_cpu_space(machine, &cheat.cpu, ADDRESS_SPACE_PROGRAM, &space))
return;
if (params > 0)
f = fopen(param[0], "w");
switch (space->spacenum)
{
default:
case ADDRESS_SPACE_PROGRAM: spaceletter = 'p'; break;
case ADDRESS_SPACE_DATA: spaceletter = 'd'; break;
case ADDRESS_SPACE_IO: spaceletter = 'i'; break;
}
switch (cheat.width)
{
default:
case 1: sizeletter = 'b'; sizemask = 0xff; break;
case 2: sizeletter = 'w'; sizemask = 0xffff; break;
case 4: sizeletter = 'd'; sizemask = 0xffffffff; break;
case 8: sizeletter = 'q'; sizemask = U64(0xffffffffffffffff); break;
}
/* write the cheat list */
for (cheatindex = 0; cheatindex < cheat.length; cheatindex += 1)
{
if (cheat.cheatmap[cheatindex].state == 1)
{
UINT64 value = cheat_read_extended(&cheat, space, cheat.cheatmap[cheatindex].offset) & sizemask;
offs_t address = memory_byte_to_address(space, cheat.cheatmap[cheatindex].offset);
if (params > 0)
{
active_cheat++;
fprintf(f, " <cheat desc=\"Possibility %d : %0*X (%0*" I64FMT "X)\">\n", active_cheat, space->logaddrchars, address, cheat.width * 2, value);
fprintf(f, " <script state=\"run\">\n");
fprintf(f, " <action>maincpu.%c%c@%0*X=%0*" I64FMT "X</action>\n", spaceletter, sizeletter, space->logaddrchars, address, cheat.width * 2, cheat.cheatmap[cheatindex].first_value & sizemask);
fprintf(f, " </script>\n");
fprintf(f, " </cheat>\n\n");
}
else
debug_console_printf(machine, "Address=%0*X Start=%0*" I64FMT "X Current=%0*" I64FMT "X\n", space->logaddrchars, address, cheat.width * 2, cheat.cheatmap[cheatindex].first_value & sizemask, cheat.width * 2, value);
}
}
if (params > 0)
fclose(f);
}
/*-------------------------------------------------
execute_cheatundo - undo the last search
-------------------------------------------------*/
static void execute_cheatundo(running_machine *machine, int ref, int params, const char *param[])
{
UINT64 cheatindex;
UINT32 undo_count = 0;
if (cheat.undo > 0)
{
for (cheatindex = 0; cheatindex < cheat.length; cheatindex += 1)
{
if (cheat.cheatmap[cheatindex].undo == cheat.undo)
{
cheat.cheatmap[cheatindex].state = 1;
cheat.cheatmap[cheatindex].undo = 0;
undo_count++;
}
}
cheat.undo--;
debug_console_printf(machine, "%u cheat reactivated\n", undo_count);
}
else
debug_console_printf(machine, "Maximum undo reached\n");
}
/*-------------------------------------------------
execute_find - execute the find command
-------------------------------------------------*/

View File

@ -1530,6 +1530,25 @@ UINT64 debug_read_qword(const address_space *space, offs_t address, int apply_tr
}
/*-------------------------------------------------
debug_read_memory - return 1,2,4 or 8 bytes
from the specified memory space
-------------------------------------------------*/
UINT64 debug_read_memory(const address_space *space, offs_t address, int size, int apply_translation)
{
UINT64 result = ~(UINT64)0 >> (64 - 8*size);
switch (size)
{
case 1: result = debug_read_byte(space, address, apply_translation); break;
case 2: result = debug_read_word(space, address, apply_translation); break;
case 4: result = debug_read_dword(space, address, apply_translation); break;
case 8: result = debug_read_qword(space, address, apply_translation); break;
}
return result;
}
/*-------------------------------------------------
debug_write_byte - write a byte to the
specified memory space
@ -1726,6 +1745,23 @@ void debug_write_qword(const address_space *space, offs_t address, UINT64 data,
}
/*-------------------------------------------------
debug_write_memory - write 1,2,4 or 8 bytes
to the specified memory space
-------------------------------------------------*/
void debug_write_memory(const address_space *space, offs_t address, UINT64 data, int size, int apply_translation)
{
switch (size)
{
case 1: debug_write_byte(space, address, data, apply_translation); break;
case 2: debug_write_word(space, address, data, apply_translation); break;
case 4: debug_write_dword(space, address, data, apply_translation); break;
case 8: debug_write_qword(space, address, data, apply_translation); break;
}
}
/*-------------------------------------------------
debug_read_opcode - read 1,2,4 or 8 bytes at
the given offset from opcode space
@ -2471,19 +2507,7 @@ static UINT64 expression_read_address_space(const address_space *space, offs_t a
UINT64 result = ~(UINT64)0 >> (64 - 8*size);
if (space != NULL)
{
/* adjust the address into a byte address */
address = memory_address_to_byte(space, address);
/* switch contexts and do the read */
switch (size)
{
case 1: result = debug_read_byte(space, address, TRUE); break;
case 2: result = debug_read_word(space, address, TRUE); break;
case 4: result = debug_read_dword(space, address, TRUE); break;
case 8: result = debug_read_qword(space, address, TRUE); break;
}
}
result = debug_read_memory(space, memory_address_to_byte(space, address), size, TRUE);
return result;
}
@ -2677,19 +2701,7 @@ static void expression_write_memory(void *param, const char *name, int space, UI
static void expression_write_address_space(const address_space *space, offs_t address, int size, UINT64 data)
{
if (space != NULL)
{
/* adjust the address into a byte address */
address = memory_address_to_byte(space, address);
/* switch contexts and do the write */
switch (size)
{
case 1: debug_write_byte(space, address, data, TRUE); break;
case 2: debug_write_word(space, address, data, TRUE); break;
case 4: debug_write_dword(space, address, data, TRUE); break;
case 8: debug_write_qword(space, address, data, TRUE); break;
}
}
debug_write_memory(space, memory_address_to_byte(space, address), data, size, TRUE);
}

View File

@ -336,6 +336,9 @@ UINT32 debug_read_dword(const address_space *space, offs_t address, int apply_tr
/* return a qword from the the specified memory space */
UINT64 debug_read_qword(const address_space *space, offs_t address, int apply_translation);
/* return 1,2,4 or 8 bytes from the specified memory space */
UINT64 debug_read_memory(const address_space *space, offs_t address, int size, int apply_translation);
/* write a byte to the specified memory space */
void debug_write_byte(const address_space *space, offs_t address, UINT8 data, int apply_translation);
@ -348,6 +351,9 @@ void debug_write_dword(const address_space *space, offs_t address, UINT32 data,
/* write a qword to the specified memory space */
void debug_write_qword(const address_space *space, offs_t address, UINT64 data, int apply_translation);
/* write 1,2,4 or 8 bytes to the specified memory space */
void debug_write_memory(const address_space *space, offs_t address, UINT64 data, int size, int apply_translation);
/* read 1,2,4 or 8 bytes at the given offset from opcode space */
UINT64 debug_read_opcode(const address_space *space, offs_t offset, int size, int arg);

View File

@ -69,6 +69,7 @@ static const help_item static_help_list[] =
" Watchpoints\n"
" Expressions\n"
" Comments\n"
" Cheats\n"
},
{
"general",
@ -203,6 +204,19 @@ static const help_item static_help_list[] =
" comsave -- save the current comments to a file\n"
"\n"
},
{
"cheats",
"\n"
"Cheat Commands\n"
"Type help <command> for further details on each command\n"
"\n"
" cheatinit [<address>,<length>[,<cpu>]] -- initialize the cheat search to the selected memory area\n"
" cheatrange <address>,<length> -- add to the cheat search the selected memory area\n"
" cheatnext <condition>[,<comparisonvalue>] -- continue cheat search comparing with the the last value\n"
" cheatnextf <condition>[,<comparisonvalue>] -- continue cheat search comparing with the the first value\n"
" cheatlist [<filename>] -- show the list of cheat search matches or save them to <filename>\n"
" cheatundo [<wpnum>] -- undo the last cheat search (state only)\n"
},
{
"do",
"\n"
@ -1029,6 +1043,152 @@ static const help_item static_help_list[] =
"comdelete 10\n"
" Deletes the comment at code address 0x10 (using the current memory bank settings)\n"
"\n"
},
{
"cheatinit",
"\n"
" cheatinit [<type>,[<address>,<length>[,<cpu>]]]\n"
"\n"
"The cheatinit command initializes the cheat search to the selected memory area.\n"
"If no parameter is specified the cheat search is initialized to all changeable memory of the main cpu.\n"
"Possible <type>:\n"
" ub\n"
" 8 bit unsigned int\n"
" uw\n"
" 16 bit unsigned int\n"
" ud\n"
" 32 bit unsigned int\n"
" uq\n"
" 64 bit unsigned int\n"
" sb\n"
" 8 bit signed int\n"
" sw\n"
" 16 bit signed int\n"
" sd\n"
" 32 bit signed int\n"
" sq\n"
" 64 bit signed int\n"
"\n"
"Examples:\n"
"\n"
"cheatinit ub,0x1000,0x10\n"
" Initialize the cheat search from 0x1000 to 0x1010 of the first CPU.\n"
"\n"
"cheatinit sw,0x2000,0x1000,1\n"
" Initialize the cheat search with width of 2 byte in signed mode from 0x2000 to 0x3000 of the second CPU.\n"
},
{
"cheatrange",
"\n"
" cheatrange <address>,<length>\n"
"\n"
"The cheatrange command adds the selected memory area to the cheat search.\n"
"Before using cheatrange it is necessary to initialize the cheat search with cheatinit.\n"
"\n"
"Examples:\n"
"\n"
"cheatrange 0x1000,0x10\n"
" Add the bytes from 0x1000 to 0x1010 to the cheat search.\n"
},
{
"cheatnext",
"\n"
" cheatnext <condition>[,<comparisonvalue>]\n"
"\n"
"The cheatnext command will make comparisons with the last search matches.\n"
"Possible <condition>:\n"
" all\n"
" no <comparisonvalue> needed.\n"
" use to update the last value without changing the current matches.\n"
" equal [eq]\n"
" without <comparisonvalue> search for all bytes that are equal to the last search.\n"
" with <comparisonvalue> search for all bytes that are equal to the <comparisonvalue>.\n"
" notequal [ne]\n"
" without <comparisonvalue> search for all bytes that are not equal to the last search.\n"
" with <comparisonvalue> search for all bytes that are not equal to the <comparisonvalue>.\n"
" decrease [de, +]\n"
" without <comparisonvalue> search for all bytes that have decreased since the last search.\n"
" with <comparisonvalue> search for all bytes that have decreased by the <comparisonvalue> since the last search.\n"
" increase [in, -]\n"
" without <comparisonvalue> search for all bytes that have increased since the last search.\n"
" with <comparisonvalue> search for all bytes that have increased by the <comparisonvalue> since the last search.\n"
" smallerof [lt]\n"
" without <comparisonvalue> this condition is invalid\n"
" with <comparisonvalue> search for all bytes that are smaller than the <comparisonvalue>.\n"
" greaterof [gt]\n"
" without <comparisonvalue> this condition is invalid\n"
" with <comparisonvalue> search for all bytes that are larger than the <comparisonvalue>.\n"
"\n"
"Examples:\n"
"\n"
"cheatnext increase\n"
" search for all bytes that have increased since the last search.\n"
"\n"
"cheatnext decrease, 1\n"
" search for all bytes that have decreased by 1 since the last search.\n"
},
{
"cheatnextf",
"\n"
" cheatnextf <condition>[,<comparisonvalue>]\n"
"\n"
"The cheatnextf command will make comparisons with the initial search.\n"
"Possible <condition>:\n"
" all\n"
" no <comparisonvalue> needed.\n"
" use to update the last value without changing the current matches.\n"
" equal [eq]\n"
" without <comparisonvalue> search for all bytes that are equal to the initial search.\n"
" with <comparisonvalue> search for all bytes that are equal to the <comparisonvalue>.\n"
" notequal [ne]\n"
" without <comparisonvalue> search for all bytes that are not equal to the initial search.\n"
" with <comparisonvalue> search for all bytes that are not equal to the <comparisonvalue>.\n"
" decrease [de, +]\n"
" without <comparisonvalue> search for all bytes that have decreased since the initial search.\n"
" with <comparisonvalue> search for all bytes that have decreased by the <comparisonvalue> since the initial search.\n"
" increase [in, -]\n"
" without <comparisonvalue> search for all bytes that have increased since the initial search.\n"
" with <comparisonvalue> search for all bytes that have increased by the <comparisonvalue> since the initial search.\n"
" smallerof [lt]\n"
" without <comparisonvalue> this condition is invalid.\n"
" with <comparisonvalue> search for all bytes that are smaller than the <comparisonvalue>.\n"
" greaterof [gt]\n"
" without <comparisonvalue> this condition is invalid.\n"
" with <comparisonvalue> search for all bytes that are larger than the <comparisonvalue>.\n"
"\n"
"Examples:\n"
"\n"
"cheatnextf increase\n"
" search for all bytes that have increased since the initial search.\n"
"\n"
"cheatnextf decrease, 1\n"
" search for all bytes that have decreased by 1 since the initial search.\n"
},
{
"cheatlist",
"\n"
" cheatlist [<filename>]\n"
"\n"
"Without <filename> show the list of matches in the debug console.\n"
"With <filename> save the list of matches in basic xml format to <filename>.\n"
"\n"
"Examples:\n"
"\n"
"cheatlist\n"
" Show the current matches in the debug console.\n"
"cheatlist cheat.txt\n"
" Save the current matches to cheat.txt.\n"
},
{
" cheatundo\n"
"\n"
"Undo the results of the last search.\n"
"The undo command has no effect on the last value.\n"
"\n"
"Examples:\n"
"\n"
"cheatundo\n"
" Undo the last search (state only).\n"
}
};