1 // FB Alpha Metal Clash driver module
2 // Based on MAME driver by Luca Elia
3 
4 #include "tiles_generic.h"
5 #include "m6809_intf.h"
6 #include "burn_ym2203.h"
7 #include "burn_ym3526.h"
8 
9 static UINT8 *AllMem;
10 static UINT8 *MemEnd;
11 static UINT8 *AllRam;
12 static UINT8 *RamEnd;
13 static UINT8 *DrvMainROM;
14 static UINT8 *DrvSubROM;
15 static UINT8 *DrvGfxROM0;
16 static UINT8 *DrvGfxROM1;
17 static UINT8 *DrvGfxROM2;
18 static UINT8 *DrvShareRAM;
19 static UINT8 *DrvPalRAM;
20 static UINT8 *DrvFgRAM;
21 static UINT8 *DrvSprRAM;
22 static UINT8 *DrvBgRAM;
23 
24 static UINT32 *DrvPalette;
25 static UINT8 DrvRecalc;
26 
27 static UINT8 bankdata;
28 static UINT8 write_mask;
29 static UINT8 flipscreen;
30 static UINT8 gfxbank;
31 static UINT8 scrollx[2];
32 
33 static INT32 vblank;
34 
35 static UINT8 DrvJoy1[8];
36 static UINT8 DrvJoy2[8];
37 static UINT8 DrvJoy3[8];
38 static UINT8 DrvInputs[3];
39 static UINT8 DrvDips[2];
40 static UINT8 DrvReset;
41 
42 static struct BurnInputInfo MetlclshInputList[] = {
43 	{"P1 Coin",			BIT_DIGITAL,	DrvJoy2 + 6,	"p1 coin"	},
44 	{"P1 Start",		BIT_DIGITAL,	DrvJoy1 + 6,	"p1 start"	},
45 	{"P1 Up",			BIT_DIGITAL,	DrvJoy1 + 2,	"p1 up"		},
46 	{"P1 Down",			BIT_DIGITAL,	DrvJoy1 + 3,	"p1 down"	},
47 	{"P1 Left",			BIT_DIGITAL,	DrvJoy1 + 1,	"p1 left"	},
48 	{"P1 Right",		BIT_DIGITAL,	DrvJoy1 + 0,	"p1 right"	},
49 	{"P1 Button 1",		BIT_DIGITAL,	DrvJoy1 + 4,	"p1 fire 1"	},
50 	{"P1 Button 2",		BIT_DIGITAL,	DrvJoy1 + 5,	"p1 fire 2"	},
51 
52 	{"P2 Coin",			BIT_DIGITAL,	DrvJoy2 + 7,	"p2 coin"	},
53 	{"P2 Start",		BIT_DIGITAL,	DrvJoy1 + 7,	"p2 start"	},
54 	{"P2 Up",			BIT_DIGITAL,	DrvJoy2 + 2,	"p2 up"		},
55 	{"P2 Down",			BIT_DIGITAL,	DrvJoy2 + 3,	"p2 down"	},
56 	{"P2 Left",			BIT_DIGITAL,	DrvJoy2 + 1,	"p2 left"	},
57 	{"P2 Right",		BIT_DIGITAL,	DrvJoy2 + 0,	"p2 right"	},
58 	{"P2 Button 1",		BIT_DIGITAL,	DrvJoy2 + 4,	"p2 fire 1"	},
59 	{"P2 Button 2",		BIT_DIGITAL,	DrvJoy2 + 5,	"p2 fire 2"	},
60 
61 	{"Reset",			BIT_DIGITAL,	&DrvReset,		"reset"		},
62 	{"Service",			BIT_DIGITAL,	DrvJoy3 + 6,	"service"	},
63 	{"Dip A",			BIT_DIPSWITCH,	DrvDips + 0,	"dip"		},
64 	{"Dip B",			BIT_DIPSWITCH,	DrvDips + 1,	"dip"		},
65 };
66 
67 STDINPUTINFO(Metlclsh)
68 
69 static struct BurnDIPInfo MetlclshDIPList[]=
70 {
71 	{0x12, 0xff, 0xff, 0x3f, NULL			},
72 	{0x13, 0xff, 0xff, 0xdf, NULL			},
73 
74 	{0   , 0xfe, 0   ,    2, "Lives"		},
75 	{0x12, 0x01, 0x01, 0x00, "2"			},
76 	{0x12, 0x01, 0x01, 0x01, "3"			},
77 
78 	{0   , 0xfe, 0   ,    2, "Enemies Speed"	},
79 	{0x12, 0x01, 0x02, 0x02, "Low"			},
80 	{0x12, 0x01, 0x02, 0x00, "High"			},
81 
82 	{0   , 0xfe, 0   ,    2, "Enemies Energy"	},
83 	{0x12, 0x01, 0x04, 0x04, "Low"			},
84 	{0x12, 0x01, 0x04, 0x00, "High"			},
85 
86 	{0   , 0xfe, 0   ,    2, "Time"			},
87 	{0x12, 0x01, 0x08, 0x00, "75"			},
88 	{0x12, 0x01, 0x08, 0x08, "90"			},
89 
90 	{0   , 0xfe, 0   ,    2, "Flip Screen"		},
91 	{0x12, 0x01, 0x10, 0x10, "Off"			},
92 	{0x12, 0x01, 0x10, 0x00, "On"			},
93 
94 	{0   , 0xfe, 0   ,    4, "Coinage"		},
95 	{0x13, 0x01, 0x03, 0x00, "2 Coins 1 Credits"	},
96 	{0x13, 0x01, 0x03, 0x03, "1 Coin  1 Credits"	},
97 	{0x13, 0x01, 0x03, 0x02, "1 Coin  2 Credits"	},
98 	{0x13, 0x01, 0x03, 0x01, "1 Coin  3 Credits"	},
99 
100 	{0   , 0xfe, 0   ,    2, "Demo Sounds"		},
101 	{0x13, 0x01, 0x20, 0x20, "Off"			},
102 	{0x13, 0x01, 0x20, 0x00, "On"			},
103 
104 	{0   , 0xfe, 0   ,    2, "Infinite Energy"	},
105 	{0x13, 0x01, 0x40, 0x40, "Off"			},
106 	{0x13, 0x01, 0x40, 0x00, "On"			},
107 
108 	{0   , 0xfe, 0   ,    2, "Infinite Lives"	},
109 	{0x13, 0x01, 0x80, 0x80, "Off"			},
110 	{0x13, 0x01, 0x80, 0x00, "On"			},
111 };
112 
STDDIPINFO(Metlclsh)113 STDDIPINFO(Metlclsh)
114 
115 static void metlclsh_main_write(UINT16 address, UINT8 data)
116 {
117 	switch (address)
118 	{
119 		case 0xc080:
120 		return;	//nop
121 
122 		case 0xc0c2:
123 			M6809Close();
124 			M6809Open(1);
125 			M6809SetIRQLine(0, CPU_IRQSTATUS_ACK);
126 			M6809Close();
127 			M6809Open(0);
128 		return;
129 
130 		case 0xc0c3:
131 			M6809SetIRQLine(0x20, CPU_IRQSTATUS_NONE);
132 		return;
133 
134 		case 0xd000:
135 		case 0xd001:
136 			BurnYM2203Write(0, address & 1, data);
137 		return;
138 
139 		case 0xe000:
140 		case 0xe001:
141 			BurnYM3526Write(address & 1, data);
142 		return;
143 	}
144 }
145 
metlclsh_main_read(UINT16 address)146 static UINT8 metlclsh_main_read(UINT16 address)
147 {
148 	switch (address)
149 	{
150 		case 0xc000:
151 			return DrvDips[1];
152 
153 		case 0xc001:
154 			return DrvInputs[0];
155 
156 		case 0xc002:
157 			return DrvInputs[1];
158 
159 		case 0xc003:
160 			return DrvInputs[2] | (vblank * 0x80);
161 
162 		case 0xd000:
163 		case 0xd001:
164 			return BurnYM2203Read(0,address & 1);
165 	}
166 
167 	return 0;
168 }
169 
bankswitch(INT32 data)170 static void bankswitch(INT32 data)
171 {
172 	bankdata = data;
173 
174 	if (data & 1)
175 	{
176 		M6809MapMemory(DrvBgRAM,			0xd000,	0xd7ff, MAP_RAM);
177 	}
178 	else
179 	{
180 		M6809MapMemory(DrvBgRAM + 0x800,	0xd000,	0xd7ff, MAP_ROM);
181 		M6809UnmapMemory(					0xd000, 0xd7ff, MAP_WRITE);
182 
183 		write_mask = 1 << (data >> 1);
184 	}
185 }
186 
metlclsh_sub_write(UINT16 address,UINT8 data)187 static void metlclsh_sub_write(UINT16 address, UINT8 data)
188 {
189 	if ((address & 0xf800) == 0xd000) {
190 		UINT8 v = DrvBgRAM[0x800 + (address & 0x7ff)] & ~write_mask;
191 		DrvBgRAM[0x800 + (address & 0x7ff)] = v | (data & write_mask);
192 		return;
193 	}
194 
195 	switch (address)
196 	{
197 		case 0xc000:
198 			if ((data & 0x04) == 0)
199 				gfxbank = data & 3;
200 		return;
201 
202 		case 0xc0c0:
203 			M6809Close();
204 			M6809Open(0);
205 			M6809SetIRQLine(0x20, CPU_IRQSTATUS_ACK);
206 			M6809Close();
207 			M6809Open(1);
208 		return;
209 
210 		case 0xc0c1:
211 			M6809SetIRQLine(0, CPU_IRQSTATUS_NONE);
212 		return;
213 
214 		case 0xe301:
215 			flipscreen = data & 1;
216 		return;
217 
218 		case 0xe401:
219 			bankswitch(data);
220 		return;
221 
222 		case 0xe402:
223 		case 0xe403:
224 			scrollx[address & 1] = data;
225 		return;
226 
227 		case 0xe417:
228 			M6809SetIRQLine(0x20, CPU_IRQSTATUS_NONE);
229 		return;
230 	}
231 }
232 
DrvYM3526IrqHandler(INT32,INT32 nStatus)233 static void DrvYM3526IrqHandler(INT32, INT32 nStatus)
234 {
235 	if (M6809GetActive() == -1) return;
236 
237 	M6809SetIRQLine(0, (nStatus) ? CPU_IRQSTATUS_ACK : CPU_IRQSTATUS_NONE);
238 }
239 
tilemap_scan(bg)240 static tilemap_scan( bg )
241 {
242 	return  (row & 7) + ((row & ~7) << 4) + ((col & 0xf) << 3) + ((col & ~0xf) << 4);
243 }
244 
tilemap_callback(bg)245 static tilemap_callback( bg )
246 {
247 	TILE_SET_INFO(0, DrvBgRAM[offs] + (gfxbank * 0x80), 0, 0);
248 }
249 
tilemap_callback(fg)250 static tilemap_callback( fg )
251 {
252 	UINT8 attr = DrvFgRAM[offs + 0x400];
253 
254 	TILE_SET_INFO(1, DrvFgRAM[offs] + (attr * 256), attr / 0x20, TILE_GROUP(attr / 0x80));
255 }
256 
DrvDoReset()257 static INT32 DrvDoReset()
258 {
259 	memset (AllRam, 0, RamEnd - AllRam);
260 
261 	M6809Open(0);
262 	M6809Reset();
263 	BurnYM2203Reset();
264 	BurnYM3526Reset();
265 	M6809Close();
266 
267 	M6809Open(1);
268 	bankswitch(1);
269 	M6809Reset();
270 	M6809Close();
271 
272 	gfxbank = 0;
273 	flipscreen = 0;
274 	scrollx[0] = scrollx[1] = 0;
275 
276 	return 0;
277 }
278 
MemIndex()279 static INT32 MemIndex()
280 {
281 	UINT8 *Next; Next = AllMem;
282 
283 	DrvMainROM		= Next; Next += 0x00c000;
284 	DrvSubROM		= Next; Next += 0x008000;
285 
286 	DrvGfxROM0		= Next; Next += 0x040000;
287 	DrvGfxROM1		= Next; Next += 0x020000;
288 	DrvGfxROM2		= Next; Next += 0x010000;
289 
290 	DrvPalette		= (UINT32*)Next; Next += 0x30 * sizeof(UINT32);
291 
292 	AllRam			= Next;
293 
294 	DrvShareRAM		= Next; Next += 0x002000;
295 	DrvPalRAM		= Next; Next += 0x000200;
296 	DrvFgRAM		= Next; Next += 0x000800;
297 	DrvSprRAM		= Next; Next += 0x000200;
298 	DrvBgRAM		= Next; Next += 0x001000;
299 
300 	RamEnd			= Next;
301 
302 	MemEnd			= Next;
303 
304 	return 0;
305 }
306 
DrvGfxDecode()307 static INT32 DrvGfxDecode()
308 {
309 	INT32 Plane0[3]  = { 0x8000*8*2, 0x8000*8*1, 0x8000*8*0 };
310 	INT32 XOffs0[16] = { STEP8(8*8*2,1), STEP8(8*8*0,1) };
311 	INT32 YOffs0[16] = { STEP8(8*8*0,8), STEP8(8*8*1,8) };
312 
313 	INT32 Plane1[3]  = { 0x4000*8*2, 0x4000*8*1, 0x4000*8*0 };
314 	INT32 XOffs1[16] = { STEP8(8*8*0+7,-1), STEP8(8*8*2+7,-1) };
315 	INT32 YOffs1[16] = { STEP8(8*8*0,8), STEP8(8*8*1,8) };
316 
317 	INT32 Plane2[2] = { 0, 4 };
318 	INT32 XOffs2[8] = { STEP4((0x2000*8),1), STEP4(0,1) };
319 	INT32 YOffs2[8] = { STEP8(0,8) };
320 
321 	UINT8 *tmp = (UINT8*)BurnMalloc(0x18000);
322 	if (tmp == NULL) {
323 		return 1;
324 	}
325 
326 	memcpy (tmp, DrvGfxROM0, 0x18000);
327 
328 	GfxDecode(0x0400, 3, 16, 16, Plane0, XOffs0, YOffs0, 0x100, tmp, DrvGfxROM0);
329 
330 	for (INT32 i = 0; i < 16; i++) {
331 		memcpy (tmp + (((i & 3) << 2) | (i >> 2)) * 0x1000, DrvGfxROM1 + i * 0x1000, 0x1000);
332 	}
333 
334 	GfxDecode(0x0200, 3, 16, 16, Plane1, XOffs1, YOffs1, 0x100, tmp, DrvGfxROM1);
335 
336 	memcpy (tmp, DrvGfxROM2 + 0x04000, 0x04000);
337 
338 	GfxDecode(0x0400, 2,  8,  8, Plane2, XOffs2, YOffs2, 0x040, tmp, DrvGfxROM2);
339 
340 	BurnFree(tmp);
341 
342 	return 0;
343 }
344 
DrvInit()345 static INT32 DrvInit()
346 {
347 	BurnSetRefreshRate(58.00);
348 
349 	AllMem = NULL;
350 	MemIndex();
351 	INT32 nLen = MemEnd - (UINT8 *)0;
352 	if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1;
353 	memset(AllMem, 0, nLen);
354 	MemIndex();
355 
356 	{
357 		if (BurnLoadRom(DrvMainROM + 0x00000,  0, 1)) return 1;
358 		if (BurnLoadRom(DrvMainROM + 0x0a000,  1, 1)) return 1;
359 
360 		if (BurnLoadRom(DrvSubROM  + 0x00000,  2, 1)) return 1;
361 
362 		if (BurnLoadRom(DrvGfxROM0 + 0x00000,  3, 1)) return 1;
363 		if (BurnLoadRom(DrvGfxROM0 + 0x08000,  4, 1)) return 1;
364 		if (BurnLoadRom(DrvGfxROM0 + 0x10000,  5, 1)) return 1;
365 
366 		if (BurnLoadRom(DrvGfxROM1 + 0x00000,  6, 1)) return 1;
367 		if (BurnLoadRom(DrvGfxROM1 + 0x08000,  7, 1)) return 1;
368 
369 		if (BurnLoadRom(DrvGfxROM2 + 0x00000,  8, 1)) return 1;
370 
371 		DrvGfxDecode();
372 	}
373 
374 	M6809Init(0);
375 	M6809Open(0);
376 	M6809MapMemory(DrvMainROM + 0x0000,	0x0000, 0x7fff, MAP_ROM);
377 	M6809MapMemory(DrvShareRAM,			0x8000, 0x9fff, MAP_RAM);
378 	M6809MapMemory(DrvMainROM + 0xa000,	0xa000, 0xbfff, MAP_ROM);
379 	M6809MapMemory(DrvPalRAM + 0x000,	0xc800, 0xc8ff, MAP_RAM);
380 	M6809MapMemory(DrvPalRAM + 0x100,	0xcc00, 0xccff, MAP_RAM);
381 	M6809MapMemory(DrvFgRAM,			0xd800,	0xdfff, MAP_RAM);
382 	M6809MapMemory(DrvSprRAM,			0xe800, 0xe9ff, MAP_RAM);
383 	M6809MapMemory(DrvMainROM + 0x7f00,	0xff00, 0xffff, MAP_ROM);
384 	M6809SetWriteHandler(metlclsh_main_write);
385 	M6809SetReadHandler(metlclsh_main_read);
386 	M6809Close();
387 
388 	M6809Init(1);
389 	M6809Open(1);
390 	M6809MapMemory(DrvSubROM + 0x0000,	0x0000, 0x7fff, MAP_ROM);
391 	M6809MapMemory(DrvShareRAM,			0x8000, 0x9fff, MAP_RAM);
392 	M6809MapMemory(DrvBgRAM,			0xd000,	0xd7ff, MAP_RAM);
393 	M6809MapMemory(DrvSubROM + 0x7f00,	0xff00, 0xffff, MAP_ROM);
394 	M6809SetWriteHandler(metlclsh_sub_write);
395 	M6809SetReadHandler(metlclsh_main_read);
396 	M6809Close();
397 
398 	BurnYM3526Init(3000000, &DrvYM3526IrqHandler, 0);
399 	BurnTimerAttachYM3526(&M6809Config, 1500000);
400 	BurnYM3526SetRoute(BURN_SND_YM3526_ROUTE, 0.50, BURN_SND_ROUTE_BOTH);
401 
402 	BurnYM2203Init(1, 1500000, NULL, 1);
403 	BurnTimerAttachM6809(1500000);
404 	BurnYM2203SetRoute(0, BURN_SND_YM2203_YM2203_ROUTE, 0.50, BURN_SND_ROUTE_BOTH);
405 	BurnYM2203SetRoute(0, BURN_SND_YM2203_AY8910_ROUTE_1, 0.10, BURN_SND_ROUTE_BOTH);
406 	BurnYM2203SetRoute(0, BURN_SND_YM2203_AY8910_ROUTE_2, 0.10, BURN_SND_ROUTE_BOTH);
407 	BurnYM2203SetRoute(0, BURN_SND_YM2203_AY8910_ROUTE_3, 0.10, BURN_SND_ROUTE_BOTH);
408 
409 	GenericTilesInit();
410 	GenericTilemapInit(0, bg_map_scan,        bg_map_callback, 16, 16, 32, 16);
411 	GenericTilemapInit(1, TILEMAP_SCAN_ROWS,  fg_map_callback,  8,  8, 32, 32);
412 	GenericTilemapSetGfx(0, DrvGfxROM1, 3, 16, 16, 0x20000, 0x10, 0x00);
413 	GenericTilemapSetGfx(1, DrvGfxROM2, 2,  8,  8, 0x10000, 0x20, 0x03);
414 	GenericTilemapSetOffsets(TMAP_GLOBAL, 0, -16);
415 	GenericTilemapSetTransparent(0, 0);
416 	GenericTilemapSetTransparent(1, 0);
417 
418 	DrvDoReset();
419 
420 	return 0;
421 }
422 
DrvExit()423 static INT32 DrvExit()
424 {
425 	GenericTilesExit();
426 
427 	M6809Exit();
428 
429 	BurnYM2203Exit();
430 	BurnYM3526Exit();
431 
432 	BurnFree(AllMem);
433 
434 	return 0;
435 }
436 
DrvPaletteUpdate()437 static void DrvPaletteUpdate()
438 {
439 	for (INT32 i = 0; i < 0x30; i++)
440 	{
441 		UINT8 r = DrvPalRAM[0x000 + i] & 0xf;
442 		UINT8 g = DrvPalRAM[0x000 + i] >> 4;
443 		UINT8 b = DrvPalRAM[0x100 + i] & 0xf;
444 
445 		DrvPalette[i] = BurnHighCol(r+r*16,g+g*16,b+b*16, 0);
446 	}
447 }
448 
draw_single_sprite(INT32 code,INT32 color,INT32 sx,INT32 sy,INT32 flipx,INT32 flipy)449 static void draw_single_sprite(INT32 code, INT32 color, INT32 sx, INT32 sy, INT32 flipx, INT32 flipy)
450 {
451 	sy -= 16;
452 
453 	if (flipy) {
454 		if (flipx) {
455 			Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 3, 0, 0, DrvGfxROM0);
456 		} else {
457 			Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 3, 0, 0, DrvGfxROM0);
458 		}
459 	} else {
460 		if (flipx) {
461 			Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 3, 0, 0, DrvGfxROM0);
462 		} else {
463 			Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 3, 0, 0, DrvGfxROM0);
464 		}
465 	}
466 }
467 
draw_sprites()468 static void draw_sprites()
469 {
470 	for (INT32 offs = 0; offs < 0x200; offs += 4)
471 	{
472 		INT32 attr = DrvSprRAM[offs];
473 		if ((attr & 0x01) == 0) continue;
474 
475 		INT32 flipy = (attr & 0x02);
476 		INT32 flipx = (attr & 0x04);
477 		INT32 color = (attr & 0x08) >> 3;
478 		INT32 sizey = (attr & 0x10);  // double height
479 		INT32 code = ((attr & 0x60) << 3) + DrvSprRAM[offs + 1];
480 
481 		INT32 sx = 240 - DrvSprRAM[offs + 3];
482 		if (sx < -7) sx += 256;
483 
484 		INT32 sy = 240 - DrvSprRAM[offs + 2];
485 
486 		if (flipscreen)
487 		{
488 			sx = 240 - sx;  flipx = !flipx;
489 			sy = 240 - sy;  flipy = !flipy;
490 			if (sizey) sy += 16;
491 			if (sy > 240) sy -= 256;
492 		}
493 
494 		for (INT32 wrapy = 0; wrapy <= 256; wrapy += 256)
495 		{
496 			if (sizey)
497 			{
498 				draw_single_sprite(code & ~1, color, sx, sy + (flipy ? 0 : -16) + wrapy, flipx, flipy);
499 				draw_single_sprite(code |  1, color, sx, sy + (flipy ? -16 : 0) + wrapy, flipx, flipy);
500 			}
501 			else
502 			{
503 				draw_single_sprite(code, color, sx, sy + wrapy, flipx, flipy);
504 			}
505 		}
506 	}
507 }
508 
DrvDraw()509 static INT32 DrvDraw()
510 {
511 	DrvPaletteUpdate();
512 
513 	BurnTransferClear(0x10);
514 
515 	GenericTilemapSetFlip(1, flipscreen ? (TMAP_FLIPX|TMAP_FLIPY):0);
516 
517 	GenericTilemapDraw(1, pTransDraw, TMAP_SET_GROUP(1));
518 
519 	if (scrollx[0] & 0x08)
520 	{
521 		INT32 scroll = scrollx[1] + ((scrollx[0] & 0x02) << 7);
522 		GenericTilemapSetFlip(0, flipscreen ? (TMAP_FLIPX|TMAP_FLIPY) : TMAP_FLIPX);
523 		GenericTilemapSetScrollX(0, flipscreen ? -scroll : scroll);
524 		GenericTilemapDraw(0, pTransDraw, 0);
525 	}
526 
527 	draw_sprites();
528 
529 	GenericTilemapDraw(1, pTransDraw, TMAP_SET_GROUP(0));
530 
531 	BurnTransferCopy(DrvPalette);
532 
533 	return 0;
534 }
535 
DrvFrame()536 static INT32 DrvFrame()
537 {
538 	if (DrvReset) {
539 		DrvDoReset();
540 	}
541 
542 	M6809NewFrame();
543 
544 	{
545 		UINT8 prev[2];
546 		prev[0] = DrvInputs[1] & 0xc0;
547 		prev[1] = DrvInputs[2] & 0x40;
548 
549 		memset (DrvInputs, 0xff, 3);
550 
551 		DrvInputs[2] = (DrvDips[0] & 0x1f) | 0x40;
552 
553 		for (INT32 i = 0; i < 8; i++) {
554 			DrvInputs[0] ^= (DrvJoy1[i] & 1) << i;
555 			DrvInputs[1] ^= (DrvJoy2[i] & 1) << i;
556 			DrvInputs[2] ^= (DrvJoy3[i] & 1) << i;
557 		}
558 
559 		// coins trigger nmi on sub cpu
560 		M6809Open(1);
561 		if (prev[0] == 0xc0 && (DrvInputs[1] & 0xc0) != 0xc0) {
562 			M6809SetIRQLine(0x20, CPU_IRQSTATUS_ACK);
563 		}
564 		if (prev[1] == 0x40 && (DrvInputs[2] & 0x40) != 0x40) {
565 			M6809SetIRQLine(0x20, CPU_IRQSTATUS_ACK);
566 		}
567 		M6809Close();
568 	}
569 
570 	INT32 nInterleave = 256*2; // game prefers high interleave for main/sub shared ram communication
571 	INT32 nCyclesTotal[2] =  { (1500000 * 100) / nBurnFPS, (1500000 * 100) / nBurnFPS };
572 
573 	for (INT32 i = 0; i < nInterleave; i++)
574 	{
575 		vblank = (i >= 240*2) ? 1 : 0;
576 
577 		M6809Open(0);
578 		BurnTimerUpdateYM3526((i + 1) * (nCyclesTotal[0] / nInterleave));
579 		M6809Close();
580 
581 		M6809Open(1);
582 		BurnTimerUpdate((i + 1) * (nCyclesTotal[1] / nInterleave));
583 		M6809Close();
584 	}
585 
586 	M6809Open(1);
587 	BurnTimerEndFrame(nCyclesTotal[1]);
588 	M6809Close();
589 
590 	M6809Open(0);
591 	BurnTimerEndFrameYM3526(nCyclesTotal[0]);
592 
593 	if (pBurnSoundOut) {
594 		BurnYM3526Update(pBurnSoundOut, nBurnSoundLen);
595 		M6809Close();
596 
597 		M6809Open(1);
598 		BurnYM2203Update(pBurnSoundOut, nBurnSoundLen);
599 	}
600 
601 	M6809Close();
602 
603 	if (pBurnDraw) {
604 		DrvDraw();
605 	}
606 
607 	return 0;
608 }
609 
DrvScan(INT32 nAction,INT32 * pnMin)610 static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
611 {
612 	struct BurnArea ba;
613 
614 	if (pnMin != NULL) {
615 		*pnMin = 0x029707;
616 	}
617 
618 	if (nAction & ACB_MEMORY_RAM) {
619 		memset(&ba, 0, sizeof(ba));
620 		ba.Data	  = AllRam;
621 		ba.nLen	  = RamEnd-AllRam;
622 		ba.szName = "All Ram";
623 		BurnAcb(&ba);
624 	}
625 
626 	if (nAction & ACB_DRIVER_DATA)
627 	{
628 		M6809Scan(nAction);
629 
630 		M6809Open(0);
631 		BurnYM3526Scan(nAction, pnMin);
632 		BurnYM2203Scan(nAction, pnMin);
633 		M6809Close();
634 
635 		SCAN_VAR(flipscreen);
636 		SCAN_VAR(scrollx);
637 		SCAN_VAR(bankdata);
638 		SCAN_VAR(gfxbank);
639 	}
640 
641 	if (nAction & ACB_WRITE)
642 	{
643 		M6809Open(1);
644 		bankswitch(bankdata);
645 		M6809Close();
646 	}
647 
648 	return 0;
649 }
650 
651 
652 // Metal Clash (Japan)
653 
654 static struct BurnRomInfo metlclshRomDesc[] = {
655 	{ "cs04.bin",	0x8000, 0xc2cc79a6, 1 | BRF_PRG | BRF_ESS }, //  0 M6809 #0 Code
656 	{ "cs00.bin",	0x2000, 0xaf0f2998, 1 | BRF_PRG | BRF_ESS }, //  1
657 
658 	{ "cs03.bin",	0x8000, 0x51c4720c, 2 | BRF_PRG | BRF_ESS }, //  2 M6809 #1 Code
659 
660 	{ "cs06.bin",	0x8000, 0x9f61403f, 3 | BRF_GRA },           //  3 Sprites
661 	{ "cs07.bin",	0x8000, 0xd0610ea5, 3 | BRF_GRA },           //  4
662 	{ "cs08.bin",	0x8000, 0xa8b02125, 3 | BRF_GRA },           //  5
663 
664 	{ "cs01.bin",	0x8000, 0x9c72343d, 4 | BRF_GRA },           //  6 Background Tiles
665 	{ "cs02.bin",	0x8000, 0x3674673e, 4 | BRF_GRA },           //  7
666 
667 	{ "cs05.bin",	0x8000, 0xf90c9c6b, 5 | BRF_GRA },           //  8 Foreground Tiles
668 
669 	{ "82s123.prm",	0x0020, 0x6844cc88, 0 | BRF_OPT },           //  9 Unknown PROM
670 };
671 
672 STD_ROM_PICK(metlclsh)
673 STD_ROM_FN(metlclsh)
674 
675 struct BurnDriver BurnDrvMetlclsh = {
676 	"metlclsh", NULL, NULL, NULL, "1985",
677 	"Metal Clash (Japan)\0", NULL, "Data East", "Miscellaneous",
678 	NULL, NULL, NULL, NULL,
679 	BDF_GAME_WORKING, 2, HARDWARE_PREFIX_DATAEAST, GBF_SCRFIGHT, 0,
680 	NULL, metlclshRomInfo, metlclshRomName, NULL, NULL, NULL, NULL, MetlclshInputInfo, MetlclshDIPInfo,
681 	DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x30,
682 	256, 224, 4, 3
683 };
684