summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2008-08-07 15:53:58 +0000
committer Aaron Giles <aaron@aarongiles.com>2008-08-07 15:53:58 +0000
commit9df01a28965b68eededf472e609bb2615ab11dcb (patch)
treee02609e61b7fd26d2d796122cc1e4b55c51481e6
parent3107dc2dffe23f7e52b4f46d35d8e458c6b663b4 (diff)
Added expression validation callback to verify names for CPUs and
memory regions. Extended error codes to report incorrect memory spaces, memory names, or memory sizes. Added verification callback to the debugger to validate CPU and memory region names, as well as verifying that a requested address space exists for a given CPU. Added support for oneshot cheats (those with only an "on" script). They are activated via UI_SELECT in the cheat menu, and pop up a message when activated. Also added a "Reset All" item in the cheat menu to reset all cheats back to their default state, and added support for UI_SELECT on a non-oneshot cheat so that it resets that cheat to its default value. Restored previous behavior that allowed popmessage() messages to overlay menus and other UI.
-rw-r--r--src/emu/cheat.c84
-rw-r--r--src/emu/cheat.h6
-rw-r--r--src/emu/debug/debugcpu.c49
-rw-r--r--src/emu/debug/express.c66
-rw-r--r--src/emu/debug/express.h19
-rw-r--r--src/emu/ui.c16
-rw-r--r--src/emu/uimenu.c47
7 files changed, 232 insertions, 55 deletions
diff --git a/src/emu/cheat.c b/src/emu/cheat.c
index d5a67ae26f1..2f43fcb8814 100644
--- a/src/emu/cheat.c
+++ b/src/emu/cheat.c
@@ -321,8 +321,17 @@ void *cheat_get_next_menu_entry(running_machine *machine, void *previous, const
if (description != NULL)
*description = astring_c(cheat->description);
+ /* if we have no parameter and no run or off script, it's a oneshot cheat */
+ if (cheat->parameter == NULL && cheat->script[SCRIPT_STATE_RUN] == NULL && cheat->script[SCRIPT_STATE_OFF] == NULL)
+ {
+ if (state != NULL)
+ *state = "Activate";
+ if (flags != NULL)
+ *flags = 0;
+ }
+
/* if we have no parameter, it's just on/off */
- if (cheat->parameter == NULL)
+ else if (cheat->parameter == NULL)
{
if (state != NULL)
*state = (cheat->state == SCRIPT_STATE_RUN) ? "On" : "Off";
@@ -374,6 +383,67 @@ void *cheat_get_next_menu_entry(running_machine *machine, void *previous, const
/*-------------------------------------------------
+ cheat_activate - activate a oneshot cheat
+-------------------------------------------------*/
+
+int cheat_activate(running_machine *machine, void *entry)
+{
+ cheat_private *cheatinfo = machine->cheat_data;
+ cheat_entry *cheat = entry;
+ int changed = FALSE;
+
+ /* if we have no parameter and no run or off script, it's a oneshot cheat */
+ if (cheat->parameter == NULL && cheat->script[SCRIPT_STATE_RUN] == NULL && cheat->script[SCRIPT_STATE_OFF] == NULL)
+ {
+ cheat_execute_script(cheatinfo, cheat, SCRIPT_STATE_ON);
+ changed = TRUE;
+ popmessage("Activated %s", astring_c(cheat->description));
+ }
+ return changed;
+}
+
+
+/*-------------------------------------------------
+ cheat_select_default_state - select the
+ default state for a cheat, or activate a
+ oneshot cheat
+-------------------------------------------------*/
+
+int cheat_select_default_state(running_machine *machine, void *entry)
+{
+ cheat_private *cheatinfo = machine->cheat_data;
+ cheat_entry *cheat = entry;
+ int changed = FALSE;
+
+ /* if we have no parameter and no run or off script, it's a oneshot cheat */
+ if (cheat->parameter == NULL && cheat->script[SCRIPT_STATE_RUN] == NULL && cheat->script[SCRIPT_STATE_OFF] == NULL)
+ ;
+
+ /* if we have no parameter, it's just on/off; default to off */
+ else if (cheat->parameter == NULL)
+ {
+ if (cheat->state != SCRIPT_STATE_OFF)
+ {
+ cheat->state = SCRIPT_STATE_OFF;
+ cheat_execute_script(cheatinfo, cheat, SCRIPT_STATE_OFF);
+ changed = TRUE;
+ }
+ }
+
+ /* if we have a value parameter, fall back to the default */
+ else
+ {
+ if (cheat->parameter->value != cheat->parameter->defval)
+ {
+ cheat->parameter->value = cheat->parameter->defval;
+ changed = TRUE;
+ }
+ }
+ return changed;
+}
+
+
+/*-------------------------------------------------
cheat_select_previous_state - select the
previous state for a cheat
-------------------------------------------------*/
@@ -384,8 +454,12 @@ int cheat_select_previous_state(running_machine *machine, void *entry)
cheat_entry *cheat = entry;
int changed = FALSE;
+ /* if we have no parameter and no run or off script, it's a oneshot cheat */
+ if (cheat->parameter == NULL && cheat->script[SCRIPT_STATE_RUN] == NULL && cheat->script[SCRIPT_STATE_OFF] == NULL)
+ ;
+
/* if we have no parameter, it's just on/off */
- if (cheat->parameter == NULL)
+ else if (cheat->parameter == NULL)
{
if (cheat->state != SCRIPT_STATE_OFF)
{
@@ -439,8 +513,12 @@ int cheat_select_next_state(running_machine *machine, void *entry)
cheat_entry *cheat = entry;
int changed = FALSE;
+ /* if we have no parameter and no run or off script, it's a oneshot cheat */
+ if (cheat->parameter == NULL && cheat->script[SCRIPT_STATE_RUN] == NULL && cheat->script[SCRIPT_STATE_OFF] == NULL)
+ ;
+
/* if we have no parameter, it's just on/off */
- if (cheat->parameter == NULL)
+ else if (cheat->parameter == NULL)
{
if (cheat->state != SCRIPT_STATE_RUN)
{
diff --git a/src/emu/cheat.h b/src/emu/cheat.h
index 45f4197f434..d341ee5f6ec 100644
--- a/src/emu/cheat.h
+++ b/src/emu/cheat.h
@@ -38,6 +38,12 @@ void cheat_render_text(running_machine *machine);
/* return data about the next menu entry, or the first entry if previous == NULL */
void *cheat_get_next_menu_entry(running_machine *machine, void *previous, const char **description, const char **state, UINT32 *flags);
+/* activate a oneshot cheat */
+int cheat_activate(running_machine *machine, void *entry);
+
+/* select the default menu state */
+int cheat_select_default_state(running_machine *machine, void *entry);
+
/* select the previous menu state */
int cheat_select_previous_state(running_machine *machine, void *entry);
diff --git a/src/emu/debug/debugcpu.c b/src/emu/debug/debugcpu.c
index d8bd632ac4c..c1b3ec97b4f 100644
--- a/src/emu/debug/debugcpu.c
+++ b/src/emu/debug/debugcpu.c
@@ -108,6 +108,7 @@ static void expression_write_address_space(int cpuindex, int space, offs_t addre
static void expression_write_program_direct(int cpuindex, int opcode, offs_t address, int size, UINT64 data);
static void expression_write_memory_region(const char *rgntag, offs_t address, int size, UINT64 data);
static void expression_write_eeprom(offs_t address, int size, UINT64 data);
+static EXPRERR expression_validate(const char *name, int space);
/* variable getters/setters */
static UINT64 get_wpaddr(void *ref);
@@ -132,7 +133,8 @@ static void set_cpu_reg(void *ref, UINT64 value);
const express_callbacks debug_expression_callbacks =
{
expression_read_memory,
- expression_write_memory
+ expression_write_memory,
+ expression_validate
};
@@ -2573,6 +2575,51 @@ static void expression_write_eeprom(offs_t address, int size, UINT64 data)
/*-------------------------------------------------
+ expression_validate - validate that the
+ provided expression references an
+ appropriate name
+-------------------------------------------------*/
+
+static EXPRERR expression_validate(const char *name, int space)
+{
+ int cpuindex;
+
+ switch (space)
+ {
+ case EXPSPACE_PROGRAM:
+ case EXPSPACE_DATA:
+ case EXPSPACE_IO:
+ cpuindex = (name != NULL) ? mame_find_cpu_index(Machine, name) : cpu_getactivecpu();
+ if (cpuindex < 0)
+ return (name == NULL) ? EXPRERR_MISSING_MEMORY_NAME : EXPRERR_INVALID_MEMORY_NAME;
+ if (cpunum_addrbus_width(cpuindex, ADDRESS_SPACE_PROGRAM + (space - EXPSPACE_PROGRAM)) == 0)
+ return EXPRERR_NO_SUCH_MEMORY_SPACE;
+ break;
+
+ case EXPSPACE_OPCODE:
+ case EXPSPACE_RAMWRITE:
+ cpuindex = (name != NULL) ? mame_find_cpu_index(Machine, name) : cpu_getactivecpu();
+ if (cpuindex < 0)
+ return (name == NULL) ? EXPRERR_MISSING_MEMORY_NAME : EXPRERR_INVALID_MEMORY_NAME;
+ break;
+
+ case EXPSPACE_EEPROM:
+ if (name != NULL)
+ return EXPRERR_INVALID_MEMORY_NAME;
+ break;
+
+ case EXPSPACE_REGION:
+ if (name == NULL)
+ return EXPRERR_MISSING_MEMORY_NAME;
+ if (memory_region(Machine, name) == NULL)
+ return EXPRERR_INVALID_MEMORY_NAME;
+ break;
+ }
+ return EXPRERR_NONE;
+}
+
+
+/*-------------------------------------------------
debug_cpu_trace_printf - writes text to a given
CPU's trace file
-------------------------------------------------*/
diff --git a/src/emu/debug/express.c b/src/emu/debug/express.c
index f61edda8407..e2d69b2093a 100644
--- a/src/emu/debug/express.c
+++ b/src/emu/debug/express.c
@@ -518,8 +518,10 @@ static void print_tokens(FILE *out, parsed_expression *expr)
forms of memory operators
-------------------------------------------------*/
-static int parse_memory_operator(parsed_expression *expr, const char *buffer, token_info *flags)
+static EXPRERR parse_memory_operator(parsed_expression *expr, int offset, const char *buffer, token_info *flags)
{
+ const char *startbuffer = buffer;
+ const char *namestring = NULL;
int space = 'p', size;
const char *dot;
int length;
@@ -531,8 +533,10 @@ static int parse_memory_operator(parsed_expression *expr, const char *buffer, to
if (dot != NULL)
{
UINT16 index;
- if (!add_expression_string(expr, buffer, dot - buffer, &index))
- return 0;
+
+ namestring = add_expression_string(expr, buffer, dot - buffer, &index);
+ if (namestring == NULL)
+ return MAKE_EXPRERR_OUT_OF_MEMORY(offset);
*flags |= index << TIN_MEMORY_INDEX_SHIFT;
buffer = dot + 1;
}
@@ -551,7 +555,7 @@ static int parse_memory_operator(parsed_expression *expr, const char *buffer, to
/* anything else is invalid */
else
- return 0;
+ return MAKE_EXPRERR_INVALID_TOKEN(offset);
/* convert the space to flags */
switch (space)
@@ -563,7 +567,7 @@ static int parse_memory_operator(parsed_expression *expr, const char *buffer, to
case 'r': *flags |= TIN_MEMORY_RAMWRITE; break;
case 'e': *flags |= TIN_MEMORY_EEPROM; break;
case 'm': *flags |= TIN_MEMORY_REGION; break;
- default: return 0;
+ default: return MAKE_EXPRERR_INVALID_MEMORY_SPACE(offset + (buffer - startbuffer));
}
/* convert the size to flags */
@@ -573,10 +577,20 @@ static int parse_memory_operator(parsed_expression *expr, const char *buffer, to
case 'w': *flags |= TIN_MEMORY_WORD; break;
case 'd': *flags |= TIN_MEMORY_DWORD; break;
case 'q': *flags |= TIN_MEMORY_QWORD; break;
- default: return 0;
+ default: return MAKE_EXPRERR_INVALID_MEMORY_SIZE(offset + (buffer - startbuffer) + length - 1);
}
-
- return 1;
+
+ /* validate the name */
+ if (expr->callbacks.valid != NULL)
+ {
+ EXPRERR err = (*expr->callbacks.valid)(namestring, (*flags & TIN_MEMORY_SPACE_MASK) >> TIN_MEMORY_SPACE_SHIFT);
+ if (err == EXPRERR_INVALID_MEMORY_SPACE)
+ return MAKE_EXPRERR_INVALID_MEMORY_SPACE(offset + (buffer - startbuffer));
+ else if (err != EXPRERR_NONE)
+ return MAKE_EXPRERR(err, offset);
+ }
+
+ return EXPRERR_NONE;
}
@@ -598,9 +612,6 @@ static EXPRERR parse_string_into_tokens(const char *stringstart, parsed_expressi
parse_token *token = expr->token;
const char *string = stringstart;
- /* zap expression object */
- memset(expr, 0, sizeof(*expr));
-
/* stash the symbol table pointer */
expr->table = table;
@@ -826,11 +837,11 @@ static EXPRERR parse_string_into_tokens(const char *stringstart, parsed_expressi
if (string[0] == '@')
{
token_info info;
- if (parse_memory_operator(expr, buffer, &info))
- {
- SET_TOKEN_INFO(1, TOK_OPERATOR, TVL_MEMORYAT, TIN_PRECEDENCE_2 | info);
- break;
- }
+ EXPRERR err = parse_memory_operator(expr, token->offset, buffer, &info);
+ if (err != EXPRERR_NONE)
+ return err;
+ SET_TOKEN_INFO(1, TOK_OPERATOR, TVL_MEMORYAT, TIN_PRECEDENCE_2 | info);
+ break;
}
/* empty string is automatically invalid */
@@ -1725,6 +1736,11 @@ EXPRERR expression_evaluate(const char *expression, const symbol_table *table, c
parsed_expression temp_expression;
EXPRERR exprerr;
+ /* zap expression object and copy the callbacks */
+ memset(&temp_expression, 0, sizeof(temp_expression));
+ if (callbacks != NULL)
+ temp_expression.callbacks = *callbacks;
+
/* first parse the tokens into the token array in order */
exprerr = parse_string_into_tokens(expression, &temp_expression, table);
if (exprerr != EXPRERR_NONE)
@@ -1741,10 +1757,6 @@ EXPRERR expression_evaluate(const char *expression, const symbol_table *table, c
/* debugging */
print_tokens(stdout, &temp_expression);
- /* copy the callbacks */
- if (callbacks != NULL)
- temp_expression.callbacks = *callbacks;
-
/* execute the expression to get the result */
exprerr = execute_tokens(&temp_expression, result);
@@ -1764,6 +1776,11 @@ EXPRERR expression_parse(const char *expression, const symbol_table *table, cons
parsed_expression temp_expression;
EXPRERR exprerr;
+ /* zap expression object and copy the callbacks */
+ memset(&temp_expression, 0, sizeof(temp_expression));
+ if (callbacks != NULL)
+ temp_expression.callbacks = *callbacks;
+
/* first parse the tokens into the token array in order */
exprerr = parse_string_into_tokens(expression, &temp_expression, table);
if (exprerr != EXPRERR_NONE)
@@ -1782,10 +1799,6 @@ EXPRERR expression_parse(const char *expression, const symbol_table *table, cons
goto cleanup;
}
- /* copy the callbacks */
- if (callbacks != NULL)
- temp_expression.callbacks = *callbacks;
-
/* copy the final expression and return */
**result = temp_expression;
return EXPRERR_NONE;
@@ -1862,6 +1875,11 @@ const char *exprerr_to_string(EXPRERR error)
case EXPRERR_INVALID_PARAM_COUNT: return "invalid number of parameters";
case EXPRERR_UNBALANCED_QUOTES: return "unbalanced quotes";
case EXPRERR_TOO_MANY_STRINGS: return "too many strings";
+ case EXPRERR_INVALID_MEMORY_SIZE: return "invalid memory size (b/w/d/q expected)";
+ case EXPRERR_NO_SUCH_MEMORY_SPACE: return "non-existent memory space";
+ case EXPRERR_INVALID_MEMORY_SPACE: return "invalid memory space (p/d/i/o/r/m expected)";
+ case EXPRERR_INVALID_MEMORY_NAME: return "invalid memory name";
+ case EXPRERR_MISSING_MEMORY_NAME: return "missing memory name";
default: return "unknown error";
}
}
diff --git a/src/emu/debug/express.h b/src/emu/debug/express.h
index a71ebec5afe..b48c6ea7d20 100644
--- a/src/emu/debug/express.h
+++ b/src/emu/debug/express.h
@@ -40,6 +40,11 @@
#define EXPRERR_INVALID_PARAM_COUNT (12)
#define EXPRERR_UNBALANCED_QUOTES (13)
#define EXPRERR_TOO_MANY_STRINGS (14)
+#define EXPRERR_INVALID_MEMORY_SIZE (15)
+#define EXPRERR_INVALID_MEMORY_SPACE (16)
+#define EXPRERR_NO_SUCH_MEMORY_SPACE (17)
+#define EXPRERR_INVALID_MEMORY_NAME (18)
+#define EXPRERR_MISSING_MEMORY_NAME (19)
/* values for the address space passed to external_read/write_memory */
#define EXPSPACE_PROGRAM (0)
@@ -76,6 +81,10 @@
#define MAKE_EXPRERR_INVALID_PARAM_COUNT(x) MAKE_EXPRERR(EXPRERR_INVALID_PARAM_COUNT, (x))
#define MAKE_EXPRERR_UNBALANCED_QUOTES(x) MAKE_EXPRERR(EXPRERR_UNBALANCED_QUOTES, (x))
#define MAKE_EXPRERR_TOO_MANY_STRINGS(x) MAKE_EXPRERR(EXPRERR_TOO_MANY_STRINGS, (x))
+#define MAKE_EXPRERR_INVALID_MEMORY_SIZE(x) MAKE_EXPRERR(EXPRERR_INVALID_MEMORY_SIZE, (x))
+#define MAKE_EXPRERR_NO_SUCH_MEMORY_SPACE(x) MAKE_EXPRERR(EXPRERR_NO_SUCH_MEMORY_SPACE, (x))
+#define MAKE_EXPRERR_INVALID_MEMORY_SPACE(x) MAKE_EXPRERR(EXPRERR_INVALID_MEMORY_SPACE, (x))
+#define MAKE_EXPRERR_INVALID_MEMORY_NAME(x) MAKE_EXPRERR(EXPRERR_INVALID_MEMORY_NAME, (x))
@@ -83,6 +92,10 @@
TYPE DEFINITIONS
***************************************************************************/
+/* EXPRERR is an error code for expression evaluation */
+typedef UINT32 EXPRERR;
+
+
/* callback functions for getting/setting a symbol value */
typedef UINT64 (*symbol_getter_func)(void *ref);
typedef void (*symbol_setter_func)(void *ref, UINT64 value);
@@ -93,6 +106,7 @@ typedef UINT64 (*function_execute_func)(void *ref, UINT32 numparams, const UINT6
/* callback function for memory reads/writes */
typedef UINT64 (*express_read_func)(const char *name, int space, UINT32 offset, int size);
typedef void (*express_write_func)(const char *name, int space, UINT32 offset, int size, UINT64 value);
+typedef EXPRERR (*express_valid_func)(const char *name, int space);
/* callback parameter for executing expressions */
@@ -101,6 +115,7 @@ struct _express_callbacks
{
express_read_func read; /* read callback */
express_write_func write; /* write callback */
+ express_valid_func valid; /* validation callback */
};
@@ -145,10 +160,6 @@ typedef struct _symbol_table symbol_table;
typedef struct _parsed_expression parsed_expression;
-/* EXPRERR is an error code for expression evaluation */
-typedef UINT32 EXPRERR;
-
-
/***************************************************************************
FUNCTION PROTOTYPES
diff --git a/src/emu/ui.c b/src/emu/ui.c
index f042ecfcf88..e10b854d3d2 100644
--- a/src/emu/ui.c
+++ b/src/emu/ui.c
@@ -437,6 +437,12 @@ void ui_update_and_render(running_machine *machine)
assert(ui_handler_callback != NULL);
ui_handler_param = (*ui_handler_callback)(machine, ui_handler_param);
+ /* display any popup messages */
+ if (osd_ticks() < popup_text_end)
+ ui_draw_text_box(astring_c(messagebox_text), JUSTIFY_CENTER, 0.5f, 0.9f, messagebox_backcolor);
+ else
+ popup_text_end = 0;
+
/* cancel takes us back to the ingame handler */
if (ui_handler_param == UI_HANDLER_CANCEL)
ui_set_handler(handler_ingame, 0);
@@ -1239,16 +1245,6 @@ static UINT32 handler_ingame(running_machine *machine, UINT32 state)
if (show_profiler)
ui_draw_text_full(profiler_get_text(), 0.0f, 0.0f, 1.0f, JUSTIFY_LEFT, WRAP_WORD, DRAW_OPAQUE, ARGB_WHITE, ARGB_BLACK, NULL, NULL);
- /* let the cheat engine display its stuff */
-// if (options_get_bool(mame_options(), OPTION_CHEAT))
-// cheat_display_watches(machine);
-
- /* display any popup messages */
- if (osd_ticks() < popup_text_end)
- ui_draw_text_box(astring_c(messagebox_text), JUSTIFY_CENTER, 0.5f, 0.9f, messagebox_backcolor);
- else
- popup_text_end = 0;
-
/* if we're single-stepping, pause now */
if (single_step)
{
diff --git a/src/emu/uimenu.c b/src/emu/uimenu.c
index 349dee245fc..f70b50cff44 100644
--- a/src/emu/uimenu.c
+++ b/src/emu/uimenu.c
@@ -2436,22 +2436,40 @@ static void menu_cheat(running_machine *machine, ui_menu *menu, void *parameter,
if (event != NULL && event->itemref != NULL)
{
int changed = FALSE;
-
- switch (event->iptkey)
+
+ /* handle reset all */
+ if ((FPTR)event->itemref == 1 && event->iptkey == IPT_UI_SELECT)
{
- /* if selected, reset to default value */
- case IPT_UI_SELECT:
- break;
+ void *curcheat;
+ for (curcheat = cheat_get_next_menu_entry(machine, NULL, NULL, NULL, NULL);
+ curcheat != NULL;
+ curcheat = cheat_get_next_menu_entry(machine, curcheat, NULL, NULL, NULL))
+ {
+ changed |= cheat_select_default_state(machine, curcheat);
+ }
+ }
+
+ /* handle individual cheats */
+ else if ((FPTR)event->itemref > 1)
+ {
+ switch (event->iptkey)
+ {
+ /* if selected, reset to default value or activate a oneshot */
+ case IPT_UI_SELECT:
+ changed = cheat_select_default_state(machine, event->itemref);
+ changed |= cheat_activate(machine, event->itemref);
+ break;
- /* left decrements */
- case IPT_UI_LEFT:
- changed = cheat_select_previous_state(machine, event->itemref);
- break;
+ /* left decrements */
+ case IPT_UI_LEFT:
+ changed = cheat_select_previous_state(machine, event->itemref);
+ break;
- /* right increments */
- case IPT_UI_RIGHT:
- changed = cheat_select_next_state(machine, event->itemref);
- break;
+ /* right increments */
+ case IPT_UI_RIGHT:
+ changed = cheat_select_next_state(machine, event->itemref);
+ break;
+ }
}
/* if things changed, update */
@@ -2478,6 +2496,9 @@ static void menu_cheat_populate(running_machine *machine, ui_menu *menu)
{
ui_menu_item_append(menu, text, subtext, flags, curcheat);
}
+
+ /* add a reset all option */
+ ui_menu_item_append(menu, "Reset All", NULL, 0, (void *)1);
}