1 /***************************************************************************
2
3 Atari/Kee Ultra Tank hardware
4
5 Games supported:
6 * Ultra Tank
7
8 Known issues:
9 - sound samples needed
10 - colors are probably correct, but should be verified
11 - invisible tanks option doesn't work
12 - coin counters aren't mapped
13 - hardware collision detection is not emulated. However, the game is fully playable,
14 since the game software uses it only as a hint to check for tanks bumping into
15 walls/mines.
16
17 ***************************************************************************/
18
19 #include "driver.h"
20 #include "vidhrdw/generic.h"
21
22 static int ultratnk_controls;
23 static UINT8 *mirror_ram;
24
25 static struct tilemap *bg_tilemap;
26
27 /*************************************
28 *
29 * Palette generation
30 *
31 *************************************/
32
33 static unsigned short colortable_source[] =
34 {
35 0x02, 0x01,
36 0x02, 0x00,
37 0x02, 0x00,
38 0x02, 0x01
39 };
40
PALETTE_INIT(ultratnk)41 static PALETTE_INIT( ultratnk )
42 {
43 palette_set_color(0,0x00,0x00,0x00); /* BLACK */
44 palette_set_color(1,0xff,0xff,0xff); /* WHITE */
45 palette_set_color(2,0x80,0x80,0x80); /* LT GREY */
46 palette_set_color(3,0x55,0x55,0x55); /* DK GREY */
47 memcpy(colortable,colortable_source,sizeof(colortable_source));
48 }
49
50
51
52 /*************************************
53 *
54 * Sprite rendering
55 *
56 *************************************/
57
ultratnk_draw_sprites(struct mame_bitmap * bitmap)58 static void ultratnk_draw_sprites( struct mame_bitmap *bitmap )
59 {
60 const UINT8 *pMem = memory_region( REGION_CPU1 );
61
62 if( (pMem[0x93]&0x80)==0 )
63 /* Probably wrong; game description indicates that one or both tanks can
64 be invisible; in this game mode, tanks are visible when hit, bumping
65 into a wall, or firing
66 */
67 {
68 drawgfx( bitmap, Machine->gfx[1], /* tank */
69 pMem[0x99]>>3,
70 0,
71 0,0, /* no flip */
72 pMem[0x90]-16,pMem[0x98]-16,
73 &Machine->visible_area,
74 TRANSPARENCY_PEN, 0 );
75
76 drawgfx( bitmap, Machine->gfx[1], /* tank */
77 pMem[0x9b]>>3,
78 1,
79 0,0, /* no flip */
80 pMem[0x92]-16,pMem[0x9a]-16,
81 &Machine->visible_area,
82 TRANSPARENCY_PEN, 0 );
83 }
84
85 drawgfx( bitmap, Machine->gfx[1], /* bullet */
86 (pMem[0x9f]>>3)|0x20,
87 0,
88 0,0, /* no flip */
89 pMem[0x96]-16,pMem[0x9e]-16,
90 &Machine->visible_area,
91 TRANSPARENCY_PEN, 0 );
92
93 drawgfx( bitmap, Machine->gfx[1], /* bullet */
94 (pMem[0x9d]>>3)|0x20,
95 1,
96 0,0, /* no flip */
97 pMem[0x94]-16,pMem[0x9c]-16,
98 &Machine->visible_area,
99 TRANSPARENCY_PEN, 0 );
100 }
101
102
103
104 /*************************************
105 *
106 * Video update
107 *
108 *************************************/
109
WRITE_HANDLER(ultratnk_videoram_w)110 static WRITE_HANDLER( ultratnk_videoram_w )
111 {
112 if (videoram[offset] != data)
113 {
114 videoram[offset] = data;
115 tilemap_mark_tile_dirty(bg_tilemap, offset);
116 }
117 }
118
get_bg_tile_info(int tile_index)119 static void get_bg_tile_info(int tile_index)
120 {
121 int attr = videoram[tile_index];
122 int code = attr & 0x3f;
123 int color = attr >> 6;
124
125 SET_TILE_INFO(0, code, color, 0)
126 }
127
VIDEO_START(ultratnk)128 VIDEO_START( ultratnk )
129 {
130 bg_tilemap = tilemap_create(get_bg_tile_info, tilemap_scan_rows,
131 TILEMAP_OPAQUE, 8, 8, 32, 32);
132
133 if ( !bg_tilemap )
134 return 1;
135
136 return 0;
137 }
138
VIDEO_UPDATE(ultratnk)139 VIDEO_UPDATE( ultratnk )
140 {
141 tilemap_draw(bitmap, &Machine->visible_area, bg_tilemap, 0, 0);
142 ultratnk_draw_sprites(bitmap);
143
144 /* Weird, but we have to update our sound registers here. */
145 discrete_sound_w(2, mirror_ram[0x88] % 16);
146 discrete_sound_w(3, mirror_ram[0x8A] % 16);
147 }
148
149 /*************************************
150 *
151 * Control reading
152 *
153 *************************************/
154
WRITE_HANDLER(da_latch_w)155 static WRITE_HANDLER( da_latch_w )
156 {
157 int joybits = readinputport(4);
158 ultratnk_controls = readinputport(3); /* start and fire buttons */
159
160 switch( data )
161 {
162 case 0x0a:
163 if( joybits&0x08 ) ultratnk_controls &= ~0x40;
164 if( joybits&0x04 ) ultratnk_controls &= ~0x04;
165
166 if( joybits&0x80 ) ultratnk_controls &= ~0x10;
167 if( joybits&0x40 ) ultratnk_controls &= ~0x01;
168 break;
169
170 case 0x05:
171 if( joybits&0x02 ) ultratnk_controls &= ~0x40;
172 if( joybits&0x01 ) ultratnk_controls &= ~0x04;
173
174 if( joybits&0x20 ) ultratnk_controls &= ~0x10;
175 if( joybits&0x10 ) ultratnk_controls &= ~0x01;
176 break;
177 }
178 }
179
180
READ_HANDLER(ultratnk_controls_r)181 static READ_HANDLER( ultratnk_controls_r )
182 {
183 return (ultratnk_controls << offset) & 0x80;
184 }
185
186
READ_HANDLER(ultratnk_barrier_r)187 static READ_HANDLER( ultratnk_barrier_r )
188 {
189 return readinputport(2) & 0x80;
190 }
191
192
READ_HANDLER(ultratnk_coin_r)193 static READ_HANDLER( ultratnk_coin_r )
194 {
195 switch (offset & 0x06)
196 {
197 case 0x00: return (readinputport(2) << 3) & 0x80; /* left coin */
198 case 0x02: return (readinputport(2) << 4) & 0x80; /* right coin */
199 case 0x04: return (readinputport(2) << 1) & 0x80; /* invisible tanks */
200 case 0x06: return (readinputport(2) << 2) & 0x80; /* rebounding shots */
201 }
202
203 return 0;
204 }
205
206
READ_HANDLER(ultratnk_tilt_r)207 static READ_HANDLER( ultratnk_tilt_r )
208 {
209 return (readinputport(2) << 5) & 0x80; /* tilt */
210 }
211
212
READ_HANDLER(ultratnk_dipsw_r)213 static READ_HANDLER( ultratnk_dipsw_r )
214 {
215 int dipsw = readinputport(0);
216 switch( offset )
217 {
218 case 0x00: return ((dipsw & 0xC0) >> 6); /* language? */
219 case 0x01: return ((dipsw & 0x30) >> 4); /* credits */
220 case 0x02: return ((dipsw & 0x0C) >> 2); /* game time */
221 case 0x03: return ((dipsw & 0x03) >> 0); /* extended time */
222 }
223 return 0;
224 }
225
226
227
228 /*************************************
229 *
230 * Sound handlers
231 *
232 *************************************/
WRITE_HANDLER(ultratnk_fire_w)233 WRITE_HANDLER( ultratnk_fire_w )
234 {
235 discrete_sound_w(offset/2, offset&1);
236 }
237
WRITE_HANDLER(ultratnk_attract_w)238 WRITE_HANDLER( ultratnk_attract_w )
239 {
240 discrete_sound_w(5, (data & 1));
241 }
242
WRITE_HANDLER(ultratnk_explosion_w)243 WRITE_HANDLER( ultratnk_explosion_w )
244 {
245 discrete_sound_w(4, data % 16);
246 }
247
248
249
250 /*************************************
251 *
252 * Interrupt generation
253 *
254 *************************************/
255
INTERRUPT_GEN(ultratnk_interrupt)256 static INTERRUPT_GEN( ultratnk_interrupt )
257 {
258 if (readinputport(1) & 0x40 )
259 {
260 /* only do NMI interrupt if not in TEST mode */
261 cpu_set_irq_line(0, IRQ_LINE_NMI, PULSE_LINE);
262 }
263 }
264
265
266
267 /*************************************
268 *
269 * Misc memory handlers
270 *
271 *************************************/
272
READ_HANDLER(ultratnk_collision_r)273 static READ_HANDLER( ultratnk_collision_r )
274 {
275 /** Note: hardware collision detection is not emulated.
276 * However, the game is fully playable, since the game software uses it
277 * only as a hint to check for tanks bumping into walls/mines.
278 */
279 switch( offset )
280 {
281 case 0x01: return 0x80; /* white tank = D7 */
282 case 0x03: return 0x80; /* black tank = D7 */
283 }
284 return 0;
285 }
286
287
WRITE_HANDLER(ultratnk_leds_w)288 static WRITE_HANDLER( ultratnk_leds_w )
289 {
290 set_led_status(offset/2,offset&1);
291 }
292
293
READ_HANDLER(mirror_r)294 static READ_HANDLER( mirror_r )
295 {
296 return mirror_ram[offset];
297 }
298
299
WRITE_HANDLER(mirror_w)300 static WRITE_HANDLER( mirror_w )
301 {
302 mirror_ram[offset] = data;
303 }
304
305
306
307 /*************************************
308 *
309 * Main CPU memory handlers
310 *
311 *************************************/
312
MEMORY_READ_START(readmem)313 static MEMORY_READ_START( readmem )
314 { 0x0000, 0x00ff, MRA_RAM },
315 { 0x0100, 0x01ff, mirror_r },
316 { 0x0800, 0x0bff, MRA_RAM },
317 { 0x0c00, 0x0cff, MRA_RAM },
318 { 0x1000, 0x1000, input_port_1_r }, /* self test, vblank */
319 { 0x1800, 0x1800, ultratnk_barrier_r }, /* barrier */
320 { 0x2000, 0x2007, ultratnk_controls_r },
321 { 0x2020, 0x2026, ultratnk_coin_r },
322 { 0x2040, 0x2043, ultratnk_collision_r },
323 { 0x2046, 0x2046, ultratnk_tilt_r },
324 { 0x2060, 0x2063, ultratnk_dipsw_r },
325 { 0x2800, 0x2fff, MRA_NOP }, /* diagnostic ROM (see code at B1F3) */
326 { 0xb000, 0xbfff, MRA_ROM },
327 { 0xf000, 0xffff, MRA_ROM },
328 MEMORY_END
329
330
331 static MEMORY_WRITE_START( writemem )
332 { 0x0000, 0x00ff, MWA_RAM, &mirror_ram },
333 { 0x0100, 0x01ff, mirror_w },
334 { 0x0800, 0x0bff, ultratnk_videoram_w, &videoram },
335 { 0x0c00, 0x0cff, MWA_RAM }, /* ? */
336 { 0x2000, 0x201f, ultratnk_attract_w }, /* attract */
337 { 0x2020, 0x203f, MWA_NOP }, /* collision reset 1-4, 2020-21=cr1, 22-23=cr2, 24-25=cr3, 26,27=cr4 */
338 { 0x2040, 0x2041, da_latch_w }, /* D/A LATCH */
339 { 0x2042, 0x2043, ultratnk_explosion_w }, /* EXPLOSION (sound) */
340 { 0x2044, 0x2045, MWA_NOP }, /* TIMER (watchdog) RESET */
341 { 0x2066, 0x2067, MWA_NOP }, /* LOCKOUT */
342 { 0x2068, 0x206b, ultratnk_leds_w },
343 { 0x206c, 0x206f, ultratnk_fire_w }, /* fire 1/2 */
344 { 0xb000, 0xbfff, MWA_ROM },
345 { 0xf000, 0xffff, MWA_ROM },
346 MEMORY_END
347
348
349
350 /*************************************
351 *
352 * Port definitions
353 *
354 *************************************/
355
356 INPUT_PORTS_START( ultratnk )
357 PORT_START
358 PORT_DIPNAME( 0x03, 0x01, "Extended Play" )
359 PORT_DIPSETTING( 0x01, "25 Points" )
360 PORT_DIPSETTING( 0x02, "50 Points" )
361 PORT_DIPSETTING( 0x03, "75 Points" )
362 PORT_DIPSETTING( 0x00, "None" )
363 PORT_DIPNAME( 0x0c, 0x04, "Game Length" )
364 PORT_DIPSETTING( 0x00, "60 Seconds" )
365 PORT_DIPSETTING( 0x04, "90 Seconds" )
366 PORT_DIPSETTING( 0x08, "120 Seconds" )
367 PORT_DIPSETTING( 0x0c, "150 Seconds" )
368 PORT_DIPNAME( 0x30, 0x20, DEF_STR( Coinage ) )
369 PORT_DIPSETTING( 0x30, DEF_STR( 2C_1C ) )
370 PORT_DIPSETTING( 0x20, DEF_STR( 1C_1C ) )
371 PORT_DIPSETTING( 0x10, DEF_STR( 1C_2C ) )
372 PORT_DIPSETTING( 0x00, DEF_STR( Free_Play ) )
373 PORT_DIPNAME( 0xc0, 0x00, "Spare" ) /* Language? Doesn't have any effect. */
374 PORT_DIPSETTING( 0x00, "A" )
375 PORT_DIPSETTING( 0x40, "B" )
376 PORT_DIPSETTING( 0x80, "C" )
377 PORT_DIPSETTING( 0xc0, "D" )
378
379 PORT_START
380 PORT_SERVICE( 0x40, IP_ACTIVE_LOW )
381 PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_VBLANK )
382
383 PORT_START /* input#2 (arbitrarily arranged) */
384 PORT_BITX(0x80, IP_ACTIVE_HIGH, IPT_SERVICE1 | IPF_TOGGLE, "Option 1", IP_KEY_DEFAULT, IP_JOY_DEFAULT )
385 PORT_BITX(0x40, IP_ACTIVE_HIGH, IPT_SERVICE2 | IPF_TOGGLE, "Option 2", IP_KEY_DEFAULT, IP_JOY_DEFAULT )
386 PORT_BITX(0x20, IP_ACTIVE_HIGH, IPT_SERVICE3 | IPF_TOGGLE, "Option 3", IP_KEY_DEFAULT, IP_JOY_DEFAULT )
387 PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN1 )
388 PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN2 )
389 PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_TILT )
390
391 PORT_START /* input#3 */
392 PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START1 )
393 PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SPECIAL ) /* joystick (taken from below) */
394 PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START2 )
395 PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_SPECIAL ) /* joystick (taken from below) */
396 PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER1 )
397 PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SPECIAL ) /* joystick (taken from below) */
398 PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER2 )
399 PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SPECIAL ) /* joystick (taken from below) */
400
401 PORT_START /* input#4 - fake */
402 PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_DOWN | IPF_PLAYER1 )
403 PORT_BIT( 0x0a, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_UP | IPF_PLAYER1 ) /* note that this sets 2 bits */
404 PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_DOWN | IPF_PLAYER1 )
405 PORT_BIT( 0x05, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_UP | IPF_PLAYER1 ) /* note that this sets 2 bits */
406 PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_DOWN | IPF_PLAYER2 )
407 PORT_BIT( 0xa0, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_UP | IPF_PLAYER2 ) /* note that this sets 2 bits */
408 PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_DOWN | IPF_PLAYER2 )
409 PORT_BIT( 0x50, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_UP | IPF_PLAYER2 ) /* note that this sets 2 bits */
410 PORT_START /* 5 */
411 PORT_ADJUSTER( 5, "Motor 1 RPM" )
412
413 PORT_START /* 6 */
414 PORT_ADJUSTER( 10, "Motor 2 RPM" )
415 INPUT_PORTS_END
416
417
418
419 /*************************************
420 *
421 * Graphics definitions
422 *
423 *************************************/
424
425 static struct GfxLayout playfield_layout =
426 {
427 8,8,
428 RGN_FRAC(1,2),
429 1,
430 { 0 },
431 { 4, 5, 6, 7, 4 + RGN_FRAC(1,2), 5 + RGN_FRAC(1,2), 6 + RGN_FRAC(1,2), 7 + RGN_FRAC(1,2) },
432 { 0, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
433 8*8
434 };
435
436
437 static struct GfxLayout motion_layout =
438 {
439 16,16,
440 RGN_FRAC(1,4),
441 1,
442 { 0 },
443 { 7, 6, 5, 4, 7 + RGN_FRAC(1,4), 6 + RGN_FRAC(1,4), 5 + RGN_FRAC(1,4), 4 + RGN_FRAC(1,4),
444 7 + RGN_FRAC(2,4), 6 + RGN_FRAC(2,4), 5 + RGN_FRAC(2,4), 4 + RGN_FRAC(2,4),
445 7 + RGN_FRAC(3,4), 6 + RGN_FRAC(3,4), 5 + RGN_FRAC(3,4), 4 + RGN_FRAC(3,4) },
446 { 0, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8,
447 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8 },
448 16*8
449 };
450
451
452 static struct GfxDecodeInfo gfxdecodeinfo[] =
453 {
454 { REGION_GFX1, 0, &playfield_layout, 0, 4 }, /* playfield graphics */
455 { REGION_GFX2, 0, &motion_layout, 0, 4 }, /* motion graphics */
456 { -1 }
457 };
458
459
460 /************************************************************************/
461 /* ultratnk Sound System Analog emulation */
462 /************************************************************************/
463
464 const struct discrete_lfsr_desc ultratnk_lfsr={
465 16, /* Bit Length */
466 0, /* Reset Value */
467 0, /* Use Bit 0 as XOR input 0 */
468 14, /* Use Bit 14 as XOR input 1 */
469 DISC_LFSR_XNOR, /* Feedback stage1 is XNOR */
470 DISC_LFSR_OR, /* Feedback stage2 is just stage 1 output OR with external feed */
471 DISC_LFSR_REPLACE, /* Feedback stage3 replaces the shifted register contents */
472 0x000001, /* Everything is shifted into the first bit only */
473 0, /* Output is not inverted */
474 15 /* Output bit */
475 };
476
477 /* Nodes - Inputs */
478 #define ULTRATNK_MOTORSND1_DATA NODE_01
479 #define ULTRATNK_MOTORSND2_DATA NODE_02
480 #define ULTRATNK_FIRESND1_EN NODE_03
481 #define ULTRATNK_FIRESND2_EN NODE_04
482 #define ULTRATNK_EXPLOSIONSND_DATA NODE_05
483 #define ULTRATNK_ATTRACT_EN NODE_06
484 /* Nodes - Sounds */
485 #define ULTRATNK_MOTORSND1 NODE_10
486 #define ULTRATNK_MOTORSND2 NODE_11
487 #define ULTRATNK_EXPLOSIONSND NODE_12
488 #define ULTRATNK_FIRESND1 NODE_13
489 #define ULTRATNK_FIRESND2 NODE_14
490 #define ULTRATNK_NOISE NODE_15
491 #define ULTRATNK_FINAL_MIX NODE_16
492
493 static DISCRETE_SOUND_START(ultratnk_sound_interface)
494 /************************************************/
495 /* Ultratnk sound system: 5 Sound Sources */
496 /* Relative Volume */
497 /* 1/2) Motor 77.72% */
498 /* 2) Explosion 100.00% */
499 /* 4/5) Fire 29.89% */
500 /* Relative volumes calculated from resitor */
501 /* network in combiner circuit */
502 /* */
503 /* Discrete sound mapping via: */
504 /* discrete_sound_w($register,value) */
505 /* $00 - Fire enable Tank 1 */
506 /* $01 - Fire enable Tank 2 */
507 /* $02 - Motorsound frequency Tank 1 */
508 /* $03 - Motorsound frequency Tank 2 */
509 /* $04 - Explode volume */
510 /* $05 - Attract */
511 /* */
512 /************************************************/
513
514 /************************************************/
515 /* Input register mapping for ultratnk */
516 /************************************************/
517 /* NODE ADDR MASK GAIN OFFSET INIT */
518 DISCRETE_INPUT (ULTRATNK_FIRESND1_EN , 0x00, 0x000f, 0.0)
519 DISCRETE_INPUT (ULTRATNK_FIRESND2_EN , 0x01, 0x000f, 0.0)
520 DISCRETE_INPUTX(ULTRATNK_MOTORSND1_DATA , 0x02, 0x000f, -1.0 , 15.0, 0.0)
521 DISCRETE_INPUTX(ULTRATNK_MOTORSND2_DATA , 0x03, 0x000f, -1.0 , 15.0, 0.0)
522 DISCRETE_INPUTX(ULTRATNK_EXPLOSIONSND_DATA , 0x04, 0x000f, 1000.0/15.0, 0, 0.0)
523 DISCRETE_INPUT (ULTRATNK_ATTRACT_EN , 0x05, 0x000f, 0.0)
524
525 /************************************************/
526 /* Motor sound circuit is based on a 556 VCO */
527 /* with the input frequency set by the MotorSND */
528 /* latch (4 bit). This freqency is then used to */
529 /* driver a modulo 12 counter, with div6, 4 & 3 */
530 /* summed as the output of the circuit. */
531 /* VCO Output is Sq wave = 27-382Hz */
532 /* F1 freq - (Div6) */
533 /* F2 freq = (Div4) */
534 /* F3 freq = (Div3) 33.3% duty, 33.3 deg phase */
535 /* To generate the frequency we take the freq. */
536 /* diff. and /15 to get all the steps between */
537 /* 0 - 15. Then add the low frequency and send */
538 /* that value to a squarewave generator. */
539 /* Also as the frequency changes, it ramps due */
540 /* to a 2.2uf capacitor on the R-ladder. */
541 /* Note the VCO freq. is controlled by a 250k */
542 /* pot. The freq. used here is for the pot set */
543 /* to 125k. The low freq is allways the same. */
544 /* This adjusts the high end. */
545 /* 0k = 214Hz. 250k = 4416Hz */
546 /************************************************/
547 DISCRETE_RCFILTER(NODE_20, 1, ULTRATNK_MOTORSND1_DATA, 123000, 2.2e-6)
548 DISCRETE_ADJUSTMENT(NODE_21, 1, (214.0-27.0)/12/15, (4416.0-27.0)/12/15, DISC_LOGADJ, 5)
549 DISCRETE_MULTIPLY(NODE_22, 1, NODE_20, NODE_21)
550
551 DISCRETE_MULTADD(NODE_23, 1, NODE_22, 2, 27.0/6) /* F1 = /12*2 = /6 */
552 DISCRETE_SQUAREWAVE(NODE_24, 1, NODE_23, (777.2/3), 50.0, 0, 0)
553 DISCRETE_RCFILTER(NODE_25, 1, NODE_24, 10000, 1e-7)
554
555 DISCRETE_MULTADD(NODE_26, 1, NODE_22, 3, 27.0/4) /* F2 = /12*3 = /4 */
556 DISCRETE_SQUAREWAVE(NODE_27, 1, NODE_26, (777.2/3), 50.0, 0, 0)
557 DISCRETE_RCFILTER(NODE_28, 1, NODE_27, 10000, 1e-7)
558
559 DISCRETE_MULTADD(NODE_29, 1, NODE_22, 4, 27.0/3) /* F3 = /12*4 = /3 */
560 DISCRETE_SQUAREWAVE(NODE_30, 1, NODE_29, (777.2/3), 100.0/3, 0, 360.0/3)
561 DISCRETE_RCFILTER(NODE_31, 1, NODE_30, 10000, 1e-7)
562
563 DISCRETE_ADDER3(ULTRATNK_MOTORSND1, ULTRATNK_ATTRACT_EN, NODE_25, NODE_28, NODE_31)
564
565 /************************************************/
566 /* Tank2 motor sound is basically the same as */
567 /* Tank1. But I shifted the frequencies up for */
568 /* it to sound different from Tank1. */
569 /************************************************/
570 DISCRETE_RCFILTER(NODE_40, 1, ULTRATNK_MOTORSND2_DATA, 123000, 2.2e-6)
571 DISCRETE_ADJUSTMENT(NODE_41, 1, (214.0-27.0)/12/15, (4416.0-27.0)/12/15, DISC_LOGADJ, 6)
572 DISCRETE_MULTIPLY(NODE_42, 1, NODE_40, NODE_41)
573
574 DISCRETE_MULTADD(NODE_43, 1, NODE_42, 2, 27.0/6) /* F1 = /12*2 = /6 */
575 DISCRETE_SQUAREWAVE(NODE_44, 1, NODE_43, (777.2/3), 50.0, 0, 0)
576 DISCRETE_RCFILTER(NODE_45, 1, NODE_44, 10000, 1e-7)
577
578 DISCRETE_MULTADD(NODE_46, 1, NODE_42, 3, 27.0/4) /* F2 = /12*3 = /4 */
579 DISCRETE_SQUAREWAVE(NODE_47, 1, NODE_46, (777.2/3), 50.0, 0, 0)
580 DISCRETE_RCFILTER(NODE_48, 1, NODE_47, 10000, 1e-7)
581
582 DISCRETE_MULTADD(NODE_49, 1, NODE_42, 4, 27.0/3) /* F3 = /12*4 = /3 */
583 DISCRETE_SQUAREWAVE(NODE_50, 1, NODE_49, (777.2/3), 100.0/3, 0, 360.0/3)
584 DISCRETE_RCFILTER(NODE_51, 1, NODE_50, 10000, 1e-7)
585
586 DISCRETE_ADDER3(ULTRATNK_MOTORSND2, ULTRATNK_ATTRACT_EN, NODE_45, NODE_48, NODE_51)
587
588 /************************************************/
589 /* Explosion circuit is built around a noise */
590 /* generator built from 2 shift registers that */
591 /* are clocked by the 2V signal. */
592 /* 2V = HSYNC/4 */
593 /* = 15750/4 */
594 /* Output is binary weighted with 4 bits of */
595 /* crash volume. */
596 /************************************************/
597 DISCRETE_LFSR_NOISE(ULTRATNK_NOISE, ULTRATNK_ATTRACT_EN, ULTRATNK_ATTRACT_EN, 15750.0/4, 1.0, 0, 0, &ultratnk_lfsr)
598
599 DISCRETE_MULTIPLY(NODE_60, 1, ULTRATNK_NOISE, ULTRATNK_EXPLOSIONSND_DATA)
600 DISCRETE_RCFILTER(ULTRATNK_EXPLOSIONSND, 1, NODE_60, 545, 1e-7)
601
602 /************************************************/
603 /* Fire circuits takes the noise output from */
604 /* the crash circuit and applies +ve feedback */
605 /* to cause oscillation. There is also an RC */
606 /* filter on the input to the feedback circuit. */
607 /* RC is 1K & 10uF */
608 /* Feedback cct is modelled by using the RC out */
609 /* as the frequency input on a VCO, */
610 /* breadboarded freq range as: */
611 /* 0 = 940Hz, 34% duty */
612 /* 1 = 630Hz, 29% duty */
613 /* the duty variance is so small we ignore it */
614 /************************************************/
615 DISCRETE_INVERT(NODE_70, ULTRATNK_NOISE)
616 DISCRETE_MULTADD(NODE_71, 1, NODE_70, 940.0-630.0, ((940.0-630.0)/2)+630.0)
617 DISCRETE_RCFILTER(NODE_72, 1, NODE_71, 1000, 1e-5)
618 DISCRETE_SQUAREWAVE(NODE_73, 1, NODE_72, 407.8, 31.5, 0, 0.0)
619 DISCRETE_ONOFF(ULTRATNK_FIRESND1, ULTRATNK_FIRESND1_EN, NODE_73)
620 DISCRETE_ONOFF(ULTRATNK_FIRESND2, ULTRATNK_FIRESND2_EN, NODE_73)
621
622 /************************************************/
623 /* Combine all 5 sound sources. */
624 /* Add some final gain to get to a good sound */
625 /* level. */
626 /************************************************/
627 DISCRETE_ADDER3(NODE_90, 1, ULTRATNK_MOTORSND1, ULTRATNK_EXPLOSIONSND, ULTRATNK_FIRESND1)
628 DISCRETE_ADDER3(NODE_91, 1, NODE_90, ULTRATNK_MOTORSND2, ULTRATNK_FIRESND2)
629 DISCRETE_GAIN(ULTRATNK_FINAL_MIX, NODE_91, 65534.0/(777.2+777.2+1000.0+298.9+298.9))
630
631 DISCRETE_OUTPUT(ULTRATNK_FINAL_MIX, 100)
632 DISCRETE_SOUND_END
633
634
635
636 /*************************************
637 *
638 * Machine driver
639 *
640 *************************************/
641
642 static MACHINE_DRIVER_START( ultratnk )
643
644 /* basic machine hardware */
645 MDRV_CPU_ADD(M6502,1500000)
646 MDRV_CPU_MEMORY(readmem,writemem)
647 MDRV_CPU_VBLANK_INT(ultratnk_interrupt,4)
648
649 MDRV_FRAMES_PER_SECOND(60)
650 MDRV_VBLANK_DURATION(DEFAULT_REAL_60HZ_VBLANK_DURATION)
651
652 /* video hardware */
653 MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER)
654 MDRV_SCREEN_SIZE(32*8, 32*8)
655 MDRV_VISIBLE_AREA(0*8, 32*8-1, 0*8, 28*8-1)
656 MDRV_GFXDECODE(gfxdecodeinfo)
657 MDRV_PALETTE_LENGTH(4)
658 MDRV_COLORTABLE_LENGTH(sizeof(colortable_source)/sizeof(unsigned short))
659
660 MDRV_PALETTE_INIT(ultratnk)
661 MDRV_VIDEO_START(ultratnk)
662 MDRV_VIDEO_UPDATE(ultratnk)
663
664 /* sound hardware */
665 MDRV_SOUND_ADD_TAG("discrete", DISCRETE, ultratnk_sound_interface)
666 MACHINE_DRIVER_END
667
668
669
670 /*************************************
671 *
672 * ROM definitions
673 *
674 *************************************/
675
676 ROM_START( ultratnk )
677 ROM_REGION( 0x12000, REGION_CPU1, 0 )
678 ROM_LOAD_NIB_LOW ( "030180.n1", 0xb000, 0x0800, CRC(b6aa6056) SHA1(6de094017b5d87a238053fac88129d20260f8222) ) /* ROM 3 D0-D3 */
679 ROM_LOAD_NIB_HIGH( "030181.k1", 0xb000, 0x0800, CRC(17145c97) SHA1(afe0c9c562c27cd1fba57ea83377b0a4c12496db) ) /* ROM 3 D4-D7 */
680 ROM_LOAD_NIB_LOW ( "030182.m1", 0xb800, 0x0800, CRC(034366a2) SHA1(dc289ce4c79e9937977ca8804ce07b4c8e40e969) ) /* ROM 4 D0-D3 */
681 ROM_RELOAD( 0xf800, 0x0800 ) /* for 6502 vectors */
682 ROM_LOAD_NIB_HIGH( "030183.l1", 0xb800, 0x0800, CRC(be141602) SHA1(17aad9bab9bf6bd22dc3c2214b049bbd68c87380) ) /* ROM 4 D4-D7 */
683 ROM_RELOAD( 0xf800, 0x0800 ) /* for 6502 vectors */
684
685 ROM_REGION( 0x0400, REGION_GFX1, ROMREGION_DISPOSE )
686 ROM_LOAD( "30172-01.j6", 0x0000, 0x0200, CRC(1d364b23) SHA1(44c5792ed3f33f40cd8632718b0e82152559ecdf) )
687 ROM_LOAD( "30173-01.h6", 0x0200, 0x0200, CRC(5c32f331) SHA1(c1d675891490fbc533eaa0da57545398d7325df8) )
688
689 ROM_REGION( 0x1000, REGION_GFX2, ROMREGION_DISPOSE )
690 ROM_LOAD( "30174-01.n6", 0x0000, 0x0400, CRC(d0e20e73) SHA1(0df1ed4a73255032bb809fb4d0a4bf3f151c749d) )
691 ROM_LOAD( "30175-01.m6", 0x0400, 0x0400, CRC(a47459c9) SHA1(4ca92edc172fbac923ba71731a25546c04ffc7b0) )
692 ROM_LOAD( "30176-01.l6", 0x0800, 0x0400, CRC(1cc7c2dd) SHA1(7f8aebe8375751183afeae35ea2d241d22ee7a4f) )
693 ROM_LOAD( "30177-01.k6", 0x0c00, 0x0400, CRC(3a91b09f) SHA1(1e713cb612eb7d78fc4a003e4e60308f62e0b169) )
694 ROM_END
695
696
697
698 /*************************************
699 *
700 * Game drivers
701 *
702 *************************************/
703
704 GAME( 1978, ultratnk, 0, ultratnk, ultratnk, 0, 0, "Atari", "Ultra Tank" )
705