Added the ability for devices to have their own custom inline config management.

This was primarily added to allow for sound routes to be supported in a way that
is compatible with the current driver structure. A device can now define a
DEVICE_CUSTOM_CONFIG callback which is called whenever one of the 
MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_* tokens is encountered. A special token
MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_FREE is defined to clean up memory allocated
and/or reset the custom configuration, and is called when the device is torn down
to allow for memory cleanup.

Reimplemented the sound routing using this new mechanism.
This commit is contained in:
Aaron Giles 2009-02-16 18:07:38 +00:00
parent 7c35019811
commit 51b90f0e85
8 changed files with 217 additions and 121 deletions

View File

@ -707,6 +707,10 @@ DEVICE_GET_INFO( cpu )
case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(cpu); break;
default:
/* if we don't have a device pointer, ignore everything else */
if (device == NULL)
break;
/* if we have a state pointer, we can handle some stuff for free */
if (device->token != NULL)
{

View File

@ -75,6 +75,7 @@ enum
DEVINFO_FCT_EXECUTE, /* R/O: device_execute_func */
DEVINFO_FCT_VALIDITY_CHECK, /* R/O: device_validity_check_func */
DEVINFO_FCT_NVRAM, /* R/O: device_nvram_func */
DEVINFO_FCT_CUSTOM_CONFIG, /* R/O: device_custom_config_func */
DEVINFO_FCT_CLASS_SPECIFIC = 0x24000, /* R/W: device-specific values start here */
DEVINFO_FCT_DEVICE_SPECIFIC = 0x28000, /* R/W: device-specific values start here */
@ -132,6 +133,10 @@ enum
#define DEVICE_VALIDITY_CHECK(name) int DEVICE_VALIDITY_CHECK_NAME(name)(const game_driver *driver, const device_config *device)
#define DEVICE_VALIDITY_CHECK_CALL(name) DEVICE_VALIDITY_CHECK(name)(driver, device)
#define DEVICE_CUSTOM_CONFIG_NAME(name) device_custom_config_##name
#define DEVICE_CUSTOM_CONFIG(name) const union _machine_config_token *DEVICE_CUSTOM_CONFIG_NAME(name)(const device_config *device, UINT32 entrytype, const union _machine_config_token *tokens)
#define DEVICE_CUSTOM_CONFIG_CALL(name) DEVICE_CUSTOM_CONFIG(name)(device, entrytype, tokens)
/* shorthand for accessing devices by machine/type/tag */
#define devtag_get_device(mach,type,tag) device_list_find_by_tag((mach)->config->devicelist, type, tag)
@ -191,6 +196,7 @@ typedef INT32 (*device_execute_func)(const device_config *device, INT32 clocks);
typedef void (*device_reset_func)(const device_config *device);
typedef void (*device_nvram_func)(const device_config *device, mame_file *file, int read_or_write);
typedef int (*device_validity_check_func)(const game_driver *driver, const device_config *device);
typedef const union _machine_config_token *(*device_custom_config_func)(const device_config *device, UINT32 entrytype, const union _machine_config_token *tokens);
/* a device_type is simply a pointer to its get_info function */
@ -211,6 +217,7 @@ union _deviceinfo
device_reset_func reset; /* DEVINFO_FCT_RESET */
device_execute_func execute; /* DEVINFO_FCT_EXECUTE */
device_validity_check_func validity_check; /* DEVINFO_FCT_VALIDITY_CHECK */
device_custom_config_func custom_config; /* DEVINFO_FCT_CUSTOM_CONFIG */
device_nvram_func nvram; /* DEVINFO_FCT_NVRAM */
const rom_entry * romregion; /* DEVINFO_PTR_ROM_REGION */
const union _machine_config_token *machine_config;/* DEVINFO_PTR_MACHINE_CONFIG */

View File

@ -27,6 +27,33 @@ static void machine_config_detokenize(machine_config *config, const machine_conf
/***************************************************************************
MACHINE CONFIGURATIONS
***************************************************************************/
/*-------------------------------------------------
remove_device - remove the head device from
the given configuration
-------------------------------------------------*/
INLINE void remove_device(device_config **listheadptr, device_type type, const char *tag)
{
device_config *device = (device_config *)device_list_find_by_tag(*listheadptr, type, tag);
device_custom_config_func custom;
assert(device != NULL);
/* call the custom config free function first */
custom = (device_custom_config_func)devtype_get_info_fct(device->type, DEVINFO_FCT_CUSTOM_CONFIG);
if (custom != NULL)
(*custom)(device, MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_FREE, NULL);
/* remove the device from the list */
device_list_remove(listheadptr, type, tag);
}
/***************************************************************************
MACHINE CONFIGURATIONS
***************************************************************************/
@ -60,7 +87,7 @@ void machine_config_free(machine_config *config)
{
/* release the device list */
while (config->devicelist != NULL)
device_list_remove(&config->devicelist, config->devicelist->type, config->devicelist->tag);
remove_device(&config->devicelist, config->devicelist->type, config->devicelist->tag);
/* release the configuration itself */
free(config);
@ -81,6 +108,7 @@ static void machine_config_detokenize(machine_config *config, const machine_conf
/* loop over tokens until we hit the end */
while (entrytype != MCONFIG_TOKEN_END)
{
device_custom_config_func custom;
int size, offset, bits;
UINT32 data32, clock;
device_type devtype;
@ -112,7 +140,7 @@ static void machine_config_detokenize(machine_config *config, const machine_conf
case MCONFIG_TOKEN_DEVICE_REMOVE:
devtype = TOKEN_GET_PTR(tokens, devtype);
tag = TOKEN_GET_STRING(tokens);
device_list_remove(&config->devicelist, devtype, device_build_tag(tempstring, owner, tag));
remove_device(&config->devicelist, devtype, device_build_tag(tempstring, owner, tag));
device = NULL;
break;
@ -134,11 +162,27 @@ static void machine_config_detokenize(machine_config *config, const machine_conf
assert(device != NULL);
device->static_config = TOKEN_GET_PTR(tokens, voidptr);
break;
case MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_1:
case MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_2:
case MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_3:
case MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_4:
case MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_5:
case MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_6:
case MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_7:
case MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_8:
case MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_9:
case MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_FREE:
assert(device != NULL);
custom = (device_custom_config_func)devtype_get_info_fct(device->type, DEVINFO_FCT_CUSTOM_CONFIG);
assert(custom != NULL);
tokens = (*custom)(device, entrytype, tokens);
break;
case MCONFIG_TOKEN_DEVICE_CONFIG_DATA32:
assert(device != NULL);
TOKEN_UNGET_UINT32(tokens);
TOKEN_GET_UINT32_UNPACK3(tokens, entrytype, 8, size, 6, offset, 12);
TOKEN_GET_UINT32_UNPACK3(tokens, entrytype, 8, size, 4, offset, 12);
data32 = TOKEN_GET_UINT32(tokens);
switch (size)
{
@ -151,7 +195,7 @@ static void machine_config_detokenize(machine_config *config, const machine_conf
case MCONFIG_TOKEN_DEVICE_CONFIG_DATA64:
assert(device != NULL);
TOKEN_UNGET_UINT32(tokens);
TOKEN_GET_UINT32_UNPACK3(tokens, entrytype, 8, size, 6, offset, 12);
TOKEN_GET_UINT32_UNPACK3(tokens, entrytype, 8, size, 4, offset, 12);
TOKEN_EXTRACT_UINT64(tokens, data64);
switch (size)
{
@ -165,7 +209,7 @@ static void machine_config_detokenize(machine_config *config, const machine_conf
case MCONFIG_TOKEN_DEVICE_CONFIG_DATAFP32:
assert(device != NULL);
TOKEN_UNGET_UINT32(tokens);
TOKEN_GET_UINT32_UNPACK4(tokens, entrytype, 8, size, 6, bits, 6, offset, 12);
TOKEN_GET_UINT32_UNPACK4(tokens, entrytype, 8, size, 4, bits, 6, offset, 12);
data32 = TOKEN_GET_UINT32(tokens);
switch (size)
{
@ -174,18 +218,6 @@ static void machine_config_detokenize(machine_config *config, const machine_conf
}
break;
case MCONFIG_TOKEN_DEVICE_CONFIG_DATAFP64:
assert(device != NULL);
TOKEN_UNGET_UINT32(tokens);
TOKEN_GET_UINT32_UNPACK4(tokens, entrytype, 8, size, 6, bits, 6, offset, 12);
TOKEN_EXTRACT_UINT64(tokens, data64);
switch (size)
{
case 4: *(float *)((UINT8 *)device->inline_config + offset) = (float)(INT64)data64 / (float)((UINT64)1 << bits); break;
case 8: *(double *)((UINT8 *)device->inline_config + offset) = (double)(INT64)data64 / (double)((UINT64)1 << bits); break;
}
break;
/* core parameters */
case MCONFIG_TOKEN_DRIVER_DATA:

View File

@ -37,14 +37,22 @@ enum
MCONFIG_TOKEN_DEVICE_ADD,
MCONFIG_TOKEN_DEVICE_REMOVE,
MCONFIG_TOKEN_DEVICE_REPLACE,
MCONFIG_TOKEN_DEVICE_MODIFY,
MCONFIG_TOKEN_DEVICE_CLOCK,
MCONFIG_TOKEN_DEVICE_CONFIG,
MCONFIG_TOKEN_DEVICE_CONFIG_DATA32,
MCONFIG_TOKEN_DEVICE_CONFIG_DATA64,
MCONFIG_TOKEN_DEVICE_CONFIG_DATAFP32,
MCONFIG_TOKEN_DEVICE_CONFIG_DATAFP64,
MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_1,
MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_2,
MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_3,
MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_4,
MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_5,
MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_6,
MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_7,
MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_8,
MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_9,
MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_FREE,
MCONFIG_TOKEN_DRIVER_DATA,
MCONFIG_TOKEN_QUANTUM_TIME,
@ -70,13 +78,6 @@ enum
MCONFIG_TOKEN_SOUND_START,
MCONFIG_TOKEN_SOUND_RESET,
MCONFIG_TOKEN_SOUND_ADD,
MCONFIG_TOKEN_SOUND_REMOVE,
MCONFIG_TOKEN_SOUND_MODIFY,
MCONFIG_TOKEN_SOUND_CONFIG,
MCONFIG_TOKEN_SOUND_REPLACE,
MCONFIG_TOKEN_SOUND_ROUTE,
};
@ -173,6 +174,9 @@ union _machine_config_token
};
/* helper macro for returning the size of a field within a struct; similar to offsetof() */
#define structsizeof(_struct, _field) sizeof(((_struct *)NULL)->_field)
/* start/end tags for the machine driver */
#define MACHINE_DRIVER_NAME(_name) \
@ -310,12 +314,10 @@ union _machine_config_token
#define MDRV_DEVICE_CLOCK(_clock) \
TOKEN_UINT64_PACK2(MCONFIG_TOKEN_DEVICE_CLOCK, 8, _clock, 32),
#define structsizeof(_struct, _field) sizeof(((_struct *)NULL)->_field)
/* inline device configurations that require 32 bits of storage in the token */
#define MDRV_DEVICE_CONFIG_DATA32_EXPLICIT(_size, _offset, _val) \
TOKEN_UINT32_PACK3(MCONFIG_TOKEN_DEVICE_CONFIG_DATA32, 8, _size, 6, _offset, 12), \
TOKEN_UINT32_PACK3(MCONFIG_TOKEN_DEVICE_CONFIG_DATA32, 8, _size, 4, _offset, 12), \
TOKEN_UINT32((UINT32)(_val)),
#define MDRV_DEVICE_CONFIG_DATA32(_struct, _field, _val) \
@ -330,7 +332,7 @@ union _machine_config_token
/* inline device configurations that require 32 bits of fixed-point storage in the token */
#define MDRV_DEVICE_CONFIG_DATAFP32_EXPLICIT(_size, _offset, _val, _fixbits) \
TOKEN_UINT32_PACK4(MCONFIG_TOKEN_DEVICE_CONFIG_DATAFP32, 8, _size, 6, _fixbits, 6, _offset, 12), \
TOKEN_UINT32_PACK4(MCONFIG_TOKEN_DEVICE_CONFIG_DATAFP32, 8, _size, 4, _fixbits, 6, _offset, 12), \
TOKEN_UINT32((INT32)((float)(_val) * (float)(1 << (_fixbits)))),
#define MDRV_DEVICE_CONFIG_DATAFP32(_struct, _field, _val, _fixbits) \
@ -345,7 +347,7 @@ union _machine_config_token
/* inline device configurations that require 64 bits of storage in the token */
#define MDRV_DEVICE_CONFIG_DATA64_EXPLICIT(_size, _offset, _val) \
TOKEN_UINT32_PACK3(MCONFIG_TOKEN_DEVICE_CONFIG_DATA64, 8, _size, 6, _offset, 12), \
TOKEN_UINT32_PACK3(MCONFIG_TOKEN_DEVICE_CONFIG_DATA64, 8, _size, 4, _offset, 12), \
TOKEN_UINT64((UINT64)(_val)),
#define MDRV_DEVICE_CONFIG_DATA64(_struct, _field, _val) \

View File

@ -317,6 +317,54 @@ static DEVICE_START( sound )
}
/*-------------------------------------------------
device_custom_config_sound - custom inline
config callback for populating sound routes
-------------------------------------------------*/
static DEVICE_CUSTOM_CONFIG( sound )
{
sound_config *config = device->inline_config;
switch (entrytype)
{
/* custom config 1 is a new route */
case MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_1:
{
sound_route **routeptr;
int output, input;
UINT32 gain;
/* put back the token that was originally fetched so we can grab a packed 64-bit token */
TOKEN_UNGET_UINT32(tokens);
TOKEN_GET_UINT64_UNPACK4(tokens, entrytype, 8, output, 12, input, 12, gain, 32);
/* allocate a new route */
for (routeptr = &config->routelist; *routeptr != NULL; routeptr = &(*routeptr)->next) ;
*routeptr = malloc_or_die(sizeof(**routeptr));
(*routeptr)->next = NULL;
(*routeptr)->output = output;
(*routeptr)->input = input;
(*routeptr)->gain = (float)gain * (1.0f / (float)(1 << 24));
(*routeptr)->target = TOKEN_GET_STRING(tokens);
break;
}
/* custom config free is also used as a reset of sound routes */
case MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_FREE:
while (config->routelist != NULL)
{
sound_route *temp = config->routelist;
config->routelist = temp->next;
free(temp);
}
break;
}
return tokens;
}
/*-------------------------------------------------
device_get_info_sound - device get info
callback
@ -340,6 +388,7 @@ DEVICE_GET_INFO( sound )
/* --- the following bits of info are returned as pointers to data or functions --- */
case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(sound); break;
case DEVINFO_FCT_SET_INFO: info->set_info = NULL; break;
case DEVINFO_FCT_CUSTOM_CONFIG: info->custom_config = DEVICE_CUSTOM_CONFIG_NAME(sound); break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case DEVINFO_STR_NAME:
@ -369,36 +418,30 @@ DEVICE_GET_INFO( sound )
static void route_sound(running_machine *machine)
{
astring *tempstring = astring_alloc();
int routenum, outputnum;
const device_config *curspeak;
const device_config *sound;
int outputnum;
/* first count up the inputs for each speaker */
for (sound = sound_first(machine->config); sound != NULL; sound = sound_next(sound))
{
const sound_config *config = sound->inline_config;
int numoutputs = stream_get_device_outputs(sound);
int numassigned = 0;
const sound_route *route;
/* iterate over all routes */
for (routenum = 0; routenum <= ALL_OUTPUTS; routenum++)
for (route = config->routelist; route != NULL; route = route->next)
{
const sound_route *mroute = &config->route[routenum];
if (mroute->target != NULL)
{
const device_config *target_speaker = devtag_get_device(machine, SPEAKER_OUTPUT, mroute->target);
const device_config *target_sound = devtag_get_device(machine, SOUND, mroute->target);
int numentries = (routenum != ALL_OUTPUTS) ? 1 : (numoutputs - numassigned);
/* if neither found, it's fatal */
if (target_speaker == NULL && target_sound == NULL)
fatalerror("Sound route \"%s\" not found!\n", mroute->target);
const device_config *target_speaker = devtag_get_device(machine, SPEAKER_OUTPUT, route->target);
const device_config *target_sound = devtag_get_device(machine, SOUND, route->target);
/* if neither found, it's fatal */
if (target_speaker == NULL && target_sound == NULL)
fatalerror("Sound route \"%s\" not found!\n", route->target);
/* if we got a speaker, bump its input count */
if (target_speaker != NULL)
get_safe_token(target_speaker)->inputs += numentries;
numassigned += numentries;
}
/* if we got a speaker, bump its input count */
if (target_speaker != NULL)
get_safe_token(target_speaker)->inputs += (route->output == ALL_OUTPUTS) ? numoutputs : 1;
}
}
@ -422,59 +465,52 @@ static void route_sound(running_machine *machine)
{
const sound_config *config = sound->inline_config;
int numoutputs = stream_get_device_outputs(sound);
UINT8 assigned[MAX_OUTPUTS] = { FALSE };
const sound_route *route;
/* iterate over all routes */
for (routenum = 0; routenum <= ALL_OUTPUTS; routenum++)
for (route = config->routelist; route != NULL; route = route->next)
{
const sound_route *mroute = &config->route[routenum];
if (mroute->target != NULL)
{
const device_config *target_speaker = devtag_get_device(machine, SPEAKER_OUTPUT, mroute->target);
const device_config *target_sound = devtag_get_device(machine, SOUND, mroute->target);
int inputnum = mroute->input;
sound_stream *stream;
int streamoutput;
const device_config *target_speaker = devtag_get_device(machine, SPEAKER_OUTPUT, route->target);
const device_config *target_sound = devtag_get_device(machine, SOUND, route->target);
int inputnum = route->input;
sound_stream *stream;
int streamoutput;
/* iterate over all outputs, matching any that apply */
for (outputnum = 0; outputnum < numoutputs; outputnum++)
if (routenum == outputnum || (routenum == ALL_OUTPUTS && !assigned[outputnum]))
/* iterate over all outputs, matching any that apply */
for (outputnum = 0; outputnum < numoutputs; outputnum++)
if (route->output == outputnum || route->output == ALL_OUTPUTS)
{
/* if it's a speaker, set the input */
if (target_speaker != NULL)
{
/* mark this output as assigned */
assigned[outputnum] = TRUE;
speaker_info *speakerinfo = get_safe_token(target_speaker);
/* if it's a speaker, set the input */
if (target_speaker != NULL)
{
speaker_info *speakerinfo = get_safe_token(target_speaker);
/* generate text for the UI */
astring_printf(tempstring, "Speaker '%s': %s '%s'", target_speaker->tag, device_get_name(sound), sound->tag);
if (numoutputs > 1)
astring_catprintf(tempstring, " Ch.%d", outputnum);
/* generate text for the UI */
astring_printf(tempstring, "Speaker '%s': %s '%s'", target_speaker->tag, device_get_name(sound), sound->tag);
if (numoutputs > 1)
astring_catprintf(tempstring, " Ch.%d", outputnum);
/* fill in the input data on this speaker */
speakerinfo->input[speakerinfo->inputs].gain = route->gain;
speakerinfo->input[speakerinfo->inputs].default_gain = route->gain;
speakerinfo->input[speakerinfo->inputs].name = auto_strdup(astring_c(tempstring));
/* fill in the input data on this speaker */
speakerinfo->input[speakerinfo->inputs].gain = mroute->gain;
speakerinfo->input[speakerinfo->inputs].default_gain = mroute->gain;
speakerinfo->input[speakerinfo->inputs].name = auto_strdup(astring_c(tempstring));
/* connect the output to the input */
if (stream_device_output_to_stream_output(sound, outputnum, &stream, &streamoutput))
stream_set_input(speakerinfo->mixer_stream, speakerinfo->inputs++, stream, streamoutput, mroute->gain);
}
/* otherwise, it's a sound chip */
else
{
sound_stream *inputstream;
int streaminput;
if (stream_device_input_to_stream_input(target_sound, inputnum++, &inputstream, &streaminput))
if (stream_device_output_to_stream_output(sound, outputnum, &stream, &streamoutput))
stream_set_input(inputstream, streaminput, stream, streamoutput, mroute->gain);
}
/* connect the output to the input */
if (stream_device_output_to_stream_output(sound, outputnum, &stream, &streamoutput))
stream_set_input(speakerinfo->mixer_stream, speakerinfo->inputs++, stream, streamoutput, route->gain);
}
}
/* otherwise, it's a sound chip */
else
{
sound_stream *inputstream;
int streaminput;
if (stream_device_input_to_stream_input(target_sound, inputnum++, &inputstream, &streaminput))
if (stream_device_output_to_stream_output(sound, outputnum, &stream, &streamoutput))
stream_set_input(inputstream, streaminput, stream, streamoutput, route->gain);
}
}
}
}

View File

@ -21,7 +21,7 @@
CONSTANTS
***************************************************************************/
#define MAX_OUTPUTS 256 /* maximum number of outputs a sound chip can support */
#define MAX_OUTPUTS 4095 /* maximum number of outputs a sound chip can support */
#define ALL_OUTPUTS (MAX_OUTPUTS) /* special value indicating all outputs for the current chip */
@ -56,8 +56,10 @@ typedef device_type sound_type;
typedef struct _sound_route sound_route;
struct _sound_route
{
const char * target; /* tag of the target */
int input; /* input ID, -1 is default behavior */
sound_route * next; /* pointer to next route */
UINT32 output; /* output index, or ALL_OUTPUTS */
const char * target; /* target tag */
UINT32 input; /* target input index */
float gain; /* gain */
};
@ -67,7 +69,7 @@ typedef struct _sound_config sound_config;
struct _sound_config
{
sound_type type; /* type of sound chip */
sound_route route[ALL_OUTPUTS+1]; /* one route per output */
sound_route * routelist; /* list of sound routes */
};
@ -104,19 +106,23 @@ struct _speaker_config
MDRV_DEVICE_MODIFY(_tag, SOUND) \
MDRV_DEVICE_CONFIG_CLEAR() \
MDRV_DEVICE_CONFIG_DATAPTR(sound_config, type, SOUND_##_type) \
MDRV_DEVICE_CLOCK(_clock)
MDRV_DEVICE_CLOCK(_clock) \
MDRV_SOUND_ROUTES_RESET()
#define MDRV_SOUND_CONFIG(_config) \
MDRV_DEVICE_CONFIG(_config)
/* sound routine is too complex for standard decoding, so we use a custom config */
#define MDRV_SOUND_ROUTE_EX(_output, _target, _gain, _input) \
MDRV_DEVICE_CONFIG_DATAPTR_ARRAY_MEMBER(sound_config, route, _output, sound_route, target, _target) \
MDRV_DEVICE_CONFIG_DATA32_ARRAY_MEMBER(sound_config, route, _output, sound_route, input, _input) \
MDRV_DEVICE_CONFIG_DATAFP32_ARRAY_MEMBER(sound_config, route, _output, sound_route, gain, _gain, 24)
TOKEN_UINT64_PACK4(MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_1, 8, _output, 12, _input, 12, ((float)(_gain) * (float)(1 << 24)), 32), \
TOKEN_PTR(stringptr, _target),
#define MDRV_SOUND_ROUTE(_output, _target, _gain) \
MDRV_SOUND_ROUTE_EX(_output, _target, _gain, 0)
#define MDRV_SOUND_ROUTES_RESET() \
TOKEN_UINT32_PACK1(MCONFIG_TOKEN_DEVICE_CONFIG_CUSTOM_FREE, 8),
/* add/remove speakers */

View File

@ -28,7 +28,7 @@
/***************************************************************************
MACROS
TYPE DEFINITIONS
***************************************************************************/
/* include this at the top of your union to get the standard fields */
@ -46,6 +46,19 @@
const INT64 * i64ptr; \
/* generic_token can be used when there are no particularly special types */
typedef struct _generic_token generic_token;
struct _generic_token
{
TOKEN_COMMON_FIELDS
};
/***************************************************************************
MACROS
***************************************************************************/
/* ----- compile-time token generation macros ----- */
/* GCC and C99 compilers can use designated initializers for type safety */

View File

@ -1498,32 +1498,28 @@ static int validate_sound(int drivnum, const machine_config *config)
for (cursound = sound_first(config); cursound != NULL; cursound = sound_next(cursound))
{
const sound_config *curconfig = cursound->inline_config;
int routenum;
const sound_route *route;
/* loop over all the routes */
for (routenum = 0; routenum <= ALL_OUTPUTS; routenum++)
for (route = curconfig->routelist; route != NULL; route = route->next)
{
const sound_route *mroute = &curconfig->route[routenum];
if (mroute->target != NULL)
/* find a speaker with the requested tag */
for (checkspeak = speaker_output_first(config); checkspeak != NULL; checkspeak = speaker_output_next(checkspeak))
if (strcmp(route->target, checkspeak->tag) == 0)
break;
/* if we didn't find one, look for another sound chip with the tag */
if (checkspeak == NULL)
{
/* find a speaker with the requested tag */
for (checkspeak = speaker_output_first(config); checkspeak != NULL; checkspeak = speaker_output_next(checkspeak))
if (strcmp(mroute->target, checkspeak->tag) == 0)
for (checksound = sound_first(config); checksound != NULL; checksound = sound_next(checksound))
if (checksound != cursound && strcmp(route->target, checksound->tag) == 0)
break;
/* if we didn't find one, look for another sound chip with the tag */
if (checkspeak == NULL)
/* if we didn't find one, it's an error */
if (checksound == NULL)
{
for (checksound = sound_first(config); checksound != NULL; checksound = sound_next(checksound))
if (checksound != cursound && strcmp(mroute->target, checksound->tag) == 0)
break;
/* if we didn't find one, it's an error */
if (checksound == NULL)
{
mame_printf_error("%s: %s attempting to route sound to non-existant speaker '%s'\n", driver->source_file, driver->name, mroute->target);
error = TRUE;
}
mame_printf_error("%s: %s attempting to route sound to non-existant speaker '%s'\n", driver->source_file, driver->name, route->target);
error = TRUE;
}
}
}