~ubuntu-branches/ubuntu/lucid/sdlmame/lucid

« back to all changes in this revision

Viewing changes to src/emu/sound/discrete.c

  • Committer: Bazaar Package Importer
  • Author(s): Cesare Falco
  • Date: 2009-11-03 17:10:15 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20091103171015-6hop4ory5lxnumpn
Tags: 0.135-0ubuntu1
* New upstream release - Closes (LP: #403212)
* debian/watch: unstable releases are no longer detected
* mame.ini: added the cheat subdirectories to cheatpath so zipped
  cheatfiles will be searched too
* renamed crsshair subdirectory to crosshair to reflect upstream change
* mame.ini: renamed references to crosshair subdirectory (see above)

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 * file. All discrete sound primatives MUST implement the following
20
20
 * API:
21
21
 *
22
 
 * dsX_NAME_step(inputs, context,float timestep)  - Perform time step
 
22
 * dsX_NAME_step(inputs, context, float timestep)  - Perform time step
23
23
 *                                                  return output value
24
24
 * dsX_NAME_reset(context) - Reset to initial state
25
25
 *
38
38
#include "inptport.h"
39
39
#include "wavwrite.h"
40
40
#include "discrete.h"
41
 
 
 
41
#include "eminline.h"
 
42
 
 
43
/*************************************
 
44
 *
 
45
 *  Performance
 
46
 *
 
47
 *************************************/
 
48
 
 
49
/*
 
50
 * Normally, the discrete core processes 960 samples per update.
 
51
 * With the various buffers involved, this on a Core2 is not as
 
52
 * performant as processing 240 samples 4 times.
 
53
 * The setting most probably depends on CPU and which modules are
 
54
 * run and how many tasks are defined.
 
55
 *
 
56
 * Values < 32 exhibit poor performance (too much overhead) while
 
57
 * Values > 500 have a slightly worse performace (too much cache misses?).
 
58
 */
 
59
 
 
60
#define MAX_SAMPLES_PER_TASK_SLICE      (240)
42
61
 
43
62
/*************************************
44
63
 *
51
70
 
52
71
/*************************************
53
72
 *
54
 
 *  Global variables
 
73
 *  Profiling Nodes
55
74
 *
56
75
 *************************************/
57
76
 
58
 
discrete_info *discrete_current_context = NULL;
59
 
 
60
 
 
 
77
#define DISCRETE_PROFILING                      (0)
61
78
 
62
79
/*************************************
63
80
 *
65
82
 *
66
83
 *************************************/
67
84
 
68
 
static void init_nodes(discrete_info *info, discrete_sound_block *block_list, const device_config *device);
69
 
static void find_input_nodes(discrete_info *info, discrete_sound_block *block_list);
70
 
static void setup_output_nodes(const device_config *device, discrete_info *info);
71
 
static void setup_disc_logs(discrete_info *info);
 
85
static void init_nodes(discrete_info *info, const linked_list_entry *block_list, const device_config *device);
 
86
static void find_input_nodes(const discrete_info *info);
 
87
static node_description *discrete_find_node(const discrete_info *info, int node);
72
88
static DEVICE_RESET( discrete );
73
 
 
74
 
 
 
89
static STREAM_UPDATE( discrete_stream_update );
 
90
static STREAM_UPDATE( buffer_stream_update );
 
91
 
 
92
static int profiling = 0;
75
93
 
76
94
/*************************************
77
95
 *
79
97
 *
80
98
 *************************************/
81
99
 
82
 
static void CLIB_DECL ATTR_PRINTF(1,2) discrete_log(const char *text, ...)
 
100
static void CLIB_DECL ATTR_PRINTF(2,3) discrete_log(const discrete_info *disc_info, const char *text, ...)
83
101
{
84
102
        if (DISCRETE_DEBUGLOG)
85
103
        {
86
104
                va_list arg;
87
105
                va_start(arg, text);
88
106
 
89
 
                if(discrete_current_context->disclogfile)
 
107
                if(disc_info->disclogfile)
90
108
                {
91
 
                        vfprintf(discrete_current_context->disclogfile, text, arg);
92
 
                        fprintf(discrete_current_context->disclogfile, "\n");
 
109
                        vfprintf(disc_info->disclogfile, text, arg);
 
110
                        fprintf(disc_info->disclogfile, "\n");
 
111
                        fflush(disc_info->disclogfile);
93
112
                }
94
113
 
95
114
                va_end(arg);
96
115
        }
97
116
}
98
117
 
99
 
 
 
118
/*************************************
 
119
 *
 
120
 *  INLINEs
 
121
 *
 
122
 *************************************/
 
123
 
 
124
INLINE int node_module_index(const node_description *node)
 
125
{
 
126
        linked_list_entry *entry;
 
127
        int index = 0;
 
128
 
 
129
        for (entry = node->info->node_list; entry != NULL; entry = entry->next)
 
130
        {
 
131
                node_description *n = (node_description *) entry->ptr;
 
132
 
 
133
                if (n == node)
 
134
                        return index;
 
135
                if (n->module->type == node->module->type)
 
136
                        index++;
 
137
        }
 
138
        return -1;
 
139
}
 
140
 
 
141
INLINE void linked_list_tail_add(const discrete_info *info, linked_list_entry ***list_tail_ptr, const void *ptr)
 
142
{
 
143
        **list_tail_ptr = auto_alloc(info->device->machine, linked_list_entry);
 
144
        (**list_tail_ptr)->ptr = ptr;
 
145
        (**list_tail_ptr)->next = NULL;
 
146
        *list_tail_ptr = &((**list_tail_ptr)->next);
 
147
}
 
148
 
 
149
INLINE int linked_list_count(const linked_list_entry *list)
 
150
{
 
151
        int cnt = 0;
 
152
        const linked_list_entry *entry;
 
153
 
 
154
        for (entry = list; entry != NULL; entry = entry->next)
 
155
                cnt++;
 
156
 
 
157
        return cnt;
 
158
}
 
159
 
 
160
INLINE void linked_list_add(const discrete_info *info, linked_list_entry **list, const void *ptr)
 
161
{
 
162
        linked_list_entry *entry;
 
163
 
 
164
        if (*list == NULL)
 
165
        {
 
166
                *list = auto_alloc(info->device->machine, linked_list_entry);
 
167
                (*list)->ptr = ptr;
 
168
                (*list)->next = NULL;
 
169
        }
 
170
        else
 
171
        {
 
172
                for (entry = *list; entry != NULL && entry->next != NULL; entry = entry->next)
 
173
                        ;
 
174
                entry->next = auto_alloc(info->device->machine, linked_list_entry);
 
175
                entry->next->ptr = ptr;
 
176
                entry->next->next = NULL;
 
177
        }
 
178
}
100
179
 
101
180
/*************************************
102
181
 *
104
183
 *
105
184
 *************************************/
106
185
 
 
186
#include "disc_sys.c"           /* discrete core modules and support functions */
107
187
#include "disc_wav.c"           /* Wave sources   - SINE/SQUARE/NOISE/etc */
108
188
#include "disc_mth.c"           /* Math Devices   - ADD/GAIN/etc */
109
189
#include "disc_inp.c"           /* Input Devices  - INPUT/CONST/etc */
120
200
 
121
201
static const discrete_module module_list[] =
122
202
{
123
 
        { DSO_OUTPUT      ,"DSO_OUTPUT"      , 0 ,0                                      ,NULL                  ,NULL                 },
124
 
        { DSO_CSVLOG      ,"DSO_CSVLOG"      , 0 ,0                                      ,NULL                  ,NULL                 },
125
 
        { DSO_WAVELOG     ,"DSO_WAVELOG"     , 0 ,0                                      ,NULL                  ,NULL                 },
 
203
        { DSO_OUTPUT      ,"DSO_OUTPUT"      , 0 ,0                                      ,dso_output_reset      ,dso_output_step      ,NULL                  ,NULL                 },
 
204
        { DSO_CSVLOG      ,"DSO_CSVLOG"      , 0 ,sizeof(struct dso_csvlog_context)      ,NULL                  ,dso_csvlog_step      ,dso_csvlog_start      ,dso_csvlog_stop      },
 
205
        { DSO_WAVELOG     ,"DSO_WAVELOG"     , 0 ,sizeof(struct dso_wavelog_context)     ,NULL                  ,dso_wavelog_step     ,dso_wavelog_start     ,dso_wavelog_stop     },
 
206
        { DSO_IMPORT      ,"DSO_IMPORT"      , 0 ,0                                      ,NULL                  ,NULL                 ,NULL                  ,NULL                 },
 
207
 
 
208
        /* parallel modules */
 
209
        { DSO_TASK_START  ,"DSO_TASK_START"  , 0 ,0                                      ,dso_task_reset        ,dso_task_start_step  ,dso_task_start_start  ,NULL                 },
 
210
        { DSO_TASK_END    ,"DSO_TASK_END"    , 0 ,0                                      ,dso_task_reset        ,dso_task_end_step    ,NULL                  ,NULL                 },
 
211
        { DSO_TASK_SYNC   ,"DSO_TASK_SYNC"   , 0 ,0                                      ,NULL                  ,NULL                 ,NULL                  ,NULL                 },
 
212
 
 
213
        /* nop */
 
214
        { DSS_NOP         ,"DSS_NOP"         , 0 ,0                                      ,NULL                  ,NULL                 ,NULL                  ,NULL                 },
126
215
 
127
216
        /* from disc_inp.c */
128
 
        { DSS_ADJUSTMENT  ,"DSS_ADJUSTMENT"  , 1 ,sizeof(struct dss_adjustment_context)  ,dss_adjustment_reset  ,dss_adjustment_step  },
129
 
        { DSS_CONSTANT    ,"DSS_CONSTANT"    , 1 ,0                                      ,dss_constant_reset    ,NULL                 },
130
 
        { DSS_INPUT_DATA  ,"DSS_INPUT_DATA"  , 1 ,sizeof(UINT8)                          ,dss_input_reset       ,NULL                 },
131
 
        { DSS_INPUT_LOGIC ,"DSS_INPUT_LOGIC" , 1 ,sizeof(UINT8)                          ,dss_input_reset       ,NULL                 },
132
 
        { DSS_INPUT_NOT   ,"DSS_INPUT_NOT"   , 1 ,sizeof(UINT8)                          ,dss_input_reset       ,NULL                 },
133
 
        { DSS_INPUT_PULSE ,"DSS_INPUT_PULSE" , 1 ,sizeof(UINT8)                          ,dss_input_reset       ,dss_input_pulse_step },
134
 
        { DSS_INPUT_STREAM,"DSS_INPUT_STREAM", 1 ,0                                      ,dss_input_stream_reset,dss_input_stream_step},
 
217
        { DSS_ADJUSTMENT  ,"DSS_ADJUSTMENT"  , 1 ,sizeof(struct dss_adjustment_context)  ,dss_adjustment_reset  ,dss_adjustment_step  ,NULL                  ,NULL                 },
 
218
        { DSS_CONSTANT    ,"DSS_CONSTANT"    , 1 ,0                                      ,dss_constant_reset    ,NULL                 ,NULL                  ,NULL                 },
 
219
        { DSS_INPUT_DATA  ,"DSS_INPUT_DATA"  , 1 ,sizeof(struct dss_input_context)       ,dss_input_reset       ,NULL                 ,NULL                  ,NULL                 },
 
220
        { DSS_INPUT_LOGIC ,"DSS_INPUT_LOGIC" , 1 ,sizeof(struct dss_input_context)       ,dss_input_reset       ,NULL                 ,NULL                  ,NULL                 },
 
221
        { DSS_INPUT_NOT   ,"DSS_INPUT_NOT"   , 1 ,sizeof(struct dss_input_context)       ,dss_input_reset       ,NULL                 ,NULL                  ,NULL                 },
 
222
        { DSS_INPUT_PULSE ,"DSS_INPUT_PULSE" , 1 ,sizeof(struct dss_input_context)       ,dss_input_reset       ,dss_input_pulse_step ,NULL                  ,NULL                 },
 
223
        { DSS_INPUT_STREAM,"DSS_INPUT_STREAM", 1 ,sizeof(struct dss_input_context)       ,dss_input_stream_reset,dss_input_stream_step,dss_input_stream_start,NULL                 },
 
224
        { DSS_INPUT_BUFFER,"DSS_INPUT_BUFFER", 1 ,sizeof(struct dss_input_context)       ,dss_input_stream_reset,dss_input_stream_step,dss_input_stream_start,NULL                 },
135
225
 
136
226
        /* from disc_wav.c */
137
227
        /* Generic modules */
138
 
        { DSS_COUNTER     ,"DSS_COUNTER"     , 1 ,sizeof(struct dss_counter_context)     ,dss_counter_reset     ,dss_counter_step     },
139
 
        { DSS_LFSR_NOISE  ,"DSS_LFSR_NOISE"  , 1 ,sizeof(struct dss_lfsr_context)        ,dss_lfsr_reset        ,dss_lfsr_step        },
140
 
        { DSS_NOISE       ,"DSS_NOISE"       , 1 ,sizeof(struct dss_noise_context)       ,dss_noise_reset       ,dss_noise_step       },
141
 
        { DSS_NOTE        ,"DSS_NOTE"        , 1 ,sizeof(struct dss_note_context)        ,dss_note_reset        ,dss_note_step        },
142
 
        { DSS_SAWTOOTHWAVE,"DSS_SAWTOOTHWAVE", 1 ,sizeof(struct dss_sawtoothwave_context),dss_sawtoothwave_reset,dss_sawtoothwave_step},
143
 
        { DSS_SINEWAVE    ,"DSS_SINEWAVE"    , 1 ,sizeof(struct dss_sinewave_context)    ,dss_sinewave_reset    ,dss_sinewave_step    },
144
 
        { DSS_SQUAREWAVE  ,"DSS_SQUAREWAVE"  , 1 ,sizeof(struct dss_squarewave_context)  ,dss_squarewave_reset  ,dss_squarewave_step  },
145
 
        { DSS_SQUAREWFIX  ,"DSS_SQUAREWFIX"  , 1 ,sizeof(struct dss_squarewfix_context)  ,dss_squarewfix_reset  ,dss_squarewfix_step  },
146
 
        { DSS_SQUAREWAVE2 ,"DSS_SQUAREWAVE2" , 1 ,sizeof(struct dss_squarewave_context)  ,dss_squarewave2_reset ,dss_squarewave2_step },
147
 
        { DSS_TRIANGLEWAVE,"DSS_TRIANGLEWAVE", 1 ,sizeof(struct dss_trianglewave_context),dss_trianglewave_reset,dss_trianglewave_step},
 
228
        { DSS_COUNTER     ,"DSS_COUNTER"     , 1 ,sizeof(struct dss_counter_context)     ,dss_counter_reset     ,dss_counter_step     ,NULL                  ,NULL                 },
 
229
        { DSS_LFSR_NOISE  ,"DSS_LFSR_NOISE"  , 2 ,sizeof(struct dss_lfsr_context)        ,dss_lfsr_reset        ,dss_lfsr_step        ,NULL                  ,NULL                 },
 
230
        { DSS_NOISE       ,"DSS_NOISE"       , 1 ,sizeof(struct dss_noise_context)       ,dss_noise_reset       ,dss_noise_step       ,NULL                  ,NULL                 },
 
231
        { DSS_NOTE        ,"DSS_NOTE"        , 1 ,sizeof(struct dss_note_context)        ,dss_note_reset        ,dss_note_step        ,NULL                  ,NULL                 },
 
232
        { DSS_SAWTOOTHWAVE,"DSS_SAWTOOTHWAVE", 1 ,sizeof(struct dss_sawtoothwave_context),dss_sawtoothwave_reset,dss_sawtoothwave_step,NULL                  ,NULL                 },
 
233
        { DSS_SINEWAVE    ,"DSS_SINEWAVE"    , 1 ,sizeof(struct dss_sinewave_context)    ,dss_sinewave_reset    ,dss_sinewave_step    ,NULL                  ,NULL                 },
 
234
        { DSS_SQUAREWAVE  ,"DSS_SQUAREWAVE"  , 1 ,sizeof(struct dss_squarewave_context)  ,dss_squarewave_reset  ,dss_squarewave_step  ,NULL                  ,NULL                 },
 
235
        { DSS_SQUAREWFIX  ,"DSS_SQUAREWFIX"  , 1 ,sizeof(struct dss_squarewfix_context)  ,dss_squarewfix_reset  ,dss_squarewfix_step  ,NULL                  ,NULL                 },
 
236
        { DSS_SQUAREWAVE2 ,"DSS_SQUAREWAVE2" , 1 ,sizeof(struct dss_squarewave_context)  ,dss_squarewave2_reset ,dss_squarewave2_step ,NULL                  ,NULL                 },
 
237
        { DSS_TRIANGLEWAVE,"DSS_TRIANGLEWAVE", 1 ,sizeof(struct dss_trianglewave_context),dss_trianglewave_reset,dss_trianglewave_step,NULL                  ,NULL                 },
148
238
        /* Component specific modules */
149
 
        { DSS_INVERTER_OSC ,"DSS_INVERTER_OSC" , 1 ,sizeof(struct dss_inverter_osc_context) ,dss_inverter_osc_reset ,dss_inverter_osc_step },
150
 
        { DSS_OP_AMP_OSC  ,"DSS_OP_AMP_OSC"  , 1 ,sizeof(struct dss_op_amp_osc_context)  ,dss_op_amp_osc_reset  ,dss_op_amp_osc_step  },
151
 
        { DSS_SCHMITT_OSC ,"DSS_SCHMITT_OSC" , 1 ,sizeof(struct dss_schmitt_osc_context) ,dss_schmitt_osc_reset ,dss_schmitt_osc_step },
 
239
        { DSS_INVERTER_OSC ,"DSS_INVERTER_OSC" , 1 ,sizeof(struct dss_inverter_osc_context) ,dss_inverter_osc_reset ,dss_inverter_osc_step ,NULL                  ,NULL                 },
 
240
        { DSS_OP_AMP_OSC  ,"DSS_OP_AMP_OSC"  , 1 ,sizeof(struct dss_op_amp_osc_context)  ,dss_op_amp_osc_reset  ,dss_op_amp_osc_step  ,NULL                  ,NULL                 },
 
241
        { DSS_SCHMITT_OSC ,"DSS_SCHMITT_OSC" , 1 ,sizeof(struct dss_schmitt_osc_context) ,dss_schmitt_osc_reset ,dss_schmitt_osc_step ,NULL                  ,NULL                 },
152
242
        /* Not yet implemented */
153
 
        { DSS_ADSR        ,"DSS_ADSR"        , 1 ,sizeof(struct dss_adsr_context)        ,dss_adsrenv_reset     ,dss_adsrenv_step     },
 
243
        { DSS_ADSR        ,"DSS_ADSR"        , 1 ,sizeof(struct dss_adsr_context)        ,dss_adsrenv_reset     ,dss_adsrenv_step     ,NULL                  ,NULL                 },
154
244
 
155
245
        /* from disc_mth.c */
156
246
        /* Generic modules */
157
 
        { DST_ADDER       ,"DST_ADDER"       , 1 ,0                                      ,NULL                  ,dst_adder_step       },
158
 
        { DST_CLAMP       ,"DST_CLAMP"       , 1 ,0                                      ,NULL                  ,dst_clamp_step       },
159
 
        { DST_DIVIDE      ,"DST_DIVIDE"      , 1 ,0                                      ,NULL                  ,dst_divide_step      },
160
 
        { DST_GAIN        ,"DST_GAIN"        , 1 ,0                                      ,NULL                  ,dst_gain_step        },
161
 
        { DST_LOGIC_INV   ,"DST_LOGIC_INV"   , 1 ,0                                      ,NULL                  ,dst_logic_inv_step   },
162
 
        { DST_LOGIC_AND   ,"DST_LOGIC_AND"   , 1 ,0                                      ,NULL                  ,dst_logic_and_step   },
163
 
        { DST_LOGIC_NAND  ,"DST_LOGIC_NAND"  , 1 ,0                                      ,NULL                  ,dst_logic_nand_step  },
164
 
        { DST_LOGIC_OR    ,"DST_LOGIC_OR"    , 1 ,0                                      ,NULL                  ,dst_logic_or_step    },
165
 
        { DST_LOGIC_NOR   ,"DST_LOGIC_NOR"   , 1 ,0                                      ,NULL                  ,dst_logic_nor_step   },
166
 
        { DST_LOGIC_XOR   ,"DST_LOGIC_XOR"   , 1 ,0                                      ,NULL                  ,dst_logic_xor_step   },
167
 
        { DST_LOGIC_NXOR  ,"DST_LOGIC_NXOR"  , 1 ,0                                      ,NULL                  ,dst_logic_nxor_step  },
168
 
        { DST_LOGIC_DFF   ,"DST_LOGIC_DFF"   , 1 ,sizeof(struct dst_flipflop_context)    ,dst_logic_ff_reset    ,dst_logic_dff_step   },
169
 
        { DST_LOGIC_JKFF  ,"DST_LOGIC_JKFF"  , 1 ,sizeof(struct dst_flipflop_context)    ,dst_logic_ff_reset    ,dst_logic_jkff_step  },
170
 
        { DST_LOOKUP_TABLE,"DST_LOOKUP_TABLE", 1 ,0                                      ,NULL                  ,dst_lookup_table_step},
171
 
        { DST_MULTIPLEX   ,"DST_MULTIPLEX"   , 1 ,sizeof(struct dst_size_context)        ,dst_multiplex_reset   ,dst_multiplex_step   },
172
 
        { DST_ONESHOT     ,"DST_ONESHOT"     , 1 ,sizeof(struct dst_oneshot_context)     ,dst_oneshot_reset     ,dst_oneshot_step     },
173
 
        { DST_RAMP        ,"DST_RAMP"        , 1 ,sizeof(struct dss_ramp_context)        ,dst_ramp_reset        ,dst_ramp_step        },
174
 
        { DST_SAMPHOLD    ,"DST_SAMPHOLD"    , 1 ,sizeof(struct dst_samphold_context)    ,dst_samphold_reset    ,dst_samphold_step    },
175
 
        { DST_SWITCH      ,"DST_SWITCH"      , 1 ,0                                      ,NULL                  ,dst_switch_step      },
176
 
        { DST_ASWITCH     ,"DST_ASWITCH"     , 1 ,0                                      ,NULL                  ,dst_aswitch_step     },
177
 
        { DST_TRANSFORM   ,"DST_TRANSFORM"   , 1 ,0                                      ,NULL                  ,dst_transform_step   },
 
247
        { DST_ADDER       ,"DST_ADDER"       , 1 ,0                                      ,NULL                  ,dst_adder_step       ,NULL                  ,NULL                 },
 
248
        { DST_CLAMP       ,"DST_CLAMP"       , 1 ,0                                      ,NULL                  ,dst_clamp_step       ,NULL                  ,NULL                 },
 
249
        { DST_DIVIDE      ,"DST_DIVIDE"      , 1 ,0                                      ,NULL                  ,dst_divide_step      ,NULL                  ,NULL                 },
 
250
        { DST_GAIN        ,"DST_GAIN"        , 1 ,0                                      ,NULL                  ,dst_gain_step        ,NULL                  ,NULL                 },
 
251
        { DST_LOGIC_INV   ,"DST_LOGIC_INV"   , 1 ,0                                      ,NULL                  ,dst_logic_inv_step   ,NULL                  ,NULL                 },
 
252
        { DST_BITS_DECODE ,"DST_BITS_DECODE" , 8 ,sizeof(struct dst_bits_decode_context) ,dst_bits_decode_reset ,dst_bits_decode_step ,NULL                  ,NULL                 },
 
253
        { DST_LOGIC_AND   ,"DST_LOGIC_AND"   , 1 ,0                                      ,NULL                  ,dst_logic_and_step   ,NULL                  ,NULL                 },
 
254
        { DST_LOGIC_NAND  ,"DST_LOGIC_NAND"  , 1 ,0                                      ,NULL                  ,dst_logic_nand_step  ,NULL                  ,NULL                 },
 
255
        { DST_LOGIC_OR    ,"DST_LOGIC_OR"    , 1 ,0                                      ,NULL                  ,dst_logic_or_step    ,NULL                  ,NULL                 },
 
256
        { DST_LOGIC_NOR   ,"DST_LOGIC_NOR"   , 1 ,0                                      ,NULL                  ,dst_logic_nor_step   ,NULL                  ,NULL                 },
 
257
        { DST_LOGIC_XOR   ,"DST_LOGIC_XOR"   , 1 ,0                                      ,NULL                  ,dst_logic_xor_step   ,NULL                  ,NULL                 },
 
258
        { DST_LOGIC_NXOR  ,"DST_LOGIC_NXOR"  , 1 ,0                                      ,NULL                  ,dst_logic_nxor_step  ,NULL                  ,NULL                 },
 
259
        { DST_LOGIC_DFF   ,"DST_LOGIC_DFF"   , 1 ,sizeof(struct dst_flipflop_context)    ,dst_logic_ff_reset    ,dst_logic_dff_step   ,NULL                  ,NULL                 },
 
260
        { DST_LOGIC_JKFF  ,"DST_LOGIC_JKFF"  , 1 ,sizeof(struct dst_flipflop_context)    ,dst_logic_ff_reset    ,dst_logic_jkff_step  ,NULL                  ,NULL                 },
 
261
        { DST_LOGIC_SHIFT ,"DST_LOGIC_SHIFT" , 1 ,sizeof(struct dst_shift_context)       ,dst_logic_shift_reset ,dst_logic_shift_step ,NULL                  ,NULL                 },
 
262
        { DST_LOOKUP_TABLE,"DST_LOOKUP_TABLE", 1 ,0                                      ,NULL                  ,dst_lookup_table_step,NULL                  ,NULL                 },
 
263
        { DST_MULTIPLEX   ,"DST_MULTIPLEX"   , 1 ,sizeof(struct dst_size_context)        ,dst_multiplex_reset   ,dst_multiplex_step   ,NULL                  ,NULL                 },
 
264
        { DST_ONESHOT     ,"DST_ONESHOT"     , 1 ,sizeof(struct dst_oneshot_context)     ,dst_oneshot_reset     ,dst_oneshot_step     ,NULL                  ,NULL                 },
 
265
        { DST_RAMP        ,"DST_RAMP"        , 1 ,sizeof(struct dss_ramp_context)        ,dst_ramp_reset        ,dst_ramp_step        ,NULL                  ,NULL                 },
 
266
        { DST_SAMPHOLD    ,"DST_SAMPHOLD"    , 1 ,sizeof(struct dst_samphold_context)    ,dst_samphold_reset    ,dst_samphold_step    ,NULL                  ,NULL                 },
 
267
        { DST_SWITCH      ,"DST_SWITCH"      , 1 ,0                                      ,NULL                  ,dst_switch_step      ,NULL                  ,NULL                 },
 
268
        { DST_ASWITCH     ,"DST_ASWITCH"     , 1 ,0                                      ,NULL                  ,dst_aswitch_step     ,NULL                  ,NULL                 },
 
269
        { DST_TRANSFORM   ,"DST_TRANSFORM"   , 1 ,0                                      ,NULL                  ,dst_transform_step   ,NULL                  ,NULL                 },
178
270
        /* Component specific */
179
 
        { DST_COMP_ADDER  ,"DST_COMP_ADDER"  , 1 ,sizeof(struct dst_comp_adder_context)  ,dst_comp_adder_reset  ,dst_comp_adder_step  },
180
 
        { DST_DAC_R1      ,"DST_DAC_R1"      , 1 ,sizeof(struct dst_dac_r1_context)      ,dst_dac_r1_reset      ,dst_dac_r1_step      },
181
 
        { DST_DIODE_MIX   ,"DST_DIODE_MIX"   , 1 ,sizeof(struct dst_diode_mix__context)  ,dst_diode_mix_reset   ,dst_diode_mix_step   },
182
 
        { DST_INTEGRATE   ,"DST_INTEGRATE"   , 1 ,sizeof(struct dst_integrate_context)   ,dst_integrate_reset   ,dst_integrate_step   },
183
 
        { DST_MIXER       ,"DST_MIXER"       , 1 ,sizeof(struct dst_mixer_context)       ,dst_mixer_reset       ,dst_mixer_step       },
184
 
        { DST_OP_AMP      ,"DST_OP_AMP"      , 1 ,sizeof(struct dst_op_amp_context)      ,dst_op_amp_reset      ,dst_op_amp_step      },
185
 
        { DST_OP_AMP_1SHT ,"DST_OP_AMP_1SHT" , 1 ,sizeof(struct dst_op_amp_1sht_context) ,dst_op_amp_1sht_reset ,dst_op_amp_1sht_step },
186
 
        { DST_TVCA_OP_AMP ,"DST_TVCA_OP_AMP" , 1 ,sizeof(struct dst_tvca_op_amp_context) ,dst_tvca_op_amp_reset ,dst_tvca_op_amp_step },
187
 
        { DST_VCA         ,"DST_VCA"         , 1 ,0                                      ,NULL                  ,NULL                 },
 
271
        { DST_COMP_ADDER  ,"DST_COMP_ADDER"  , 1 ,sizeof(struct dst_comp_adder_context)  ,dst_comp_adder_reset  ,dst_comp_adder_step  ,NULL                  ,NULL                 },
 
272
        { DST_DAC_R1      ,"DST_DAC_R1"      , 1 ,sizeof(struct dst_dac_r1_context)      ,dst_dac_r1_reset      ,dst_dac_r1_step      ,NULL                  ,NULL                 },
 
273
        { DST_DIODE_MIX   ,"DST_DIODE_MIX"   , 1 ,sizeof(struct dst_diode_mix__context)  ,dst_diode_mix_reset   ,dst_diode_mix_step   ,NULL                  ,NULL                 },
 
274
        { DST_INTEGRATE   ,"DST_INTEGRATE"   , 1 ,sizeof(struct dst_integrate_context)   ,dst_integrate_reset   ,dst_integrate_step   ,NULL                  ,NULL                 },
 
275
        { DST_MIXER       ,"DST_MIXER"       , 1 ,sizeof(struct dst_mixer_context)       ,dst_mixer_reset       ,dst_mixer_step       ,NULL                  ,NULL                 },
 
276
        { DST_OP_AMP      ,"DST_OP_AMP"      , 1 ,sizeof(struct dst_op_amp_context)      ,dst_op_amp_reset      ,dst_op_amp_step      ,NULL                  ,NULL                 },
 
277
        { DST_OP_AMP_1SHT ,"DST_OP_AMP_1SHT" , 1 ,sizeof(struct dst_op_amp_1sht_context) ,dst_op_amp_1sht_reset ,dst_op_amp_1sht_step ,NULL                  ,NULL                 },
 
278
        { DST_TVCA_OP_AMP ,"DST_TVCA_OP_AMP" , 1 ,sizeof(struct dst_tvca_op_amp_context) ,dst_tvca_op_amp_reset ,dst_tvca_op_amp_step ,NULL                  ,NULL                 },
 
279
        { DST_VCA         ,"DST_VCA"         , 1 ,0                                      ,NULL                  ,NULL                 ,NULL                  ,NULL                 },
188
280
 
189
281
        /* from disc_flt.c */
190
282
        /* Generic modules */
191
 
        { DST_FILTER1     ,"DST_FILTER1"     , 1 ,sizeof(struct dss_filter1_context)     ,dst_filter1_reset     ,dst_filter1_step     },
192
 
        { DST_FILTER2     ,"DST_FILTER2"     , 1 ,sizeof(struct dss_filter2_context)     ,dst_filter2_reset     ,dst_filter2_step     },
 
283
        { DST_FILTER1     ,"DST_FILTER1"     , 1 ,sizeof(struct dss_filter1_context)     ,dst_filter1_reset     ,dst_filter1_step     ,NULL                  ,NULL                 },
 
284
        { DST_FILTER2     ,"DST_FILTER2"     , 1 ,sizeof(struct dss_filter2_context)     ,dst_filter2_reset     ,dst_filter2_step     ,NULL                  ,NULL                 },
193
285
        /* Component specific modules */
194
 
        { DST_SALLEN_KEY  ,"DST_SALLEN_KEY"  , 1 ,sizeof(struct dss_filter2_context)     ,dst_sallen_key_reset  ,dst_sallen_key_step  },
195
 
        { DST_CRFILTER    ,"DST_CRFILTER"    , 1 ,sizeof(struct dst_rcfilter_context)    ,dst_crfilter_reset    ,dst_crfilter_step    },
196
 
        { DST_OP_AMP_FILT ,"DST_OP_AMP_FILT" , 1 ,sizeof(struct dst_op_amp_filt_context) ,dst_op_amp_filt_reset ,dst_op_amp_filt_step },
197
 
        { DST_RCDISC      ,"DST_RCDISC"      , 1 ,sizeof(struct dst_rcdisc_context)      ,dst_rcdisc_reset      ,dst_rcdisc_step      },
198
 
        { DST_RCDISC2     ,"DST_RCDISC2"     , 1 ,sizeof(struct dst_rcdisc_context)      ,dst_rcdisc2_reset     ,dst_rcdisc2_step     },
199
 
        { DST_RCDISC3     ,"DST_RCDISC3"     , 1 ,sizeof(struct dst_rcdisc_context)      ,dst_rcdisc3_reset     ,dst_rcdisc3_step     },
200
 
        { DST_RCDISC4     ,"DST_RCDISC4"     , 1 ,sizeof(struct dst_rcdisc4_context)     ,dst_rcdisc4_reset     ,dst_rcdisc4_step     },
201
 
        { DST_RCDISC5     ,"DST_RCDISC5"     , 1 ,sizeof(struct dst_rcdisc_context)      ,dst_rcdisc5_reset     ,dst_rcdisc5_step     },
202
 
        { DST_RCINTEGRATE ,"DST_RCINTEGRATE" , 1 ,sizeof(struct dst_rcintegrate_context) ,dst_rcintegrate_reset ,dst_rcintegrate_step },
203
 
        { DST_RCDISC_MOD  ,"DST_RCDISC_MOD"  , 1 ,sizeof(struct dst_rcdisc_mod_context)  ,dst_rcdisc_mod_reset  ,dst_rcdisc_mod_step  },
204
 
        { DST_RCFILTER    ,"DST_RCFILTER"    , 1 ,sizeof(struct dst_rcfilter_context)    ,dst_rcfilter_reset    ,dst_rcfilter_step    },
205
 
        { DST_RCFILTER_SW ,"DST_RCFILTER_SW" , 1 ,sizeof(struct dst_rcfilter_sw_context) ,dst_rcfilter_sw_reset ,dst_rcfilter_sw_step },
 
286
        { DST_SALLEN_KEY  ,"DST_SALLEN_KEY"  , 1 ,sizeof(struct dss_filter2_context)     ,dst_sallen_key_reset  ,dst_sallen_key_step  ,NULL                  ,NULL                 },
 
287
        { DST_CRFILTER    ,"DST_CRFILTER"    , 1 ,sizeof(struct dst_rcfilter_context)    ,dst_crfilter_reset    ,dst_crfilter_step    ,NULL                  ,NULL                 },
 
288
        { DST_OP_AMP_FILT ,"DST_OP_AMP_FILT" , 1 ,sizeof(struct dst_op_amp_filt_context) ,dst_op_amp_filt_reset ,dst_op_amp_filt_step ,NULL                  ,NULL                 },
 
289
        { DST_RC_CIRCUIT_1,"DST_RC_CIRCUIT_1", 1 ,sizeof(struct dst_rc_circuit_1_context),dst_rc_circuit_1_reset,dst_rc_circuit_1_step,NULL                  ,NULL                 },
 
290
        { DST_RCDISC      ,"DST_RCDISC"      , 1 ,sizeof(struct dst_rcdisc_context)      ,dst_rcdisc_reset      ,dst_rcdisc_step      ,NULL                  ,NULL                 },
 
291
        { DST_RCDISC2     ,"DST_RCDISC2"     , 1 ,sizeof(struct dst_rcdisc_context)      ,dst_rcdisc2_reset     ,dst_rcdisc2_step     ,NULL                  ,NULL                 },
 
292
        { DST_RCDISC3     ,"DST_RCDISC3"     , 1 ,sizeof(struct dst_rcdisc_context)      ,dst_rcdisc3_reset     ,dst_rcdisc3_step     ,NULL                  ,NULL                 },
 
293
        { DST_RCDISC4     ,"DST_RCDISC4"     , 1 ,sizeof(struct dst_rcdisc4_context)     ,dst_rcdisc4_reset     ,dst_rcdisc4_step     ,NULL                  ,NULL                 },
 
294
        { DST_RCDISC5     ,"DST_RCDISC5"     , 1 ,sizeof(struct dst_rcdisc_context)      ,dst_rcdisc5_reset     ,dst_rcdisc5_step     ,NULL                  ,NULL                 },
 
295
        { DST_RCINTEGRATE ,"DST_RCINTEGRATE" , 1 ,sizeof(struct dst_rcintegrate_context) ,dst_rcintegrate_reset ,dst_rcintegrate_step ,NULL                  ,NULL                 },
 
296
        { DST_RCDISC_MOD  ,"DST_RCDISC_MOD"  , 1 ,sizeof(struct dst_rcdisc_mod_context)  ,dst_rcdisc_mod_reset  ,dst_rcdisc_mod_step  ,NULL                  ,NULL                 },
 
297
        { DST_RCFILTER    ,"DST_RCFILTER"    , 1 ,sizeof(struct dst_rcfilter_context)    ,dst_rcfilter_reset    ,dst_rcfilter_step    ,NULL                  ,NULL                 },
 
298
        { DST_RCFILTER_SW ,"DST_RCFILTER_SW" , 1 ,sizeof(struct dst_rcfilter_sw_context) ,dst_rcfilter_sw_reset ,dst_rcfilter_sw_step ,NULL                  ,NULL                 },
206
299
        /* For testing - seem to be buggered.  Use versions not ending in N. */
207
 
        { DST_RCFILTERN   ,"DST_RCFILTERN"   , 1 ,sizeof(struct dss_filter1_context)     ,dst_rcfilterN_reset   ,dst_filter1_step     },
208
 
        { DST_RCDISCN     ,"DST_RCDISCN"     , 1 ,sizeof(struct dss_filter1_context)     ,dst_rcdiscN_reset     ,dst_rcdiscN_step     },
209
 
        { DST_RCDISC2N    ,"DST_RCDISC2N"    , 1 ,sizeof(struct dss_rcdisc2_context)     ,dst_rcdisc2N_reset    ,dst_rcdisc2N_step    },
 
300
        { DST_RCFILTERN   ,"DST_RCFILTERN"   , 1 ,sizeof(struct dss_filter1_context)     ,dst_rcfilterN_reset   ,dst_filter1_step     ,NULL                  ,NULL                 },
 
301
        { DST_RCDISCN     ,"DST_RCDISCN"     , 1 ,sizeof(struct dss_filter1_context)     ,dst_rcdiscN_reset     ,dst_rcdiscN_step     ,NULL                  ,NULL                 },
 
302
        { DST_RCDISC2N    ,"DST_RCDISC2N"    , 1 ,sizeof(struct dss_rcdisc2_context)     ,dst_rcdisc2N_reset    ,dst_rcdisc2N_step    ,NULL                  ,NULL                 },
210
303
 
211
304
        /* from disc_dev.c */
212
305
        /* generic modules */
213
 
        { DST_CUSTOM      ,"DST_CUSTOM"      , 1 ,0                                      ,NULL                  ,NULL                 },
 
306
        { DST_CUSTOM      ,"DST_CUSTOM"      , 1 ,0                                      ,NULL                  ,NULL                 ,NULL                  ,NULL                 },
214
307
        /* Component specific modules */
215
 
        { DSD_555_ASTBL   ,"DSD_555_ASTBL"   , 1 ,sizeof(struct dsd_555_astbl_context)   ,dsd_555_astbl_reset   ,dsd_555_astbl_step   },
216
 
        { DSD_555_MSTBL   ,"DSD_555_MSTBL"   , 1 ,sizeof(struct dsd_555_mstbl_context)   ,dsd_555_mstbl_reset   ,dsd_555_mstbl_step   },
217
 
        { DSD_555_CC      ,"DSD_555_CC"      , 1 ,sizeof(struct dsd_555_cc_context)      ,dsd_555_cc_reset      ,dsd_555_cc_step      },
218
 
        { DSD_555_VCO1    ,"DSD_555_VCO1"    , 1 ,sizeof(struct dsd_555_vco1_context)    ,dsd_555_vco1_reset    ,dsd_555_vco1_step    },
219
 
        { DSD_566         ,"DSD_566"         , 1 ,sizeof(struct dsd_566_context)         ,dsd_566_reset         ,dsd_566_step         },
220
 
        { DSD_LS624       ,"DSD_LS624"       , 1 ,sizeof(struct dsd_ls624_context)       ,dsd_ls624_reset       ,dsd_ls624_step       },
 
308
        { DSD_555_ASTBL   ,"DSD_555_ASTBL"   , 1 ,sizeof(struct dsd_555_astbl_context)   ,dsd_555_astbl_reset   ,dsd_555_astbl_step   ,NULL                  ,NULL                 },
 
309
        { DSD_555_MSTBL   ,"DSD_555_MSTBL"   , 1 ,sizeof(struct dsd_555_mstbl_context)   ,dsd_555_mstbl_reset   ,dsd_555_mstbl_step   ,NULL                  ,NULL                 },
 
310
        { DSD_555_CC      ,"DSD_555_CC"      , 1 ,sizeof(struct dsd_555_cc_context)      ,dsd_555_cc_reset      ,dsd_555_cc_step      ,NULL                  ,NULL                 },
 
311
        { DSD_555_VCO1    ,"DSD_555_VCO1"    , 1 ,sizeof(struct dsd_555_vco1_context)    ,dsd_555_vco1_reset    ,dsd_555_vco1_step    ,NULL                  ,NULL                 },
 
312
        { DSD_566         ,"DSD_566"         , 1 ,sizeof(struct dsd_566_context)         ,dsd_566_reset         ,dsd_566_step         ,NULL                  ,NULL                 },
 
313
        { DSD_LS624       ,"DSD_LS624"       , 1 ,sizeof(struct dsd_ls624_context)       ,dsd_ls624_reset       ,dsd_ls624_step       ,NULL                  ,NULL                 },
 
314
        { DSD_LS629       ,"DSD_LS629"       , 1 ,sizeof(struct dsd_ls629_context)       ,dsd_ls629_reset       ,dsd_ls629_step       ,NULL                  ,NULL                 },
221
315
        /* must be the last one */
222
 
        { DSS_NULL        ,"DSS_NULL"        , 0 ,0                                      ,NULL                  ,NULL                 }
 
316
        { DSS_NULL        ,"DSS_NULL"        , 0 ,0                                      ,NULL                  ,NULL                 ,NULL                  ,NULL                 }
223
317
};
224
318
 
225
 
 
 
319
INLINE void step_nodes_in_list(const linked_list_entry *list)
 
320
{
 
321
        const linked_list_entry *entry;
 
322
 
 
323
        if (EXPECTED(!profiling))
 
324
        {
 
325
                for (entry = list; entry != NULL; entry = entry->next)
 
326
                {
 
327
                        node_description *node = (node_description *) entry->ptr;
 
328
 
 
329
                        /* Now step the node */
 
330
                        (*node->step)(node);
 
331
                }
 
332
        }
 
333
        else
 
334
        {
 
335
                osd_ticks_t last = get_profile_ticks();
 
336
 
 
337
                for (entry = list; entry != NULL; entry = entry->next)
 
338
                {
 
339
                        node_description *node = (node_description *) entry->ptr;
 
340
 
 
341
                        node->run_time -= last;
 
342
                        (*node->step)(node);
 
343
                        last = get_profile_ticks();
 
344
                        node->run_time += last;
 
345
                }
 
346
        }
 
347
}
226
348
 
227
349
/*************************************
228
350
 *
230
352
 *
231
353
 *************************************/
232
354
 
233
 
node_description *discrete_find_node(void *chip, int node)
 
355
static node_description *discrete_find_node(const discrete_info *info, int node)
234
356
{
235
 
        discrete_info *info = chip ? (discrete_info *)chip : discrete_current_context;
236
357
        if (node < NODE_START || node > NODE_END) return NULL;
237
358
        return info->indexed_node[NODE_INDEX(node)];
238
359
}
239
360
 
240
 
 
 
361
/*************************************
 
362
 *
 
363
 *  Build import list
 
364
 *
 
365
 *************************************/
 
366
 
 
367
static void discrete_build_list(discrete_info *info, const discrete_sound_block *intf, linked_list_entry ***current)
 
368
{
 
369
        int node_count = 0;
 
370
 
 
371
        for (; intf[node_count].type != DSS_NULL; )
 
372
        {
 
373
                /* scan imported */
 
374
                if (intf[node_count].type == DSO_IMPORT)
 
375
                {
 
376
                        discrete_log(info, "discrete_build_list() - DISCRETE_IMPORT @ NODE_%02d", NODE_INDEX(intf[node_count].node) );
 
377
                        discrete_build_list(info, (discrete_sound_block *) intf[node_count].custom, current);
 
378
                }
 
379
                else if (intf[node_count].type == DSO_REPLACE)
 
380
                {
 
381
                        linked_list_entry *entry;
 
382
 
 
383
                        node_count++;
 
384
                        if (intf[node_count].type == DSS_NULL)
 
385
                                fatalerror("discrete_build_list: DISCRETE_REPLACE at end of node_list");
 
386
 
 
387
                        for (entry = info->block_list; entry != NULL; entry = entry->next)
 
388
                        {
 
389
                                discrete_sound_block *block = (discrete_sound_block *) entry->ptr;
 
390
 
 
391
                                if (block->type != NODE_SPECIAL )
 
392
                                        if (block->node == intf[node_count].node)
 
393
                                        {
 
394
                                                entry->ptr = (void *) &intf[node_count];
 
395
                                                discrete_log(info, "discrete_build_list() - DISCRETE_REPLACE @ NODE_%02d", NODE_INDEX(intf[node_count].node) );
 
396
                                                break;
 
397
                                        }
 
398
                        }
 
399
 
 
400
                        if (entry == NULL)
 
401
                                fatalerror("discrete_build_list: DISCRETE_REPLACE did not found node %d", NODE_INDEX(intf[node_count].node));
 
402
 
 
403
                }
 
404
                else if (intf[node_count].type == DSO_DELETE)
 
405
                {
 
406
                        linked_list_entry *entry, *last;
 
407
 
 
408
                        last = NULL;
 
409
                        for (entry = info->block_list; entry != NULL; last = entry, entry = entry->next)
 
410
                        {
 
411
                                discrete_sound_block *block = (discrete_sound_block *) entry->ptr;
 
412
 
 
413
                                if ((block->node >= intf[node_count].input_node[0]) &&
 
414
                                                (block->node <= intf[node_count].input_node[1]))
 
415
                                {
 
416
                                        discrete_log(info, "discrete_build_list() - DISCRETE_DELETE deleted NODE_%02d", NODE_INDEX(block->node) );
 
417
                                        if (last != NULL)
 
418
                                                last->next = entry->next;
 
419
                                        else
 
420
                                                info->block_list = entry->next;
 
421
                                }
 
422
                        }
 
423
                }
 
424
                else
 
425
                {
 
426
                        discrete_log(info, "discrete_build_list() - adding node %d (*current %p)\n", node_count, *current);
 
427
                        linked_list_tail_add(info, current, &intf[node_count]);
 
428
                }
 
429
 
 
430
                node_count++;
 
431
        }
 
432
}
 
433
 
 
434
/*************************************
 
435
 *
 
436
 *  Sanity check list
 
437
 *
 
438
 *************************************/
 
439
 
 
440
static void discrete_sanity_check(const discrete_info *info)
 
441
{
 
442
        const linked_list_entry *entry;
 
443
        int node_count = 0;
 
444
 
 
445
        discrete_log(info, "discrete_start() - Doing node list sanity check");
 
446
        for (entry = info->block_list; entry != NULL; entry = entry->next)
 
447
        {
 
448
                discrete_sound_block *block = (discrete_sound_block *) entry->ptr;
 
449
 
 
450
                /* make sure we don't have too many nodes overall */
 
451
                if (node_count > DISCRETE_MAX_NODES)
 
452
                        fatalerror("discrete_start() - Upper limit of %d nodes exceeded, have you terminated the interface block?", DISCRETE_MAX_NODES);
 
453
 
 
454
                /* make sure the node number is in range */
 
455
                if (block->node < NODE_START || block->node > NODE_END)
 
456
                        fatalerror("discrete_start() - Invalid node number on node %02d descriptor", block->node);
 
457
 
 
458
                /* make sure the node type is valid */
 
459
                if (block->type > DSO_OUTPUT)
 
460
                        fatalerror("discrete_start() - Invalid function type on NODE_%02d", NODE_INDEX(block->node) );
 
461
 
 
462
                /* make sure this is a main node */
 
463
                if (NODE_CHILD_NODE_NUM(block->node) > 0)
 
464
                        fatalerror("discrete_start() - Child node number on NODE_%02d", NODE_INDEX(block->node) );
 
465
 
 
466
                node_count++;
 
467
        }
 
468
        discrete_log(info, "discrete_start() - Sanity check counted %d nodes", node_count);
 
469
 
 
470
}
241
471
 
242
472
/*************************************
243
473
 *
247
477
 
248
478
static DEVICE_START( discrete )
249
479
{
250
 
        discrete_sound_block *intf = (discrete_sound_block *)device->static_config;
 
480
        linked_list_entry **intf;
 
481
        const linked_list_entry *entry;
 
482
        const discrete_sound_block *intf_start = (discrete_sound_block *)device->static_config;
251
483
        discrete_info *info = get_safe_token(device);
252
484
        char name[32];
253
485
 
261
493
        info->sample_time = 1.0 / info->sample_rate;
262
494
        info->neg_sample_time = - info->sample_time;
263
495
 
 
496
        info->total_samples = 0;
 
497
        info->total_stream_updates = 0;
 
498
 
264
499
        /* create the logfile */
265
500
        sprintf(name, "discrete%s.log", device->tag);
266
 
        if (DISCRETE_DEBUGLOG && !info->disclogfile)
 
501
        if (DISCRETE_DEBUGLOG)
267
502
                info->disclogfile = fopen(name, "w");
268
503
 
269
 
        discrete_current_context = info;
 
504
        /* enable profiling */
 
505
        if (getenv("DISCRETE_PROFILING"))
 
506
                profiling = atoi(getenv("DISCRETE_PROFILING"));
 
507
 
 
508
        /* Build the final block list */
 
509
        info->block_list = NULL;
 
510
        intf = &info->block_list;
 
511
        discrete_build_list(info, intf_start, &intf);
270
512
 
271
513
        /* first pass through the nodes: sanity check, fill in the indexed_nodes, and make a total count */
272
 
        discrete_log("discrete_start() - Doing node list sanity check");
273
 
        for (info->node_count = 0; intf[info->node_count].type != DSS_NULL; info->node_count++)
274
 
        {
275
 
                /* make sure we don't have too many nodes overall */
276
 
                if (info->node_count > DISCRETE_MAX_NODES)
277
 
                        fatalerror("discrete_start() - Upper limit of %d nodes exceeded, have you terminated the interface block?", DISCRETE_MAX_NODES);
278
 
 
279
 
                /* make sure the node number is in range */
280
 
                if (intf[info->node_count].node < NODE_START || intf[info->node_count].node > NODE_END)
281
 
                        fatalerror("discrete_start() - Invalid node number on node %02d descriptor", info->node_count);
282
 
 
283
 
                /* make sure the node type is valid */
284
 
                if (intf[info->node_count].type > DSO_OUTPUT)
285
 
                        fatalerror("discrete_start() - Invalid function type on NODE_%02d", NODE_INDEX(intf[info->node_count].node) );
286
 
 
287
 
                /* make sure this is a main node */
288
 
                if (NODE_CHILD_NODE_NUM(intf[info->node_count].node) > 0)
289
 
                        fatalerror("discrete_start() - Child node number on NODE_%02d", NODE_INDEX(intf[info->node_count].node) );
290
 
        }
291
 
        info->node_count++;
292
 
        discrete_log("discrete_start() - Sanity check counted %d nodes", info->node_count);
293
 
 
294
 
        /* allocate memory for the array of actual nodes */
295
 
        info->node_list = auto_alloc_array_clear(device->machine, node_description, info->node_count);
296
 
 
297
 
        /* allocate memory for the node execution order array */
298
 
        info->running_order = auto_alloc_array_clear(device->machine, node_description *, info->node_count);
 
514
        discrete_sanity_check(info);
 
515
 
 
516
        /* Start with empty lists */
 
517
        info->node_list = NULL;
 
518
        info->output_list = NULL;
 
519
        info->input_list = NULL;
299
520
 
300
521
        /* allocate memory to hold pointers to nodes by index */
301
522
        info->indexed_node = auto_alloc_array_clear(device->machine, node_description *, DISCRETE_MAX_NODES);
302
523
 
303
524
        /* initialize the node data */
304
 
        init_nodes(info, intf, device);
 
525
        init_nodes(info, info->block_list, device);
305
526
 
306
527
        /* now go back and find pointers to all input nodes */
307
 
        find_input_nodes(info, intf);
308
 
 
309
 
        /* then set up the output nodes */
310
 
        setup_output_nodes(device, info);
311
 
 
312
 
        setup_disc_logs(info);
313
 
 
314
 
        discrete_current_context = NULL;
 
528
        find_input_nodes(info);
 
529
 
 
530
        /* initialize the stream(s) */
 
531
        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);
 
