summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2009-02-16 18:07:38 +0000
committer Aaron Giles <aaron@aarongiles.com>2009-02-16 18:07:38 +0000
commit51b90f0e859a484c7f8408bed297b3928de5be34 (patch)
treed5706a7221f5442700b2f5c971492a950190d72d
parent7c350198118dadcf373f5fc0d209683138904644 (diff)
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.
-rw-r--r--src/emu/cpuexec.c4
-rw-r--r--src/emu/devintrf.h7
-rw-r--r--src/emu/mconfig.c66
-rw-r--r--src/emu/mconfig.h30
-rw-r--r--src/emu/sound.c162
-rw-r--r--src/emu/sound.h22
-rw-r--r--src/emu/tokenize.h15
-rw-r--r--src/emu/validity.c34
8 files changed, 218 insertions, 122 deletions
diff --git a/src/emu/cpuexec.c b/src/emu/cpuexec.c
index fa709823692..08f4fe9e241 100644
--- a/src/emu/cpuexec.c
+++ b/src/emu/cpuexec.c
@@ -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)
{
diff --git a/src/emu/devintrf.h b/src/emu/devintrf.h
index 203e432c30c..06027ab3d09 100644
--- a/src/emu/devintrf.h
+++ b/src/emu/devintrf.h
@@ -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 */
diff --git a/src/emu/mconfig.c b/src/emu/mconfig.c
index a93e17a92a2..01118f1a679 100644
--- a/src/emu/mconfig.c
+++ b/src/emu/mconfig.c
@@ -32,6 +32,33 @@ static void machine_config_detokenize(machine_config *config, const machine_conf
***************************************************************************/
/*-------------------------------------------------
+ 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
+***************************************************************************/
+
+/*-------------------------------------------------
machine_config_alloc - allocate a new
machine configuration and populate it using
the supplied constructor
@@ -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:
diff --git a/src/emu/mconfig.h b/src/emu/mconfig.h
index e0ca465edf5..3671a023051 100644
--- a/src/emu/mconfig.h
+++ b/src/emu/mconfig.h
@@ -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) \
diff --git a/src/emu/sound.c b/src/emu/sound.c
index 3b22fc2b9f5..33cf0a18cd4 100644
--- a/src/emu/sound.c
+++ b/src/emu/sound.c
@@ -318,6 +318,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);
-
- /* if we got a speaker, bump its input count */
- if (target_speaker != NULL)
- get_safe_token(target_speaker)->inputs += numentries;
- numassigned += numentries;
- }
+ 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 += (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;
-
- /* iterate over all outputs, matching any that apply */
- for (outputnum = 0; outputnum < numoutputs; outputnum++)
- if (routenum == outputnum || (routenum == ALL_OUTPUTS && !assigned[outputnum]))
+ 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 (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;
-
- /* if it's a speaker, set the input */
- if (target_speaker != NULL)
- {
- speaker_info *speakerinfo = get_safe_token(target_speaker);
+ 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 = mroute->gain;
- speakerinfo->input[speakerinfo->inputs].default_gain = mroute->gain;
- speakerinfo->input[speakerinfo->inputs].name = auto_strdup(astring_c(tempstring));
+ /* 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));
- /* 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);
- }
+ /* 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;
- /* 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);
- }
+ 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);
}
- }
+ }
}
}
diff --git a/src/emu/sound.h b/src/emu/sound.h
index 2f57ae6c040..48ebafe097a 100644
--- a/src/emu/sound.h
+++ b/src/emu/sound.h
@@ -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 */
diff --git a/src/emu/tokenize.h b/src/emu/tokenize.h
index aaff8a6f73b..82152411938 100644
--- a/src/emu/tokenize.h
+++ b/src/emu/tokenize.h
@@ -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 */
diff --git a/src/emu/validity.c b/src/emu/validity.c
index 1302f0f72bb..b88278fba5e 100644
--- a/src/emu/validity.c
+++ b/src/emu/validity.c
@@ -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;
}
}
}