1 /***************************************************************************
2 
3 	Atari Canyon Bomber hardware
4 
5 	driver by Mike Balfour
6 
7 	Games supported:
8 		* Canyon Bomber
9 
10 	Known issues:
11 		* none at this time
12 
13 ****************************************************************************
14 
15 	Memory Map:
16         0000-01FF       WRAM
17         0400-04FF       W A0=0:MOTOR1, A0=1:MOTOR2
18         0500-05FF       W A0=0:EXPLODE, A0=1:TIMER RESET
19         0600-067F       W A0=0:WHISTLE1, A0=1:WHISTLE2
20         0680-06FF       W A0=0:LED1, A0=1:LED2
21         0700-077F       W A0=0:ATTRACT1, A0=1:ATTRACT2
22         0800-0FFF       DISPLAY / RAM
23         1000-17FF       SWITCHES
24         1800-1FFF       OPTIONS
25         2000-27FF       ROM1
26         2800-2FFF       ROM2
27         3000-37FF       ROM3 (Language ROM)
28         3800-3FFF       ROM4 (Program ROM)
29 
30 	If you have any questions about how this driver works, don't hesitate to
31 	ask.  - Mike Balfour (mab22@po.cwru.edu)
32 
33 ***************************************************************************/
34 
35 #include "driver.h"
36 
37 extern WRITE_HANDLER( canyon_videoram_w );
38 
39 extern VIDEO_START( canyon );
40 extern VIDEO_UPDATE( canyon );
41 
42 extern UINT8* canyon_videoram;
43 
44 
45 /*************************************
46  *
47  *	Palette generation
48  *
49  *************************************/
50 
PALETTE_INIT(canyon)51 static PALETTE_INIT( canyon )
52 {
53 	palette_set_color(0, 0x00, 0x00, 0x00); /* BLACK */
54 	palette_set_color(1, 0xff, 0xff, 0xff); /* WHITE */
55 	palette_set_color(2, 0x80, 0x80, 0x80); /* GREY  */
56 
57 	colortable[0] = 2;
58 	colortable[1] = 0;
59 	colortable[2] = 2;
60 	colortable[3] = 1;
61 }
62 
63 
64 /*************************************
65  *
66  *	Read handlers
67  *
68  *************************************/
69 
READ_HANDLER(canyon_switches_r)70 static READ_HANDLER( canyon_switches_r )
71 {
72 	UINT8 val = 0;
73 
74 	if ((readinputport(2) >> (offset & 7)) & 1)
75 	{
76 		val |= 0x80;
77 	}
78 	if ((readinputport(1) >> (offset & 3)) & 1)
79 	{
80 		val |= 0x01;
81 	}
82 
83 	return val;
84 }
85 
86 
READ_HANDLER(canyon_options_r)87 static READ_HANDLER( canyon_options_r )
88 {
89 	return (readinputport(0) >> (2 * (~offset & 3))) & 3;
90 }
91 
92 
READ_HANDLER(canyon_wram_r)93 static READ_HANDLER( canyon_wram_r )
94 {
95 	return memory_region(REGION_CPU1)[offset];
96 }
97 
98 
99 
100 /*************************************
101  *
102  *	Write handlers
103  *
104  *************************************/
105 
WRITE_HANDLER(canyon_led_w)106 static WRITE_HANDLER( canyon_led_w )
107 {
108 	set_led_status(offset & 0x01, offset & 0x02);
109 }
110 
111 
WRITE_HANDLER(canyon_motor_w)112 static WRITE_HANDLER( canyon_motor_w )
113 {
114 	discrete_sound_w(offset & 0x01, data & 0x0f);
115 }
116 
117 
WRITE_HANDLER(canyon_explode_w)118 static WRITE_HANDLER( canyon_explode_w )
119 {
120 	discrete_sound_w(6, data / 16);
121 }
122 
123 
WRITE_HANDLER(canyon_attract_w)124 static WRITE_HANDLER( canyon_attract_w )
125 {
126 	discrete_sound_w(4 + (offset & 0x01), !(offset & 0x02));
127 }
128 
129 
WRITE_HANDLER(canyon_whistle_w)130 static WRITE_HANDLER( canyon_whistle_w )
131 {
132 	discrete_sound_w(2 + (offset & 0x01), (offset & 0x02) >> 1);
133 }
134 
135 
WRITE_HANDLER(canyon_wram_w)136 static WRITE_HANDLER( canyon_wram_w )
137 {
138 	memory_region(REGION_CPU1)[offset] = data;
139 }
140 
141 
142 
143 /*************************************
144  *
145  *	Main CPU memory handlers
146  *
147  *************************************/
148 
MEMORY_READ_START(readmem)149 static MEMORY_READ_START( readmem )
150 	{ 0x0000, 0x00ff, MRA_RAM },
151 	{ 0x0100, 0x01ff, canyon_wram_r },
152 	{ 0x0800, 0x0bff, MRA_RAM },
153 	{ 0x1000, 0x17ff, canyon_switches_r },
154 	{ 0x1800, 0x1fff, canyon_options_r },
155 	{ 0x2000, 0x3fff, MRA_ROM },
156 	{ 0xe000, 0xffff, MRA_ROM }, /* mirror for 6502 vectors */
157 MEMORY_END
158 
159 
160 static MEMORY_WRITE_START( writemem )
161 	{ 0x0000, 0x00ff, MWA_RAM },
162 	{ 0x0100, 0x01ff, canyon_wram_w },
163 	{ 0x0400, 0x0401, canyon_motor_w },
164 	{ 0x0500, 0x0500, canyon_explode_w },
165 	{ 0x0501, 0x0501, MWA_NOP }, /* watchdog, disabled in service mode */
166 	{ 0x0600, 0x0603, canyon_whistle_w },
167 	{ 0x0680, 0x0683, canyon_led_w },
168 	{ 0x0700, 0x0703, canyon_attract_w },
169 	{ 0x0800, 0x0bff, canyon_videoram_w, &canyon_videoram },
170 	{ 0x1000, 0x17ff, MWA_NOP }, /* sloppy code writes here */
171 	{ 0x2000, 0x3fff, MWA_ROM },
172 MEMORY_END
173 
174 
175 
176 /*************************************
177  *
178  *	Port definitions
179  *
180  *************************************/
181 
182 INPUT_PORTS_START( canyon )
183 	PORT_START      /* DSW */
184 	PORT_DIPNAME( 0x03, 0x00, "Language" )
185 	PORT_DIPSETTING(    0x00, "English" )
186 	PORT_DIPSETTING(    0x01, "Spanish" )
187 	PORT_DIPSETTING(    0x02, "French" )
188 	PORT_DIPSETTING(    0x03, "German" )
189 	PORT_DIPNAME( 0x30, 0x00, "Misses Per Play" )
190 	PORT_DIPSETTING(    0x00, "3" )
191 	PORT_DIPSETTING(    0x10, "4" )
192 	PORT_DIPSETTING(    0x20, "5" )
193 	PORT_DIPSETTING(    0x30, "6" )
194 	PORT_DIPNAME( 0xC0, 0x80, DEF_STR( Coinage ))
195 	PORT_DIPSETTING(    0xC0, DEF_STR( 2C_1C ))
196 	PORT_DIPSETTING(    0x80, DEF_STR( 1C_1C ))
197 	PORT_DIPSETTING(    0x40, DEF_STR( 1C_2C ))
198 	PORT_DIPSETTING(    0x00, DEF_STR( Free_Play ) )
199 
200 	PORT_START      /* IN1 */
201 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
202 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
203 	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_BUTTON1 | IPF_PLAYER1 )
204 	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_BUTTON1 | IPF_PLAYER2 )
205 
206 	PORT_START      /* IN2 */
207 	PORT_BIT ( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 )
208 	PORT_BIT ( 0x02, IP_ACTIVE_HIGH, IPT_COIN2 )
209 	PORT_BIT ( 0x04, IP_ACTIVE_HIGH, IPT_START1 )
210 	PORT_BIT ( 0x08, IP_ACTIVE_HIGH, IPT_START2 )
211 	PORT_SERVICE( 0x10, IP_ACTIVE_HIGH )
212 	PORT_BIT ( 0x20, IP_ACTIVE_LOW, IPT_VBLANK )
213 	PORT_BITX( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON7, "Hiscore Reset", KEYCODE_H, IP_JOY_DEFAULT )
214 	PORT_BIT ( 0x80, IP_ACTIVE_HIGH, IPT_TILT ) /* SLAM */
215 
216 	PORT_START
217 	PORT_ADJUSTER( 20, "Motor 1 RPM" )
218 
219 	PORT_START
220 	PORT_ADJUSTER( 30, "Motor 2 RPM" )
221 
222 	PORT_START
223 	PORT_ADJUSTER( 70, "Whistle 1 Freq" )
224 
225 	PORT_START
226 	PORT_ADJUSTER( 80, "Whistle 2 Freq" )
227 INPUT_PORTS_END
228 
229 
230 
231 /*************************************
232  *
233  *	Graphics definitions
234  *
235  *************************************/
236 
237 static struct GfxLayout tile_layout =
238 {
239 	8, 8,
240     64,
241     1,
242     { 0 },
243     {
244 		0x4, 0x5, 0x6, 0x7, 0xC, 0xD, 0xE, 0xF
245 	},
246 	{
247 		0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70
248 	},
249 	0x80
250 };
251 
252 
253 static struct GfxLayout sprite_layout =
254 {
255 	32, 16,
256 	4,
257 	1,
258 	{ 0 },
259 	{
260 		0x007, 0x006, 0x005, 0x004, 0x003, 0x002, 0x001, 0x000,
261 		0x00F, 0x00E, 0x00D, 0x00C, 0x00B, 0x00A, 0x009, 0x008,
262 		0x107, 0x106, 0x105, 0x104, 0x103, 0x102, 0x101, 0x100,
263 		0x10F, 0x10E, 0x10D, 0x10C, 0x10B, 0x10A, 0x109, 0x108
264 	},
265 	{
266 		0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
267 		0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0
268 	},
269 	0x200
270 };
271 
272 
273 static struct GfxDecodeInfo gfxdecodeinfo[] =
274 {
275 	{ REGION_GFX1, 0, &tile_layout,   0, 2 },
276 	{ REGION_GFX2, 0, &sprite_layout, 0, 2 },
277 	{ -1 }
278 };
279 
280 
281 
282 /************************************************************************/
283 /* canyon Sound System Analog emulation                               */
284 /************************************************************************/
285 
286 const struct discrete_555_astbl_desc canyonWhistl555 =
287 {
288 	DISC_555_OUT_CAP | DISC_555_OUT_AC,
289 	5,		// B+ voltage of 555
290 	5.0 - 1.7,	// High output voltage of 555 (Usually v555 - 1.7)
291 	5.0 * 2.0 /3.0,	// normally 2/3 of v555
292 	5.0 / 3.0	// normally 1/3 of v555
293 };
294 
295 const struct discrete_lfsr_desc canyon_lfsr={
296 	16,                 /* Bit Length */
297 	0,                  /* Reset Value */
298 	6,                  /* Use Bit 6 as XOR input 0 */
299 	8,                  /* Use Bit 8 as XOR input 1 */
300 	DISC_LFSR_XNOR,     /* Feedback stage1 is XNOR */
301 	DISC_LFSR_OR,       /* Feedback stage2 is just stage 1 output OR with external feed */
302 	DISC_LFSR_REPLACE,  /* Feedback stage3 replaces the shifted register contents */
303 	0x000001,           /* Everything is shifted into the first bit only */
304 	0,                  /* Output is not inverted, Active Low Reset */
305 	15                  /* Output bit */
306 };
307 
308 /* Nodes - Inputs */
309 #define CANYON_MOTORSND1_DATA		NODE_01
310 #define CANYON_MOTORSND2_DATA		NODE_02
311 #define CANYON_EXPLODESND_DATA		NODE_03
312 #define CANYON_WHISTLESND1_EN		NODE_04
313 #define CANYON_WHISTLESND2_EN		NODE_05
314 #define CANYON_ATTRACT1_EN		NODE_06
315 #define CANYON_ATTRACT2_EN		NODE_07
316 /* Nodes - Sounds */
317 #define CANYON_MOTORSND1		NODE_10
318 #define CANYON_MOTORSND2		NODE_11
319 #define CANYON_EXPLODESND		NODE_12
320 #define CANYON_WHISTLESND1		NODE_13
321 #define CANYON_WHISTLESND2		NODE_14
322 #define CANYON_NOISE			NODE_15
323 #define CANYON_FINAL_MIX1		NODE_16
324 #define CANYON_FINAL_MIX2		NODE_17
325 
326 static DISCRETE_SOUND_START(canyon_sound_interface)
327 	/************************************************/
328 	/* Canyon sound system: 5 Sound Sources         */
329 	/*                     Relative Volume          */
330 	/*    1/2) Motor           14.29%               */
331 	/*      3) Explode        100.00%               */
332 	/*    4/5) Whistle         51.94%               */
333 	/* Relative volumes calculated from resitor     */
334 	/* network in combiner circuit taking voltages  */
335 	/* into account                                 */
336 	/*                                              */
337 	/* Motor   3.8V * 5/(5+100) = 0.1810            */
338 	/* Explode 3.8V * 5/(5+10)  = 1.2667            */
339 	/* Whistle 5.0V * 5/(5+33)  = 0.6579            */
340 	/*                                              */
341 	/*  Discrete sound mapping via:                 */
342 	/*     discrete_sound_w($register,value)        */
343 	/*  $00 - Motorsound frequency 1                */
344 	/*  $01 - Motorsound frequency 2                */
345 	/*  $02 - Whistle enable 1                      */
346 	/*  $03 - Whistle enable 2                      */
347 	/*  $04 - Attract enable 1                      */
348 	/*  $05 - Attract enable 2                      */
349 	/*  $06 - Explode volume                        */
350 	/*                                              */
351 	/************************************************/
352 
353 	/************************************************/
354 	/* Input register mapping for canyon            */
355 	/************************************************/
356 	/*                   NODE                  ADDR  MASK    GAIN    OFFSET  INIT */
357 	DISCRETE_INPUTX(CANYON_MOTORSND1_DATA    , 0x00, 0x000f, -1.0   , 15.0,   0.0)
358 	DISCRETE_INPUTX(CANYON_MOTORSND2_DATA    , 0x01, 0x000f, -1.0   , 15.0,   0.0)
359 	DISCRETE_INPUT (CANYON_WHISTLESND1_EN    , 0x02, 0x000f,                  0.0)
360 	DISCRETE_INPUT (CANYON_WHISTLESND2_EN    , 0x03, 0x000f,                  0.0)
361 	DISCRETE_INPUT (CANYON_ATTRACT1_EN       , 0x04, 0x000f,                  0.0)
362 	DISCRETE_INPUT (CANYON_ATTRACT2_EN       , 0x05, 0x000f,                  0.0)
363 	DISCRETE_INPUTX(CANYON_EXPLODESND_DATA   , 0x06, 0x000f, 1000.0/15.0, 0,  0.0)
364 
365 	/************************************************/
366 	/* Motor sound circuit is based on a 556 VCO    */
367 	/* with the input frequency set by the MotorSND */
368 	/* latch (4 bit). This freqency is then used to */
369 	/* driver a modulo 12 counter, with div6, 4 & 3 */
370 	/* summed as the output of the circuit.         */
371 	/* VCO Output is Sq wave = 27-382Hz             */
372 	/*  F1 freq - (Div6)                            */
373 	/*  F2 freq = (Div4)                            */
374 	/*  F3 freq = (Div3) 33.3% duty, 33.3 deg phase */
375 	/* To generate the frequency we take the freq.  */
376 	/* diff. and /15 to get all the steps between   */
377 	/* 0 - 15.  Then add the low frequency and send */
378 	/* that value to a squarewave generator.        */
379 	/* Also as the frequency changes, it ramps due  */
380 	/* to a 1uf capacitor on the R-ladder.          */
381 	/* Note the VCO freq. is controlled by a 250k   */
382 	/* pot.  The freq. used here is for the pot set */
383 	/* to 125k.  The low freq is allways the same.  */
384 	/* This adjusts the high end.                   */
385 	/* 0k = 214Hz.   250k = 4416Hz                  */
386 	/************************************************/
387 	DISCRETE_RCFILTER(NODE_20, 1, CANYON_MOTORSND1_DATA, 123000, 1e-6)
388 	DISCRETE_ADJUSTMENT(NODE_21, 1, (214.0-27.0)/12/15, (4416.0-27.0)/12/15, DISC_LOGADJ, 3)
389 	DISCRETE_MULTIPLY(NODE_22, 1, NODE_20, NODE_21)
390 
391 	DISCRETE_MULTADD(NODE_23, 1, NODE_22, 2, 27.0/6)	/* F1 = /12*2 = /6 */
392 	DISCRETE_SQUAREWAVE(NODE_24, 1, NODE_23, (142.9/3), 50.0, 0, 0)
393 	DISCRETE_RCFILTER(NODE_25, 1, NODE_24, 10000, 1e-7)
394 
395 	DISCRETE_MULTADD(NODE_26, 1, NODE_22, 3, 27.0/4)	/* F2 = /12*3 = /4 */
396 	DISCRETE_SQUAREWAVE(NODE_27, 1, NODE_26, (142.9/3), 50.0, 0, 0)
397 	DISCRETE_RCFILTER(NODE_28, 1, NODE_27, 10000, 1e-7)
398 
399 	DISCRETE_MULTADD(NODE_29, 1, NODE_22, 4, 27.0/3)	/* F3 = /12*4 = /3 */
400 	DISCRETE_SQUAREWAVE(NODE_30, 1, NODE_29, (142.9/3), 100.0/3, 0, 360.0/3)
401 	DISCRETE_RCFILTER(NODE_31, 1, NODE_30, 10000, 1e-7)
402 
403 	DISCRETE_ADDER3(CANYON_MOTORSND1, CANYON_ATTRACT1_EN, NODE_25, NODE_28, NODE_31)
404 
405 	/************************************************/
406 	/* The motor2 sound is basically the same as    */
407 	/* for 1.  But I shifted the frequencies up for */
408 	/* it to sound different from motor 1.          */
409 	/************************************************/
410 	DISCRETE_RCFILTER(NODE_40, 1, CANYON_MOTORSND2_DATA, 123000, 1e-6)
411 	DISCRETE_ADJUSTMENT(NODE_41, 1, (214.0-27.0)/12/15, (4416.0-27.0)/12/15, DISC_LOGADJ, 4)
412 	DISCRETE_MULTIPLY(NODE_42, 1, NODE_40, NODE_41)
413 
414 	DISCRETE_MULTADD(NODE_43, 1, NODE_42, 2, 27.0/6)	/* F1 = /12*2 = /6 */
415 	DISCRETE_SQUAREWAVE(NODE_44, 1, NODE_43, (142.9/3), 50.0, 0, 0)
416 	DISCRETE_RCFILTER(NODE_45, 1, NODE_44, 10000, 1e-7)
417 
418 	DISCRETE_MULTADD(NODE_46, 1, NODE_42, 3, 27.0/4)	/* F2 = /12*3 = /4 */
419 	DISCRETE_SQUAREWAVE(NODE_47, 1, NODE_46, (142.9/3), 50.0, 0, 0)
420 	DISCRETE_RCFILTER(NODE_48, 1, NODE_47, 10000, 1e-7)
421 
422 	DISCRETE_MULTADD(NODE_49, 1, NODE_42, 4, 27.0/3)	/* F3 = /12*4 = /3 */
423 	DISCRETE_SQUAREWAVE(NODE_50, 1, NODE_49, (142.9/3), 100.0/3, 0, 360.0/3)
424 	DISCRETE_RCFILTER(NODE_51, 1, NODE_50, 10000, 1e-7)
425 
426 	DISCRETE_ADDER3(CANYON_MOTORSND2, CANYON_ATTRACT2_EN, NODE_45, NODE_48, NODE_51)
427 
428 	/************************************************/
429 	/* Explode circuit is built around a noise      */
430 	/* generator built from 2 shift registers that  */
431 	/* are clocked by the 2V signal.                */
432 	/* 2V = HSYNC/4                                 */
433 	/*    = 15750/4                                 */
434 	/* Output is binary weighted with 4 bits of     */
435 	/* crash volume.                                */
436 	/************************************************/
437 	DISCRETE_LOGIC_OR(NODE_60, 1, CANYON_ATTRACT1_EN, CANYON_ATTRACT2_EN)
438 	DISCRETE_LFSR_NOISE(CANYON_NOISE, NODE_60, NODE_60, 15750.0/4, 1.0, 0, 0, &canyon_lfsr)
439 
440 	DISCRETE_MULTIPLY(NODE_61, 1, CANYON_NOISE, CANYON_EXPLODESND_DATA)
441 	DISCRETE_RCFILTER(CANYON_EXPLODESND, 1, NODE_61, 545, 5e-6)
442 
443 	/************************************************/
444 	/* Whistle circuit is a 555 capacitor charge    */
445 	/* waveform.  The original game pot varies from */
446 	/* 0-100k, but we are going to limit it because */
447 	/* below 50k the frequency is too high.         */
448 	/* When triggered it starts at it's highest     */
449 	/* frequency, then decays at the rate set by    */
450 	/* a 68k resistor and 22uf capacitor.           */
451 	/************************************************/
452 	DISCRETE_ADJUSTMENT(NODE_70, 1, 50000, 100000, DISC_LINADJ, 5)	/* R59 */
453 	DISCRETE_MULTADD(NODE_71, 1, CANYON_WHISTLESND1_EN, 3.05-0.33, 0.33)
454 	DISCRETE_RCDISC2(NODE_72, CANYON_WHISTLESND1_EN, NODE_71, 1.0, NODE_71, 68000.0, 2.2e-5)	/* CV */
455 	DISCRETE_555_ASTABLE(NODE_73, CANYON_WHISTLESND1_EN, 33000, NODE_70, 1e-8, NODE_72, &canyonWhistl555)
456 	DISCRETE_MULTIPLY(CANYON_WHISTLESND1, CANYON_WHISTLESND1_EN, NODE_73, 519.4/3.3)
457 
458 	DISCRETE_ADJUSTMENT(NODE_75, 1, 50000, 100000, DISC_LINADJ, 6)	/* R69 */
459 	DISCRETE_MULTADD(NODE_76, 1, CANYON_WHISTLESND2_EN, 3.05-0.33, 0.33)
460 	DISCRETE_RCDISC2(NODE_77, CANYON_WHISTLESND2_EN, NODE_76, 1.0, NODE_76, 68000.0, 2.2e-5)	/* CV */
461 	DISCRETE_555_ASTABLE(NODE_78, CANYON_WHISTLESND2_EN, 33000, NODE_75, 1e-8, NODE_77, &canyonWhistl555)
462 	DISCRETE_MULTIPLY(CANYON_WHISTLESND2, CANYON_WHISTLESND2_EN, NODE_78, 519.4/3.3)
463 
464 	/************************************************/
465 	/* Combine all 5 sound sources.                 */
466 	/* Add some final gain to get to a good sound   */
467 	/* level.                                       */
468 	/************************************************/
469 	DISCRETE_ADDER3(NODE_90, 1, CANYON_MOTORSND1, CANYON_EXPLODESND, CANYON_WHISTLESND1)
470 	DISCRETE_ADDER3(NODE_91, 1, CANYON_MOTORSND2, CANYON_EXPLODESND, CANYON_WHISTLESND2)
471 	DISCRETE_GAIN(CANYON_FINAL_MIX1, NODE_90, 77)
472 	DISCRETE_GAIN(CANYON_FINAL_MIX2, NODE_91, 77)
473 
474 	DISCRETE_OUTPUT(CANYON_FINAL_MIX1, MIXER(100,MIXER_PAN_LEFT))
475 	DISCRETE_OUTPUT(CANYON_FINAL_MIX2, MIXER(100,MIXER_PAN_RIGHT))
476 DISCRETE_SOUND_END
477 
478 
479 
480 /*************************************
481  *
482  *	Machine driver
483  *
484  *************************************/
485 
486 static MACHINE_DRIVER_START( canyon )
487 
488 	/* basic machine hardware */
489 	MDRV_CPU_ADD(M6502, 12096000 / 16)
490 	MDRV_CPU_MEMORY(readmem, writemem)
491 	MDRV_CPU_VBLANK_INT(nmi_line_pulse, 1)
492 
493 	MDRV_FRAMES_PER_SECOND(60)
494 	MDRV_VBLANK_DURATION(22 * 1000000 / 15750)
495 
496 	/* video hardware */
497 	MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER)
498 	MDRV_SCREEN_SIZE(256, 240)
499 	MDRV_VISIBLE_AREA(0, 255, 0, 239)
500 	MDRV_GFXDECODE(gfxdecodeinfo)
501 	MDRV_PALETTE_LENGTH(3)
502 	MDRV_COLORTABLE_LENGTH(4)
503 
504 	MDRV_PALETTE_INIT(canyon)
505 	MDRV_VIDEO_START(canyon)
506 	MDRV_VIDEO_UPDATE(canyon)
507 
508 	/* sound hardware */
509 	MDRV_SOUND_ATTRIBUTES(SOUND_SUPPORTS_STEREO)
510 	MDRV_SOUND_ADD_TAG("discrete", DISCRETE, canyon_sound_interface)
511 MACHINE_DRIVER_END
512 
513 
514 
515 /*************************************
516  *
517  *	ROM definitions
518  *
519  *************************************/
520 
521 ROM_START( canyon )
522 	ROM_REGION( 0x10000, REGION_CPU1, 0 )
523 	ROM_LOAD_NIB_LOW ( "9499-01.j1", 0x3000, 0x0400, CRC(31800767) SHA1(d4aebe12d3c45a2a8a361dc6f63e1a6230a78c17) )
524 	ROM_LOAD_NIB_HIGH( "9503-01.p1", 0x3000, 0x0400, CRC(1eddbe28) SHA1(7d30280bf9edff743c16386d7cdec78094477996) )
525 	ROM_LOAD         ( "9496-01.d1", 0x3800, 0x0800, CRC(8be15080) SHA1(095c15e9ac91623b2d514858dca2e4c261d36fd0) )
526 	ROM_RELOAD(                      0xF800, 0x0800 ) /* for 6502 vectors */
527 
528 	ROM_REGION( 0x0400, REGION_GFX1, ROMREGION_DISPOSE )
529 	ROM_LOAD( "9492-01.n8", 0x0000, 0x0400, CRC(7449f754) SHA1(a8ffc39e1a86c94487551f5026eedbbd066b12c9) )
530 
531 	ROM_REGION( 0x0100, REGION_GFX2, ROMREGION_DISPOSE )
532 	ROM_LOAD_NIB_LOW ( "9506-01.m5", 0x0000, 0x0100, CRC(0d63396a) SHA1(147fae3b02a86310c8d022a7e7cfbf71ea511616) )
533 	ROM_LOAD_NIB_HIGH( "9505-01.n5", 0x0000, 0x0100, CRC(60507c07) SHA1(fcb76890cbaa37e02392bf8b97f7be9a6fe6a721) )
534 
535 	ROM_REGION( 0x0100, REGION_PROMS, 0 )
536 	ROM_LOAD( "9491-01.j6", 0x0000, 0x0100, CRC(b8094b4c) SHA1(82dc6799a19984f3b204ee3aeeb007e55afc8be3) )	/* sync (not used) */
537 ROM_END
538 
539 
540 ROM_START( canyonp )
541 	ROM_REGION( 0x10000, REGION_CPU1, 0 )
542 	ROM_LOAD_NIB_LOW ( "cbp3000l.j1", 0x3000, 0x0800, CRC(49cf29a0) SHA1(b58f024f45f85e5c2a48a95c60e80fd1be60eaac) )
543 	ROM_LOAD_NIB_HIGH( "cbp3000m.p1", 0x3000, 0x0800, CRC(b4385c23) SHA1(b550dfe9182f2b29aedba160a0917ca78b82f0e7) )
544 	ROM_LOAD_NIB_LOW ( "cbp3800l.h1", 0x3800, 0x0800, CRC(c7ee4431) SHA1(7a0f4454a981c4e9ee27e273e9a8379458e660e5) )
545 	ROM_RELOAD(                       0xf800, 0x0800 ) /* for 6502 vectors */
546 	ROM_LOAD_NIB_HIGH( "cbp3800m.r1", 0x3800, 0x0800, CRC(94246a9a) SHA1(5ff8b69fb744a5f62d4cf291e8f25e3620b479e7) )
547 	ROM_RELOAD(                       0xf800, 0x0800 ) /* for 6502 vectors */
548 
549 	ROM_REGION( 0x0400, REGION_GFX1, ROMREGION_DISPOSE )
550 	ROM_LOAD( "9492-01.n8", 0x0000, 0x0400, CRC(7449f754) SHA1(a8ffc39e1a86c94487551f5026eedbbd066b12c9) )
551 
552 	ROM_REGION( 0x0100, REGION_GFX2, ROMREGION_DISPOSE )
553 	ROM_LOAD_NIB_LOW ( "9506-01.m5", 0x0000, 0x0100, CRC(0d63396a) SHA1(147fae3b02a86310c8d022a7e7cfbf71ea511616) )
554 	ROM_LOAD_NIB_HIGH( "9505-01.n5", 0x0000, 0x0100, CRC(60507c07) SHA1(fcb76890cbaa37e02392bf8b97f7be9a6fe6a721) )
555 
556 	ROM_REGION( 0x0100, REGION_PROMS, 0 )
557 	ROM_LOAD( "9491-01.j6", 0x0000, 0x0100, CRC(b8094b4c) SHA1(82dc6799a19984f3b204ee3aeeb007e55afc8be3) )	/* sync (not used) */
558 ROM_END
559 
560 
561 
562 /*************************************
563  *
564  *	Game drivers
565  *
566  *************************************/
567 
568 GAME( 1977, canyon,  0,      canyon, canyon, 0, ROT0, "Atari", "Canyon Bomber" )
569 GAME( 1977, canyonp, canyon, canyon, canyon, 0, ROT0, "Atari", "Canyon Bomber (prototype)" )
570