1 // FB Alpha Cloak and Dagger driver module
2 // Based on MAME driver by Dan Boris and Mirko Buffoni
3 
4 #include "tiles_generic.h"
5 #include "m6502_intf.h"
6 #include "pokey.h"
7 #include "resnet.h"
8 
9 static UINT8 *AllMem;
10 static UINT8 *MemEnd;
11 static UINT8 *AllRam;
12 static UINT8 *RamEnd;
13 static UINT8 *DrvM6502ROM0;
14 static UINT8 *DrvM6502ROM1;
15 static UINT8 *DrvGfxROM0;
16 static UINT8 *DrvGfxROM1;
17 static UINT8 *DrvM6502RAM0;
18 static UINT8 *DrvM6502RAM1;
19 static UINT8 *DrvVidRAM;
20 static UINT8 *DrvNVRAM;
21 static UINT8 *DrvShareRAM;
22 static UINT8 *DrvSprRAM;
23 static UINT16 *DrvPalRAM;
24 static UINT8 *bitmap[2];
25 
26 static UINT32 *DrvPalette;
27 static UINT8 DrvRecalc;
28 
29 static UINT8 flipscreen;
30 static UINT8 nvram_enable;
31 static UINT8 video_selected;
32 static UINT8 video_address_x;
33 static UINT8 video_address_y;
34 
35 static INT32 watchdog;
36 static UINT8 vblank;
37 
38 static UINT8 DrvJoy1[8];
39 static UINT8 DrvJoy3[8];
40 static UINT8 DrvJoy4[8];
41 static UINT8 DrvDips[1];
42 static UINT8 DrvInputs[4];
43 static UINT8 DrvReset;
44 
45 static struct BurnInputInfo CloakInputList[] = {
46 	{"Coin A",		BIT_DIGITAL,	DrvJoy3 + 3,	"p1 coin"	},
47 	{"Coin B",		BIT_DIGITAL,	DrvJoy3 + 2,	"p2 coin"	},
48 	{"Start 1",		BIT_DIGITAL,	DrvJoy4 + 7,	"p1 start"	},
49 	{"Start 2",		BIT_DIGITAL,	DrvJoy4 + 6,	"p2 start"	},
50 	{"P1 Left Up",		BIT_DIGITAL,	DrvJoy1 + 5,	"p1 up"		},
51 	{"P1 Left Down",	BIT_DIGITAL,	DrvJoy1 + 4,	"p1 down"	},
52 	{"P1 Left Left",	BIT_DIGITAL,	DrvJoy1 + 7,	"p1 left"	},
53 	{"P1 Left Right",	BIT_DIGITAL,	DrvJoy1 + 6,	"p1 right"	},
54 
55 	{"P1 Right Up",		BIT_DIGITAL,	DrvJoy1 + 1,	"p2 up"		},
56 	{"P1 Right Down",	BIT_DIGITAL,	DrvJoy1 + 0,	"p2 down"	},
57 	{"P1 Right Left",	BIT_DIGITAL,	DrvJoy1 + 3,	"p2 left"	},
58 	{"P1 Right Right",	BIT_DIGITAL,	DrvJoy1 + 2,	"p2 right"	},
59 
60 	{"P1 Button 1",		BIT_DIGITAL,	DrvJoy3 + 7,	"p1 fire 1"	},
61 
62 	{"Reset",		BIT_DIGITAL,	&DrvReset,	"reset"		},
63 	{"Service",		BIT_DIGITAL,	DrvJoy3 + 5,	"service"	},
64 	{"Dip A",		BIT_DIPSWITCH,	DrvDips + 0,	"dip"		},
65 };
66 
67 STDINPUTINFO(Cloak)
68 
69 static struct BurnDIPInfo CloakDIPList[]=
70 {
71 	{0x0f, 0xff, 0xff, 0x02, NULL			},
72 
73 	{0   , 0xfe, 0   ,    4, "Credits"		},
74 	{0x0f, 0x01, 0x03, 0x02, "1 Credit/1 Game"	},
75 	{0x0f, 0x01, 0x03, 0x01, "1 Credit/2 Games"	},
76 	{0x0f, 0x01, 0x03, 0x03, "2 Credits/1 Game"	},
77 	{0x0f, 0x01, 0x03, 0x00, "Free Play"		},
78 
79 	{0   , 0xfe, 0   ,    4, "Coin B"		},
80 	{0x0f, 0x01, 0x0c, 0x00, "1 Coin  1 Credits"	},
81 	{0x0f, 0x01, 0x0c, 0x04, "1 Coin  4 Credits"	},
82 	{0x0f, 0x01, 0x0c, 0x08, "1 Coin  5 Credits"	},
83 	{0x0f, 0x01, 0x0c, 0x0c, "1 Coin  6 Credits"	},
84 
85 	{0   , 0xfe, 0   ,    2, "Coin A"		},
86 	{0x0f, 0x01, 0x10, 0x00, "1 Coin  1 Credits"	},
87 	{0x0f, 0x01, 0x10, 0x10, "1 Coin  2 Credits"	},
88 
89 	{0   , 0xfe, 0   ,    0, "Demo Freeze Mode"	},
90 	{0x0f, 0x01, 0x40, 0x00, "Off"			},
91 	{0x0f, 0x01, 0x40, 0x40, "On"			},
92 };
93 
STDDIPINFO(Cloak)94 STDDIPINFO(Cloak)
95 
96 static UINT8 adjust_xy_r(INT32 offset)
97 {
98 	UINT8 pxl = bitmap[video_selected][(video_address_y * 256) | video_address_x];
99 
100 	switch (offset & 7)
101 	{
102 		case 0:
103 			video_address_x--;
104 			video_address_y++;
105 		break;
106 
107 		case 1:
108 			video_address_y--;
109 		break;
110 
111 		case 2:
112 			video_address_x--;
113 		break;
114 
115 		case 4:
116 			video_address_x++;
117 			video_address_y++;
118 		break;
119 
120 		case 5:
121 			video_address_y++;
122 		break;
123 
124 		case 6:
125 			video_address_x++;
126 		break;
127 	}
128 
129 	return pxl;
130 }
131 
adjust_xy_w(INT32 offset,INT32 data)132 static void adjust_xy_w(INT32 offset, INT32 data)
133 {
134 	switch (offset & 7)
135 	{
136 		case 3:
137 			video_address_x = data;
138 		break;
139 
140 		case 7:
141 			video_address_y = data;
142 		break;
143 
144 	    default:
145 			bitmap[video_selected^1][(video_address_y * 256) | video_address_x] = data & 0xf;
146 			adjust_xy_r(offset);
147 		break;
148 	}
149 }
150 
cloak_main_write(UINT16 address,UINT8 data)151 static void cloak_main_write(UINT16 address, UINT8 data)
152 {
153 	if ((address & 0xff80) == 0x3200) {
154 		UINT16 offset = address - 0x3200;
155 		DrvPalRAM[offset & 0x3f] = ((offset & 0x40) << 2) | data;
156 		return;
157 	}
158 
159 	if ((address & 0xff00) == 0x2f00) {
160 		return; // nop
161 	}
162 
163 	if ((address & 0xfff0) == 0x1000) {
164 		pokey1_w(address & 0xf, data);
165 		return;
166 	}
167 
168 	if ((address & 0xfff0) == 0x1800) {
169 		pokey2_w(address & 0xf, data);
170 		return;
171 	}
172 
173 #if 0
174 	if ((address & 0xfe00) == 0x2800) {
175 		if (nvram_enable) {
176 			DrvNVRAM[address & 0x1ff] = data;
177 		}
178 		return;
179 	}
180 #endif
181 
182 	switch (address)
183 	{
184 		case 0x2600:
185 			// custom (unused)
186 		return;
187 
188 		case 0x3800:
189 		case 0x3801:
190 			// coin counter
191 		return;
192 
193 		case 0x3803:
194 			flipscreen = data & 0x80;
195 		return;
196 
197 		case 0x3805:
198 		return;	// nop
199 
200 		case 0x3806:
201 		case 0x3807:
202 			// leds
203 		return;
204 
205 		case 0x3a00:
206 			watchdog = 0;
207 		return;
208 
209 		case 0x3c00:
210 			M6502SetIRQLine(0, CPU_IRQSTATUS_NONE);
211 		return;
212 
213 		case 0x3e00:
214 			nvram_enable = data & 1;
215 		return;
216 	}
217 }
218 
cloak_main_read(UINT16 address)219 static UINT8 cloak_main_read(UINT16 address)
220 {
221 	if ((address & 0xff00) == 0x2f00) {
222 		return 0; // nop
223 	}
224 
225 	if ((address & 0xfff0) == 0x1000) {		// pokey 1
226 		switch (address&0xf) {
227 			case ALLPOT_C: return DrvInputs[3] ^ 0xf0;
228 			default: return pokey1_r(address&0xf);
229 		}
230 	}
231 
232 	if ((address & 0xfff0) == 0x1800) {		// pokey 2
233 		switch (address&0xf) {
234 			case ALLPOT_C: return DrvDips[0];
235 			default: return pokey2_r(address&0xf);
236 		}
237 	}
238 
239 	switch (address)
240 	{
241 		case 0x2000:
242 			return DrvInputs[0]; // p1
243 
244 		case 0x2200:
245 			return 0xff;
246 
247 		case 0x2400:
248 			return (DrvInputs[2] & 0xfe) | ((vblank) ? 0x00 : 0x01);
249 	}
250 
251 	return 0;
252 }
253 
cloak_sub_write(UINT16 address,UINT8 data)254 static void cloak_sub_write(UINT16 address, UINT8 data)
255 {
256 	if (address < 0x0008 || (address >= 0x0010 && address <= 0x07ff)) {
257 		DrvM6502RAM1[address & 0x7ff] = data;
258 		return;
259 	}
260 
261 	if ((address & 0xfff8) == 0x0008) {
262 		adjust_xy_w(address, data);
263 		return;
264 	}
265 
266 	switch (address)
267 	{
268 		case 0x1000:
269 			M6502SetIRQLine(0, CPU_IRQSTATUS_NONE);
270 		return;
271 
272 		case 0x1200:
273 		{
274 			video_selected = data & 1;
275 
276 			if (data & 2) {
277 				memset (bitmap[video_selected^1], 0, 256 * 256);
278 			}
279 		}
280 		return;
281 
282 		case 0x1400:
283 			// custom (unused)
284 		return;
285 	}
286 }
287 
cloak_sub_read(UINT16 address)288 static UINT8 cloak_sub_read(UINT16 address)
289 {
290 	if (address < 0x0008 || (address >= 0x0010 && address <= 0x07ff)) {
291 		return DrvM6502RAM1[address & 0x7ff];
292 	}
293 
294 	if ((address & 0xfff8) == 0x0008) {
295 		return adjust_xy_r(address);
296 	}
297 
298 	return 0;
299 }
300 
DrvDoReset(INT32 full_reset)301 static INT32 DrvDoReset(INT32 full_reset)
302 {
303 	if (full_reset) {
304 		memset(AllRam, 0, RamEnd - AllRam);
305 	}
306 
307 	M6502Open(0);
308 	M6502Reset();
309 	M6502Close();
310 
311 	M6502Open(1);
312 	M6502Reset();
313 	M6502Close();
314 
315 	watchdog = 0;
316 
317 	flipscreen = 0;
318 	nvram_enable = 0;
319 	video_selected = 0;
320 	video_address_x = 0;
321 	video_address_y = 0;
322 
323 	return 0;
324 }
325 
MemIndex()326 static INT32 MemIndex()
327 {
328 	UINT8 *Next; Next = AllMem;
329 
330 	DrvM6502ROM0		= Next; Next += 0x010000;
331 	DrvM6502ROM1		= Next; Next += 0x010000;
332 
333 	DrvGfxROM0		= Next; Next += 0x004000;
334 	DrvGfxROM1		= Next; Next += 0x004000;
335 
336 	DrvNVRAM		= Next; Next += 0x000200;
337 
338 	DrvPalette		= (UINT32*)Next; Next += 0x0040 * sizeof(UINT32);
339 
340 	AllRam			= Next;
341 
342 	DrvM6502RAM0		= Next; Next += 0x000800;
343 	DrvM6502RAM1		= Next; Next += 0x000800;
344 	DrvVidRAM		= Next; Next += 0x000800;
345 	DrvShareRAM		= Next; Next += 0x000800;
346 	DrvSprRAM		= Next; Next += 0x000100;
347 
348 	DrvPalRAM		= (UINT16*)Next; Next += 0x0040 * 2;
349 
350 	bitmap[0]		= Next; Next += 256 * 256;
351 	bitmap[1]		= Next; Next += 256 * 256;
352 
353 	RamEnd			= Next;
354 
355 	MemEnd			= Next;
356 
357 	return 0;
358 }
359 
DrvGfxDecode()360 static INT32 DrvGfxDecode()
361 {
362 	INT32 Plane[4] = { STEP4(0,1) };
363 	INT32 XOffs[8] = { 0x1000*8+0, 0x1000*8+4, 0, 4, 0x1000*8+8, 0x1000*8+12, 8, 12 };
364 	INT32 YOffs[16]= { STEP16(0,16) };
365 
366 	UINT8 *tmp = (UINT8*)BurnMalloc(0x2000);
367 	if (tmp == NULL) {
368 		return 1;
369 	}
370 
371 	memcpy (tmp, DrvGfxROM0, 0x2000);
372 
373 	GfxDecode(0x0100, 4, 8,  8, Plane, XOffs, YOffs, 0x080, tmp, DrvGfxROM0);
374 
375 	memcpy (tmp, DrvGfxROM1, 0x2000);
376 
377 	GfxDecode(0x0080, 4, 8, 16, Plane, XOffs, YOffs, 0x100, tmp, DrvGfxROM1);
378 
379 	BurnFree(tmp);
380 
381 	return 0;
382 }
383 
DrvInit()384 static INT32 DrvInit()
385 {
386 	AllMem = NULL;
387 	MemIndex();
388 	INT32 nLen = MemEnd - (UINT8 *)0;
389 	if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1;
390 	memset(AllMem, 0, nLen);
391 	MemIndex();
392 
393 	{
394 		if (BurnLoadRom(DrvM6502ROM0 + 0x4000,  0, 1)) return 1;
395 		if (BurnLoadRom(DrvM6502ROM0 + 0x6000,  1, 1)) return 1;
396 		if (BurnLoadRom(DrvM6502ROM0 + 0x8000,  2, 1)) return 1;
397 		if (BurnLoadRom(DrvM6502ROM0 + 0xc000,  3, 1)) return 1;
398 
399 		if (BurnLoadRom(DrvM6502ROM1 + 0x2000,  4, 1)) return 1;
400 		if (BurnLoadRom(DrvM6502ROM1 + 0x4000,  5, 1)) return 1;
401 		if (BurnLoadRom(DrvM6502ROM1 + 0x6000,  6, 1)) return 1;
402 		if (BurnLoadRom(DrvM6502ROM1 + 0x8000,  7, 1)) return 1;
403 		if (BurnLoadRom(DrvM6502ROM1 + 0xa000,  8, 1)) return 1;
404 		if (BurnLoadRom(DrvM6502ROM1 + 0xc000,  9, 1)) return 1;
405 		if (BurnLoadRom(DrvM6502ROM1 + 0xe000, 10, 1)) return 1;
406 
407 		if (BurnLoadRom(DrvGfxROM0   + 0x0000, 11, 1)) return 1;
408 		if (BurnLoadRom(DrvGfxROM0   + 0x1000, 12, 1)) return 1;
409 
410 		if (BurnLoadRom(DrvGfxROM1   + 0x0000, 13, 1)) return 1;
411 		if (BurnLoadRom(DrvGfxROM1   + 0x1000, 14, 1)) return 1;
412 
413 		DrvGfxDecode();
414 	}
415 
416 	M6502Init(0, TYPE_M6502);
417 	M6502Open(0);
418 	M6502MapMemory(DrvM6502RAM0,		0x0000, 0x03ff, MAP_RAM);
419 	M6502MapMemory(DrvVidRAM,		0x0400, 0x07ff, MAP_RAM);
420 	M6502MapMemory(DrvShareRAM,		0x0800, 0x0fff, MAP_RAM);
421 	M6502MapMemory(DrvNVRAM,		0x2800, 0x29ff, MAP_RAM);
422 	M6502MapMemory(DrvSprRAM,		0x3000, 0x30ff, MAP_RAM);
423 //	M6502MapMemory(DrvPalRAM,		0x3200, 0x32ff, MAP_RAM); // handler
424 	M6502MapMemory(DrvM6502ROM0 + 0x4000,	0x4000, 0xffff, MAP_ROM);
425 	M6502SetWriteHandler(cloak_main_write);
426 	M6502SetReadHandler(cloak_main_read);
427 	M6502Close();
428 
429 	M6502Init(1, TYPE_M6502);
430 	M6502Open(1);
431 	M6502MapMemory(DrvM6502RAM1,		0x0000, 0x00ff, MAP_FETCH);
432 	M6502MapMemory(DrvM6502RAM1 + 0x0100,	0x0100, 0x07ff, MAP_RAM);
433 	M6502MapMemory(DrvShareRAM,		0x0800, 0x0fff, MAP_RAM);
434 	M6502MapMemory(DrvM6502ROM1 + 0x2000,	0x2000, 0xffff, MAP_ROM);
435 	M6502SetWriteHandler(cloak_sub_write);
436 	M6502SetReadHandler(cloak_sub_read);
437 	M6502Close();
438 
439 	PokeyInit(1250000, 2, 1.00, 0);
440 
441 	GenericTilesInit();
442 
443 	DrvDoReset(1);
444 
445 	return 0;
446 }
447 
DrvExit()448 static INT32 DrvExit()
449 {
450 	GenericTilesExit();
451 
452 	M6502Exit();
453 	PokeyExit();
454 
455 	BurnFree(AllMem);
456 
457 	return 0;
458 }
459 
palette_update()460 static void palette_update()
461 {
462 	static const int resistances_rgb[3] = { 10000, 4700, 2200 };
463 	double weights_rgb[3];
464 
465 	compute_resistor_weights(0, 0xff, -1.0,
466 						   3, &resistances_rgb[0], weights_rgb, 0, 1000,
467 						   0,0,0,0,0,
468 						   0,0,0,0,0);
469 
470 	for (INT32 i = 0; i < 0x40; i++)
471 	{
472 		INT32 bit0 = (~DrvPalRAM[i] >> 6) & 0x01;
473 		INT32 bit1 = (~DrvPalRAM[i] >> 7) & 0x01;
474 		INT32 bit2 = (~DrvPalRAM[i] >> 8) & 0x01;
475 		INT32 r = combine_3_weights(weights_rgb, bit0, bit1, bit2);
476 
477 		bit0 = (~DrvPalRAM[i] >> 3) & 0x01;
478 		bit1 = (~DrvPalRAM[i] >> 4) & 0x01;
479 		bit2 = (~DrvPalRAM[i] >> 5) & 0x01;
480 		INT32 g = combine_3_weights(weights_rgb, bit0, bit1, bit2);
481 
482 		bit0 = (~DrvPalRAM[i] >> 0) & 0x01;
483 		bit1 = (~DrvPalRAM[i] >> 1) & 0x01;
484 		bit2 = (~DrvPalRAM[i] >> 2) & 0x01;
485 		INT32 b = combine_3_weights(weights_rgb, bit0, bit1, bit2);
486 
487 		DrvPalette[i] = BurnHighCol(r,g,b,0);
488 	}
489 }
490 
draw_layer()491 static void draw_layer()
492 {
493 	for (INT32 offs = /*3 * 32*/0; offs < 32 * 32; offs++)
494 	{
495 		INT32 sx = (offs & 0x1f) * 8;
496 		INT32 sy = (offs / 0x20) * 8;
497 
498 		INT32 code = DrvVidRAM[offs];
499 
500 		Render8x8Tile_Clip(pTransDraw, code, sx, sy - 24, 0, 4, 0, DrvGfxROM0);
501 	}
502 }
503 
draw_bitmap()504 static void draw_bitmap()
505 {
506 	for (INT32 y = 24; y < 256; y++)
507 	{
508 		for (INT32 x = 0; x < 256; x++)
509 		{
510 			UINT8 pen = bitmap[video_selected][(y * 256) | x] & 0x07;
511 
512 			if (pen) {
513 				pTransDraw[((y - 24) * nScreenWidth) + ((x - 6) & 0xff)] = 0x10 | ((x & 0x80) >> 4) | pen;
514 					//0x10 | ((x >> 4) & 8) | pen;
515 			}
516 		}
517 	}
518 }
519 
draw_sprites()520 static void draw_sprites()
521 {
522 	for (INT32 offs = (0x100 / 4) - 1; offs >= 0; offs--)
523 	{
524 		INT32 code  = DrvSprRAM[offs + 64] & 0x7f;
525 		INT32 color = 0;
526 		INT32 flipx = DrvSprRAM[offs + 64] & 0x80;
527 		INT32 flipy = 0;
528 		INT32 sx    = DrvSprRAM[offs + 192];
529 		INT32 sy    = 240 - DrvSprRAM[offs];
530 
531 		if (flipscreen)
532 		{
533 			sx -= 9;
534 			sy = 240 - sy;
535 			flipx = !flipx;
536 			flipy = !flipy;
537 		} else {
538 			sy -= 24;
539 		}
540 
541 		if (flipy) {
542 			if (flipx) {
543 				RenderCustomTile_Mask_FlipXY_Clip(pTransDraw, 8, 16, code, sx, sy, color, 4, 0, 0x20, DrvGfxROM1);
544 			} else {
545 				RenderCustomTile_Mask_FlipY_Clip(pTransDraw, 8, 16, code, sx, sy, color, 4, 0, 0x20, DrvGfxROM1);
546 			}
547 		} else {
548 			if (flipx) {
549 				RenderCustomTile_Mask_FlipX_Clip(pTransDraw, 8, 16, code, sx, sy, color, 4, 0, 0x20, DrvGfxROM1);
550 			} else {
551 				RenderCustomTile_Mask_Clip(pTransDraw, 8, 16, code, sx, sy, color, 4, 0, 0x20, DrvGfxROM1);
552 			}
553 		}
554 	}
555 }
556 
DrvDraw()557 static INT32 DrvDraw()
558 {
559 	//if (DrvRecalc) {
560 		palette_update();
561 		DrvRecalc = 0;
562 	//}
563 
564 	BurnTransferClear();
565 
566 	if (nBurnLayer & 1) draw_layer();
567 	if (nBurnLayer & 2) draw_bitmap();
568 	if (nBurnLayer & 4) draw_sprites();
569 
570 	BurnTransferCopy(DrvPalette);
571 
572 	return 0;
573 }
574 
DrvFrame()575 static INT32 DrvFrame()
576 {
577 	if (DrvReset) {
578 		DrvDoReset(1);
579 	}
580 
581 	watchdog++;
582 	if (watchdog >= 180) {
583 		DrvDoReset(0);
584 	}
585 
586 	{
587 		memset (DrvInputs, 0xff, 4);
588 
589 		for (INT32 i = 0; i < 8; i++) {
590 			DrvInputs[0] ^= (DrvJoy1[i] & 1) << i;
591 			DrvInputs[2] ^= (DrvJoy3[i] & 1) << i;
592 			DrvInputs[3] ^= (DrvJoy4[i] & 1) << i;
593 		}
594 	}
595 
596 	INT32 nInterleave = 262;
597 	INT32 nCyclesTotal[2] = { 1000000 / 60, 1250000 / 60 };
598 	INT32 nCyclesDone[2] = { 0, 0 };
599 
600 	vblank = 0;
601 
602 	for (INT32 i = 0; i < nInterleave; i++)
603 	{
604 		M6502Open(0);
605 		nCyclesDone[0] += M6502Run(nCyclesTotal[0] / nInterleave);
606 		if ((i & 0x3f) == 0x3f) M6502SetIRQLine(0, CPU_IRQSTATUS_HOLD);
607 		M6502Close();
608 
609 		M6502Open(1);
610 		nCyclesDone[1] += M6502Run(nCyclesTotal[1] / nInterleave);
611 		if ((i & 0x7f) == 0x7f) M6502SetIRQLine(0, CPU_IRQSTATUS_HOLD);
612 		M6502Close();
613 
614 		if (i == 240) vblank = 1;
615 	}
616 
617 	if (pBurnSoundOut) {
618 		pokey_update(pBurnSoundOut, nBurnSoundLen);
619 	}
620 
621 	if (pBurnDraw) {
622 		DrvDraw();
623 	}
624 
625 	return 0;
626 }
627 
DrvScan(INT32 nAction,INT32 * pnMin)628 static INT32 DrvScan(INT32 nAction,INT32 *pnMin)
629 {
630 	struct BurnArea ba;
631 
632 	if (pnMin) {
633 		*pnMin = 0x029727;
634 	}
635 
636 	if (nAction & ACB_NVRAM) {
637 		memset(&ba, 0, sizeof(ba));
638 		ba.Data		= DrvNVRAM;
639 		ba.nLen		= 0x000200;
640 		ba.szName	= "Nonvolatile RAM";
641 		BurnAcb(&ba);
642 	}
643 
644 	if (nAction & ACB_VOLATILE) {
645 		memset(&ba, 0, sizeof(ba));
646 		ba.Data	  = AllRam;
647 		ba.nLen	  = RamEnd - AllRam;
648 		ba.szName = "All Ram";
649 		BurnAcb(&ba);
650 
651 		M6502Scan(nAction);
652 
653 		pokey_scan(nAction, pnMin);
654 
655 		SCAN_VAR(nvram_enable);
656 		SCAN_VAR(flipscreen);
657 		SCAN_VAR(video_selected);
658 		SCAN_VAR(video_address_x);
659 		SCAN_VAR(video_address_y);
660 	}
661 
662 	return 0;
663 }
664 
665 
666 // Cloak & Dagger (rev 5)
667 
668 static struct BurnRomInfo cloakRomDesc[] = {
669 	{ "136023-501.bin",	0x2000, 0xc2dbef1b, 1 | BRF_PRG | BRF_ESS }, //  0 M6502 #0 code
670 	{ "136023-502.bin",	0x2000, 0x316d0c7b, 1 | BRF_PRG | BRF_ESS }, //  1
671 	{ "136023-503.bin",	0x4000, 0xb9c291a6, 1 | BRF_PRG | BRF_ESS }, //  2
672 	{ "136023-504.bin",	0x4000, 0xd014a1c0, 1 | BRF_PRG | BRF_ESS }, //  3
673 
674 	{ "136023-509.bin",	0x2000, 0x46c021a4, 2 | BRF_GRA },           //  4 M6502 #1 code
675 	{ "136023-510.bin",	0x2000, 0x8c9cf017, 2 | BRF_GRA },           //  5
676 	{ "136023-511.bin",	0x2000, 0x66fd8a34, 2 | BRF_GRA },           //  6
677 	{ "136023-512.bin",	0x2000, 0x48c8079e, 2 | BRF_GRA },           //  7
678 	{ "136023-513.bin",	0x2000, 0x13f1cbab, 2 | BRF_GRA },           //  8
679 	{ "136023-514.bin",	0x2000, 0x6f8c7991, 2 | BRF_GRA },           //  9
680 	{ "136023-515.bin",	0x2000, 0x835438a0, 2 | BRF_GRA },           // 10
681 
682 	{ "136023-105.bin",	0x1000, 0xee443909, 3 | BRF_GRA },           // 11 Background tiles
683 	{ "136023-106.bin",	0x1000, 0xd708b132, 3 | BRF_GRA },           // 12
684 
685 	{ "136023-107.bin",	0x1000, 0xc42c84a4, 4 | BRF_GRA },           // 13 Sprites
686 	{ "136023-108.bin",	0x1000, 0x4fe13d58, 4 | BRF_GRA },           // 14
687 
688 	{ "136023-116.3n",	0x0100, 0xef2668e5, 5 | BRF_OPT },           // 15 Timing prom
689 };
690 
691 STD_ROM_PICK(cloak)
692 STD_ROM_FN(cloak)
693 
694 struct BurnDriver BurnDrvCloak = {
695 	"cloak", NULL, NULL, NULL, "1983",
696 	"Cloak & Dagger (rev 5)\0", NULL, "Atari", "Miscellaneous",
697 	NULL, NULL, NULL, NULL,
698 	BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_ACTION, 0,
699 	NULL, cloakRomInfo, cloakRomName, NULL, NULL, NULL, NULL, CloakInputInfo, CloakDIPInfo,
700 	DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x40,
701 	256, 232, 4, 3
702 };
703 
704 
705 // Cloak & Dagger (Spanish)
706 
707 static struct BurnRomInfo cloakspRomDesc[] = {
708 	{ "136023-501.bin",	0x2000, 0xc2dbef1b, 1 | BRF_PRG | BRF_ESS }, //  0 M6502 #0 code
709 	{ "136023-502.bin",	0x2000, 0x316d0c7b, 1 | BRF_PRG | BRF_ESS }, //  1
710 	{ "136023-503.bin",	0x4000, 0xb9c291a6, 1 | BRF_PRG | BRF_ESS }, //  2
711 	{ "136023-804.bin",	0x4000, 0x994899c7, 1 | BRF_PRG | BRF_ESS }, //  3
712 
713 	{ "136023-509.bin",	0x2000, 0x46c021a4, 2 | BRF_GRA },           //  4 M6502 #1 code
714 	{ "136023-510.bin",	0x2000, 0x8c9cf017, 2 | BRF_GRA },           //  5
715 	{ "136023-511.bin",	0x2000, 0x66fd8a34, 2 | BRF_GRA },           //  6
716 	{ "136023-512.bin",	0x2000, 0x48c8079e, 2 | BRF_GRA },           //  7
717 	{ "136023-513.bin",	0x2000, 0x13f1cbab, 2 | BRF_GRA },           //  8
718 	{ "136023-514.bin",	0x2000, 0x6f8c7991, 2 | BRF_GRA },           //  9
719 	{ "136023-515.bin",	0x2000, 0x835438a0, 2 | BRF_GRA },           // 10
720 
721 	{ "136023-105.bin",	0x1000, 0xee443909, 3 | BRF_GRA },           // 11 Background tiles
722 	{ "136023-106.bin",	0x1000, 0xd708b132, 3 | BRF_GRA },           // 12
723 
724 	{ "136023-107.bin",	0x1000, 0xc42c84a4, 4 | BRF_GRA },           // 13 Sprites
725 	{ "136023-108.bin",	0x1000, 0x4fe13d58, 4 | BRF_GRA },           // 14
726 
727 	{ "136023-116.3n",	0x0100, 0xef2668e5, 5 | BRF_OPT },           // 15 Timing prom
728 };
729 
730 STD_ROM_PICK(cloaksp)
731 STD_ROM_FN(cloaksp)
732 
733 struct BurnDriver BurnDrvCloaksp = {
734 	"cloaksp", "cloak", NULL, NULL, "1983",
735 	"Cloak & Dagger (Spanish)\0", NULL, "Atari", "Miscellaneous",
736 	NULL, NULL, NULL, NULL,
737 	BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_ACTION, 0,
738 	NULL, cloakspRomInfo, cloakspRomName, NULL, NULL, NULL, NULL, CloakInputInfo, CloakDIPInfo,
739 	DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x40,
740 	256, 232, 4, 3
741 };
742 
743 
744 // Cloak & Dagger (French)
745 
746 static struct BurnRomInfo cloakfrRomDesc[] = {
747 	{ "136023-501.bin",	0x2000, 0xc2dbef1b, 1 | BRF_PRG | BRF_ESS }, //  0 M6502 #0 code
748 	{ "136023-502.bin",	0x2000, 0x316d0c7b, 1 | BRF_PRG | BRF_ESS }, //  1
749 	{ "136023-503.bin",	0x4000, 0xb9c291a6, 1 | BRF_PRG | BRF_ESS }, //  2
750 	{ "136023-704.bin",	0x4000, 0xbf225ea0, 1 | BRF_PRG | BRF_ESS }, //  3
751 
752 	{ "136023-509.bin",	0x2000, 0x46c021a4, 2 | BRF_GRA },           //  4 M6502 #1 code
753 	{ "136023-510.bin",	0x2000, 0x8c9cf017, 2 | BRF_GRA },           //  5
754 	{ "136023-511.bin",	0x2000, 0x66fd8a34, 2 | BRF_GRA },           //  6
755 	{ "136023-512.bin",	0x2000, 0x48c8079e, 2 | BRF_GRA },           //  7
756 	{ "136023-513.bin",	0x2000, 0x13f1cbab, 2 | BRF_GRA },           //  8
757 	{ "136023-514.bin",	0x2000, 0x6f8c7991, 2 | BRF_GRA },           //  9
758 	{ "136023-515.bin",	0x2000, 0x835438a0, 2 | BRF_GRA },           // 10
759 
760 	{ "136023-105.bin",	0x1000, 0xee443909, 3 | BRF_GRA },           // 11 Background tiles
761 	{ "136023-106.bin",	0x1000, 0xd708b132, 3 | BRF_GRA },           // 12
762 
763 	{ "136023-107.bin",	0x1000, 0xc42c84a4, 4 | BRF_GRA },           // 13 Sprites
764 	{ "136023-108.bin",	0x1000, 0x4fe13d58, 4 | BRF_GRA },           // 14
765 
766 	{ "136023-116.3n",	0x0100, 0xef2668e5, 5 | BRF_OPT },           // 15 Timing prom
767 };
768 
769 STD_ROM_PICK(cloakfr)
770 STD_ROM_FN(cloakfr)
771 
772 struct BurnDriver BurnDrvCloakfr = {
773 	"cloakfr", "cloak", NULL, NULL, "1983",
774 	"Cloak & Dagger (French)\0", NULL, "Atari", "Miscellaneous",
775 	NULL, NULL, NULL, NULL,
776 	BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_ACTION, 0,
777 	NULL, cloakfrRomInfo, cloakfrRomName, NULL, NULL, NULL, NULL, CloakInputInfo, CloakDIPInfo,
778 	DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x40,
779 	256, 232, 4, 3
780 };
781 
782 
783 // Cloak & Dagger (German)
784 
785 static struct BurnRomInfo cloakgrRomDesc[] = {
786 	{ "136023-501.bin",	0x2000, 0xc2dbef1b, 1 | BRF_PRG | BRF_ESS }, //  0 M6502 #0 code
787 	{ "136023-502.bin",	0x2000, 0x316d0c7b, 1 | BRF_PRG | BRF_ESS }, //  1
788 	{ "136023-503.bin",	0x4000, 0xb9c291a6, 1 | BRF_PRG | BRF_ESS }, //  2
789 	{ "136023-604.bin",	0x4000, 0x7ac66aea, 1 | BRF_PRG | BRF_ESS }, //  3
790 
791 	{ "136023-509.bin",	0x2000, 0x46c021a4, 2 | BRF_GRA },           //  4 M6502 #1 code
792 	{ "136023-510.bin",	0x2000, 0x8c9cf017, 2 | BRF_GRA },           //  5
793 	{ "136023-511.bin",	0x2000, 0x66fd8a34, 2 | BRF_GRA },           //  6
794 	{ "136023-512.bin",	0x2000, 0x48c8079e, 2 | BRF_GRA },           //  7
795 	{ "136023-513.bin",	0x2000, 0x13f1cbab, 2 | BRF_GRA },           //  8
796 	{ "136023-514.bin",	0x2000, 0x6f8c7991, 2 | BRF_GRA },           //  9
797 	{ "136023-515.bin",	0x2000, 0x835438a0, 2 | BRF_GRA },           // 10
798 
799 	{ "136023-105.bin",	0x1000, 0xee443909, 3 | BRF_GRA },           // 11 Background tiles
800 	{ "136023-106.bin",	0x1000, 0xd708b132, 3 | BRF_GRA },           // 12
801 
802 	{ "136023-107.bin",	0x1000, 0xc42c84a4, 4 | BRF_GRA },           // 13 Sprites
803 	{ "136023-108.bin",	0x1000, 0x4fe13d58, 4 | BRF_GRA },           // 14
804 
805 	{ "136023-116.3n",	0x0100, 0xef2668e5, 5 | BRF_OPT },           // 15 Timing prom
806 };
807 
808 STD_ROM_PICK(cloakgr)
809 STD_ROM_FN(cloakgr)
810 
811 struct BurnDriver BurnDrvCloakgr = {
812 	"cloakgr", "cloak", NULL, NULL, "1983",
813 	"Cloak & Dagger (German)\0", NULL, "Atari", "Miscellaneous",
814 	NULL, NULL, NULL, NULL,
815 	BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_ACTION, 0,
816 	NULL, cloakgrRomInfo, cloakgrRomName, NULL, NULL, NULL, NULL, CloakInputInfo, CloakDIPInfo,
817 	DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x40,
818 	256, 232, 4, 3
819 };
820 
821 
822 // Agent X (prototype, rev 4)
823 
824 static struct BurnRomInfo agentx4RomDesc[] = {
825 	{ "136401-023.bin",	0x2000, 0xf7edac86, 1 | BRF_PRG | BRF_ESS }, //  0 M6502 #0 code
826 	{ "136402-023.bin",	0x2000, 0xdb5e2382, 1 | BRF_PRG | BRF_ESS }, //  1
827 	{ "136403-023.bin",	0x4000, 0x87de01b4, 1 | BRF_PRG | BRF_ESS }, //  2
828 	{ "136404-023.bin",	0x4000, 0xb97219dc, 1 | BRF_PRG | BRF_ESS }, //  3
829 
830 	{ "136409-023.bin",	0x2000, 0xadd4a749, 2 | BRF_GRA },           //  4 M6502 #1 code
831 	{ "136410-023.bin",	0x2000, 0xb1e1c074, 2 | BRF_GRA },           //  5
832 	{ "136411-023.bin",	0x2000, 0x6d0c1ee5, 2 | BRF_GRA },           //  6
833 	{ "136412-023.bin",	0x2000, 0x815af543, 2 | BRF_GRA },           //  7
834 	{ "136413-023.bin",	0x2000, 0x2ad9e622, 2 | BRF_GRA },           //  8
835 	{ "136414-023.bin",	0x2000, 0xcadf9ab0, 2 | BRF_GRA },           //  9
836 	{ "136415-023.bin",	0x2000, 0xf5024961, 2 | BRF_GRA },           // 10
837 
838 	{ "136105-023.bin",	0x1000, 0xee443909, 3 | BRF_GRA },           // 11 Background tiles
839 	{ "136106-023.bin",	0x1000, 0xd708b132, 3 | BRF_GRA },           // 12
840 
841 	{ "136107-023.bin",	0x1000, 0xc42c84a4, 4 | BRF_GRA },           // 13 Sprites
842 	{ "136108-023.bin",	0x1000, 0x4fe13d58, 4 | BRF_GRA },           // 14
843 
844 	{ "136023-116.3n",	0x0100, 0xef2668e5, 5 | BRF_OPT },           // 15 Timing prom
845 };
846 
847 STD_ROM_PICK(agentx4)
848 STD_ROM_FN(agentx4)
849 
850 struct BurnDriver BurnDrvAgentx4 = {
851 	"agentx4", "cloak", NULL, NULL, "1983",
852 	"Agent X (prototype, rev 4)\0", NULL, "Atari", "Miscellaneous",
853 	NULL, NULL, NULL, NULL,
854 	BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_ACTION, 0,
855 	NULL, agentx4RomInfo, agentx4RomName, NULL, NULL, NULL, NULL, CloakInputInfo, CloakDIPInfo,
856 	DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x40,
857 	256, 232, 4, 3
858 };
859 
860 
861 // Agent X (prototype, rev 3)
862 
863 static struct BurnRomInfo agentx3RomDesc[] = {
864 	{ "136301-023.bin",	0x2000, 0xfba1d9de, 1 | BRF_PRG | BRF_ESS }, //  0 M6502 #0 code
865 	{ "136302-023.bin",	0x2000, 0xe5694c72, 1 | BRF_PRG | BRF_ESS }, //  1
866 	{ "136303-023.bin",	0x4000, 0x70ef51c5, 1 | BRF_PRG | BRF_ESS }, //  2
867 	{ "136304-023.bin",	0x4000, 0xf4a86cda, 1 | BRF_PRG | BRF_ESS }, //  3
868 
869 	{ "136309-023.bin",	0x2000, 0x1c04282d, 2 | BRF_GRA },           //  4 M6502 #1 code
870 	{ "136310-023.bin",	0x2000, 0xa61eaa88, 2 | BRF_GRA },           //  5
871 	{ "136311-023.bin",	0x2000, 0xa670f4b4, 2 | BRF_GRA },           //  6
872 	{ "136312-023.bin",	0x2000, 0xe955af62, 2 | BRF_GRA },           //  7
873 	{ "136313-023.bin",	0x2000, 0xb4b46d9d, 2 | BRF_GRA },           //  8
874 	{ "136314-023.bin",	0x2000, 0x3138a3b2, 2 | BRF_GRA },           //  9
875 	{ "136315-023.bin",	0x2000, 0xd12f5523, 2 | BRF_GRA },           // 10
876 
877 	{ "136105-023.bin",	0x1000, 0xee443909, 3 | BRF_GRA },           // 11 Background tiles
878 	{ "136106-023.bin",	0x1000, 0xd708b132, 3 | BRF_GRA },           // 12
879 
880 	{ "136107-023.bin",	0x1000, 0xc42c84a4, 4 | BRF_GRA },           // 13 Sprites
881 	{ "136108-023.bin",	0x1000, 0x4fe13d58, 4 | BRF_GRA },           // 14
882 
883 	{ "136023-116.3n",	0x0100, 0xef2668e5, 5 | BRF_OPT },           // 15 Timing prom
884 };
885 
886 STD_ROM_PICK(agentx3)
887 STD_ROM_FN(agentx3)
888 
889 struct BurnDriver BurnDrvAgentx3 = {
890 	"agentx3", "cloak", NULL, NULL, "1983",
891 	"Agent X (prototype, rev 3)\0", NULL, "Atari", "Miscellaneous",
892 	NULL, NULL, NULL, NULL,
893 	BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_ACTION, 0,
894 	NULL, agentx3RomInfo, agentx3RomName, NULL, NULL, NULL, NULL, CloakInputInfo, CloakDIPInfo,
895 	DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x40,
896 	256, 232, 4, 3
897 };
898 
899 
900 // Agent X (prototype, rev 2)
901 
902 static struct BurnRomInfo agentx2RomDesc[] = {
903 	{ "136201-023.bin",	0x2000, 0xe6c7041f, 1 | BRF_PRG | BRF_ESS }, //  0 M6502 #0 code
904 	{ "136202-023.bin",	0x2000, 0x4c94929e, 1 | BRF_PRG | BRF_ESS }, //  1
905 	{ "136203-023.bin",	0x4000, 0xc7a59697, 1 | BRF_PRG | BRF_ESS }, //  2
906 	{ "136204-023.bin",	0x4000, 0xe6e06a9c, 1 | BRF_PRG | BRF_ESS }, //  3
907 
908 	{ "136209-023.bin",	0x2000, 0x319772d8, 2 | BRF_GRA },           //  4 M6502 #1 code
909 	{ "136210-023.bin",	0x2000, 0x6e95f628, 2 | BRF_GRA },           //  5
910 	{ "136211-023.bin",	0x2000, 0x8d936132, 2 | BRF_GRA },           //  6
911 	{ "136212-023.bin",	0x2000, 0x9a3074c8, 2 | BRF_GRA },           //  7
912 	{ "136213-023.bin",	0x2000, 0x15984981, 2 | BRF_GRA },           //  8
913 	{ "136214-023.bin",	0x2000, 0xdba311ec, 2 | BRF_GRA },           //  9
914 	{ "136215-023.bin",	0x2000, 0xdc20c185, 2 | BRF_GRA },           // 10
915 
916 	{ "136105-023.bin",	0x1000, 0xee443909, 3 | BRF_GRA },           // 11 Background tiles
917 	{ "136106-023.bin",	0x1000, 0xd708b132, 3 | BRF_GRA },           // 12
918 
919 	{ "136107-023.bin",	0x1000, 0xc42c84a4, 4 | BRF_GRA },           // 13 Sprites
920 	{ "136108-023.bin",	0x1000, 0x4fe13d58, 4 | BRF_GRA },           // 14
921 
922 	{ "136023-116.3n",	0x0100, 0xef2668e5, 5 | BRF_OPT },           // 15 Timing prom
923 };
924 
925 STD_ROM_PICK(agentx2)
926 STD_ROM_FN(agentx2)
927 
928 struct BurnDriver BurnDrvAgentx2 = {
929 	"agentx2", "cloak", NULL, NULL, "1983",
930 	"Agent X (prototype, rev 2)\0", NULL, "Atari", "Miscellaneous",
931 	NULL, NULL, NULL, NULL,
932 	BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_ACTION, 0,
933 	NULL, agentx2RomInfo, agentx2RomName, NULL, NULL, NULL, NULL, CloakInputInfo, CloakDIPInfo,
934 	DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x40,
935 	256, 232, 4, 3
936 };
937 
938 
939 // Agent X (prototype, rev 1)
940 
941 static struct BurnRomInfo agentx1RomDesc[] = {
942 	{ "136101-023.bin",	0x2000, 0xa12b9c22, 1 | BRF_PRG | BRF_ESS }, //  0 M6502 #0 code
943 	{ "136102-023.bin",	0x2000, 0xe65d30df, 1 | BRF_PRG | BRF_ESS }, //  1
944 	{ "136103-023.bin",	0x4000, 0xc6f8a128, 1 | BRF_PRG | BRF_ESS }, //  2
945 	{ "136104-023.bin",	0x4000, 0xdb002945, 1 | BRF_PRG | BRF_ESS }, //  3
946 
947 	{ "136109-023.bin",	0x2000, 0x31487f5d, 2 | BRF_GRA },           //  4 M6502 #1 code
948 	{ "136110-023.bin",	0x2000, 0x1ee38ecb, 2 | BRF_GRA },           //  5
949 	{ "136111-023.bin",	0x2000, 0xca6a6b0c, 2 | BRF_GRA },           //  6
950 	{ "136112-023.bin",	0x2000, 0x933051bc, 2 | BRF_GRA },           //  7
951 	{ "136113-023.bin",	0x2000, 0x1706a674, 2 | BRF_GRA },           //  8
952 	{ "136114-023.bin",	0x2000, 0x7c7c905d, 2 | BRF_GRA },           //  9
953 	{ "136115-023.bin",	0x2000, 0x7f36710c, 2 | BRF_GRA },           // 10
954 
955 	{ "136105-023.bin",	0x1000, 0xee443909, 3 | BRF_GRA },           // 11 Background tiles
956 	{ "136106-023.bin",	0x1000, 0xd708b132, 3 | BRF_GRA },           // 12
957 
958 	{ "136107-023.bin",	0x1000, 0xc42c84a4, 4 | BRF_GRA },           // 13 Sprites
959 	{ "136108-023.bin",	0x1000, 0x4fe13d58, 4 | BRF_GRA },           // 14
960 
961 	{ "136023-116.3n",	0x0100, 0xef2668e5, 5 | BRF_OPT },           // 15 Timing prom
962 };
963 
964 STD_ROM_PICK(agentx1)
965 STD_ROM_FN(agentx1)
966 
967 struct BurnDriver BurnDrvAgentx1 = {
968 	"agentx1", "cloak", NULL, NULL, "1983",
969 	"Agent X (prototype, rev 1)\0", NULL, "Atari", "Miscellaneous",
970 	NULL, NULL, NULL, NULL,
971 	BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_ACTION, 0,
972 	NULL, agentx1RomInfo, agentx1RomName, NULL, NULL, NULL, NULL, CloakInputInfo, CloakDIPInfo,
973 	DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x40,
974 	256, 232, 4, 3
975 };
976