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.
This commit is contained in:
Aaron Giles 2008-08-07 15:53:58 +00:00
parent 3107dc2dff
commit 9df01a2896
7 changed files with 232 additions and 55 deletions

View File

@ -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";
@ -373,6 +382,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)
{

View File

@ -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);

View File

@ -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
};
@ -2572,6 +2574,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

View File

@ -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";
}
}

View File

@ -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

View File

@ -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)
{

View File

@ -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);
}