1 /***************************************************************************
2 
3 	Atari Basketball hardware
4 
5 	driver by Mike Balfour
6 
7 	Games supported:
8 		* Basketball
9 
10 	Known issues:
11 		* none at this time
12 
13 ****************************************************************************
14 
15 	Note:  The original hardware uses the Player 1 and Player 2 Start buttons
16 	as the Jump/Shoot buttons.	I've taken button 1 and mapped it to the Start
17 	buttons to keep people from getting confused.
18 
19 	If you have any questions about how this driver works, don't hesitate to
20 	ask.  - Mike Balfour (mab22@po.cwru.edu)
21 
22 ***************************************************************************/
23 
24 #include "driver.h"
25 #include "vidhrdw/generic.h"
26 
27 extern UINT8 *bsktball_motion;
28 
29 extern WRITE_HANDLER( bsktball_videoram_w );
30 
31 extern VIDEO_START( bsktball );
32 extern VIDEO_UPDATE( bsktball );
33 
34 extern WRITE_HANDLER( bsktball_nmion_w );
35 extern INTERRUPT_GEN( bsktball_interrupt );
36 extern WRITE_HANDLER( bsktball_ld1_w );
37 extern WRITE_HANDLER( bsktball_ld2_w );
38 extern READ_HANDLER( bsktball_in0_r );
39 extern WRITE_HANDLER( bsktball_led1_w );
40 extern WRITE_HANDLER( bsktball_led2_w );
41 extern WRITE_HANDLER( bsktball_bounce_w );
42 extern WRITE_HANDLER( bsktball_note_w );
43 extern WRITE_HANDLER( bsktball_noise_reset_w );
44 
45 /*************************************
46  *
47  *	Palette generation
48  *
49  *************************************/
50 
51 static unsigned short colortable_source[] =
52 {
53 	/* Playfield */
54 	0x01, 0x00, 0x00, 0x00,
55 	0x01, 0x03, 0x03, 0x03,
56 
57 	/* Motion */
58 	0x01, 0x00, 0x00, 0x00,
59 	0x01, 0x00, 0x01, 0x00,
60 	0x01, 0x00, 0x02, 0x00,
61 	0x01, 0x00, 0x03, 0x00,
62 
63 	0x01, 0x01, 0x00, 0x00,
64 	0x01, 0x01, 0x01, 0x00,
65 	0x01, 0x01, 0x02, 0x00,
66 	0x01, 0x01, 0x03, 0x00,
67 
68 	0x01, 0x02, 0x00, 0x00,
69 	0x01, 0x02, 0x01, 0x00,
70 	0x01, 0x02, 0x02, 0x00,
71 	0x01, 0x02, 0x03, 0x00,
72 
73 	0x01, 0x03, 0x00, 0x00,
74 	0x01, 0x03, 0x01, 0x00,
75 	0x01, 0x03, 0x02, 0x00,
76 	0x01, 0x03, 0x03, 0x00,
77 
78 	0x01, 0x00, 0x00, 0x01,
79 	0x01, 0x00, 0x01, 0x01,
80 	0x01, 0x00, 0x02, 0x01,
81 	0x01, 0x00, 0x03, 0x01,
82 
83 	0x01, 0x01, 0x00, 0x01,
84 	0x01, 0x01, 0x01, 0x01,
85 	0x01, 0x01, 0x02, 0x01,
86 	0x01, 0x01, 0x03, 0x01,
87 
88 	0x01, 0x02, 0x00, 0x01,
89 	0x01, 0x02, 0x01, 0x01,
90 	0x01, 0x02, 0x02, 0x01,
91 	0x01, 0x02, 0x03, 0x01,
92 
93 	0x01, 0x03, 0x00, 0x01,
94 	0x01, 0x03, 0x01, 0x01,
95 	0x01, 0x03, 0x02, 0x01,
96 	0x01, 0x03, 0x03, 0x01,
97 
98 	0x01, 0x00, 0x00, 0x02,
99 	0x01, 0x00, 0x01, 0x02,
100 	0x01, 0x00, 0x02, 0x02,
101 	0x01, 0x00, 0x03, 0x02,
102 
103 	0x01, 0x01, 0x00, 0x02,
104 	0x01, 0x01, 0x01, 0x02,
105 	0x01, 0x01, 0x02, 0x02,
106 	0x01, 0x01, 0x03, 0x02,
107 
108 	0x01, 0x02, 0x00, 0x02,
109 	0x01, 0x02, 0x01, 0x02,
110 	0x01, 0x02, 0x02, 0x02,
111 	0x01, 0x02, 0x03, 0x02,
112 
113 	0x01, 0x03, 0x00, 0x02,
114 	0x01, 0x03, 0x01, 0x02,
115 	0x01, 0x03, 0x02, 0x02,
116 	0x01, 0x03, 0x03, 0x02,
117 
118 	0x01, 0x00, 0x00, 0x03,
119 	0x01, 0x00, 0x01, 0x03,
120 	0x01, 0x00, 0x02, 0x03,
121 	0x01, 0x00, 0x03, 0x03,
122 
123 	0x01, 0x01, 0x00, 0x03,
124 	0x01, 0x01, 0x01, 0x03,
125 	0x01, 0x01, 0x02, 0x03,
126 	0x01, 0x01, 0x03, 0x03,
127 
128 	0x01, 0x02, 0x00, 0x03,
129 	0x01, 0x02, 0x01, 0x03,
130 	0x01, 0x02, 0x02, 0x03,
131 	0x01, 0x02, 0x03, 0x03,
132 
133 	0x01, 0x03, 0x00, 0x03,
134 	0x01, 0x03, 0x01, 0x03,
135 	0x01, 0x03, 0x02, 0x03,
136 	0x01, 0x03, 0x03, 0x03,
137 };
138 
PALETTE_INIT(bsktball)139 static PALETTE_INIT( bsktball )
140 {
141 	palette_set_color(0,0x00,0x00,0x00); /* BLACK */
142 	palette_set_color(1,0x80,0x80,0x80); /* LIGHT GREY */
143 	palette_set_color(2,0x50,0x50,0x50); /* DARK GREY */
144 	palette_set_color(3,0xff,0xff,0xff); /* WHITE */
145 	memcpy(colortable,colortable_source,sizeof(colortable_source));
146 }
147 
148 
149 
150 /*************************************
151  *
152  *	Main CPU memory handlers
153  *
154  *************************************/
155 
MEMORY_READ_START(readmem)156 static MEMORY_READ_START( readmem )
157 	{ 0x0000, 0x01ff, MRA_RAM }, /* Zero Page RAM */
158 	{ 0x0800, 0x0800, bsktball_in0_r },
159 	{ 0x0802, 0x0802, input_port_5_r },
160 	{ 0x0803, 0x0803, input_port_6_r },
161 	{ 0x1800, 0x1cff, MRA_RAM }, /* video ram */
162 	{ 0x2000, 0x3fff, MRA_ROM }, /* PROGRAM */
163 	{ 0xfff0, 0xffff, MRA_ROM }, /* PROM8 for 6502 vectors */
164 MEMORY_END
165 
166 
167 static MEMORY_WRITE_START( writemem )
168 	{ 0x0000, 0x01ff, MWA_RAM }, /* WRAM */
169 	{ 0x1000, 0x1000, MWA_NOP }, /* Timer Reset */
170 	{ 0x1010, 0x1010, bsktball_bounce_w }, /* Crowd Amp / Bounce */
171 	{ 0x1022, 0x1023, MWA_NOP }, /* Coin Counter */
172 	{ 0x1024, 0x1025, bsktball_led1_w }, /* LED 1 */
173 	{ 0x1026, 0x1027, bsktball_led2_w }, /* LED 2 */
174 	{ 0x1028, 0x1029, bsktball_ld1_w }, /* LD 1 */
175 	{ 0x102a, 0x102b, bsktball_ld2_w }, /* LD 2 */
176 	{ 0x102c, 0x102d, bsktball_noise_reset_w }, /* Noise Reset */
177 	{ 0x102e, 0x102f, bsktball_nmion_w }, /* NMI On */
178 	{ 0x1030, 0x1030, bsktball_note_w }, /* Music Ckt Note Dvsr */
179 	{ 0x1800, 0x1bbf, bsktball_videoram_w, &videoram }, /* DISPLAY */
180 	{ 0x1bc0, 0x1bff, MWA_RAM, &bsktball_motion },
181 	{ 0x2000, 0x3fff, MWA_ROM }, /* PROM1-PROM8 */
182 MEMORY_END
183 
184 
185 
186 /*************************************
187  *
188  *	Port definitions
189  *
190  *************************************/
191 
192 INPUT_PORTS_START( bsktball )
193 	PORT_START	/* IN0 */
194 	PORT_ANALOG( 0xFF, 0x00, IPT_TRACKBALL_X, 100, 10, 0, 0 ) /* Sensitivity, clip, min, max */
195 
196 	PORT_START	/* IN0 */
197 	PORT_ANALOG( 0xFF, 0x00, IPT_TRACKBALL_Y, 100, 10, 0, 0 )
198 
199 	PORT_START	/* IN0 */
200 	PORT_ANALOG( 0xFF, 0x00, IPT_TRACKBALL_X | IPF_PLAYER2, 100, 10, 0, 0 ) /* Sensitivity, clip, min, max */
201 
202 	PORT_START	/* IN0 */
203 	PORT_ANALOG( 0xFF, 0x00, IPT_TRACKBALL_Y | IPF_PLAYER2, 100, 10, 0, 0 )
204 
205 	PORT_START		/* IN0 */
206 	PORT_BIT ( 0x01, IP_ACTIVE_LOW, IPT_START1 )
207 	PORT_BIT ( 0x02, IP_ACTIVE_LOW, IPT_START2 )
208 	PORT_BIT ( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) /* SPARE */
209 	PORT_BIT ( 0x08, IP_ACTIVE_LOW, IPT_BUTTON1 | IPF_PLAYER2 ) /* SPARE */
210 	/* 0x10 - DR0 = PL2 H DIR */
211 	/* 0x20 - DR1 = PL2 V DIR */
212 	/* 0x40 - DR2 = PL1 H DIR */
213 	/* 0x80 - DR3 = PL1 V DIR */
214 
215 	PORT_START		/* IN2 */
216 	PORT_BIT ( 0x01, IP_ACTIVE_HIGH, IPT_VBLANK )
217 	PORT_BIT ( 0x02, IP_ACTIVE_LOW, IPT_TILT )
218 	PORT_BIT ( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* SPARE */
219 	PORT_BIT ( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* TEST STEP */
220 	PORT_SERVICE( 0x10, IP_ACTIVE_LOW )
221 	PORT_BIT ( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* COIN 0 */
222 	PORT_BIT ( 0x40, IP_ACTIVE_LOW, IPT_COIN2 ) /* COIN 1 */
223 	PORT_BIT ( 0x80, IP_ACTIVE_LOW, IPT_COIN1 ) /* COIN 2 */
224 
225 	PORT_START		/* DSW */
226 	PORT_DIPNAME( 0x07, 0x00, "Play Time per Credit" )
227 	PORT_DIPSETTING(	0x07, DEF_STR( Free_Play ) )
228 	PORT_DIPSETTING(	0x06, "2:30" )
229 	PORT_DIPSETTING(	0x05, "2:00" )
230 	PORT_DIPSETTING(	0x04, "1:30" )
231 	PORT_DIPSETTING(	0x03, "1:15" )
232 	PORT_DIPSETTING(	0x02, "0:45" )
233 	PORT_DIPSETTING(	0x01, "0:30" )
234 	PORT_DIPSETTING(	0x00, "1:00" )
235 	PORT_DIPNAME( 0x18, 0x00, DEF_STR( Coinage ) )
236 	PORT_DIPSETTING(	0x00, DEF_STR( 1C_1C ) )
237 	PORT_DIPSETTING(	0x10, DEF_STR( 1C_4C ) )
238 	PORT_DIPSETTING(	0x08, DEF_STR( 1C_5C ) )
239 	PORT_DIPSETTING(	0x18, DEF_STR( 1C_6C ) )
240 	PORT_DIPNAME( 0x20, 0x00, "Cost" )
241 	PORT_DIPSETTING(	0x20, "Two Coin Minimum" )
242 	PORT_DIPSETTING(	0x00, "One Coin Minimum" )
243 	PORT_DIPNAME( 0xC0, 0x00, "Language" )
244 	PORT_DIPSETTING(	0xC0, "German" )
245 	PORT_DIPSETTING(	0x80, "French" )
246 	PORT_DIPSETTING(	0x40, "Spanish" )
247 	PORT_DIPSETTING(	0x00, "English" )
248 INPUT_PORTS_END
249 
250 
251 
252 /*************************************
253  *
254  *	Graphics layouts
255  *
256  *************************************/
257 
258 static struct GfxLayout charlayout =
259 {
260 	8,8,
261 	64,
262 	2,
263 	{ 0, 8*0x800 },
264 	{ 0, 1, 2, 3, 4, 5, 6, 7 },
265 	{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
266 	8*8
267 };
268 
269 
270 static struct GfxLayout motionlayout =
271 {
272 	8,32,
273 	64,
274 	2,
275 	{ 0, 8*0x800 },
276 	{ 0, 1, 2, 3, 4, 5, 6, 7 },
277 	{	0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8,
278 		8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8,
279 		16*8, 17*8, 18*8, 19*8, 20*8, 21*8, 22*8, 23*8,
280 		24*8, 25*8, 26*8, 27*8, 28*8, 29*8, 30*8, 31*8 },
281 	32*8
282 };
283 
284 
285 static struct GfxDecodeInfo gfxdecodeinfo[] =
286 {
287 	{ REGION_GFX1, 0x0600, &charlayout,   0x00, 0x02 },
288 	{ REGION_GFX1, 0x0000, &motionlayout, 0x08, 0x40 },
289 	{ -1 }
290 };
291 
292 
293 /************************************************************************/
294 /* bsktball Sound System Analog emulation                               */
295 /************************************************************************/
296 
297 const struct discrete_lfsr_desc bsktball_lfsr={
298 	16,			/* Bit Length */
299 	0,			/* Reset Value */
300 	0,			/* Use Bit 0 as XOR input 0 */
301 	14,			/* Use Bit 14 as XOR input 1 */
302 	DISC_LFSR_XNOR,		/* Feedback stage1 is XNOR */
303 	DISC_LFSR_OR,		/* Feedback stage2 is just stage 1 output OR with external feed */
304 	DISC_LFSR_REPLACE,	/* Feedback stage3 replaces the shifted register contents */
305 	0x000001,		/* Everything is shifted into the first bit only */
306 	0,			/* Output is already inverted by XNOR */
307 	15			/* Output bit */
308 };
309 
310 /* Nodes - Inputs */
311 #define BSKTBALL_NOTE_DATA		NODE_01
312 #define BSKTBALL_CROWD_DATA		NODE_02
313 #define BSKTBALL_NOISE_EN		NODE_03
314 #define BSKTBALL_BOUNCE_EN		NODE_04
315 /* Nodes - Sounds */
316 #define BSKTBALL_NOISE			NODE_10
317 #define BSKTBALL_BOUNCE_SND		NODE_11
318 #define BSKTBALL_NOTE_SND		NODE_12
319 #define BSKTBALL_CROWD_SND		NODE_13
320 
321 static DISCRETE_SOUND_START(bsktball_sound_interface)
322 	/************************************************/
323 	/* bsktball  Effects Relataive Gain Table       */
324 	/*                                              */
325 	/* Effect       V-ampIn   Gain ratio  Relative  */
326 	/* Note          3.8      47/47        1000.0   */
327 	/* Bounce        3.8      47/47        1000.0   */
328 	/* Crowd         3.8      47/220        213.6   */
329 	/************************************************/
330 
331 	/************************************************/
332 	/* Input register mapping for bsktball          */
333 	/************************************************/
334 	/*              NODE                 ADDR  MASK    GAIN     OFFSET  INIT */
335 	DISCRETE_INPUT (BSKTBALL_NOTE_DATA,  0x00, 0x000f,                  0.0)
336 	DISCRETE_INPUTX(BSKTBALL_CROWD_DATA, 0x01, 0x000f, 213.6/15, 0,     0.0)
337 	DISCRETE_INPUTX(BSKTBALL_BOUNCE_EN,  0x02, 0x000f, 1000.0/2, 0,     0.0)
338 	DISCRETE_INPUT (BSKTBALL_NOISE_EN,   0x03, 0x000f,                  0.0)
339 
340 	/************************************************/
341 	/* Bounce is a trigger fed directly to the amp  */
342 	/************************************************/
343 	DISCRETE_FILTER2(BSKTBALL_BOUNCE_SND, 1, BSKTBALL_BOUNCE_EN, 10.0, 5, DISC_FILTER_HIGHPASS)	/* remove DC*/
344 
345 	/************************************************/
346 	/* Crowd effect is variable amplitude, filtered */
347 	/* random noise.                                */
348 	/* LFSR clk = 256H = 15750.0Hz                  */
349 	/************************************************/
350 	DISCRETE_LFSR_NOISE(BSKTBALL_NOISE, BSKTBALL_NOISE_EN, BSKTBALL_NOISE_EN, 15750.0, BSKTBALL_CROWD_DATA, 0, 0, &bsktball_lfsr)
351 	DISCRETE_FILTER2(BSKTBALL_CROWD_SND, 1, BSKTBALL_NOISE, 330.0, (1.0 / 7.6), DISC_FILTER_BANDPASS)
352 
353 	/************************************************/
354 	/* Note sound is created by a divider circuit.  */
355 	/* The master clock is the 32H signal, which is */
356 	/* 12.096MHz/128.  This is then sent to a       */
357 	/* preloadable 8 bit counter, which loads the   */
358 	/* value from OUT30 when overflowing from 0xFF  */
359 	/* to 0x00.  Therefore it divides by 2 (OUT30   */
360 	/* = FE) to 256 (OUT30 = 00).                   */
361 	/* There is also a final /2 stage.              */
362 	/* Note that there is no music disable line.    */
363 	/* When there is no music, the game sets the    */
364 	/* oscillator to 0Hz.  (OUT30 = FF)             */
365 	/************************************************/
366 	DISCRETE_ADDER2(NODE_20, 1, BSKTBALL_NOTE_DATA, 1)	/* To get values of 1 - 256 */
367 	DISCRETE_DIVIDE(NODE_21, 1, 12096000.0/128/2, NODE_20)
368 	DISCRETE_SQUAREWAVE(BSKTBALL_NOTE_SND, BSKTBALL_NOTE_DATA, NODE_21, 1000, 50.0, 0, 0.0)	/* NOTE=FF Disables audio */
369 
370 	DISCRETE_ADDER3(NODE_90, 1, BSKTBALL_BOUNCE_SND, BSKTBALL_NOTE_SND, BSKTBALL_CROWD_SND)
371 	DISCRETE_GAIN(NODE_91, NODE_90, 65534.0/(1000.0+1000.0+213.6))
372 	DISCRETE_OUTPUT(NODE_91, 100)
373 DISCRETE_SOUND_END
374 
375 
376 /*************************************
377  *
378  *	Machine driver
379  *
380  *************************************/
381 
382 static MACHINE_DRIVER_START( bsktball )
383 
384 	/* basic machine hardware */
385 	MDRV_CPU_ADD(M6502,750000)
386 	MDRV_CPU_MEMORY(readmem,writemem)
387 	MDRV_CPU_VBLANK_INT(bsktball_interrupt,8)
388 
389 	MDRV_FRAMES_PER_SECOND(60)
390 	MDRV_VBLANK_DURATION(DEFAULT_REAL_60HZ_VBLANK_DURATION)
391 
392 	/* video hardware */
393 	MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER)
394 	MDRV_SCREEN_SIZE(32*8, 28*8)
395 	MDRV_VISIBLE_AREA(0*8, 32*8-1, 0*8, 28*8-1)
396 	MDRV_GFXDECODE(gfxdecodeinfo)
397 	MDRV_PALETTE_LENGTH(4)
398 	MDRV_COLORTABLE_LENGTH(sizeof(colortable_source) / sizeof(colortable_source[0]))
399 
400 	MDRV_PALETTE_INIT(bsktball)
401 	MDRV_VIDEO_START(bsktball)
402 	MDRV_VIDEO_UPDATE(bsktball)
403 
404 	/* sound hardware */
405 	MDRV_SOUND_ADD_TAG("discrete", DISCRETE, bsktball_sound_interface)
406 MACHINE_DRIVER_END
407 
408 
409 
410 /*************************************
411  *
412  *	ROM definitions
413  *
414  *************************************/
415 
416 ROM_START( bsktball )
417 	ROM_REGION( 0x10000, REGION_CPU1, 0 ) /* 64k for code */
418 	ROM_LOAD( "034765.d1",    0x2000, 0x0800, CRC(798cea39) SHA1(b1b709a74258b01b21d7c2038a3b6abe879944c5) )
419 	ROM_LOAD( "034764.c1",    0x2800, 0x0800, CRC(a087109e) SHA1(f5d6dcccc4a54db35be3d8997bc51e73892747fb) )
420 	ROM_LOAD( "034766.f1",    0x3000, 0x0800, CRC(a82e9a9f) SHA1(9aca236c5145c04a8aaebb316179482bbdc9ddfc) )
421 	ROM_LOAD( "034763.b1",    0x3800, 0x0800, CRC(1fc69359) SHA1(a215ba3bb18ea2c57c443dfc4c4a0a3846bbedfe) )
422 	ROM_RELOAD(               0xf800, 0x0800 )
423 
424 	ROM_REGION( 0x1000, REGION_GFX1, ROMREGION_DISPOSE )
425 	ROM_LOAD( "034757.a6",    0x0000, 0x0800, CRC(010e8ad3) SHA1(43ce2c2089ec3011e2d28e8257a35efeed0e71c5) )
426 	ROM_LOAD( "034758.b6",    0x0800, 0x0800, CRC(f7bea344) SHA1(df544bff67bb0334f77cef11792199d9c3f5fdf4) )
427 ROM_END
428 
429 
430 
431 /*************************************
432  *
433  *	Game drivers
434  *
435  *************************************/
436 
437 GAME( 1979, bsktball, 0, bsktball, bsktball, 0, ROT0, "Atari", "Basketball" )
438