1 /***************************************************************************
2
3 Atari Drag Race Driver
4
5 ***************************************************************************/
6
7 #include "driver.h"
8
9 extern VIDEO_START( dragrace );
10 extern VIDEO_UPDATE( dragrace );
11
12 extern UINT8* dragrace_playfield_ram;
13 extern UINT8* dragrace_position_ram;
14
15 static unsigned dragrace_misc_flags = 0;
16
17 static int dragrace_gear[2];
18
19
dragrace_frame_callback(int dummy)20 static void dragrace_frame_callback(int dummy)
21 {
22 int i;
23
24 for (i = 0; i < 2; i++)
25 {
26 switch (readinputport(5 + i))
27 {
28 case 0x01: dragrace_gear[i] = 1; break;
29 case 0x02: dragrace_gear[i] = 2; break;
30 case 0x04: dragrace_gear[i] = 3; break;
31 case 0x08: dragrace_gear[i] = 4; break;
32 case 0x10: dragrace_gear[i] = 0; break;
33 }
34 }
35 }
36
37
MACHINE_INIT(dragrace)38 static MACHINE_INIT( dragrace )
39 {
40 timer_pulse(cpu_getscanlinetime(0), 0, dragrace_frame_callback);
41 }
42
dragrace_update_misc_flags(void)43 static void dragrace_update_misc_flags(void)
44 {
45 /* 0x0900 = set 3SPEED1 0x00000001
46 * 0x0901 = set 4SPEED1 0x00000002
47 * 0x0902 = set 5SPEED1 0x00000004
48 * 0x0903 = set 6SPEED1 0x00000008
49 * 0x0904 = set 7SPEED1 0x00000010
50 * 0x0905 = set EXPLOSION1 0x00000020
51 * 0x0906 = set SCREECH1 0x00000040
52 * 0x0920 - 0x0927 = clear 0x0900 - 0x0907
53
54 * 0x0909 = set KLEXPL1 0x00000200
55 * 0x090b = set MOTOR1 0x00000800
56 * 0x090c = set ATTRACT 0x00001000
57 * 0x090d = set LOTONE 0x00002000
58 * 0x090f = set Player 1 Start Lamp 0x00008000
59 * 0x0928 - 0x092f = clear 0x0908 - 0x090f
60
61 * 0x0910 = set 3SPEED2 0x00010000
62 * 0x0911 = set 4SPEED2 0x00020000
63 * 0x0912 = set 5SPEED2 0x00040000
64 * 0x0913 = set 6SPEED2 0x00080000
65 * 0x0914 = set 7SPEED2 0x00100000
66 * 0x0915 = set EXPLOSION2 0x00200000
67 * 0x0916 = set SCREECH2 0x00400000
68 * 0x0930 = clear 0x0910 - 0x0917
69
70 * 0x0919 = set KLEXPL2 0x02000000
71 * 0x091b = set MOTOR2 0x08000000
72 * 0x091d = set HITONE 0x20000000
73 * 0x091f = set Player 2 Start Lamp 0x80000000
74 * 0x0938 = clear 0x0918 - 0x091f
75 */
76 set_led_status(0, dragrace_misc_flags & 0x00008000);
77 set_led_status(1, dragrace_misc_flags & 0x80000000);
78
79 discrete_sound_w(0x06, ~dragrace_misc_flags & 0x0000001f); /* Speed1 data**/
80 discrete_sound_w(0x04, (dragrace_misc_flags & 0x00000020) ? 1: 0); /* Explosion1 enable*/
81 discrete_sound_w(0x00, (dragrace_misc_flags & 0x00000040) ? 1: 0); /* Screech1 enable*/
82 discrete_sound_w(0x0a, (dragrace_misc_flags & 0x00000200) ? 1: 0); /* KLEXPL1 enable*/
83 discrete_sound_w(0x08, (dragrace_misc_flags & 0x00000800) ? 1: 0); /* Motor1 enable*/
84
85 discrete_sound_w(0x07, (~dragrace_misc_flags & 0x001f0000) >> 0x10); /* Speed2 data**/
86 discrete_sound_w(0x05, (dragrace_misc_flags & 0x00200000) ? 1: 0); /* Explosion2 enable*/
87 discrete_sound_w(0x01, (dragrace_misc_flags & 0x00400000) ? 1: 0); /* Screech2 enable*/
88 discrete_sound_w(0x0b, (dragrace_misc_flags & 0x02000000) ? 1: 0); /* KLEXPL2 enable*/
89 discrete_sound_w(0x09, (dragrace_misc_flags & 0x08000000) ? 1: 0); /* Motor2 enable*/
90
91 discrete_sound_w(0x0c, (dragrace_misc_flags & 0x00001000) ? 1: 0); /* Attract enable*/
92 discrete_sound_w(0x02, (dragrace_misc_flags & 0x00002000) ? 1: 0); /* LoTone enable*/
93 discrete_sound_w(0x03, (dragrace_misc_flags & 0x20000000) ? 1: 0); /* HiTone enable*/
94 }
95
WRITE_HANDLER(dragrace_misc_w)96 WRITE_HANDLER( dragrace_misc_w )
97 {
98 /* Set/clear individual bit */
99 UINT32 mask = 1 << offset;
100 if (data & 0x01)
101 dragrace_misc_flags |= mask;
102 else
103 dragrace_misc_flags &= (~mask);
104 log_cb(RETRO_LOG_DEBUG, LOGPRE "Set %#6x, Mask=%#10x, Flag=%#10x, Data=%x\n", 0x0900+offset, mask, dragrace_misc_flags, data & 0x01);
105 dragrace_update_misc_flags();
106 }
107
WRITE_HANDLER(dragrace_misc_clear_w)108 WRITE_HANDLER( dragrace_misc_clear_w )
109 {
110 /* Clear 8 bits */
111 UINT32 mask = 0xff << (((offset >> 3) & 0x03) * 8);
112 dragrace_misc_flags &= (~mask);
113 log_cb(RETRO_LOG_DEBUG, LOGPRE "Clear %#6x, Mask=%#10x, Flag=%#10x, Data=%x\n", 0x0920+offset, mask, dragrace_misc_flags, data & 0x01);
114 dragrace_update_misc_flags();
115 }
116
READ_HANDLER(dragrace_input_r)117 READ_HANDLER( dragrace_input_r )
118 {
119 int val = readinputport(2);
120
121 UINT8 maskA = 1 << (offset % 8);
122 UINT8 maskB = 1 << (offset / 8);
123
124 int i;
125
126 for (i = 0; i < 2; i++)
127 {
128 int in = readinputport(i);
129
130 if (dragrace_gear[i] != 0)
131 {
132 in &= ~(1 << dragrace_gear[i]);
133 }
134
135 if (in & maskA)
136 {
137 val |= 1 << i;
138 }
139 }
140
141 return (val & maskB) ? 0xFF : 0x7F;
142 }
143
144
READ_HANDLER(dragrace_steering_r)145 READ_HANDLER( dragrace_steering_r )
146 {
147 int bitA[2];
148 int bitB[2];
149
150 int i;
151
152 for (i = 0; i < 2; i++)
153 {
154 int dial = readinputport(3 + i);
155
156 bitA[i] = ((dial + 1) / 2) & 1;
157 bitB[i] = ((dial + 0) / 2) & 1;
158 }
159
160 return
161 (bitA[0] << 0) | (bitB[0] << 1) |
162 (bitA[1] << 2) | (bitB[1] << 3);
163 }
164
165
READ_HANDLER(dragrace_scanline_r)166 READ_HANDLER( dragrace_scanline_r )
167 {
168 return (cpu_getscanline() ^ 0xf0) | 0x0f;
169 }
170
171
MEMORY_READ_START(dragrace_readmem)172 static MEMORY_READ_START( dragrace_readmem )
173 { 0x0080, 0x00ff, MRA_RAM },
174 { 0x0800, 0x083f, dragrace_input_r },
175 { 0x0c00, 0x0c00, dragrace_steering_r },
176 { 0x0d00, 0x0d00, dragrace_scanline_r },
177 { 0x1000, 0x1fff, MRA_ROM }, /* program */
178 { 0xf800, 0xffff, MRA_ROM }, /* program mirror */
179 MEMORY_END
180
181 static MEMORY_WRITE_START( dragrace_writemem )
182 { 0x0080, 0x00ff, MWA_RAM },
183 { 0x0900, 0x091f, dragrace_misc_w },
184 { 0x0920, 0x093f, dragrace_misc_clear_w },
185 { 0x0a00, 0x0aff, MWA_RAM, &dragrace_playfield_ram },
186 { 0x0b00, 0x0bff, MWA_RAM, &dragrace_position_ram },
187 { 0x0e00, 0x0e00, MWA_NOP }, /* watchdog (disabled in service mode) */
188 { 0x1000, 0x1fff, MWA_ROM }, /* program */
189 { 0xf800, 0xffff, MWA_ROM }, /* program mirror */
190 MEMORY_END
191
192
193 INPUT_PORTS_START( dragrace )
194 PORT_START /* IN0 */
195 PORT_BITX( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER1, "Player 1 Gas", IP_KEY_DEFAULT, IP_JOY_DEFAULT )
196 PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) /* player 1 gear 1 */
197 PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) /* player 1 gear 2 */
198 PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) /* player 1 gear 3 */
199 PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) /* player 1 gear 4 */
200 PORT_SERVICE( 0x20, IP_ACTIVE_LOW )
201 PORT_DIPNAME( 0xc0, 0x80, "Extended Play" )
202 PORT_DIPSETTING( 0x00, "6.9 seconds" )
203 PORT_DIPSETTING( 0x80, "5.9 seconds" )
204 PORT_DIPSETTING( 0x40, "4.9 seconds" )
205 PORT_DIPSETTING( 0xc0, "Never" )
206
207 PORT_START /* IN1 */
208 PORT_BITX( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER2, "Player 2 Gas", IP_KEY_DEFAULT, IP_JOY_DEFAULT )
209 PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) /* player 2 gear 1 */
210 PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED ) /* player 2 gear 2 */
211 PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) /* player 2 gear 3 */
212 PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) /* player 2 gear 4 */
213 PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
214 PORT_DIPNAME( 0xc0, 0x80, "Number Of Heats" )
215 PORT_DIPSETTING( 0xc0, "3" )
216 PORT_DIPSETTING( 0x80, "4" )
217 PORT_DIPSETTING( 0x00, "5" )
218
219 PORT_START /* IN2 */
220 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) /* IN0 connects here */
221 PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED ) /* IN1 connects here */
222 PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_COIN1 )
223 PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_COIN2 )
224 PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_START1 )
225 PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_START2 )
226 PORT_DIPNAME( 0xc0, 0x40, DEF_STR( Coinage ) )
227 PORT_DIPSETTING( 0xc0, DEF_STR( 2C_1C ) )
228 PORT_DIPSETTING( 0x40, DEF_STR( 1C_1C ) )
229 PORT_DIPSETTING( 0x80, DEF_STR( 1C_2C ) )
230 PORT_DIPSETTING( 0x00, DEF_STR( Free_Play ) )
231
232 PORT_START /* IN3 */
233 PORT_ANALOG( 0xff, 0x00, IPT_DIAL_V | IPF_PLAYER1, 25, 10, 0, 0 )
234
235 PORT_START /* IN4 */
236 PORT_ANALOG( 0xff, 0x00, IPT_DIAL_V | IPF_PLAYER2, 25, 10, 0, 0 )
237
238 PORT_START /* IN5 */
239 PORT_BITX(0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 | IPF_PLAYER1, "Player 1 Gear 1", IP_KEY_DEFAULT, IP_JOY_DEFAULT )
240 PORT_BITX(0x02, IP_ACTIVE_HIGH, IPT_BUTTON3 | IPF_PLAYER1, "Player 1 Gear 2", IP_KEY_DEFAULT, IP_JOY_DEFAULT )
241 PORT_BITX(0x04, IP_ACTIVE_HIGH, IPT_BUTTON4 | IPF_PLAYER1, "Player 1 Gear 3", IP_KEY_DEFAULT, IP_JOY_DEFAULT )
242 PORT_BITX(0x08, IP_ACTIVE_HIGH, IPT_BUTTON5 | IPF_PLAYER1, "Player 1 Gear 4", IP_KEY_DEFAULT, IP_JOY_DEFAULT )
243 PORT_BITX(0x10, IP_ACTIVE_HIGH, IPT_BUTTON6 | IPF_PLAYER1, "Player 1 Neutral", IP_KEY_DEFAULT, IP_JOY_DEFAULT )
244
245 PORT_START /* IN6 */
246 PORT_BITX(0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 | IPF_PLAYER2, "Player 2 Gear 1", IP_KEY_DEFAULT, IP_JOY_DEFAULT )
247 PORT_BITX(0x02, IP_ACTIVE_HIGH, IPT_BUTTON3 | IPF_PLAYER2, "Player 2 Gear 2", IP_KEY_DEFAULT, IP_JOY_DEFAULT )
248 PORT_BITX(0x04, IP_ACTIVE_HIGH, IPT_BUTTON4 | IPF_PLAYER2, "Player 2 Gear 3", IP_KEY_DEFAULT, IP_JOY_DEFAULT )
249 PORT_BITX(0x08, IP_ACTIVE_HIGH, IPT_BUTTON5 | IPF_PLAYER2, "Player 2 Gear 4", IP_KEY_DEFAULT, IP_JOY_DEFAULT )
250 PORT_BITX(0x10, IP_ACTIVE_HIGH, IPT_BUTTON6 | IPF_PLAYER2, "Player 2 Neutral", IP_KEY_DEFAULT, IP_JOY_DEFAULT )
251 PORT_START
252 PORT_ADJUSTER( 81, "Motor 1 RPM" )
253
254 PORT_START
255 PORT_ADJUSTER( 85, "Motor 2 RPM" )
256 INPUT_PORTS_END
257
258
259 static struct GfxLayout dragrace_tile_layout1 =
260 {
261 16, 16, /* width, height */
262 0x40, /* total */
263 1, /* planes */
264 { 0 }, /* plane offsets */
265 {
266 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
267 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87
268 },
269 {
270 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38,
271 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78
272 },
273 0x100 /* increment */
274 };
275
276
277 static struct GfxLayout dragrace_tile_layout2 =
278 {
279 16, 16, /* width, height */
280 0x20, /* total */
281 2, /* planes */
282 { /* plane offsets */
283 0x0000, 0x2000
284 },
285 {
286 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
287 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87
288 },
289 {
290 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38,
291 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78
292 },
293 0x100 /* increment */
294 };
295
296
297 static struct GfxDecodeInfo dragrace_gfx_decode_info[] =
298 {
299 { REGION_GFX1, 0, &dragrace_tile_layout1, 0, 4 },
300 { REGION_GFX2, 0, &dragrace_tile_layout2, 8, 2 },
301 { -1 } /* end of array */
302 };
303
304
PALETTE_INIT(dragrace)305 static PALETTE_INIT( dragrace )
306 {
307 palette_set_color(0, 0xFF, 0xFF, 0xFF); /* 2 color tiles */
308 palette_set_color(1, 0x00, 0x00, 0x00);
309 palette_set_color(2, 0x00, 0x00, 0x00);
310 palette_set_color(3, 0xFF, 0xFF, 0xFF);
311 palette_set_color(4, 0x00, 0x00, 0x00);
312 palette_set_color(5, 0x00, 0x00, 0x00);
313 palette_set_color(6, 0xFF, 0xFF, 0xFF);
314 palette_set_color(7, 0xFF, 0xFF, 0xFF);
315 palette_set_color(8, 0xFF, 0xFF, 0xFF); /* 4 color tiles */
316 palette_set_color(9, 0xB0, 0xB0, 0xB0);
317 palette_set_color(10,0x5F, 0x5F, 0x5F);
318 palette_set_color(11,0x00, 0x00, 0x00);
319 palette_set_color(12,0xFF, 0xFF, 0xFF);
320 palette_set_color(13,0x5F, 0x5F, 0x5F);
321 palette_set_color(14,0xB0, 0xB0, 0xB0);
322 palette_set_color(15,0x00, 0x00, 0x00);
323 }
324
325
326 /************************************************************************/
327 /* dragrace Sound System Analog emulation */
328 /************************************************************************/
329
330 const struct discrete_lfsr_desc dragrace_lfsr = {
331 16, /* Bit Length */
332 0, /* Reset Value */
333 0, /* Use Bit 0 as XOR input 0 */
334 14, /* Use Bit 14 as XOR input 1 */
335 DISC_LFSR_XNOR, /* Feedback stage1 is XNOR */
336 DISC_LFSR_OR, /* Feedback stage2 is just stage 1 output OR with external feed */
337 DISC_LFSR_REPLACE, /* Feedback stage3 replaces the shifted register contents */
338 0x000001, /* Everything is shifted into the first bit only */
339 0, /* Output is already inverted by XNOR */
340 15 /* Output bit */
341 };
342
343 /* Nodes - Inputs */
344 #define DRAGRACE_SCREECH1_EN NODE_01
345 #define DRAGRACE_SCREECH2_EN NODE_02
346 #define DRAGRACE_LOTONE_EN NODE_03
347 #define DRAGRACE_HITONE_EN NODE_04
348 #define DRAGRACE_EXPLODE1_EN NODE_05
349 #define DRAGRACE_EXPLODE2_EN NODE_06
350 #define DRAGRACE_MOTOR1_DATA NODE_07
351 #define DRAGRACE_MOTOR2_DATA NODE_08
352 #define DRAGRACE_MOTOR1_EN NODE_80
353 #define DRAGRACE_MOTOR2_EN NODE_81
354 #define DRAGRACE_KLEXPL1_EN NODE_82
355 #define DRAGRACE_KLEXPL2_EN NODE_83
356 #define DRAGRACE_ATTRACT_EN NODE_09
357 /* Nodes - Sounds */
358 #define DRAGRACE_NOISE NODE_10
359 #define DRAGRACE_SCREECH1_SND NODE_11
360 #define DRAGRACE_SCREECH2_SND NODE_12
361 #define DRAGRACE_LOTONE_SND NODE_13
362 #define DRAGRACE_HITONE_SND NODE_14
363 #define DRAGRACE_TONE_SND NODE_15
364 #define DRAGRACE_EXPLODE1_SND NODE_16
365 #define DRAGRACE_EXPLODE2_SND NODE_17
366 #define DRAGRACE_MOTOR1_SND NODE_18
367 #define DRAGRACE_MOTOR2_SND NODE_19
368
369 static DISCRETE_SOUND_START(dragrace_sound_interface)
370 /************************************************/
371 /* dragrace Effects Relataive Gain Table */
372 /* */
373 /* Effect V-ampIn Gain ratio Relative */
374 /* LoTone 3.8 10/32 593.8 */
375 /* HiTone 3.8 10/32 593.8 */
376 /* Screech 3.8 10/330 57.6 */
377 /* Motor 3.8 10/32.67 581.6 */
378 /* Explode 5.0 10/25 1000.0 */
379 /************************************************/
380
381
382 /************************************************/
383 /* Input register mapping for dragrace */
384 /************************************************/
385 /* NODE ADDR MASK INIT */
386 DISCRETE_INPUT(DRAGRACE_SCREECH1_EN, 0x00, 0x000f, 0.0)
387 DISCRETE_INPUT(DRAGRACE_SCREECH2_EN, 0x01, 0x000f, 0.0)
388 DISCRETE_INPUT(DRAGRACE_LOTONE_EN, 0x02, 0x000f, 0.0)
389 DISCRETE_INPUT(DRAGRACE_HITONE_EN, 0x03, 0x000f, 0.0)
390 DISCRETE_INPUT(DRAGRACE_EXPLODE1_EN, 0x04, 0x000f, 0.0)
391 DISCRETE_INPUT(DRAGRACE_EXPLODE2_EN, 0x05, 0x000f, 0.0)
392 DISCRETE_INPUT(DRAGRACE_MOTOR1_DATA, 0x06, 0x000f, 0.0)
393 DISCRETE_INPUT(DRAGRACE_MOTOR2_DATA, 0x07, 0x000f, 0.0)
394 DISCRETE_INPUT(DRAGRACE_MOTOR1_EN, 0x08, 0x000f, 0.0)
395 DISCRETE_INPUT(DRAGRACE_MOTOR2_EN, 0x09, 0x000f, 0.0)
396 DISCRETE_INPUT(DRAGRACE_KLEXPL1_EN, 0x0a, 0x000f, 0.0)
397 DISCRETE_INPUT(DRAGRACE_KLEXPL2_EN, 0x0b, 0x000f, 0.0)
398 DISCRETE_INPUT(DRAGRACE_ATTRACT_EN, 0x0c, 0x000f, 0.0)
399
400 /************************************************/
401 /* Motor sound circuit is based on a 556 VCO */
402 /* with the input frequency set by the MotorSND */
403 /* latch (4 bit). This freqency is then used to */
404 /* driver a modulo 12 counter, with div6, 4 & 3 */
405 /* summed as the output of the circuit. */
406 /* VCO Output is Sq wave = 27-382Hz */
407 /* F1 freq - (Div6) */
408 /* F2 freq = (Div4) */
409 /* F3 freq = (Div3) 33.3% duty, 33.3 deg phase */
410 /* To generate the frequency we take the freq. */
411 /* diff. and /15 to get all the steps between */
412 /* 0 - 15. Then add the low frequency and send */
413 /* that value to a squarewave generator. */
414 /* Also as the frequency changes, it ramps due */
415 /* to a 2.2uf capacitor on the R-ladder. */
416 /* Note the VCO freq. is controlled by a 250k */
417 /* pot. The freq. used here is for the pot set */
418 /* to 125k. The low freq is allways the same. */
419 /* This adjusts the high end. */
420 /* 0k = 214Hz. 250k = 4416Hz */
421 /* NOTE: freqs are ripped from Sprint for now. */
422 /************************************************/
423 DISCRETE_RCFILTER(NODE_20, 1, DRAGRACE_MOTOR1_DATA, 119898, 2.2e-6)
424 DISCRETE_ADJUSTMENT(NODE_21, 1, (214.0-27.0)/12/31, (4416.0-27.0)/12/31, DISC_LOGADJ, 7)
425 DISCRETE_MULTIPLY(NODE_22, 1, NODE_20, NODE_21)
426
427 DISCRETE_MULTADD(NODE_23, 1, NODE_22, 2, 27.0/6) /* F1 = /12*2 = /6 */
428 DISCRETE_SQUAREWAVE(NODE_24, 1, NODE_23, (581.6/3), 50.0, 0, 0)
429 DISCRETE_RCFILTER(NODE_25, 1, NODE_24, 10000, 1e-7)
430
431 DISCRETE_MULTADD(NODE_26, 1, NODE_22, 3, 27.0/4) /* F2 = /12*3 = /4 */
432 DISCRETE_SQUAREWAVE(NODE_27, 1, NODE_26, (581.6/3), 50.0, 0, 0)
433 DISCRETE_RCFILTER(NODE_28, 1, NODE_27, 10000, 1e-7)
434
435 DISCRETE_MULTADD(NODE_29, 1, NODE_22, 4, 27.0/3) /* F3 = /12*4 = /3 */
436 DISCRETE_SQUAREWAVE(NODE_30, 1, NODE_29, (581.6/3), 100.0/3, 0, 360.0/3)
437 DISCRETE_RCFILTER(NODE_31, 1, NODE_30, 10000, 1e-7)
438
439 DISCRETE_ADDER3(DRAGRACE_MOTOR1_SND, DRAGRACE_MOTOR1_EN, NODE_25, NODE_28, NODE_31)
440
441 /************************************************/
442 /* Car2 motor sound is basically the same as */
443 /* Car1. But I shifted the frequencies up for */
444 /* it to sound different from car1. */
445 /************************************************/
446 DISCRETE_RCFILTER(NODE_40, 1, DRAGRACE_MOTOR2_DATA, 119898, 2.2e-6)
447 DISCRETE_ADJUSTMENT(NODE_41, 1, (214.0-27.0)/12/31, (4416.0-27.0)/12/31, DISC_LOGADJ, 8)
448 DISCRETE_MULTIPLY(NODE_42, 1, NODE_40, NODE_41)
449
450 DISCRETE_MULTADD(NODE_43, 1, NODE_42, 2, 27.0/6) /* F1 = /12*2 = /6 */
451 DISCRETE_SQUAREWAVE(NODE_44, 1, NODE_43, (581.6/3), 50.0, 0, 0)
452 DISCRETE_RCFILTER(NODE_45, 1, NODE_44, 10000, 1e-7)
453
454 DISCRETE_MULTADD(NODE_46, 1, NODE_42, 3, 27.0/4) /* F2 = /12*3 = /4 */
455 DISCRETE_SQUAREWAVE(NODE_47, 1, NODE_46, (581.6/3), 50.0, 0, 0)
456 DISCRETE_RCFILTER(NODE_48, 1, NODE_47, 10000, 1e-7)
457
458 DISCRETE_MULTADD(NODE_49, 1, NODE_42, 4, 27.0/3) /* F3 = /12*4 = /3 */
459 DISCRETE_SQUAREWAVE(NODE_50, 1, NODE_49, (581.6/3), 100.0/3, 0, 360.0/3)
460 DISCRETE_RCFILTER(NODE_51, 1, NODE_50, 10000, 1e-7)
461
462 DISCRETE_ADDER3(DRAGRACE_MOTOR2_SND, DRAGRACE_MOTOR2_EN, NODE_45, NODE_48, NODE_51)
463
464 /************************************************/
465 /* Explosion circuit is built around a noise */
466 /* generator built from 2 shift registers that */
467 /* are clocked by the 1V signal. */
468 /* 1V = HSYNC/2 */
469 /* = 15750/2 */
470 /* Output is integrated to apply decay. */
471 /************************************************/
472 DISCRETE_LFSR_NOISE(DRAGRACE_NOISE, 1, DRAGRACE_ATTRACT_EN, 15750.0/2, 1.0, 0, 0, &dragrace_lfsr)
473
474 DISCRETE_RAMP(NODE_61, DRAGRACE_EXPLODE1_EN, DRAGRACE_EXPLODE1_EN, (1000.0-0.0)/1, 1000.0, 0.0, 1000.0)
475 DISCRETE_MULTIPLY(NODE_62, 1, DRAGRACE_NOISE, NODE_61)
476 DISCRETE_RCFILTER(DRAGRACE_EXPLODE1_SND, DRAGRACE_KLEXPL1_EN, NODE_62, 1500, 2.2e-7)
477
478 DISCRETE_RAMP(NODE_66, DRAGRACE_EXPLODE2_EN, DRAGRACE_EXPLODE2_EN, (1000.0-0.0)/1, 1000.0, 0.0, 1000.0)
479 DISCRETE_MULTIPLY(NODE_67, 1, DRAGRACE_NOISE, NODE_66)
480 DISCRETE_RCFILTER(DRAGRACE_EXPLODE2_SND, DRAGRACE_KLEXPL2_EN, NODE_67, 1500, 2.2e-7)
481
482 /************************************************/
483 /* Skid circuits takes the noise output from */
484 /* the crash circuit and applies +ve feedback */
485 /* to cause oscillation. There is also an RC */
486 /* filter on the input to the feedback cct. */
487 /* RC is 1K & 10uF */
488 /* Feedback cct is modelled by using the RC out */
489 /* as the frequency input on a VCO, */
490 /* breadboarded freq range as: */
491 /* 0 = 940Hz, 34% duty */
492 /* 1 = 630Hz, 29% duty */
493 /* the duty variance is so small we ignore it */
494 /************************************************/
495 DISCRETE_INVERT(NODE_70, DRAGRACE_NOISE)
496 DISCRETE_MULTADD(NODE_71, 1, NODE_70, 940.0-630.0, ((940.0-630.0)/2)+630.0)
497 DISCRETE_RCFILTER(NODE_72, 1, NODE_71, 1000, 1e-5)
498 DISCRETE_SQUAREWAVE(NODE_73, 1, NODE_72, 407.8, 31.5, 0, 0.0)
499 DISCRETE_ONOFF(DRAGRACE_SCREECH1_SND, DRAGRACE_SCREECH1_EN, NODE_73)
500 DISCRETE_ONOFF(DRAGRACE_SCREECH2_SND, DRAGRACE_SCREECH2_EN, NODE_73)
501
502 /************************************************/
503 /* LoTone = 32V = 15750Hz/2/32 */
504 /* HiTone = 4V = 15750Hz/2/4 */
505 /************************************************/
506 DISCRETE_SQUAREWFIX(DRAGRACE_LOTONE_SND, DRAGRACE_LOTONE_EN, 15750.0/2/32, 593.8, 50.0, 0, 0.0)
507 DISCRETE_SQUAREWFIX(DRAGRACE_HITONE_SND, DRAGRACE_HITONE_EN, 15750.0/2/4, 593.8, 50.0, 0, 0.0)
508 DISCRETE_ADDER2(DRAGRACE_TONE_SND, 1, DRAGRACE_LOTONE_SND, DRAGRACE_HITONE_SND)
509
510 /************************************************/
511 /* Combine all 5 sound sources. */
512 /* Add some final gain to get to a good sound */
513 /* level. */
514 /************************************************/
515 DISCRETE_ADDER4(NODE_90, DRAGRACE_ATTRACT_EN, DRAGRACE_TONE_SND, DRAGRACE_MOTOR1_SND, DRAGRACE_EXPLODE1_SND, DRAGRACE_SCREECH1_SND)
516 DISCRETE_ADDER4(NODE_91, DRAGRACE_ATTRACT_EN, DRAGRACE_TONE_SND, DRAGRACE_MOTOR2_SND, DRAGRACE_EXPLODE2_SND, DRAGRACE_SCREECH2_SND)
517 DISCRETE_GAIN(NODE_92, NODE_90, 65534.0/(593.8+581.6+1000.0+57.6))
518 DISCRETE_GAIN(NODE_93, NODE_91, 65534.0/(593.8+581.6+1000.0+57.6))
519
520 DISCRETE_OUTPUT(NODE_92, MIXER(100,MIXER_PAN_LEFT))
521 DISCRETE_OUTPUT(NODE_93, MIXER(100,MIXER_PAN_RIGHT))
522 DISCRETE_SOUND_END
523
524
525 static MACHINE_DRIVER_START( dragrace )
526
527 /* basic machine hardware */
528 MDRV_CPU_ADD(M6800, 12096000 / 12)
529 MDRV_CPU_MEMORY(dragrace_readmem, dragrace_writemem)
530 MDRV_CPU_VBLANK_INT(irq0_line_hold, 4)
531
532 MDRV_FRAMES_PER_SECOND(60)
533 MDRV_VBLANK_DURATION((int) ((22. * 1000000) / (262. * 60) + 0.5))
534
535 MDRV_MACHINE_INIT(dragrace)
536
537 /* video hardware */
538 MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER)
539 MDRV_SCREEN_SIZE(256, 240)
540 MDRV_VISIBLE_AREA(0, 255, 0, 239)
541 MDRV_GFXDECODE(dragrace_gfx_decode_info)
542 MDRV_PALETTE_LENGTH(16)
543 MDRV_PALETTE_INIT(dragrace)
544 MDRV_VIDEO_START(dragrace)
545 MDRV_VIDEO_UPDATE(dragrace)
546
547 /* sound hardware */
548 MDRV_SOUND_ATTRIBUTES(SOUND_SUPPORTS_STEREO)
549 MDRV_SOUND_ADD_TAG("discrete", DISCRETE, dragrace_sound_interface)
550 MACHINE_DRIVER_END
551
552
553 ROM_START( dragrace )
554 ROM_REGION( 0x10000, REGION_CPU1, 0 )
555 ROM_LOAD( "8513.c1", 0x1000, 0x0800, CRC(543bbb30) SHA1(646a41d1124c8365f07a93de38af007895d7d263) )
556 ROM_LOAD( "8514.a1", 0x1800, 0x0800, CRC(ad218690) SHA1(08ba5f4fa4c75d8dad1a7162888d44b3349cbbe4) )
557 ROM_RELOAD( 0xF800, 0x0800 )
558
559 ROM_REGION( 0x800, REGION_GFX1, ROMREGION_DISPOSE ) /* 2 color tiles */
560 ROM_LOAD( "8519dr.j0", 0x000, 0x200, CRC(aa221ba0) SHA1(450acbf349d77a790a25f3e303c31b38cc426a38) )
561 ROM_LOAD( "8521dr.k0", 0x200, 0x200, CRC(0cb33f12) SHA1(d50cb55391aec03e064eecad1624d50d4c30ccab) )
562 ROM_LOAD( "8520dr.r0", 0x400, 0x200, CRC(ee1ae6a7) SHA1(83491095260c8b7c616ff17ec1e888d05620f166) )
563
564 ROM_REGION( 0x800, REGION_GFX2, ROMREGION_DISPOSE ) /* 4 color tiles */
565 ROM_LOAD( "8515dr.e0", 0x000, 0x200, CRC(9510a59e) SHA1(aea0782b919279efe55a07007bd55a16f7f59239) )
566 ROM_LOAD( "8517dr.h0", 0x200, 0x200, CRC(8b5bff1f) SHA1(fdcd719c66bff7c4b9f3d56d1e635259dd8add61) )
567 ROM_LOAD( "8516dr.l0", 0x400, 0x200, CRC(d1e74af1) SHA1(f55a3bfd7d152ac9af128697f55c9a0c417779f5) )
568 ROM_LOAD( "8518dr.n0", 0x600, 0x200, CRC(b1369028) SHA1(598a8779982d532c9f34345e793a79fcb29cac62) )
569 ROM_END
570
571
572 GAME( 1977, dragrace, 0, dragrace, dragrace, 0, 0, "Atari", "Drag Race" )
573