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.
This commit is contained in:
Aaron Giles 2008-05-25 21:24:19 +00:00
parent 032c1ddaee
commit 67db0742f0
5 changed files with 274 additions and 109 deletions

View File

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

View File

@ -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:
if (curfield == NULL)
fatalerror("INPUT_TOKEN_CODE_DEC encountered with no active field");
index = entrytype - INPUT_TOKEN_CODE;
TOKEN_UNGET_UINT32(ipt);
if (curfield == NULL)
{
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_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:
if (curfield == NULL)
fatalerror("INPUT_TOKEN_CODE_INC encountered with no active field");
index = entrytype - INPUT_TOKEN_CODE;
TOKEN_UNGET_UINT32(ipt);
if (curfield == NULL)
{
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_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,7 +3171,8 @@ 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);
error_buf_append(errorbuf, errorbuflen, "Switch location '%s' has invalid format!\n", location);
else
(*tailptr)->swnum = val;
/* advance to the next item */
@ -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;
}

View File

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

View File

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

View File

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