diff --git a/src/emu/sound/disc_inp.c b/src/emu/sound/disc_inp.c index 52882a8d8fc..8258d6b3fd4 100644 --- a/src/emu/sound/disc_inp.c +++ b/src/emu/sound/disc_inp.c @@ -31,6 +31,18 @@ struct dss_adjustment_context double scale; }; +struct dss_input_context +{ + stream_sample_t *ptr; /* current in ptr for stream */ + UINT8 data; /* data written */ + double gain; /* node gain */ + double offset; /* node offset */ + UINT8 is_stream; + UINT8 is_buffered; + UINT32 stream_in_number; + UINT32 stream_out_number; +}; + INLINE discrete_info *get_safe_token(const device_config *device) { assert(device != NULL); @@ -50,14 +62,14 @@ READ8_DEVICE_HANDLER(discrete_sound_r) /* Read the node input value if allowed */ if (node) { - UINT8 *node_data = (UINT8 *)node->context; + struct dss_input_context *context = (struct dss_input_context *)node->context; /* Bring the system up to now */ stream_update(info->discrete_stream); if ((node->module->type >= DSS_INPUT_DATA) && (node->module->type <= DSS_INPUT_PULSE)) { - data = *node_data; + data = context->data; } } else @@ -75,8 +87,7 @@ WRITE8_DEVICE_HANDLER(discrete_sound_w) /* Update the node input value if it's a proper input node */ if (node) { - UINT8 *node_data = (UINT8 *)node->context; - UINT8 last_data = *node_data; + struct dss_input_context *context = (struct dss_input_context *)node->context; UINT8 new_data = 0; switch (node->module->type) @@ -93,15 +104,15 @@ WRITE8_DEVICE_HANDLER(discrete_sound_w) break; } - if (last_data != new_data) + if (context->data != new_data) { /* Bring the system up to now */ stream_update(info->discrete_stream); - *node_data = new_data; + context->data = new_data; /* Update the node output here so we don't have to do it each step */ - node->output[0] = *node_data * DSS_INPUT__GAIN + DSS_INPUT__OFFSET; + node->output[0] = new_data * context->gain + context->offset; } } else @@ -217,33 +228,38 @@ static DISCRETE_RESET(dss_constant) ************************************************************************/ static DISCRETE_RESET(dss_input) { - UINT8 *node_data = (UINT8 *)node->context; + struct dss_input_context *context = (struct dss_input_context *)node->context; + + context->is_buffered = FALSE; + context->is_stream = FALSE; + context->gain = DSS_INPUT__GAIN; + context->offset = DSS_INPUT__OFFSET; switch (node->module->type) { case DSS_INPUT_DATA: - *node_data = DSS_INPUT__INIT; + context->data = DSS_INPUT__INIT; break; case DSS_INPUT_LOGIC: case DSS_INPUT_PULSE: - *node_data = (DSS_INPUT__INIT == 0) ? 0 : 1; + context->data = (DSS_INPUT__INIT == 0) ? 0 : 1; break; case DSS_INPUT_NOT: - *node_data = (DSS_INPUT__INIT == 0) ? 1 : 0; + context->data = (DSS_INPUT__INIT == 0) ? 1 : 0; break; } - node->output[0] = *node_data * DSS_INPUT__GAIN + DSS_INPUT__OFFSET; + node->output[0] = context->data * context->gain + context->offset; } static DISCRETE_STEP(dss_input_pulse) { - UINT8 *node_data = (UINT8 *)node->context; + struct dss_input_context *context = (struct dss_input_context *)node->context; /* Set a valid output */ - node->output[0] = *node_data; + node->output[0] = context->data; /* Reset the input to default for the next cycle */ /* node order is now important */ - *node_data = DSS_INPUT__INIT; + context->data = DSS_INPUT__INIT; } @@ -263,13 +279,12 @@ static DISCRETE_STEP(dss_input_pulse) static DISCRETE_STEP(dss_input_stream) { /* the context pointer is set to point to the current input stream data in discrete_stream_update */ - stream_sample_t **ptr = (stream_sample_t **)node->context; - stream_sample_t *data = *ptr; + struct dss_input_context *context = (struct dss_input_context *)node->context; - if (data) + if (context->ptr) { - node->output[0] = (*data) * DSS_INPUT_STREAM__GAIN + DSS_INPUT_STREAM__OFFSET; - (*ptr)++; + node->output[0] = (*context->ptr) * context->gain + context->offset; + context->ptr++; } else node->output[0] = 0; @@ -277,8 +292,13 @@ static DISCRETE_STEP(dss_input_stream) static DISCRETE_RESET(dss_input_stream) { - int istream = DSS_INPUT_STREAM__STREAM; - /* we will use the node's context pointer to point to the input stream data */ - assert(istream < node->info->discrete_input_streams); - node->context = (discrete_info *) &node->info->input_stream_data[istream]; + struct dss_input_context *context = (struct dss_input_context *)node->context; + + assert(DSS_INPUT_STREAM__STREAM < linked_list_count(node->info->input_list)); + context->is_buffered = FALSE; + context->is_stream = TRUE; + context->stream_in_number = DSS_INPUT_STREAM__STREAM; + context->gain = DSS_INPUT_STREAM__GAIN; + context->offset = DSS_INPUT_STREAM__OFFSET; + context->ptr = NULL; } diff --git a/src/emu/sound/discrete.c b/src/emu/sound/discrete.c index 1657043e922..c7e35012339 100644 --- a/src/emu/sound/discrete.c +++ b/src/emu/sound/discrete.c @@ -169,6 +169,39 @@ static DISCRETE_RESET( dso_output ) /* nothing to do - just avoid being stepped */ } + +/************************************* + * + * Add an entry to a list + * + *************************************/ + +static void linked_list_add(discrete_info *info, linked_list_entry ***list_tail_ptr, void *ptr) +{ + **list_tail_ptr = auto_alloc(info->device->machine, linked_list_entry); + (**list_tail_ptr)->ptr = ptr; + (**list_tail_ptr)->next = NULL; + *list_tail_ptr = &((**list_tail_ptr)->next); +} + +/************************************* + * + * Count entries in a list + * + *************************************/ + +static int linked_list_count(linked_list_entry *list) +{ + int cnt = 0; + linked_list_entry *entry; + + for (entry = list; entry != NULL; entry = entry->next) + cnt++; + + return cnt; +} + + /************************************* * * Included simulation objects @@ -191,7 +224,7 @@ static DISCRETE_RESET( dso_output ) static const discrete_module module_list[] = { - { DSO_OUTPUT ,"DSO_OUTPUT" , 0 ,sizeof(0) ,dso_output_reset ,dso_output_step }, + { DSO_OUTPUT ,"DSO_OUTPUT" , 0 ,0 ,dso_output_reset ,dso_output_step }, { DSO_CSVLOG ,"DSO_CSVLOG" , 0 ,0 ,NULL ,NULL }, { DSO_WAVELOG ,"DSO_WAVELOG" , 0 ,0 ,NULL ,NULL }, { DSO_IMPORT ,"DSO_IMPORT" , 0 ,0 ,NULL ,NULL }, @@ -207,11 +240,11 @@ static const discrete_module module_list[] = /* from disc_inp.c */ { DSS_ADJUSTMENT ,"DSS_ADJUSTMENT" , 1 ,sizeof(struct dss_adjustment_context) ,dss_adjustment_reset ,dss_adjustment_step }, { DSS_CONSTANT ,"DSS_CONSTANT" , 1 ,0 ,dss_constant_reset ,NULL }, - { DSS_INPUT_DATA ,"DSS_INPUT_DATA" , 1 ,sizeof(UINT8) ,dss_input_reset ,NULL }, - { DSS_INPUT_LOGIC ,"DSS_INPUT_LOGIC" , 1 ,sizeof(UINT8) ,dss_input_reset ,NULL }, - { DSS_INPUT_NOT ,"DSS_INPUT_NOT" , 1 ,sizeof(UINT8) ,dss_input_reset ,NULL }, - { DSS_INPUT_PULSE ,"DSS_INPUT_PULSE" , 1 ,sizeof(UINT8) ,dss_input_reset ,dss_input_pulse_step }, - { DSS_INPUT_STREAM,"DSS_INPUT_STREAM", 1 ,0 ,dss_input_stream_reset,dss_input_stream_step}, + { DSS_INPUT_DATA ,"DSS_INPUT_DATA" , 1 ,sizeof(struct dss_input_context) ,dss_input_reset ,NULL }, + { DSS_INPUT_LOGIC ,"DSS_INPUT_LOGIC" , 1 ,sizeof(struct dss_input_context) ,dss_input_reset ,NULL }, + { DSS_INPUT_NOT ,"DSS_INPUT_NOT" , 1 ,sizeof(struct dss_input_context) ,dss_input_reset ,NULL }, + { DSS_INPUT_PULSE ,"DSS_INPUT_PULSE" , 1 ,sizeof(struct dss_input_context) ,dss_input_reset ,dss_input_pulse_step }, + { DSS_INPUT_STREAM,"DSS_INPUT_STREAM", 1 ,sizeof(struct dss_input_context) ,dss_input_stream_reset,dss_input_stream_step}, /* from disc_wav.c */ /* Generic modules */ @@ -304,20 +337,6 @@ static const discrete_module module_list[] = { DSS_NULL ,"DSS_NULL" , 0 ,0 ,NULL ,NULL } }; -/************************************* - * - * Add an entry to a list - * - *************************************/ - -static void add_list(discrete_info *info, linked_list_entry ***list, void *ptr) -{ - **list = auto_alloc(info->device->machine, linked_list_entry); - (**list)->ptr = ptr; - (**list)->next = NULL; - *list = &((**list)->next); -} - /************************************* * * Find a given node @@ -396,7 +415,7 @@ static void discrete_build_list(discrete_info *info, discrete_sound_block *intf, else { discrete_log(info, "discrete_build_list() - adding node %d (*current %p)\n", node_count, *current); - add_list(info, current, &intf[node_count]); + linked_list_add(info, current, &intf[node_count]); } node_count++; @@ -482,6 +501,8 @@ static DEVICE_START( discrete ) /* Start with empty lists */ info->node_list = NULL; info->step_list = NULL; + info->output_list = NULL; + info->input_list = NULL; /* allocate memory to hold pointers to nodes by index */ info->indexed_node = auto_alloc_array_clear(device->machine, node_description *, DISCRETE_MAX_NODES); @@ -494,7 +515,7 @@ static DEVICE_START( discrete ) /* then set up the output nodes */ /* initialize the stream(s) */ - info->discrete_stream = stream_create(device, info->discrete_input_streams, info->discrete_outputs, info->sample_rate, info, discrete_stream_update); + info->discrete_stream = stream_create(device,linked_list_count(info->input_list), linked_list_count(info->output_list), info->sample_rate, info, discrete_stream_update); /* allocate a queue */ @@ -749,22 +770,22 @@ static STREAM_UPDATE( discrete_stream_update ) { discrete_info *info = (discrete_info *)param; linked_list_entry *entry; - int samplenum, nodenum, outputnum; - //int j; int left; int run; + int samplenum, outputnum; if (samples == 0) return; /* Setup any output streams */ - for (outputnum = 0; outputnum < info->discrete_outputs; outputnum++) + for (entry = info->output_list, outputnum = 0; entry != NULL; entry = entry->next, outputnum++) { - info->output_node[outputnum]->context = (void *) outputs[outputnum]; + ((node_description *) entry->ptr)->context = (void *) outputs[outputnum]; } /* Setup any input streams */ - for (nodenum = 0; nodenum < info->discrete_input_streams; nodenum++) + for (entry = info->input_list; entry != NULL; entry = entry->next) { - info->input_stream_data[nodenum] = inputs[nodenum]; + struct dss_input_context *context = (struct dss_input_context *) ((node_description *) entry->ptr)->context; + context->ptr = (void *) inputs[context->stream_in_number]; } for (entry = info->task_list; entry != 0; entry = entry->next) @@ -812,17 +833,15 @@ static STREAM_UPDATE( discrete_stream_update ) static void init_nodes(discrete_info *info, linked_list_entry *block_list, const device_config *device) { - linked_list_entry **step_list = &info->step_list; - linked_list_entry **node_list = &info->node_list; - linked_list_entry **task_list = &info->task_list; linked_list_entry **cur_task_node = NULL; linked_list_entry *entry; discrete_task_context *task = NULL; - - /* start with no outputs or input streams */ - - info->discrete_outputs = 0; - info->discrete_input_streams = 0; + /* list tail pointers */ + linked_list_entry **step_list = &info->step_list; + linked_list_entry **node_list = &info->node_list; + linked_list_entry **task_list = &info->task_list; + linked_list_entry **output_list = &info->output_list; + linked_list_entry **input_list = &info->input_list; /* loop over all nodes */ for (entry = block_list; entry != NULL; entry = entry->next) @@ -854,9 +873,7 @@ static void init_nodes(discrete_info *info, linked_list_entry *block_list, const { /* Output Node */ case DSO_OUTPUT: - if (info->discrete_outputs == DISCRETE_MAX_OUTPUTS) - fatalerror("init_nodes() - There can not be more then %d output nodes", DISCRETE_MAX_OUTPUTS); - info->output_node[info->discrete_outputs++] = node; + linked_list_add(info, &output_list, node); break; /* CSVlog Node for debugging */ @@ -878,7 +895,7 @@ static void init_nodes(discrete_info *info, linked_list_entry *block_list, const if (cur_task_node != NULL) fatalerror("init_nodes() - Nested DISCRETE_START_TASK."); task = auto_alloc_clear(info->device->machine, discrete_task_context); - add_list(info, &task_list, task); + linked_list_add(info, &task_list, task); cur_task_node = &task->list; break; @@ -924,15 +941,11 @@ static void init_nodes(discrete_info *info, linked_list_entry *block_list, const /* if we are an stream input node, track that */ if (block->type == DSS_INPUT_STREAM) { - if (info->discrete_input_streams == DISCRETE_MAX_OUTPUTS) - fatalerror("init_nodes() - There can not be more then %d input stream nodes", DISCRETE_MAX_OUTPUTS); - - node->context = NULL; - info->discrete_input_streams++; + linked_list_add(info, &input_list, node); } /* add to node list */ - add_list(info, &node_list, node); + linked_list_add(info, &node_list, node); /* our running order just follows the order specified */ /* does the node step ? */ @@ -940,9 +953,9 @@ static void init_nodes(discrete_info *info, linked_list_entry *block_list, const { /* do we belong to a task? */ if (cur_task_node == NULL) - add_list(info, &step_list, node); + linked_list_add(info, &step_list, node); else - add_list(info, &cur_task_node, node); + linked_list_add(info, &cur_task_node, node); } if (block->type == DSO_TASK_END) @@ -956,7 +969,7 @@ static void init_nodes(discrete_info *info, linked_list_entry *block_list, const } /* if no outputs, give an error */ - if (info->discrete_outputs == 0) + if (linked_list_count(info->output_list) == 0) fatalerror("init_nodes() - Couldn't find an output node"); } diff --git a/src/emu/sound/discrete.h b/src/emu/sound/discrete.h index 4f629ee5dff..4c208bd3842 100644 --- a/src/emu/sound/discrete.h +++ b/src/emu/sound/discrete.h @@ -438,8 +438,12 @@ * Note: The discrete system is floating point based. So when routing a stream * set it's gain to 100% and then use DISCRETE_INPUTX_STREAM to adjust * it if needed. + * If you need to access a stream from a discrete task, the stream node + * must be part of that task. If a given stream is used in two tasks or + * a task and the main task, you must declare two stream nodes acccessing the + * same stream input NUM. * - * EXAMPLES: see + * EXAMPLES: see scramble, frogger * *********************************************************************** ======================================================================= @@ -3371,10 +3375,9 @@ #define DISCRETE_MAX_NODES 300 #define DISCRETE_MAX_INPUTS 10 -#define DISCRETE_MAX_OUTPUTS 16 #define DISCRETE_MAX_WAVELOGS 10 #define DISCRETE_MAX_CSVLOGS 10 -#define DISCRETE_MAX_NODE_OUTPUTS 8 +#define DISCRETE_MAX_OUTPUTS 8 /************************************* @@ -3625,7 +3628,7 @@ struct _discrete_module struct _node_description { int node; /* The node's index number in the node list */ - double output[DISCRETE_MAX_NODE_OUTPUTS]; /* The node's last output value */ + double output[DISCRETE_MAX_OUTPUTS]; /* The node's last output value */ int active_inputs; /* Number of active inputs on this node type */ int input_is_node; /* Bit Flags. 1 in bit location means input_is_node */ @@ -3667,7 +3670,6 @@ struct _discrete_task_context double *ptr; double node_buf[2048]; double **dest; - volatile INT32 active; }; struct _discrete_info @@ -3695,12 +3697,10 @@ struct _discrete_info linked_list_entry *task_list; /* discrete_task_context * */ /* the input streams */ - int discrete_input_streams; - stream_sample_t *input_stream_data[DISCRETE_MAX_OUTPUTS]; + linked_list_entry *input_list; /* output node tracking */ - int discrete_outputs; - node_description *output_node[DISCRETE_MAX_OUTPUTS]; + linked_list_entry *output_list; /* the output stream */ sound_stream *discrete_stream; @@ -4024,10 +4024,10 @@ struct _discrete_inverter_osc_desc * *************************************/ -#define NODE0_DEF(_x) NODE_ ## 0 ## _x = (0x40000000 + (_x) * DISCRETE_MAX_NODE_OUTPUTS), \ +#define NODE0_DEF(_x) NODE_ ## 0 ## _x = (0x40000000 + (_x) * DISCRETE_MAX_OUTPUTS), \ NODE_ ## 0 ## _x ## _01, NODE_ ## 0 ## _x ## _02, NODE_ ## 0 ## _x ## _03, NODE_ ## 0 ## _x ## _04, \ NODE_ ## 0 ## _x ## _05, NODE_ ## 0 ## _x ## _06, NODE_ ## 0 ## _x ## _07 -#define NODE_DEF(_x) NODE_ ## _x = (0x40000000 + (_x) * DISCRETE_MAX_NODE_OUTPUTS), \ +#define NODE_DEF(_x) NODE_ ## _x = (0x40000000 + (_x) * DISCRETE_MAX_OUTPUTS), \ NODE_ ## _x ## _01, NODE_ ## _x ## _02, NODE_ ## _x ## _03, NODE_ ## _x ## _04, \ NODE_ ## _x ## _05, NODE_ ## _x ## _06, NODE_ ## _x ## _07 @@ -4066,15 +4066,15 @@ enum { /* Some Pre-defined nodes for convenience */ -#define NODE(_x) (NODE_00 + (_x) * DISCRETE_MAX_NODE_OUTPUTS) +#define NODE(_x) (NODE_00 + (_x) * DISCRETE_MAX_OUTPUTS) #define NODE_SUB(_x, _y) (NODE(_x) + (_y)) -#if DISCRETE_MAX_NODE_OUTPUTS == 8 +#if DISCRETE_MAX_OUTPUTS == 8 #define NODE_CHILD_NODE_NUM(_x) ((int)(_x) & 7) #define NODE_DEFAULT_NODE(_x) ((int)(_x) & ~7) #define NODE_INDEX(_x) (((int)(_x) - NODE_START)>>3) #else -#error "DISCRETE_MAX_NODE_OUTPUTS != 8" +#error "DISCRETE_MAX_OUTPUTS != 8" #endif #define NODE_RELATIVE(_x, _y) (NODE(NODE_INDEX(_x) + (_y)))