1 /***************************************************************************
2 
3 	Sun Electronics Arabian hardware
4 
5 	driver by Dan Boris
6 
7 	Games supported:
8 		* Arabian
9 
10 	Known bugs:
11 		* none at this time
12 
13 ****************************************************************************
14 
15 	Memory map
16 
17 ****************************************************************************
18 
19 	========================================================================
20 	CPU #1 (Arabian)
21 	========================================================================
22 	0000-7FFF   R     xxxxxxxx    Program ROM
23 	8000-BFFF   R/W   xxxxxxxx    Bitmap RAM
24 	C000        R     ----xxxx    Coin inputs
25 	C200        R     ----xxxx    Option switches
26 	D000-DFFF   R/W   xxxxxxxx    Custom microprocessor RAM
27 	E000          W   ----xxxx    BSEL Bank select
28 	E001          W   xxxxxxxx    DMA ROM start address low
29 	E002          W   xxxxxxxx    DMA ROM start address high
30 	E003          W   xxxxxxxx    DMA RAM start address low
31 	E004          W   xxxxxxxx    DMA RAM start address high
32 	E005          W   xxxxxxxx    Picture size/DMA start low
33 	E006          W   xxxxxxxx    Picture size/DMA start high
34 	========================================================================
35 	C800          W   xxxxxxxx    Sound chip address
36 	CA00        R/W   xxxxxxxx    Sound chip data
37 	========================================================================
38 	Interrupts:
39 		NMI not connected
40 		IRQ generated by VBLANK
41 	========================================================================
42 
43 	========================================================================
44 	CPU #1 (Kangaroo)
45 	========================================================================
46 	0000-7FFF   R     xxxxxxxx    Program ROM
47 	8000-BFFF   R/W   xxxxxxxx    Bitmap RAM
48 	C000        R     ----xxxx    Coin inputs
49 	C200        R     ----xxxx    Option switches
50 	D000-DFFF   R/W   xxxxxxxx    Custom microprocessor RAM
51 	E000          W   ----xxxx    BSEL Bank select
52 	E001          W   xxxxxxxx    DMA ROM start address low
53 	E002          W   xxxxxxxx    DMA ROM start address high
54 	E003          W   xxxxxxxx    DMA RAM start address low
55 	E004          W   xxxxxxxx    DMA RAM start address high
56 	E005          W   xxxxxxxx    Picture size/DMA start low
57 	E006          W   xxxxxxxx    Picture size/DMA start high
58 	========================================================================
59 	C800          W   xxxxxxxx    Sound chip address
60 	CA00        R/W   xxxxxxxx    Sound chip data
61 	========================================================================
62 	Interrupts:
63 		NMI not connected
64 		IRQ generated by VBLANK
65 	========================================================================
66 
67 ***************************************************************************/
68 
69 #include "driver.h"
70 #include "arabian.h"
71 #include "vidhrdw/generic.h"
72 
73 
74 /* constants */
75 #define MAIN_OSC		12000000
76 
77 
78 /* local variables */
79 static UINT8 custom_cpu_reset;
80 static UINT8 custom_cpu_busy;
81 static UINT8 *custom_cpu_ram;
82 
83 
84 
85 /*************************************
86  *
87  *	Audio chip output ports
88  *
89  *************************************/
90 
WRITE_HANDLER(ay8910_porta_w)91 static WRITE_HANDLER( ay8910_porta_w )
92 {
93 	/*
94 		bit 7 = ENA
95 		bit 6 = ENB
96 		bit 5 = /ABHF
97 		bit 4 = /AGHF
98 		bit 3 = /ARHF
99 	*/
100 	arabian_video_control = data;
101 }
102 
103 
WRITE_HANDLER(ay8910_portb_w)104 static WRITE_HANDLER( ay8910_portb_w )
105 {
106 	/*
107 		bit 5 = /IREQ to custom CPU
108 		bit 4 = /SRES to custom CPU
109 		bit 1 = coin 2 counter
110 		bit 0 = coin 1 counter
111 	*/
112 
113 	/* track the custom CPU reset */
114 	custom_cpu_reset = ~data & 0x10;
115 
116 	/* clock the coin counters */
117 	coin_counter_w(1, ~data & 0x02);
118 	coin_counter_w(0, ~data & 0x01);
119 }
120 
121 
122 
123 /*************************************
124  *
125  *	Custom CPU RAM snooping
126  *
127  *************************************/
128 
READ_HANDLER(custom_cpu_r)129 static READ_HANDLER( custom_cpu_r )
130 {
131 	/* since we don't have a simulator for the Fujitsu 8841 4-bit microprocessor */
132 	/* we have to simulate its behavior; it looks like Arabian reads out of the  */
133 	/* alternate CPU's RAM space while the CPU is running. If the CPU is not     */
134 	/* running (i.e., the /SRES line is low), it needs to look like RAM to pass  */
135 	/* the self-tests */
136 
137 	/* if the CPU reset line is being held down, just return RAM */
138 	if (custom_cpu_reset)
139 		return custom_cpu_ram[0x7f0 + offset];
140 
141 	/* otherwise, assume the custom CPU is live */
142 	switch (offset)
143 	{
144 		/* 4-bit input ports from the custom */
145 		case 0:
146 		case 1:
147 		case 2:
148 		case 3:
149 		case 4:
150 		case 5:
151 			return readinputport(2 + offset);
152 
153 		/* busy flag; this is polled to check the custom CPU's readiness */
154 		/* we just toggle it on and off until the main CPU gets the result */
155 		/* it wants. There appears to be a number of different ways to make */
156 		/* the custom turn this on. */
157 		case 6:
158 			return custom_cpu_busy ^= 1;
159 
160 		/* handshake read; the main CPU writes to the previous memory location */
161 		/* and waits for the custom to copy that value here */
162 		case 8:
163 			return custom_cpu_ram[0x7f0 + offset - 1];
164 
165 		/* error cases */
166 		default:
167 			logerror("Input Port %04X read.  PC=%04X\n", offset+0xd7f0, activecpu_get_pc());
168 			return 0;
169 	}
170 	return 0;
171 }
172 
173 
update_flip_state(void)174 static void update_flip_state(void)
175 {
176 	/* the custom CPU also controls the video flip control line; unfortunately,    */
177 	/* it appears that the custom is smart enough to flip the screen itself, based */
178 	/* on the information stored at $d400 and $d401. The value at $d400 specifies  */
179 	/* the active player number, and the value at $d401 is a copy of the input     */
180 	/* port from $c200. Also, the value at $d34b controls the global flip screen   */
181 	/* state. */
182 
183 	/* initial state is based on the flip screen flag */
184 	arabian_flip_screen = custom_cpu_ram[0x34b];
185 
186 	/* flip if not player 1 and cocktail mode */
187 	if (custom_cpu_ram[0x400] != 0 && !(custom_cpu_ram[0x401] & 0x02))
188 		arabian_flip_screen = !arabian_flip_screen;
189 }
190 
191 
WRITE_HANDLER(custom_flip_w)192 static WRITE_HANDLER( custom_flip_w )
193 {
194 	custom_cpu_ram[0x34b + offset] = data;
195 	update_flip_state();
196 }
197 
198 
WRITE_HANDLER(custom_cocktail_w)199 static WRITE_HANDLER( custom_cocktail_w )
200 {
201 	custom_cpu_ram[0x400 + offset] = data;
202 	update_flip_state();
203 }
204 
205 
206 
207 /*************************************
208  *
209  *	Main CPU memory handlers
210  *
211  *************************************/
212 
MEMORY_READ_START(readmem)213 static MEMORY_READ_START( readmem )
214 	{ 0x0000, 0x7fff, MRA_ROM },
215 	{ 0xc000, 0xc000, input_port_0_r },
216 	{ 0xc200, 0xc200, input_port_1_r },
217 	{ 0xd000, 0xd7ef, MRA_RAM },
218 	{ 0xd7f0, 0xd7ff, custom_cpu_r },
219 MEMORY_END
220 
221 
222 static MEMORY_WRITE_START( writemem )
223 	{ 0x0000, 0x7fff, MWA_ROM },
224 	{ 0x8000, 0xbfff, arabian_videoram_w, &videoram },
225 	{ 0xd000, 0xd7ff, MWA_RAM, &custom_cpu_ram },
226 	{ 0xe000, 0xe07f, arabian_blitter_w, &spriteram },
227 MEMORY_END
228 
229 
230 
231 /*************************************
232  *
233  *	Main CPU port handlers
234  *
235  *************************************/
236 
237 static PORT_WRITE_START( writeport )
238 	{ 0xc800, 0xc800, AY8910_control_port_0_w },
239 	{ 0xca00, 0xca00, AY8910_write_port_0_w },
240 PORT_END
241 
242 
243 
244 /*************************************
245  *
246  *	Port definitions
247  *
248  *************************************/
249 
250 INPUT_PORTS_START( arabian )
251 	PORT_START      /* IN0 */
252 	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 )
253 	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_COIN2 )
254 	PORT_SERVICE( 0x04, IP_ACTIVE_HIGH )
255 	PORT_BIT( 0xf8, IP_ACTIVE_HIGH, IPT_UNKNOWN )
256 
257 	PORT_START      /* DSW1 */
258 	PORT_DIPNAME( 0x01, 0x00, DEF_STR( Lives ))
259 	PORT_DIPSETTING(    0x00, "3" )
260 	PORT_DIPSETTING(    0x01, "5" )
261 	PORT_DIPNAME( 0x02, 0x02, DEF_STR( Cabinet ))
262 	PORT_DIPSETTING(    0x02, DEF_STR( Upright ))
263 	PORT_DIPSETTING(    0x00, DEF_STR( Cocktail ))
264 	PORT_DIPNAME( 0x04, 0x04, DEF_STR( Flip_Screen ))
265 	PORT_DIPSETTING(    0x04, DEF_STR( Off ))
266 	PORT_DIPSETTING(    0x00, DEF_STR( On ))
267 	PORT_DIPNAME( 0x08, 0x00, "Carry Bowls to Next Life" )
268 	PORT_DIPSETTING(    0x08, DEF_STR( No ))
269 	PORT_DIPSETTING(    0x00, DEF_STR( Yes ))
270 	PORT_DIPNAME( 0xf0, 0x00, DEF_STR( Coinage ))
271 	PORT_DIPSETTING(    0x10, "A 2/1 B 2/1" )
272 	PORT_DIPSETTING(    0x20, "A 2/1 B 1/3" )
273 	PORT_DIPSETTING(    0x00, "A 1/1 B 1/1" )
274 	PORT_DIPSETTING(    0x30, "A 1/1 B 1/2" )
275 	PORT_DIPSETTING(    0x40, "A 1/1 B 1/3" )
276 	PORT_DIPSETTING(    0x50, "A 1/1 B 1/4" )
277 	PORT_DIPSETTING(    0x60, "A 1/1 B 1/5" )
278 	PORT_DIPSETTING(    0x70, "A 1/1 B 1/6" )
279 	PORT_DIPSETTING(    0x80, "A 1/2 B 1/2" )
280 	PORT_DIPSETTING(    0x90, "A 1/2 B 1/4" )
281 	PORT_DIPSETTING(    0xa0, "A 1/2 B 1/6" )
282 	PORT_DIPSETTING(    0xb0, "A 1/2 B 1/10" )
283 	PORT_DIPSETTING(    0xc0, "A 1/2 B 1/11" )
284 	PORT_DIPSETTING(    0xd0, "A 1/2 B 1/12" )
285 	PORT_DIPSETTING(    0xf0, DEF_STR( Free_Play ))
286 	/* 0xe0 gives A 1/2 B 1/6 */
287 
288 	PORT_START      /* COM0 */
289 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
290 	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_START1 )
291 	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_START2 )
292 	PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_COIN3 )		/* IN3 */
293 
294 	PORT_START      /* COM1 */
295 	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT | IPF_8WAY )
296 	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT  | IPF_8WAY )
297 	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP    | IPF_8WAY )
298 	PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN  | IPF_8WAY )
299 
300 	PORT_START      /* COM2 */
301 	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 )
302 	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNKNOWN )	/* IN9 */
303 	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNKNOWN )	/* IN10 */
304 	PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNKNOWN )	/* IN11 */
305 
306 	PORT_START      /* COM3 */
307 	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT | IPF_8WAY | IPF_COCKTAIL )
308 	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT  | IPF_8WAY | IPF_COCKTAIL )
309 	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP    | IPF_8WAY | IPF_COCKTAIL )
310 	PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN  | IPF_8WAY | IPF_COCKTAIL )
311 
312 	PORT_START      /* COM4 */
313 	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 | IPF_COCKTAIL )
314 	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNKNOWN )	/* IN17 */
315 	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNKNOWN )	/* IN18 */
316 	PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNKNOWN )	/* IN19 */
317 
318 	PORT_START      /* COM5 */
319 	PORT_DIPNAME( 0x01, 0x00, "Coin Chutes" )
320 	PORT_DIPSETTING(    0x01, "1" )
321 	PORT_DIPSETTING(    0x00, "2" )
322 	PORT_DIPNAME( 0x02, 0x00, DEF_STR( Demo_Sounds ))
323 	PORT_DIPSETTING(    0x02, DEF_STR( Off ))
324 	PORT_DIPSETTING(    0x00, DEF_STR( On ))
325 	PORT_DIPNAME( 0x0c, 0x04, DEF_STR( Bonus_Life ))
326 	PORT_DIPSETTING(    0x04, "20000" )
327 	PORT_DIPSETTING(    0x08, "40000" )
328 	PORT_DIPSETTING(    0x0c, "20000 50000 +100K" )
329 	PORT_DIPSETTING(    0x00, "None" )
330 INPUT_PORTS_END
331 
332 
333 
334 /*************************************
335  *
336  *	Sound definitions
337  *
338  *************************************/
339 
340 static struct AY8910interface ay8910_interface =
341 {
342 	1,
343 	MAIN_OSC/4/2,	/* 1.5 MHz */
344 	{ 50 },
345 	{ 0 },
346 	{ 0 },
347 	{ ay8910_porta_w },
348 	{ ay8910_portb_w }
349 };
350 
351 
352 
353 /*************************************
354  *
355  *	Machine driver
356  *
357  *************************************/
358 
359 static MACHINE_DRIVER_START( arabian )
360 
361 	/* basic machine hardware */
362 	MDRV_CPU_ADD(Z80, MAIN_OSC/4)
MDRV_CPU_FLAGS(CPU_16BIT_PORT)363 	MDRV_CPU_FLAGS(CPU_16BIT_PORT)
364 	MDRV_CPU_MEMORY(readmem,writemem)
365 	MDRV_CPU_PORTS(0,writeport)
366 	MDRV_CPU_VBLANK_INT(irq0_line_hold,1)
367 
368 	MDRV_FRAMES_PER_SECOND(60)
369 	MDRV_VBLANK_DURATION(DEFAULT_60HZ_VBLANK_DURATION)
370 
371 	/* video hardware */
372 	MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER)
373 	MDRV_SCREEN_SIZE(256, 256)
374 	MDRV_VISIBLE_AREA(0, 255, 11, 244)
375 	MDRV_PALETTE_LENGTH(64)
376 	MDRV_COLORTABLE_LENGTH(256*32)
377 
378 	MDRV_PALETTE_INIT(arabian)
379 	MDRV_VIDEO_START(arabian)
380 	MDRV_VIDEO_UPDATE(arabian)
381 
382 	/* sound hardware */
383 	MDRV_SOUND_ADD(AY8910, ay8910_interface)
384 MACHINE_DRIVER_END
385 
386 
387 
388 /*************************************
389  *
390  *	ROM definitions
391  *
392  *************************************/
393 
394 ROM_START( arabian )
395 	ROM_REGION( 0x10000, REGION_CPU1, 0 )
396 	ROM_LOAD( "ic1rev2.87", 0x0000, 0x2000, CRC(5e1c98b8) SHA1(1775b7b125dde3502aefcf6221662e82f55b3f2a) )
397 	ROM_LOAD( "ic2rev2.88", 0x2000, 0x2000, CRC(092f587e) SHA1(a722a61d35629ff4087c7a5e4c98b3ab51d6322b) )
398 	ROM_LOAD( "ic3rev2.89", 0x4000, 0x2000, CRC(15145f23) SHA1(ae250116b57455ed84948cd9a6bdda86b2ac3e16) )
399 	ROM_LOAD( "ic4rev2.90", 0x6000, 0x2000, CRC(32b77b44) SHA1(9d7951e723bc65e3d607f89836f1436b99f2585b) )
400 
401 	ROM_REGION( 0x10000, REGION_GFX1, 0 )
402 	ROM_LOAD( "ic84.91",    0x0000, 0x2000, CRC(c4637822) SHA1(0c73d9a4db925421a535784780ad93bb0f091051) )
403 	ROM_LOAD( "ic85.92",    0x2000, 0x2000, CRC(f7c6866d) SHA1(34f545c5f7c152cd59f7be0a72105f739852cd6a) )
404 	ROM_LOAD( "ic86.93",    0x4000, 0x2000, CRC(71acd48d) SHA1(cd0bffed351b14c9aebbfc1d3d4d232a5b91a68f) )
405 	ROM_LOAD( "ic87.94",    0x6000, 0x2000, CRC(82160b9a) SHA1(03511f6ebcf22ba709a80a565e71acf5bdecbabb) )
406 ROM_END
407 
408 
409 ROM_START( arabiana )
410 	ROM_REGION( 0x10000, REGION_CPU1, 0 )
411 	ROM_LOAD( "ic1.87",     0x0000, 0x2000, CRC(51e9a6b1) SHA1(a2e6beab5380eed56972f5625be21b01c7e2082a) )
412 	ROM_LOAD( "ic2.88",     0x2000, 0x2000, CRC(1cdcc1ab) SHA1(46886d53cc8a1c1d540fd0e1ddf1811fb256c1f3) )
413 	ROM_LOAD( "ic3.89",     0x4000, 0x2000, CRC(b7b7faa0) SHA1(719418b7b7c057acb6d3060cf7061ffacf00798c) )
414 	ROM_LOAD( "ic4.90",     0x6000, 0x2000, CRC(dbded961) SHA1(ecc09fa95f6dd58c4ac0e095a89ffd3aae681da4) )
415 
416 	ROM_REGION( 0x10000, REGION_GFX1, 0 )
417 	ROM_LOAD( "ic84.91",    0x0000, 0x2000, CRC(c4637822) SHA1(0c73d9a4db925421a535784780ad93bb0f091051) )
418 	ROM_LOAD( "ic85.92",    0x2000, 0x2000, CRC(f7c6866d) SHA1(34f545c5f7c152cd59f7be0a72105f739852cd6a) )
419 	ROM_LOAD( "ic86.93",    0x4000, 0x2000, CRC(71acd48d) SHA1(cd0bffed351b14c9aebbfc1d3d4d232a5b91a68f) )
420 	ROM_LOAD( "ic87.94",    0x6000, 0x2000, CRC(82160b9a) SHA1(03511f6ebcf22ba709a80a565e71acf5bdecbabb) )
421 ROM_END
422 
423 
424 
425 /*************************************
426  *
427  *	Driver initialization
428  *
429  *************************************/
430 
431 static DRIVER_INIT( arabian )
432 {
433 	install_mem_write_handler(0, 0xd34b, 0xd34b, custom_flip_w);
434 	install_mem_write_handler(0, 0xd400, 0xd401, custom_cocktail_w);
435 }
436 
437 
438 
439 /*************************************
440  *
441  *	Game drivers
442  *
443  *************************************/
444 
445 GAME( 1983, arabian,  0,       arabian, arabian, arabian, ROT270, "Sun Electronics", "Arabian" )
446 GAME( 1983, arabiana, arabian, arabian, arabian, arabian, ROT270, "[Sun Electronics] (Atari license)", "Arabian (Atari)" )
447