1 // FB Alpha Flipper Jack driver module
2 // Based on MAME driver by Algelo Salese and Hap
3 
4 #include "tiles_generic.h"
5 #include "z80_intf.h"
6 #include "8255ppi.h"
7 #include "ay8910.h"
8 
9 static UINT8 *AllMem;
10 static UINT8 *MemEnd;
11 static UINT8 *AllRam;
12 static UINT8 *RamEnd;
13 static UINT8 *DrvZ80ROM0;
14 static UINT8 *DrvZ80ROM1;
15 static UINT8 *DrvGfxROM;
16 static UINT8 *DrvBlitROM;
17 static UINT8 *DrvZ80RAM0;
18 static UINT8 *DrvZ80RAM1;
19 static UINT8 *DrvColRAM;
20 static UINT8 *DrvVidRAM;
21 static UINT8 *DrvFbRAM;
22 
23 static UINT32 *DrvPalette;
24 static UINT8 DrvRecalc;
25 
26 static UINT8 bankdata;
27 static UINT8 layer_reg;
28 static UINT8 previous_coin;
29 static UINT8 soundlatch;
30 
31 static UINT8 DrvJoy1[8];
32 static UINT8 DrvJoy2[8];
33 static UINT8 DrvJoy3[8];
34 static UINT8 DrvJoy4[1];
35 static UINT8 DrvDips[1];
36 static UINT8 DrvInputs[4];
37 static UINT8 DrvReset;
38 
39 static struct BurnInputInfo FlipjackInputList[] = {
40 	{"P1 Coin",				BIT_DIGITAL,	DrvJoy4 + 0,	"p1 coin"	},
41 	{"P1 Start",			BIT_DIGITAL,	DrvJoy1 + 4,	"p1 start"	},
42 	{"P1 Left Flipper",		BIT_DIGITAL,	DrvJoy1 + 1,	"p1 fire 1"	},
43 	{"P1 Right Flipper",	BIT_DIGITAL,	DrvJoy1 + 3,	"p1 fire 2"	},
44 	{"P1 Shoot",			BIT_DIGITAL,	DrvJoy1 + 0,	"p1 fire 3"	},
45 	{"P1 Tilt",				BIT_DIGITAL,	DrvJoy1 + 2,	"p1 fire 4"	},
46 
47 	{"P2 Start",			BIT_DIGITAL,	DrvJoy2 + 4,	"p2 start"	},
48 	{"P2 Left Flipper",		BIT_DIGITAL,	DrvJoy2 + 1,	"p2 fire 1"	},
49 	{"P2 Right Flipper",	BIT_DIGITAL,	DrvJoy2 + 3,	"p2 fire 2"	},
50 	{"P2 Shoot",			BIT_DIGITAL,	DrvJoy2 + 0,	"p2 fire 3"	},
51 	{"P2 Tilt",				BIT_DIGITAL,	DrvJoy2 + 2,	"p2 fire 4"	},
52 
53 	{"Reset",				BIT_DIGITAL,	&DrvReset,		"reset"		},
54 	{"Dip A",				BIT_DIPSWITCH,	DrvDips + 0,	"dip"		},
55 };
56 
57 STDINPUTINFO(Flipjack)
58 
59 static struct BurnDIPInfo FlipjackDIPList[]=
60 {
61 	{0x0c, 0xff, 0xff, 0xf6, NULL					},
62 
63 	{0   , 0xfe, 0   ,    2, "Demo Sounds"			},
64 	{0x0c, 0x01, 0x01, 0x01, "Off"					},
65 	{0x0c, 0x01, 0x01, 0x00, "On"					},
66 
67 	{0   , 0xfe, 0   ,    2, "Coinage"				},
68 	{0x0c, 0x01, 0x02, 0x02, "1 Coin  1 Credits"	},
69 	{0x0c, 0x01, 0x02, 0x00, "1 Coin  2 Credits"	},
70 
71 	{0   , 0xfe, 0   ,    2, "Drop Target"			},
72 	{0x0c, 0x01, 0x04, 0x00, "Off"					},
73 	{0x0c, 0x01, 0x04, 0x04, "On"					},
74 
75 	{0   , 0xfe, 0   ,    2, "Cabinet"				},
76 	{0x0c, 0x01, 0x08, 0x00, "Upright"				},
77 	{0x0c, 0x01, 0x08, 0x08, "Cocktail"				},
78 
79 	{0   , 0xfe, 0   ,    5, "Bonus Life"			},
80 	{0x0c, 0x01, 0x70, 0x70, "150K & Every 70K"		},
81 	{0x0c, 0x01, 0x70, 0x60, "150K & Every 100K"	},
82 	{0x0c, 0x01, 0x70, 0x50, "200K & Every 70K"		},
83 	{0x0c, 0x01, 0x70, 0x40, "200K & Every 100K"	},
84 	{0x0c, 0x01, 0x70, 0x00, "None"					},
85 
86 	{0   , 0xfe, 0   ,    2, "Lives"				},
87 	{0x0c, 0x01, 0x80, 0x80, "3"					},
88 	{0x0c, 0x01, 0x80, 0x00, "5"					},
89 };
90 
STDDIPINFO(Flipjack)91 STDDIPINFO(Flipjack)
92 
93 static void bankswitch(INT32 data)
94 {
95 	bankdata = data;
96 
97 	ZetMapMemory(DrvZ80ROM0 + ((data & 4) ? 0x6000 : 0x4000), 0x2000, 0x3fff, MAP_ROM);
98 }
99 
flipjack_main_write(UINT16 address,UINT8 data)100 static void __fastcall flipjack_main_write(UINT16 address, UINT8 data)
101 {
102 	switch (address)
103 	{
104 		case 0x6800:
105 		case 0x6801:
106 		case 0x6802:
107 		case 0x6803:
108 			ppi8255_w(0, address & 3, data);
109 		return;
110 
111 		case 0x7000:
112 			soundlatch = data;
113 			ZetSetIRQLine(1, 0, CPU_IRQSTATUS_ACK);
114 		return;
115 
116 		case 0x7010:// hd6845 address
117 		case 0x7011:// hd6845 register
118 		return;
119 
120 		case 0x7800:
121 			layer_reg = data;
122 		return;
123 	}
124 }
125 
flipjack_main_read(UINT16 address)126 static UINT8 __fastcall flipjack_main_read(UINT16 address)
127 {
128 	switch (address)
129 	{
130 		case 0x6800:
131 		case 0x6801:
132 		case 0x6802:
133 		case 0x6803:
134 		    return ppi8255_r(0, address & 3);
135 
136 		case 0x7020:
137 			return DrvDips[0];
138 	}
139 
140 	return 0;
141 }
142 
flipjack_main_write_port(UINT16 port,UINT8 data)143 static void __fastcall flipjack_main_write_port(UINT16 port, UINT8 data)
144 {
145 	switch (port & 0xff)
146 	{
147 		case 0xff:
148 			bankswitch(data);
149 		return;
150 	}
151 }
152 
flipjack_sound_write(UINT16 address,UINT8 data)153 static void __fastcall flipjack_sound_write(UINT16 address, UINT8 data)
154 {
155 	switch (address)
156 	{
157 		case 0x4000:
158 			AY8910Write(1, 1, data);
159 		return;
160 
161 		case 0x6000:
162 			AY8910Write(1, 0, data);
163 		return;
164 
165 		case 0x8000:
166 			AY8910Write(0, 1, data);
167 		return;
168 
169 		case 0xa000:
170 			AY8910Write(0, 0, data);
171 		return;
172 	}
173 }
174 
flipjack_sound_read(UINT16 address)175 static UINT8 __fastcall flipjack_sound_read(UINT16 address)
176 {
177 	switch (address)
178 	{
179 		case 0x4000:
180 			return AY8910Read(1);
181 
182 		case 0x8000:
183 			return AY8910Read(0);
184 	}
185 
186 	return 0;
187 }
188 
flipjack_sound_write_port(UINT16 port,UINT8)189 static void __fastcall flipjack_sound_write_port(UINT16 port, UINT8 /*data*/)
190 {
191 	switch (port & 0xff)
192 	{
193 		case 0x00:
194 			ZetSetIRQLine(0x20, CPU_IRQSTATUS_NONE);
195 		return;
196 	}
197 }
198 
tilemap_callback(bg)199 static tilemap_callback( bg )
200 {
201 	TILE_SET_INFO(0, DrvVidRAM[offs] + (bankdata * 256), DrvColRAM[offs], 0);
202 }
203 
ppiportAread()204 static UINT8 ppiportAread()
205 {
206 	return DrvInputs[0];
207 }
208 
ppiportBread()209 static UINT8 ppiportBread()
210 {
211 	return DrvInputs[1];
212 }
213 
ppiportCread()214 static UINT8 ppiportCread()
215 {
216 	return DrvInputs[2];
217 }
218 
ay8910_0_read_A(UINT32)219 static UINT8 ay8910_0_read_A(UINT32)
220 {
221 	ZetSetIRQLine(0, CPU_IRQSTATUS_NONE);
222 	return soundlatch;
223 }
224 
DrvDoReset()225 static INT32 DrvDoReset()
226 {
227 	memset (AllRam, 0, RamEnd - AllRam);
228 
229 	ZetOpen(0);
230 	bankswitch(0);
231 	ZetReset();
232 	ZetClose();
233 
234 	ZetReset(1);
235 
236 	AY8910Reset(0);
237 
238 	previous_coin = 0;
239 	soundlatch = 0;
240 	layer_reg = 0;
241 
242 	return 0;
243 }
244 
MemIndex()245 static INT32 MemIndex()
246 {
247 	UINT8 *Next; Next = AllMem;
248 
249 	DrvZ80ROM0		= Next; Next += 0x008000;
250 	DrvZ80ROM1		= Next; Next += 0x002000;
251 
252 	DrvGfxROM		= Next; Next += 0x010000;
253 	DrvBlitROM		= Next; Next += 0x006000;
254 
255 	DrvPalette		= (UINT32*)Next; Next += BurnDrvGetPaletteEntries() * sizeof(UINT32);
256 
257 	AllRam			= Next;
258 
259 	DrvZ80RAM0		= Next; Next += 0x002800;
260 	DrvZ80RAM1		= Next; Next += 0x000800;
261 
262 	DrvColRAM		= Next; Next += 0x002000;
263 	DrvVidRAM		= Next; Next += 0x002000;
264 	DrvFbRAM		= Next; Next += 0x002000;
265 
266 	RamEnd			= Next;
267 
268 	MemEnd			= Next;
269 
270 	return 0;
271 }
272 
DrvGfxDecode()273 static INT32 DrvGfxDecode()
274 {
275 	INT32 Plane[1] = { 0 };
276 	INT32 XOffs[8] = { STEP8(0,1) };
277 	INT32 YOffs[8] = { STEP8(0,8) };
278 
279 	UINT8 *tmp = (UINT8*)BurnMalloc(0x2000);
280 	if (tmp == NULL) {
281 		return 1;
282 	}
283 
284 	memcpy (tmp, DrvGfxROM, 0x2000);
285 
286 	GfxDecode(0x0400, 1, 8, 8, Plane, XOffs, YOffs, 0x040, tmp, DrvGfxROM);
287 
288 	BurnFree(tmp);
289 
290 	return 0;
291 }
292 
DrvInit()293 static INT32 DrvInit()
294 {
295 	AllMem = NULL;
296 	MemIndex();
297 	INT32 nLen = MemEnd - (UINT8 *)0;
298 	if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1;
299 	memset(AllMem, 0, nLen);
300 	MemIndex();
301 
302 	{
303 		if (BurnLoadRom(DrvZ80ROM0 + 0x0000,  0, 1)) return 1;
304 		if (BurnLoadRom(DrvZ80ROM0 + 0x2000,  1, 1)) return 1;
305 		if (BurnLoadRom(DrvZ80ROM0 + 0x4000,  2, 1)) return 1;
306 		if (BurnLoadRom(DrvZ80ROM0 + 0x6000,  3, 1)) return 1;
307 
308 		if (BurnLoadRom(DrvZ80ROM1 + 0x0000,  4, 1)) return 1;
309 
310 		if (BurnLoadRom(DrvGfxROM  + 0x0000,  5, 1)) return 1;
311 
312 		if (BurnLoadRom(DrvBlitROM + 0x0000,  6, 1)) return 1;
313 		if (BurnLoadRom(DrvBlitROM + 0x2000,  7, 1)) return 1;
314 		if (BurnLoadRom(DrvBlitROM + 0x4000,  8, 1)) return 1;
315 
316 		DrvGfxDecode();
317 	}
318 
319 	ZetInit(0);
320 	ZetOpen(0);
321 	ZetMapMemory(DrvZ80ROM0,			0x0000, 0x1fff, MAP_ROM);
322 	ZetMapMemory(DrvZ80RAM0,			0x4000, 0x67ff, MAP_RAM);
323 	ZetMapMemory(DrvZ80ROM0 + 0x2000,	0x8000, 0x9fff, MAP_RAM);
324 	ZetMapMemory(DrvColRAM,				0xa000, 0xbfff, MAP_RAM);
325 	ZetMapMemory(DrvVidRAM,				0xc000, 0xdfff, MAP_RAM);
326 	ZetMapMemory(DrvFbRAM,				0xe000, 0xffff, MAP_RAM);
327 	ZetSetWriteHandler(flipjack_main_write);
328 	ZetSetReadHandler(flipjack_main_read);
329 	ZetSetOutHandler(flipjack_main_write_port);
330 	ZetClose();
331 
332 	ZetInit(1);
333 	ZetOpen(1);
334 	ZetMapMemory(DrvZ80ROM1,			0x0000, 0x1fff, MAP_ROM);
335 	ZetMapMemory(DrvZ80RAM1,			0x2000, 0x27ff, MAP_RAM);
336 	ZetSetWriteHandler(flipjack_sound_write);
337 	ZetSetReadHandler(flipjack_sound_read);
338 	ZetSetOutHandler(flipjack_sound_write_port);
339 	ZetClose();
340 
341 	ppi8255_init(1);
342 	ppi8255_set_read_ports(0, ppiportAread, ppiportBread, ppiportCread);
343 
344 	AY8910Init(0, 2000000, 0);
345 	AY8910Init(1, 2000000, 1);
346 	AY8910SetPorts(0, &ay8910_0_read_A, NULL, NULL, NULL);
347 	AY8910SetAllRoutes(0, 0.14, BURN_SND_ROUTE_BOTH);
348 	AY8910SetAllRoutes(1, 0.14, BURN_SND_ROUTE_BOTH);
349 
350 	GenericTilesInit();
351 	GenericTilemapInit(0, TILEMAP_SCAN_ROWS, bg_map_callback, 8, 8, 256, 32);
352 	GenericTilemapSetGfx(0, DrvGfxROM, 1, 8, 8, 0x10000, 0, 7);
353 	GenericTilemapSetTransparent(0, 0);
354 
355 	DrvDoReset();
356 
357 	return 0;
358 }
359 
DrvExit()360 static INT32 DrvExit()
361 {
362 	GenericTilesExit();
363 
364 	ZetExit();
365 
366 	ppi8255_exit();
367 
368 	AY8910Exit(0);
369 	AY8910Exit(1);
370 
371 	BurnFree(AllMem);
372 
373 	return 0;
374 }
375 
DrvPaletteInit()376 static void DrvPaletteInit()
377 {
378 	for (INT32 i = 0; i < 16; i++)
379 	{
380 		UINT8 r = (i & 4) ? 0xff : 0;
381 		UINT8 g = (i & 8) ? 0xff : 0;
382 		UINT8 b = (i & 2) ? 0xff : 0;
383 
384 		DrvPalette[i] = BurnHighCol(r, g, b, 0);
385 	}
386 }
387 
draw_playfield()388 static void draw_playfield()
389 {
390 	for (INT32 offs = 0; offs < 0x1800; offs++)
391 	{
392 		INT32 sx = (offs & 0x1f) * 8;
393 		INT32 sy = (offs / 0x20);
394 
395 		UINT8 r = DrvBlitROM[offs];
396 		UINT8 g = DrvBlitROM[offs + 0x2000];
397 		UINT8 b = DrvBlitROM[offs + 0x4000];
398 
399 		UINT16 *dest = pTransDraw + (sy * nScreenWidth) + sx;
400 
401 		for (INT32 x = 0; x < 8; x++)
402 		{
403 			dest[7 - x] = (((r >> x) & 1) << 1) | (((g >> x) & 1) << 2) | (((b >> x) & 1) << 3);
404 		}
405 	}
406 }
407 
draw_framebuffer()408 static void draw_framebuffer()
409 {
410 	for (INT32 offs = 0; offs < 0x1800; offs++)
411 	{
412 		INT32 sx = (offs & 0x1f) * 8;
413 		INT32 sy = (offs / 0x20);
414 
415 		UINT8 data = DrvFbRAM[offs];
416 
417 		UINT16 *dest = pTransDraw + (sy * nScreenWidth) + sx;
418 
419 		for (INT32 x = 0; x < 8; x++)
420 		{
421 			if (data & (0x80 >> x))
422 			{
423 				dest[x] = 0x0e;
424 			}
425 		}
426 	}
427 }
428 
DrvDraw()429 static INT32 DrvDraw()
430 {
431 	if (DrvRecalc) {
432 		DrvPaletteInit();
433 		DrvRecalc = 0;
434 	}
435 
436 	if ((layer_reg & 0x02) && (nBurnLayer & 1))
437 	{
438 		draw_playfield();
439 	}
440 	else
441 	{
442 		BurnTransferClear();
443 	}
444 
445 	if (nBurnLayer & 2) GenericTilemapDraw(0, pTransDraw, 0);
446 
447 	if ((layer_reg & 0x04) && (nBurnLayer & 4))
448 	{
449 		draw_framebuffer();
450 	}
451 
452 	BurnTransferCopy(DrvPalette);
453 
454 	return 0;
455 }
456 
DrvFrame()457 static INT32 DrvFrame()
458 {
459 	if (DrvReset) {
460 		DrvDoReset();
461 	}
462 
463 	{
464 		memset (DrvInputs, 0xff, 3);
465 
466 		for (INT32 i = 0; i < 8; i++) {
467 			DrvInputs[0] ^= (DrvJoy1[i] & 1) << i;
468 			DrvInputs[1] ^= (DrvJoy2[i] & 1) << i;
469 			DrvInputs[2] ^= (DrvJoy3[i] & 1) << i;
470 		}
471 
472 		if (previous_coin && (DrvJoy4[0] & 1) == 0) {
473 			ZetOpen(0);
474 			ZetNmi();
475 			ZetClose();
476 		}
477 		previous_coin = DrvJoy4[0] & 1;
478 	}
479 
480 	INT32 nInterleave = 10;
481 	INT32 nCyclesTotal[2] = { 4000000 / 60, 4000000 / 60 };
482 	INT32 nCyclesDone[2] = { 0, 0 };
483 
484 	for (INT32 i = 0; i < nInterleave; i++)
485 	{
486 		ZetOpen(0);
487 		nCyclesDone[0] += ZetRun(nCyclesTotal[0] / nInterleave);
488 		if (i == (nInterleave - 1)) ZetSetIRQLine(0, CPU_IRQSTATUS_HOLD);
489 		ZetClose();
490 
491 		ZetOpen(1);
492 		nCyclesDone[1] += ZetRun(nCyclesTotal[1] / nInterleave);
493 		if (i == (nInterleave - 1)) ZetSetIRQLine(0x20, CPU_IRQSTATUS_ACK);
494 		ZetClose();
495 	}
496 
497 	if (pBurnSoundOut) {
498 		AY8910Render(pBurnSoundOut, nBurnSoundLen);
499 	}
500 
501 	if (pBurnDraw) {
502 		DrvDraw();
503 	}
504 
505 	return 0;
506 }
507 
DrvScan(INT32 nAction,INT32 * pnMin)508 static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
509 {
510 	struct BurnArea ba;
511 
512 	if (pnMin) {
513 		*pnMin = 0x029708;
514 	}
515 
516 	if (nAction & ACB_VOLATILE) {
517 		memset(&ba, 0, sizeof(ba));
518 
519 		ba.Data	  = AllRam;
520 		ba.nLen	  = RamEnd - AllRam;
521 		ba.szName = "All Ram";
522 		BurnAcb(&ba);
523 
524 		ZetScan(nAction);
525 		AY8910Scan(nAction, pnMin);
526 
527 		SCAN_VAR(bankdata);
528 		SCAN_VAR(layer_reg);
529 		SCAN_VAR(previous_coin);
530 		SCAN_VAR(soundlatch);
531 	}
532 
533 	if (nAction & ACB_WRITE)
534 	{
535 		ZetOpen(0);
536 		bankswitch(bankdata);
537 		ZetClose();
538 	}
539 
540 	return 0;
541 }
542 
543 
544 // Flipper Jack
545 
546 static struct BurnRomInfo flipjackRomDesc[] = {
547 	{ "3.d5",			0x2000, 0x123bd992, 1 | BRF_PRG | BRF_ESS }, //  0 Z80 #0 Code
548 	{ "4.f5",			0x2000, 0xd27e0184, 1 | BRF_PRG | BRF_ESS }, //  1
549 	{ "1.l5",			0x2000, 0x4632263b, 1 | BRF_PRG | BRF_ESS }, //  2
550 	{ "2.m5",			0x2000, 0xe2bdce13, 1 | BRF_PRG | BRF_ESS }, //  3
551 
552 	{ "s.s5",			0x2000, 0x34515a7b, 2 | BRF_PRG | BRF_ESS }, //  4 Z80 #1 Code
553 
554 	{ "cg.l6",			0x2000, 0x8d87f6b9, 3 | BRF_GRA },           //  5 Tiles
555 
556 	{ "b.h6",			0x2000, 0xbbc8fdcc, 4 | BRF_GRA },           //  6 Blit data
557 	{ "r.f6",			0x2000, 0x8c02fe71, 4 | BRF_GRA },           //  7
558 	{ "g.d6",			0x2000, 0x8624d07f, 4 | BRF_GRA },           //  8
559 
560 	{ "m3-7611-5.f8",	0x0100, 0xf0248102, 5 | BRF_GRA },           //  9 Color data
561 };
562 
563 STD_ROM_PICK(flipjack)
564 STD_ROM_FN(flipjack)
565 
566 struct BurnDriver BurnDrvFlipjack = {
567 	"flipjack", NULL, NULL, NULL, "1983",
568 	"Flipper Jack\0", NULL, "Jackson Co., Ltd.", "Miscellaneous",
569 	NULL, NULL, NULL, NULL,
570 	BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_PINBALL, 0,
571 	NULL, flipjackRomInfo, flipjackRomName, NULL, NULL, NULL, NULL, FlipjackInputInfo, FlipjackDIPInfo,
572 	DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 16,
573 	192, 256, 3, 4
574 };
575