mirror of
https://github.com/holub/mame
synced 2025-05-14 09:58:14 +03:00
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:
parent
032c1ddaee
commit
67db0742f0
@ -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);
|
||||
|
@ -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,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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) \
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user