532
 
 
533
        /* allocate a queue */
 
534
 
 
535
        info->queue = osd_work_queue_alloc(WORK_QUEUE_FLAG_MULTI | WORK_QUEUE_FLAG_HIGH_FREQ);
 
536
 
 
537
        /* Process nodes which have a start func */
 
538
 
 
539
        for (entry = info->node_list; entry != NULL; entry = entry->next)
 
540
        {
 
541
                node_description *node = (node_description *) entry->ptr;
 
542
 
 
543
                if (node->module->start)
 
544
                        (*node->module->start)(node);
 
545
        }
 
546
 
315
547
}
316
548
 
317
549
 
322
554
 *
323
555
 *************************************/
324
556
 
 
557
static UINT64 list_run_time(const linked_list_entry *list)
 
558
{
 
559
        const linked_list_entry *entry;
 
560
        UINT64 total = 0;
 
561
 
 
562
        for (entry = list; entry != NULL; entry = entry->next)
 
563
        {
 
564
                node_description *node = (node_description *) entry->ptr;
 
565
 
 
566
                total += node->run_time;
 
567
        }
 
568
        return total;
 
569
}
 
570
 
 
571
static void display_profiling(const discrete_info *info)
 
572
{
 
573
        int count;
 
574
        UINT64 total;
 
575
        UINT64 tresh;
 
576
        double tt;
 
577
        linked_list_entry *entry;
 
578
 
 
579
        /* calculate total time */
 
580
        total = list_run_time(info->node_list);
 
581
        count = linked_list_count(info->node_list);
 
582
        /* print statistics */
 
583
        printf("Total Samples  : %16" I64FMT "d\n", info->total_samples);
 
584
        tresh = total / count;
 
585
        printf("Treshold (mean): %16" I64FMT "d\n", tresh / info->total_samples );
 
586
        for (entry = info->node_list; entry != NULL; entry = entry->next)
 
587
        {
 
588
                node_description *node = (node_description *) entry->ptr;
 
589
 
 
590
                if (node->run_time > tresh)
 
591
                        printf("%3d: %20s %8.2f %10.2f\n", NODE_BLOCKINDEX(node), node->module->name, (float) node->run_time / (float) total * 100.0, ((float) node->run_time) / (float) info->total_samples);
 
592
        }
 
593
 
 
594
        /* Task information */
 
595
        for (entry = info->task_list; entry != 0; entry = entry->next)
 
596
        {
 
597
                discrete_task *task = (discrete_task *) entry->ptr;
 
598
                tt =  list_run_time(task->list);
 
599
 
 
600
                printf("Task(%d): %8.2f %15.2f\n", task->task_group, tt / (double) total * 100.0, tt / (double) info->total_samples);
 
601
        }
 
602
 
 
603
        printf("Average samples/stream_update: %8.2f\n", (double) info->total_samples / (double) info->total_stream_updates);
 
604
}
 
