mirror of
https://github.com/holub/mame
synced 2025-05-19 12:18:56 +03:00
Atari Cops'n Robbers Updates [Derrick Renaud]
Converted controls to Positional type. Started Discrete sounds. (Motor 2 & 3, Crash sounds implemented) Optimized speed of DISCRETE_DAC_R1 [Derrick Renaud]
This commit is contained in:
parent
a9521177b8
commit
c956d18f78
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -1270,6 +1270,7 @@ src/mame/audio/cclimber.c svneol=native#text/plain
|
||||
src/mame/audio/cinemat.c svneol=native#text/plain
|
||||
src/mame/audio/circus.c svneol=native#text/plain
|
||||
src/mame/audio/cliffhgr.c svneol=native#text/plain
|
||||
src/mame/audio/copsnrob.c svneol=native#text/plain
|
||||
src/mame/audio/cps3.c svneol=native#text/plain
|
||||
src/mame/audio/crbaloon.c svneol=native#text/plain
|
||||
src/mame/audio/cyberbal.c svneol=native#text/plain
|
||||
@ -3279,7 +3280,6 @@ src/mame/machine/cdicdic.h svneol=native#text/plain
|
||||
src/mame/machine/cdislave.c svneol=native#text/plain
|
||||
src/mame/machine/cdislave.h svneol=native#text/plain
|
||||
src/mame/machine/chaknpop.c svneol=native#text/plain
|
||||
src/mame/machine/copsnrob.c svneol=native#text/plain
|
||||
src/mame/machine/cps2crpt.c svneol=native#text/plain
|
||||
src/mame/machine/cubocd32.c svneol=native#text/plain
|
||||
src/mame/machine/cx4data.c svneol=native#text/plain
|
||||
|
@ -56,7 +56,6 @@ struct dsd_555_mstbl_context
|
||||
int trig_is_logic;
|
||||
int trig_discharges_cap;
|
||||
int output_type;
|
||||
int output_is_ac;
|
||||
double ac_shift; /* DC shift needed to make waveform ac */
|
||||
int flip_flop; /* 555 flip/flop output state */
|
||||
int has_rc_nodes;
|
||||
@ -483,14 +482,15 @@ DISCRETE_STEP(dsd_555_mstbl)
|
||||
DISCRETE_DECLARE_INFO(discrete_555_desc)
|
||||
|
||||
double v_cap; /* Current voltage on capacitor, before dt */
|
||||
double v_cap_next = 0; /* Voltage on capacitor, after dt */
|
||||
double x_time = 0; /* time since change happened */
|
||||
double x_time = 0; /* time since change happened */
|
||||
double dt, exponent;
|
||||
double out = 0;
|
||||
int trigger = 0;
|
||||
int trigger_type;
|
||||
int update_exponent = 0;
|
||||
int update_exponent = context->has_rc_nodes;
|
||||
int flip_flop;
|
||||
|
||||
if(DSD_555_MSTBL__RESET)
|
||||
if(UNEXPECTED(DSD_555_MSTBL__RESET))
|
||||
{
|
||||
/* We are in RESET */
|
||||
node->output[0] = 0;
|
||||
@ -499,102 +499,115 @@ DISCRETE_STEP(dsd_555_mstbl)
|
||||
return;
|
||||
}
|
||||
|
||||
trigger_type = info->options;
|
||||
dt = node->info->sample_time;
|
||||
flip_flop = context->flip_flop;
|
||||
trigger_type = info->options;
|
||||
v_cap = context->cap_voltage;
|
||||
|
||||
switch (trigger_type & DSD_555_TRIGGER_TYPE_MASK)
|
||||
{
|
||||
case DISC_555_TRIGGER_IS_LOGIC:
|
||||
trigger = (int)!DSD_555_MSTBL__TRIGGER;
|
||||
trigger = ((int)DSD_555_MSTBL__TRIGGER) ? 0 : 1;
|
||||
if (UNEXPECTED(trigger))
|
||||
x_time = 1.0 - DSD_555_MSTBL__TRIGGER;
|
||||
break;
|
||||
case DISC_555_TRIGGER_IS_VOLTAGE:
|
||||
trigger = (int)(DSD_555_MSTBL__TRIGGER < context->trigger);
|
||||
break;
|
||||
case DISC_555_TRIGGER_IS_COUNT:
|
||||
trigger = (int)DSD_555_MSTBL__TRIGGER;
|
||||
if (trigger && !context->flip_flop)
|
||||
{
|
||||
if (UNEXPECTED(trigger))
|
||||
x_time = DSD_555_MSTBL__TRIGGER - trigger;
|
||||
if (x_time != 0)
|
||||
{
|
||||
/* adjust sample to after trigger */
|
||||
x_time = (1.0 - x_time);
|
||||
update_exponent = 1;
|
||||
dt = x_time * node->info->sample_time;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (UNEXPECTED(trigger && !flip_flop && x_time != 0))
|
||||
{
|
||||
/* adjust sample to after trigger */
|
||||
update_exponent = 1;
|
||||
dt *= x_time;
|
||||
}
|
||||
x_time = 0;
|
||||
|
||||
if ((trigger_type & DISC_555_TRIGGER_DISCHARGES_CAP) && trigger)
|
||||
context->cap_voltage = 0;
|
||||
|
||||
/* Wait for trigger */
|
||||
if (!context->flip_flop && trigger)
|
||||
context->flip_flop = 1;
|
||||
|
||||
if (context->flip_flop)
|
||||
if (UNEXPECTED(!flip_flop && trigger))
|
||||
{
|
||||
v_cap = context->cap_voltage;
|
||||
flip_flop = 1;
|
||||
context->flip_flop = 1;
|
||||
}
|
||||
|
||||
if (flip_flop)
|
||||
{
|
||||
/* Sometimes a switching network is used to setup the capacitance.
|
||||
* These may select 'no' capacitor, causing oscillation to stop.
|
||||
*/
|
||||
if (DSD_555_MSTBL__C == 0)
|
||||
if (UNEXPECTED(DSD_555_MSTBL__C == 0))
|
||||
{
|
||||
context->flip_flop = 0;
|
||||
/* The voltage goes high because the cap circuit is open. */
|
||||
v_cap_next = info->v_pos;
|
||||
v_cap = info->v_pos;
|
||||
/* The trigger voltage goes high because the cap circuit is open.
|
||||
* and the cap discharges */
|
||||
v_cap = info->v_pos; /* needed for cap output type */
|
||||
context->cap_voltage = 0;
|
||||
|
||||
if (!trigger)
|
||||
{
|
||||
flip_flop = 0;
|
||||
context->flip_flop = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Charging */
|
||||
update_exponent |= context->has_rc_nodes;
|
||||
if (update_exponent)
|
||||
double v_diff = context->v_charge - v_cap;
|
||||
|
||||
if (UNEXPECTED(update_exponent))
|
||||
exponent = RC_CHARGE_EXP_DT(DSD_555_MSTBL__R * DSD_555_MSTBL__C, dt);
|
||||
else
|
||||
exponent = context->exp_charge;
|
||||
v_cap_next = v_cap + ((info->v_pos - v_cap) * exponent);
|
||||
v_cap += v_diff * exponent;
|
||||
|
||||
/* Has it charged past upper limit? */
|
||||
/* If trigger is still enabled, then we keep charging,
|
||||
* regardless of threshold. */
|
||||
if ((v_cap_next >= context->threshold) && !trigger)
|
||||
if (UNEXPECTED((v_cap >= context->threshold) && !trigger))
|
||||
{
|
||||
dt = DSD_555_MSTBL__R * DSD_555_MSTBL__C * log(1.0 / (1.0 - ((v_cap_next - context->threshold) / (context->v_charge - v_cap))));
|
||||
x_time = dt / node->info->sample_time;
|
||||
v_cap_next = 0;
|
||||
v_cap = context->threshold;
|
||||
dt = DSD_555_MSTBL__R * DSD_555_MSTBL__C * log(1.0 / (1.0 - ((v_cap - context->threshold) / v_diff)));
|
||||
x_time = 1.0 - dt / node->info->sample_time;
|
||||
v_cap = 0;
|
||||
flip_flop = 0;
|
||||
context->flip_flop = 0;
|
||||
}
|
||||
context->cap_voltage = v_cap;
|
||||
}
|
||||
|
||||
context->cap_voltage = v_cap_next;
|
||||
}
|
||||
|
||||
switch (info->options & DISC_555_OUT_MASK)
|
||||
switch (context->output_type)
|
||||
{
|
||||
case DISC_555_OUT_SQW:
|
||||
node->output[0] = context->flip_flop * context->v_out_high;
|
||||
/* Fake it to AC if needed */
|
||||
if (context->output_is_ac)
|
||||
node->output[0] -= context->v_out_high / 2.0;
|
||||
out = flip_flop * context->v_out_high - context->ac_shift;
|
||||
break;
|
||||
case DISC_555_OUT_CAP:
|
||||
node->output[0] = v_cap_next;
|
||||
/* Fake it to AC if needed */
|
||||
if (context->output_is_ac)
|
||||
node->output[0] -= context->threshold * 3.0 /4.0;
|
||||
if (x_time > 0)
|
||||
out = v_cap * x_time;
|
||||
else
|
||||
out = v_cap;
|
||||
|
||||
out -= context->ac_shift;
|
||||
break;
|
||||
case DISC_555_OUT_ENERGY:
|
||||
if (x_time == 0) x_time = 1.0;
|
||||
node->output[0] = context->v_out_high * (context->flip_flop ? x_time : (1.0 - x_time));
|
||||
if (context->output_is_ac)
|
||||
node->output[0] -= context->v_out_high / 2.0;
|
||||
if (x_time > 0)
|
||||
out = context->v_out_high * x_time;
|
||||
else if (flip_flop)
|
||||
out = context->v_out_high;
|
||||
else
|
||||
out = 0;
|
||||
|
||||
out -= context->ac_shift;
|
||||
break;
|
||||
}
|
||||
node->output[0] = out;
|
||||
}
|
||||
|
||||
DISCRETE_RESET(dsd_555_mstbl)
|
||||
@ -617,9 +630,16 @@ DISCRETE_RESET(dsd_555_mstbl)
|
||||
context->threshold = info->v_pos * 2.0 / 3.0;
|
||||
context->trigger = info->v_pos / 3.0;
|
||||
|
||||
context->output_is_ac = info->options & DISC_555_OUT_AC;
|
||||
/* Calculate DC shift needed to make squarewave waveform AC */
|
||||
context->ac_shift = context->output_is_ac ? -context->v_out_high / 2.0 : 0;
|
||||
/* Calculate DC shift needed to make waveform AC */
|
||||
if (info->options & DISC_555_OUT_AC)
|
||||
{
|
||||
if (context->output_type == DISC_555_OUT_CAP)
|
||||
context->ac_shift = context->threshold * 3.0 /4.0;
|
||||
else
|
||||
context->ac_shift = context->v_out_high / 2.0;
|
||||
}
|
||||
else
|
||||
context->ac_shift = 0;
|
||||
|
||||
context->trig_is_logic = (info->options & DISC_555_TRIGGER_IS_VOLTAGE) ? 0: 1;
|
||||
context->trig_discharges_cap = (info->options & DISC_555_TRIGGER_DISCHARGES_CAP) ? 1: 0;
|
||||
@ -1870,6 +1890,5 @@ DISCRETE_RESET(dsd_ls624)
|
||||
else
|
||||
context->has_freq_in_cap = 0;
|
||||
|
||||
|
||||
node->output[0] = 0;
|
||||
}
|
||||
|
@ -65,10 +65,10 @@ struct dst_bits_decode_context
|
||||
|
||||
struct dst_dac_r1_context
|
||||
{
|
||||
double i_bias; /* current of the bias circuit */
|
||||
double exponent; /* smoothing curve */
|
||||
double r_total; /* all resistors in parallel */
|
||||
int last_data;
|
||||
double exponent;
|
||||
double last_v;
|
||||
double v_step[256];
|
||||
int has_c_filter;
|
||||
};
|
||||
|
||||
struct dst_diode_mix_context
|
||||
@ -250,7 +250,8 @@ DISCRETE_RESET(dst_comp_adder)
|
||||
DISCRETE_DECLARE_INFO(discrete_comp_adder_table)
|
||||
|
||||
int i, bit;
|
||||
int length = 1 << info->length;
|
||||
int bit_length = info->length;
|
||||
int length = 1 << bit_length;
|
||||
|
||||
assert(length <= 256);
|
||||
|
||||
@ -261,18 +262,21 @@ DISCRETE_RESET(dst_comp_adder)
|
||||
{
|
||||
case DISC_COMP_P_CAPACITOR:
|
||||
context->total[i] = info->cDefault;
|
||||
for(bit = 0; bit < info->length; bit++)
|
||||
for(bit = 0; bit < bit_length; bit++)
|
||||
{
|
||||
if (i & (1 << bit)) context->total[i] += info->c[bit];
|
||||
if (i & (1 << bit))
|
||||
context->total[i] += info->c[bit];
|
||||
}
|
||||
break;
|
||||
case DISC_COMP_P_RESISTOR:
|
||||
context->total[i] = (info->cDefault != 0) ? 1.0 / info->cDefault : 0;
|
||||
for(bit = 0; bit < info->length; bit++)
|
||||
for(bit = 0; bit < bit_length; bit++)
|
||||
{
|
||||
if ((i & (1 << bit)) && (info->c[bit] != 0)) context->total[i] += 1.0 / info->c[bit];
|
||||
if ((i & (1 << bit)) && (info->c[bit] != 0))
|
||||
context->total[i] += 1.0 / info->c[bit];
|
||||
}
|
||||
if (context->total[i] != 0) context->total[i] = 1.0 / context->total[i];
|
||||
if (context->total[i] != 0)
|
||||
context->total[i] = 1.0 / context->total[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -310,6 +314,7 @@ DISCRETE_STEP(dst_clamp)
|
||||
* also passed discrete_dac_r1_ladder structure
|
||||
*
|
||||
* Mar 2004, D Renaud.
|
||||
* Nov 2010, D Renaud. - optimized for speed
|
||||
************************************************************************/
|
||||
#define DST_DAC_R1__DATA DISCRETE_INPUT(0)
|
||||
#define DST_DAC_R1__VON DISCRETE_INPUT(1)
|
||||
@ -317,49 +322,33 @@ DISCRETE_STEP(dst_clamp)
|
||||
DISCRETE_STEP(dst_dac_r1)
|
||||
{
|
||||
DISCRETE_DECLARE_CONTEXT(dst_dac_r1)
|
||||
DISCRETE_DECLARE_INFO(discrete_dac_r1_ladder)
|
||||
|
||||
int bit, bit_val, data;
|
||||
double v, i_bit, i_total, x_time, von;
|
||||
int data = (int)DST_DAC_R1__DATA;
|
||||
double v = context->v_step[data];
|
||||
double x_time = DST_DAC_R1__DATA - data;
|
||||
double last_v = context->last_v;
|
||||
|
||||
i_total = context->i_bias;
|
||||
context->last_v = v;
|
||||
|
||||
data = (int)DST_DAC_R1__DATA;
|
||||
x_time = DST_DAC_R1__DATA - data;
|
||||
|
||||
von = DST_DAC_R1__VON;
|
||||
for (bit=0; bit < info->ladderLength; bit++)
|
||||
{
|
||||
/* Add up currents of ON circuits per Millman. */
|
||||
|
||||
/* ignore if no resistor present */
|
||||
if (info->r[bit] != 0)
|
||||
{
|
||||
i_bit = von / info->r[bit];
|
||||
bit_val = (data >> bit) & 0x01;
|
||||
|
||||
if ((x_time != 0.0) && (bit_val != ((context->last_data >> bit) & 0x01)))
|
||||
{
|
||||
/* there is x_time and a change in bit,
|
||||
* so anti-alias the current */
|
||||
i_bit *= bit_val ? x_time : 1.0 - x_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* there is no x_time or a change in bit,
|
||||
* so 0 the current if the bit value is 0 */
|
||||
if (bit_val == 0)
|
||||
i_bit = 0;
|
||||
}
|
||||
i_total += i_bit;
|
||||
}
|
||||
}
|
||||
|
||||
v = i_total * context->r_total;
|
||||
context->last_data = data;
|
||||
if (x_time > 0)
|
||||
v = x_time * (v - last_v) + last_v;
|
||||
|
||||
/* Filter if needed, else just output voltage */
|
||||
node->output[0] = info->cFilter ? node->output[0] + ((v - node->output[0]) * context->exponent) : v;
|
||||
if (context->has_c_filter)
|
||||
{
|
||||
double out = node->output[0];
|
||||
double v_diff = v - out;
|
||||
/* optimization - if charged close enough to voltage */
|
||||
if (fabs(v_diff) < 0.000001)
|
||||
node->output[0] = v;
|
||||
else
|
||||
{
|
||||
out += v_diff * context->exponent;
|
||||
node->output[0] = out;
|
||||
}
|
||||
}
|
||||
else
|
||||
node->output[0] = v;
|
||||
}
|
||||
|
||||
DISCRETE_RESET(dst_dac_r1)
|
||||
@ -368,24 +357,31 @@ DISCRETE_RESET(dst_dac_r1)
|
||||
DISCRETE_DECLARE_INFO(discrete_dac_r1_ladder)
|
||||
|
||||
int bit;
|
||||
int ladderLength = info->ladderLength;
|
||||
int total_steps = 1 << ladderLength;
|
||||
double r_total = 0;
|
||||
double i_bias;
|
||||
double v_on = DST_DAC_R1__VON;
|
||||
|
||||
context->last_v = 0;
|
||||
|
||||
/* Calculate the Millman current of the bias circuit */
|
||||
if (info->rBias)
|
||||
context->i_bias = info->vBias / info->rBias;
|
||||
i_bias = info->vBias / info->rBias;
|
||||
else
|
||||
context->i_bias = 0;
|
||||
i_bias = 0;
|
||||
|
||||
/*
|
||||
* We will do a small amount of error checking.
|
||||
* But if you are an idiot and pass a bad ladder table
|
||||
* then you deserve a crash.
|
||||
*/
|
||||
if (info->ladderLength < 2)
|
||||
if (ladderLength < 2 && info->rBias == 0 && info->rGnd == 0)
|
||||
{
|
||||
/* You need at least 2 resistors for a ladder */
|
||||
discrete_log(node->info, "dst_dac_r1_reset - Ladder length too small");
|
||||
}
|
||||
if (info->ladderLength > DISC_LADDER_MAXRES )
|
||||
if (ladderLength > DISC_LADDER_MAXRES )
|
||||
{
|
||||
discrete_log(node->info, "dst_dac_r1_reset - Ladder length exceeds DISC_LADDER_MAXRES");
|
||||
}
|
||||
@ -395,22 +391,48 @@ DISCRETE_RESET(dst_dac_r1)
|
||||
* This is the combined resistance of the voltage sources.
|
||||
* This is used for the charging curve.
|
||||
*/
|
||||
context->r_total = 0;
|
||||
for(bit = 0; bit < info->ladderLength; bit++)
|
||||
for(bit = 0; bit < ladderLength; bit++)
|
||||
{
|
||||
if (info->r[bit] != 0)
|
||||
context->r_total += 1.0 / info->r[bit];
|
||||
r_total += 1.0 / info->r[bit];
|
||||
}
|
||||
if (info->rBias) context->r_total += 1.0 / info->rBias;
|
||||
if (info->rGnd) context->r_total += 1.0 / info->rGnd;
|
||||
context->r_total = 1.0 / context->r_total;
|
||||
if (info->rBias) r_total += 1.0 / info->rBias;
|
||||
if (info->rGnd) r_total += 1.0 / info->rGnd;
|
||||
r_total = 1.0 / r_total;
|
||||
|
||||
node->output[0] = 0;
|
||||
|
||||
if (info->cFilter)
|
||||
if (info->cFilter > 0)
|
||||
{
|
||||
/* Setup filter constants */
|
||||
context->exponent = RC_CHARGE_EXP(context->r_total * info->cFilter);
|
||||
context->has_c_filter = 1;
|
||||
/* Setup filter constant */
|
||||
context->exponent = RC_CHARGE_EXP(r_total * info->cFilter);
|
||||
}
|
||||
else
|
||||
context->has_c_filter = 0;
|
||||
|
||||
/* pre-calculate all possible values to speed up step routine */
|
||||
for(int i = 0; i < total_steps; i++)
|
||||
{
|
||||
double i_total = i_bias;
|
||||
for (bit = 0; bit < ladderLength; bit++)
|
||||
{
|
||||
/* Add up currents of ON circuits per Millman. */
|
||||
|
||||
/* ignore if no resistor present */
|
||||
if (EXPECTED(info->r[bit] != 0))
|
||||
{
|
||||
double i_bit;
|
||||
int bit_val = (i >> bit) & 0x01;
|
||||
|
||||
if (bit_val != 0)
|
||||
i_bit = v_on / info->r[bit];
|
||||
else
|
||||
i_bit = 0;
|
||||
i_total += i_bit;
|
||||
}
|
||||
}
|
||||
context->v_step[i] = i_total * r_total;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -306,7 +306,7 @@ static const discrete_module module_list[] =
|
||||
|
||||
/* from disc_dev.c */
|
||||
/* generic modules */
|
||||
{ DST_CUSTOM ,"DST_CUSTOM" , 1 ,0 ,NULL ,NULL ,NULL ,NULL },
|
||||
{ DST_CUSTOM ,"DST_CUSTOM" , 8 ,0 ,NULL ,NULL ,NULL ,NULL },
|
||||
/* Component specific modules */
|
||||
{ DSD_555_ASTBL ,"DSD_555_ASTBL" , 1 ,sizeof(struct dsd_555_astbl_context) ,dsd_555_astbl_reset ,dsd_555_astbl_step ,NULL ,NULL },
|
||||
{ DSD_555_MSTBL ,"DSD_555_MSTBL" , 1 ,sizeof(struct dsd_555_mstbl_context) ,dsd_555_mstbl_reset ,dsd_555_mstbl_step ,NULL ,NULL },
|
||||
@ -1035,7 +1035,7 @@ static void find_input_nodes(const discrete_info *info)
|
||||
if (!node_ref)
|
||||
fatalerror("discrete_start - NODE_%02d referenced a non existent node NODE_%02d", NODE_BLOCKINDEX(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) && (node_ref->module->type != DST_CUSTOM))
|
||||
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));
|
||||
|
||||
node->input[inputnum] = &(node_ref->output[NODE_CHILD_NODE_NUM(inputnode)]); /* Link referenced node out to input */
|
||||
|
@ -1866,7 +1866,7 @@
|
||||
*
|
||||
* DISCRETE_DAC_R1(name of node,
|
||||
* data node (static value is useless),
|
||||
* vData node or static value (voltage when a bit is on ),
|
||||
* vData static value (voltage when a bit is on ),
|
||||
* address of discrete_dac_r1_ladder structure)
|
||||
*
|
||||
* discrete_dac_r1_ladder = {ladderLength, r{}, vBias, rBias, rGnd, cFilter}
|
||||
@ -4517,7 +4517,7 @@ enum
|
||||
#define DISCRETE_TRANSFORM5(NODE,INP0,INP1,INP2,INP3,INP4,FUNCT) { NODE, DST_TRANSFORM , 5, { INP0,INP1,INP2,INP3,INP4 }, { INP0,INP1,INP2,INP3,INP4 }, FUNCT, "DISCRETE_TRANSFORM5" },
|
||||
/* Component specific */
|
||||
#define DISCRETE_COMP_ADDER(NODE,DATA,TABLE) { NODE, DST_COMP_ADDER , 1, { DATA }, { DATA }, TABLE, "DISCRETE_COMP_ADDER" },
|
||||
#define DISCRETE_DAC_R1(NODE,DATA,VDATA,LADDER) { NODE, DST_DAC_R1 , 2, { DATA,VDATA }, { DATA,VDATA }, LADDER, "DISCRETE_DAC_R1" },
|
||||
#define DISCRETE_DAC_R1(NODE,DATA,VDATA,LADDER) { NODE, DST_DAC_R1 , 2, { DATA,NODE_NC }, { DATA,VDATA }, LADDER, "DISCRETE_DAC_R1" },
|
||||
#define DISCRETE_DIODE_MIXER2(NODE,IN0,IN1,TABLE) { NODE, DST_DIODE_MIX , 3, { IN0,IN1 }, { IN0,IN1 }, TABLE, "DISCRETE_DIODE_MIXER2" },
|
||||
#define DISCRETE_DIODE_MIXER3(NODE,IN0,IN1,IN2,TABLE) { NODE, DST_DIODE_MIX , 4, { IN0,IN1,IN2 }, { IN0,IN1,IN2 }, TABLE, "DISCRETE_DIODE_MIXER3" },
|
||||
#define DISCRETE_DIODE_MIXER4(NODE,IN0,IN1,IN2,IN3,TABLE) { NODE, DST_DIODE_MIX , 5, { IN0,IN1,IN2,IN3 }, { IN0,IN1,IN2,IN3 }, TABLE, "DISCRETE_DIODE_MIXER4" },
|
||||
|
665
src/mame/audio/copsnrob.c
Normal file
665
src/mame/audio/copsnrob.c
Normal file
@ -0,0 +1,665 @@
|
||||
/************************************************************************
|
||||
* copsnrob Sound System Analog emulation
|
||||
* Nov 2010, Derrick Renaud
|
||||
************************************************************************/
|
||||
#include "emu.h"
|
||||
#include "includes/copsnrob.h"
|
||||
#include "sound/discrete.h"
|
||||
|
||||
|
||||
/* Discrete Sound Input Nodes */
|
||||
#define COPSNROB_MOTOR0_INV NODE_01
|
||||
#define COPSNROB_MOTOR1_INV NODE_02
|
||||
#define COPSNROB_MOTOR2_INV NODE_03
|
||||
#define COPSNROB_MOTOR3_INV NODE_04
|
||||
#define COPSNROB_ZINGS_INV NODE_05
|
||||
#define COPSNROB_FIRES_INV NODE_06
|
||||
#define COPSNROB_CRASH_INV NODE_07
|
||||
#define COPSNROB_SCREECH_INV NODE_08
|
||||
#define COPSNROB_AUDIO_ENABLE NODE_09
|
||||
|
||||
/* Discrete Sound Output Nodes */
|
||||
#define COPSNROB_MOTOR0_SND NODE_11
|
||||
#define COPSNROB_MOTOR1_SND NODE_12
|
||||
#define COPSNROB_MOTOR2_SND NODE_13
|
||||
#define COPSNROB_MOTOR3_SND NODE_14
|
||||
#define COPSNROB_FZ_SND NODE_15
|
||||
#define COPSNROB_CRASH_SND NODE_16
|
||||
#define COPSNROB_SCREECH_SND NODE_17
|
||||
#define COPSNROB_NOISE_1 NODE_18
|
||||
#define COPSNROB_NOISE_2 NODE_18_01
|
||||
|
||||
/* Parts List - Resistors */
|
||||
#define COPSNROB_R16 RES_K(10)
|
||||
#define COPSNROB_R18 RES_K(100)
|
||||
#define COPSNROB_R19 RES_K(100)
|
||||
#define COPSNROB_R20 RES_K(100)
|
||||
#define COPSNROB_R21 RES_K(47)
|
||||
#define COPSNROB_R25 RES_K(47)
|
||||
#define COPSNROB_R26 RES_K(150)
|
||||
#define COPSNROB_R27 RES_K(22)
|
||||
#define COPSNROB_R28 RES_K(18)
|
||||
#define COPSNROB_R33 RES_K(10)
|
||||
#define COPSNROB_R35 RES_K(10)
|
||||
#define COPSNROB_R36 RES_K(15)
|
||||
#define COPSNROB_R37 RES_K(4.7)
|
||||
#define COPSNROB_R38 RES_K(15)
|
||||
#define COPSNROB_R39 RES_K(10)
|
||||
#define COPSNROB_R41 RES_K(33)
|
||||
#define COPSNROB_R42 RES_K(33)
|
||||
#define COPSNROB_R47 RES_K(10)
|
||||
#define COPSNROB_R48 RES_K(1)
|
||||
#define COPSNROB_R49 RES_K(47)
|
||||
#define COPSNROB_R50 RES_K(47)
|
||||
#define COPSNROB_R53 RES_K(47)
|
||||
#define COPSNROB_R54 RES_K(22)
|
||||
#define COPSNROB_R55 RES_K(47)
|
||||
#define COPSNROB_R56 RES_K(470)
|
||||
#define COPSNROB_R57 RES_K(820)
|
||||
#define COPSNROB_R58 RES_K(68)
|
||||
#define COPSNROB_R59 RES_K(1)
|
||||
#define COPSNROB_R64 RES_K(47)
|
||||
#define COPSNROB_R65 RES_K(4.7)
|
||||
#define COPSNROB_R66 RES_K(1.5)
|
||||
#define COPSNROB_R69 RES_K(330)
|
||||
#define COPSNROB_R70 RES_K(330)
|
||||
#define COPSNROB_R71 RES_K(100)
|
||||
#define COPSNROB_R72 RES_K(100)
|
||||
#define COPSNROB_R73 RES_K(47)
|
||||
#define COPSNROB_R74 RES_K(1)
|
||||
#define COPSNROB_R75 RES_K(1)
|
||||
#define COPSNROB_R76 RES_K(12)
|
||||
#define COPSNROB_R77 RES_K(33)
|
||||
#define COPSNROB_R78 RES_K(100)
|
||||
#define COPSNROB_R79 RES_K(2.2)
|
||||
#define COPSNROB_R80 RES_K(1)
|
||||
#define COPSNROB_R81 RES_K(8.2)
|
||||
#define COPSNROB_R82 RES_K(3.9)
|
||||
#define COPSNROB_R83 RES_K(27)
|
||||
#define COPSNROB_R84 RES_K(15)
|
||||
#define COPSNROB_R85 (330)
|
||||
#define COPSNROB_R86 RES_K(330)
|
||||
#define COPSNROB_R87 (820)
|
||||
#define COPSNROB_R88 RES_K(1)
|
||||
#define COPSNROB_R89 RES_K(1)
|
||||
#define COPSNROB_R92 RES_K(100)
|
||||
#define COPSNROB_R93 RES_K(100)
|
||||
#define COPSNROB_R94 RES_K(10)
|
||||
|
||||
/* Parts List - Capacitors */
|
||||
#define COPSNROB_C3 CAP_U(100)
|
||||
#define COPSNROB_C12 CAP_U(0.1)
|
||||
#define COPSNROB_C13 CAP_U(0.1)
|
||||
#define COPSNROB_C17 CAP_U(0.001)
|
||||
#define COPSNROB_C19 CAP_U(10)
|
||||
#define COPSNROB_C20 CAP_U(0.01)
|
||||
#define COPSNROB_C23 CAP_U(0.1)
|
||||
#define COPSNROB_C24 CAP_U(0.22)
|
||||
#define COPSNROB_C28 CAP_U(1)
|
||||
#define COPSNROB_C30 CAP_U(0.01)
|
||||
#define COPSNROB_C31 CAP_U(0.1)
|
||||
#define COPSNROB_C32 CAP_U(5)
|
||||
#define COPSNROB_C33 CAP_U(10)
|
||||
#define COPSNROB_C36 CAP_U(100)
|
||||
#define COPSNROB_C39 CAP_U(0.1)
|
||||
#define COPSNROB_C37 CAP_U(0.1)
|
||||
#define COPSNROB_C40 CAP_U(0.1)
|
||||
#define COPSNROB_C41 CAP_U(0.03)
|
||||
#define COPSNROB_C42 CAP_U(0.047)
|
||||
#define COPSNROB_C43 CAP_U(0.047)
|
||||
#define COPSNROB_C55 CAP_U(0.1)
|
||||
#define COPSNROB_C58 CAP_U(0.1)
|
||||
#define COPSNROB_C59 CAP_U(0.1)
|
||||
|
||||
/* Timing values */
|
||||
#define COPSNROB_2V (15750/2/2) /* has to be verified */
|
||||
|
||||
|
||||
static const discrete_555_desc copsnrob_motor23_555_1 =
|
||||
{
|
||||
DISC_555_OUT_SQW,
|
||||
5, DEFAULT_555_VALUES
|
||||
};
|
||||
|
||||
static const discrete_555_desc copsnrob_motor23_555_2 =
|
||||
{
|
||||
DISC_555_OUT_ENERGY | DISC_555_TRIGGER_IS_LOGIC,
|
||||
5, DEFAULT_555_VALUES
|
||||
};
|
||||
|
||||
static const discrete_op_amp_filt_info copsnrob_motor23_filter =
|
||||
{
|
||||
COPSNROB_R28, 0, COPSNROB_R87, 0, COPSNROB_R86, /* r1, r2, r3, r4, rF */
|
||||
COPSNROB_C42, COPSNROB_C43, 0, /* c1, c2, c3 */
|
||||
5.0 * RES_VOLTAGE_DIVIDER(COPSNROB_R88, COPSNROB_R89), 5, 0 /* vRef, vP, vN */
|
||||
};
|
||||
|
||||
static const discrete_dac_r1_ladder copsnrob_crash_dac =
|
||||
{
|
||||
4, /* ladderLength */
|
||||
{COPSNROB_R81, COPSNROB_R82, COPSNROB_R79, COPSNROB_R80},
|
||||
0, 0, 0, COPSNROB_C58 /* vBias, rBias, rGnd, cFilter */
|
||||
};
|
||||
|
||||
static const discrete_mixer_desc copsnrob_final_mixer01 =
|
||||
{
|
||||
DISC_MIXER_IS_RESISTOR,
|
||||
{COPSNROB_R21, COPSNROB_R25, COPSNROB_R33, COPSNROB_R70, COPSNROB_R71},
|
||||
{0}, {0}, 0, COPSNROB_R35, 0, COPSNROB_C59, /* r_node{}, c{}, rI, rF, cF, cAmp */
|
||||
0, 1 /* vRef, gain */
|
||||
};
|
||||
|
||||
static const discrete_mixer_desc copsnrob_final_mixer23 =
|
||||
{
|
||||
DISC_MIXER_IS_RESISTOR,
|
||||
{COPSNROB_R93, COPSNROB_R92, COPSNROB_R72, COPSNROB_R69, COPSNROB_R16},
|
||||
{0}, {0}, 0, COPSNROB_R94, 0, COPSNROB_C55, /* r_node{}, c{}, rI, rF, cF, cAmp */
|
||||
0, 1 /* vRef, gain */
|
||||
};
|
||||
|
||||
static const discrete_dac_r1_ladder copsnrob_motor23_cv_dac =
|
||||
{
|
||||
1, /* ladderLength */
|
||||
{COPSNROB_R65},
|
||||
5, RES_K(5), RES_K(10), COPSNROB_C36 /* vBias; rBias; rGnd; cFilter */
|
||||
};
|
||||
|
||||
#define COPSNROB_MOTOR01_BASE_NODE NODE_20
|
||||
#define COPSNROB_MOTOR23_BASE_NODE NODE_30
|
||||
#define COPSNROB_NODE(_base, _num, _offset) NODE_RELATIVE(_base, _num * 100 + _offset)
|
||||
#define COPSNROB_MOTOR01_NODE(_num, _offset) COPSNROB_NODE(COPSNROB_MOTOR01_BASE_NODE, _num, _offset)
|
||||
#define COPSNROB_MOTOR23_NODE(_num, _offset) COPSNROB_NODE(COPSNROB_MOTOR23_BASE_NODE, _num, _offset)
|
||||
|
||||
|
||||
/************************************************
|
||||
* MOTOR2/3 Definition Start
|
||||
************************************************/
|
||||
#define COPSNROB_MOTOR23(_output, _input, _num) \
|
||||
/* simulate the RC connected to the 555 CV pin with a DAC */ \
|
||||
DISCRETE_DAC_R1(COPSNROB_MOTOR23_NODE(_num, 1), \
|
||||
_input, 4.2, &copsnrob_motor23_cv_dac) /* DATA; VDATA - TTL with light load */ \
|
||||
DISCRETE_555_ASTABLE_CV(COPSNROB_MOTOR23_NODE(_num, 2), /* IC J2, pin 5 */ \
|
||||
1, /* RESET */ \
|
||||
COPSNROB_R64, COPSNROB_R42, COPSNROB_C24, \
|
||||
COPSNROB_MOTOR23_NODE(_num, 1), /* CTRLV - IC J2, pin 3 */ \
|
||||
&copsnrob_motor23_555_1) \
|
||||
/* R27 and C17 can be ignored, we will just trigger on the logic */ \
|
||||
DISCRETE_555_MSTABLE(COPSNROB_MOTOR23_NODE(_num, 3), /* IC J3, pin 9 */ \
|
||||
1, /* RESET */ \
|
||||
COPSNROB_MOTOR23_NODE(_num, 2), /* IC J3, pin 8 */ \
|
||||
COPSNROB_R41, COPSNROB_C23, \
|
||||
&copsnrob_motor23_555_2) \
|
||||
DISCRETE_OP_AMP_FILTER(_output, /* IC L4, pin 7 */ \
|
||||
1, /* ENAB */ \
|
||||
COPSNROB_MOTOR23_NODE(_num, 3), 0, /* INP0; INP1 */ \
|
||||
DISC_OP_AMP_FILTER_IS_BAND_PASS_1M, &copsnrob_motor23_filter)
|
||||
/************************************************
|
||||
* MOTOR2/3 Definition End
|
||||
************************************************/
|
||||
|
||||
|
||||
/************************************************
|
||||
* CUSTOM_NOISE Definition Start
|
||||
* - output is energy
|
||||
************************************************/
|
||||
#define COPSNROB_CUSTOM_NOISE__FREQ DISCRETE_INPUT(0)
|
||||
|
||||
struct copsnrob_custom_noise_context
|
||||
{
|
||||
int flip_flop;
|
||||
int noise1_had_xtime;
|
||||
int noise2_had_xtime;
|
||||
UINT8 high_byte;
|
||||
UINT8 low_byte;
|
||||
double t_used;
|
||||
double t1;
|
||||
};
|
||||
|
||||
#define COPSNROB_CUSTOM_NOISE_HIGH 4.2
|
||||
|
||||
DISCRETE_STEP(copsnrob_custom_noise)
|
||||
{
|
||||
DISCRETE_DECLARE_CONTEXT(copsnrob_custom_noise)
|
||||
|
||||
double t_used = context->t_used;
|
||||
double t1 = context->t1;
|
||||
double x_time = 0;
|
||||
UINT8 low_byte = context->low_byte;
|
||||
UINT8 high_byte = context->high_byte;
|
||||
UINT8 xnor_out; /* IC F2, pin 2 */
|
||||
int last_noise1_bit = (low_byte >> 4) & 0x01;
|
||||
int last_noise2_bit = (low_byte >> 5) & 0x01;
|
||||
|
||||
t_used += node->info->sample_time;
|
||||
|
||||
/* This clock will never run faster then the sample rate,
|
||||
* so we do not bother to check.
|
||||
*/
|
||||
if (t_used > t1)
|
||||
{
|
||||
/* calculate the overshoot time */
|
||||
t_used -= t1;
|
||||
context->flip_flop ^= 1;
|
||||
/* clocks on low to high */
|
||||
if (context->flip_flop)
|
||||
{
|
||||
int new_noise_bit;
|
||||
|
||||
/* shift */
|
||||
xnor_out = (((low_byte >> 6) & 0x01) ^ (high_byte & 0x01)) ^ 0x01;
|
||||
low_byte = (low_byte << 1) | ((high_byte >> 7) & 0x01);
|
||||
high_byte = (high_byte << 1) | xnor_out;
|
||||
if (high_byte == 0xff) /* IC H1, pin 8 */
|
||||
high_byte = 0;
|
||||
context->low_byte = low_byte;
|
||||
context->high_byte = high_byte;
|
||||
|
||||
/* Convert last switch time to a ratio */
|
||||
x_time = t_used / node->info->sample_time;
|
||||
/* use x_time if bit changed */
|
||||
new_noise_bit = (low_byte >> 4) & 0x01;
|
||||
if (last_noise1_bit != new_noise_bit)
|
||||
{
|
||||
node->output[0] = COPSNROB_CUSTOM_NOISE_HIGH * (new_noise_bit ? x_time : (1.0 - x_time));
|
||||
context->noise1_had_xtime = 1;
|
||||
}
|
||||
new_noise_bit = (low_byte >> 5) & 0x01;
|
||||
if (last_noise2_bit != new_noise_bit)
|
||||
{
|
||||
node->output[1] = COPSNROB_CUSTOM_NOISE_HIGH * (new_noise_bit ? x_time : (1.0 - x_time));
|
||||
context->noise2_had_xtime = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* see if we need to move from x_time state to full state */
|
||||
if (context->noise1_had_xtime)
|
||||
{
|
||||
node->output[0] = COPSNROB_CUSTOM_NOISE_HIGH * last_noise1_bit;
|
||||
context->noise1_had_xtime = 0;
|
||||
}
|
||||
if (context->noise2_had_xtime)
|
||||
{
|
||||
node->output[1] = COPSNROB_CUSTOM_NOISE_HIGH * last_noise2_bit;
|
||||
context->noise2_had_xtime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
context->t_used = t_used;
|
||||
}
|
||||
|
||||
DISCRETE_RESET(copsnrob_custom_noise)
|
||||
{
|
||||
DISCRETE_DECLARE_CONTEXT(copsnrob_custom_noise)
|
||||
|
||||
context->t1 = 0.5 / COPSNROB_CUSTOM_NOISE__FREQ ;
|
||||
context->flip_flop = 0;
|
||||
context->low_byte = 0;
|
||||
context->high_byte = 0;
|
||||
context->t_used = 0;
|
||||
context->noise1_had_xtime = 0;
|
||||
context->noise2_had_xtime = 0;
|
||||
}
|
||||
|
||||
static const discrete_custom_info copsnrob_custom_noise =
|
||||
{
|
||||
DISCRETE_CUSTOM_MODULE( copsnrob_custom_noise, struct copsnrob_custom_noise_context),
|
||||
NULL
|
||||
};
|
||||
/************************************************
|
||||
* CUSTOM_NOISE Definition End
|
||||
************************************************/
|
||||
|
||||
|
||||
#if (0)
|
||||
/************************************************
|
||||
* CUSTOM_ZINGS_555_MONOSTABLE Definition Start
|
||||
* - output is energy
|
||||
************************************************/
|
||||
#define COPSNROB_CUSTOM_ZINGS_555_MONOSTABLE__TRIG DISCRETE_INPUT(0)
|
||||
#define COPSNROB_CUSTOM_ZINGS_555_MONOSTABLE__R DISCRETE_INPUT(1)
|
||||
#define COPSNROB_CUSTOM_ZINGS_555_MONOSTABLE__C DISCRETE_INPUT(2)
|
||||
|
||||
struct copsnrob_zings_555_monostable_context
|
||||
{
|
||||
double rc;
|
||||
double exponent;
|
||||
double v_cap;
|
||||
int flip_flop;
|
||||
};
|
||||
|
||||
DISCRETE_STEP(copsnrob_zings_555_monostable)
|
||||
{
|
||||
DISCRETE_DECLARE_CONTEXT(copsnrob_zings_555_monostable)
|
||||
|
||||
const double v_threshold = 5.0 * 2 / 3;
|
||||
const double v_out_high = 5.0 - 0.5; /* light load */
|
||||
|
||||
/* int ff_reset = (COPSNROB_CUSTOM_ZINGS_555_MONOSTABLE__TRIG > v_threshold ? 1 : 0; */
|
||||
int ff_set = COPSNROB_CUSTOM_ZINGS_555_MONOSTABLE__TRIG < (5.0 / 3) ? 1 : 0;
|
||||
int flip_flop = context->flip_flop;
|
||||
double v_cap = context->v_cap;
|
||||
double x_time = 0;
|
||||
|
||||
/* From testing a real IC */
|
||||
/* Trigger going low overides everything. It forces the FF/Output high.
|
||||
* If Threshold is high, the output will still go high as long as trigger is low.
|
||||
* The output will then go low when trigger rises above it's 1/3VCC value.
|
||||
* If threshold is below it's 2/3VCC value, the output will remain high.
|
||||
*/
|
||||
if (ff_set)
|
||||
{
|
||||
flip_flop = 1;
|
||||
context->flip_flop = flip_flop;
|
||||
}
|
||||
|
||||
if (flip_flop)
|
||||
{
|
||||
double v_diff = v_out_high - v_cap;
|
||||
|
||||
/* charge */
|
||||
v_cap += v_diff * context->exponent;
|
||||
/* no state change if trigger is low */
|
||||
if (!ff_set && (v_cap > v_threshold))
|
||||
{
|
||||
double rc = context->rc;
|
||||
|
||||
flip_flop = 0;
|
||||
context->flip_flop = flip_flop;
|
||||
/* calculate overshoot */
|
||||
x_time = rc * log(1.0 / (1.0 - ((v_cap - v_threshold) / v_diff)));
|
||||
/* discharge the overshoot */
|
||||
v_cap = v_threshold;
|
||||
v_cap -= v_cap * RC_CHARGE_EXP_DT(rc, x_time);
|
||||
x_time /= node->info->sample_time;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Optimization - already discharged */
|
||||
if (v_cap == 0)
|
||||
return;
|
||||
/* discharge */
|
||||
v_cap -= v_cap * context->exponent;
|
||||
/* Optimization - close enough to 0 to be 0 */
|
||||
if (v_cap < 0.0001)
|
||||
v_cap = 0;
|
||||
}
|
||||
context->v_cap = v_cap;
|
||||
|
||||
if (x_time > 0)
|
||||
node->output[0] = v_out_high * x_time;
|
||||
else if (flip_flop)
|
||||
node->output[0] = v_out_high;
|
||||
else
|
||||
node->output[0] = 0;
|
||||
}
|
||||
|
||||
DISCRETE_RESET(copsnrob_zings_555_monostable)
|
||||
{
|
||||
DISCRETE_DECLARE_CONTEXT(copsnrob_zings_555_monostable)
|
||||
|
||||
context->rc = COPSNROB_CUSTOM_ZINGS_555_MONOSTABLE__R * COPSNROB_CUSTOM_ZINGS_555_MONOSTABLE__C;
|
||||
context->exponent = RC_CHARGE_EXP(context->rc);
|
||||
context->v_cap = 0;
|
||||
context->flip_flop = 0;
|
||||
node->output[0] = 0;
|
||||
}
|
||||
|
||||
static const discrete_custom_info copsnrob_zings_555_monostable =
|
||||
{
|
||||
DISCRETE_CUSTOM_MODULE( copsnrob_zings_555_monostable, struct copsnrob_zings_555_monostable_context),
|
||||
NULL
|
||||
};
|
||||
/************************************************
|
||||
* CUSTOM_ZINGS_555_MONOSTABLE Definition End
|
||||
************************************************/
|
||||
|
||||
|
||||
/************************************************
|
||||
* CUSTOM_ZINGS_555_ASTABLE Definition Start
|
||||
* - output is energy
|
||||
************************************************/
|
||||
#define COPSNROB_CUSTOM_ZINGS_555_ASTABLE__RESET DISCRETE_INPUT(0)
|
||||
#define COPSNROB_CUSTOM_ZINGS_555_ASTABLE__R1 DISCRETE_INPUT(1)
|
||||
#define COPSNROB_CUSTOM_ZINGS_555_ASTABLE__R2 DISCRETE_INPUT(2)
|
||||
#define COPSNROB_CUSTOM_ZINGS_555_ASTABLE__C1 DISCRETE_INPUT(3)
|
||||
#define COPSNROB_CUSTOM_ZINGS_555_ASTABLE__C2 DISCRETE_INPUT(4)
|
||||
|
||||
struct copsnrob_zings_555_astable_context
|
||||
{
|
||||
double r1c1;
|
||||
double r2c2;
|
||||
double exponent1;
|
||||
double exponent2;
|
||||
double v_cap1;
|
||||
double v_cap2;
|
||||
int flip_flop;
|
||||
};
|
||||
|
||||
DISCRETE_STEP(copsnrob_zings_555_astable)
|
||||
{
|
||||
DISCRETE_DECLARE_CONTEXT(copsnrob_zings_555_astable)
|
||||
|
||||
int reset_active = COPSNROB_CUSTOM_ZINGS_555_ASTABLE__RESET < 0.7;
|
||||
int flip_flop = context->flip_flop;
|
||||
double v_cap1 = context->v_cap1;
|
||||
double v_cap2 = context->v_cap2;
|
||||
double x_time = 0;
|
||||
|
||||
if (reset_active)
|
||||
{
|
||||
if (flip_flop)
|
||||
{
|
||||
flip_flop = 0;
|
||||
context->flip_flop = 0;
|
||||
}
|
||||
/* Optimization - only discharge if needed */
|
||||
if (v_cap1 != 0)
|
||||
{
|
||||
/* discharge */
|
||||
v_cap1 -= v_cap1 * context->exponent;
|
||||
/* Optimization - close enough to 0 to be 0 */
|
||||
if (v_cap1 < 0.0001)
|
||||
v_cap1 = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* this oscillator will never create a frequency greater then 1/2 the sample rate,
|
||||
* so we won't worry about missing samples */
|
||||
if (flip_flop)
|
||||
{
|
||||
/* The reset voltage also charges the CV cap */
|
||||
double v_diff1 = COPSNROB_CUSTOM_ZINGS_555_ASTABLE__RESET - v_cap1;
|
||||
|
||||
/* charge */
|
||||
v_cap1 += v_diff1 * context->exponent1;
|
||||
|
||||
if (v_cap1 > v_threshold)
|
||||
{
|
||||
double r1c1 = context->r1c1;
|
||||
|
||||
flip_flop = 0;
|
||||
context->flip_flop = flip_flop;
|
||||
/* calculate overshoot */
|
||||
x_time = r1c1 * log(1.0 / (1.0 - ((v_cap1 - v_threshold) / v_diff1)));
|
||||
/* discharge the overshoot */
|
||||
v_cap1 = v_threshold;
|
||||
v_cap1 -= v_cap1 * RC_CHARGE_EXP_DT(r1c1, x_time);
|
||||
x_time /= node->info->sample_time;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DISCRETE_RESET(copsnrob_zings_555_astable)
|
||||
{
|
||||
DISCRETE_DECLARE_CONTEXT(copsnrob_zings_555_astable)
|
||||
|
||||
context->r1c1 = COPSNROB_CUSTOM_ZINGS_555_MONOSTABLE__R1 * COPSNROB_CUSTOM_ZINGS_555_MONOSTABLE__C1;
|
||||
context->r2c2 = COPSNROB_CUSTOM_ZINGS_555_MONOSTABLE__R2 * COPSNROB_CUSTOM_ZINGS_555_MONOSTABLE__C2;
|
||||
context->exponent1 = RC_CHARGE_EXP(context->r1c1);
|
||||
context->exponent2 = RC_CHARGE_EXP(context->r2c2);
|
||||
context->v_cap1 = 0;
|
||||
context->v_cap2 = 0;
|
||||
context->flip_flop = 0;
|
||||
node->output[0] = 0;
|
||||
}
|
||||
|
||||
static const discrete_custom_info copsnrob_zings_555_astable =
|
||||
{
|
||||
DISCRETE_CUSTOM_MODULE( copsnrob_zings_555_astable, struct copsnrob_zings_555_astable_context),
|
||||
NULL
|
||||
};
|
||||
/************************************************
|
||||
* CUSTOM_ZINGS_555_ASTABLE Definition End
|
||||
************************************************/
|
||||
#endif
|
||||
|
||||
|
||||
DISCRETE_SOUND_START(copsnrob)
|
||||
|
||||
/************************************************
|
||||
* Input register mapping
|
||||
************************************************/
|
||||
DISCRETE_INPUTX_LOGIC(COPSNROB_MOTOR0_INV, 3.8, 0, 0) /* TTL at high load */
|
||||
DISCRETE_INPUTX_LOGIC(COPSNROB_MOTOR1_INV, 3.8, 0, 0) /* TTL at high load */
|
||||
DISCRETE_INPUT_LOGIC(COPSNROB_MOTOR2_INV)
|
||||
DISCRETE_INPUT_LOGIC(COPSNROB_MOTOR3_INV)
|
||||
DISCRETE_INPUT_LOGIC(COPSNROB_ZINGS_INV)
|
||||
DISCRETE_INPUT_LOGIC(COPSNROB_FIRES_INV)
|
||||
DISCRETE_INPUT_NOT(COPSNROB_CRASH_INV) /* inverted for counter use */
|
||||
DISCRETE_INPUT_LOGIC(COPSNROB_SCREECH_INV)
|
||||
DISCRETE_INPUT_NOT(COPSNROB_AUDIO_ENABLE) /* IC A1, pins 2 & 12 */
|
||||
|
||||
/************************************************
|
||||
* MOTOR0/1
|
||||
************************************************/
|
||||
DISCRETE_CONSTANT(COPSNROB_MOTOR0_SND, 0)
|
||||
DISCRETE_CONSTANT(COPSNROB_MOTOR1_SND, 0)
|
||||
|
||||
/************************************************
|
||||
* MOTOR2/3
|
||||
************************************************/
|
||||
COPSNROB_MOTOR23(COPSNROB_MOTOR2_SND, COPSNROB_MOTOR2_INV, 0)
|
||||
COPSNROB_MOTOR23(COPSNROB_MOTOR3_SND, COPSNROB_MOTOR3_INV, 1)
|
||||
|
||||
/************************************************
|
||||
* CRASH
|
||||
************************************************/
|
||||
DISCRETE_CUSTOM1(COPSNROB_NOISE_1, /* IC J2, pin 10 */
|
||||
COPSNROB_2V, /* CLK */
|
||||
&copsnrob_custom_noise)
|
||||
/* COPSNROB_NOISE_2 derived from sub out of above custom module - IC J2, pin 11 */
|
||||
/* We use the measured 555 timer frequency (IC M3) for speed */
|
||||
DISCRETE_COUNTER(NODE_40, /* IC L2 */
|
||||
NODE_41, /* ENAB - IC L2, pin 14 */
|
||||
COPSNROB_CRASH_INV, /* RESET - IC L2, pin 11 */
|
||||
92, /* IC L2, pin 4 - freq measured */
|
||||
0, 15, DISC_COUNT_DOWN, 15, DISC_CLK_IS_FREQ) /* MIN; MAX; DIR; INIT0; CLKTYPE */
|
||||
DISCRETE_TRANSFORM2(NODE_41, /* IC M2, pin 3 - goes high at count 0 */
|
||||
NODE_40, 0, "01=!") /* -we will invert it for use by the counter module */
|
||||
DISCRETE_SWITCH(NODE_42, /* IC L3 */
|
||||
1, COPSNROB_NOISE_2, 0, NODE_40) /* ENAB; SWITCH; INP0; INP1 */
|
||||
DISCRETE_DAC_R1(COPSNROB_CRASH_SND,
|
||||
NODE_42, 3.8, /* DATA; VDATA */
|
||||
&copsnrob_crash_dac)
|
||||
//DISCRETE_WAVLOG2(COPSNROB_NOISE_1, 1000, COPSNROB_NOISE_2, 1000)
|
||||
//DISCRETE_WAVLOG2(NODE_42, 1000, COPSNROB_CRASH_SND, 1000)
|
||||
|
||||
/************************************************
|
||||
* SCREECH
|
||||
************************************************/
|
||||
DISCRETE_CONSTANT(COPSNROB_SCREECH_SND, 0)
|
||||
|
||||
/************************************************
|
||||
* FZ (Fires, Zings)
|
||||
************************************************/
|
||||
#if (0)
|
||||
DISCRETE_CUSTOM2(NODE_60, /* IC D3, pin 5 */
|
||||
COPSNROB_R38, COPSNROB_C19,
|
||||
&copsnrob_zings_555_monostable)
|
||||
DISCRETE_CUSTOM4(NODE_60, /* IC D3, pin 8 & 12 */
|
||||
COPSNROB_R36, COPSNROB_R37,
|
||||
COPSNROB_C3, COPSNROB_C13,
|
||||
&copsnrob_zings_555_astable)
|
||||
|
||||
#else
|
||||
DISCRETE_CONSTANT(COPSNROB_FZ_SND, 0)
|
||||
#endif
|
||||
|
||||
/************************************************
|
||||
* MIXER
|
||||
************************************************/
|
||||
DISCRETE_MIXER5(NODE_90, /* IC B3, pin 3 */
|
||||
COPSNROB_AUDIO_ENABLE, /* ENAB */
|
||||
COPSNROB_MOTOR1_SND, COPSNROB_MOTOR0_SND, COPSNROB_FZ_SND, COPSNROB_SCREECH_SND, COPSNROB_CRASH_SND,
|
||||
&copsnrob_final_mixer01)
|
||||
DISCRETE_MIXER5(NODE_91, /* IC P3, pin 3 */
|
||||
COPSNROB_AUDIO_ENABLE, /* ENAB */
|
||||
COPSNROB_MOTOR3_SND, COPSNROB_MOTOR2_SND, COPSNROB_CRASH_SND, COPSNROB_SCREECH_SND, COPSNROB_FZ_SND,
|
||||
&copsnrob_final_mixer23)
|
||||
DISCRETE_OUTPUT(NODE_90, 32767.0*3.5)
|
||||
DISCRETE_OUTPUT(NODE_91, 32767.0*3.5)
|
||||
DISCRETE_SOUND_END
|
||||
|
||||
|
||||
WRITE8_HANDLER( copsnrob_misc_w )
|
||||
{
|
||||
device_t *device = space->machine->device("discrete");
|
||||
copsnrob_state *state = space->machine->driver_data<copsnrob_state>();
|
||||
UINT8 latched_data = state->ic_h3_data;
|
||||
UINT8 special_data = data & 0x01;
|
||||
|
||||
/* ignore if no change */
|
||||
if (((latched_data >> offset) & 0x01) == special_data)
|
||||
return;
|
||||
|
||||
if (special_data)
|
||||
latched_data |= 1 << offset;
|
||||
else
|
||||
latched_data &= ~(1 << offset);
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 0x00:
|
||||
discrete_sound_w(device, COPSNROB_MOTOR3_INV, special_data);
|
||||
break;
|
||||
|
||||
case 0x01:
|
||||
discrete_sound_w(device, COPSNROB_MOTOR2_INV, special_data);
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
discrete_sound_w(device, COPSNROB_MOTOR1_INV, special_data);
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
discrete_sound_w(device, COPSNROB_MOTOR0_INV, special_data);
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
discrete_sound_w(device, COPSNROB_SCREECH_INV, special_data);
|
||||
break;
|
||||
|
||||
case 0x05:
|
||||
discrete_sound_w(device, COPSNROB_CRASH_INV, special_data);
|
||||
break;
|
||||
|
||||
case 0x06:
|
||||
/* One Start */
|
||||
set_led_status(space->machine, 0, !special_data);
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
discrete_sound_w(device, COPSNROB_AUDIO_ENABLE, special_data);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
state->ic_h3_data = latched_data;
|
||||
}
|
@ -38,8 +38,7 @@
|
||||
|
||||
I/O Write:
|
||||
|
||||
0500-0503 Direction of the cars
|
||||
0504-0507 (sounds/enable) - 0506: LED 1
|
||||
0500-0507 (sounds/enable) - 0506: LED 1
|
||||
0600 Beer Truck Y
|
||||
0700-07ff Beer Truck Sync Area
|
||||
0800-08ff Bullets RAM
|
||||
@ -76,26 +75,22 @@ static PALETTE_INIT( copsnrob )
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* LEDs
|
||||
* I/O
|
||||
*
|
||||
*************************************/
|
||||
|
||||
static READ8_HANDLER( copsnrob_misc_r )
|
||||
{
|
||||
copsnrob_state *state = space->machine->driver_data<copsnrob_state>();
|
||||
return state->misc | (input_port_read(space->machine, "IN0") & 0x80);
|
||||
return input_port_read(space->machine, "IN0") & 0x80;
|
||||
}
|
||||
|
||||
static WRITE8_HANDLER( copsnrob_misc_w )
|
||||
static WRITE8_HANDLER( copsnrob_misc2_w )
|
||||
{
|
||||
copsnrob_state *state = space->machine->driver_data<copsnrob_state>();
|
||||
|
||||
state->misc = data & 0x7f;
|
||||
set_led_status(space->machine, 1, ~data & 0x40);
|
||||
}
|
||||
|
||||
static WRITE8_HANDLER( copsnrob_led_w )
|
||||
{
|
||||
set_led_status(space->machine, 0, ~data & 0x01);
|
||||
/* Multi Player Start */
|
||||
set_led_status(space->machine, 1, !((data >> 6) & 0x01));
|
||||
}
|
||||
|
||||
|
||||
@ -109,9 +104,7 @@ static WRITE8_HANDLER( copsnrob_led_w )
|
||||
static ADDRESS_MAP_START( main_map, ADDRESS_SPACE_PROGRAM, 8 )
|
||||
ADDRESS_MAP_GLOBAL_MASK(0x1fff)
|
||||
AM_RANGE(0x0000, 0x01ff) AM_RAM
|
||||
AM_RANGE(0x0500, 0x0503) AM_WRITEONLY
|
||||
// AM_RANGE(0x0504, 0x0507) AM_WRITENOP // ???
|
||||
AM_RANGE(0x0506, 0x0506) AM_WRITE(copsnrob_led_w)
|
||||
AM_RANGE(0x0500, 0x0507) AM_WRITE(copsnrob_misc_w)
|
||||
AM_RANGE(0x0600, 0x0600) AM_WRITEONLY AM_BASE_MEMBER(copsnrob_state, trucky)
|
||||
AM_RANGE(0x0700, 0x07ff) AM_WRITEONLY AM_BASE_MEMBER(copsnrob_state, truckram)
|
||||
AM_RANGE(0x0800, 0x08ff) AM_RAM AM_BASE_MEMBER(copsnrob_state, bulletsram)
|
||||
@ -122,8 +115,11 @@ static ADDRESS_MAP_START( main_map, ADDRESS_SPACE_PROGRAM, 8 )
|
||||
// AM_RANGE(0x1000, 0x1003) AM_WRITENOP
|
||||
// AM_RANGE(0x1000, 0x1000) AM_READ_PORT("IN0")
|
||||
AM_RANGE(0x1000, 0x1000) AM_READ(copsnrob_misc_r)
|
||||
AM_RANGE(0x1000, 0x1000) AM_WRITE(copsnrob_misc_w)
|
||||
AM_RANGE(0x1002, 0x100e) AM_READ(copsnrob_gun_position_r)
|
||||
AM_RANGE(0x1000, 0x1000) AM_WRITE(copsnrob_misc2_w)
|
||||
AM_RANGE(0x1002, 0x1002) AM_READ_PORT("CTRL1")
|
||||
AM_RANGE(0x1006, 0x1006) AM_READ_PORT("CTRL2")
|
||||
AM_RANGE(0x100a, 0x100a) AM_READ_PORT("CTRL3")
|
||||
AM_RANGE(0x100e, 0x100e) AM_READ_PORT("CTRL4")
|
||||
AM_RANGE(0x1012, 0x1012) AM_READ_PORT("DSW")
|
||||
AM_RANGE(0x1016, 0x1016) AM_READ_PORT("IN1")
|
||||
AM_RANGE(0x101a, 0x101a) AM_READ_PORT("IN2")
|
||||
@ -138,6 +134,8 @@ ADDRESS_MAP_END
|
||||
*
|
||||
*************************************/
|
||||
|
||||
static const int gun_table[] = {0x3f, 0x5f, 0x6f, 0x77, 0x7b, 0x7d, 0x7e};
|
||||
|
||||
static INPUT_PORTS_START( copsnrob )
|
||||
PORT_START("IN0")
|
||||
PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_VBLANK )
|
||||
@ -166,25 +164,20 @@ static INPUT_PORTS_START( copsnrob )
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(2)
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(1)
|
||||
|
||||
/* These input ports are fake */
|
||||
PORT_START("FAKE0")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_HIGH,IPT_JOYSTICK_UP ) PORT_4WAY PORT_PLAYER(1)
|
||||
PORT_BIT( 0x02, IP_ACTIVE_HIGH,IPT_JOYSTICK_DOWN ) PORT_4WAY PORT_PLAYER(1)
|
||||
PORT_START("CTRL1")
|
||||
PORT_BIT( 0x7f, 0x03, IPT_POSITIONAL_V ) PORT_POSITIONS(7) PORT_REMAP_TABLE(gun_table) PORT_SENSITIVITY(15) PORT_KEYDELTA(1) PORT_CENTERDELTA(0) PORT_PLAYER(1)
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)
|
||||
|
||||
PORT_START("FAKE1")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_HIGH,IPT_JOYSTICK_UP ) PORT_4WAY PORT_PLAYER(2)
|
||||
PORT_BIT( 0x02, IP_ACTIVE_HIGH,IPT_JOYSTICK_DOWN ) PORT_4WAY PORT_PLAYER(2)
|
||||
PORT_START("CTRL2")
|
||||
PORT_BIT( 0x7f, 0x03, IPT_POSITIONAL_V ) PORT_POSITIONS(7) PORT_REMAP_TABLE(gun_table) PORT_SENSITIVITY(15) PORT_KEYDELTA(1) PORT_CENTERDELTA(0) PORT_PLAYER(2)
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
|
||||
|
||||
PORT_START("FAKE2")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_HIGH,IPT_JOYSTICK_UP ) PORT_4WAY PORT_PLAYER(3)
|
||||
PORT_BIT( 0x02, IP_ACTIVE_HIGH,IPT_JOYSTICK_DOWN ) PORT_4WAY PORT_PLAYER(3)
|
||||
PORT_START("CTRL3")
|
||||
PORT_BIT( 0x7f, 0x03, IPT_POSITIONAL_V ) PORT_POSITIONS(7) PORT_REMAP_TABLE(gun_table) PORT_SENSITIVITY(15) PORT_KEYDELTA(1) PORT_CENTERDELTA(0) PORT_PLAYER(3)
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(3)
|
||||
|
||||
PORT_START("FAKE3")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_HIGH,IPT_JOYSTICK_UP ) PORT_4WAY PORT_PLAYER(4)
|
||||
PORT_BIT( 0x02, IP_ACTIVE_HIGH,IPT_JOYSTICK_DOWN ) PORT_4WAY PORT_PLAYER(4)
|
||||
PORT_START("CTRL4")
|
||||
PORT_BIT( 0x7f, 0x03, IPT_POSITIONAL_V ) PORT_POSITIONS(7) PORT_REMAP_TABLE(gun_table) PORT_SENSITIVITY(15) PORT_KEYDELTA(1) PORT_CENTERDELTA(0) PORT_PLAYER(4)
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(4)
|
||||
INPUT_PORTS_END
|
||||
|
||||
@ -260,6 +253,7 @@ static MACHINE_START( copsnrob )
|
||||
{
|
||||
copsnrob_state *state = machine->driver_data<copsnrob_state>();
|
||||
|
||||
state_save_register_global(machine, state->ic_h3_data);
|
||||
state_save_register_global(machine, state->misc);
|
||||
}
|
||||
|
||||
@ -267,6 +261,7 @@ static MACHINE_RESET( copsnrob )
|
||||
{
|
||||
copsnrob_state *state = machine->driver_data<copsnrob_state>();
|
||||
|
||||
state->ic_h3_data = 0;
|
||||
state->misc = 0;
|
||||
}
|
||||
|
||||
@ -293,6 +288,14 @@ static MACHINE_CONFIG_START( copsnrob, copsnrob_state )
|
||||
|
||||
MDRV_PALETTE_INIT(copsnrob)
|
||||
MDRV_VIDEO_UPDATE(copsnrob)
|
||||
|
||||
/* sound hardware */
|
||||
MDRV_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
|
||||
|
||||
MDRV_SOUND_ADD("discrete", DISCRETE, 0)
|
||||
MDRV_SOUND_CONFIG_DISCRETE(copsnrob)
|
||||
MDRV_SOUND_ROUTE(0, "lspeaker", 1.0)
|
||||
MDRV_SOUND_ROUTE(1, "rspeaker", 1.0)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
@ -341,4 +344,4 @@ ROM_END
|
||||
*
|
||||
*************************************/
|
||||
|
||||
GAMEL( 1976, copsnrob, 0, copsnrob, copsnrob, 0, ROT0, "Atari", "Cops'n Robbers", GAME_NO_SOUND | GAME_SUPPORTS_SAVE, layout_copsnrob )
|
||||
GAMEL( 1976, copsnrob, 0, copsnrob, copsnrob, 0, ROT0, "Atari", "Cops'n Robbers", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE, layout_copsnrob )
|
||||
|
@ -4,6 +4,9 @@
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
#include "sound/discrete.h"
|
||||
|
||||
|
||||
class copsnrob_state : public driver_device
|
||||
{
|
||||
public:
|
||||
@ -21,6 +24,7 @@ public:
|
||||
|
||||
/* misc */
|
||||
UINT8 misc;
|
||||
UINT8 ic_h3_data;
|
||||
};
|
||||
|
||||
|
||||
@ -32,3 +36,9 @@ READ8_HANDLER( copsnrob_gun_position_r );
|
||||
/*----------- defined in video/copsnrob.c -----------*/
|
||||
|
||||
VIDEO_UPDATE( copsnrob );
|
||||
|
||||
|
||||
/*----------- defined in audio/copsnrob.c -----------*/
|
||||
|
||||
DISCRETE_SOUND_EXTERN( copsnrob );
|
||||
WRITE8_HANDLER( copsnrob_misc_w );
|
||||
|
@ -1,61 +0,0 @@
|
||||
/***************************************************************************
|
||||
|
||||
Atari Cops'n Robbers hardware
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "includes/copsnrob.h"
|
||||
|
||||
static const int gun_mask[] = {0x7e, 0x7d, 0x7b, 0x77, 0x6f, 0x5f, 0x3f};
|
||||
|
||||
// The gun control is a 7 position switch. I'm doing the following to
|
||||
// emulate it:
|
||||
//
|
||||
// I read out the current gun position via the sprite image locations,
|
||||
// and then decrement/increment it if the up/down keys are pressed.
|
||||
|
||||
READ8_HANDLER( copsnrob_gun_position_r )
|
||||
{
|
||||
copsnrob_state *state = space->machine->driver_data<copsnrob_state>();
|
||||
int keys, current_car_image, current_gun_pos = 0;
|
||||
|
||||
// Determine which player we need
|
||||
switch (offset)
|
||||
{
|
||||
default:
|
||||
case 0x00:
|
||||
current_car_image = state->carimage[0];
|
||||
keys = input_port_read(space->machine, "FAKE0");
|
||||
break;
|
||||
case 0x04:
|
||||
current_car_image = state->carimage[1];
|
||||
keys = input_port_read(space->machine, "FAKE1");
|
||||
break;
|
||||
case 0x08:
|
||||
current_car_image = state->carimage[2];
|
||||
keys = input_port_read(space->machine, "FAKE2");
|
||||
break;
|
||||
case 0x0c:
|
||||
current_car_image = state->carimage[3];
|
||||
keys = input_port_read(space->machine, "FAKE3");
|
||||
break;
|
||||
}
|
||||
|
||||
if (current_car_image < 7)
|
||||
{
|
||||
current_gun_pos = 6 - current_car_image;
|
||||
}
|
||||
else if (current_car_image < 14)
|
||||
{
|
||||
current_gun_pos = 13 - current_car_image;
|
||||
}
|
||||
|
||||
// Gun up
|
||||
if ((keys & 0x01) && (current_gun_pos != 6)) current_gun_pos++;
|
||||
|
||||
// Gun down
|
||||
if ((keys & 0x02) && (current_gun_pos != 0)) current_gun_pos--;
|
||||
|
||||
return (keys & 0x80) | gun_mask[current_gun_pos];
|
||||
}
|
@ -411,7 +411,7 @@ $(MAMEOBJ)/atari.a: \
|
||||
$(DRIVERS)/cloud9.o $(VIDEO)/cloud9.o \
|
||||
$(DRIVERS)/cmmb.o \
|
||||
$(DRIVERS)/cojag.o $(AUDIO)/jaguar.o $(VIDEO)/jaguar.o \
|
||||
$(DRIVERS)/copsnrob.o $(MACHINE)/copsnrob.o $(VIDEO)/copsnrob.o \
|
||||
$(DRIVERS)/copsnrob.o $(AUDIO)/copsnrob.o $(VIDEO)/copsnrob.o \
|
||||
$(DRIVERS)/cyberbal.o $(AUDIO)/cyberbal.o $(VIDEO)/cyberbal.o \
|
||||
$(DRIVERS)/destroyr.o \
|
||||
$(DRIVERS)/dragrace.o $(AUDIO)/dragrace.o $(VIDEO)/dragrace.o \
|
||||
|
Loading…
Reference in New Issue
Block a user