Discrete work - this one needs a full recompile

- change the way custom modules are handled
- updated drivers mario and dkong accordingly
- minor change to stream input handling
- no more linear lists for nodes. All node processing switched to linked lists.
- module step and reset now only get a node pointer passed
- Added discrete_info * pointer to node
- Only nodes with a step routine actually get processed.
- Fixed a bug: discrete logs did not work since some time
- preliminary parallel task constants; depending on results these may vanish again.
- Overall slight performance increase. dkong 940% to 960%, galaxian 740% to 790%
This commit is contained in:
Couriersud 2009-08-23 19:04:41 +00:00
parent dc0df4572e
commit 20caff1c3b
9 changed files with 374 additions and 274 deletions

View File

@ -234,7 +234,7 @@ static DISCRETE_STEP(dsd_555_astbl)
* dt = R*C(log(1/(1-(Vc/Vr))))
*/
dt = disc_info->sample_time;
dt = node->info->sample_time;
/* Sometimes a switching network is used to setup the capacitance.
* These may select no capacitor, causing oscillation to stop.
@ -338,7 +338,7 @@ static DISCRETE_STEP(dsd_555_astbl)
}
/* Convert last switch time to a ratio */
x_time = x_time / disc_info->sample_time;
x_time = x_time / node->info->sample_time;
switch (context->output_type)
{
@ -387,7 +387,7 @@ static DISCRETE_RESET(dsd_555_astbl)
context->v_out_high = (info->v_out_high == DEFAULT_555_HIGH) ? info->v_pos - 1.2 : info->v_out_high;
/* setup v_charge or node */
v_charge_node = discrete_find_node(disc_info, info->v_charge);
v_charge_node = discrete_find_node(node->info, info->v_charge);
if (v_charge_node)
context->v_charge_node = &(v_charge_node->output[NODE_CHILD_NODE_NUM(info->v_charge)]);
else
@ -548,7 +548,7 @@ static DISCRETE_RESET(dsd_555_mstbl)
context->output_type = info->options & DISC_555_OUT_MASK;
if ((context->output_type == DISC_555_OUT_COUNT_F) || (context->output_type == DISC_555_OUT_COUNT_R))
{
discrete_log(disc_info, "Invalid Output type in NODE_%d.\n", node->node - NODE_00);
discrete_log(node->info, "Invalid Output type in NODE_%d.\n", node->node - NODE_00);
context->output_type = DISC_555_OUT_SQW;
}
@ -642,7 +642,7 @@ static DISCRETE_STEP(dsd_555_cc)
return;
}
dt = disc_info->sample_time; /* Change in time */
dt = node->info->sample_time; /* Change in time */
v_cap = context->cap_voltage; /* Set to voltage before change */
v_vcharge_limit = DSD_555_CC__VIN + info->v_cc_junction; /* the max v_cap can be and still be charged by i */
/* Calculate charging current */
@ -888,7 +888,7 @@ static DISCRETE_STEP(dsd_555_cc)
context->cap_voltage = v_cap_next;
/* Convert last switch time to a ratio */
x_time = x_time / disc_info->sample_time;
x_time = x_time / node->info->sample_time;
switch (context->output_type)
{
@ -1171,7 +1171,7 @@ static DISCRETE_STEP(dsd_555_vco1)
double v_cap; /* Current voltage on capacitor, before dt */
double v_cap_next = 0; /* Voltage on capacitor, after dt */
dt = disc_info->sample_time; /* Change in time */
dt = node->info->sample_time; /* Change in time */
v_cap = context->cap_voltage;
/* Check: if the Control Voltage node is connected. */
@ -1275,7 +1275,7 @@ static DISCRETE_STEP(dsd_555_vco1)
context->cap_voltage = v_cap_next;
/* Convert last switch time to a ratio. No x_time in reset. */
x_time = x_time / disc_info->sample_time;
x_time = x_time / node->info->sample_time;
if (!DSD_555_VCO1__RESET) x_time = 0;
switch (context->output_type)
@ -1403,7 +1403,7 @@ static DISCRETE_STEP(dsd_566)
if (DSD_566__ENABLE && !context->error)
{
dt = disc_info->sample_time; /* Change in time */
dt = node->info->sample_time; /* Change in time */
v_cap = context->cap_voltage; /* Set to voltage before change */
/* get the v_charge and update each step if it is a node */
@ -1528,7 +1528,7 @@ static DISCRETE_RESET(dsd_566)
}
/* setup v_charge or node */
v_charge_node = discrete_find_node(disc_info, info->v_charge);
v_charge_node = discrete_find_node(node->info, info->v_charge);
if (v_charge_node)
context->v_charge_node = &(v_charge_node->output[NODE_CHILD_NODE_NUM(info->v_charge)]);
else
@ -1608,7 +1608,7 @@ static DISCRETE_STEP(dsd_ls624)
double en = 0.0f;
int cntf = 0, cntr = 0;
sample_t = disc_info->sample_time; /* Change in time */
sample_t = node->info->sample_time; /* Change in time */
//dt = LS624_T(DSD_LS624__C, DSD_LS624__VRNG, DSD_LS624__VMOD) / 2.0;
dt = 1.0f / (2.0f * LS624_F(DSD_LS624__C, DSD_LS624__VMOD, DSD_LS624__VRNG));
t = context->remain;

View File

@ -229,7 +229,7 @@ static DISCRETE_RESET(dst_filter1)
{
struct dss_filter1_context *context = (struct dss_filter1_context *)node->context;
calculate_filter1_coefficients(disc_info, DST_FILTER1__FREQ, DST_FILTER1__TYPE, &context->a1, &context->b0, &context->b1);
calculate_filter1_coefficients(node->info, DST_FILTER1__FREQ, DST_FILTER1__TYPE, &context->a1, &context->b0, &context->b1);
node->output[0] = 0;
}
@ -259,7 +259,7 @@ static void calculate_filter2_coefficients(const discrete_info *disc_info,
double w; /* cutoff freq, in radians/sec */
double w_squared;
double den; /* temp variable */
double two_over_T = 2*disc_info->sample_rate;
double two_over_T = 2 * disc_info->sample_rate;
double two_over_T_squared = two_over_T * two_over_T;
/* calculate digital filter coefficents */
@ -318,7 +318,7 @@ static DISCRETE_RESET(dst_filter2)
{
struct dss_filter2_context *context = (struct dss_filter2_context *)node->context;
calculate_filter2_coefficients(disc_info, DST_FILTER2__FREQ, DST_FILTER2__DAMP, DST_FILTER2__TYPE,
calculate_filter2_coefficients(node->info, DST_FILTER2__FREQ, DST_FILTER2__DAMP, DST_FILTER2__TYPE,
&context->a1, &context->a2,
&context->b0, &context->b1, &context->b2);
node->output[0] = 0;
@ -508,7 +508,7 @@ static DISCRETE_RESET(dst_op_amp_filt)
double d = (info->c1 + info->c2) / sqrt(info->rF / context->rTotal * info->c1 * info->c2);
double gain = -info->rF / context->rTotal * info->c2 / (info->c1 + info->c2);
calculate_filter2_coefficients(disc_info, fc, d, DISC_FILTER_BANDPASS,
calculate_filter2_coefficients(node->info, fc, d, DISC_FILTER_BANDPASS,
&context->a1, &context->a2,
&context->b0, &context->b1, &context->b2);
context->b0 *= gain;
@ -577,7 +577,7 @@ static DISCRETE_STEP(dst_rcdisc)
if (DST_RCDISC__ENABLE)
{
node->output[0] = DST_RCDISC__IN * exp(context->t / context->exponent0);
context->t += disc_info->sample_time;
context->t += node->info->sample_time;
} else
{
context->state = 0;
@ -780,17 +780,17 @@ static DISCRETE_RESET( dst_rcdisc4)
/* some error checking. */
if (DST_RCDISC4__R1 <= 0 || DST_RCDISC4__R2 <= 0 || DST_RCDISC4__C1 <= 0 || (DST_RCDISC4__R3 <= 0 && context->type == 1))
{
discrete_log(disc_info, "Invalid component values in NODE_%d.\n", node->node - NODE_00);
discrete_log(node->info, "Invalid component values in NODE_%d.\n", node->node - NODE_00);
return;
}
if (DST_RCDISC4__VP < 3)
{
discrete_log(disc_info, "vP must be >= 3V in NODE_%d.\n", node->node - NODE_00);
discrete_log(node->info, "vP must be >= 3V in NODE_%d.\n", node->node - NODE_00);
return;
}
if (DST_RCDISC4__TYPE < 1 || DST_RCDISC4__TYPE > 3)
{
discrete_log(disc_info, "Invalid circuit type in NODE_%d.\n", node->node - NODE_00);
discrete_log(node->info, "Invalid circuit type in NODE_%d.\n", node->node - NODE_00);
return;
}
@ -1236,7 +1236,7 @@ static DISCRETE_RESET(dst_rcintegrate)
struct dst_rcintegrate_context *context = (struct dst_rcintegrate_context *)node->context;
double r;
double dt = disc_info->sample_time;
double dt = node->info->sample_time;
context->type = DST_RCINTEGRATE__TYPE;
@ -1312,7 +1312,7 @@ static DISCRETE_RESET(dst_sallen_key)
fatalerror("Unknown sallen key filter type");
}
calculate_filter2_coefficients(disc_info, freq, 1.0 / q, DISC_FILTER_LOWPASS,
calculate_filter2_coefficients(node->info, freq, 1.0 / q, DISC_FILTER_LOWPASS,
&context->a1, &context->a2,
&context->b0, &context->b1, &context->b2);
node->output[0] = 0;
@ -1460,8 +1460,8 @@ static DISCRETE_RESET(dst_rcdisc2N)
f1 = 1.0 / (2 * M_PI * DST_RCDISC2N__R0 * DST_RCDISC2N__C);
f2 = 1.0 / (2 * M_PI * DST_RCDISC2N__R1 * DST_RCDISC2N__C);
calculate_filter1_coefficients(disc_info, f1, DISC_FILTER_LOWPASS, &context->a1_0, &context->b0_0, &context->b1_0);
calculate_filter1_coefficients(disc_info, f2, DISC_FILTER_LOWPASS, &context->a1_1, &context->b0_1, &context->b1_1);
calculate_filter1_coefficients(node->info, f1, DISC_FILTER_LOWPASS, &context->a1_0, &context->b0_0, &context->b1_0);
calculate_filter1_coefficients(node->info, f2, DISC_FILTER_LOWPASS, &context->a1_1, &context->b0_1, &context->b1_1);
/* Initialize the object */
node->output[0] = 0;

View File

@ -15,6 +15,8 @@
*
************************************************************************/
#define EXPERIMENTAL_STREAM_PARALLEL (0)
#define DSS_INPUT__GAIN (*(node->input[0]))
#define DSS_INPUT__OFFSET (*(node->input[1]))
#define DSS_INPUT__INIT (*(node->input[2]))
@ -54,7 +56,7 @@ READ8_DEVICE_HANDLER(discrete_sound_r)
/* Bring the system up to now */
stream_update(info->discrete_stream);
if ((node->module.type >= DSS_INPUT_DATA) && (node->module.type <= DSS_INPUT_PULSE))
if ((node->module->type >= DSS_INPUT_DATA) && (node->module->type <= DSS_INPUT_PULSE))
{
data = *node_data;
}
@ -65,7 +67,7 @@ READ8_DEVICE_HANDLER(discrete_sound_r)
return data;
}
#if 0
#if EXPERIMENTAL_STREAM_PARALLEL
static STREAM_BACKGROUND_CALLBACK( disc_cb )
{
node_description *node = (node_description *) ptr;
@ -86,7 +88,7 @@ WRITE8_DEVICE_HANDLER(discrete_sound_w)
UINT8 last_data = *node_data;
UINT8 new_data = 0;
switch (node->module.type)
switch (node->module->type)
{
case DSS_INPUT_DATA:
new_data = data;
@ -102,7 +104,7 @@ WRITE8_DEVICE_HANDLER(discrete_sound_w)
if (last_data != new_data)
{
#if 1
#if !EXPERIMENTAL_STREAM_PARALLEL
/* Bring the system up to now */
stream_update(info->discrete_stream);
@ -172,12 +174,12 @@ static DISCRETE_RESET(dss_adjustment)
if (node->custom)
{
context->port = input_port_by_tag(disc_info->device->machine->portconfig, (const char *)node->custom);
context->port = input_port_by_tag(node->info->device->machine->portconfig, (const char *)node->custom);
if (context->port == NULL)
fatalerror("DISCRETE_ADJUSTMENT_TAG - NODE_%d has invalid tag", node->node-NODE_00);
}
else
context->port = input_port_by_index(disc_info->device->machine->portconfig, DSS_ADJUSTMENT__PORT);
context->port = input_port_by_index(node->info->device->machine->portconfig, DSS_ADJUSTMENT__PORT);
context->lastpval = 0x7fffffff;
context->pmin = DSS_ADJUSTMENT__PMIN;
@ -233,7 +235,7 @@ static DISCRETE_RESET(dss_input)
{
UINT8 *node_data = (UINT8 *)node->context;
switch (node->module.type)
switch (node->module->type)
{
case DSS_INPUT_DATA:
*node_data = DSS_INPUT__INIT;
@ -280,13 +282,19 @@ static DISCRETE_STEP(dss_input_stream)
stream_sample_t **ptr = (stream_sample_t **)node->context;
stream_sample_t *data = *ptr;
node->output[0] = data ? (*data) * DSS_INPUT_STREAM__GAIN + DSS_INPUT_STREAM__OFFSET : 0;
if (data)
{
node->output[0] = (*data) * DSS_INPUT_STREAM__GAIN + DSS_INPUT_STREAM__OFFSET;
(*ptr)++;
}
else
node->output[0] = 0;
}
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 < disc_info->discrete_input_streams);
node->context = (discrete_info *) &disc_info->input_stream_data[istream];
assert(istream < node->info->discrete_input_streams);
node->context = (discrete_info *) &node->info->input_stream_data[istream];
}

View File

@ -384,11 +384,11 @@ static DISCRETE_RESET(dst_dac_r1)
if (info->ladderLength < 2)
{
/* You need at least 2 resistors for a ladder */
discrete_log(disc_info, "dst_dac_r1_reset - Ladder length too small");
discrete_log(node->info, "dst_dac_r1_reset - Ladder length too small");
}
if (info->ladderLength > DISC_LADDER_MAXRES )
{
discrete_log(disc_info, "dst_dac_r1_reset - Ladder length exceeds DISC_LADDER_MAXRES");
discrete_log(node->info, "dst_dac_r1_reset - Ladder length exceeds DISC_LADDER_MAXRES");
}
/*
@ -491,7 +491,7 @@ static DISCRETE_STEP(dst_divide)
if(DST_DIVIDE__DIV == 0)
{
node->output[0 ]= DBL_MAX; /* Max out but don't break */
discrete_log(disc_info, "dst_divider_step() - Divide by Zero attempted in NODE_%02d.\n",NODE_INDEX(node->node));
discrete_log(node->info, "dst_divider_step() - Divide by Zero attempted in NODE_%02d.\n",NODE_INDEX(node->node));
}
else
{
@ -609,7 +609,7 @@ static DISCRETE_STEP(dst_integrate)
i_neg = context->v_max_in / info->r1;
i_pos = (DST_INTEGRATE__TRG0 - OP_AMP_NORTON_VBE) / info->r2;
if (i_pos < 0) i_pos = 0;
node->output[0] += (i_pos - i_neg) / disc_info->sample_rate / info->c;
node->output[0] += (i_pos - i_neg) / node->info->sample_rate / info->c;
break;
case DISC_INTEGRATE_OP_AMP_2 | DISC_OP_AMP_IS_NORTON:
@ -618,7 +618,7 @@ static DISCRETE_STEP(dst_integrate)
i_neg = dst_trigger_function(trig0, trig1, 0, info->f0) ? context->v_max_in_d / info->r1 : 0;
i_pos = dst_trigger_function(trig0, trig1, 0, info->f1) ? context->v_max_in / info->r2 : 0;
i_pos += dst_trigger_function(trig0, trig1, 0, info->f2) ? context->v_max_in_d / info->r3 : 0;
node->output[0] += (i_pos - i_neg) / disc_info->sample_rate / info->c;
node->output[0] += (i_pos - i_neg) / node->info->sample_rate / info->c;
break;
}
@ -646,7 +646,7 @@ static DISCRETE_RESET(dst_integrate)
v = info->v1 * info->r3 / (info->r2 + info->r3); /* vRef */
v = info->v1 - v; /* actual charging voltage */
i = v / info->r1;
context->change = i / disc_info->sample_rate / info->c;
context->change = i / node->info->sample_rate / info->c;
}
node->output[0] = 0;
}
@ -1227,7 +1227,7 @@ static DISCRETE_RESET(dst_mixer)
context->r_node_bit_flag = 0;
for (bit = 0; bit < 8; bit++)
{
r_node = discrete_find_node(disc_info, info->r_node[bit]);
r_node = discrete_find_node(node->info, info->r_node[bit]);
if (r_node != NULL)
{
context->r_node[bit] = &(r_node->output[NODE_CHILD_NODE_NUM(info->r_node[bit])]);
@ -1354,7 +1354,7 @@ static DISCRETE_STEP(dst_multiplex)
else
{
/* Bad address. We will leave the output alone. */
discrete_log(disc_info, "NODE_%02d - Address = %d. Out of bounds\n", node->node-NODE_00, addr);
discrete_log(node->info, "NODE_%02d - Address = %d. Out of bounds\n", node->node-NODE_00, addr);
}
}
else
@ -1439,7 +1439,7 @@ static DISCRETE_STEP(dst_oneshot)
if (do_count)
{
context->countdown -= disc_info->sample_time;
context->countdown -= node->info->sample_time;
if(context->countdown <= 0.0)
{
node->output[0] = (DST_ONESHOT__TYPE & DISC_OUT_ACTIVE_LOW) ? DST_ONESHOT__AMP : 0;
@ -1514,7 +1514,7 @@ static DISCRETE_RESET(dst_ramp)
struct dss_ramp_context *context = (struct dss_ramp_context *)node->context;
node->output[0] = DST_RAMP__CLAMP;
context->step = DST_RAMP__GRAD / disc_info->sample_rate;
context->step = DST_RAMP__GRAD / node->info->sample_rate;
context->dir = ((DST_RAMP__END - DST_RAMP__START) == abs(DST_RAMP__END - DST_RAMP__START));
context->last_en = 0;
}
@ -1560,7 +1560,7 @@ static DISCRETE_STEP(dst_samphold)
if (DST_SAMPHOLD__CLOCK == 0) node->output[0] = DST_SAMPHOLD__IN0;
break;
default:
discrete_log(disc_info, "dst_samphold_step - Invalid clocktype passed");
discrete_log(node->info, "dst_samphold_step - Invalid clocktype passed");
break;
}
}
@ -1762,7 +1762,7 @@ static DISCRETE_STEP(dst_transform)
top = (int)number1 ^ (int)top;
break;
default:
discrete_log(disc_info, "dst_transform_step - Invalid function type/variable passed");
discrete_log(node->info, "dst_transform_step - Invalid function type/variable passed");
node->output[0] = 0;
break;
}
@ -1869,7 +1869,7 @@ static DISCRETE_RESET(dst_op_amp)
}
else
/* linear charge */
context->exponent = disc_info->sample_rate * info->c;
context->exponent = node->info->sample_rate * info->c;
}
if (info->r3 > 0)

View File

@ -199,10 +199,10 @@ static DISCRETE_STEP(dss_counter)
if (context->clock_type == DISC_CLK_IS_FREQ)
{
/* We need to keep clocking the internal clock even if disabled. */
cycles = (context->t_left + disc_info->sample_time) * ds_clock;
cycles = (context->t_left + node->info->sample_time) * ds_clock;
inc = (int)cycles;
context->t_left = (cycles - inc) / ds_clock;
if (inc) x_time = context->t_left / disc_info->sample_time;
if (inc) x_time = context->t_left / node->info->sample_time;
}
else
{
@ -401,7 +401,7 @@ static DISCRETE_STEP(dss_lfsr)
if (lfsr_desc->clock_type == DISC_CLK_IS_FREQ)
{
/* We need to keep clocking the internal clock even if disabled. */
cycles = (context->t_left + disc_info->sample_time) / context->t_clock;
cycles = (context->t_left + node->info->sample_time) / context->t_clock;
inc = (int)cycles;
context->t_left = (cycles - inc) * context->t_clock;
}
@ -445,22 +445,22 @@ static DISCRETE_STEP(dss_lfsr)
fbresult = (context->lfsr_reg >> lfsr_desc->bitlength) & 0x01;
/* Stage 2 feedback combine fbresultNew with infeed bit */
fbresult = dss_lfsr_function(disc_info, lfsr_desc->feedback_function1, fbresult, noise_feed, 0x01);
fbresult = dss_lfsr_function(node->info, lfsr_desc->feedback_function1, fbresult, noise_feed, 0x01);
/* Stage 3 first we setup where the bit is going to be shifted into */
fbresult = fbresult * lfsr_desc->feedback_function2_mask;
/* Then we left shift the register, */
context->lfsr_reg = context->lfsr_reg << 1;
/* Now move the fbresult into the shift register and mask it to the bitlength */
context->lfsr_reg = dss_lfsr_function(disc_info, lfsr_desc->feedback_function2, fbresult, context->lfsr_reg, (1 << lfsr_desc->bitlength) - 1 );
context->lfsr_reg = dss_lfsr_function(node->info, lfsr_desc->feedback_function2, fbresult, context->lfsr_reg, (1 << lfsr_desc->bitlength) - 1 );
/* Now get and store the new feedback result */
/* Fetch the feedback bits */
fb0 = (context->lfsr_reg >> lfsr_desc->feedback_bitsel0) & 0x01;
fb1 = (context->lfsr_reg >> lfsr_desc->feedback_bitsel1) & 0x01;
/* Now do the combo on them */
fbresult = dss_lfsr_function(disc_info, lfsr_desc->feedback_function0, fb0, fb1, 0x01);
context->lfsr_reg = dss_lfsr_function(disc_info, DISC_LFSR_REPLACE, context->lfsr_reg, fbresult << lfsr_desc->bitlength, (2 << lfsr_desc->bitlength) - 1);
fbresult = dss_lfsr_function(node->info, lfsr_desc->feedback_function0, fb0, fb1, 0x01);
context->lfsr_reg = dss_lfsr_function(node->info, DISC_LFSR_REPLACE, context->lfsr_reg, fbresult << lfsr_desc->bitlength, (2 << lfsr_desc->bitlength) - 1);
}
/* Now select the output bit */
@ -500,7 +500,7 @@ static DISCRETE_RESET(dss_lfsr)
context->out_lfsr_reg = (lfsr_desc->flags & DISC_LFSR_FLAG_OUTPUT_SR_SN1) ? 1 : 0;
if ((lfsr_desc->clock_type < DISC_CLK_ON_F_EDGE) || (lfsr_desc->clock_type > DISC_CLK_IS_FREQ))
discrete_log(disc_info, "Invalid clock type passed in NODE_%d\n", NODE_INDEX(node->node));
discrete_log(node->info, "Invalid clock type passed in NODE_%d\n", NODE_INDEX(node->node));
context->last = (DSS_COUNTER__CLOCK != 0);
if (lfsr_desc->clock_type == DISC_CLK_IS_FREQ) context->t_clock = 1.0 / DSS_LFSR_NOISE__CLOCK;
@ -513,8 +513,8 @@ static DISCRETE_RESET(dss_lfsr)
fb0 = (context->lfsr_reg >> lfsr_desc->feedback_bitsel0) & 0x01;
fb1=(context->lfsr_reg >> lfsr_desc->feedback_bitsel1) & 0x01;
/* Now do the combo on them */
fbresult = dss_lfsr_function(disc_info, lfsr_desc->feedback_function0, fb0, fb1, 0x01);
context->lfsr_reg=dss_lfsr_function(disc_info, DISC_LFSR_REPLACE, context->lfsr_reg, fbresult << lfsr_desc->bitlength, (2<< lfsr_desc->bitlength ) - 1);
fbresult = dss_lfsr_function(node->info, lfsr_desc->feedback_function0, fb0, fb1, 0x01);
context->lfsr_reg=dss_lfsr_function(node->info, DISC_LFSR_REPLACE, context->lfsr_reg, fbresult << lfsr_desc->bitlength, (2<< lfsr_desc->bitlength ) - 1);
/* Now select and setup the output bit */
node->output[0] = (context->lfsr_reg >> lfsr_desc->output_bit) & 0x01;
@ -554,7 +554,7 @@ static DISCRETE_STEP(dss_noise)
if(context->phase > (2.0 * M_PI))
{
/* GCC's rand returns a RAND_MAX value of 0x7fff */
int newval = (mame_rand(disc_info->device->machine) & 0x7fff) - 16384;
int newval = (mame_rand(node->info->device->machine) & 0x7fff) - 16384;
/* make sure the peak to peak values are the amplitude */
node->output[0] = DSS_NOISE__AMP / 2;
@ -577,7 +577,7 @@ static DISCRETE_STEP(dss_noise)
/* The enable input only curtails output, phase rotation still occurs. */
/* We allow the phase to exceed 2Pi here, so we can tell when to sample the noise. */
context->phase += ((2.0 * M_PI * DSS_NOISE__FREQ) / disc_info->sample_rate);
context->phase += ((2.0 * M_PI * DSS_NOISE__FREQ) / node->info->sample_rate);
}
@ -621,10 +621,10 @@ static DISCRETE_STEP(dss_note)
if (context->clock_type == DISC_CLK_IS_FREQ)
{
/* We need to keep clocking the internal clock even if disabled. */
cycles = (context->t_left + disc_info->sample_time) / context->t_clock;
cycles = (context->t_left + node->info->sample_time) / context->t_clock;
inc = (int)cycles;
context->t_left = (cycles - inc) * context->t_clock;
if (inc) x_time = context->t_left / disc_info->sample_time;
if (inc) x_time = context->t_left / node->info->sample_time;
}
else
{
@ -754,7 +754,7 @@ static DISCRETE_STEP(dss_op_amp_osc)
UINT8 force_charge = 0;
UINT8 enable = DSS_OP_AMP_OSC__ENABLE;
dt = disc_info->sample_time; /* Change in time */
dt = node->info->sample_time; /* Change in time */
vC = context->v_cap; /* Set to voltage before change */
/* work out the charge currents for the VCOs. */
@ -931,7 +931,7 @@ static DISCRETE_RESET(dss_op_amp_osc)
{
if IS_VALUE_A_NODE(*r_info_ptr)
{
r_node = discrete_find_node(disc_info, *r_info_ptr);
r_node = discrete_find_node(node->info, *r_info_ptr);
*r_context_ptr = &(r_node->output[NODE_CHILD_NODE_NUM((int)*r_info_ptr)]);
}
else
@ -1078,7 +1078,7 @@ static DISCRETE_STEP(dss_sawtoothwave)
/* boils out to */
/* phase step = (2Pi*output freq)/sample freq) */
/* Also keep the new phasor in the 2Pi range. */
context->phase = fmod((context->phase + ((2.0 * M_PI * DSS_SAWTOOTHWAVE__FREQ) / disc_info->sample_rate)), 2.0 * M_PI);
context->phase = fmod((context->phase + ((2.0 * M_PI * DSS_SAWTOOTHWAVE__FREQ) / node->info->sample_rate)), 2.0 * M_PI);
}
static DISCRETE_RESET(dss_sawtoothwave)
@ -1257,7 +1257,7 @@ static DISCRETE_STEP(dss_sinewave)
/* boils out to */
/* phase step = (2Pi*output freq)/sample freq) */
/* Also keep the new phasor in the 2Pi range. */
context->phase=fmod((context->phase + ((2.0 * M_PI * DSS_SINEWAVE__FREQ) / disc_info->sample_rate)), 2.0 * M_PI);
context->phase=fmod((context->phase + ((2.0 * M_PI * DSS_SINEWAVE__FREQ) / node->info->sample_rate)), 2.0 * M_PI);
}
static DISCRETE_RESET(dss_sinewave)
@ -1323,7 +1323,7 @@ static DISCRETE_STEP(dss_squarewave)
/* boils out to */
/* phase step = (2Pi*output freq)/sample freq) */
/* Also keep the new phasor in the 2Pi range. */
context->phase=fmod(context->phase + ((2.0 * M_PI * DSS_SQUAREWAVE__FREQ) / disc_info->sample_rate), 2.0 * M_PI);
context->phase=fmod(context->phase + ((2.0 * M_PI * DSS_SQUAREWAVE__FREQ) / node->info->sample_rate), 2.0 * M_PI);
}
static DISCRETE_RESET(dss_squarewave)
@ -1392,7 +1392,7 @@ static DISCRETE_RESET(dss_squarewfix)
{
struct dss_squarewfix_context *context = (struct dss_squarewfix_context *)node->context;
context->sample_step = 1.0 / disc_info->sample_rate;
context->sample_step = 1.0 / node->info->sample_rate;
context->flip_flop = 1;
/* Do the intial time shift and convert freq to off/on times */
@ -1454,7 +1454,7 @@ static DISCRETE_STEP(dss_squarewave2)
/* phase step = 2Pi/(output period/sample period) */
/* boils out to */
/* phase step = 2Pi/(output period*sample freq) */
newphase = context->phase + ((2.0 * M_PI) / ((DSS_SQUAREWAVE2__T_OFF + DSS_SQUAREWAVE2__T_ON) * disc_info->sample_rate));
newphase = context->phase + ((2.0 * M_PI) / ((DSS_SQUAREWAVE2__T_OFF + DSS_SQUAREWAVE2__T_ON) * node->info->sample_rate));
/* Keep the new phasor in the 2Pi range.*/
context->phase = fmod(newphase, 2.0 * M_PI);
@ -1607,7 +1607,7 @@ static DISCRETE_STEP(dss_inverter_osc)
vMix = rMix* ( (vG3-vG2) / context->r1 + (DSS_INVERTER_OSC__MOD-vG2) / context->r2 + (vI-0.7-vG2)/context->rp);
}
diff = vMix - context->v_cap;
diff = diff - diff * exp(-disc_info->sample_time / (context->c * rMix));
diff = diff - diff * exp(-node->info->sample_time / (context->c * rMix));
break;
case DISC_OSC_INVERTER_IS_TYPE5:
if ((info->clamp >= 0.0) && ((vI< - info->clamp) || (vI> info->vB+info->clamp)))
@ -1625,7 +1625,7 @@ static DISCRETE_STEP(dss_inverter_osc)
vMix = rMix* ( (vG3 - vG2) / context->r1 + (DSS_INVERTER_OSC__MOD-vG2) / context->r2 + (vI+0.7-vG2)/context->rp);
}
diff = vMix - context->v_cap;
diff = diff - diff * exp(-disc_info->sample_time/(context->c * rMix));
diff = diff - diff * exp(-node->info->sample_time/(context->c * rMix));
break;
default:
fatalerror("DISCRETE_INVERTER_OSC - Wrong type on NODE_%02d", node->node - NODE_00);
@ -1648,8 +1648,8 @@ static DISCRETE_RESET(dss_inverter_osc)
int i;
/* exponent */
context->w = exp(-disc_info->sample_time / (DSS_INVERTER_OSC__RC * DSS_INVERTER_OSC__C));
context->wc = exp(-disc_info->sample_time / ((DSS_INVERTER_OSC__RC * DSS_INVERTER_OSC__RP) / (DSS_INVERTER_OSC__RP + DSS_INVERTER_OSC__RC) * DSS_INVERTER_OSC__C));
context->w = exp(-node->info->sample_time / (DSS_INVERTER_OSC__RC * DSS_INVERTER_OSC__C));
context->wc = exp(-node->info->sample_time / ((DSS_INVERTER_OSC__RC * DSS_INVERTER_OSC__RP) / (DSS_INVERTER_OSC__RP + DSS_INVERTER_OSC__RC) * DSS_INVERTER_OSC__C));
node->output[0] = 0;
context->v_cap = 0;
context->v_g2_old = 0;
@ -1708,7 +1708,7 @@ static DISCRETE_STEP(dss_trianglewave)
/* boils out to */
/* phase step = (2Pi*output freq)/sample freq) */
/* Also keep the new phasor in the 2Pi range. */
context->phase=fmod((context->phase + ((2.0 * M_PI * DSS_TRIANGLEWAVE__FREQ) / disc_info->sample_rate)), 2.0 * M_PI);
context->phase=fmod((context->phase + ((2.0 * M_PI * DSS_TRIANGLEWAVE__FREQ) / node->info->sample_rate)), 2.0 * M_PI);
}
static DISCRETE_RESET(dss_trianglewave)