605
 
325
606
static DEVICE_STOP( discrete )
326
607
{
327
608
        discrete_info *info = get_safe_token(device);
328
 
        int log_num;
329
 
 
330
 
#if (DISCRETE_PROFILING)
331
 
        {
332
 
                int nodenum;
333
 
                osd_ticks_t total = 0;
334
 
                osd_ticks_t tresh;
335
 
 
336
 
                /* calculate total time */
337
 
                for (nodenum = 0; nodenum < info->node_count; nodenum++)
338
 
                {
339
 
                        node_description *node = info->running_order[nodenum];
340
 
 
341
 
                        /* Now step the node */
342
 
                        total += node->run_time;
343
 
                }
344
 
                /* print statistics */
345
 
                tresh = total / info->node_count;
346
 
                for (nodenum = 0; nodenum < info->node_count; nodenum++)
347
 
                {
348
 
                        node_description *node = info->running_order[nodenum];
349
 
 
350
 
                        if (node->run_time > tresh)
351
 
                                printf("%3d: %20s %8.2f\n", NODE_INDEX(node->node), node->module.name, (float) node->run_time / (float) total * 100.0);
352
 
                        /* Now step the node */
353
 
                        total += node->run_time;
354
 
                }
355
 
        }
356
 
#endif
357
 
 
358
 
        /* close any csv files */
359
 
        for (log_num = 0; log_num < info->num_csvlogs; log_num++)
360
 
                if (info->disc_csv_file[log_num])
361
 
                        fclose(info->disc_csv_file[log_num]);
362
 
 
363
 
        /* close any wave files */
364
 
        for (log_num = 0; log_num < info->num_wavelogs; log_num++)
365
 
                if (info->disc_wav_file[log_num])
366
 
                        wav_close(info->disc_wav_file[log_num]);
 
609
        const linked_list_entry *entry;
 
610
 
 
611
        osd_work_queue_free(info->queue);
 
612
 
 
613
        if (profiling)
 
614
        {
 
615
                display_profiling(info);
 
616
        }
 
617
 
 
618
        /* Process nodes which have a stop func */
 
619
 
 
620
        for (entry = info->node_list; entry != NULL; entry = entry->next)
 
621
        {
 
622
                node_description *node = (node_description *) entry->ptr;
 
623
 
 
624
                if (node->module->stop)
 
625
                        (*node->module->stop)(node);
 
626
        }
367
627
 
368
628
        if (DISCRETE_DEBUGLOG)
369
629
        {
384
644
 
385
645
static DEVICE_RESET( discrete )
386
646
{
387
 
        discrete_info *info = get_safe_token(device);
388
 
        int nodenum;
389
 
 
390
 
        discrete_current_context = info;
 
647
        const discrete_info *info = get_safe_token(device);
 
648
        const linked_list_entry *entry;
391
649
 
392
650
        /* loop over all nodes */
393
 
        for (nodenum = 0; nodenum < info->node_count; nodenum++)
 
651
        for (entry = info->node_list; entry != 0; entry = entry->next)
394
652
        {
395
 
                node_description *node = info->running_order[nodenum];
 
653
                node_description *node = (node_description *) entry->ptr;
396
654
 
397
655
                node->output[0] = 0;
398
656
 
399
657
                /* if the node has a reset function, call it */
400
 
                if (node->module.reset)
401
 
                        (*node->module.reset)(device, node);
 
658
                if (node->module->reset)
 
659
                        (*node->module->reset)(node);
402
660
 
403
661
                /* otherwise, just step it */
404
 
                else if (node->module.step)
405
 
                        (*node->module.step)(device, node);
 
662
                else if (node->step)
 
663
                        (*node->step)(node);
406
664
        }
407
 
 
408
 
        discrete_current_context = NULL;
409
665
}
410
666
 
411
 
 
412
 
 
413
667
/*************************************
414
668
 *
415
669
 *  Stream update functions
416
670
 *
417
671
 *************************************/
418
672
 
 
673
static void *task_callback(void *param, int threadid)
 
674
{
 
675
        const linked_list_entry *list = (linked_list_entry *) param;
 
676
        const linked_list_entry *entry;
 
677
        int samples;
 
678
 
 
679
        do
 
680
        {
 
681
                for (entry = list; entry != 0; entry = entry->next)
 
682
                {
 
683
                        discrete_task           *task = (discrete_task *) entry->ptr;
 
684
                        INT32                           prev_id;
 
685
 
 
686
                        /* try to lock */
 
687
                        prev_id = compare_exchange32(&task->threadid, -1, threadid);
 
688
                        if (prev_id == -1 && task->threadid == threadid)
 
689
                        {
 
690
                                linked_list_entry       *src_entry;
 
691
 
 
692
                                samples = MIN(task->samples, MAX_SAMPLES_PER_TASK_SLICE);
 
693
 
 
694
                                /* check dependencies */
 
695
                                for (src_entry = task->source_list; src_entry != NULL; src_entry = src_entry->next)
 
696
                                {
 
697
                                        discrete_source_node *sn = (discrete_source_node *) src_entry->ptr;
 
698
                                        int avail;
 
699
 
 
700
                                        avail = sn->task->ptr[sn->output_node] - sn->ptr;
 
701
                                        assert_always(avail >= 0, "task_callback: available samples are negative");
 
702
                                        if (avail < samples)
 
703
                                                samples = avail;
 
704
                                }
 
705
 
 
706
                                task->samples -= samples;
 
707
                                assert_always(task->samples >=0, "task_callback: task_samples got negative");
 
708
                                while (samples > 0)
 
709
                                {
 
710
                                        /* step */
 
711
                                        step_nodes_in_list(task->list);
 
712
                                        samples--;
 
713
                                }
 
714
                                if (task->samples == 0)
 
715
                                {
 
716
                                        return NULL;
 
717
                                }
 
718
                                task->threadid = -1;
 
719
                        }
 
720
                }
 
721
        } while (1);
 
722
 
 
723
        return NULL;
 
724
}
 
725
 
 
726
 
 
727
static STREAM_UPDATE( buffer_stream_update )
 
728
{
 
729
        const node_description *node = (node_description *) param;
 
730
        const struct dss_input_context *context = (struct dss_input_context *)node->context;
 
731
        stream_sample_t *ptr = outputs[0];
 
732
        int data = context->data;
 
733
        int samplenum = samples;
 
734
 
 
735
        while (samplenum-- > 0)
 
736
          *(ptr++) = data;
 
737
}
 
738
 
 
739
 
419
740
static STREAM_UPDATE( discrete_stream_update )
420
741
{
421
742
        discrete_info *info = (discrete_info *)param;
422
 
        int samplenum, nodenum, outputnum;
423
 
        double val;
424
 
        INT16 wave_data_l, wave_data_r;
425
 
 
426
 
        discrete_current_context = info;
 
743
        const linked_list_entry *entry;
 
744
        int outputnum;
 
745
        //, task_group;
 
746
 
 
747
        if (samples == 0)
 
748
                return;
 
749
 
 
750
        /* Setup any output streams */
 
751
        for (entry = info->output_list, outputnum = 0; entry != NULL; entry = entry->next, outputnum++)
 
752
        {
 
753
                ((node_description *) entry->ptr)->context = (void *) outputs[outputnum];
 
754
        }
427
755
 
428
756
        /* Setup any input streams */
429
 
        for (nodenum = 0; nodenum < info->discrete_input_streams; nodenum++)
430
 
        {
431
 
                info->input_stream_data[nodenum] = inputs[nodenum];
432
 
        }
433
 
 
434
 
        /* Now we must do samples iterations of the node list, one output for each step */
435
 
        for (samplenum = 0; samplenum < samples; samplenum++)
436
 
        {
437
 
                /* loop over all nodes */
438
 
                for (nodenum = 0; nodenum < info->node_count; nodenum++)
439
 
                {
440
 
                        node_description *node = info->running_order[nodenum];
441
 
 
442
 
                        /* Now step the node */
443
 
#if (DISCRETE_PROFILING)
444
 
                        node->run_time -= osd_profiling_ticks();
445
 
#endif
446
 
                        if (node->module.step)
447
 
                                (*node->module.step)(info->device, node);
448
 
#if (DISCRETE_PROFILING)
449
 
                        node->run_time += osd_profiling_ticks();
450
 
#endif
451
 
                }
452
 
 
453
 
                /* Add gain to the output and put into the buffers */
454
 
                /* Clipping will be handled by the main sound system */
455
 
                for (outputnum = 0; outputnum < info->discrete_outputs; outputnum++)
456
 
                {
457
 
                        val = (*info->output_node[outputnum]->input[0]) * (*info->output_node[outputnum]->input[1]);
458
 
                        outputs[outputnum][samplenum] = val;
459
 
                }
460
 
 
461
 
                /* Dump any csv logs */
462
 
                for (outputnum = 0; outputnum < info->num_csvlogs; outputnum++)
463
 
                {
464
 
                        fprintf(info->disc_csv_file[outputnum], "%lld", ++info->sample_num);
465
 
                        for (nodenum = 0; nodenum < info->csvlog_node[outputnum]->active_inputs; nodenum++)
466
 
                        {
467
 
                                fprintf(info->disc_csv_file[outputnum], ", %f", *info->csvlog_node[outputnum]->input[nodenum]);
468
 
                        }
469
 
                        fprintf(info->disc_csv_file[outputnum], "\n");
470
 
                }
471
 
 
472
 
                /* Dump any wave logs */
473
 
                for (outputnum = 0; outputnum < info->num_wavelogs; outputnum++)
474
 
                {
475
 
                        /* get nodes to be logged and apply gain, then clip to 16 bit */
476
 
                        val = (*info->wavelog_node[outputnum]->input[0]) * (*info->wavelog_node[outputnum]->input[1]);
477
 
                        val = (val < -32768) ? -32768 : (val > 32767) ? 32767 : val;
478
 
                        wave_data_l = (INT16)val;
479
 
                        if (info->wavelog_node[outputnum]->active_inputs == 2)
480
 
                        {
481
 
                                /* DISCRETE_WAVELOG1 */
482
 
                                wav_add_data_16(info->disc_wav_file[outputnum], &wave_data_l, 1);
483
 
                        }
484
 
                        else
485
 
                        {
486
 
                                /* DISCRETE_WAVELOG2 */
487
 
                                val = (*info->wavelog_node[outputnum]->input[2]) * (*info->wavelog_node[outputnum]->input[3]);
488
 
                                val = (val < -32768) ? -32768 : (val > 32767) ? 32767 : val;
489
 
                                wave_data_r = (INT16)val;
490
 
 
491
 
                                wav_add_data_16lr(info->disc_wav_file[outputnum], &wave_data_l, &wave_data_r, 1);
492
 
                        }
493
 
                }
494
 
 
495
 
                /* advance input streams */
496
 
                for (nodenum = 0; nodenum < info->discrete_input_streams; nodenum++)
497
 
                {
498
 
                        info->input_stream_data[nodenum]++;
499
 
                }
500
 
        }
501
 
 
502
 
        discrete_current_context = NULL;
 
757
        for (entry = info->input_list; entry != NULL; entry = entry->next)
 
758
        {
 
759
                struct dss_input_context *context = (struct dss_input_context *) ((node_description *) entry->ptr)->context;
 
760
                context->ptr = (stream_sample_t *) inputs[context->stream_in_number];
 
761
        }
 
762
 
 
763
        /* Setup tasks */
 
764
        for (entry = info->task_list; entry != 0; entry = entry->next)
 
765
        {
 
766
                discrete_task           *task = (discrete_task *) entry->ptr;
 
767
                linked_list_entry       *src_entry;
 
768
                int                                     i;
 
769
 
 
770
                task->samples = samples;
 
771
                task->threadid = -1;
 
772
 
 
773
                /* set up task buffers */
 
774
                for (i = 0; i < task->numbuffered; i++)
 
775
                        task->ptr[i] = task->node_buf[i];
 
776
 
 
777
                /* initialize sources */
 
778
                for (src_entry = task->source_list; src_entry != 0; src_entry = src_entry->next)
 
779
                {
 
780
                        discrete_source_node *sn = (discrete_source_node *) src_entry->ptr;
 
781
                        sn->ptr = sn->task->node_buf[sn->output_node];
 
782
                }
 
783
        }
 
784
 
 
785
        for (entry = info->task_list; entry != 0; entry = entry->next)
 
786
        {
 
787
                /* Fire a work item for each task */
 
788
                osd_work_item_queue(info->queue, task_callback, (void *) info->task_list, WORK_ITEM_FLAG_AUTO_RELEASE);
 
789
        }
 
790
        osd_work_queue_wait(info->queue, osd_ticks_per_second()*10);
 
791
 
 
792
        if (profiling)
 
793
        {
 
794
                info->total_samples += samples;
 
795
                info->total_stream_updates++;
 
796
        }
 
797
 
503
798
}
504
799
 
505
800
 
510
805
 *
511
806
 *************************************/
512
807
 
513
 
static void init_nodes(discrete_info *info, discrete_sound_block *block_list, const device_config *device)
 
808
 
 
809
static void init_nodes(discrete_info *info, const linked_list_entry *block_list, const device_config *device)
514
810
{
515
 
        int nodenum;
516
 
 
517
 
        /* start with no outputs or input streams */
518
 
        info->discrete_outputs = 0;
519
 
        info->discrete_input_streams = 0;
 
811
        const linked_list_entry *entry;
 
812
        linked_list_entry       *task_node_list = NULL;
 
813
        discrete_task *task = NULL;
 
814
        /* list tail pointers */
 
815
        linked_list_entry       **task_node_list_ptr = NULL;
 
816
        linked_list_entry       **node_list_ptr = &info->node_list;
 
817
        linked_list_entry       **task_list_ptr = &info->task_list;
 
818
        linked_list_entry       **output_list_ptr = &info->output_list;
 
819
        linked_list_entry       **input_list_ptr = &info->input_list;
 
820
        int                                     has_tasks = 0;
 
821
 
 
822
        /* check whether we have tasks ... */
 
823
        for (entry = block_list; entry != NULL; entry = entry->next)
 
824
        {
 
825
                const discrete_sound_block *block = (discrete_sound_block *) entry->ptr;
 
826
                if (block->type == DSO_TASK_START)
 
827
                        has_tasks = 1;
 
828
        }
 
829
 
 
830
        if (!has_tasks)
 
831
        {
 
832
                /* set up a main task */
 
833
                task_node_list = NULL;
 
834
                task_node_list_ptr = &task_node_list;
 
835
        }
520
836
 
521
837
        /* loop over all nodes */
522
 
        for (nodenum = 0; nodenum < info->node_count; nodenum++)
 
838
        for (entry = block_list; entry != NULL; entry = entry->next)
523
839
        {
524
 
                discrete_sound_block *block = &block_list[nodenum];
525
 
                node_description *node = &info->node_list[nodenum];
526
 
                int inputnum, modulenum;
527
 
 
528
 
                /* our running order just follows the order specified */
529
 
                info->running_order[nodenum] = node;
 
840
                const discrete_sound_block *block = (discrete_sound_block *) entry->ptr;
 
841
                node_description *node = auto_alloc_clear(info->device->machine, node_description);
 
842
                int modulenum;
 
843
 
 
844
                /* find the requested module */
 
845
                for (modulenum = 0; module_list[modulenum].type != DSS_NULL; modulenum++)
 
846
                        if (module_list[modulenum].type == block->type)
 
847
                                break;
 
848
                if (module_list[modulenum].type != block->type)
 
849
                        fatalerror("init_nodes() - Unable to find discrete module type %d for NODE_%02d", block->type, NODE_INDEX(block->node));
 
850
 
 
851
                /* static inits */
 
852
                node->context = NULL;
 
853
                node->info = info;
 
854
                node->module = &module_list[modulenum];
 
855
                node->output[0] = 0.0;
 
856
                node->block = block;
 
857
                node->custom = block->custom;
 
858
                node->active_inputs = block->active_inputs;
 
859
                node->run_time = 0;
 
860
 
 
861
                /* setup module if custom */
 
862
                if (block->type == DST_CUSTOM)
 
863
                {
 
864
                        const discrete_custom_info *custom = (const discrete_custom_info *)node->custom;
 
865
                        node->module = &custom->module;
 
866
                        node->custom = custom->custom;
 
867
                }
 
868
 
 
869
                /* copy initial / default step function */
 
870
                node->step = node->module->step;
 
871
 
 
872
                /* allocate memory if necessary */
 
873
                if (node->module->contextsize)
 
874
                        node->context = auto_alloc_array_clear(device->machine, UINT8, node->module->contextsize);
530
875
 
531
876
                /* keep track of special nodes */
532
877
                if (block->node == NODE_SPECIAL)
535
880
                        {
536
881
                                /* Output Node */
537
882
                                case DSO_OUTPUT:
538
 
                                        if (info->discrete_outputs == DISCRETE_MAX_OUTPUTS)
539
 
                                                fatalerror("init_nodes() - There can not be more then %d output nodes", DISCRETE_MAX_OUTPUTS);
540
 
                                        info->output_node[info->discrete_outputs++] = node;
 
883
                                        linked_list_tail_add(info, &output_list_ptr, node);
541
884
                                        break;
542
885
 
543
886
                                /* CSVlog Node for debugging */
544
887
                                case DSO_CSVLOG:
545
 
                                        if (info->num_csvlogs == DISCRETE_MAX_CSVLOGS)
546
 
                                                fatalerror("init_nodes() - There can not be more then %d discrete CSV logs.", DISCRETE_MAX_WAVELOGS);
547
 
                                        info->csvlog_node[info->num_csvlogs++] = node;
548
888
                                        break;
549
889
 
550
890
                                /* Wavelog Node for debugging */
551
891
                                case DSO_WAVELOG:
552
 
                                        if (info->num_wavelogs == DISCRETE_MAX_WAVELOGS)
553
 
                                                fatalerror("init_nodes() - There can not be more then %d discrete wave logs.", DISCRETE_MAX_WAVELOGS);
554
 
                                        info->wavelog_node[info->num_wavelogs++] = node;
 
892
                                        break;
 
893
 
 
894
                                /* Task processing */
 
895
                                case DSO_TASK_START:
 
896
                                        if (task_node_list_ptr != NULL)
 
897
                                                fatalerror("init_nodes() - Nested DISCRETE_START_TASK.");
 
898
                                        task = auto_alloc_clear(info->device->machine, discrete_task);
 
899
                                        node->context = task;
 
900
                                        task_node_list = NULL;
 
901
                                        task_node_list_ptr = &task_node_list;
 
902
                                        break;
 
903
 
 
904
                                case DSO_TASK_END:
 
905
                                        if (task_node_list_ptr == NULL)
 
906
                                                fatalerror("init_nodes() - NO DISCRETE_START_TASK.");
 
907
                                        task->numbuffered = 0;
 
908
                                        task->list = task_node_list;
 
909
                                        task->task_group = -1; /* will be set later */
 
910
                                        task->source_list = NULL;
 
911
                                        linked_list_tail_add(info, &task_list_ptr, task);
 
912
                                        node->context = task;
 
913
                                        task = NULL;
 
914
                                        task_node_list = NULL;
555
915
                                        break;
556
916
 
557
917
                                default:
567
927
                        info->indexed_node[NODE_INDEX(block->node)] = node;
568
928
                }
569
929
 
570
 
                /* find the requested module */
571
 
                for (modulenum = 0; module_list[modulenum].type != DSS_NULL; modulenum++)
572
 
                        if (module_list[modulenum].type == block->type)
573
 
                                break;
574
 
                if (module_list[modulenum].type != block->type)
575
 
                        fatalerror("init_nodes() - Unable to find discrete module type %d for NODE_%02d", block->type, NODE_INDEX(block->node));
576
 
 
577
 
                /* static inits */
578
 
                node->node = block->node;
579
 
                node->module = module_list[modulenum];
580
 
                node->output[0] = 0.0;
581
 
                node->block = block;
582
 
 
583
 
                node->active_inputs = block->active_inputs;
584
 
                for (inputnum = 0; inputnum < DISCRETE_MAX_INPUTS; inputnum++)
585
 
                {
586
 
                        node->input[inputnum] = &(block->initial[inputnum]);
587
 
                }
588
 
 
589
 
                node->context = NULL;
590
 
                node->name = block->name;
591
 
                node->custom = block->custom;
592
 
 
593
 
                /* setup module if custom */
594
 
                if (block->type == DST_CUSTOM)
595
 
                {
596
 
                        const discrete_custom_info *custom = (const discrete_custom_info *)node->custom;
597
 
                        node->module.reset = custom->reset;
598
 
                        node->module.step = custom->step;
599
 
                        node->module.contextsize = custom->contextsize;
600
 
                        node->custom = custom->custom;
601
 
                }
602
 
 
603
 
                /* allocate memory if necessary */
604
 
                if (node->module.contextsize)
605
 
                        node->context = auto_alloc_array_clear(device->machine, UINT8, node->module.contextsize);
606
 
 
607
930
                /* if we are an stream input node, track that */
608
931
                if (block->type == DSS_INPUT_STREAM)
609
932
                {
610
 
                        if (info->discrete_input_streams == DISCRETE_MAX_OUTPUTS)
611
 
                                fatalerror("init_nodes() - There can not be more then %d input stream nodes", DISCRETE_MAX_OUTPUTS);
612
 
                        /* we will use the node's context pointer to point to the input stream data */
613
 
                        //node->context = &info->input_stream_data[info->discrete_input_streams++];
614
 
                        node->context = NULL;
615
 
                        info->discrete_input_streams++;
 
933
                        linked_list_tail_add(info, &input_list_ptr, node);
 
934
                }
 
935
                else if (block->type == DSS_INPUT_BUFFER)
 
936
                {
 
937
                        linked_list_tail_add(info, &input_list_ptr, node);
 
938
                }
 
939
 
 
940
                /* add to node list */
 
941
                linked_list_tail_add(info, &node_list_ptr, node);
 
942
 
 
943
                /* our running order just follows the order specified */
 
944
                /* does the node step ? */
 
945
                if (node->step != NULL)
 
946
                {
 
947
                        /* do we belong to a task? */
 
948
                        if (task_node_list_ptr == NULL)
 
949
                                fatalerror("init_nodes() - found node outside of task.");
 
950
                        else
 
951
                                linked_list_tail_add(info, &task_node_list_ptr, node);
 
952
                }
 
953
 
 
954
                if (block->type == DSO_TASK_END)
 
955
                {
 
956
                        task_node_list_ptr = NULL;
616
957
                }
617
958
 
618
959
                /* and register save state */
619
 
                state_save_register_device_item_array(device, nodenum, node->output);
 
960
                if (node->block->node != NODE_SPECIAL)
 
961
                        state_save_register_device_item_array(device, node->block->node, node->output);
 
962
        }
 
963
 
 
964
        if (!has_tasks)
 
965
        {
 
966
                /* make sure we have one simple task
 
967
         * No need to create a node since there are no dependencies.
 
968
         */
 
969
                task = auto_alloc_clear(info->device->machine, discrete_task);
 
970
                task->numbuffered = 0;
 
971
                task->list = task_node_list;
 
972
                task->task_group = 0;
 
973
                task->source_list = NULL;
 
974
                linked_list_tail_add(info, &task_list_ptr, task);
620
975
        }
621
976
 
622
977
        /* if no outputs, give an error */
623
 
        if (info->discrete_outputs == 0)
 
978
        if (linked_list_count(info->output_list) == 0)
624
979
                fatalerror("init_nodes() - Couldn't find an output node");
625
980
}
626
981
 
627
982
 
628
 
 
629
983
/*************************************
630
984
 *
631
985
 *  Find and attach all input nodes
632
986
 *
633
987
 *************************************/
634
988
 
635
 
static void find_input_nodes(discrete_info *info, discrete_sound_block *block_list)
636
 
{
637
 
        int nodenum, inputnum;
 
989
/* attempt to group all static node parameters together.
 
990
 * Has a negative impact on performance - but it should
 
991
 * reduce memory bandwidth - this is weird. */
 
992
 
 
993
#if 0
 
994
static double dbuf[10240] = { 0.0, 1.0 };
 
995
static int dbufptr = 2;
 
996
 
 
997
static double *getDoublePtr(double val)
 
998
{
 
999
        int i;
 
1000
        for (i=0; i<dbufptr; i+=1)
 
1001
        {
 
1002
                if (dbuf[i] == val)
 
1003
                {
 
1004
                        return &dbuf[i];
 
1005
                }
 
1006
        }
 
1007
        dbuf[dbufptr] = val;
 
1008
        dbufptr+=1;
 
1009
        return &dbuf[dbufptr-1];
 
1010
}
 
1011
#endif
 
1012
 
 
1013
static void find_input_nodes(const discrete_info *info)
 
1014
{
 
1015
        const linked_list_entry *entry;
 
1016
        int inputnum;
638
1017
 
639
1018
        /* loop over all nodes */
640
 
        for (nodenum = 0; nodenum < info->node_count; nodenum++)
 
1019
        for (entry = info->node_list; entry != NULL; entry = entry->next)
641
1020
        {
642
 
                node_description *node = &info->node_list[nodenum];
643
 
                discrete_sound_block *block = &block_list[nodenum];
 
1021
                node_description *node = (node_description *) entry->ptr;
 
1022
                const discrete_sound_block *block = node->block;
644
1023
 
645
1024
                /* loop over all active inputs */
646
1025
                for (inputnum = 0; inputnum < node->active_inputs; inputnum++)
650
1029
                        /* if this input is node-based, find the node in the indexed list */
651
1030
                        if IS_VALUE_A_NODE(inputnode)
652
1031
                        {
653
 
                                node_description *node_ref = info->indexed_node[NODE_INDEX(inputnode)];
 
1032
                                const node_description *node_ref = info->indexed_node[NODE_INDEX(inputnode)];
654
1033
                                if (!node_ref)
655
 
                                        fatalerror("discrete_start - NODE_%02d referenced a non existent node NODE_%02d", NODE_INDEX(node->node), NODE_INDEX(inputnode));
 
1034
                                        fatalerror("discrete_start - NODE_%02d referenced a non existent node NODE_%02d", NODE_BLOCKINDEX(node), NODE_INDEX(inputnode));
656
1035
 
657
 
                                if (NODE_CHILD_NODE_NUM(inputnode) >= node_ref->module.num_output)
658
 
                                        fatalerror("discrete_start - NODE_%02d referenced non existent output %d on node NODE_%02d", NODE_INDEX(node->node), NODE_CHILD_NODE_NUM(inputnode), NODE_INDEX(inputnode));
 
1036
                                if (NODE_CHILD_NODE_NUM(inputnode) >= node_ref->module->num_output)
 
1037
                                        fatalerror("discrete_start - NODE_%02d referenced non existent output %d on node NODE_%02d", NODE_BLOCKINDEX(node), NODE_CHILD_NODE_NUM(inputnode), NODE_INDEX(inputnode));
659
1038
 
660
1039
                                node->input[inputnum] = &(node_ref->output[NODE_CHILD_NODE_NUM(inputnode)]);    /* Link referenced node out to input */
661
1040
                                node->input_is_node |= 1 << inputnum;                   /* Bit flag if input is node */
665
1044
                                /* warn if trying to use a node for an input that can only be static */
666
1045
                                if IS_VALUE_A_NODE(block->initial[inputnum])
667
1046
                                {
668
 
                                        discrete_log("Warning - discrete_start - NODE_%02d trying to use a node on static input %d",  NODE_INDEX(node->node), inputnum);
 
1047
                                        discrete_log(info, "Warning - discrete_start - NODE_%02d trying to use a node on static input %d",  NODE_BLOCKINDEX(node), inputnum);
669
1048
                                        /* also report it in the error log so it is not missed */
670
 
                                        logerror("Warning - discrete_start - NODE_%02d trying to use a node on static input %d",  NODE_INDEX(node->node), inputnum);
 
1049
                                        logerror("Warning - discrete_start - NODE_%02d trying to use a node on static input %d",  NODE_BLOCKINDEX(node), inputnum);
 
1050
                                }
 
1051
                                else
 
1052
                                {
 
1053
                                        node->input[inputnum] = &(node->block->initial[inputnum]);
 
1054
                                        //node->input[inputnum] = getDoublePtr(node->block->initial[inputnum]);
671
1055
                                }
672
1056
                        }
673
1057
                }
674
 
        }
675
 
}
676
 
 
677
 
 
678
 
 
679
 
/*************************************
680
 
 *
681
 
 *  Set up the output nodes
682
 
 *
683
 
 *************************************/
684
 
 
685
 
static void setup_output_nodes(const device_config *device, discrete_info *info)
686
 
{
687
 
        /* initialize the stream(s) */
688
 
        info->discrete_stream = stream_create(device, info->discrete_input_streams, info->discrete_outputs, info->sample_rate, info, discrete_stream_update);
689
 
}
690
 
 
691
 
 
692
 
 
693
 
/*************************************
694
 
 *
695
 
 *  Set up the logs
696
 
 *
697
 
 *************************************/
698
 
 
699
 
static void setup_disc_logs(discrete_info *info)
700
 
{
701
 
        int log_num, node_num;
702
 
        char name[32];
703
 
 
704
 
        for (log_num = 0; log_num < info->num_csvlogs; log_num++)
705
 
        {
706
 
                sprintf(name, "discrete%s_%d.csv", info->device->tag, log_num);
707
 
                info->disc_csv_file[log_num] = fopen(name, "w");
708
 
                /* Output some header info */
709
 
                fprintf(info->disc_csv_file[log_num], "\"MAME Discrete System Node Log\"\n");
710
 
                fprintf(info->disc_csv_file[log_num], "\"Log Version\", 1.0\n");
711
 
                fprintf(info->disc_csv_file[log_num], "\"Sample Rate\", %d\n", info->sample_rate);
712
 
                fprintf(info->disc_csv_file[log_num], "\n");
713
 
                fprintf(info->disc_csv_file[log_num], "\"Sample\"");
714
 
                for (node_num = 0; node_num < info->csvlog_node[log_num]->active_inputs; node_num++)
 
1058
                for (inputnum = node->active_inputs; inputnum < DISCRETE_MAX_INPUTS; inputnum++)
715
1059
                {
716
 
                        fprintf(info->disc_csv_file[log_num], ", \"NODE_%2d\"", NODE_INDEX(info->csvlog_node[log_num]->block->input_node[node_num]));
 
1060
                        /* FIXME: Check that no nodes follow ! */
 
1061
                        node->input[inputnum] = &(block->initial[inputnum]);
717
1062
                }
718
 
                fprintf(info->disc_csv_file[log_num], "\n");
719
 
        }
720
 
 
721
 
        for (log_num = 0; log_num < info->num_wavelogs; log_num++)
722
 
        {
723
 
                sprintf(name, "discrete%s_%d.wav", info->device->tag, log_num);
724
 
                info->disc_wav_file[log_num] = wav_open(name, info->sample_rate, info->wavelog_node[log_num]->active_inputs/2);
725
1063
        }
726
1064
}
727
1065
 
728
 
 
729
 
 
730
1066
/**************************************************************************
731
1067
 * Generic get_info
732
1068
 **************************************************************************/
745
1081
 
746
1082
                /* --- the following bits of info are returned as NULL-terminated strings --- */
747
1083
                case DEVINFO_STR_NAME:                                                  strcpy(info->s, "Discrete");                                            break;
748
 
                case DEVINFO_STR_FAMILY:                                        strcpy(info->s, "Analog");                                                      break;
749
 
                case DEVINFO_STR_VERSION:                                       strcpy(info->s, "1.1");                                                         break;
750
 
                case DEVINFO_STR_SOURCE_FILE:                                           strcpy(info->s, __FILE__);                                                      break;
751
 
                case DEVINFO_STR_CREDITS:                                       strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
 
1084
                case DEVINFO_STR_FAMILY:                                                strcpy(info->s, "Analog");                                                      break;
 
1085
                case DEVINFO_STR_VERSION:                                               strcpy(info->s, "1.1");                                                         break;
 
1086
                case DEVINFO_STR_SOURCE_FILE:                                   strcpy(info->s, __FILE__);                                                      break;
 
1087
                case DEVINFO_STR_CREDITS:                                               strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
752
1088
        }
753
1089
}
754
1090