diff options
author | Derrick Renaud <derrickr@mamedev.org> | 2009-09-21 23:20:32 +0000 |
---|---|---|
committer | Derrick Renaud <derrickr@mamedev.org> | 2009-09-21 23:20:32 +0000 |
commit | ecffbf4c3b59ccc50edb735e9ab78b3c7351ab7a (patch) | |
tree | 37602d8114d148c401322ef5a458d1a06a80d627 | |
parent | 1031a08ed85f6694a2e656d55e41be56e13e8255 (diff) |
Discrete Updates:
Added DISCRETE_LOGIC_SHIFT - generic shift register
Fixed DISCRETE_BIT_DECODE to apply proper voltage instead of clipping to INT.
Sky Raider - Partial discrete sound
-rw-r--r-- | .gitattributes | 2 | ||||
-rw-r--r-- | src/emu/sound/disc_mth.c | 119 | ||||
-rw-r--r-- | src/emu/sound/disc_wav.c | 2 | ||||
-rw-r--r-- | src/emu/sound/discrete.c | 3 | ||||
-rw-r--r-- | src/emu/sound/discrete.h | 44 | ||||
-rw-r--r-- | src/mame/audio/skyraid.c | 427 | ||||
-rw-r--r-- | src/mame/drivers/skyraid.c | 23 | ||||
-rw-r--r-- | src/mame/includes/skyraid.h | 8 | ||||
-rw-r--r-- | src/mame/mame.mak | 2 |
9 files changed, 605 insertions, 25 deletions
diff --git a/.gitattributes b/.gitattributes index 6f46d96887d..7e15b05779d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1207,6 +1207,7 @@ src/mame/audio/seibu.c svneol=native#text/plain src/mame/audio/seibu.h svneol=native#text/plain src/mame/audio/senjyo.c svneol=native#text/plain src/mame/audio/skydiver.c svneol=native#text/plain +src/mame/audio/skyraid.c svneol=native#text/plain src/mame/audio/snes.c svneol=native#text/plain src/mame/audio/snk6502.c svneol=native#text/plain src/mame/audio/spacefb.c svneol=native#text/plain @@ -2533,6 +2534,7 @@ src/mame/includes/shuuz.h svneol=native#text/plain src/mame/includes/simpsons.h svneol=native#text/plain src/mame/includes/skullxbo.h svneol=native#text/plain src/mame/includes/skydiver.h svneol=native#text/plain +src/mame/includes/skyraid.h svneol=native#text/plain src/mame/includes/slapfght.h svneol=native#text/plain src/mame/includes/slapstic.h svneol=native#text/plain src/mame/includes/snes.h svneol=native#text/plain diff --git a/src/emu/sound/disc_mth.c b/src/emu/sound/disc_mth.c index 5e8a40c140f..18b8311eb3b 100644 --- a/src/emu/sound/disc_mth.c +++ b/src/emu/sound/disc_mth.c @@ -10,6 +10,7 @@ ************************************************************************ * * DST_ADDDER - Multichannel adder + * DST_BITS_DECODE - Decode Bits from input node * DST_CLAMP - Simple signal clamping circuit * DST_COMP_ADDER - Selectable parallel component circuit * DST_DAC_R1 - R1 Ladder DAC with cap filtering @@ -26,6 +27,7 @@ * DST_LOGIC_NXOR - Logic NXOR gate 2 input * DST_LOGIC_DFF - Logic D-type flip/flop * DST_LOGIC_JKFF - Logic JK-type flip/flop + * DST_LOGIC_SHIFT - Logic Shift Register * DST_LOOKUP_TABLE - Return value from lookup table * DST_MIXER - Final Mixer Stage * DST_MULTIPLEX - 1 of x Multiplexer/switch @@ -53,7 +55,6 @@ struct dst_bits_decode_context int from; int count; int last_val; - int v_out; }; struct dst_dac_r1_context @@ -123,6 +124,17 @@ struct dst_samphold_context int clocktype; }; +struct dst_shift_context +{ + double t_left; /* time unused during last sample in seconds */ + UINT32 shift_data; + UINT32 bit_mask; + UINT8 clock_type; + UINT8 reset_on_high; + UINT8 shift_r; + UINT8 last; +}; + struct dst_size_context { int size; @@ -681,7 +693,7 @@ static DISCRETE_STEP(dst_bits_decode) { context->last_val = v; for (i = 0; i < context->count; i++ ) - node->output[i] = ((v >> (i+context->from)) & 1) * context->v_out; + node->output[i] = ((v >> (i+context->from)) & 1) * DST_BITS_DECODE__VOUT; } } @@ -691,7 +703,6 @@ static DISCRETE_RESET(dst_bits_decode) context->from = DST_BITS_DECODE__FROM; context->count = DST_BITS_DECODE__TO - context->from + 1; - context->v_out = DST_BITS_DECODE__VOUT; DISCRETE_STEP_CALL(dst_bits_decode); } @@ -901,6 +912,108 @@ static DISCRETE_STEP(dst_logic_jkff) /************************************************************************ * + * DST_LOGIC_SHIFT - Shift Register implementation + * + ************************************************************************/ +#define DST_LOGIC_SHIFT__IN DISCRETE_INPUT(0) +#define DST_LOGIC_SHIFT__RESET DISCRETE_INPUT(1) +#define DST_LOGIC_SHIFT__CLK DISCRETE_INPUT(2) +#define DST_LOGIC_SHIFT__SIZE DISCRETE_INPUT(3) +#define DST_LOGIC_SHIFT__OPTIONS DISCRETE_INPUT(4) + +static DISCRETE_STEP(dst_logic_shift) +{ + struct dst_shift_context *context = (struct dst_shift_context *)node->context; + + double cycles; + double ds_clock; + int clock = 0, inc = 0; + + int input_bit = (DST_LOGIC_SHIFT__IN != 0) ? 1 : 0; + ds_clock = DST_LOGIC_SHIFT__CLK; + if (context->clock_type == DISC_CLK_IS_FREQ) + { + /* We need to keep clocking the internal clock even if in reset. */ + cycles = (context->t_left + node->info->sample_time) * ds_clock; + inc = (int)cycles; + context->t_left = (cycles - inc) / ds_clock; + } + else + { + clock = (int)ds_clock; + } + + /* If reset enabled then set output to the reset value. No x_time in reset. */ + if(((DST_LOGIC_SHIFT__RESET == 0) ? 0 : 1) == context->reset_on_high) + { + context->shift_data = 0; + node->output[0] = 0; + return; + } + + /* increment clock */ + switch (context->clock_type) + { + case DISC_CLK_ON_F_EDGE: + case DISC_CLK_ON_R_EDGE: + /* See if the clock has toggled to the proper edge */ + clock = (clock != 0); + if (context->last != clock) + { + context->last = clock; + if (context->clock_type == clock) + { + /* Toggled */ + inc = 1; + } + } + break; + + case DISC_CLK_BY_COUNT: + /* Clock number of times specified. */ + inc = clock; + break; + } + + if (inc > 0) + { + if (context->shift_r) + { + context->shift_data >>= 1; + context->shift_data |= input_bit << ((int)DST_LOGIC_SHIFT__SIZE - 1); + inc--; + context->shift_data >>= inc; + } + else + { + context->shift_data <<= 1; + context->shift_data |= input_bit; + inc--; + context->shift_data <<= inc; + } + context->shift_data &= context->bit_mask; + } + + node->output[0] = context->shift_data; +} + +static DISCRETE_RESET(dst_logic_shift) +{ + struct dst_shift_context *context = (struct dst_shift_context *)node->context; + + context->bit_mask = (1 << (int)DST_LOGIC_SHIFT__SIZE) - 1; + context->clock_type = (int)DST_LOGIC_SHIFT__OPTIONS & DISC_CLK_MASK; + context->reset_on_high = ((int)DST_LOGIC_SHIFT__OPTIONS & DISC_LOGIC_SHIFT__RESET_H) ? 1 : 0; + context->shift_r = ((int)DST_LOGIC_SHIFT__OPTIONS & DISC_LOGIC_SHIFT__RIGHT) ? 1 : 0; + + context->t_left = 0; + context->last = 0; + context->shift_data = 0; + node->output[0] = 0; +} + +/************************************************************************ + * * DST_LOOKUP_TABLE - Return value from lookup table * * input[0] - Input 1 diff --git a/src/emu/sound/disc_wav.c b/src/emu/sound/disc_wav.c index 2caa854203b..d43e37a6085 100644 --- a/src/emu/sound/disc_wav.c +++ b/src/emu/sound/disc_wav.c @@ -407,7 +407,7 @@ static DISCRETE_STEP(dss_lfsr) } /* Reset everything if necessary */ - if((DSS_LFSR_NOISE__RESET ? 1 : 0) == context->reset_on_high) + if(((DSS_LFSR_NOISE__RESET == 0) ? 0 : 1) == context->reset_on_high) { DISCRETE_RESET_CALL(dss_lfsr); return; diff --git a/src/emu/sound/discrete.c b/src/emu/sound/discrete.c index 2e0d078e28c..ef0a09b7d48 100644 --- a/src/emu/sound/discrete.c +++ b/src/emu/sound/discrete.c @@ -19,7 +19,7 @@ * file. All discrete sound primatives MUST implement the following * API: * - * dsX_NAME_step(inputs, context,float timestep) - Perform time step + * dsX_NAME_step(inputs, context, float timestep) - Perform time step * return output value * dsX_NAME_reset(context) - Reset to initial state * @@ -231,6 +231,7 @@ static const discrete_module module_list[] = { DST_LOGIC_NXOR ,"DST_LOGIC_NXOR" , 1 ,0 ,NULL ,dst_logic_nxor_step ,NULL ,NULL }, { DST_LOGIC_DFF ,"DST_LOGIC_DFF" , 1 ,sizeof(struct dst_flipflop_context) ,dst_logic_ff_reset ,dst_logic_dff_step ,NULL ,NULL }, { DST_LOGIC_JKFF ,"DST_LOGIC_JKFF" , 1 ,sizeof(struct dst_flipflop_context) ,dst_logic_ff_reset ,dst_logic_jkff_step ,NULL ,NULL }, + { DST_LOGIC_SHIFT ,"DST_LOGIC_SHIFT" , 1 ,sizeof(struct dst_shift_context) ,dst_logic_shift_reset ,dst_logic_shift_step ,NULL ,NULL }, { DST_LOOKUP_TABLE,"DST_LOOKUP_TABLE", 1 ,0 ,NULL ,dst_lookup_table_step,NULL ,NULL }, { DST_MULTIPLEX ,"DST_MULTIPLEX" , 1 ,sizeof(struct dst_size_context) ,dst_multiplex_reset ,dst_multiplex_step ,NULL ,NULL }, { DST_ONESHOT ,"DST_ONESHOT" , 1 ,sizeof(struct dst_oneshot_context) ,dst_oneshot_reset ,dst_oneshot_step ,NULL ,NULL }, diff --git a/src/emu/sound/discrete.h b/src/emu/sound/discrete.h index 8c1ed99c8dc..23d6668c699 100644 --- a/src/emu/sound/discrete.h +++ b/src/emu/sound/discrete.h @@ -275,6 +275,7 @@ * DISCRETE_LOGIC_NXOR(NODE,INP0,INP1) * DISCRETE_LOGIC_DFLIPFLOP(NODE,RESET,SET,CLK,INP) * DISCRETE_LOGIC_JKFLIPFLOP(NODE,RESET,SET,CLK,J,K) + * DISCRETE_LOGIC_SHIFT(NODE,INP0,RESET,CLK,SIZE,OPTIONS) * DISCRETE_MULTIPLEX2(NODE,ADDR,INP0,INP1) * DISCRETE_MULTIPLEX4(NODE,ADDR,INP0,INP1,INP2,INP3) * DISCRETE_MULTIPLEX8(NODE,ADDR,INP0,INP1,INP2,INP3,INP4,INP5,INP6,INP7) @@ -1286,7 +1287,7 @@ * *********************************************************************** * - * DISCRETE_LOGIC_INVERT - Logic invertor + * DISCRETE_LOGIC_INVERT - Logic invertor * DISCRETE_LOGIC_AND - Logic AND gate (3 & 4 input also available) * DISCRETE_LOGIC_NAND - Logic NAND gate (3 & 4 input also available) * DISCRETE_LOGIC_OR - Logic OR gate (3 & 4 input also available) @@ -1309,7 +1310,7 @@ * Declaration syntax * * DISCRETE_LOGIC_XXXn(name of node, - * (X=INV/AND/etc) + * (X=INV/AND/etc) * (n=Blank/2/3) input0 node or static value, * [input1 node or static value], * [input2 node or static value], @@ -1432,6 +1433,31 @@ * *********************************************************************** * + * DISCRETE_LOGIC_SHIFT - shift register + * + * Declaration syntax + * + * DISCRETE_LOGIC_SHIFT(name of node, + * input node, + * reset node or static value, + * clock node or static value, + * size static value, + * options static value) + * + * Options: + * reset type: DISC_LOGIC_SHIFT__RESET_L + * DISC_LOGIC_SHIFT__RESET_H + * shift type: DISC_LOGIC_SHIFT__LEFT + * DISC_LOGIC_SHIFT__RIGHT + * clock type: DISC_CLK_ON_F_EDGE - toggle on falling edge. + * DISC_CLK_ON_R_EDGE - toggle on rising edge. + * DISC_CLK_BY_COUNT - toggle specified number of times. + * DISC_CLK_IS_FREQ - internally clock at this frequency. + * + * EXAMPLES: see Sky Raider + * + *********************************************************************** + * * DISCRETE_GAIN - Node multiplication function output is equal * DISCRETE_MULTIPLY to INPUT0 * INPUT1 * DISCRETE_MULTADD to (INPUT0 * INPUT1) + INPUT 2 @@ -3236,7 +3262,7 @@ * if you have used DISCRETE_STEP(basename) and DISCRETE_RESET(basename) to define * the step/reset procedures. * - * EXAMPLES: see Donkey Kong, Mario Bros. + * EXAMPLES: see Donkey Kong, Mario Bros., Sky Raider * *********************************************************************** ======================================================================= @@ -3406,7 +3432,7 @@ #define DISC_COUNT_DOWN 0 #define DISC_COUNT_UP 1 - + #define DISC_COUNTER_IS_7492 0x08 #define DISC_OUT_MASK 0x30 @@ -3443,6 +3469,12 @@ #define DISC_SAMPHOLD_HLATCH 2 #define DISC_SAMPHOLD_LLATCH 3 +/* Shift options */ +#define DISC_LOGIC_SHIFT__RESET_L 0x00 +#define DISC_LOGIC_SHIFT__RESET_H 0x10 +#define DISC_LOGIC_SHIFT__LEFT 0x00 +#define DISC_LOGIC_SHIFT__RIGHT 0x20 + /* Maximum number of resistors in ladder chain */ #define DISC_LADDER_MAXRES 8 @@ -3548,7 +3580,7 @@ enum /* 566 output flags */ #define DISC_566_OUT_DC 0x00 #define DISC_566_OUT_AC 0x01 - + #define DISC_566_OUT_SQUARE 0x00 /* Squarewave */ #define DISC_566_OUT_TRIANGLE 0x10 /* Triangle waveform */ #define DISC_566_OUT_LOGIC 0x20 /* 0/1 logic output */ @@ -4149,6 +4181,7 @@ enum DST_LOGIC_NXOR, DST_LOGIC_DFF, DST_LOGIC_JKFF, + DST_LOGIC_SHIFT, DST_LOOKUP_TABLE, /* return value from lookup table */ DST_MULTIPLEX, /* 1 of x multiplexer */ DST_ONESHOT, /* One-shot pulse generator */ @@ -4309,6 +4342,7 @@ enum #define DISCRETE_LOGIC_NXOR(NODE,INP0,INP1) { NODE, DST_LOGIC_NXOR , 2, { INP0,INP1 }, { INP0,INP1 }, NULL, "DISCRETE_LOGIC_NXOR" }, #define DISCRETE_LOGIC_DFLIPFLOP(NODE,RESET,SET,CLK,INP) { NODE, DST_LOGIC_DFF , 4, { RESET,SET,CLK,INP }, { RESET,SET,CLK,INP }, NULL, "DISCRETE_LOGIC_DFLIPFLOP" }, #define DISCRETE_LOGIC_JKFLIPFLOP(NODE,RESET,SET,CLK,J,K) { NODE, DST_LOGIC_JKFF , 5, { RESET,SET,CLK,J,K }, { RESET,SET,CLK,J,K }, NULL, "DISCRETE_LOGIC_JKFLIPFLOP" }, +#define DISCRETE_LOGIC_SHIFT(NODE,INP0,RESET,CLK,SIZE,OPTIONS) { NODE, DST_LOGIC_SHIFT , 5, { INP0,RESET,CLK,NODE_NC,NODE_NC }, { INP0,RESET,CLK,SIZE,OPTIONS }, NULL, "DISCRETE_LOGIC_SHIFT" }, #define DISCRETE_LOOKUP_TABLE(NODE,ADDR,SIZE,TABLE) { NODE, DST_LOOKUP_TABLE, 2, { ADDR,NODE_NC }, { ADDR,SIZE }, TABLE, "DISCRETE_LOOKUP_TABLE" }, #define DISCRETE_MULTIPLEX2(NODE,ADDR,INP0,INP1) { NODE, DST_MULTIPLEX , 3, { ADDR,INP0,INP1 }, { ADDR,INP0,INP1 }, NULL, "DISCRETE_MULTIPLEX2" }, #define DISCRETE_MULTIPLEX4(NODE,ADDR,INP0,INP1,INP2,INP3) { NODE, DST_MULTIPLEX , 5, { ADDR,INP0,INP1,INP2,INP3 }, { ADDR,INP0,INP1,INP2,INP3 }, NULL, "DISCRETE_MULTIPLEX4" }, diff --git a/src/mame/audio/skyraid.c b/src/mame/audio/skyraid.c new file mode 100644 index 00000000000..0f22ec8011a --- /dev/null +++ b/src/mame/audio/skyraid.c @@ -0,0 +1,427 @@ +/************************************************************************ + * skyraid Sound System Analog emulation + * Sept 2009, Derrick Renaud + ************************************************************************/ + +#include "driver.h" +#include "skyraid.h" + + +/* Discrete Sound Input Nodes */ +#define SKYRAID_PLANE_SWEEP_EN NODE_01 +#define SKYRAID_MISSILE_EN NODE_02 +#define SKYRAID_EXPLOSION_EN NODE_03 +#define SKYRAID_PLANE_ON_EN NODE_04 +#define SKYRAID_PLANE_ON__IC_E8 SKYRAID_PLANE_ON_EN +#define SKYRAID_ATTRACT_EN NODE_05 + +/* Discrete Sound Output Nodes */ +#define SKYRAID_NOISE NODE_10 +#define SKYRAID_EXPLOSION_SND NODE_11 +#define SKYRAID_JET_A_SND NODE_12 +#define SKYRAID_JET_B_SND NODE_13 +#define SKYRAID_MSL_A_SND NODE_14 +#define SKYRAID_MSL_B_SND NODE_15 +#define SKYRAID_PLANE_SND NODE_16 + +/* Parts List - Resistors */ +#define SKYRAID_R12 RES_K(1) +#define SKYRAID_R13 RES_K(10) +#define SKYRAID_R14 RES_K(100) +#define SKYRAID_R16 RES_M(10) +#define SKYRAID_R18 RES_K(10) +#define SKYRAID_R19 RES_K(10) +#define SKYRAID_R20 RES_K(47) +#define SKYRAID_R24 RES_M(10) +#define SKYRAID_R25 RES_M(3.9) +#define SKYRAID_R27 RES_M(1.5) +#define SKYRAID_R28 RES_M(1.5) +#define SKYRAID_R29 RES_M(4.7) +#define SKYRAID_R30 RES_M(1) +#define SKYRAID_R31 RES_M(1) +#define SKYRAID_R32 RES_M(4.7) +#define SKYRAID_R84 RES_K(22) +#define SKYRAID_R85 RES_K(100) +#define SKYRAID_R86 820 +#define SKYRAID_R110 RES_K(330) +#define SKYRAID_R118 RES_K(470) +#define SKYRAID_R119 RES_K(10) +#define SKYRAID_R120 RES_K(220) +#define SKYRAID_R121 RES_K(1) +#define SKYRAID_R122 RES_K(150) + +/* Parts List - Capacitors */ +#define SKYRAID_C44 CAP_U(4.7) +#define SKYRAID_C45 CAP_U(.0047) +#define SKYRAID_C46 CAP_U(.001) +#define SKYRAID_C48 CAP_U(.0047) +#define SKYRAID_C49 CAP_U(.1) +#define SKYRAID_C50 CAP_U(.001) +#define SKYRAID_C51 CAP_U(.01) +#define SKYRAID_C68 CAP_U(10) +#define SKYRAID_C85 CAP_U(.068) +#define SKYRAID_C86 CAP_U(.1) +#define SKYRAID_C93 CAP_U(.1) + + +static const discrete_lfsr_desc skyraid_lfsr = +{ + DISC_CLK_IS_FREQ, + 16, /* Bit Length */ + 0, /* Reset Value */ + 0, /* Use Bit 0 as XOR input 0 */ + 14, /* Use Bit 14 as XOR input 1 */ + DISC_LFSR_XNOR, /* Feedback stage1 is XNOR */ + DISC_LFSR_OR, /* Feedback stage2 is just stage 1 output OR with external feed */ + DISC_LFSR_REPLACE, /* Feedback stage3 replaces the shifted register contents */ + 0x000001, /* Everything is shifted into the first bit only */ + DISC_LFSR_FLAG_RESET_TYPE_H, /* Output is not inverted */ + 15 /* Output bit */ +}; + +static const discrete_op_amp_filt_info skyraid_explosion_filter = +{ + SKYRAID_R85, 0, SKYRAID_R86, 0, SKYRAID_R110, /* r1, r2, r3, r4, rF*/ + SKYRAID_C85, SKYRAID_C86, 0, /* c1, c2, c3 */ + 0, 12, -5, /* vRef, vP, vN */ +}; + +static const discrete_566_desc skyraid_566_desc = +{ + DISC_566_OUT_LOGIC, + 5, /* v_pos */ + -5, /* v_neg */ + 5 /* v_charge */ +}; + +static const discrete_dac_r1_ladder skyraid_plane_dac = +{ + 2, {SKYRAID_R28, SKYRAID_R27}, + 0, 0, 0, 0 /* no vBias, rBias, rGnd, cFilter */ +}; + +static const discrete_mixer_desc skyraid_mixer = +{ + DISC_MIXER_IS_RESISTOR, + {SKYRAID_R120, SKYRAID_R32, SKYRAID_R29, SKYRAID_R30, SKYRAID_R31, RES_2_PARALLEL(SKYRAID_R28, SKYRAID_R27)}, + {0, 0, 0, 0, 0, SKYRAID_PLANE_ON__IC_E8}, /* r_nodes */ + {0}, 0, 0, 0, 0, 0, 1 /* no c, rI, rF, cF, cAmp, vRef, gain */ +}; + + +/************************************************************************ + * + * Custom skyraid explosion charge + * + * input[0] - In1 (Logic) + * input[1] - In2 (Logic) + * input[2] - R + * input[3] - C + * + * 5V + * v + * | + * .-------. + * | 4066 | + * In1 >---|c | + * '-------' + * | + * +------------. + * | | + * .-------. --- C + * | 4066 | --- + * In2 >---|c | | + * '-------' gnd + * | + * +----> Node Output + * | + * Z + * Z R + * Z + * | + * gnd + * + ************************************************************************/ +#define SKYRAID_EXPLOSION_CUSTOM_IN1 DISCRETE_INPUT(0) +#define SKYRAID_EXPLOSION_CUSTOM_IN2 DISCRETE_INPUT(1) +#define SKYRAID_EXPLOSION_CUSTOM_R DISCRETE_INPUT(2) +#define SKYRAID_EXPLOSION_CUSTOM_C DISCRETE_INPUT(3) + +#define SKYRAID_4066_R_ON 270 + +static struct skyraid_explosion_custom_charge_context +{ + double v_cap; + double v_charge_1_2; + double v_drop; + double exp_1; + double exp_1_2; + double exp_2; +}; + +static DISCRETE_STEP( skyraid_explosion_custom_charge ) +{ + struct skyraid_explosion_custom_charge_context *context = (struct skyraid_explosion_custom_charge_context *)node->context; + + if (SKYRAID_EXPLOSION_CUSTOM_IN1 == 0) + if (SKYRAID_EXPLOSION_CUSTOM_IN2 == 0) + /* cap is floating and does not change charge */ + /* output is pulled to ground */ + node->output[0] = 0; + else + { + /* cap is discharged */ + context->v_cap -= context->v_cap * context->exp_2; + node->output[0] = context->v_cap * context->v_drop; + } + else + if (SKYRAID_EXPLOSION_CUSTOM_IN2 == 0) + { + /* cap is charged */ + context->v_cap += (5.0 - context->v_cap) * context->exp_1; + /* output is pulled to ground */ + node->output[0] = 0; + } + else + { + /* cap is charged slightly less */ + context->v_cap += (context->v_charge_1_2 - context->v_cap) * context->exp_1_2; + node->output[0] = context->v_cap * context->v_drop; + } +} + +static DISCRETE_RESET( skyraid_explosion_custom_charge ) +{ + struct skyraid_explosion_custom_charge_context *context = (struct skyraid_explosion_custom_charge_context *)node->context; + + /* the charging voltage across the cap based on in2*/ + context->v_drop = RES_VOLTAGE_DIVIDER(SKYRAID_4066_R_ON, SKYRAID_4066_R_ON + SKYRAID_EXPLOSION_CUSTOM_R); + context->v_charge_1_2 = 5.0 * context->v_drop; + context->v_cap = 0; + + /* precalculate charging exponents */ + /* discharge cap - in1 = 0, in2 = 1*/ + context->exp_2 = RC_CHARGE_EXP((SKYRAID_4066_R_ON + SKYRAID_EXPLOSION_CUSTOM_R) * SKYRAID_EXPLOSION_CUSTOM_C); + /* charge cap - in1 = 1, in2 = 0 */ + context->exp_1 = RC_CHARGE_EXP(SKYRAID_4066_R_ON * SKYRAID_EXPLOSION_CUSTOM_C); + /* charge cap - in1 = 1, in2 = 1 */ + context->exp_1_2 = RC_CHARGE_EXP(RES_2_PARALLEL(SKYRAID_4066_R_ON, SKYRAID_4066_R_ON + SKYRAID_EXPLOSION_CUSTOM_R) * SKYRAID_EXPLOSION_CUSTOM_C); + + /* starts at 0 until cap starts charging */ + node->output[0] = 0; +} + +static const discrete_custom_info skyraid_explosion_custom_charge = +{ + DISCRETE_CUSTOM_MODULE(skyraid_explosion_custom_charge, struct skyraid_explosion_custom_charge_context), + NULL +}; + + +/************************************************************************ + * + * Custom skyraid missle charge + * + * input[0] - In1 (Logic) + * input[1] - R1 + * input[2] - R2 + * input[3] - R3 + * input[4] - C + * + * 12V 5V + * v v + * | | + * Z --- + * Z R1 ^ 1N914 + * Z / \ Diode + * | ----- + * | | + * +--------------+ + * | | + * --- Z + * --- C Z R2 + * | Z + * | | + * +--------------+----> Node Output + * | + * Z + * Z R3 + * O.C. Z + * |\ | + * In1 >--| o--+ + * |/ + * + ************************************************************************/ +#define SKYRAID_MISSLE_CUSTOM_IN1 DISCRETE_INPUT(0) +#define SKYRAID_MISSLE_CUSTOM_R1 DISCRETE_INPUT(1) +#define SKYRAID_MISSLE_CUSTOM_R2 DISCRETE_INPUT(2) +#define SKYRAID_MISSLE_CUSTOM_R3 DISCRETE_INPUT(3) +#define SKYRAID_MISSLE_CUSTOM_C DISCRETE_INPUT(4) + +static struct skyraid_missle_custom_charge_context +{ + double v_charge[2]; + double v_cap; + double exp[2]; +}; + +/* the high charge is clamped by the diode to 0.7V above the 5V line */ +#define SKYRAID_MISSLE_CHARGE_PLUS (5.0 + 0.7) + +static DISCRETE_STEP( skyraid_missle_custom_charge ) +{ + struct skyraid_missle_custom_charge_context *context = (struct skyraid_missle_custom_charge_context *)node->context; + + int in_1 = (SKYRAID_MISSLE_CUSTOM_IN1 == 0) ? 0 : 1; + + /* charge/discharge cap */ + context->v_cap += (context->v_charge[in_1] - context->v_cap) * context->exp[in_1]; + + node->output[0] = SKYRAID_MISSLE_CHARGE_PLUS - context->v_cap; +} + +static DISCRETE_RESET( skyraid_missle_custom_charge ) +{ + struct skyraid_missle_custom_charge_context *context = (struct skyraid_missle_custom_charge_context *)node->context; + + /* everything is based on the input to the O.C. inverter */ + + /* the charging voltage across the cap */ + context->v_charge[0] = 0; + context->v_charge[1] = SKYRAID_MISSLE_CHARGE_PLUS * RES_VOLTAGE_DIVIDER(SKYRAID_MISSLE_CUSTOM_R1 + SKYRAID_MISSLE_CUSTOM_R2, SKYRAID_MISSLE_CUSTOM_R3); + context->v_charge[1] = SKYRAID_MISSLE_CHARGE_PLUS - context->v_charge[1]; + context->v_cap = 0; + + /* precalculate charging exponents */ + /* discharge cap */ + context->exp[0] = RC_CHARGE_EXP(SKYRAID_MISSLE_CUSTOM_R2 * SKYRAID_MISSLE_CUSTOM_C); + /* charge cap */ + context->exp[1] = RC_CHARGE_EXP(RES_2_PARALLEL(SKYRAID_MISSLE_CUSTOM_R1 + SKYRAID_MISSLE_CUSTOM_R2, SKYRAID_MISSLE_CUSTOM_R3) * SKYRAID_MISSLE_CUSTOM_C); + + /* starts at full voltage until cap starts charging */ + node->output[0] = SKYRAID_MISSLE_CHARGE_PLUS; +} + +static const discrete_custom_info skyraid_missle_custom_charge = +{ + DISCRETE_CUSTOM_MODULE( skyraid_missle_custom_charge, struct skyraid_missle_custom_charge_context), + NULL +}; + + +DISCRETE_SOUND_START( skyraid ) + /************************************************ + * Input register mapping + ************************************************/ + /* convert the PLANE_SWEEP line to voltage*/ + DISCRETE_INPUTX_LOGIC(SKYRAID_PLANE_SWEEP_EN, DEFAULT_TTL_V_LOGIC_1 * RES_VOLTAGE_DIVIDER(SKYRAID_R25, SKYRAID_R24), 0, 0) + DISCRETE_INPUT_LOGIC(SKYRAID_MISSILE_EN) + DISCRETE_INPUT_LOGIC(SKYRAID_EXPLOSION_EN) + /* convert PLANE_ON into 4066 Ron value of 270 ohms @ 5V */ + DISCRETE_INPUTX_LOGIC(SKYRAID_PLANE_ON__IC_E8, 270, 0, 0) + DISCRETE_INPUT_LOGIC(SKYRAID_ATTRACT_EN) + + /************************************************ + * Noise Generator, Explosion sound + ************************************************/ + /* Note: the noise reset is not emulated 100% accurate */ + /* According to the schematics, Attract only clears the lower 8 bits. */ + /* I may modify the noise module in the future to properly emulate this, */ + /* but you will never hear the difference. */ + /* It only wrong for 8 cycles of the 555 while no sound is being generated. */ + DISCRETE_LFSR_NOISE(SKYRAID_NOISE, /* IC F7, pin 13 */ + 1, /* ENAB */ + SKYRAID_ATTRACT_EN, /* RESET */ + 1.49 / ((SKYRAID_R20 + 2 * SKYRAID_R19) * SKYRAID_C51), /* CLK - 555 astable source */ + 1, 0, 0.5, &skyraid_lfsr) /* AMPL,FEED,BIAS,LFSRTB */ + + DISCRETE_LOGIC_NOR(NODE_20, SKYRAID_EXPLOSION_EN, SKYRAID_NOISE) + DISCRETE_CUSTOM4(NODE_21, SKYRAID_EXPLOSION_EN, NODE_20, RES_2_PARALLEL(SKYRAID_R84, SKYRAID_R85 + SKYRAID_R86), SKYRAID_C68, &skyraid_explosion_custom_charge) + DISCRETE_OP_AMP_FILTER(NODE_22, + 1, /* ENAB */ + NODE_21, 0, /* INP0,INP1 */ + DISC_OP_AMP_FILTER_IS_BAND_PASS_1M, &skyraid_explosion_filter) /* TYPE,INFO */ + /* IC E10, pin 14 gain and clipping */ + DISCRETE_GAIN(NODE_23, NODE_22, SKYRAID_R119 / SKYRAID_R121 + 1) + DISCRETE_CLAMP(SKYRAID_EXPLOSION_SND, 1, NODE_23, -5, 12.0 - 1.5, 0) + + /************************************************ + * Jet, Plane sound + ************************************************/ + DISCRETE_RCFILTER(NODE_30, /* IC J6, pin 5 */ + 1, /* ENAB */ + SKYRAID_PLANE_SWEEP_EN, /* IN0 */ + RES_2_PARALLEL(SKYRAID_R25, SKYRAID_R24), SKYRAID_C49) + DISCRETE_566(NODE_31, /* IC J6, pin 3 */ + 1, /* ENAB */ + NODE_30, /* VMOD */ + SKYRAID_R18, SKYRAID_C48, &skyraid_566_desc) + DISCRETE_LOGIC_SHIFT(NODE_32, /* IC H7, J7 output */ + SKYRAID_NOISE, /* IC H7, J7 pins 1 & 2 */ + 1, NODE_31, 16, /* RESET, CLK, SIZE */ + DISC_LOGIC_SHIFT__RESET_L | DISC_LOGIC_SHIFT__LEFT | DISC_CLK_ON_R_EDGE) + /* move bits together for ease of use */ + DISCRETE_TRANSFORM4(NODE_33, NODE_32, 1, 1 << 14, 2, "01&02/3&|") + DISCRETE_DAC_R1(SKYRAID_PLANE_SND, + 1, /* ENAB */ + NODE_33, /* DATA */ + DEFAULT_TTL_V_LOGIC_1, &skyraid_plane_dac) + DISCRETE_BIT_DECODE(SKYRAID_JET_A_SND, NODE_32, 0, DEFAULT_TTL_V_LOGIC_1) /* IC H7, pin 3 */ + DISCRETE_BIT_DECODE(SKYRAID_JET_B_SND, NODE_32, 15, DEFAULT_TTL_V_LOGIC_1) /* IC J7, pin 13 */ + + /************************************************ + * Missle sound + ************************************************/ + DISCRETE_CUSTOM5(NODE_40, SKYRAID_MISSILE_EN, SKYRAID_R12, SKYRAID_R14, SKYRAID_R13, SKYRAID_C44, &skyraid_missle_custom_charge) + DISCRETE_566(NODE_41, /* IC K6, pin 3 */ + 1, /* ENAB */ + NODE_40, /* VMOD */ + SKYRAID_R16, SKYRAID_C45, &skyraid_566_desc) + DISCRETE_LOGIC_SHIFT(NODE_42, /* IC K7, L7 output */ + SKYRAID_NOISE, /* IC K7, L7 pins 1 & 2 */ + 1, NODE_41, 16, /* RESET, CLK, SIZE */ + DISC_LOGIC_SHIFT__RESET_L | DISC_LOGIC_SHIFT__LEFT | DISC_CLK_ON_R_EDGE) + DISCRETE_BIT_DECODE(SKYRAID_MSL_A_SND, NODE_42, 0, DEFAULT_TTL_V_LOGIC_1) /* IC K7, pin 3 */ + DISCRETE_BIT_DECODE(SKYRAID_MSL_B_SND, NODE_42, 15, DEFAULT_TTL_V_LOGIC_1) /* IC L7, pin 13 */ + + /************************************************ + * Final Mix + ************************************************/ + DISCRETE_LOGIC_INVERT(NODE_91, SKYRAID_ATTRACT_EN) + DISCRETE_MIXER6(NODE_92, + NODE_91, /* ENAB */ + SKYRAID_EXPLOSION_SND, + SKYRAID_JET_A_SND, + SKYRAID_JET_B_SND, + SKYRAID_MSL_A_SND, + SKYRAID_MSL_B_SND, + SKYRAID_PLANE_SND, + &skyraid_mixer) + DISCRETE_CRFILTER(NODE_93, + 1, /* ENAB */ + NODE_92, /* IN0 */ + SKYRAID_R122 + RES_6_PARALLEL(SKYRAID_R120, SKYRAID_R32, SKYRAID_R29, SKYRAID_R30, SKYRAID_R31, RES_2_PARALLEL(SKYRAID_R27, SKYRAID_R28)), + SKYRAID_C93) + /* IC E10, pin 1 gain and clipping */ + DISCRETE_GAIN(NODE_94, NODE_93, - SKYRAID_R118 / (SKYRAID_R122 + RES_5_PARALLEL(SKYRAID_R120, SKYRAID_R32, SKYRAID_R29, SKYRAID_R30, SKYRAID_R31))) + DISCRETE_CLAMP(NODE_95, 1, NODE_94, -5, 12.0 - 1.5, 0) + DISCRETE_OUTPUT(NODE_95, 32700.0/12) +DISCRETE_SOUND_END + + +WRITE8_DEVICE_HANDLER( skyraid_sound_w ) +{ + /* BIT0 => PLANE SWEEP */ + /* BIT1 => MISSILE */ + /* BIT2 => EXPLOSION */ + /* BIT3 => START LAMP */ + /* BIT4 => PLANE ON */ + /* BIT5 => ATTRACT */ + + discrete_sound_w(device, SKYRAID_PLANE_SWEEP_EN, data & 0x01); + discrete_sound_w(device, SKYRAID_MISSILE_EN, data & 0x02); + discrete_sound_w(device, SKYRAID_EXPLOSION_EN, data & 0x04); + set_led_status(0, !(data & 0x08)); + discrete_sound_w(device, SKYRAID_PLANE_ON_EN, data & 0x10); + discrete_sound_w(device, SKYRAID_ATTRACT_EN, data & 0x20); +} diff --git a/src/mame/drivers/skyraid.c b/src/mame/drivers/skyraid.c index 0abca95036d..c0a0fa1ebbd 100644 --- a/src/mame/drivers/skyraid.c +++ b/src/mame/drivers/skyraid.c @@ -6,6 +6,7 @@ Atari Sky Raider driver #include "driver.h" #include "cpu/m6502/m6502.h" +#include "skyraid.h" extern UINT8* skyraid_alpha_num_ram; extern UINT8* skyraid_pos_ram; @@ -56,18 +57,6 @@ static READ8_HANDLER( skyraid_port_0_r ) return val; } -static WRITE8_HANDLER( skyraid_sound_w ) -{ - /* BIT0 => PLANE SWEEP */ - /* BIT1 => MISSILE */ - /* BIT2 => EXPLOSION */ - /* BIT3 => START LAMP */ - /* BIT4 => PLANE ON */ - /* BIT5 => ATTRACT */ - - set_led_status(0, !(data & 0x08)); -} - static WRITE8_HANDLER( skyraid_range_w ) { @@ -97,7 +86,7 @@ static ADDRESS_MAP_START( skyraid_map, ADDRESS_SPACE_PROGRAM, 8 ) AM_RANGE(0x1400, 0x1401) AM_READ_PORT("SYSTEM") AM_RANGE(0x1c00, 0x1c0f) AM_WRITEONLY AM_BASE(&skyraid_obj_ram) AM_RANGE(0x4000, 0x4000) AM_WRITE(skyraid_scroll_w) - AM_RANGE(0x4400, 0x4400) AM_WRITE(skyraid_sound_w) + AM_RANGE(0x4400, 0x4400) AM_DEVWRITE("discrete", skyraid_sound_w) AM_RANGE(0x4800, 0x4800) AM_WRITE(skyraid_range_w) AM_RANGE(0x5000, 0x5000) AM_WRITE(watchdog_reset_w) AM_RANGE(0x5800, 0x5800) AM_WRITE(skyraid_offset_w) @@ -240,6 +229,7 @@ static MACHINE_DRIVER_START( skyraid ) MDRV_CPU_ADD("maincpu", M6502, 12096000 / 12) MDRV_CPU_PROGRAM_MAP(skyraid_map) MDRV_CPU_VBLANK_INT("screen", irq0_line_hold) + MDRV_WATCHDOG_VBLANK_INIT(4) /* video hardware */ MDRV_SCREEN_ADD("screen", RASTER) @@ -258,6 +248,11 @@ static MACHINE_DRIVER_START( skyraid ) MDRV_VIDEO_UPDATE(skyraid) /* sound hardware */ + MDRV_SPEAKER_STANDARD_MONO("mono") + + MDRV_SOUND_ADD("discrete", DISCRETE, 96000) + MDRV_SOUND_CONFIG_DISCRETE(skyraid) + MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0) MACHINE_DRIVER_END @@ -291,4 +286,4 @@ ROM_START( skyraid ) ROM_END -GAME( 1978, skyraid, 0, skyraid, skyraid, 0, ORIENTATION_FLIP_Y, "Atari", "Sky Raider", GAME_NO_SOUND | GAME_IMPERFECT_COLORS ) +GAME( 1978, skyraid, 0, skyraid, skyraid, 0, ORIENTATION_FLIP_Y, "Atari", "Sky Raider", GAME_IMPERFECT_SOUND | GAME_IMPERFECT_COLORS ) diff --git a/src/mame/includes/skyraid.h b/src/mame/includes/skyraid.h new file mode 100644 index 00000000000..8b44e3b6268 --- /dev/null +++ b/src/mame/includes/skyraid.h @@ -0,0 +1,8 @@ +#include "sound/discrete.h" + + +/*----------- defined in audio/norautp.c -----------*/ + +DISCRETE_SOUND_EXTERN( skyraid ); + +extern WRITE8_DEVICE_HANDLER( skyraid_sound_w ); diff --git a/src/mame/mame.mak b/src/mame/mame.mak index 3f0b9427c5d..68805fbf8eb 100644 --- a/src/mame/mame.mak +++ b/src/mame/mame.mak @@ -430,7 +430,7 @@ $(MAMEOBJ)/atari.a: \ $(DRIVERS)/shuuz.o $(VIDEO)/shuuz.o \ $(DRIVERS)/skullxbo.o $(VIDEO)/skullxbo.o \ $(DRIVERS)/skydiver.o $(AUDIO)/skydiver.o $(VIDEO)/skydiver.o \ - $(DRIVERS)/skyraid.o $(VIDEO)/skyraid.o \ + $(DRIVERS)/skyraid.o $(AUDIO)/skyraid.o $(VIDEO)/skyraid.o \ $(DRIVERS)/sprint2.o $(AUDIO)/sprint2.o $(VIDEO)/sprint2.o \ $(DRIVERS)/sprint4.o $(VIDEO)/sprint4.o $(AUDIO)/sprint4.o \ $(DRIVERS)/sprint8.o $(VIDEO)/sprint8.o \ |