From 6b159dfd11f55124f818048cbf7603ff76b2a5bc Mon Sep 17 00:00:00 2001 From: Aaron Giles Date: Thu, 3 Sep 2009 08:54:11 +0000 Subject: [PATCH] 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. --- src/emu/debug/debugcmd.c | 490 +++++++++++++++++++++++++++++++++++++++ src/emu/debug/debugcpu.c | 64 ++--- src/emu/debug/debugcpu.h | 6 + src/emu/debug/debughlp.c | 160 +++++++++++++ 4 files changed, 694 insertions(+), 26 deletions(-) diff --git a/src/emu/debug/debugcmd.c b/src/emu/debug/debugcmd.c index 628d07d9d72..1e2996a9ee8 100644 --- a/src/emu/debug/debugcmd.c +++ b/src/emu/debug/debugcmd.c @@ -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, " \n", active_cheat, space->logaddrchars, address, cheat.width * 2, value); + fprintf(f, " \n"); + fprintf(f, " \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 -------------------------------------------------*/ diff --git a/src/emu/debug/debugcpu.c b/src/emu/debug/debugcpu.c index 1d6c96cafa1..5137e6bac2c 100644 --- a/src/emu/debug/debugcpu.c +++ b/src/emu/debug/debugcpu.c @@ -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); } diff --git a/src/emu/debug/debugcpu.h b/src/emu/debug/debugcpu.h index 2b70037fa15..82d2e6117df 100644 --- a/src/emu/debug/debugcpu.h +++ b/src/emu/debug/debugcpu.h @@ -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); diff --git a/src/emu/debug/debughlp.c b/src/emu/debug/debughlp.c index 8a975c90ff3..f82c610c0ea 100644 --- a/src/emu/debug/debughlp.c +++ b/src/emu/debug/debughlp.c @@ -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 for further details on each command\n" + "\n" + " cheatinit [
,[,]] -- initialize the cheat search to the selected memory area\n" + " cheatrange
, -- add to the cheat search the selected memory area\n" + " cheatnext [,] -- continue cheat search comparing with the the last value\n" + " cheatnextf [,] -- continue cheat search comparing with the the first value\n" + " cheatlist [] -- show the list of cheat search matches or save them to \n" + " cheatundo [] -- 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 [,[
,[,]]]\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 :\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
,\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 [,]\n" + "\n" + "The cheatnext command will make comparisons with the last search matches.\n" + "Possible :\n" + " all\n" + " no needed.\n" + " use to update the last value without changing the current matches.\n" + " equal [eq]\n" + " without search for all bytes that are equal to the last search.\n" + " with search for all bytes that are equal to the .\n" + " notequal [ne]\n" + " without search for all bytes that are not equal to the last search.\n" + " with search for all bytes that are not equal to the .\n" + " decrease [de, +]\n" + " without search for all bytes that have decreased since the last search.\n" + " with search for all bytes that have decreased by the since the last search.\n" + " increase [in, -]\n" + " without search for all bytes that have increased since the last search.\n" + " with search for all bytes that have increased by the since the last search.\n" + " smallerof [lt]\n" + " without this condition is invalid\n" + " with search for all bytes that are smaller than the .\n" + " greaterof [gt]\n" + " without this condition is invalid\n" + " with search for all bytes that are larger than the .\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 [,]\n" + "\n" + "The cheatnextf command will make comparisons with the initial search.\n" + "Possible :\n" + " all\n" + " no needed.\n" + " use to update the last value without changing the current matches.\n" + " equal [eq]\n" + " without search for all bytes that are equal to the initial search.\n" + " with search for all bytes that are equal to the .\n" + " notequal [ne]\n" + " without search for all bytes that are not equal to the initial search.\n" + " with search for all bytes that are not equal to the .\n" + " decrease [de, +]\n" + " without search for all bytes that have decreased since the initial search.\n" + " with search for all bytes that have decreased by the since the initial search.\n" + " increase [in, -]\n" + " without search for all bytes that have increased since the initial search.\n" + " with search for all bytes that have increased by the since the initial search.\n" + " smallerof [lt]\n" + " without this condition is invalid.\n" + " with search for all bytes that are smaller than the .\n" + " greaterof [gt]\n" + " without this condition is invalid.\n" + " with search for all bytes that are larger than the .\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 []\n" + "\n" + "Without show the list of matches in the debug console.\n" + "With save the list of matches in basic xml format to .\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" } };