View File

@ -57,16 +57,14 @@
#define DISCRETE_PROFILING (0)
/*************************************
*
* Prototypes
*
*************************************/
static void init_nodes(discrete_info *info, discrete_sound_block *block_list, const device_config *device);
static void find_input_nodes(discrete_info *info, discrete_sound_block *block_list);
static void init_nodes(discrete_info *info, linked_list_entry *block_list, const device_config *device);
static void find_input_nodes(discrete_info *info);
static void setup_output_nodes(const device_config *device, discrete_info *info);
static void setup_disc_logs(discrete_info *info);
static node_description *discrete_find_node(const discrete_info *info, int node);
@ -229,7 +227,19 @@ 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);
}
/*************************************
*
@ -249,7 +259,7 @@ static node_description *discrete_find_node(const discrete_info *info, int node)
*
*************************************/
static int discrete_build_list(discrete_info *info, discrete_sound_block *intf, discrete_sound_block *out, int offset)
static void discrete_build_list(discrete_info *info, discrete_sound_block *intf, linked_list_entry ***current)
{
int node_count = 0;
@ -258,56 +268,103 @@ static int discrete_build_list(discrete_info *info, discrete_sound_block *intf,
/* scan imported */
if (intf[node_count].type == DSO_IMPORT)
{
offset = discrete_build_list(info, (discrete_sound_block *) intf[node_count].custom, out, offset);
discrete_log(info, "discrete_build_list() - DISCRETE_IMPORT @ NODE_%02d", NODE_INDEX(intf[node_count].node) );
discrete_build_list(info, (discrete_sound_block *) intf[node_count].custom, current);
}
else if (intf[node_count].type == DSO_REPLACE)
{
int i;
linked_list_entry *entry;
node_count++;
if (intf[node_count].type == DSS_NULL)
fatalerror("discrete_build_list: DISCRETE_REPLACE at end of node_list");
for (i = 0; i < offset; i++)
if (out[i].type != NODE_SPECIAL )
if (out[i].node == intf[node_count].node)
for (entry = info->block_list; entry != NULL; entry = entry->next)
{
discrete_sound_block *block = (discrete_sound_block *) entry->ptr;
if (block->type != NODE_SPECIAL )
if (block->node == intf[node_count].node)
{
out[i] = intf[node_count];
entry->ptr = (void *) &intf[node_count];
discrete_log(info, "discrete_build_list() - DISCRETE_REPLACE @ NODE_%02d", NODE_INDEX(intf[node_count].node) );
break;
}
}
if (i >= offset)
if (entry == NULL)
fatalerror("discrete_build_list: DISCRETE_REPLACE did not found node %d", NODE_INDEX(intf[node_count].node));
}
else if (intf[node_count].type == DSO_DELETE)
{
int i,p,deleted;
int p,deleted;
linked_list_entry *entry, *last;
p = 0;
deleted = 0;
for (i = 0; i < offset; i++)
last = NULL;
for (entry = info->block_list; entry != NULL; last = entry, entry = entry->next)
{
if ((out[i].node >= intf[node_count].input_node[0]) &&
(out[i].node <= intf[node_count].input_node[1]))
discrete_sound_block *block = (discrete_sound_block *) entry->ptr;
if ((block->node >= intf[node_count].input_node[0]) &&
(block->node <= intf[node_count].input_node[1]))
{
discrete_log(info, "discrete_build_list() - DISCRETE_DELETE deleted NODE_%02d", NODE_INDEX(out[i].node) );
deleted++;
}
else
{
out[p++] = out[i];
discrete_log(info, "discrete_build_list() - DISCRETE_DELETE deleted NODE_%02d", NODE_INDEX(block->node) );
if (last != NULL)
last->next = entry->next;
else
info->block_list = entry->next;
}
}
offset -= deleted;
}
else
out[offset++] = intf[node_count];
{
discrete_log(info, "discrete_build_list() - adding node %d (*current %p)\n", node_count, *current);
add_list(info, current, &intf[node_count]);
}
node_count++;
}
out[offset] = intf[node_count];
return offset;
}
/*************************************
*
* Sanity check list
*
*************************************/
static void discrete_sanity_check(discrete_info *info)
{
linked_list_entry *entry;
int node_count = 0;
discrete_log(info, "discrete_start() - Doing node list sanity check");
for (entry = info->block_list; entry != NULL; entry = entry->next)
{
discrete_sound_block *block = (discrete_sound_block *) entry->ptr;
/* make sure we don't have too many nodes overall */
if (node_count > DISCRETE_MAX_NODES)
fatalerror("discrete_start() - Upper limit of %d nodes exceeded, have you terminated the interface block?", DISCRETE_MAX_NODES);
/* make sure the node number is in range */
if (block->node < NODE_START || block->node > NODE_END)
fatalerror("discrete_start() - Invalid node number on node %02d descriptor", block->node);
/* make sure the node type is valid */
if (block->type > DSO_OUTPUT)
fatalerror("discrete_start() - Invalid function type on NODE_%02d", NODE_INDEX(block->node) );
/* make sure this is a main node */
if (NODE_CHILD_NODE_NUM(block->node) > 0)
fatalerror("discrete_start() - Child node number on NODE_%02d", NODE_INDEX(block->node) );
node_count++;
}
discrete_log(info, "discrete_start() - Sanity check counted %d nodes", node_count);
}
/*************************************
@ -318,7 +375,7 @@ static int discrete_build_list(discrete_info *info, discrete_sound_block *intf,
static DEVICE_START( discrete )
{
discrete_sound_block *intf;
linked_list_entry **intf;
discrete_sound_block *intf_start = (discrete_sound_block *)device->static_config;
discrete_info *info = get_safe_token(device);
char name[32];
@ -337,50 +394,29 @@ static DEVICE_START( discrete )
/* create the logfile */
sprintf(name, "discrete%s.log", device->tag);
if (DISCRETE_DEBUGLOG && !info->disclogfile)
if (DISCRETE_DEBUGLOG)
info->disclogfile = fopen(name, "w");
/* Build the final block list */
intf = auto_alloc_array_clear(device->machine, discrete_sound_block, DISCRETE_MAX_NODES);
discrete_build_list(info, intf_start, intf, 0);
info->block_list = NULL;
intf = &info->block_list;
discrete_build_list(info, intf_start, &intf);
/* first pass through the nodes: sanity check, fill in the indexed_nodes, and make a total count */
discrete_log(info, "discrete_start() - Doing node list sanity check");
for (info->node_count = 0; intf[info->node_count].type != DSS_NULL; info->node_count++)
{
/* make sure we don't have too many nodes overall */
if (info->node_count > DISCRETE_MAX_NODES)
fatalerror("discrete_start() - Upper limit of %d nodes exceeded, have you terminated the interface block?", DISCRETE_MAX_NODES);
discrete_sanity_check(info);
/* make sure the node number is in range */
if (intf[info->node_count].node < NODE_START || intf[info->node_count].node > NODE_END)
fatalerror("discrete_start() - Invalid node number on node %02d descriptor", info->node_count);
/* make sure the node type is valid */
if (intf[info->node_count].type > DSO_OUTPUT)
fatalerror("discrete_start() - Invalid function type on NODE_%02d", NODE_INDEX(intf[info->node_count].node) );
/* make sure this is a main node */
if (NODE_CHILD_NODE_NUM(intf[info->node_count].node) > 0)
fatalerror("discrete_start() - Child node number on NODE_%02d", NODE_INDEX(intf[info->node_count].node) );
}
info->node_count++;
discrete_log(info, "discrete_start() - Sanity check counted %d nodes", info->node_count);
/* allocate memory for the array of actual nodes */
info->node_list = auto_alloc_array_clear(device->machine, node_description, info->node_count);
/* allocate memory for the node execution order array */
info->running_order = auto_alloc_array_clear(device->machine, node_description *, info->node_count);
/* Start with empty lists */
info->node_list = NULL;
info->step_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);
/* initialize the node data */
init_nodes(info, intf, device);
init_nodes(info, info->block_list, device);
/* now go back and find pointers to all input nodes */
find_input_nodes(info, intf);
find_input_nodes(info);
/* then set up the output nodes */
setup_output_nodes(device, info);
@ -403,27 +439,29 @@ static DEVICE_STOP( discrete )
if (DISCRETE_PROFILING)
{
int nodenum;
int count = 0;
linked_list_entry *entry;
osd_ticks_t total = 0;
osd_ticks_t tresh;
printf("Total Samples: %d\n", info->total_samples);
/* calculate total time */
for (nodenum = 0; nodenum < info->node_count; nodenum++)
for (entry = info->step_list; entry != NULL; entry = entry->next)
{
node_description *node = info->running_order[nodenum];
node_description *node = (node_description *) entry->ptr;
/* Now step the node */
total += node->run_time;
count++;
}
/* print statistics */
tresh = total / info->node_count;
for (nodenum = 0; nodenum < info->node_count; nodenum++)
printf("Total Samples: %d\n", info->total_samples);
tresh = total / count;
for (entry = info->step_list; entry != NULL; entry = entry->next)
{
node_description *node = info->running_order[nodenum];
node_description *node = (node_description *) entry->ptr;
if (node->run_time > tresh)
printf("%3d: %20s %8.2f %10d\n", NODE_INDEX(node->node), node->module.name, (float) node->run_time / (float) total * 100.0, ((int) node->run_time) / info->total_samples);
printf("%3d: %20s %8.2f %10d\n", NODE_INDEX(node->node), node->module->name, (float) node->run_time / (float) total * 100.0, ((int) node->run_time) / info->total_samples);
}
}
@ -457,22 +495,22 @@ static DEVICE_STOP( discrete )
static DEVICE_RESET( discrete )
{
discrete_info *info = get_safe_token(device);
int nodenum;
linked_list_entry *entry;
/* loop over all nodes */
for (nodenum = 0; nodenum < info->node_count; nodenum++)
for (entry = info->node_list; entry != 0; entry = entry->next)
{
node_description *node = info->running_order[nodenum];
node_description *node = (node_description *) entry->ptr;
node->output[0] = 0;
/* if the node has a reset function, call it */
if (node->module.reset)
(*node->module.reset)(info, node);
if (node->module->reset)
(*node->module->reset)(node);
/* otherwise, just step it */
else if (node->module.step)
(*node->module.step)(info, node);
else if (node->module->step)
(*node->module->step)(node);
}
}
@ -562,12 +600,96 @@ INLINE void bigselect(const device_config *device, node_description *node)
*
*************************************/
INLINE void discrete_stream_update_csv(discrete_info *info)
{
int nodenum, outputnum;
/* Dump any csv logs */
for (outputnum = 0; outputnum < info->num_csvlogs; outputnum++)
{
fprintf(info->disc_csv_file[outputnum], "%" I64FMT "d", ++info->sample_num);
for (nodenum = 0; nodenum < info->csvlog_node[outputnum]->active_inputs; nodenum++)
{
fprintf(info->disc_csv_file[outputnum], ", %f", *info->csvlog_node[outputnum]->input[nodenum]);
}
fprintf(info->disc_csv_file[outputnum], "\n");
}
}
INLINE void discrete_stream_update_wave(discrete_info *info)
{
int outputnum;
double val;
INT16 wave_data_l, wave_data_r;
/* Dump any wave logs */
for (outputnum = 0; outputnum < info->num_wavelogs; outputnum++)
{
/* get nodes to be logged and apply gain, then clip to 16 bit */
val = (*info->wavelog_node[outputnum]->input[0]) * (*info->wavelog_node[outputnum]->input[1]);
val = (val < -32768) ? -32768 : (val > 32767) ? 32767 : val;
wave_data_l = (INT16)val;
if (info->wavelog_node[outputnum]->active_inputs == 2)
{
/* DISCRETE_WAVELOG1 */
wav_add_data_16(info->disc_wav_file[outputnum], &wave_data_l, 1);
}
else
{
/* DISCRETE_WAVELOG2 */
val = (*info->wavelog_node[outputnum]->input[2]) * (*info->wavelog_node[outputnum]->input[3]);
val = (val < -32768) ? -32768 : (val > 32767) ? 32767 : val;
wave_data_r = (INT16)val;
wav_add_data_16lr(info->disc_wav_file[outputnum], &wave_data_l, &wave_data_r, 1);
}
}
}
INLINE void discrete_stream_update_nodes(discrete_info *info, stream_sample_t **outputs)
{
int outputnum;
double val;
linked_list_entry *entry;
if (DISCRETE_PROFILING)
info->total_samples++;
/* loop over all nodes */
for (entry = info->step_list; entry != NULL; entry = entry->next)
{
node_description *node = (node_description *) entry->ptr;
/* Now step the node */
if (DISCRETE_PROFILING)
node->run_time -= osd_profiling_ticks();
(*node->module->step)(node);
//bigselect(info->device, node);
if (DISCRETE_PROFILING)
node->run_time += osd_profiling_ticks();
}
/* Add gain to the output and put into the buffers */
/* Clipping will be handled by the main sound system */
for (outputnum = 0; outputnum < info->discrete_outputs; outputnum++)
{
val = (*info->output_node[outputnum]->input[0]) * (*info->output_node[outputnum]->input[1]);
*(outputs[outputnum]++) = val;
}
}
static STREAM_UPDATE( discrete_stream_update )
{
discrete_info *info = (discrete_info *)param;
stream_sample_t *outptr[DISCRETE_MAX_OUTPUTS];
int samplenum, nodenum, outputnum;
double val;
INT16 wave_data_l, wave_data_r;
/* Setup any output streams */
for (outputnum = 0; outputnum < info->discrete_outputs; outputnum++)
outptr[outputnum] = outputs[outputnum];
/* Setup any input streams */
for (nodenum = 0; nodenum < info->discrete_input_streams; nodenum++)
@ -575,74 +697,23 @@ static STREAM_UPDATE( discrete_stream_update )
info->input_stream_data[nodenum] = inputs[nodenum];
}
/* Now we must do samples iterations of the node list, one output for each step */
for (samplenum = 0; samplenum < samples; samplenum++)
if ((info->num_csvlogs > 0) || (info->num_wavelogs > 0))
{
info->total_samples++;
/* loop over all nodes */
for (nodenum = 0; nodenum < info->node_count; nodenum++)
/* Now we must do samples iterations of the node list, one output for each step */
for (samplenum = 0; samplenum < samples; samplenum++)
{
node_description *node = info->running_order[nodenum];
/* Now step the node */
if (DISCRETE_PROFILING)
node->run_time -= osd_profiling_ticks();
if (node->module.step)
(*node->module.step)(info, node);
//bigselect(info->device, node);
if (DISCRETE_PROFILING)
node->run_time += osd_profiling_ticks();
discrete_stream_update_nodes(info, outptr);
}
/* Add gain to the output and put into the buffers */
/* Clipping will be handled by the main sound system */
for (outputnum = 0; outputnum < info->discrete_outputs; outputnum++)
}
else
{
/* Now we must do samples iterations of the node list, one output for each step */
for (samplenum = 0; samplenum < samples; samplenum++)
{
val = (*info->output_node[outputnum]->input[0]) * (*info->output_node[outputnum]->input[1]);
outputs[outputnum][samplenum] = val;
}
discrete_stream_update_nodes(info, outptr);
discrete_stream_update_csv(info);
discrete_stream_update_wave(info);
/* Dump any csv logs */
for (outputnum = 0; outputnum < info->num_csvlogs; outputnum++)
{
fprintf(info->disc_csv_file[outputnum], "%" I64FMT "d", ++info->sample_num);
for (nodenum = 0; nodenum < info->csvlog_node[outputnum]->active_inputs; nodenum++)
{
fprintf(info->disc_csv_file[outputnum], ", %f", *info->csvlog_node[outputnum]->input[nodenum]);
}
fprintf(info->disc_csv_file[outputnum], "\n");
}
/* Dump any wave logs */
for (outputnum = 0; outputnum < info->num_wavelogs; outputnum++)
{
/* get nodes to be logged and apply gain, then clip to 16 bit */
val = (*info->wavelog_node[outputnum]->input[0]) * (*info->wavelog_node[outputnum]->input[1]);
val = (val < -32768) ? -32768 : (val > 32767) ? 32767 : val;
wave_data_l = (INT16)val;
if (info->wavelog_node[outputnum]->active_inputs == 2)
{
/* DISCRETE_WAVELOG1 */
wav_add_data_16(info->disc_wav_file[outputnum], &wave_data_l, 1);
}
else
{
/* DISCRETE_WAVELOG2 */
val = (*info->wavelog_node[outputnum]->input[2]) * (*info->wavelog_node[outputnum]->input[3]);
val = (val < -32768) ? -32768 : (val > 32767) ? 32767 : val;
wave_data_r = (INT16)val;
wav_add_data_16lr(info->disc_wav_file[outputnum], &wave_data_l, &wave_data_r, 1);
}
}
/* advance input streams */
for (nodenum = 0; nodenum < info->discrete_input_streams; nodenum++)
{
info->input_stream_data[nodenum]++;
}
}
@ -656,24 +727,24 @@ static STREAM_UPDATE( discrete_stream_update )
*
*************************************/
static void init_nodes(discrete_info *info, discrete_sound_block *block_list, const device_config *device)
static void init_nodes(discrete_info *info, linked_list_entry *block_list, const device_config *device)
{
int nodenum;
linked_list_entry **step_list = &info->step_list;
linked_list_entry **node_list = &info->node_list;
linked_list_entry *entry;
/* start with no outputs or input streams */
info->discrete_outputs = 0;
info->discrete_input_streams = 0;
/* loop over all nodes */
for (nodenum = 0; nodenum < info->node_count; nodenum++)
for (entry = block_list; entry != NULL; entry = entry->next)
{
discrete_sound_block *block = &block_list[nodenum];
node_description *node = &info->node_list[nodenum];
discrete_sound_block *block = (discrete_sound_block *) entry->ptr;
node_description *node = auto_alloc_clear(info->device->machine, node_description);
int inputnum, modulenum;
/* our running order just follows the order specified */
info->running_order[nodenum] = node;
/* keep track of special nodes */
if (block->node == NODE_SPECIAL)
{
@ -721,8 +792,9 @@ static void init_nodes(discrete_info *info, discrete_sound_block *block_list, co
fatalerror("init_nodes() - Unable to find discrete module type %d for NODE_%02d", block->type, NODE_INDEX(block->node));
/* static inits */
node->info = info;
node->node = block->node;
node->module = module_list[modulenum];
node->module = &module_list[modulenum];
node->output[0] = 0.0;
node->block = block;
@ -733,36 +805,40 @@ static void init_nodes(discrete_info *info, discrete_sound_block *block_list, co
}
node->context = NULL;
node->name = block->name;
node->custom = block->custom;
/* setup module if custom */
if (block->type == DST_CUSTOM)
{
const discrete_custom_info *custom = (const discrete_custom_info *)node->custom;
node->module.reset = custom->reset;
node->module.step = custom->step;
node->module.contextsize = custom->contextsize;
node->module = &custom->module;
node->custom = custom->custom;
}
/* allocate memory if necessary */
if (node->module.contextsize)
node->context = auto_alloc_array_clear(device->machine, UINT8, node->module.contextsize);
if (node->module->contextsize)
node->context = auto_alloc_array_clear(device->machine, UINT8, node->module->contextsize);
/* 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);
/* we will use the node's context pointer to point to the input stream data */
//node->context = &info->input_stream_data[info->discrete_input_streams++];
node->context = NULL;
info->discrete_input_streams++;
}
/* add to node list */
add_list(info, &node_list, node);
/* our running order just follows the order specified */
/* does the node step ? */
if (node->module->step != NULL)
add_list(info, &step_list, node);
/* and register save state */
state_save_register_device_item_array(device, nodenum, node->output);
state_save_register_device_item_array(device, node->node, node->output);
}
/* if no outputs, give an error */
@ -778,15 +854,16 @@ static void init_nodes(discrete_info *info, discrete_sound_block *block_list, co
*
*************************************/
static void find_input_nodes(discrete_info *info, discrete_sound_block *block_list)
static void find_input_nodes(discrete_info *info)
{
int nodenum, inputnum;
int inputnum;
linked_list_entry *entry;
/* loop over all nodes */
for (nodenum = 0; nodenum < info->node_count; nodenum++)
for (entry = info->node_list; entry != NULL; entry = entry->next)
{
node_description *node = &info->node_list[nodenum];
discrete_sound_block *block = &block_list[nodenum];
node_description *node = (node_description *) entry->ptr;
const discrete_sound_block *block = node->block;
/* loop over all active inputs */
for (inputnum = 0; inputnum < node->active_inputs; inputnum++)
@ -800,7 +877,7 @@ static void find_input_nodes(discrete_info *info, discrete_sound_block *block_li
if (!node_ref)
fatalerror("discrete_start - NODE_%02d referenced a non existent node NODE_%02d", NODE_INDEX(node->node), NODE_INDEX(inputnode));
if (NODE_CHILD_NODE_NUM(inputnode) >= node_ref->module.num_output)
if (NODE_CHILD_NODE_NUM(inputnode) >= node_ref->module->num_output)
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));
node->input[inputnum] = &(node_ref->output[NODE_CHILD_NODE_NUM(inputnode)]); /* Link referenced node out to input */

View File

@ -3228,13 +3228,18 @@
* DISCRETE_CUSTOMx(name of node,
* input 0 node or static value, ...)
*
* discrete_custom_info = {reset, step, contextsize, custom}
* reset = address called to reset a node after creation or system reset
* step = address called to execute one time delta of output update
* contextsize = size of context to create
* discrete_custom_info = {discrete_module, custom}
* discrete_module = discrete module definition
* custom = address of specific initialization data
*
* EXAMPLES: see Donkey Kong
* In most case, you should be able to use
*
* discrete_custom_info = {DISCRETE_CUSTOM_MODULE(basename, context type), custom}
*
* if you have used DISCRETE_STEP(basename) and DISCRETE_RESET(basename) to define
* the step/reset procedures.
*
* EXAMPLES: see Donkey Kong, Mario Bros.
*
***********************************************************************
=======================================================================
@ -3329,13 +3334,13 @@
*************************************/
/* calculate charge exponent using discrete sample time */
#define RC_CHARGE_EXP(rc) (1.0 - exp(disc_info->neg_sample_time / (rc)))
#define RC_CHARGE_EXP(rc) (1.0 - exp(node->info->neg_sample_time / (rc)))
/* calculate charge exponent using given sample time */
#define RC_CHARGE_EXP_DT(rc, dt) (1.0 - exp(-(dt) / (rc)))
#define RC_CHARGE_NEG_EXP_DT(rc, dt) (1.0 - exp((dt) / (rc)))
/* calculate discharge exponent using discrete sample time */
#define RC_DISCHARGE_EXP(rc) (exp(disc_info->neg_sample_time / (rc)))
#define RC_DISCHARGE_EXP(rc) (exp(node->info->neg_sample_time / (rc)))
/* calculate discharge exponent using given sample time */
#define RC_DISCHARGE_EXP_DT(rc, dt) (exp(-(dt) / (rc)))
#define RC_DISCHARGE_NEG_EXP_DT(rc, dt) (exp((dt) / (rc)))
@ -3349,19 +3354,14 @@
#define DISCRETE_STEP_NAME( _func ) _func ## _step
#define DISCRETE_RESET_NAME( _func ) _func ## _reset
#define DISCRETE_STEP(_func) void DISCRETE_STEP_NAME(_func) (const discrete_info *disc_info, node_description *node)
#define DISCRETE_RESET(_func) void DISCRETE_RESET_NAME(_func) (const discrete_info *disc_info, node_description *node)
#define DISCRETE_STEP(_func) void DISCRETE_STEP_NAME(_func) (node_description *node)
#define DISCRETE_RESET(_func) void DISCRETE_RESET_NAME(_func) (node_description *node)
#define DISCRETE_STEP_CALL(_func) DISCRETE_STEP_NAME(_func) (disc_info, node)
#define DISCRETE_RESET_CALL(_func) DISCRETE_RESET_NAME(_func) (disc_info, node)
#define DISCRETE_STEP_CALL(_func) DISCRETE_STEP_NAME(_func) (node)
#define DISCRETE_RESET_CALL(_func) DISCRETE_RESET_NAME(_func) (node)
#if 0
#define DISCRETE_STEP(_func) void DISCRETE_STEP_NAME(_func) (const device_config *device, node_description *node)
#define DISCRETE_RESET(_func) void DISCRETE_RESET_NAME(_func) (const device_config *device, node_description *node)
#define DISCRETE_STEP_CALL(_func) DISCRETE_STEP_NAME(_func) (device, node)
#define DISCRETE_RESET_CALL(_func) DISCRETE_RESET_NAME(_func) (device, node)
#endif
#define DISCRETE_CUSTOM_MODULE(_basename, _context_type) \
{ DST_CUSTOM, "CUSTOM", 1, sizeof(_context_type), DISCRETE_RESET_NAME(_basename), DISCRETE_STEP_NAME(_basename) }
/*************************************
*
@ -3611,8 +3611,8 @@ struct _discrete_module
const char * name;
int num_output; /* Total number of output nodes, i.e. Master node + 1 */
size_t contextsize;
void (*reset)(const discrete_info *disc_info, node_description *node); /* Called to reset a node after creation or system reset */
void (*step)(const discrete_info *disc_info, node_description *node); /* Called to execute one time delta of output update */
void (*reset)(node_description *node); /* Called to reset a node after creation or system reset */
void (*step)(node_description *node); /* Called to execute one time delta of output update */
};
@ -3631,11 +3631,13 @@ struct _node_description
int input_is_node; /* Bit Flags. 1 in bit location means input_is_node */
const double * input[DISCRETE_MAX_INPUTS]; /* Addresses of Input values */
discrete_module module; /* Copy of the node's module info */
const discrete_sound_block *block; /* Points to the node's setup block. */
void * context; /* Contextual information specific to this node type */
const char * name; /* Text name string for identification/debug */
const void * custom; /* Custom function specific initialisation data */
const discrete_module *module; /* Node's module info */
const discrete_sound_block *block; /* Points to the node's setup block. */
const discrete_info *info; /* Points to the parent */
osd_ticks_t run_time;
};
@ -3650,6 +3652,13 @@ struct _node_description
*
*************************************/
typedef struct _linked_list_entry linked_list_entry;
struct _linked_list_entry
{
void *ptr;
linked_list_entry *next;
};
struct _discrete_info
{
const device_config *device;
@ -3660,10 +3669,16 @@ struct _discrete_info
double neg_sample_time;
/* internal node tracking */
int node_count;
node_description **running_order;
node_description **indexed_node;
node_description *node_list;
/* list of all nodes */
linked_list_entry *node_list; /* node_description * */
/* list of nodes which step */
linked_list_entry *step_list; /* node_description * */
/* list of discrete blocks after prescan (IMPORT, DELETE, REPLACE) */
linked_list_entry *block_list; /* discrete_sound_block * */
/* the input streams */
int discrete_input_streams;
@ -3953,9 +3968,7 @@ struct _discrete_adsr
typedef struct _discrete_custom_info discrete_custom_info;
struct _discrete_custom_info
{
void (*reset)(const discrete_info *disc_info, node_description *node); /* Called to reset a node after creation or system reset */
void (*step)(const discrete_info *disc_info, node_description *node); /* Called to execute one time delta of output update */
size_t contextsize;
const discrete_module module;
const void *custom; /* Custom function specific initialisation data */
};
@ -4185,6 +4198,12 @@ enum
DSO_REPLACE, /* replace next node */
DSO_DELETE, /* delete nodes */
/* Parallel execution */
DSO_TASK_START, /* start of parallel task */
DSO_TASK_END, /* end of parallel task */
DSO_TASK_SYNC, /* wait for all parallel tasks to finish */
/* Marks end of this enum -- must be last entry ! */
DSO_LAST
};

View File

@ -343,9 +343,7 @@ static DISCRETE_RESET( dkong_custom_mixer )
static const discrete_custom_info dkong_custom_mixer_info =
{
DISCRETE_RESET_NAME( dkong_custom_mixer ),
DISCRETE_STEP_NAME( dkong_custom_mixer ),
sizeof(struct dkong_custom_mixer_context),
DISCRETE_CUSTOM_MODULE( dkong_custom_mixer, struct dkong_custom_mixer_context),
NULL
};
#endif

View File

@ -192,7 +192,7 @@ static DISCRETE_STEP( mario_custom_run )
double t1 = 0.5 / LS624_F(MARIO_CUSTOM_C1, MARIO_CUSTOM_IN1, RUN_VCO_VOLTAGE);
double t2 = 0.5 / LS624_F(MARIO_CUSTOM_C2, MARIO_CUSTOM_IN2, RUN_VCO_VOLTAGE);
double sample_t = disc_info->sample_time;
double sample_t = node->info->sample_time;
double vn, t;
//if (MARIO_CUSTOM_VOUT)
@ -258,9 +258,7 @@ static DISCRETE_RESET( mario_custom_run )
static const discrete_custom_info mario_custom_run_info =
{
DISCRETE_RESET_NAME( mario_custom_run ),
DISCRETE_STEP_NAME( mario_custom_run ),
sizeof(struct mario_custom_run_context),
DISCRETE_CUSTOM_MODULE( mario_custom_run, struct mario_custom_run_context),
NULL
};