1 // FB Alpha Heavy Unit driver module
2 // Based on MAME drivery Angelo Salese, Tomasz Slanina, and David Haywood
3 
4 #include "tiles_generic.h"
5 #include "z80_intf.h"
6 #include "mermaid.h"
7 #include "burn_ym2203.h"
8 #include "pandora.h"
9 
10 static UINT8 *AllMem;
11 static UINT8 *MemEnd;
12 static UINT8 *AllRam;
13 static UINT8 *RamEnd;
14 static UINT8 *DrvZ80ROM0;
15 static UINT8 *DrvZ80ROM1;
16 static UINT8 *DrvZ80ROM2;
17 static UINT8 *DrvMCUROM;
18 static UINT8 *DrvGfxROM0;
19 static UINT8 *DrvGfxROM1;
20 static UINT8 *DrvSprRAM;
21 static UINT8 *DrvPandoraRAM;
22 static UINT8 *DrvZ80RAM0;
23 static UINT8 *DrvZ80RAM1;
24 static UINT8 *DrvZ80RAM2;
25 static UINT8 *DrvShareRAM;
26 static UINT8 *DrvVidRAM;
27 static UINT8 *DrvColRAM;
28 static UINT8 *DrvPalRAM;
29 
30 static UINT32 *DrvPalette;
31 static UINT8  DrvRecalc;
32 
33 static UINT16 scrollx;
34 static UINT16 scrolly;
35 static UINT8 soundlatch;
36 static UINT8 z80banks[3];
37 
38 static INT32 nExtraCycles[4];
39 
40 static UINT8 DrvJoy1[8];
41 static UINT8 DrvJoy2[8];
42 static UINT8 DrvJoy3[8];
43 static UINT8 DrvInputs[6];
44 static UINT8 DrvReset;
45 
46 static struct BurnInputInfo HvyunitInputList[] = {
47 	{"P1 Coin",		BIT_DIGITAL,	DrvJoy1 + 2,	"p1 coin"	},
48 	{"P1 Start",		BIT_DIGITAL,	DrvJoy1 + 0,	"p1 start"	},
49 	{"P1 Up",		BIT_DIGITAL,	DrvJoy2 + 0,	"p1 up"		},
50 	{"P1 Down",		BIT_DIGITAL,	DrvJoy2 + 1,	"p1 down"	},
51 	{"P1 Left",		BIT_DIGITAL,	DrvJoy2 + 2,	"p1 left"	},
52 	{"P1 Right",		BIT_DIGITAL,	DrvJoy2 + 3,	"p1 right"	},
53 	{"P1 Button 1",		BIT_DIGITAL,	DrvJoy2 + 4,	"p1 fire 1"	},
54 	{"P1 Button 2",		BIT_DIGITAL,	DrvJoy2 + 5,	"p1 fire 2"	},
55 
56 	{"P2 Coin",		BIT_DIGITAL,	DrvJoy1 + 3,	"p2 coin"	},
57 	{"P2 Start",		BIT_DIGITAL,	DrvJoy1 + 1,	"p2 start"	},
58 	{"P2 Up",		BIT_DIGITAL,	DrvJoy3 + 0,	"p2 up"		},
59 	{"P2 Down",		BIT_DIGITAL,	DrvJoy3 + 1,	"p2 down"	},
60 	{"P2 Left",		BIT_DIGITAL,	DrvJoy3 + 2,	"p2 left"	},
61 	{"P2 Right",		BIT_DIGITAL,	DrvJoy3 + 3,	"p2 right"	},
62 	{"P2 Button 1",		BIT_DIGITAL,	DrvJoy3 + 4,	"p2 fire 1"	},
63 	{"P2 Button 2",		BIT_DIGITAL,	DrvJoy3 + 5,	"p2 fire 2"	},
64 
65 	{"Reset",		BIT_DIGITAL,	&DrvReset,	"reset"		},
66 	{"Dip A",		BIT_DIPSWITCH,	DrvInputs + 4,	"dip"		},
67 	{"Dip B",		BIT_DIPSWITCH,	DrvInputs + 5,	"dip"		},
68 };
69 
70 STDINPUTINFO(Hvyunit)
71 
72 static struct BurnDIPInfo HvyunitDIPList[]=
73 {
74 	{0x11, 0xff, 0xff, 0xfe, NULL			},
75 	{0x12, 0xff, 0xff, 0xf7, NULL			},
76 
77 	{0   , 0xfe, 0   ,    1, "Cabinet"		},
78 	{0x11, 0x01, 0x01, 0x00, "Upright"		},
79 //	{0x11, 0x01, 0x01, 0x01, "Cocktail"		},
80 
81 	{0   , 0xfe, 0   ,    2, "Flip Screen"		},
82 	{0x11, 0x01, 0x02, 0x02, "Off"			},
83 	{0x11, 0x01, 0x02, 0x00, "On"			},
84 
85 	{0   , 0xfe, 0   ,    2, "Service Mode"		},
86 	{0x11, 0x01, 0x04, 0x04, "Off"			},
87 	{0x11, 0x01, 0x04, 0x00, "On"			},
88 
89 	{0   , 0xfe, 0   ,    2, "Coin Mode"		},
90 	{0x11, 0x01, 0x08, 0x08, "Mode 1"		},
91 	{0x11, 0x01, 0x08, 0x00, "Mode 2"		},
92 
93 	{0   , 0xfe, 0   ,    8, "Coin A"		},
94 	{0x11, 0x01, 0x30, 0x20, "2 Coins 1 Credits"	},
95 	{0x11, 0x01, 0x30, 0x30, "1 Coin  1 Credits"	},
96 	{0x11, 0x01, 0x30, 0x10, "1 Coin  2 Credits"	},
97 	{0x11, 0x01, 0x30, 0x00, "1 Coin  6 Credits"	},
98 	{0x11, 0x01, 0x30, 0x20, "2 Coins 1 Credits"	},
99 	{0x11, 0x01, 0x30, 0x30, "1 Coin  1 Credits"	},
100 	{0x11, 0x01, 0x30, 0x10, "1 Coin  3 Credits"	},
101 	{0x11, 0x01, 0x30, 0x00, "1 Coin  4 Credits"	},
102 
103 	{0   , 0xfe, 0   ,    8, "Coin B"		},
104 	{0x11, 0x01, 0xc0, 0x80, "2 Coins 1 Credits"	},
105 	{0x11, 0x01, 0xc0, 0xc0, "1 Coin  1 Credits"	},
106 	{0x11, 0x01, 0xc0, 0x40, "1 Coin  2 Credits"	},
107 	{0x11, 0x01, 0xc0, 0x00, "1 Coin  6 Credits"	},
108 	{0x11, 0x01, 0xc0, 0x80, "2 Coins 1 Credits"	},
109 	{0x11, 0x01, 0xc0, 0xc0, "1 Coin  1 Credits"	},
110 	{0x11, 0x01, 0xc0, 0x40, "1 Coin  3 Credits"	},
111 	{0x11, 0x01, 0xc0, 0x00, "1 Coin  4 Credits"	},
112 
113 	{0   , 0xfe, 0   ,    4, "Difficulty"		},
114 	{0x12, 0x01, 0x03, 0x02, "Easy"			},
115 	{0x12, 0x01, 0x03, 0x03, "Normal"		},
116 	{0x12, 0x01, 0x03, 0x01, "Hard"			},
117 	{0x12, 0x01, 0x03, 0x00, "Hardest"		},
118 
119 	{0   , 0xfe, 0   ,    2, "Allow Continue"	},
120 	{0x12, 0x01, 0x04, 0x00, "Off"			},
121 	{0x12, 0x01, 0x04, 0x04, "On"			},
122 
123 	{0   , 0xfe, 0   ,    2, "Bonus"		},
124 	{0x12, 0x01, 0x08, 0x08, "Off"			},
125 	{0x12, 0x01, 0x08, 0x00, "On"			},
126 
127 	{0   , 0xfe, 0   ,    4, "Lives"		},
128 	{0x12, 0x01, 0x30, 0x30, "3"			},
129 	{0x12, 0x01, 0x30, 0x20, "4"			},
130 	{0x12, 0x01, 0x30, 0x10, "5"			},
131 	{0x12, 0x01, 0x30, 0x00, "7"			},
132 
133 	{0   , 0xfe, 0   ,    2, "Demo Sounds"		},
134 	{0x12, 0x01, 0x40, 0x00, "Off"			},
135 	{0x12, 0x01, 0x40, 0x40, "On"			},
136 };
137 
138 STDDIPINFO(Hvyunit)
139 
140 static struct BurnDIPInfo HvyunitjDIPList[]=
141 {
142 	{0x11, 0xff, 0xff, 0xfe, NULL			},
143 	{0x12, 0xff, 0xff, 0xf7, NULL			},
144 
145 	{0   , 0xfe, 0   ,    1, "Cabinet"		},
146 	{0x11, 0x01, 0x01, 0x00, "Upright"		},
147 //	{0x11, 0x01, 0x01, 0x01, "Cocktail"		},
148 
149 	{0   , 0xfe, 0   ,    2, "Flip Screen"		},
150 	{0x11, 0x01, 0x02, 0x02, "Off"			},
151 	{0x11, 0x01, 0x02, 0x00, "On"			},
152 
153 	{0   , 0xfe, 0   ,    2, "Service Mode"		},
154 	{0x11, 0x01, 0x04, 0x04, "Off"			},
155 	{0x11, 0x01, 0x04, 0x00, "On"			},
156 
157 	{0   , 0xfe, 0   ,    4, "Coin A"		},
158 	{0x11, 0x01, 0x30, 0x10, "2 Coins 1 Credits"	},
159 	{0x11, 0x01, 0x30, 0x30, "1 Coin  1 Credits"	},
160 	{0x11, 0x01, 0x30, 0x00, "2 Coins 3 Credits"	},
161 	{0x11, 0x01, 0x30, 0x20, "1 Coin  2 Credits"	},
162 
163 	{0   , 0xfe, 0   ,    4, "Coin B"		},
164 	{0x11, 0x01, 0xc0, 0x40, "2 Coins 1 Credits"	},
165 	{0x11, 0x01, 0xc0, 0xc0, "1 Coin  1 Credits"	},
166 	{0x11, 0x01, 0xc0, 0x00, "2 Coins 3 Credits"	},
167 	{0x11, 0x01, 0xc0, 0x80, "1 Coin  2 Credits"	},
168 
169 	{0   , 0xfe, 0   ,    4, "Difficulty"		},
170 	{0x12, 0x01, 0x03, 0x02, "Easy"			},
171 	{0x12, 0x01, 0x03, 0x03, "Normal"		},
172 	{0x12, 0x01, 0x03, 0x01, "Hard"			},
173 	{0x12, 0x01, 0x03, 0x00, "Hardest"		},
174 
175 	{0   , 0xfe, 0   ,    2, "Allow Continue"	},
176 	{0x12, 0x01, 0x04, 0x00, "Off"			},
177 	{0x12, 0x01, 0x04, 0x04, "On"			},
178 
179 	{0   , 0xfe, 0   ,    2, "Bonus"		},
180 	{0x12, 0x01, 0x08, 0x08, "Off"			},
181 	{0x12, 0x01, 0x08, 0x00, "On"			},
182 
183 	{0   , 0xfe, 0   ,    4, "Lives"		},
184 	{0x12, 0x01, 0x30, 0x30, "3"			},
185 	{0x12, 0x01, 0x30, 0x20, "4"			},
186 	{0x12, 0x01, 0x30, 0x10, "5"			},
187 	{0x12, 0x01, 0x30, 0x00, "7"			},
188 
189 	{0   , 0xfe, 0   ,    2, "Demo Sounds"		},
190 	{0x12, 0x01, 0x40, 0x00, "Off"			},
191 	{0x12, 0x01, 0x40, 0x40, "On"			},
192 };
193 
STDDIPINFO(Hvyunitj)194 STDDIPINFO(Hvyunitj)
195 
196 static void __fastcall hvyunit_main_write(UINT16 address, UINT8 data)
197 {
198 	if ((address & 0xf000) == 0xc000) {
199 		DrvSprRAM[address & 0xfff] = data;
200 
201 		address = (address & 0x800) | ((address & 0xff) << 3) | ((address & 0x700) >> 8);
202 
203 		DrvPandoraRAM[address] = data;
204 		return;
205 	}
206 }
207 
master_bankswitch(INT32 data)208 static void master_bankswitch(INT32 data)
209 {
210 	z80banks[0] = data;
211 	INT32 bank = (data & 7) * 0x4000;
212 
213 	ZetMapMemory(DrvZ80ROM0 + bank, 0x8000, 0xbfff, MAP_ROM);
214 }
215 
hvyunit_main_write_port(UINT16 port,UINT8 data)216 static void __fastcall hvyunit_main_write_port(UINT16 port, UINT8 data)
217 {
218 	switch (port & 0xff)
219 	{
220 		case 0x00:
221 		case 0x01:
222 			master_bankswitch(data);
223 		return;
224 
225 		case 0x02:
226 		{
227 			ZetNmi(1);
228 		}
229 		return;
230 	}
231 }
232 
slave_bankswitch(INT32 data)233 static void slave_bankswitch(INT32 data)
234 {
235 	z80banks[1] = data;
236 	INT32 bank = (data & 0x03) * 0x4000;
237 
238 	ZetMapMemory(DrvZ80ROM1 + bank,	0x8000, 0xbfff, MAP_ROM);
239 }
240 
hvyunit_sub_write_port(UINT16 port,UINT8 data)241 static void __fastcall hvyunit_sub_write_port(UINT16 port, UINT8 data)
242 {
243 	switch (port & 0xff)
244 	{
245 		case 0x00:
246 			scrollx = (scrollx & 0xff) | ((data & 0x40) << 2);
247 			scrolly = (scrolly & 0xff) | ((data & 0x80) << 1);
248 			slave_bankswitch(data);
249 		return;
250 
251 		case 0x02:
252 		{
253 			soundlatch = data;
254 			ZetNmi(2);
255 		}
256 		return;
257 
258 		case 0x04:
259 			mermaidWrite(data);
260 		return;
261 
262 		case 0x06:
263 			scrolly = (scrolly & 0x100) | data;
264 		return;
265 
266 		case 0x08:
267 			scrollx = (scrollx & 0x100) | data;
268 		return;
269 
270 		case 0x0e:
271 			// coin counter
272 		return;
273 	}
274 }
275 
hvyunit_sub_read_port(UINT16 port)276 static UINT8 __fastcall hvyunit_sub_read_port(UINT16 port)
277 {
278 	switch (port & 0xff)
279 	{
280 		case 0x04:
281 			return mermaidRead();
282 
283 		case 0x0c:
284 			return mermaidStatus();
285 	}
286 
287 	return 0;
288 }
289 
sound_bankswitch(INT32 data)290 static void sound_bankswitch(INT32 data)
291 {
292 	z80banks[2] = data;
293 	INT32 bank = (data & 0x03) * 0x4000;
294 
295 	ZetMapMemory(DrvZ80ROM2 + bank,	0x8000, 0xbfff, MAP_ROM);
296 }
297 
hvyunit_sound_write_port(UINT16 port,UINT8 data)298 static void __fastcall hvyunit_sound_write_port(UINT16 port, UINT8 data)
299 {
300 	switch (port & 0xff)
301 	{
302 		case 0x00:
303 			sound_bankswitch(data);
304 		return;
305 
306 		case 0x02:
307 		case 0x03:
308 			BurnYM2203Write(0, port & 1, data);
309 		return;
310 	}
311 }
312 
hvyunit_sound_read_port(UINT16 port)313 static UINT8 __fastcall hvyunit_sound_read_port(UINT16 port)
314 {
315 	switch (port & 0xff)
316 	{
317 		case 0x02:
318 		case 0x03:
319 			return BurnYM2203Read(0, port & 1);
320 
321 		case 0x04:
322 			return soundlatch;
323 	}
324 
325 	return 0;
326 }
327 
DrvDoReset()328 static INT32 DrvDoReset()
329 {
330 	memset (AllRam, 0, RamEnd - AllRam);
331 
332 	ZetOpen(0);
333 	ZetReset();
334 	master_bankswitch(0);
335 	ZetClose();
336 
337 	ZetOpen(1);
338 	ZetReset();
339 	slave_bankswitch(0);
340 	ZetClose();
341 
342 	ZetOpen(2);
343 	ZetReset();
344 	sound_bankswitch(0);
345 	BurnYM2203Reset();
346 	ZetClose();
347 
348 	mermaidReset();
349 
350 	scrollx = 0;
351 	scrolly = 0;
352 	soundlatch = 0;
353 
354 	nExtraCycles[0] = nExtraCycles[1] = nExtraCycles[2] = nExtraCycles[3] = 0;
355 
356 	return 0;
357 }
358 
DrvGfxDecode()359 static INT32 DrvGfxDecode()
360 {
361 	static INT32 Plane[4]  = { STEP4(0,1) };
362 	static INT32 XOffs[16] = { STEP8(0,4), STEP8(256,4) };
363 	static INT32 YOffs[16] = { STEP8(0,32), STEP8(512,32) };
364 
365 	UINT8 *tmp = (UINT8*)BurnMalloc(0x200000);
366 	if (tmp == NULL) {
367 		return 1;
368 	}
369 
370 	memcpy (tmp, DrvGfxROM0, 0x200000);
371 
372 	GfxDecode(0x4000, 4, 16, 16, Plane, XOffs, YOffs, 0x400, tmp, DrvGfxROM0);
373 
374 	memcpy (tmp, DrvGfxROM1, 0x080000);
375 
376 	GfxDecode(0x1000, 4, 16, 16, Plane, XOffs, YOffs, 0x400, tmp, DrvGfxROM1);
377 
378 	BurnFree (tmp);
379 
380 	return 0;
381 }
382 
MemIndex()383 static INT32 MemIndex()
384 {
385 	UINT8 *Next; Next = AllMem;
386 
387 	DrvZ80ROM0		= Next; Next += 0x020000;
388 	DrvZ80ROM1		= Next; Next += 0x010000;
389 	DrvZ80ROM2		= Next; Next += 0x010000;
390 
391 	DrvMCUROM		= Next; Next += 0x001000;
392 
393 	DrvGfxROM0		= Next; Next += 0x400000;
394 	DrvGfxROM1		= Next; Next += 0x100000;
395 
396 	DrvPalette		= (UINT32*)Next; Next += 0x0200 * sizeof(UINT32);
397 
398 	AllRam			= Next;
399 
400 	DrvSprRAM		= Next; Next += 0x001000;
401 	DrvPandoraRAM		= Next; Next += 0x001000;
402 	DrvZ80RAM0		= Next; Next += 0x001000;
403 	DrvZ80RAM1		= Next; Next += 0x001000;
404 	DrvShareRAM		= Next; Next += 0x002000;
405 	DrvVidRAM		= Next; Next += 0x000400;
406 	DrvColRAM		= Next; Next += 0x000400;
407 	DrvPalRAM		= Next; Next += 0x000400;
408 	DrvZ80RAM2		= Next; Next += 0x000800;
409 
410 	RamEnd			= Next;
411 
412 	MemEnd			= Next;
413 
414 	return 0;
415 }
416 
DrvInit(INT32 select)417 static INT32 DrvInit(INT32 select)
418 {
419 	BurnSetRefreshRate(58);
420 
421 	AllMem = NULL;
422 	MemIndex();
423 	INT32 nLen = MemEnd - (UINT8 *)0;
424 	if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1;
425 	memset(AllMem, 0, nLen);
426 	MemIndex();
427 
428 	{
429 		if (BurnLoadRom(DrvZ80ROM0 + 0x000000,  0, 1)) return 1;
430 
431 		if (BurnLoadRom(DrvZ80ROM1 + 0x000000,  1, 1)) return 1;
432 
433 		if (BurnLoadRom(DrvZ80ROM2 + 0x000000,  2, 1)) return 1;
434 
435 		if (BurnLoadRom(DrvMCUROM  + 0x000000,  3, 1)) return 1;
436 
437 		switch (select)
438 		{
439 			case 0: // hvyunit, hvyunitjo
440 			{
441 				if (BurnLoadRom(DrvGfxROM0 + 0x000000,  4, 1)) return 1;
442 				if (BurnLoadRom(DrvGfxROM0 + 0x100000,  5, 1)) return 1;
443 				if (BurnLoadRom(DrvGfxROM0 + 0x120000,  6, 1)) return 1;
444 				if (BurnLoadRom(DrvGfxROM0 + 0x140000,  7, 1)) return 1;
445 				if (BurnLoadRom(DrvGfxROM0 + 0x160000,  8, 1)) return 1;
446 				if (BurnLoadRom(DrvGfxROM0 + 0x180000,  9, 1)) return 1;
447 				if (BurnLoadRom(DrvGfxROM0 + 0x1a0000, 10, 1)) return 1;
448 				if (BurnLoadRom(DrvGfxROM0 + 0x1c0000, 11, 1)) return 1;
449 
450 				if (BurnLoadRom(DrvGfxROM1 + 0x00000,  12, 1)) return 1;
451 			}
452 			break;
453 
454 			case 1: // hvyunitj
455 			{
456 				if (BurnLoadRom(DrvGfxROM0 + 0x000000,  4, 1)) return 1;
457 				if (BurnLoadRom(DrvGfxROM0 + 0x100000,  5, 1)) return 1;
458 				if (BurnLoadRom(DrvGfxROM0 + 0x110000,  6, 1)) return 1;
459 				if (BurnLoadRom(DrvGfxROM0 + 0x120000,  7, 1)) return 1;
460 				if (BurnLoadRom(DrvGfxROM0 + 0x130000,  8, 1)) return 1;
461 				if (BurnLoadRom(DrvGfxROM0 + 0x140000,  9, 1)) return 1;
462 				if (BurnLoadRom(DrvGfxROM0 + 0x150000, 10, 1)) return 1;
463 				if (BurnLoadRom(DrvGfxROM0 + 0x160000, 11, 1)) return 1;
464 
465 				if (BurnLoadRom(DrvGfxROM1 + 0x00000,  12, 1)) return 1;
466 			}
467 			break;
468 
469 			case 2: // hvyunitu
470 			{
471 				if (BurnLoadRom(DrvGfxROM0 + 0x000000,  4, 1)) return 1;
472 				if (BurnLoadRom(DrvGfxROM0 + 0x100000,  5, 1)) return 1;
473 				if (BurnLoadRom(DrvGfxROM0 + 0x120000,  6, 1)) return 1;
474 				if (BurnLoadRom(DrvGfxROM0 + 0x140000,  7, 1)) return 1;
475 				if (BurnLoadRom(DrvGfxROM0 + 0x160000,  8, 1)) return 1;
476 
477 				if (BurnLoadRom(DrvGfxROM1 + 0x00000,   9, 1)) return 1;
478 			}
479 			break;
480 		}
481 
482 		DrvGfxDecode();
483 	}
484 
485 	ZetInit(0);
486 	ZetOpen(0);
487 	ZetMapMemory(DrvZ80ROM0,	0x0000, 0x7fff, MAP_ROM);
488 	ZetMapMemory(DrvSprRAM,		0xc000, 0xcfff, MAP_ROM);
489 	ZetMapMemory(DrvZ80RAM0,	0xd000, 0xdfff, MAP_RAM);
490 	ZetMapMemory(DrvShareRAM,	0xe000, 0xffff, MAP_RAM);
491 	ZetSetWriteHandler(hvyunit_main_write);
492 	//ZetSetReadHandler(hvyunit_main_read);
493 	ZetSetOutHandler(hvyunit_main_write_port);
494 	//ZetSetInHandler(hvyunit_main_read_port);
495 	ZetClose();
496 
497 	ZetInit(1);
498 	ZetOpen(1);
499 	ZetMapMemory(DrvZ80ROM1,	0x0000, 0x7fff, MAP_ROM);
500 	ZetMapMemory(DrvVidRAM,		0xc000, 0xc3ff, MAP_RAM);
501 	ZetMapMemory(DrvColRAM,		0xc400, 0xc7ff, MAP_RAM);
502 	ZetMapMemory(DrvZ80RAM1,	0xd000, 0xdfff, MAP_RAM);
503 	ZetMapMemory(DrvPalRAM + 0x200,	0xd000, 0xd1ff, MAP_RAM);
504 	ZetMapMemory(DrvPalRAM,		0xd800, 0xd9ff, MAP_RAM);
505 	ZetMapMemory(DrvShareRAM,	0xe000, 0xffff, MAP_RAM);
506 	ZetSetOutHandler(hvyunit_sub_write_port);
507 	ZetSetInHandler(hvyunit_sub_read_port);
508 	ZetClose();
509 
510 	ZetInit(2);
511 	ZetOpen(2);
512 	ZetMapMemory(DrvZ80ROM2,	0x0000, 0x7fff, MAP_ROM);
513 	ZetMapMemory(DrvZ80RAM2,	0xc000, 0xc7ff, MAP_RAM);
514 	ZetSetOutHandler(hvyunit_sound_write_port);
515 	ZetSetInHandler(hvyunit_sound_read_port);
516 	ZetClose();
517 
518 	mermaidInit(DrvMCUROM, DrvInputs);
519 
520 	BurnYM2203Init(1, 3000000, NULL, 0);
521 	BurnTimerAttachZet(6000000);
522 	BurnYM2203SetRoute(0, BURN_SND_YM2203_YM2203_ROUTE, 0.50, BURN_SND_ROUTE_BOTH);
523 	BurnYM2203SetRoute(0, BURN_SND_YM2203_AY8910_ROUTE_1, 0.25, BURN_SND_ROUTE_BOTH);
524 	BurnYM2203SetRoute(0, BURN_SND_YM2203_AY8910_ROUTE_2, 0.25, BURN_SND_ROUTE_BOTH);
525 	BurnYM2203SetRoute(0, BURN_SND_YM2203_AY8910_ROUTE_3, 0.25, BURN_SND_ROUTE_BOTH);
526 
527 	GenericTilesInit();
528 
529 	pandora_init(DrvPandoraRAM, DrvGfxROM0, (0x400000/0x100)-1, 0x100, 0, -16);
530 
531 	DrvDoReset();
532 
533 	return 0;
534 }
535 
DrvExit()536 static INT32 DrvExit()
537 {
538 	pandora_exit();
539 
540 	GenericTilesExit();
541 
542 	ZetExit();
543 	mermaidExit();
544 
545 	BurnYM2203Exit();
546 
547 	BurnFree(AllMem);
548 
549 	return 0;
550 }
551 
DrvRecalcPalette()552 static void DrvRecalcPalette()
553 {
554 	for (INT32 i = 0; i < 0x400/2; i++) {
555 		INT32 r = DrvPalRAM[0x200+i] & 0xf;
556 		INT32 g = (DrvPalRAM[i] >> 4) & 0xf;
557 		INT32 b = DrvPalRAM[i] & 0xf;
558 
559 		DrvPalette[i] = BurnHighCol(r|r*16, g|g*16, b|b*16, 0);
560 	}
561 }
562 
draw_layer()563 static void draw_layer()
564 {
565 	for (INT32 offs = 0; offs < 32 * 32; offs++)
566 	{
567 		INT32 sx = (offs & 0x1f) * 16;
568 		INT32 sy = (offs / 0x20) * 16;
569 
570 		sx -= (scrollx + 96) & 0x1ff;
571 		sy -= (scrolly + 16);
572 		if (sx < -15) sx += 512;
573 		if (sy < -15) sy += 512;
574 		if (sx >= nScreenWidth || sy >= nScreenHeight) continue;
575 
576 		INT32 code  = DrvVidRAM[offs] | (DrvColRAM[offs] << 8);
577 		INT32 color = code >> 12;
578 
579 		Render16x16Tile_Clip(pTransDraw, code & 0xfff, sx, sy, color, 4, 0, DrvGfxROM1);
580 	}
581 }
582 
DrvDraw()583 static INT32 DrvDraw()
584 {
585 	DrvRecalcPalette();
586 
587 	draw_layer();
588 
589 	pandora_flipscreen = 0;
590 	pandora_update(pTransDraw);
591 
592 	BurnTransferCopy(DrvPalette);
593 
594 	return 0;
595 }
596 
DrvFrame()597 static INT32 DrvFrame()
598 {
599 	if (DrvReset) {
600 		DrvDoReset();
601 	}
602 
603 	ZetNewFrame();
604 	// mermaid new frame
605 
606 	{
607 		memset (DrvInputs, 0xff, 4);
608 		for (INT32 i = 0; i < 8; i++) {
609 			DrvInputs[2] ^= (DrvJoy1[i] & 1) << i;
610 			DrvInputs[0] ^= (DrvJoy2[i] & 1) << i;
611 			DrvInputs[1] ^= (DrvJoy3[i] & 1) << i;
612 		}
613 	}
614 
615 	INT32 nInterleave = 256*4;
616 	INT32 nCyclesTotal[4] =  { 6000000 / 58, 6000000 / 58, 6000000 / 58, 6000000 / 12 / 58 };
617 	INT32 nCyclesDone[4] = { nExtraCycles[0], nExtraCycles[1], nExtraCycles[2], nExtraCycles[3] };
618 
619 	for (INT32 i = 0; i < nInterleave; i++) {
620 
621 		INT32 nSegment;
622 
623 		ZetOpen(0);
624 		if (i == 64*4) {
625 			ZetSetVector(0xff);
626 			ZetSetIRQLine(0, CPU_IRQSTATUS_HOLD);
627 		}
628 		if (i == 240*4) {
629 			ZetSetVector(0xfd);
630 			ZetSetIRQLine(0, CPU_IRQSTATUS_HOLD);
631 		}
632 		nSegment = (nCyclesTotal[0] * (i + 1) / nInterleave) - nCyclesDone[0];
633 		nCyclesDone[0] += ZetRun(nSegment);
634 		ZetClose();
635 
636 		ZetOpen(1);
637 		if (i == 240*4) ZetSetIRQLine(0, CPU_IRQSTATUS_HOLD);
638 		nSegment = (nCyclesTotal[1] * (i + 1) / nInterleave) - nCyclesDone[1];
639 		nCyclesDone[1] += ZetRun(nSegment);
640 		ZetClose();
641 
642 		ZetOpen(2);
643 		if (i == 240*4) ZetSetIRQLine(0, CPU_IRQSTATUS_HOLD);
644 		BurnTimerUpdate((i + 1) * nCyclesTotal[2] / nInterleave);
645 		ZetClose();
646 
647 		nSegment = (nCyclesTotal[3] * (i + 1) / nInterleave) - nCyclesDone[3];
648 		nCyclesDone[3] += mermaidRun(nSegment);
649 
650 		if (i == 239*4) {
651 			pandora_buffer_sprites();
652 
653 			if (pBurnDraw) {
654 				DrvDraw();
655 			}
656 		}
657 	}
658 
659 	ZetOpen(2);
660 	BurnTimerEndFrame(nCyclesTotal[2]);
661 
662 	if (pBurnSoundOut) {
663 		BurnYM2203Update(pBurnSoundOut, nBurnSoundLen);
664 	}
665 
666 	ZetClose();
667 
668 	nExtraCycles[0] = nCyclesDone[0] - nCyclesTotal[0];
669 	nExtraCycles[1] = nCyclesDone[1] - nCyclesTotal[1];
670 	nExtraCycles[3] = nCyclesDone[3] - nCyclesTotal[3];
671 
672 	return 0;
673 }
674 
DrvScan(INT32 nAction,INT32 * pnMin)675 static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
676 {
677 	struct BurnArea ba;
678 
679 	if (pnMin != NULL) {
680 		*pnMin = 0x029672;
681 	}
682 
683 	if (nAction & ACB_MEMORY_RAM) {
684 		memset(&ba, 0, sizeof(ba));
685 		ba.Data	  = AllRam;
686 		ba.nLen	  = RamEnd-AllRam;
687 		ba.szName = "All Ram";
688 		BurnAcb(&ba);
689 	}
690 
691 	if (nAction & ACB_DRIVER_DATA) {
692 		ZetScan(nAction);
693 		mermaidScan(nAction);
694 
695 		BurnYM2203Scan(nAction, pnMin);
696 
697 		SCAN_VAR(scrollx);
698 		SCAN_VAR(scrolly);
699 		SCAN_VAR(soundlatch);
700 		SCAN_VAR(z80banks);
701 		SCAN_VAR(nExtraCycles);
702 	}
703 
704 	if (nAction & ACB_WRITE) {
705 		ZetOpen(0);
706 		master_bankswitch(z80banks[0]);
707 		ZetClose();
708 
709 		ZetOpen(1);
710 		slave_bankswitch(z80banks[1]);
711 		ZetClose();
712 
713 		ZetOpen(2);
714 		sound_bankswitch(z80banks[2]);
715 		ZetClose();
716 	}
717 
718 	return 0;
719 }
720 
721 
722 // Heavy Unit (World)
723 
724 static struct BurnRomInfo hvyunitRomDesc[] = {
725 	{ "b73_10.5c",		0x20000, 0xca52210f, 1 | BRF_PRG | BRF_ESS }, //  0 Z80 #0 Code
726 
727 	{ "b73_11.5p",		0x10000, 0xcb451695, 2 | BRF_PRG | BRF_ESS }, //  1 Z80 #1 Code
728 
729 	{ "b73_12.7e",		0x10000, 0xd1d24fab, 3 | BRF_PRG | BRF_ESS }, //  2 Z80 #2 Code
730 
731 	{ "mermaid.bin",	0x00e00, 0x88c5dd27, 4 | BRF_PRG | BRF_ESS }, //  3 I80C51 (mermaid) Code
732 
733 	{ "b73_08.2f",		0x80000, 0xf83dd808, 5 | BRF_GRA },           //  4 Sprites
734 	{ "b73_07.2c",		0x10000, 0x5cffa42c, 5 | BRF_GRA },           //  5
735 	{ "b73_06.2b",		0x10000, 0xa98e4aea, 5 | BRF_GRA },           //  6
736 	{ "b73_01.1b",		0x10000, 0x3a8a4489, 5 | BRF_GRA },           //  7
737 	{ "b73_02.1c",		0x10000, 0x025c536c, 5 | BRF_GRA },           //  8
738 	{ "b73_03.1d",		0x10000, 0xec6020cf, 5 | BRF_GRA },           //  9
739 	{ "b73_04.1f",		0x10000, 0xf7badbb2, 5 | BRF_GRA },           // 10
740 	{ "b73_05.1h",		0x10000, 0xb8e829d2, 5 | BRF_GRA },           // 11
741 
742 	{ "b73_09.2p",		0x80000, 0x537c647f, 6 | BRF_GRA },           // 12 Background Tiles
743 };
744 
745 STD_ROM_PICK(hvyunit)
STD_ROM_FN(hvyunit)746 STD_ROM_FN(hvyunit)
747 
748 static INT32 hvyunitInit()
749 {
750 	return DrvInit(0);
751 }
752 
753 struct BurnDriver BurnDrvHvyunit = {
754 	"hvyunit", NULL, NULL, NULL, "1988",
755 	"Heavy Unit (World)\0", NULL, "Kaneko / Taito", "Miscellaneous",
756 	NULL, NULL, NULL, NULL,
757 	BDF_GAME_WORKING, 2, HARDWARE_KANEKO_MISC, GBF_VERSHOOT, 0,
758 	NULL, hvyunitRomInfo, hvyunitRomName, NULL, NULL, NULL, NULL, HvyunitInputInfo, HvyunitDIPInfo,
759 	hvyunitInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200,
760 	256, 224, 4, 3
761 };
762 
763 
764 // Heavy Unit (Japan, Newer)
765 
766 static struct BurnRomInfo hvyunitjRomDesc[] = {
767 	{ "b73_30.5c",		0x20000, 0x600af545, 1 | BRF_PRG | BRF_ESS }, //  0 Z80 #0 Code
768 
769 	{ "b73_14.5p",		0x10000, 0x0dfb51d4, 2 | BRF_PRG | BRF_ESS }, //  1 Z80 #1 Code
770 
771 	{ "b73_12.7e",		0x10000, 0xd1d24fab, 3 | BRF_PRG | BRF_ESS }, //  2 Z80 #2 Code
772 
773 	{ "mermaid.bin",	0x00e00, 0x88c5dd27, 4 | BRF_PRG | BRF_ESS }, //  3 I80C51 (mermaid) Code
774 
775 	{ "b73_08.2f",		0x80000, 0xf83dd808, 5 | BRF_GRA },           //  4 Sprites
776 	{ "b73_07.2c",		0x10000, 0x5cffa42c, 5 | BRF_GRA },           //  5
777 	{ "b73_06.2b",		0x10000, 0xa98e4aea, 5 | BRF_GRA },           //  6
778 	{ "b73_01.1b",		0x10000, 0x3a8a4489, 5 | BRF_GRA },           //  7
779 	{ "b73_02.1c",		0x10000, 0x025c536c, 5 | BRF_GRA },           //  8
780 	{ "b73_03.1d",		0x10000, 0xec6020cf, 5 | BRF_GRA },           //  9
781 	{ "b73_04.1f",		0x10000, 0xf7badbb2, 5 | BRF_GRA },           // 10
782 	{ "b73_05.1h",		0x10000, 0xb8e829d2, 5 | BRF_GRA },           // 11
783 
784 	{ "b73_09.2p",		0x80000, 0x537c647f, 6 | BRF_GRA },           // 12 Background Tiles
785 };
786 
787 STD_ROM_PICK(hvyunitj)
STD_ROM_FN(hvyunitj)788 STD_ROM_FN(hvyunitj)
789 
790 static INT32 hvyunitjInit()
791 {
792 	return DrvInit(1);
793 }
794 
795 struct BurnDriver BurnDrvHvyunitj = {
796 	"hvyunitj", "hvyunit", NULL, NULL, "1988",
797 	"Heavy Unit (Japan, Newer)\0", NULL, "Kaneko / Taito", "Miscellaneous",
798 	NULL, NULL, NULL, NULL,
799 	BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_KANEKO_MISC, GBF_VERSHOOT, 0,
800 	NULL, hvyunitjRomInfo, hvyunitjRomName, NULL, NULL, NULL, NULL, HvyunitInputInfo, HvyunitjDIPInfo,
801 	hvyunitjInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200,
802 	256, 224, 4, 3
803 };
804 
805 
806 // Heavy Unit (Japan, Older)
807 
808 static struct BurnRomInfo hvyunitjoRomDesc[] = {
809 	{ "b73_13.5c",		0x20000, 0xe2874601, 1 | BRF_PRG | BRF_ESS }, //  0 Z80 #0 Code
810 
811 	{ "b73_14.5p",		0x10000, 0x0dfb51d4, 2 | BRF_PRG | BRF_ESS }, //  1 Z80 #1 Code
812 
813 	{ "b73_12.7e",		0x10000, 0xd1d24fab, 3 | BRF_PRG | BRF_ESS }, //  2 Z80 #2 Code
814 
815 	{ "mermaid.bin",	0x00e00, 0x88c5dd27, 4 | BRF_PRG | BRF_ESS }, //  3 I80C51 (mermaid) Code
816 
817 	{ "b73_08.2f",		0x80000, 0xf83dd808, 5 | BRF_GRA },           //  4 Sprites
818 	{ "b73_07.2c",		0x10000, 0x5cffa42c, 5 | BRF_GRA },           //  5
819 	{ "b73_06.2b",		0x10000, 0xa98e4aea, 5 | BRF_GRA },           //  6
820 	{ "b73_01.1b",		0x10000, 0x3a8a4489, 5 | BRF_GRA },           //  7
821 	{ "b73_02.1c",		0x10000, 0x025c536c, 5 | BRF_GRA },           //  8
822 	{ "b73_03.1d",		0x10000, 0xec6020cf, 5 | BRF_GRA },           //  9
823 	{ "b73_04.1f",		0x10000, 0xf7badbb2, 5 | BRF_GRA },           // 10
824 	{ "b73_05.1h",		0x10000, 0xb8e829d2, 5 | BRF_GRA },           // 11
825 
826 	{ "b73_09.2p",		0x80000, 0x537c647f, 6 | BRF_GRA },           // 12 Background Tiles
827 };
828 
829 STD_ROM_PICK(hvyunitjo)
830 STD_ROM_FN(hvyunitjo)
831 
832 struct BurnDriver BurnDrvHvyunitjo = {
833 	"hvyunitjo", "hvyunit", NULL, NULL, "1988",
834 	"Heavy Unit (Japan, Older)\0", NULL, "Kaneko / Taito", "Miscellaneous",
835 	NULL, NULL, NULL, NULL,
836 	BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_KANEKO_MISC, GBF_VERSHOOT, 0,
837 	NULL, hvyunitjoRomInfo, hvyunitjoRomName, NULL, NULL, NULL, NULL, HvyunitInputInfo, HvyunitjDIPInfo,
838 	hvyunitInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200,
839 	256, 224, 4, 3
840 };
841 
842 
843 // Heavy Unit -U.S.A. Version- (US)
844 
845 static struct BurnRomInfo hvyunituRomDesc[] = {
846 	{ "b73_34.5c",		0x20000, 0x05c30a90, 1 | BRF_PRG | BRF_ESS }, //  0 Z80 #0 Code
847 
848 	{ "b73_35.6p",		0x10000, 0xaed1669d, 2 | BRF_PRG | BRF_ESS }, //  1 Z80 #1 Code
849 
850 	{ "b73_12.7e",		0x10000, 0xd1d24fab, 3 | BRF_PRG | BRF_ESS }, //  2 Z80 #2 Code
851 
852 	{ "mermaid.bin",	0x00e00, 0x88c5dd27, 4 | BRF_PRG | BRF_ESS }, //  3 I80C51 (mermaid) Code
853 
854 	{ "b73_08.2f",		0x80000, 0xf83dd808, 5 | BRF_GRA },           //  4 Sprites
855 	{ "b73_28.2c",		0x20000, 0xa02e08d6, 5 | BRF_GRA },           //  5
856 	{ "b73_27.2b",		0x20000, 0x8708f97c, 5 | BRF_GRA },           //  6
857 	{ "b73_25.0b",		0x20000, 0x2f13f81e, 5 | BRF_GRA },           //  7
858 	{ "b73_26.0c",		0x10000, 0xb8e829d2, 5 | BRF_GRA },           //  8
859 
860 	{ "b73_09.2p",		0x80000, 0x537c647f, 6 | BRF_GRA },           //  9 Background Tiles
861 };
862 
863 STD_ROM_PICK(hvyunitu)
STD_ROM_FN(hvyunitu)864 STD_ROM_FN(hvyunitu)
865 
866 static INT32 hvyunituInit()
867 {
868 	return DrvInit(2);
869 }
870 
871 struct BurnDriver BurnDrvHvyunitu = {
872 	"hvyunitu", "hvyunit", NULL, NULL, "1988",
873 	"Heavy Unit -U.S.A. Version- (US)\0", NULL, "Kaneko / Taito", "Miscellaneous",
874 	NULL, NULL, NULL, NULL,
875 	BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_KANEKO_MISC, GBF_VERSHOOT, 0,
876 	NULL, hvyunituRomInfo, hvyunituRomName, NULL, NULL, NULL, NULL, HvyunitInputInfo, HvyunitjDIPInfo,
877 	hvyunituInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x200,
878 	256, 224, 4, 3
879 };
880