1 // FB Alpha Cloud 9 / Firebeast driver module
2 // Based on MAME driver by Mike Balfour and Aaron Giles
3 
4 #include "tiles_generic.h"
5 #include "m6502_intf.h"
6 #include "watchdog.h"
7 #include "pokey.h"
8 
9 static UINT8 *AllMem;
10 static UINT8 *AllRam;
11 static UINT8 *RamEnd;
12 static UINT8 *MemEnd;
13 static UINT8 *DrvM6502ROM;
14 static UINT8 *DrvGfxROM;
15 static UINT8 *DrvVidPROM;
16 static UINT8 *DrvNVRAM;
17 static UINT8 *DrvSprRAM;
18 static UINT8 *DrvVidRAM;
19 static UINT16 *DrvPalRAM;
20 
21 static UINT32 *DrvPalette;
22 static UINT8 DrvRecalc;
23 
24 static INT32 irq_state;
25 static UINT8 video_latch[8];
26 static UINT8 bitmode_addr[2];
27 
28 static INT32 vblank;
29 
30 static UINT8 DrvJoy1[8];
31 static UINT8 DrvJoy2[8];
32 static UINT8 DrvJoy3[8];
33 static UINT8 DrvDips[2];
34 static UINT8 DrvInputs[2];
35 static UINT8 DrvReset;
36 
37 static INT32 TrackX;
38 static INT32 TrackY;
39 
40 static INT32 is_firebeast = 0;
41 
42 static struct BurnInputInfo Cloud9InputList[] = {
43 	{"P1 Coin",			BIT_DIGITAL,	DrvJoy1 + 5,	"p1 coin"	},
44 	{"P1 Start",		BIT_DIGITAL,	DrvJoy2 + 7,	"p1 start"	},
45 	{"P1 Button 1",		BIT_DIGITAL,	DrvJoy2 + 5,	"p1 fire 1"	},
46 	{"P1 Button 2",		BIT_DIGITAL,	DrvJoy2 + 4,	"p1 fire 2"	},
47 
48 	{"P1 Up",		    BIT_DIGITAL,	DrvJoy3 + 0,	"p1 up"		},
49 	{"P1 Down",		    BIT_DIGITAL,	DrvJoy3 + 1,	"p1 down"	},
50 	{"P1 Left",		    BIT_DIGITAL,	DrvJoy3 + 2,	"p1 left"	},
51 	{"P1 Right",		BIT_DIGITAL,	DrvJoy3 + 3,	"p1 right"	},
52 
53 	{"Reset",			BIT_DIGITAL,	&DrvReset,		"reset"		},
54 	{"Service",			BIT_DIGITAL,	DrvJoy1 + 4,	"service"	},
55 	{"Dip A",			BIT_DIPSWITCH,	DrvDips + 0,	"dip"		},
56 	{"Dip B",			BIT_DIPSWITCH,	DrvDips + 1,	"dip"		},
57 };
58 
59 STDINPUTINFO(Cloud9)
60 
61 static struct BurnInputInfo FirebeasInputList[] = {
62 	{"P1 Coin",			BIT_DIGITAL,	DrvJoy1 + 5,	"p1 coin"	},
63 	{"P1 Start",		BIT_DIGITAL,	DrvJoy2 + 7,	"p1 start"	},
64 	{"P1 Button 1",		BIT_DIGITAL,	DrvJoy2 + 5,	"p1 fire 1"	},
65 	{"P1 Button 2",		BIT_DIGITAL,	DrvJoy2 + 3,	"p1 fire 2"	},
66 
67 	{"P1 Up",		    BIT_DIGITAL,	DrvJoy3 + 0,	"p1 up"		},
68 	{"P1 Down",		    BIT_DIGITAL,	DrvJoy3 + 1,	"p1 down"	},
69 	{"P1 Left",		    BIT_DIGITAL,	DrvJoy3 + 2,	"p1 left"	},
70 	{"P1 Right",		BIT_DIGITAL,	DrvJoy3 + 3,	"p1 right"	},
71 
72 	{"Reset",			BIT_DIGITAL,	&DrvReset,		"reset"		},
73 	{"Service",			BIT_DIGITAL,	DrvJoy1 + 4,	"service"	},
74 	{"Dip A",			BIT_DIPSWITCH,	DrvDips + 0,	"dip"		},
75 	{"Dip B",			BIT_DIPSWITCH,	DrvDips + 1,	"dip"		},
76 };
77 
78 STDINPUTINFO(Firebeas)
79 
80 static struct BurnDIPInfo Cloud9DIPList[]=
81 {
82 	{0x0a, 0xff, 0xff, 0x05, NULL					},
83 	{0x0b, 0xff, 0xff, 0x08, NULL					},
84 
85 	{0   , 0xfe, 0   ,    11, "Coinage"				},
86 	{0x0a, 0x01, 0xfe, 0x22, "9 Coins 1 Credits"	},
87 	{0x0a, 0x01, 0xfe, 0x1e, "8 Coins 1 Credits"	},
88 	{0x0a, 0x01, 0xfe, 0x1a, "7 Coins 1 Credits"	},
89 	{0x0a, 0x01, 0xfe, 0x16, "6 Coins 1 Credits"	},
90 	{0x0a, 0x01, 0xfe, 0x12, "5 Coins 1 Credits"	},
91 	{0x0a, 0x01, 0xfe, 0x0e, "4 Coins 1 Credits"	},
92 	{0x0a, 0x01, 0xfe, 0x0a, "3 Coins 1 Credits"	},
93 	{0x0a, 0x01, 0xfe, 0x06, "2 Coins 1 Credits"	},
94 	{0x0a, 0x01, 0xfe, 0x04, "1 Coin  1 Credits"	},
95 	{0x0a, 0x01, 0xfe, 0x02, "1 Coin  2 Credits"	},
96 	{0x0a, 0x01, 0xfe, 0x00, "Free Play"			},
97 
98 	{0   , 0xfe, 0   ,    2, "Service Mode"			},
99 	{0x0b, 0x01, 0x08, 0x08, "Off"					},
100 	{0x0b, 0x01, 0x08, 0x00, "On"					},
101 };
102 
103 STDDIPINFO(Cloud9)
104 
105 static struct BurnDIPInfo FirebeasDIPList[]=
106 {
107 	{0x0a, 0xff, 0xff, 0xff, NULL					},
108 	{0x0b, 0xff, 0xff, 0x08, NULL					},
109 
110 	{0   , 0xfe, 0   ,    2, "Service Mode"			},
111 	{0x0b, 0x01, 0x08, 0x08, "Off"					},
112 	{0x0b, 0x01, 0x08, 0x00, "On"					},
113 };
114 
STDDIPINFO(Firebeas)115 STDDIPINFO(Firebeas)
116 
117 static void palette_write(UINT8 offset, INT32 data)
118 {
119 	DrvPalRAM[offset] = data;
120 
121 	data ^= 0x1ff;
122 
123 	INT32 bit0 = (data >> 6) & 0x01;
124 	INT32 bit1 = (data >> 7) & 0x01;
125 	INT32 bit2 = (data >> 8) & 0x01;
126 	INT32 r = (((bit0 * 4700) + (bit1 * 10000) + (bit2 * 22000)) * 255) / 36700;
127 
128 	bit0 = (data >> 3) & 0x01;
129 	bit1 = (data >> 4) & 0x01;
130 	bit2 = (data >> 5) & 0x01;
131 	INT32 g = (((bit0 * 4700) + (bit1 * 10000) + (bit2 * 22000)) * 255) / 36700;
132 
133 	bit0 = (data >> 0) & 0x01;
134 	bit1 = (data >> 1) & 0x01;
135 	bit2 = (data >> 2) & 0x01;
136 	INT32 b = (((bit0 * 4700) + (bit1 * 10000) + (bit2 * 22000)) * 255) / 36700;
137 
138 	DrvPalette[offset] = BurnHighCol(r,g,b,0);
139 }
140 
bitmode_autoinc()141 static inline void bitmode_autoinc()
142 {
143 	if (!video_latch[0])
144 		bitmode_addr[0]++;
145 
146 	if (!video_latch[1])
147 		bitmode_addr[1]++;
148 }
149 
write_vram(UINT16 addr,UINT8 data,UINT8 bitmd,UINT8 pixba)150 static void write_vram(UINT16 addr, UINT8 data, UINT8 bitmd, UINT8 pixba )
151 {
152 	UINT8 *dest = &DrvVidRAM[0x0000 | (addr & 0x3fff)];
153 	UINT8 *dest2 = &DrvVidRAM[0x4000 | (addr & 0x3fff)];
154 	UINT8 promaddr = 0;
155 	UINT8 wpbits;
156 
157 	promaddr |= bitmd << 7;
158 	promaddr |= video_latch[4] << 6;
159 	promaddr |= video_latch[6] << 5;
160 	promaddr |= ((addr & 0xf000) != 0x4000) << 4;
161 	promaddr |= ((addr & 0x3800) == 0x0000) << 3;
162 	promaddr |= ((addr & 0x0600) == 0x0600) << 2;
163 	promaddr |= (pixba << 0);
164 
165 	wpbits = DrvVidPROM[0x200 + promaddr];
166 
167 	if (!(wpbits & 1))
168 		dest2[0] = (dest2[0] & 0x0f) | (data & 0xf0);
169 	if (!(wpbits & 2))
170 		dest2[0] = (dest2[0] & 0xf0) | (data & 0x0f);
171 	if (!(wpbits & 4))
172 		dest[0] = (dest[0] & 0x0f) | (data & 0xf0);
173 	if (!(wpbits & 8))
174 		dest[0] = (dest[0] & 0xf0) | (data & 0x0f);
175 }
176 
bitmode_read()177 static UINT8 bitmode_read()
178 {
179 	UINT16 addr = (bitmode_addr[1] << 6) | (bitmode_addr[0] >> 2);
180 
181 	UINT8 result = DrvVidRAM[((~bitmode_addr[0] & 2) << 13) | addr] << ((bitmode_addr[0] & 1) * 4);
182 
183 	bitmode_autoinc();
184 
185 	return (result >> 4) | 0xf0;
186 }
187 
bitmode_write(UINT8 data)188 static void bitmode_write(UINT8 data)
189 {
190 	UINT16 addr = (bitmode_addr[1] << 6) | (bitmode_addr[0] >> 2);
191 
192 	data = (data & 0x0f) | (data << 4);
193 
194 	write_vram(addr, data, 1, bitmode_addr[0] & 3);
195 
196 	bitmode_autoinc();
197 }
198 
cloud9_write(UINT16 address,UINT8 data)199 static void cloud9_write(UINT16 address, UINT8 data)
200 {
201 	if (address <= 0x0001) {
202 		write_vram(address, data, 0, 0);
203 		bitmode_addr[address] = data;
204 		// falls through to write_vram()!
205 	}
206 
207 	if (address == 0x0002) {
208 		bitmode_write(data);
209 		return;
210 	}
211 
212 	if (address <= 0x4fff) {
213 		write_vram(address, data, 0, 0);
214 		return;
215 	}
216 
217 	if ((address & 0xff80) == 0x5400) {
218 		BurnWatchdogWrite();
219 		return;
220 	}
221 
222 	if ((address & 0xff80) == 0x5480) {
223 		if (irq_state) {
224 			M6502SetIRQLine(0, CPU_IRQSTATUS_NONE);
225 			irq_state = 0;
226 		}
227 		return;
228 	}
229 
230 	if ((address & 0xff80) == 0x5500) {
231 		INT32 val = (data << 1) | ((address & 0x40) >> 6);
232 		palette_write(address & 0x3f, val);
233 		return;
234 	}
235 
236 	if ((address & 0xff80) == 0x5580) {
237 		video_latch[address & 7] = data >> 7;
238 		return;
239 	}
240 
241 	if ((address & 0xff80) == 0x5600) {
242 		data >>= 7;
243 		address &= 7;
244 		// coin coiners & leds
245 		return;
246 	}
247 
248 	if ((address & 0xff80) == 0x5680) {
249 		// nvram store
250 		return;
251 	}
252 
253 	if ((address & 0xff80) == 0x5700) {
254 		// nvram recall
255 		return;
256 	}
257 
258 	if ((address & 0xfe00) == 0x5a00) {
259 		pokey_write((address >> 8) & 1, address & 0xf, data);
260 		return;
261 	}
262 
263 	if ((address & 0xfc00) == 0x5c00) {
264 		DrvNVRAM[address & 0xff] = data & 0x0f;
265 		return;
266 	}
267 }
268 
cloud9_read(UINT16 address)269 static UINT8 cloud9_read(UINT16 address)
270 {
271 	if (address == 0x0002) {
272 		return bitmode_read();
273 	}
274 
275 	if (address >= 0x0000 && address <= 0x4fff) {
276 		return DrvVidRAM[address];
277 	}
278 
279 	if ((address & 0xff80) == 0x5800) {
280 		if (address & 1) {
281 			return DrvInputs[1];
282 		} else {
283 			return (DrvInputs[0] & ~0x80) | (vblank ? 0 : 0x80);
284 		}
285 	}
286 
287 	if ((address & 0xfffc) == 0x5900) {
288 		return (address & 3) ? (TrackX & 0xff) : (TrackY & 0xff);
289 	}
290 
291 	if ((address & 0xfe00) == 0x5a00) {
292 		return pokey_read((address >> 8) & 1, address & 0xf);
293 	}
294 
295 	if ((address & 0xfc00) == 0x5c00) {
296 		return DrvNVRAM[address & 0xff] | 0xf0;
297 	}
298 
299 	return 0;
300 }
301 
pokey_1_callback(INT32)302 static INT32 pokey_1_callback(INT32)
303 {
304 	return DrvDips[0];
305 }
306 
DrvDoReset(INT32 clear_mem)307 static INT32 DrvDoReset(INT32 clear_mem)
308 {
309 	if (clear_mem) {
310 		memset (AllRam, 0, RamEnd - AllRam);
311 	}
312 
313 	M6502Open(0);
314 	M6502Reset();
315 	M6502Close();
316 
317 	BurnWatchdogReset();
318 
319 	PokeyReset();
320 
321 	irq_state = 0;
322 	for (INT32 i = 0; i < 8; i++) {
323 		video_latch[i] = 0;
324 	}
325 	bitmode_addr[0] = 0;
326 	bitmode_addr[1] = 0;
327 
328 	return 0;
329 }
330 
MemIndex()331 static INT32 MemIndex()
332 {
333 	UINT8 *Next; Next = AllMem;
334 
335 	DrvM6502ROM		= Next; Next += 0x010000;
336 
337 	DrvGfxROM		= Next; Next += 0x010000;
338 
339 	DrvVidPROM		= Next; Next += 0x000400;
340 
341 	DrvPalette		= (UINT32*)Next; Next += 0x0041 * sizeof(UINT32);
342 
343 	DrvNVRAM		= Next; Next += 0x000100;
344 
345 	AllRam			= Next;
346 
347 	DrvSprRAM		= Next; Next += 0x000800;
348 	DrvVidRAM		= Next; Next += 0x008000;
349 
350 	DrvPalRAM		= (UINT16*)Next; Next += 0x000040 * sizeof(UINT16);
351 
352 	RamEnd			= Next;
353 
354 	MemEnd			= Next;
355 
356 	return 0;
357 }
358 
DrvGfxDecode()359 static INT32 DrvGfxDecode()
360 {
361 	INT32 Plane[4]  = { 0x2000*8*3, 0x2000*8*2, 0x2000*8*1, 0x2000*8*0 };
362 	INT32 XOffs[16] = { STEP16(0,1) };
363 	INT32 YOffs[16] = { STEP16(0,16) };
364 
365 	UINT8 *tmp = (UINT8*)BurnMalloc(0x8000);
366 	if (tmp == NULL) {
367 		return 1;
368 	}
369 
370 	memcpy (tmp, DrvGfxROM, 0x8000);
371 
372 	GfxDecode(0x0100, 4, 16, 16, Plane, XOffs, YOffs, 0x100, tmp, DrvGfxROM);
373 
374 	BurnFree(tmp);
375 
376 	return 0;
377 }
378 
DrvInit()379 static INT32 DrvInit()
380 {
381 	BurnAllocMemIndex();
382 
383 	{
384 		INT32 k = 0;
385 		if (BurnLoadRom(DrvM6502ROM + 0x6000, k++, 1)) return 1;
386 		if (BurnLoadRom(DrvM6502ROM + 0x8000, k++, 1)) return 1;
387 		if (BurnLoadRom(DrvM6502ROM + 0xa000, k++, 1)) return 1;
388 		if (BurnLoadRom(DrvM6502ROM + 0xc000, k++, 1)) return 1;
389 		if (BurnLoadRom(DrvM6502ROM + 0xe000, k++, 1)) return 1;
390 
391 		// firebeast has a half-sized rom at the end (check for 0'd vectors)
392 		if (DrvM6502ROM[0xffff] == 0 && DrvM6502ROM[0xfffe] == 0) {
393 			memcpy (DrvM6502ROM + 0xf000, DrvM6502ROM + 0xe000, 0x1000);
394 			is_firebeast = 1;
395 		}
396 
397 		if (BurnLoadRom(DrvGfxROM   + 0x0000, k++, 1)) return 1;
398 		if (BurnLoadRom(DrvGfxROM   + 0x2000, k++, 1)) return 1;
399 		if (BurnLoadRom(DrvGfxROM   + 0x4000, k++, 1)) return 1;
400 		if (BurnLoadRom(DrvGfxROM   + 0x6000, k++, 1)) return 1;
401 
402 		if (BurnLoadRom(DrvVidPROM  + 0x0000, k++, 1)) return 1;
403 		if (BurnLoadRom(DrvVidPROM  + 0x0100, k++, 1)) return 1;
404 		if (BurnLoadRom(DrvVidPROM  + 0x0200, k++, 1)) return 1;
405 		if (BurnLoadRom(DrvVidPROM  + 0x0300, k++, 1)) return 1;
406 
407 		DrvGfxDecode();
408 	}
409 
410 	memset(DrvNVRAM, 0xff, 0x100);
411 
412 	M6502Init(0, TYPE_M6502);
413 	M6502Open(0);
414 	//M6502MapMemory(DrvVidRAM,				0x0000, 0x4fff, MAP_ROM); // handler!!
415 	M6502MapMemory(DrvSprRAM,				0x5000, 0x53ff, MAP_RAM);
416 	M6502MapMemory(DrvM6502ROM + 0x6000,	0x6000, 0xffff, MAP_RAM);
417 	M6502SetWriteHandler(cloud9_write);
418 	M6502SetReadHandler(cloud9_read);
419 	M6502Close();
420 
421 	BurnWatchdogInit(DrvDoReset, 180);
422 
423 	PokeyInit(1250000, 2, 1.25, 0);
424 	PokeyAllPotCallback(1, pokey_1_callback);
425 	PokeySetTotalCyclesCB(M6502TotalCycles);
426 
427 	GenericTilesInit();
428 
429 	DrvDoReset(1);
430 
431 #if 0
432 	// might come in handy to find values for other drivers that might uses similar sync prom?
433 	INT32 m_vblank_start = 0;
434 	INT32 m_vblank_end = 0;
435 	/* find the start of VBLANK in the SYNC PROM */
436 	for (m_vblank_start = 0; m_vblank_start < 256; m_vblank_start++)
437 		if ((DrvVidPROM[(m_vblank_start - 1) & 0xff] & 2) != 0 && (DrvVidPROM[m_vblank_start] & 2) == 0)
438 			break;
439 	if (m_vblank_start == 0)
440 		m_vblank_start = 256;
441 
442 	/* find the end of VBLANK in the SYNC PROM */
443 	for (m_vblank_end = 0; m_vblank_end < 256; m_vblank_end++)
444 		if ((DrvVidPROM[(m_vblank_end - 1) & 0xff] & 2) == 0 && (DrvVidPROM[m_vblank_end] & 2) != 0)
445 			break;
446 
447 	bprintf(0, _T("vblank begin: %d  vblank end: %d.\n"), m_vblank_start, m_vblank_end);
448 #endif
449 
450 	return 0;
451 }
452 
DrvExit()453 static INT32 DrvExit()
454 {
455 	GenericTilesExit();
456 	M6502Exit();
457 
458 	PokeyExit();
459 
460 	BurnFreeMemIndex();
461 
462 	is_firebeast = 0;
463 
464 	return 0;
465 }
466 
467 #define SCREEN_START_OFFSET 24
468 
draw_sprites()469 static void draw_sprites()
470 {
471 	for (INT32 offs = 0; offs < 0x20; offs++)
472 	{
473 		if ((DrvSprRAM[offs + 0x00] & 0xfe) == 0) continue;
474 		INT32 sx    = DrvSprRAM[offs + 0x60];
475 		INT32 sy    = 241 - DrvSprRAM[offs] - SCREEN_START_OFFSET;
476 		INT32 flipx = DrvSprRAM[offs + 0x40] & 0x80;
477 		INT32 flipy = DrvSprRAM[offs + 0x40] & 0x40;
478 		INT32 code  = DrvSprRAM[offs + 0x20];
479 
480 		Draw16x16MaskTile(pTransDraw, code, sx, sy, flipx, flipy, 0, 4, 0, 0x10, DrvGfxROM);
481 
482 		if (sx >= 240) // wrap
483 			Draw16x16MaskTile(pTransDraw, code, sx - 256, sy, flipx, flipy, 0, 4, 0, 0x10, DrvGfxROM);
484 	}
485 }
486 
487 static INT32 lastline;
488 
draw_bitmap(INT32 line)489 static void draw_bitmap(INT32 line)
490 {
491 	INT32 flip = video_latch[5] ? 0xff : 0x00;
492 
493 	UINT8 *src[2] = { DrvVidRAM + 0x4000, DrvVidRAM };
494 
495 	for (INT32 y = lastline + SCREEN_START_OFFSET; y < line + SCREEN_START_OFFSET; y++)
496 	{
497 		if ((y - SCREEN_START_OFFSET) >= nScreenHeight) break;
498 		UINT16 *dst = pTransDraw + (y - SCREEN_START_OFFSET) * nScreenWidth;
499 		INT32 effy = (y ^ flip) * 64;
500 
501 		for (INT32 x = 0; x < nScreenWidth; x++)
502 		{
503 			INT32 effx = x ^ flip;
504 
505 			dst[x] = ((src[(effx >> 1) & 1][effy + (effx / 4)] >> ((~effx & 1) * 4)) & 0x0f);
506 		}
507 	}
508 }
509 
DrvDrawBegin()510 static void DrvDrawBegin()
511 {
512 	lastline = 0;
513 
514 	if (DrvRecalc) {
515 		for (INT32 i = 0; i < 0x40; i++) {
516 			palette_write(i, DrvPalRAM[i]);
517 		}
518 		DrvRecalc = 0;
519 	}
520 
521 	if ((nBurnLayer & 1) == 0)
522 		BurnTransferClear();
523 }
524 
DrvDrawLine(INT32 line)525 static void DrvDrawLine(INT32 line)
526 {
527 	if ((nBurnLayer & 1) != 0)
528 		draw_bitmap(line);
529 
530 	lastline = line;
531 }
532 
DrvDrawEnd()533 static void DrvDrawEnd()
534 {
535 	DrvDrawLine(256);
536 
537 	if ((nSpriteEnable & 1) != 0)
538 		draw_sprites();
539 
540 	INT32 palette_bank = video_latch[7] ? 0x20 : 0x00;
541 
542 	BurnTransferCopy(DrvPalette + palette_bank);
543 }
544 
DrvReRedraw()545 static INT32 DrvReRedraw()
546 {
547 	DrvDrawBegin();
548 	DrvDrawLine(256);
549 	DrvDrawEnd();
550 
551 	return 0;
552 }
553 
DrvFrame()554 static INT32 DrvFrame()
555 {
556 	BurnWatchdogUpdate();
557 
558 	if (DrvReset) {
559 		DrvDoReset(1);
560 	}
561 
562 	{
563 		DrvInputs[0] = 0xff;
564 		DrvInputs[1] = 0xff;
565 
566 		for (INT32 i = 0; i < 8; i++) {
567 			DrvInputs[0] ^= (DrvJoy1[i] & 1) << i;
568 			DrvInputs[1] ^= (DrvJoy2[i] & 1) << i;
569 		}
570 
571 		DrvInputs[0] = (DrvInputs[0] & ~0x08) | (DrvDips[1] & 0x08);
572 
573 		{
574 			// UDLR fake trackball
575 			if (DrvJoy3[0]) TrackY+=3;
576 			if (DrvJoy3[1]) TrackY-=3;
577 			if (is_firebeast == 0) {
578 				if (DrvJoy3[2]) TrackX-=3;
579 				if (DrvJoy3[3]) TrackX+=3;
580 			} else {
581 				if (DrvJoy3[2]) TrackX+=3;
582 				if (DrvJoy3[3]) TrackX-=3;
583 			}
584 		}
585 	}
586 
587 	INT32 nInterleave = 262;
588 	INT32 nCyclesTotal[1] = { 1250000 / 60 };
589 	INT32 nCyclesDone[1] = { 0 };
590 
591 	M6502Open(0);
592 
593 	if (pBurnDraw)
594 		DrvDrawBegin();
595 
596 	for (INT32 i = 0; i < nInterleave; i++) {
597 		vblank = (~DrvVidPROM[i & 0xff] >> 1) & 1;
598 
599 		CPU_RUN(0, M6502);
600 
601 		if ((i%64) == 63) {
602 			M6502SetIRQLine(0, CPU_IRQSTATUS_ACK);
603 			irq_state = 1;
604 			DrvDrawLine(i);
605 		}
606 	}
607 
608 	M6502Close();
609 
610 	if (pBurnSoundOut) {
611 		pokey_update(pBurnSoundOut, nBurnSoundLen);
612 	}
613 
614 	if (pBurnDraw) {
615 		DrvDrawEnd();
616 	}
617 
618 	return 0;
619 }
620 
DrvScan(INT32 nAction,INT32 * pnMin)621 static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
622 {
623 	struct BurnArea ba;
624 
625 	if (pnMin) {
626 		*pnMin = 0x029702;
627 	}
628 
629 	if (nAction & ACB_VOLATILE) {
630 		memset(&ba, 0, sizeof(ba));
631 
632 		ba.Data	  = AllRam;
633 		ba.nLen	  = RamEnd - AllRam;
634 		ba.szName = "All Ram";
635 		BurnAcb(&ba);
636 
637 		M6502Scan(nAction);
638 		pokey_scan(nAction, pnMin);
639 
640 		SCAN_VAR(irq_state);
641 		SCAN_VAR(video_latch);
642 		SCAN_VAR(bitmode_addr);
643 		SCAN_VAR(TrackX);
644 		SCAN_VAR(TrackY);
645 	}
646 
647 	if (nAction & ACB_NVRAM) {
648 		ba.Data		= DrvNVRAM;
649 		ba.nLen		= 0x00100;
650 		ba.nAddress	= 0;
651 		ba.szName	= "NV RAM";
652 		BurnAcb(&ba);
653 	}
654 
655 	return 0;
656 }
657 
658 
659 // Cloud 9 (prototype)
660 
661 static struct BurnRomInfo cloud9RomDesc[] = {
662 	{ "c9_6000.bin",	0x2000, 0xb5d95d98, 1 | BRF_PRG | BRF_ESS }, //  0 M6502 Code
663 	{ "c9_8000.bin",	0x2000, 0x49af8f22, 1 | BRF_PRG | BRF_ESS }, //  1
664 	{ "c9_a000.bin",	0x2000, 0x7cf404a6, 1 | BRF_PRG | BRF_ESS }, //  2
665 	{ "c9_c000.bin",	0x2000, 0x26a4d7df, 1 | BRF_PRG | BRF_ESS }, //  3
666 	{ "c9_e000.bin",	0x2000, 0x6e663bce, 1 | BRF_PRG | BRF_ESS }, //  4
667 
668 	{ "c9_gfx0.bin",	0x1000, 0xd01a8019, 2 | BRF_GRA },           //  5 Sprites
669 	{ "c9_gfx1.bin",	0x1000, 0x514ac009, 2 | BRF_GRA },           //  6
670 	{ "c9_gfx2.bin",	0x1000, 0x930c1ade, 2 | BRF_GRA },           //  7
671 	{ "c9_gfx3.bin",	0x1000, 0x27e9b88d, 2 | BRF_GRA },           //  8
672 
673 	{ "63s141.e10",		0x0100, 0x8e98083f, 3 | BRF_GRA },           //  9 PROMs
674 	{ "63s141.m10",		0x0100, 0xb0b039c0, 3 | BRF_GRA },           // 10
675 	{ "82s129.p3",		0x0100, 0x615d784d, 3 | BRF_GRA },           // 11
676 	{ "63s141.m8",		0x0100, 0x6d7479ec, 3 | BRF_GRA },           // 12
677 };
678 
679 STD_ROM_PICK(cloud9)
680 STD_ROM_FN(cloud9)
681 
682 struct BurnDriver BurnDrvCloud9 = {
683 	"cloud9", NULL, NULL, NULL, "1983",
684 	"Cloud 9 (prototype)\0", NULL, "Atari", "Miscellaneous",
685 	NULL, NULL, NULL, NULL,
686 	BDF_GAME_WORKING | BDF_PROTOTYPE, 2, HARDWARE_MISC_PRE90S, GBF_VERSHOOT | GBF_ACTION, 0,
687 	NULL, cloud9RomInfo, cloud9RomName, NULL, NULL, NULL, NULL, Cloud9InputInfo, Cloud9DIPInfo,
688 	DrvInit, DrvExit, DrvFrame, DrvReRedraw, DrvScan, &DrvRecalc, 0x40,
689 	256, 232, 4, 3
690 };
691 
692 
693 // Firebeast (prototype)
694 
695 static struct BurnRomInfo firebeasRomDesc[] = {
696 	{ "6000.j2",		0x2000, 0xdbd04782, 1 | BRF_PRG | BRF_ESS }, //  0 M6502 Code
697 	{ "8000.kl2",		0x2000, 0x96231ca4, 1 | BRF_PRG | BRF_ESS }, //  1
698 	{ "a000.lm2",		0x2000, 0xf7e0bf25, 1 | BRF_PRG | BRF_ESS }, //  2
699 	{ "c000.n2",		0x2000, 0x43a91b74, 1 | BRF_PRG | BRF_ESS }, //  3
700 	{ "e000.p2",		0x1000, 0x8e5045ab, 1 | BRF_PRG | BRF_ESS }, //  4
701 
702 	{ "mo0000.r12",		0x2000, 0x5246c979, 2 | BRF_GRA },           //  5 Sprites
703 	{ "mo2000.p12",		0x2000, 0x1a3b6d57, 2 | BRF_GRA },           //  6
704 	{ "mo4000.n12",		0x2000, 0x69e18319, 2 | BRF_GRA },           //  7
705 	{ "mo6000.m12",		0x2000, 0xb722997f, 2 | BRF_GRA },           //  8
706 
707 	{ "63s141.e10",		0x0100, 0x8e98083f, 3 | BRF_GRA },           //  9 PROMs
708 	{ "63s141.m10",		0x0100, 0xb0b039c0, 3 | BRF_GRA },           // 10
709 	{ "82s129.p3",		0x0100, 0x615d784d, 3 | BRF_GRA },           // 11
710 	{ "63s141.m8",		0x0100, 0x6d7479ec, 3 | BRF_GRA },           // 12
711 };
712 
713 STD_ROM_PICK(firebeas)
714 STD_ROM_FN(firebeas)
715 
716 struct BurnDriver BurnDrvFirebeas = {
717 	"firebeas", NULL, NULL, NULL, "1983",
718 	"Firebeast (prototype)\0", NULL, "Atari", "Miscellaneous",
719 	NULL, NULL, NULL, NULL,
720 	BDF_GAME_WORKING | BDF_PROTOTYPE, 2, HARDWARE_MISC_PRE90S, GBF_SCRFIGHT, 0,
721 	NULL, firebeasRomInfo, firebeasRomName, NULL, NULL, NULL, NULL, FirebeasInputInfo, FirebeasDIPInfo,
722 	DrvInit, DrvExit, DrvFrame, DrvReRedraw, DrvScan, &DrvRecalc, 0x40,
723 	256, 232, 4, 3
724 };
725