summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2008-05-25 21:24:19 +0000
committer Aaron Giles <aaron@aarongiles.com>2008-05-25 21:24:19 +0000
commit67db0742f0c043b09370964a04fc4e40e1a41c4e (patch)
tree0aa01ee6a3bd53bd7341024e54158e77f92db9cc
parent032c1ddaee9aead44279fe44f1cac63301a60628 (diff)
Added TOKEN_SKIP_* macros to tokenize.h.
Changed error reporting during input port detokenization to fill a buffer rather than fatalerror-ing immediately. Should now properly skip over any invalid tokens. Enhanced error detection during input port detokenization to catch duplicate bits. There are a lot of these! Updated initialization code to print errors and fatal only if the input ports were unable to be constructed at all.
-rw-r--r--src/emu/info.c2
-rw-r--r--src/emu/inptport.c364
-rw-r--r--src/emu/inptport.h2
-rw-r--r--src/emu/tokenize.h6
-rw-r--r--src/emu/validity.c5
5 files changed, 272 insertions, 107 deletions
diff --git a/src/emu/info.c b/src/emu/info.c
index 2503cecd59a..71f499f804b 100644
--- a/src/emu/info.c
+++ b/src/emu/info.c
@@ -846,7 +846,7 @@ static void print_game_info(FILE *out, const game_driver *game)
/* temporary hook until MESS device transition is complete */
mess_devices_setup(config, game);
#endif /* MESS */
- portconfig = input_port_config_alloc(game->ipt);
+ portconfig = input_port_config_alloc(game->ipt, NULL, 0);
/* print the header and the game name */
fprintf(out, "\t<" XML_TOP);
diff --git a/src/emu/inptport.c b/src/emu/inptport.c
index d2d901c3ab3..e42ca7b3cc7 100644
--- a/src/emu/inptport.c
+++ b/src/emu/inptport.c
@@ -101,6 +101,7 @@
#include "deprecat.h"
#include <ctype.h>
#include <time.h>
+#include <stdarg.h>
#ifdef MESS
#include "inputx.h"
@@ -481,7 +482,7 @@ static void frame_update_analog_field(analog_field_state *analog);
static int frame_get_digital_field_state(const input_field_config *field);
/* port configuration helpers */
-static input_port_config *port_config_detokenize(input_port_config *listhead, const input_port_token *ipt);
+static input_port_config *port_config_detokenize(input_port_config *listhead, const input_port_token *ipt, char *errorbuf, int errorbuflen);
static input_port_config *port_config_alloc(const input_port_config **listhead);
static void port_config_free(const input_port_config **portptr);
static input_port_config *port_config_find(const input_port_config *listhead, const char *tag);
@@ -489,7 +490,7 @@ static input_field_config *field_config_alloc(input_port_config *port, int type,
static void field_config_free(input_field_config **fieldptr);
static input_setting_config *setting_config_alloc(input_field_config *field, input_port_value value, const char *name);
static void setting_config_free(input_setting_config **settingptr);
-static const input_field_diplocation *diplocation_list_alloc(const input_field_config *field, const char *location);
+static const input_field_diplocation *diplocation_list_alloc(const input_field_config *field, const char *location, char *errorbuf, int errorbuflen);
static void diplocation_free(input_field_diplocation **diplocptr);
/* tokenization helpers */
@@ -596,6 +597,26 @@ INLINE int get_port_index(const input_port_config *portlist, const char *tag)
}
+/*-------------------------------------------------
+ error_buf_append - append text to an error
+ buffer
+-------------------------------------------------*/
+
+INLINE void *error_buf_append(char *errorbuf, int errorbuflen, const char *format, ...)
+{
+ int curlen = strlen(errorbuf);
+ int bytesleft = errorbuflen - curlen;
+ va_list va;
+
+ va_start(va, format);
+ if (strlen(format) + 25 < bytesleft)
+ vsprintf(&errorbuf[curlen], format, va);
+ va_end(va);
+
+ return NULL;
+}
+
+
/***************************************************************************
CORE SYSTEM MANAGEMENT
@@ -609,6 +630,7 @@ INLINE int get_port_index(const input_port_config *portlist, const char *tag)
time_t input_port_init(running_machine *machine, const input_port_token *tokens)
{
input_port_private *portdata;
+ char errorbuf[1024];
time_t basetime;
/* allocate memory for our data structure */
@@ -626,7 +648,11 @@ time_t input_port_init(running_machine *machine, const input_port_token *tokens)
/* if we have a token list, proceed */
if (tokens != NULL)
{
- machine->portconfig = input_port_config_alloc(tokens);
+ machine->portconfig = input_port_config_alloc(tokens, errorbuf, sizeof(errorbuf));
+ if (errorbuf[0] != 0)
+ mame_printf_error("Input port errors:\n%s", errorbuf);
+ if (machine->portconfig == NULL)
+ fatalerror("Unable to construct input ports!");
init_port_state(machine);
}
@@ -668,14 +694,16 @@ static void input_port_exit(running_machine *machine)
input ports from the given token list
-------------------------------------------------*/
-const input_port_config *input_port_config_alloc(const input_port_token *tokens)
+const input_port_config *input_port_config_alloc(const input_port_token *tokens, char *errorbuf, int errorbuflen)
{
- return port_config_detokenize(NULL, tokens);
+ if (errorbuf != NULL)
+ *errorbuf = 0;
+ return port_config_detokenize(NULL, tokens, errorbuf, errorbuflen);
}
/*-------------------------------------------------
- input_port_config_alloc - free memory
+ input_port_config_free - free memory
allocated from input_port_alloc
-------------------------------------------------*/
@@ -2312,12 +2340,13 @@ static int frame_get_digital_field_state(const input_field_config *field)
detokenize a series of input port tokens
-------------------------------------------------*/
-static input_port_config *port_config_detokenize(input_port_config *listhead, const input_port_token *ipt)
+static input_port_config *port_config_detokenize(input_port_config *listhead, const input_port_token *ipt, char *errorbuf, int errorbuflen)
{
UINT32 entrytype = INPUT_TOKEN_INVALID;
input_setting_config *cursetting = NULL;
input_field_config *curfield = NULL;
input_port_config *curport = NULL;
+ input_port_value maskbits = 0;
/* loop over tokens until we hit the end */
while (entrytype != INPUT_TOKEN_END)
@@ -2338,7 +2367,7 @@ static input_port_config *port_config_detokenize(input_port_config *listhead, co
/* including */
case INPUT_TOKEN_INCLUDE:
- listhead = port_config_detokenize(listhead, TOKEN_GET_PTR(ipt, tokenptr));
+ listhead = port_config_detokenize(listhead, TOKEN_GET_PTR(ipt, tokenptr), errorbuf, errorbuflen);
break;
/* start of a new input port */
@@ -2349,6 +2378,7 @@ static input_port_config *port_config_detokenize(input_port_config *listhead, co
curport->tag = TOKEN_GET_STRING(ipt);
curfield = NULL;
cursetting = NULL;
+ maskbits = 0;
break;
/* modify an existing port */
@@ -2358,23 +2388,30 @@ static input_port_config *port_config_detokenize(input_port_config *listhead, co
/* input field definition */
case INPUT_TOKEN_FIELD:
- if (curport == NULL)
- fatalerror("INPUT_TOKEN_FIELD encountered with no active port");
-
TOKEN_UNGET_UINT32(ipt);
TOKEN_GET_UINT32_UNPACK2(ipt, entrytype, 8, type, 24);
TOKEN_GET_UINT64_UNPACK2(ipt, mask, 32, defval, 32);
+ if (curport == NULL)
+ return error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_FIELD encountered with no active port (mask=%X defval=%X)\n", mask, defval);
+ if ((maskbits & mask) != 0)
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_FIELD specifies duplicate port bits (mask=%X)\n", mask);
+ maskbits |= mask;
+
curfield = field_config_alloc(curport, type, defval, mask);
cursetting = NULL;
break;
/* field or setting condition */
case INPUT_TOKEN_CONDITION:
- if (curfield == NULL && cursetting == NULL)
- fatalerror("INPUT_TOKEN_CONDITION encountered with no active field or setting");
-
TOKEN_UNGET_UINT32(ipt);
+ if (curfield == NULL && cursetting == NULL)
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_CONDITION encountered with no active field or setting\n");
+ TOKEN_SKIP_UINT32(ipt);
+ TOKEN_SKIP_UINT64(ipt);
+ break;
+ }
TOKEN_GET_UINT32_UNPACK2(ipt, entrytype, 8, condition.condition, 24);
TOKEN_GET_UINT64_UNPACK2(ipt, condition.mask, 32, condition.value, 32);
condition.tag = TOKEN_GET_STRING(ipt);
@@ -2395,74 +2432,108 @@ static input_port_config *port_config_detokenize(input_port_config *listhead, co
case INPUT_TOKEN_PLAYER7:
case INPUT_TOKEN_PLAYER8:
if (curfield == NULL)
- fatalerror("INPUT_TOKEN_PLAYERn encountered with no active field");
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_PLAYERn encountered with no active field\n");
+ break;
+ }
curfield->player = entrytype - INPUT_TOKEN_PLAYER1;
break;
/* field category */
case INPUT_TOKEN_CATEGORY:
- if (curfield == NULL)
- fatalerror("INPUT_TOKEN_CATEGORY encountered with no active field");
TOKEN_UNGET_UINT32(ipt);
+ if (curfield == NULL)
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_CATEGORY encountered with no active field\n");
+ TOKEN_SKIP_UINT32(ipt);
+ break;
+ }
TOKEN_GET_UINT32_UNPACK2(ipt, entrytype, 8, curfield->category, 24);
break;
/* field flags */
case INPUT_TOKEN_UNUSED:
if (curfield == NULL)
- fatalerror("INPUT_TOKEN_UNUSED encountered with no active field");
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_UNUSED encountered with no active field\n");
+ break;
+ }
curfield->flags |= FIELD_FLAG_UNUSED;
break;
case INPUT_TOKEN_COCKTAIL:
if (curfield == NULL)
- fatalerror("INPUT_TOKEN_COCKTAIL encountered with no active field");
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_COCKTAIL encountered with no active field\n");
+ break;
+ }
curfield->flags |= FIELD_FLAG_COCKTAIL;
curfield->player = 1;
break;
case INPUT_TOKEN_ROTATED:
if (curfield == NULL)
- fatalerror("INPUT_TOKEN_ROTATED encountered with no active field");
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_ROTATED encountered with no active field\n");
+ break;
+ }
curfield->flags |= FIELD_FLAG_ROTATED;
break;
case INPUT_TOKEN_TOGGLE:
if (curfield == NULL)
- fatalerror("INPUT_TOKEN_TOGGLE encountered with no active field");
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_TOGGLE encountered with no active field\n");
+ break;
+ }
curfield->flags |= FIELD_FLAG_TOGGLE;
break;
/* field impulse */
case INPUT_TOKEN_IMPULSE:
- if (curfield == NULL)
- fatalerror("INPUT_TOKEN_IMPULSE encountered with no active field");
TOKEN_UNGET_UINT32(ipt);
+ if (curfield == NULL)
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_IMPULSE encountered with no active field\n");
+ TOKEN_SKIP_UINT32(ipt);
+ break;
+ }
TOKEN_GET_UINT32_UNPACK2(ipt, entrytype, 8, curfield->impulse, 24);
break;
/* field name */
case INPUT_TOKEN_NAME:
if (curfield == NULL)
- fatalerror("INPUT_TOKEN_NAME encountered with no active field");
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_NAME encountered with no active field\n");
+ TOKEN_SKIP_STRING(ipt);
+ break;
+ }
curfield->name = input_port_string_from_token(*ipt++);
break;
/* field code sequence */
case INPUT_TOKEN_CODE:
- if (curfield == NULL)
- fatalerror("INPUT_TOKEN_CODE encountered with no active field");
-
TOKEN_UNGET_UINT32(ipt);
+ if (curfield == NULL)
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_CODE encountered with no active field\n");
+ TOKEN_SKIP_UINT64(ipt);
+ break;
+ }
TOKEN_GET_UINT64_UNPACK2(ipt, entrytype, 8, val, 32);
-
input_seq_append_or(&curfield->seq[SEQ_TYPE_STANDARD], val);
break;
/* field custom callback */
case INPUT_TOKEN_CUSTOM:
if (curfield == NULL)
- fatalerror("INPUT_TOKEN_CUSTOM encountered with no active field");
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_CUSTOM encountered with no active field\n");
+ TOKEN_SKIP_PTR(ipt);
+ TOKEN_SKIP_PTR(ipt);
+ break;
+ }
curfield->custom = TOKEN_GET_PTR(ipt, customptr);
curfield->custom_param = (void *)TOKEN_GET_PTR(ipt, voidptr);
break;
@@ -2470,7 +2541,12 @@ static input_port_config *port_config_detokenize(input_port_config *listhead, co
/* field changed callback */
case INPUT_TOKEN_CHANGED:
if (curfield == NULL)
- fatalerror("INPUT_TOKEN_CHANGED encountered with no active field");
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_CHANGED encountered with no active field\n");
+ TOKEN_SKIP_PTR(ipt);
+ TOKEN_SKIP_PTR(ipt);
+ break;
+ }
curfield->changed = TOKEN_GET_PTR(ipt, changedptr);
curfield->changed_param = (void *)TOKEN_GET_PTR(ipt, voidptr);
break;
@@ -2478,8 +2554,12 @@ static input_port_config *port_config_detokenize(input_port_config *listhead, co
/* DIP switch location */
case INPUT_TOKEN_DIPLOCATION:
if (curfield == NULL)
- fatalerror("INPUT_TOKEN_DIPLOCATION encountered with no active field");
- curfield->diploclist = diplocation_list_alloc(curfield, TOKEN_GET_STRING(ipt));
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_DIPLOCATION encountered with no active field\n");
+ TOKEN_SKIP_STRING(ipt);
+ break;
+ }
+ curfield->diploclist = diplocation_list_alloc(curfield, TOKEN_GET_STRING(ipt), errorbuf, errorbuflen);
break;
/* joystick flags */
@@ -2488,18 +2568,23 @@ static input_port_config *port_config_detokenize(input_port_config *listhead, co
case INPUT_TOKEN_8WAY:
case INPUT_TOKEN_16WAY:
if (curfield == NULL)
- fatalerror("INPUT_TOKEN_nWAY encountered with no active field");
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_nWAY encountered with no active field\n");
+ break;
+ }
curfield->way = 2 << (entrytype - INPUT_TOKEN_2WAY);
break;
/* (MESS) natural keyboard support */
case INPUT_TOKEN_CHAR:
- if (curfield == NULL)
- fatalerror("INPUT_TOKEN_CHAR encountered with no active field");
-
TOKEN_UNGET_UINT32(ipt);
+ if (curfield == NULL)
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_CHAR encountered with no active field\n");
+ TOKEN_SKIP_UINT64(ipt);
+ break;
+ }
TOKEN_GET_UINT64_UNPACK2(ipt, entrytype, 8, val, 32);
-
for (index = 0; index < ARRAY_LENGTH(curfield->chars); index++)
if (curfield->chars[index] == 0)
{
@@ -2511,69 +2596,97 @@ static input_port_config *port_config_detokenize(input_port_config *listhead, co
/* analog minimum/maximum */
case INPUT_TOKEN_MINMAX:
if (curfield == NULL)
- fatalerror("INPUT_TOKEN_MINMAX encountered with no active field");
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_MINMAX encountered with no active field\n");
+ TOKEN_SKIP_UINT64(ipt);
+ break;
+ }
TOKEN_GET_UINT64_UNPACK2(ipt, curfield->min, 32, curfield->max, 32);
break;
/* analog sensitivity */
case INPUT_TOKEN_SENSITIVITY:
- if (curfield == NULL)
- fatalerror("INPUT_TOKEN_SENSITIVITY encountered with no active field");
TOKEN_UNGET_UINT32(ipt);
+ if (curfield == NULL)
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_SENSITIVITY encountered with no active field\n");
+ TOKEN_SKIP_UINT32(ipt);
+ break;
+ }
TOKEN_GET_UINT32_UNPACK2(ipt, entrytype, 8, curfield->sensitivity, 24);
break;
/* analog keyboard delta */
case INPUT_TOKEN_KEYDELTA:
- if (curfield == NULL)
- fatalerror("INPUT_TOKEN_KEYDELTA encountered with no active field");
TOKEN_UNGET_UINT32(ipt);
+ if (curfield == NULL)
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_KEYDELTA encountered with no active field\n");
+ TOKEN_SKIP_UINT32(ipt);
+ break;
+ }
TOKEN_GET_UINT32_UNPACK2(ipt, entrytype, 8, curfield->delta, -24);
curfield->centerdelta = curfield->delta;
break;
/* analog autocenter delta */
case INPUT_TOKEN_CENTERDELTA:
- if (curfield == NULL)
- fatalerror("INPUT_TOKEN_CENTERDELTA encountered with no active field");
TOKEN_UNGET_UINT32(ipt);
+ if (curfield == NULL)
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_CENTERDELTA encountered with no active field\n");
+ TOKEN_SKIP_UINT32(ipt);
+ break;
+ }
TOKEN_GET_UINT32_UNPACK2(ipt, entrytype, 8, curfield->centerdelta, -24);
break;
/* analog reverse flags */
case INPUT_TOKEN_REVERSE:
if (curfield == NULL)
- fatalerror("INPUT_TOKEN_REVERSE encountered with no active field");
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_REVERSE encountered with no active field\n");
+ break;
+ }
curfield->flags |= ANALOG_FLAG_REVERSE;
break;
case INPUT_TOKEN_RESET:
if (curfield == NULL)
- fatalerror("INPUT_TOKEN_RESET encountered with no active field");
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_RESET encountered with no active field\n");
+ break;
+ }
curfield->flags |= ANALOG_FLAG_RESET;
break;
case INPUT_TOKEN_WRAPS:
if (curfield == NULL)
- fatalerror("INPUT_TOKEN_WRAPS encountered with no active field");
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_WRAPS encountered with no active field\n");
curfield->flags |= ANALOG_FLAG_WRAPS;
break;
case INPUT_TOKEN_INVERT:
if (curfield == NULL)
- fatalerror("INPUT_TOKEN_INVERT encountered with no active field");
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_INVERT encountered with no active field\n");
+ break;
+ }
curfield->flags |= ANALOG_FLAG_INVERT;
break;
/* analog crosshair parameters */
case INPUT_TOKEN_CROSSHAIR:
- if (curfield == NULL)
- fatalerror("INPUT_TOKEN_CROSSHAIR encountered with no active field");
-
TOKEN_UNGET_UINT32(ipt);
+ if (curfield == NULL)
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_CROSSHAIR encountered with no active field\n");
+ TOKEN_SKIP_UINT32(ipt);
+ TOKEN_SKIP_UINT64(ipt);
+ break;
+ }
TOKEN_GET_UINT32_UNPACK3(ipt, entrytype, 8, curfield->crossaxis, 4, curfield->crossaltaxis, -20);
TOKEN_GET_UINT64_UNPACK2(ipt, curfield->crossscale, -32, curfield->crossoffset, -32);
-
curfield->crossaltaxis *= 1.0f / 65536.0f;
curfield->crossscale *= 1.0f / 65536.0f;
curfield->crossoffset *= 1.0f / 65536.0f;
@@ -2581,83 +2694,110 @@ static input_port_config *port_config_detokenize(input_port_config *listhead, co
/* analog decrement sequence */
case INPUT_TOKEN_CODE_DEC:
+ TOKEN_UNGET_UINT32(ipt);
if (curfield == NULL)
- fatalerror("INPUT_TOKEN_CODE_DEC encountered with no active field");
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_CODE_DEC encountered with no active field\n");
+ TOKEN_SKIP_UINT64(ipt);
+ break;
+ }
index = entrytype - INPUT_TOKEN_CODE;
-
- TOKEN_UNGET_UINT32(ipt);
TOKEN_GET_UINT64_UNPACK2(ipt, entrytype, 8, val, 32);
-
input_seq_append_or(&curfield->seq[SEQ_TYPE_DECREMENT], val);
break;
/* analog increment sequence */
case INPUT_TOKEN_CODE_INC:
+ TOKEN_UNGET_UINT32(ipt);
if (curfield == NULL)
- fatalerror("INPUT_TOKEN_CODE_INC encountered with no active field");
+ {
+ TOKEN_SKIP_UINT64(ipt);
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_CODE_INC encountered with no active field\n");
+ break;
+ }
index = entrytype - INPUT_TOKEN_CODE;
-
- TOKEN_UNGET_UINT32(ipt);
TOKEN_GET_UINT64_UNPACK2(ipt, entrytype, 8, val, 32);
-
input_seq_append_or(&curfield->seq[SEQ_TYPE_INCREMENT], val);
break;
/* analog wraps flag */
case INPUT_TOKEN_FULL_TURN_COUNT:
- if (curfield == NULL)
- fatalerror("INPUT_TOKEN_FULL_TURN_COUNT encountered with no active field");
TOKEN_UNGET_UINT32(ipt);
+ if (curfield == NULL)
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_FULL_TURN_COUNT encountered with no active field\n");
+ TOKEN_SKIP_UINT32(ipt);
+ break;
+ }
TOKEN_GET_UINT32_UNPACK2(ipt, entrytype, 8, curfield->full_turn_count, 24);
break;
case INPUT_TOKEN_POSITIONS:
- if (curfield == NULL)
- fatalerror("INPUT_TOKEN_POSITIONS encountered with no active field");
TOKEN_UNGET_UINT32(ipt);
+ if (curfield == NULL)
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_POSITIONS encountered with no active field\n");
+ TOKEN_SKIP_UINT32(ipt);
+ break;
+ }
TOKEN_GET_UINT32_UNPACK2(ipt, entrytype, 8, curfield->max, 24);
break;
case INPUT_TOKEN_REMAP_TABLE:
if (curfield == NULL)
- fatalerror("INPUT_TOKEN_REMAP_TABLE encountered with no active field");
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_REMAP_TABLE encountered with no active field\n");
+ TOKEN_SKIP_PTR(ipt);
+ break;
+ }
curfield->remap_table = TOKEN_GET_PTR(ipt, ui32ptr);
break;
/* DIP switch definition */
case INPUT_TOKEN_DIPNAME:
if (curport == NULL)
- fatalerror("INPUT_TOKEN_DIPNAME encountered with no active port");
-
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_DIPNAME encountered with no active port\n");
+ TOKEN_SKIP_UINT64(ipt);
+ TOKEN_SKIP_STRING(ipt);
+ break;
+ }
TOKEN_GET_UINT64_UNPACK2(ipt, mask, 32, defval, 32);
-
curfield = field_config_alloc(curport, IPT_DIPSWITCH, defval, mask);
cursetting = NULL;
-
curfield->name = input_port_string_from_token(*ipt++);
break;
/* DIP switch setting */
case INPUT_TOKEN_DIPSETTING:
- if (curfield == NULL)
- fatalerror("INPUT_TOKEN_DIPSETTING encountered with no active field");
-
TOKEN_UNGET_UINT32(ipt);
+ if (curfield == NULL)
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_DIPSETTING encountered with no active field\n");
+ TOKEN_SKIP_UINT64(ipt);
+ TOKEN_SKIP_STRING(ipt);
+ break;
+ }
TOKEN_GET_UINT64_UNPACK2(ipt, entrytype, 8, defval, 32);
-
cursetting = setting_config_alloc(curfield, defval & curfield->mask, input_port_string_from_token(*ipt++));
break;
/* special DIP switch with on/off values */
case INPUT_TOKEN_SPECIAL_ONOFF:
- if (curport == NULL)
- fatalerror("INPUT_TOKEN_SPECIAL_ONOFF encountered with no active port");
-
TOKEN_UNGET_UINT32(ipt);
TOKEN_GET_UINT32_UNPACK3(ipt, entrytype, 8, hasdiploc, 1, temptoken.i, 23);
TOKEN_GET_UINT64_UNPACK2(ipt, mask, 32, defval, 32);
+ if (curport == NULL)
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_SPECIAL_ONOFF encountered with no active port\n");
+ TOKEN_SKIP_UINT32(ipt);
+ TOKEN_SKIP_UINT64(ipt);
+ if (hasdiploc)
+ TOKEN_SKIP_STRING(ipt);
+ break;
+ }
curfield = field_config_alloc(curport, IPT_DIPSWITCH, defval, mask);
cursetting = NULL;
@@ -2668,7 +2808,7 @@ static input_port_config *port_config_detokenize(input_port_config *listhead, co
curfield->seq[SEQ_TYPE_STANDARD].code[0] = KEYCODE_F2;
}
if (hasdiploc)
- curfield->diploclist = diplocation_list_alloc(curfield, TOKEN_GET_STRING(ipt));
+ curfield->diploclist = diplocation_list_alloc(curfield, TOKEN_GET_STRING(ipt), errorbuf, errorbuflen);
temptoken.i = INPUT_STRING_Off;
cursetting = setting_config_alloc(curfield, defval & mask, input_port_string_from_token(temptoken));
@@ -2680,67 +2820,79 @@ static input_port_config *port_config_detokenize(input_port_config *listhead, co
/* configuration definition */
case INPUT_TOKEN_CONFNAME:
if (curport == NULL)
- fatalerror("INPUT_TOKEN_CONFNAME encountered with no active port");
-
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_CONFNAME encountered with no active port\n");
+ TOKEN_SKIP_UINT64(ipt);
+ TOKEN_SKIP_STRING(ipt);
+ break;
+ }
TOKEN_GET_UINT64_UNPACK2(ipt, mask, 32, defval, 32);
-
curfield = field_config_alloc(curport, IPT_CONFIG, defval, mask);
cursetting = NULL;
-
curfield->name = input_port_string_from_token(*ipt++);
break;
/* configuration setting */
case INPUT_TOKEN_CONFSETTING:
- if (curfield == NULL)
- fatalerror("INPUT_TOKEN_CONFSETTING encountered with no active field");
-
TOKEN_UNGET_UINT32(ipt);
+ if (curfield == NULL)
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_CONFSETTING encountered with no active field\n");
+ TOKEN_SKIP_UINT64(ipt);
+ TOKEN_SKIP_STRING(ipt);
+ break;
+ }
TOKEN_GET_UINT64_UNPACK2(ipt, entrytype, 8, defval, 32);
-
cursetting = setting_config_alloc(curfield, defval & curfield->mask, input_port_string_from_token(*ipt++));
break;
/* configuration definition */
case INPUT_TOKEN_CATEGORY_NAME:
if (curport == NULL)
- fatalerror("INPUT_TOKEN_CATEGORY_NAME encountered with no active port");
-
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_CATEGORY_NAME encountered with no active port\n");
+ TOKEN_SKIP_UINT64(ipt);
+ TOKEN_SKIP_STRING(ipt);
+ break;
+ }
TOKEN_GET_UINT64_UNPACK2(ipt, mask, 32, defval, 32);
-
curfield = field_config_alloc(curport, IPT_CATEGORY, defval, mask);
cursetting = NULL;
-
curfield->name = input_port_string_from_token(*ipt++);
break;
/* configuration setting */
case INPUT_TOKEN_CATEGORY_SETTING:
- if (curfield == NULL)
- fatalerror("INPUT_TOKEN_CATEGORY_SETTING encountered with no active field");
-
TOKEN_UNGET_UINT32(ipt);
+ if (curfield == NULL)
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_CATEGORY_SETTING encountered with no active field\n");
+ TOKEN_SKIP_UINT64(ipt);
+ TOKEN_SKIP_STRING(ipt);
+ break;
+ }
TOKEN_GET_UINT64_UNPACK2(ipt, entrytype, 8, defval, 32);
-
cursetting = setting_config_alloc(curfield, defval & curfield->mask, input_port_string_from_token(*ipt++));
break;
/* analog adjuster definition */
case INPUT_TOKEN_ADJUSTER:
- if (curport == NULL)
- fatalerror("INPUT_TOKEN_ADJUSTER encountered with no active port");
-
TOKEN_UNGET_UINT32(ipt);
+ if (curport == NULL)
+ {
+ error_buf_append(errorbuf, errorbuflen, "INPUT_TOKEN_ADJUSTER encountered with no active port\n");
+ TOKEN_SKIP_UINT64(ipt);
+ TOKEN_SKIP_STRING(ipt);
+ break;
+ }
TOKEN_GET_UINT64_UNPACK2(ipt, entrytype, 8, defval, 32);
-
curfield = field_config_alloc(curport, IPT_ADJUSTER, defval, 0xff);
cursetting = NULL;
-
curfield->name = TOKEN_GET_STRING(ipt);
break;
default:
- fatalerror("Invalid token %d in input ports\n", entrytype);
+ error_buf_append(errorbuf, errorbuflen, "Invalid token %d in input ports\n", entrytype);
break;
}
}
@@ -2949,7 +3101,7 @@ static void setting_config_free(input_setting_config **settingptr)
descriptions
-------------------------------------------------*/
-static const input_field_diplocation *diplocation_list_alloc(const input_field_config *field, const char *location)
+static const input_field_diplocation *diplocation_list_alloc(const input_field_config *field, const char *location, char *errorbuf, int errorbuflen)
{
input_field_diplocation *head = NULL;
input_field_diplocation **tailptr = &head;
@@ -3001,7 +3153,10 @@ static const input_field_diplocation *diplocation_list_alloc(const input_field_c
{
char *namecopy;
if (lastname == NULL)
- fatalerror("Switch location '%s' missing switch name!", location);
+ {
+ error_buf_append(errorbuf, errorbuflen, "Switch location '%s' missing switch name!\n", location);
+ lastname = (char *)"UNK";
+ }
(*tailptr)->swname = namecopy = malloc_or_die(strlen(lastname) + 1);
strcpy(namecopy, lastname);
}
@@ -3016,8 +3171,9 @@ static const input_field_diplocation *diplocation_list_alloc(const input_field_c
/* now scan the switch number */
if (sscanf(number, "%d", &val) != 1)
- fatalerror("Switch location '%s' has invalid format!", location);
- (*tailptr)->swnum = val;
+ error_buf_append(errorbuf, errorbuflen, "Switch location '%s' has invalid format!\n", location);
+ else
+ (*tailptr)->swnum = val;
/* advance to the next item */
curentry = comma;
@@ -3030,7 +3186,7 @@ static const input_field_diplocation *diplocation_list_alloc(const input_field_c
for (bits = 0, temp = field->mask; temp != 0 && bits < 32; bits++)
temp &= temp - 1;
if (bits != entries)
- fatalerror("Switch location '%s' does not describe enough bits for mask %X\n", location, field->mask);
+ error_buf_append(errorbuf, errorbuflen, "Switch location '%s' does not describe enough bits for mask %X\n", location, field->mask);
return head;
}
diff --git a/src/emu/inptport.h b/src/emu/inptport.h
index 546fdbedced..286fe5dd61f 100644
--- a/src/emu/inptport.h
+++ b/src/emu/inptport.h
@@ -936,7 +936,7 @@ time_t input_port_init(running_machine *machine, const input_port_token *tokens)
/* ----- port configurations ----- */
/* allocate a list of input ports from the given token list */
-const input_port_config *input_port_config_alloc(const input_port_token *tokens);
+const input_port_config *input_port_config_alloc(const input_port_token *tokens, char *errorbuf, int errorbuflen);
/* free memory allocated from input_port_alloc */
void input_port_config_free(const input_port_config *portlist);
diff --git a/src/emu/tokenize.h b/src/emu/tokenize.h
index f9e85f862b8..aaff8a6f73b 100644
--- a/src/emu/tokenize.h
+++ b/src/emu/tokenize.h
@@ -128,6 +128,12 @@
#define TOKEN_UNGET_UINT32(tp) ((tp)--)
#define TOKEN_UNGET_UINT64(tp) ((tp) -= 8 / sizeof(FPTR))
+/* token skip primitives */
+#define TOKEN_SKIP_PTR(tp) ((tp)++)
+#define TOKEN_SKIP_STRING(tp) ((tp)++)
+#define TOKEN_SKIP_UINT32(tp) ((tp)++)
+#define TOKEN_SKIP_UINT64(tp) ((tp) += 8 / sizeof(FPTR))
+
/* extract a value from a fixed number of bits; if bits is negative, treat it as a signed value */
#define UNSHIFT_AND_MASK32(src, val, bits, shift) do { \
if ((bits) < 0) \
diff --git a/src/emu/validity.c b/src/emu/validity.c
index f48031edc2b..b0141747d1d 100644
--- a/src/emu/validity.c
+++ b/src/emu/validity.c
@@ -1190,6 +1190,7 @@ static int validate_inputs(int drivnum, const machine_config *config)
const input_field_config *field;
const game_driver *driver = drivers[drivnum];
int empty_string_found = FALSE;
+ char errorbuf[1024];
quark_entry *entry;
int error = FALSE;
UINT32 crc;
@@ -1208,7 +1209,9 @@ static int validate_inputs(int drivnum, const machine_config *config)
quark_add(inputs_table, drivnum, crc);
/* allocate the input ports */
- portlist = input_port_config_alloc(driver->ipt);
+ portlist = input_port_config_alloc(driver->ipt, errorbuf, sizeof(errorbuf));
+ if (errorbuf[0] != 0)
+ mame_printf_error("%s: %s has input port errors:\n%s\n", driver->source_file, driver->name, errorbuf);
/* check for duplicate tags */
for (port = portlist; port != NULL; port = port->next)