1 // FB Alpha Sand Scorpion driver module based on MAME driver by Luca Elia
2 
3 #include "tiles_generic.h"
4 #include "z80_intf.h"
5 #include "m68000_intf.h"
6 #include "msm6295.h"
7 #include "burn_ym2203.h"
8 #include "kaneko_tmap.h"
9 #include "pandora.h"
10 
11 static UINT8 *AllMem;
12 static UINT8 *MemEnd;
13 static UINT8 *AllRam;
14 static UINT8 *RamEnd;
15 static UINT8 *Drv68KROM;
16 static UINT8 *DrvZ80ROM;
17 static UINT8 *DrvGfxROM0;
18 static UINT8 *DrvGfxROM1;
19 static UINT8 *DrvTransTab;
20 static UINT8 *Drv68KRAM;
21 static UINT8 *DrvZ80RAM;
22 static UINT8 *DrvPandoraRAM;
23 static UINT8 *DrvSprRAM;
24 static UINT8 *DrvPalRAM;
25 static UINT8 *DrvVideoRAM;
26 static UINT8 *DrvVidRegs;
27 
28 static UINT32 *DrvPalette;
29 static UINT8 DrvRecalc;
30 
31 static UINT8 nDrvZ80Bank;
32 static UINT8 soundlatch;
33 static UINT8 soundlatch2;
34 static INT32 watchdog;
35 static INT32 vblank_irq;
36 static INT32 sprite_irq;
37 static INT32 unknown_irq;
38 static INT32 latch1_full;
39 static INT32 latch2_full;
40 
41 typedef struct
42 {
43 	UINT16 x1p, y1p, x1s, y1s;
44 	UINT16 x2p, y2p, x2s, y2s;
45 	INT16 x12, y12, x21, y21;
46 	UINT16 mult_a, mult_b;
47 } calc1_hit_t;
48 
49 static calc1_hit_t m_hit;
50 
51 static UINT8 DrvJoy1[16];
52 static UINT8 DrvJoy2[16];
53 static UINT8 DrvJoy3[16];
54 static UINT8 DrvDips[2];
55 static UINT16 DrvInputs[3];
56 static UINT8 DrvReset;
57 
58 static struct BurnInputInfo SandscrpInputList[] = {
59 	{"P1 Coin",			BIT_DIGITAL,	DrvJoy3 + 2,	"p1 coin"	},
60 	{"P1 Start",		BIT_DIGITAL,	DrvJoy3 + 0,	"p1 start"	},
61 	{"P1 Up",			BIT_DIGITAL,	DrvJoy1 + 0,	"p1 up"		},
62 	{"P1 Down",			BIT_DIGITAL,	DrvJoy1 + 1,	"p1 down"	},
63 	{"P1 Left",			BIT_DIGITAL,	DrvJoy1 + 2,	"p1 left"	},
64 	{"P1 Right",		BIT_DIGITAL,	DrvJoy1 + 3,	"p1 right"	},
65 	{"P1 Button 1",		BIT_DIGITAL,	DrvJoy1 + 4,	"p1 fire 1"	},
66 	{"P1 Button 2",		BIT_DIGITAL,	DrvJoy1 + 5,	"p1 fire 2"	},
67 
68 	{"P2 Coin",			BIT_DIGITAL,	DrvJoy3 + 3,	"p2 coin"	},
69 	{"P2 Start",		BIT_DIGITAL,	DrvJoy3 + 1,	"p2 start"	},
70 	{"P2 Up",			BIT_DIGITAL,	DrvJoy2 + 0,	"p2 up"		},
71 	{"P2 Down",			BIT_DIGITAL,	DrvJoy2 + 1,	"p2 down"	},
72 	{"P2 Left",			BIT_DIGITAL,	DrvJoy2 + 2,	"p2 left"	},
73 	{"P2 Right",		BIT_DIGITAL,	DrvJoy2 + 3,	"p2 right"	},
74 	{"P2 Button 1",		BIT_DIGITAL,	DrvJoy2 + 4,	"p2 fire 1"	},
75 	{"P2 Button 2",		BIT_DIGITAL,	DrvJoy2 + 5,	"p2 fire 2"	},
76 
77 	{"Reset",			BIT_DIGITAL,	&DrvReset,		"reset"		},
78 	{"Service",			BIT_DIGITAL,	DrvJoy3 + 6,	"service"	},
79 	{"Tilt",			BIT_DIGITAL,	DrvJoy3 + 4,	"tilt"		},
80 	{"Dip A",			BIT_DIPSWITCH,	DrvDips + 0,	"dip"		},
81 	{"Dip B",			BIT_DIPSWITCH,	DrvDips + 1,	"dip"		},
82 };
83 
84 STDINPUTINFO(Sandscrp)
85 
86 static struct BurnDIPInfo SandscrpDIPList[]=
87 {
88 	{0x13, 0xff, 0xff, 0xff, NULL					},
89 	{0x14, 0xff, 0xff, 0xff, NULL					},
90 
91 	{0   , 0xfe, 0   ,    4, "Lives"				},
92 	{0x13, 0x01, 0x03, 0x02, "1"					},
93 	{0x13, 0x01, 0x03, 0x01, "2"					},
94 	{0x13, 0x01, 0x03, 0x03, "3"					},
95 	{0x13, 0x01, 0x03, 0x00, "5"					},
96 
97 	{0   , 0xfe, 0   ,    4, "Bombs"				},
98 	{0x13, 0x01, 0x0c, 0x08, "1"					},
99 	{0x13, 0x01, 0x0c, 0x04, "2"					},
100 	{0x13, 0x01, 0x0c, 0x0c, "3"					},
101 	{0x13, 0x01, 0x0c, 0x00, "5"					},
102 
103 	{0   , 0xfe, 0   ,    4, "Difficulty"			},
104 	{0x13, 0x01, 0x30, 0x30, "Easy"					},
105 	{0x13, 0x01, 0x30, 0x20, "Normal"				},
106 	{0x13, 0x01, 0x30, 0x10, "Hard"					},
107 	{0x13, 0x01, 0x30, 0x00, "Hardest"				},
108 
109 	{0   , 0xfe, 0   ,    4, "Bonus Life"			},
110 	{0x13, 0x01, 0xc0, 0x80, "100K, 300K"			},
111 	{0x13, 0x01, 0xc0, 0xc0, "200K, 500K"			},
112 	{0x13, 0x01, 0xc0, 0x40, "500K, 1000K"			},
113 	{0x13, 0x01, 0xc0, 0x00, "1000K, 3000K"			},
114 
115 	{0   , 0xfe, 0   ,    16, "Coinage"				},
116 	{0x14, 0x01, 0x0f, 0x0a, "6 Coins 1 Credits"	},
117 	{0x14, 0x01, 0x0f, 0x0b, "5 Coins 1 Credits"	},
118 	{0x14, 0x01, 0x0f, 0x0c, "4 Coins 1 Credits"	},
119 	{0x14, 0x01, 0x0f, 0x0d, "3 Coins 1 Credits"	},
120 	{0x14, 0x01, 0x0f, 0x01, "8 Coins 3 Credits"	},
121 	{0x14, 0x01, 0x0f, 0x0e, "2 Coins 1 Credits"	},
122 	{0x14, 0x01, 0x0f, 0x02, "5 Coins 3 Credits"	},
123 	{0x14, 0x01, 0x0f, 0x03, "3 Coins 2 Credits"	},
124 	{0x14, 0x01, 0x0f, 0x0f, "1 Coin  1 Credits"	},
125 	{0x14, 0x01, 0x0f, 0x04, "2 Coins 3 Credits"	},
126 	{0x14, 0x01, 0x0f, 0x09, "1 Coin  2 Credits"	},
127 	{0x14, 0x01, 0x0f, 0x08, "1 Coin  3 Credits"	},
128 	{0x14, 0x01, 0x0f, 0x07, "1 Coin  4 Credits"	},
129 	{0x14, 0x01, 0x0f, 0x06, "1 Coin  5 Credits"	},
130 	{0x14, 0x01, 0x0f, 0x05, "1 Coin  6 Credits"	},
131 	{0x14, 0x01, 0x0f, 0x00, "Free Play"			},
132 
133 	{0   , 0xfe, 0   ,    2, "Flip Screen"			},
134 	{0x14, 0x01, 0x10, 0x10, "Off"					},
135 	{0x14, 0x01, 0x10, 0x00, "On"					},
136 
137 	{0   , 0xfe, 0   ,    2, "Allow Continue"		},
138 	{0x14, 0x01, 0x20, 0x00, "Off"					},
139 	{0x14, 0x01, 0x20, 0x20, "On"					},
140 
141 	{0   , 0xfe, 0   ,    2, "Demo Sounds"			},
142 	{0x14, 0x01, 0x40, 0x00, "Off"					},
143 	{0x14, 0x01, 0x40, 0x40, "On"					},
144 
145 	{0   , 0xfe, 0   ,    2, "Service Mode"			},
146 	{0x14, 0x01, 0x80, 0x80, "Off"					},
147 	{0x14, 0x01, 0x80, 0x00, "On"					},
148 };
149 
STDDIPINFO(Sandscrp)150 STDDIPINFO(Sandscrp)
151 
152 static inline void palette_update(UINT16 offset)
153 {
154 	INT32 p = BURN_ENDIAN_SWAP_INT16(*((UINT16*)(DrvPalRAM + offset)));
155 
156 	INT32 r = (p >>  5) & 0x1f;
157 	INT32 g = (p >> 10) & 0x1f;
158 	INT32 b = (p >>  0) & 0x1f;
159 
160 	r = (r << 3) | (r >> 2);
161 	g = (g << 3) | (g >> 2);
162 	b = (b << 3) | (b >> 2);
163 
164 	DrvPalette[offset/2] = BurnHighCol(r, g, b, 0);
165 }
166 
galpanib_calc_read(UINT32 offset)167 static UINT16 galpanib_calc_read(UINT32 offset) // Simulation of the CALC1 MCU
168 {
169 	calc1_hit_t &hit = m_hit;
170 
171 	switch (offset)
172 	{
173 		case 0x00/2: // watchdog
174 			watchdog = 0;
175 			return 0;
176 
177 		case 0x04/2: // similar to the hit detection from SuperNova, but much simpler
178 		{
179 			UINT16 data = 0;
180 
181 			// X Absolute Collision
182 			if      (hit.x1p >  hit.x2p)	data |= 0x0200;
183 			else if (hit.x1p == hit.x2p)	data |= 0x0400;
184 			else if (hit.x1p <  hit.x2p)	data |= 0x0800;
185 
186 			// Y Absolute Collision
187 			if      (hit.y1p >  hit.y2p)	data |= 0x2000;
188 			else if (hit.y1p == hit.y2p)	data |= 0x4000;
189 			else if (hit.y1p <  hit.y2p)	data |= 0x8000;
190 
191 			// XY Overlap Collision
192 			hit.x12 = (hit.x1p) - (hit.x2p + hit.x2s);
193 			hit.y12 = (hit.y1p) - (hit.y2p + hit.y2s);
194 			hit.x21 = (hit.x1p + hit.x1s) - (hit.x2p);
195 			hit.y21 = (hit.y1p + hit.y1s) - (hit.y2p);
196 
197 			if ((hit.x12 < 0) && (hit.y12 < 0) && (hit.x21 >= 0) && (hit.y21 >= 0))
198 				data |= 0x0001;
199 
200 			return data;
201 		}
202 
203 		case 0x10/2:
204 			return (((UINT32)hit.mult_a * (UINT32)hit.mult_b) >> 16);
205 
206 		case 0x12/2:
207 			return (((UINT32)hit.mult_a * (UINT32)hit.mult_b) & 0xffff);
208 
209 
210 		case 0x14/2:
211 			return BurnRandom(); // really rand
212 	}
213 
214 	return 0;
215 }
216 
galpanib_calc_write(INT32 offset,UINT16 data)217 static void galpanib_calc_write(INT32 offset, UINT16 data)
218 {
219 	calc1_hit_t &hit = m_hit;
220 
221 	switch (offset)
222 	{
223 		case 0x00/2: hit.x1p    = data; break;
224 		case 0x02/2: hit.x1s    = data; break;
225 		case 0x04/2: hit.y1p    = data; break;
226 		case 0x06/2: hit.y1s    = data; break;
227 		case 0x08/2: hit.x2p    = data; break;
228 		case 0x0a/2: hit.x2s    = data; break;
229 		case 0x0c/2: hit.y2p    = data; break;
230 		case 0x0e/2: hit.y2s    = data; break;
231 		case 0x10/2: hit.mult_a = data; break;
232 		case 0x12/2: hit.mult_b = data; break;
233 	}
234 }
235 
update_irq_state()236 static void update_irq_state()
237 {
238 	INT32 irq = (vblank_irq || sprite_irq || unknown_irq) ? 1 : 0;
239 
240 	SekSetIRQLine(1, irq ? CPU_IRQSTATUS_ACK : CPU_IRQSTATUS_NONE);
241 }
242 
sound_sync()243 static void sound_sync()
244 {
245 	BurnTimerUpdate(SekTotalCycles() / 5);
246 }
247 
sandscrp_main_write_word(UINT32 address,UINT16 data)248 static void __fastcall sandscrp_main_write_word(UINT32 address, UINT16 data)
249 {
250 	if ((address & 0xffffe0) == 0x200000) {
251 		galpanib_calc_write((address & 0x1f) >> 1, data);
252 		return;
253 	}
254 
255 	switch (address)
256 	{
257 		case 0x100000:
258 			if (data & 0x08) sprite_irq = 0;
259 			if (data & 0x10) unknown_irq = 0;
260 			if (data & 0x20) vblank_irq = 0;
261 			update_irq_state();
262 		return;
263 
264 		case 0xa00000:
265 		return; // coin counter
266 
267 		case 0xe00000:
268 			sound_sync();
269 			latch1_full = 1;
270 			soundlatch = data & 0xff;
271 			ZetNmi();
272 			BurnTimerUpdate((SekTotalCycles() / 5) + 133);
273 		return;
274 
275 		case 0xe40000:
276 			sound_sync();
277 			latch1_full = data & 0x80;
278 			latch2_full = data & 0x40;
279 		return;
280 	}
281 }
282 
sandscrp_main_write_byte(UINT32 address,UINT8 data)283 static void __fastcall sandscrp_main_write_byte(UINT32 address, UINT8 data)
284 {
285 	bprintf (0, _T("MWB %5.5x %2.2x\n"), address, data);
286 }
287 
sandscrp_main_read_word(UINT32 address)288 static UINT16 __fastcall sandscrp_main_read_word(UINT32 address)
289 {
290 	if ((address & 0xffffe0) == 0x200000) {
291 		return galpanib_calc_read((address & 0x1f) >> 1);
292 	}
293 
294 	switch (address)
295 	{
296 		case 0x800000:
297 			return ((sprite_irq << 3) | (unknown_irq << 4) | (vblank_irq << 5));
298 
299 		case 0xb00000:
300 			return DrvInputs[0];
301 
302 		case 0xb00002:
303 			return DrvInputs[1];
304 
305 		case 0xb00004:
306 			return DrvInputs[2];
307 
308 		case 0xb00006:
309 			return 0xffff;
310 
311 		case 0xe00000:
312 			sound_sync();
313 			latch2_full = 0;
314 			return soundlatch2;
315 
316 		case 0xe40000:
317 			sound_sync();
318 			return (latch1_full ? 0x80 : 0) | (latch2_full ? 0x40 : 0);
319 
320 		case 0xec0000:
321 			watchdog = 0;
322 			return 0;
323 	}
324 
325 	return 0;
326 }
327 
sandscrp_main_read_byte(UINT32 address)328 static UINT8 __fastcall sandscrp_main_read_byte(UINT32 address)
329 {
330 	bprintf (0, _T("MRB %5.5x\n"), address);
331 
332 	return 0;
333 }
334 
sandscrp_pandora_write_word(UINT32 address,UINT16 data)335 static void __fastcall sandscrp_pandora_write_word(UINT32 address, UINT16 data)
336 {
337 	address &= 0x1ffe;
338 
339 	data &= 0xff;
340 
341 	DrvSprRAM[address + 0] = data;
342 	DrvSprRAM[address + 1] = data;
343 
344 	DrvPandoraRAM[address/2] = data;
345 }
346 
sandscrp_pandora_write_byte(UINT32 address,UINT8 data)347 static void __fastcall sandscrp_pandora_write_byte(UINT32 address, UINT8 data)
348 {
349 	address &= 0x1ffe;
350 
351 	DrvSprRAM[address + 0] = data;
352 	DrvSprRAM[address + 1] = data;
353 
354 	DrvPandoraRAM[address/2] = data;
355 }
356 
sandscrp_palette_write_word(UINT32 address,UINT16 data)357 static void __fastcall sandscrp_palette_write_word(UINT32 address, UINT16 data)
358 {
359 	*((UINT16*)(DrvPalRAM + (address & 0xffe))) = BURN_ENDIAN_SWAP_INT16(data);
360 	palette_update(address & 0xffe);
361 }
362 
sandscrp_palette_write_byte(UINT32 address,UINT8 data)363 static void __fastcall sandscrp_palette_write_byte(UINT32 address, UINT8 data)
364 {
365 	DrvPalRAM[(address & 0xfff) ^ 1] = data;
366 	palette_update(address & 0xffe);
367 }
368 
bankswitch(INT32 bank)369 static void bankswitch(INT32 bank)
370 {
371 	nDrvZ80Bank = bank & 7;
372 
373 	ZetMapMemory(DrvZ80ROM + ((bank & 0x07) * 0x4000), 0x8000, 0xbfff, MAP_ROM);
374 }
375 
sandscrp_sound_write_port(UINT16 port,UINT8 data)376 static void __fastcall sandscrp_sound_write_port(UINT16 port, UINT8 data)
377 {
378 	switch (port & 0xff)
379 	{
380 		case 0x00:
381 			bankswitch(data);
382 		return;
383 
384 		case 0x02:
385 			BurnYM2203Write(0, 0, data);
386 		return;
387 
388 		case 0x03:
389 			BurnYM2203Write(0, 1, data);
390 		return;
391 
392 		case 0x04:
393 			MSM6295Write(0, data);
394 		return;
395 
396 		case 0x06:
397 			latch2_full = 1;
398 			soundlatch2 = data;
399 		return;
400 	}
401 }
402 
sandscrp_sound_read_port(UINT16 port)403 static UINT8 __fastcall sandscrp_sound_read_port(UINT16 port)
404 {
405 	switch (port & 0xff)
406 	{
407 		case 0x02:
408 			return BurnYM2203Read(0, 0);
409 
410 		case 0x03:
411 			return BurnYM2203Read(0, 1);
412 
413 		case 0x07:
414 			latch1_full = 0;
415 			return soundlatch;
416 
417 		case 0x08:
418 			return (latch2_full ? 0x80 : 0) | (latch1_full ? 0x40 : 0);
419 	}
420 
421 	return 0;
422 }
423 
DrvYM2203PortA(UINT32)424 static UINT8 DrvYM2203PortA(UINT32)
425 {
426 	return DrvDips[0];
427 }
428 
DrvYM2203PortB(UINT32)429 static UINT8 DrvYM2203PortB(UINT32)
430 {
431 	return DrvDips[1];
432 }
433 
DrvFMIRQHandler(INT32,INT32 nStatus)434 static void DrvFMIRQHandler(INT32, INT32 nStatus)
435 {
436 	ZetSetIRQLine(0, (nStatus) ? CPU_IRQSTATUS_ACK : CPU_IRQSTATUS_NONE);
437 }
438 
DrvDoReset(INT32 full_reset)439 static INT32 DrvDoReset(INT32 full_reset)
440 {
441 	if (full_reset) {
442 		memset (AllRam, 0, RamEnd - AllRam);
443 	}
444 
445 	SekOpen(0);
446 	SekReset();
447 	SekClose();
448 
449 	ZetOpen(0);
450 	ZetReset();
451 	BurnYM2203Reset();
452 	ZetClose();
453 
454 	MSM6295Reset(0);
455 
456 	nDrvZ80Bank = 0;
457 	vblank_irq = 0;
458 	sprite_irq = 0;
459 	unknown_irq = 0;
460 	soundlatch = 0;
461 	soundlatch2 = 0;
462 	latch1_full = 0;
463 	latch2_full = 0;
464 	watchdog = 0;
465 
466 	return 0;
467 }
468 
MemIndex()469 static INT32 MemIndex()
470 {
471 	UINT8 *Next; Next = AllMem;
472 
473 	Drv68KROM		= Next; Next += 0x080000;
474 	DrvZ80ROM		= Next; Next += 0x020000;
475 
476 	DrvGfxROM0		= Next; Next += 0x200000;
477 	DrvGfxROM1		= Next; Next += 0x200000;
478 
479 	DrvTransTab		= Next; Next += 0x400000 / 0x100;
480 
481 	MSM6295ROM		= Next; Next += 0x040000;
482 
483 	AllRam			= Next;
484 
485 	DrvZ80RAM		= Next; Next += 0x002000;
486 
487 	Drv68KRAM		= Next; Next += 0x010000;
488 	DrvPandoraRAM		= Next; Next += 0x002000;
489 	DrvSprRAM		= Next; Next += 0x002000;
490 	DrvPalRAM		= Next; Next += 0x001000;
491 
492 	DrvVideoRAM		= Next; Next += 0x004000;
493 	DrvVidRegs		= Next; Next += 0x000400;
494 
495 	RamEnd			= Next;
496 
497 	DrvPalette		= (UINT32*)Next; Next += 0x0800 * sizeof(UINT32);
498 
499 	MemEnd			= Next;
500 
501 	return 0;
502 }
503 
DrvFillTransTable()504 static void DrvFillTransTable()
505 {
506 	memset (DrvTransTab, 0, 0x4000);
507 
508 	for (INT32 i = 0; i < 0x400000; i+= 0x100) {
509 		DrvTransTab[i/0x100] = 1; // transparent
510 
511 		for (INT32 j = 0; j < 0x100; j++) {
512 			if (DrvGfxROM0[j + i]) {
513 				DrvTransTab[i/0x100] = 0;
514 				break;
515 			}
516 		}
517 	}
518 }
519 
DrvGfxDecode()520 static INT32 DrvGfxDecode()
521 {
522 	static INT32 Plane[4]   = { STEP4(0,1) };
523 	static INT32 XOffs0[16] = { STEP4(12, -4), STEP4(28, -4), STEP4(268, -4),STEP4(284, -4) };
524 	static INT32 XOffs1[16] = { STEP8(0,4), STEP8(256,4) };
525 	static INT32 YOffs[16]  = { STEP8(0, 32), STEP8(512, 32) };
526 
527 	UINT8 *tmp = (UINT8*)BurnMalloc(0x200000);
528 	if (tmp == NULL) {
529 		return 1;
530 	}
531 
532 	memcpy (tmp, DrvGfxROM0, 0x200000);
533 
534 	GfxDecode(0x2000, 4, 16, 16, Plane, XOffs0, YOffs, 0x400, tmp, DrvGfxROM0);
535 
536 	memcpy (tmp, DrvGfxROM1, 0x200000);
537 
538 	GfxDecode(0x2000, 4, 16, 16, Plane, XOffs1, YOffs, 0x400, tmp, DrvGfxROM1);
539 
540 	BurnFree (tmp);
541 
542 	return 0;
543 }
544 
DrvInit(INT32 type)545 static INT32 DrvInit(INT32 type)
546 {
547 	AllMem = NULL;
548 	MemIndex();
549 	INT32 nLen = MemEnd - (UINT8 *)0;
550 	if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1;
551 	memset(AllMem, 0, nLen);
552 	MemIndex();
553 
554 	{
555 		if (BurnLoadRom(Drv68KROM  + 0x000001,  0, 2)) return 1;
556 		if (BurnLoadRom(Drv68KROM  + 0x000000,  1, 2)) return 1;
557 
558 		if (BurnLoadRom(DrvZ80ROM  + 0x000000,  2, 1)) return 1;
559 
560 		if (type == 0) // early revisions
561 		{
562 			if (BurnLoadRom(DrvGfxROM0 + 0x000000,  3, 2)) return 1;
563 			if (BurnLoadRom(DrvGfxROM0 + 0x000001,  4, 2)) return 1;
564 
565 			if (BurnLoadRom(DrvGfxROM1 + 0x000000,  5, 1)) return 1;
566 			if (BurnLoadRom(DrvGfxROM1 + 0x080000,  6, 1)) return 1;
567 
568 			if (BurnLoadRom(MSM6295ROM + 0x000000,  7, 1)) return 1;
569 		}
570 		else
571 		{
572 			if (BurnLoadRom(DrvGfxROM0 + 0x000000,  3, 1)) return 1;
573 			BurnByteswap(DrvGfxROM0, 0x200000);
574 
575 			if (BurnLoadRom(DrvGfxROM1 + 0x000000,  4, 1)) return 1;
576 
577 			if (BurnLoadRom(MSM6295ROM + 0x000000,  5, 1)) return 1;
578 		}
579 
580 		DrvGfxDecode();
581 		DrvFillTransTable();
582 	}
583 
584 	SekInit(0, 0x68000);
585 	SekOpen(0);
586 	SekMapMemory(Drv68KROM,		0x000000, 0x07ffff, MAP_ROM);
587 	SekMapMemory(DrvVidRegs,	0x300000, 0x30000f|0x3ff, MAP_RAM);
588 	SekMapMemory(DrvVideoRAM,	0x400000, 0x403fff, MAP_RAM);
589 	SekMapMemory(DrvSprRAM,		0x500000, 0x501fff, MAP_ROM);
590 	SekMapMemory(DrvPalRAM,		0x600000, 0x600fff, MAP_ROM);
591 	SekMapMemory(Drv68KRAM,		0x700000, 0x70ffff, MAP_RAM);
592 	SekSetWriteWordHandler(0,	sandscrp_main_write_word);
593 	SekSetWriteByteHandler(0,	sandscrp_main_write_byte);
594 	SekSetReadWordHandler(0,	sandscrp_main_read_word);
595 	SekSetReadByteHandler(0,	sandscrp_main_read_byte);
596 
597 	SekMapHandler(1,		0x500000, 0x501fff, MAP_WRITE);
598 	SekSetWriteWordHandler(1,	sandscrp_pandora_write_word);
599 	SekSetWriteByteHandler(1,	sandscrp_pandora_write_byte);
600 
601 	SekMapHandler(2,		0x600000, 0x600fff, MAP_WRITE);
602 	SekSetWriteWordHandler(2,	sandscrp_palette_write_word);
603 	SekSetWriteByteHandler(2,	sandscrp_palette_write_byte);
604 	SekClose();
605 
606 	ZetInit(0);
607 	ZetOpen(0);
608 	ZetMapMemory(DrvZ80ROM,	0x0000, 0xbfff, MAP_ROM);
609 	ZetMapMemory(DrvZ80RAM,	0xc000, 0xdfff, MAP_RAM);
610 	ZetSetOutHandler(sandscrp_sound_write_port);
611 	ZetSetInHandler(sandscrp_sound_read_port);
612 	ZetClose();
613 
614 	BurnYM2203Init(1, 4000000, &DrvFMIRQHandler, 0);
615 	BurnYM2203SetPorts(0, &DrvYM2203PortA, &DrvYM2203PortB, NULL, NULL);
616 	BurnTimerAttachZet(4000000);
617 	BurnYM2203SetRoute(0, BURN_SND_YM2203_YM2203_ROUTE, 0.50, BURN_SND_ROUTE_BOTH);
618 	BurnYM2203SetRoute(0, BURN_SND_YM2203_AY8910_ROUTE_1, 0.25, BURN_SND_ROUTE_BOTH);
619 	BurnYM2203SetRoute(0, BURN_SND_YM2203_AY8910_ROUTE_2, 0.25, BURN_SND_ROUTE_BOTH);
620 	BurnYM2203SetRoute(0, BURN_SND_YM2203_AY8910_ROUTE_3, 0.25, BURN_SND_ROUTE_BOTH);
621 
622 	MSM6295Init(0, 2000000 / 132, 1);
623 	MSM6295SetRoute(0, 0.80, BURN_SND_ROUTE_BOTH);
624 
625 	GenericTilesInit();
626 
627 	kaneko_view2_init(0, DrvVideoRAM, DrvVidRegs, DrvGfxROM0, 0x400, DrvTransTab, 91, 5);
628 	pandora_init(DrvPandoraRAM, DrvGfxROM1, (0x200000/0x100)-1, 0x000, 0, -16);
629 
630 	DrvDoReset(1);
631 
632 	return 0;
633 }
634 
DrvExit()635 static INT32 DrvExit()
636 {
637 	BurnYM2203Exit();
638 
639 	MSM6295Exit(0);
640 	MSM6295ROM = NULL;
641 
642 	SekExit();
643 	ZetExit();
644 
645 	pandora_exit();
646 	kaneko_view2_exit();
647 
648 	GenericTilesExit();
649 
650 	BurnFree (AllMem);
651 
652 	return 0;
653 }
654 
DrvDraw()655 static INT32 DrvDraw()
656 {
657 	if (DrvRecalc)
658 	{
659 		for (INT32 i = 0; i < 0x1000; i+=2) {
660 			palette_update(i);
661 		}
662 
663 		DrvRecalc = 0;
664 	}
665 
666 	BurnTransferClear();
667 
668 	for (INT32 i = 0; i < 4; i++) {
669 		kaneko_view2_draw_layer(0, 0, i);
670 		kaneko_view2_draw_layer(0, 1, i);
671 	}
672 
673 	pandora_update(pTransDraw);
674 
675 	for (INT32 i = 4; i < 8; i++) {
676 		kaneko_view2_draw_layer(0, 0, i);
677 		kaneko_view2_draw_layer(0, 1, i);
678 	}
679 
680 	BurnTransferCopy(DrvPalette);
681 
682 	return 0;
683 }
684 
DrvFrame()685 static INT32 DrvFrame()
686 {
687 	watchdog++;
688 	if (watchdog > 180) {
689 		DrvDoReset(0);
690 	}
691 
692 	if (DrvReset) {
693 		DrvDoReset(1);
694 	}
695 
696 	SekNewFrame();
697 	ZetNewFrame();
698 
699 	{
700 		memset (DrvInputs, 0xff, 3 * sizeof(UINT16));
701 		for (INT32 i = 0; i < 8; i++) {
702 			DrvInputs[0] ^= (DrvJoy1[i] & 1) << i;
703 			DrvInputs[1] ^= (DrvJoy2[i] & 1) << i;
704 			DrvInputs[2] ^= (DrvJoy3[i] & 1) << i;
705 		}
706 	}
707 
708 	INT32 nInterleave = 256;
709 	INT32 nCyclesTotal[2] =  { 20000000 / 60, 4000000 / 60 };
710 	INT32 nCyclesDone[2] = { 0, 0 };
711 
712 	SekOpen(0);
713 	ZetOpen(0);
714 
715 	for (INT32 i = 0; i < nInterleave; i++) {
716 
717 		CPU_RUN(0, Sek);
718 
719 		if (i == 240) {
720 			vblank_irq = 1;
721 			update_irq_state();
722 		}
723 
724 		if (i == 255) {
725 			sprite_irq = 1;
726 			update_irq_state();
727 		}
728 
729 		BurnTimerUpdate(SekTotalCycles()/5);
730 	}
731 
732 	BurnTimerEndFrame(nCyclesTotal[1]);
733 
734 	if (pBurnSoundOut) {
735 		BurnYM2203Update(pBurnSoundOut, nBurnSoundLen);
736 		MSM6295Render(0, pBurnSoundOut, nBurnSoundLen);
737 	}
738 
739 	ZetClose();
740 	SekClose();
741 
742 	if (pBurnDraw) {
743 		DrvDraw();
744 	}
745 
746 	pandora_buffer_sprites();
747 
748 	return 0;
749 }
750 
DrvScan(INT32 nAction,INT32 * pnMin)751 static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
752 {
753 	struct BurnArea ba;
754 
755 	if (pnMin) {
756 		*pnMin = 0x029707;
757 	}
758 
759 	if (nAction & ACB_VOLATILE) {
760 		memset(&ba, 0, sizeof(ba));
761 
762 		ba.Data	  = AllRam;
763 		ba.nLen	  = RamEnd - AllRam;
764 		ba.szName = "All Ram";
765 		BurnAcb(&ba);
766 
767 		ba.Data	  = &m_hit;
768 		ba.nLen	  = sizeof(calc1_hit_t);
769 		ba.szName = "hit calculation";
770 		BurnAcb(&ba);
771 
772 		SekScan(nAction);
773 		ZetScan(nAction);
774 
775 		BurnYM2203Scan(nAction, pnMin);
776 		MSM6295Scan(nAction, pnMin);
777 
778 		SCAN_VAR(vblank_irq);
779 		SCAN_VAR(sprite_irq);
780 		SCAN_VAR(unknown_irq);
781 		SCAN_VAR(soundlatch);
782 		SCAN_VAR(soundlatch2);
783 		SCAN_VAR(latch1_full);
784 		SCAN_VAR(latch2_full);
785 		SCAN_VAR(nDrvZ80Bank);
786 
787 		BurnRandomScan(nAction);
788 	}
789 
790 	if (nAction & ACB_WRITE) {
791 		ZetOpen(0);
792 		bankswitch(nDrvZ80Bank);
793 		ZetClose();
794 	}
795 
796 	return 0;
797 }
798 
799 
800 // Sand Scorpion
801 
802 static struct BurnRomInfo sandscrpRomDesc[] = {
803 	{ "11.bin",	0x40000, 0x9b24ab40, 1 | BRF_PRG | BRF_ESS }, //  0 68k Code
804 	{ "12.bin",	0x40000, 0xad12caee, 1 | BRF_PRG | BRF_ESS }, //  1
805 
806 	{ "8.ic51",	0x20000, 0x6f3e9db1, 2 | BRF_PRG | BRF_ESS }, //  2 Z80 Code
807 
808 	{ "4.ic32",	0x80000, 0xb9222ff2, 3 | BRF_GRA },           //  3 Tiles
809 	{ "3.ic33",	0x80000, 0xadf20fa0, 3 | BRF_GRA },           //  4
810 
811 	{ "5.ic16",	0x80000, 0x9bb675f6, 4 | BRF_GRA },           //  5 Sprites
812 	{ "6.ic17",	0x80000, 0x7df2f219, 4 | BRF_GRA },           //  6
813 
814 	{ "7.ic55",	0x40000, 0x9870ab12, 5 | BRF_SND },           //  7 Samples
815 };
816 
817 STD_ROM_PICK(sandscrp)
STD_ROM_FN(sandscrp)818 STD_ROM_FN(sandscrp)
819 
820 static INT32 sandscrpInit()
821 {
822 	return DrvInit(0);
823 }
824 
825 struct BurnDriver BurnDrvSandscrp = {
826 	"sandscrp", NULL, NULL, NULL, "1992",
827 	"Sand Scorpion\0", NULL, "Face", "Miscellaneous",
828 	NULL, NULL, NULL, NULL,
829 	BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0,
830 	NULL, sandscrpRomInfo, sandscrpRomName, NULL, NULL, NULL, NULL, SandscrpInputInfo, SandscrpDIPInfo,
831 	sandscrpInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800,
832 	224, 256, 3, 4
833 };
834 
835 
836 // Sand Scorpion (Earlier)
837 
838 static struct BurnRomInfo sandscrpaRomDesc[] = {
839 	{ "1.ic4",	0x40000, 0xc0943ae2, 1 | BRF_PRG | BRF_ESS }, //  0 68k Code
840 	{ "2.ic5",	0x40000, 0x6a8e0012, 1 | BRF_PRG | BRF_ESS }, //  1
841 
842 	{ "8.ic51",	0x20000, 0x6f3e9db1, 2 | BRF_PRG | BRF_ESS }, //  2 Z80 Code
843 
844 	{ "4.ic32",	0x80000, 0xb9222ff2, 3 | BRF_GRA },           //  3 Tiles
845 	{ "3.ic33",	0x80000, 0xadf20fa0, 3 | BRF_GRA },           //  4
846 
847 	{ "5.ic16",	0x80000, 0x9bb675f6, 4 | BRF_GRA },           //  5 Sprites
848 	{ "6.ic17",	0x80000, 0x7df2f219, 4 | BRF_GRA },           //  6
849 
850 	{ "7.ic55",	0x40000, 0x9870ab12, 5 | BRF_SND },           //  7 Samples
851 };
852 
853 STD_ROM_PICK(sandscrpa)
854 STD_ROM_FN(sandscrpa)
855 
856 struct BurnDriver BurnDrvSandscrpa = {
857 	"sandscrpa", "sandscrp", NULL, NULL, "1992",
858 	"Sand Scorpion (Earlier)\0", NULL, "Face", "Miscellaneous",
859 	NULL, NULL, NULL, NULL,
860 	BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0,
861 	NULL, sandscrpaRomInfo, sandscrpaRomName, NULL, NULL, NULL, NULL, SandscrpInputInfo, SandscrpDIPInfo,
862 	sandscrpInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800,
863 	224, 256, 3, 4
864 };
865 
866 
867 // Sand Scorpion (Chinese Title Screen, Revised Hardware)
868 
869 static struct BurnRomInfo sandscrpbRomDesc[] = {
870 	{ "11.ic4",	0x040000, 0x80020cab, 1 | BRF_PRG | BRF_ESS }, //  0 68k Code
871 	{ "12.ic5",	0x040000, 0x8df1d42f, 1 | BRF_PRG | BRF_ESS }, //  1
872 
873 	{ "8.ic51",	0x020000, 0x6f3e9db1, 2 | BRF_PRG | BRF_ESS }, //  2 Z80 Code
874 
875 	{ "ss501.ic30",	0x100000, 0x0cf9f99d, 3 | BRF_GRA },           //  3 Tiles
876 
877 	{ "ss502.ic16",	0x100000, 0xd8012ebb, 4 | BRF_GRA },           //  4 Sprites
878 
879 	{ "7.ic55",	0x040000, 0x9870ab12, 5 | BRF_SND },           //  5 Samples
880 };
881 
882 STD_ROM_PICK(sandscrpb)
STD_ROM_FN(sandscrpb)883 STD_ROM_FN(sandscrpb)
884 
885 static INT32 sandscrpbInit()
886 {
887 	return DrvInit(1);
888 }
889 
890 struct BurnDriver BurnDrvSandscrpb = {
891 	"sandscrpb", "sandscrp", NULL, NULL, "1992",
892 	"Sand Scorpion (Chinese Title Screen, Revised Hardware)\0", NULL, "Face", "Miscellaneous",
893 	NULL, NULL, NULL, NULL,
894 	BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0,
895 	NULL, sandscrpbRomInfo, sandscrpbRomName, NULL, NULL, NULL, NULL, SandscrpInputInfo, SandscrpDIPInfo,
896 	sandscrpbInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x800,
897 	224, 256, 3, 4
898 };
899