1 #include "toaplan.h"
2 // Enma Daio
3 
4 static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0};
5 static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0};
6 static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0};
7 static UINT8 DrvDips[1] = { 0 };
8 static UINT8 DrvInput[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
9 
10 static UINT8 *Mem = NULL, *MemEnd = NULL;
11 static UINT8 *RamStart, *RamEnd;
12 static UINT8 *Rom01;
13 static UINT8 *Ram01, *RamPal;
14 
15 static const INT32 nColCount = 0x0800;
16 
17 static UINT8 DrvReset = 0;
18 
19 static INT32 bankaddress = 0;
20 
21 static UINT8 nIRQPending;
22 
23 static struct BurnInputInfo EnmadaioInputList[] = {
24 	{"P1 Coin",			BIT_DIGITAL,	DrvButton + 3,	"p1 coin"	},
25 	{"P1 Start",		BIT_DIGITAL,	DrvButton + 5,	"p1 start"	},
26 	{"P1 Button 1",		BIT_DIGITAL,	DrvJoy2 + 4,	"p1 fire 1"	},
27 	{"P1 Button 2",		BIT_DIGITAL,	DrvJoy2 + 5,	"p1 fire 2"	},
28 
29 	{"Reset",			BIT_DIGITAL,	&DrvReset,		"reset"		},
30 	{"Service",			BIT_DIGITAL,	DrvButton + 0,	"service"	},
31 	{"Tilt",			BIT_DIGITAL,	DrvButton + 1,	"tilt"		},
32 	{"Fake",  			BIT_DIPSWITCH,	DrvDips + 0,	"dip"		},
33 };
34 
35 STDINPUTINFO(Enmadaio)
36 
37 static struct BurnDIPInfo EnmadaioDIPList[] = {
38 	// Defaults
39 	{0x07,	0xFF,  0xFF,	0x00,	  NULL},
40 };
41 
STDDIPINFO(Enmadaio)42 STDDIPINFO(Enmadaio)
43 
44 static UINT8 __fastcall enmadaioReadByte(UINT32 sekAddress)
45 {
46 	switch (sekAddress) {
47 
48 		case 0x20000d:
49 			return ToaVBlankRegister();
50 
51 		case 0x700001:
52 			return ToaScanlineRegister();
53 
54 		case 0x700004:
55 		case 0x700005:								// dswa
56 			return 0; //DrvInput[0];
57 
58 		case 0x70000c:
59 		case 0x70000d:								// MISC2
60 			return 0; //DrvInput[1];
61 
62 		case 0x700010:
63 		case 0x700011:								// MISC3
64 			return DrvInput[1];
65 
66 		case 0x700014:
67 		case 0x700015:								// MISC4
68 			return 0; //DrvInput[3];
69 
70 		case 0x700018:
71 		case 0x700019:								// SYS
72 			return DrvInput[2];
73 
74 		case 0x70001c:// return 0x01;
75 		case 0x70001d:// return 0x01; 							// UNK
76 			return 0; //DrvInput[5];
77 
78 		case 0x400001:
79 			return BurnYM2151Read();
80 
81 		case 0x400003:
82 			return BurnYM2151Read();
83 
84 		case 0x500001:
85 			return MSM6295Read(0);
86 
87 		default: {
88 			bprintf(0, _T("Attempt to read byte value of location %x\n"), sekAddress);
89 		}
90 	}
91 	return 0;
92 }
93 
enmadaioReadWord(UINT32 sekAddress)94 static UINT16 __fastcall enmadaioReadWord(UINT32 sekAddress)
95 {
96 	switch (sekAddress) {
97 
98 		case 0x200004:
99 			return ToaGP9001ReadRAM_Hi(0);
100 
101 		case 0x200006:
102 			return ToaGP9001ReadRAM_Lo(0);
103 
104 		case 0x700000:
105 			return ToaScanlineRegister();
106 
107 		case 0x700004:
108 			return 0; //DrvInput[0];
109 
110 		case 0x70000c:
111 			return 0; //DrvInput[1];
112 
113 		case 0x700010:
114 			return DrvInput[1];
115 
116 		case 0x700014:
117 			return 0; //DrvInput[3];
118 
119 		case 0x700018:
120 			return DrvInput[2];
121 
122 		case 0x70001c: return 0x0100;  // 0x0100 = unfreeze! -dink  // UNK
123 
124 		case 0x400000:
125 			return BurnYM2151Read();
126 
127 		case 0x500000:
128 			return MSM6295Read(0);
129 
130 		default: {
131 			bprintf(0, _T("Attempt to read word value of location %x\n"), sekAddress);
132 		}
133 	}
134 	return 0;
135 }
136 
oki_bankswitch(INT32 bank)137 static void oki_bankswitch(INT32 bank)
138 {
139 	if (bank >= 0x60) return;
140 
141 	bankaddress = bank;
142 
143 	MSM6295SetBank(0, MSM6295ROM + bankaddress * 0x20000, 0, 0x3ffff);
144 }
145 
enmadaioWriteByte(UINT32 sekAddress,UINT8 byteValue)146 static void __fastcall enmadaioWriteByte(UINT32 sekAddress, UINT8 byteValue)
147 {
148 	switch (sekAddress) {
149 		case 0x400001:
150 			BurnYM2151SelectRegister(byteValue);
151 			break;
152 		case 0x400003:
153 			BurnYM2151WriteRegister(byteValue);
154 			break;
155 
156 		case 0x500001:
157 			MSM6295Write(0, byteValue);
158 			break;
159 
160 		case 0x700021:
161 			oki_bankswitch(byteValue);
162 			break;
163 
164 		default: {
165 			bprintf(0, _T("Attempt to write byte value %x to location %x\n"), byteValue, sekAddress);
166 		}
167 	}
168 }
169 
enmadaioWriteWord(UINT32 sekAddress,UINT16 wordValue)170 static void __fastcall enmadaioWriteWord(UINT32 sekAddress, UINT16 wordValue)
171 {
172 	switch (sekAddress) {
173 		case 0x200000:								// Set GP9001 VRAM address-pointer
174 			ToaGP9001SetRAMPointer(wordValue);
175 			break;
176 
177 		case 0x200004:
178 		case 0x200006:
179 			ToaGP9001WriteRAM(wordValue, 0);
180 			break;
181 
182 		case 0x200008:
183 			ToaGP9001SelectRegister(wordValue);
184 			break;
185 
186 		case 0x20000C:
187 			ToaGP9001WriteRegister(wordValue);
188 			break;
189 
190 		case 0x400000:
191 			BurnYM2151SelectRegister(wordValue);
192 			break;
193 
194 		case 0x400002:
195 			BurnYM2151WriteRegister(wordValue);
196 			break;
197 
198 		case 0x500000:
199 			MSM6295Write(0, wordValue & 0xFF);
200 			break;
201 
202 		case 0x700020:
203 			oki_bankswitch(wordValue);
204 			break;
205 
206 		case 0x700028:
207 		case 0x70003c:
208 			return; // NOP
209 
210 		default: {
211 			bprintf(0, _T("Attempt to write word value %x to location %x\n"), wordValue, sekAddress);
212 		}
213 	}
214 }
215 
DrvExit()216 static INT32 DrvExit()
217 {
218 	MSM6295Exit(0);
219 	BurnYM2151Exit();
220 
221 	ToaPalExit();
222 
223 	ToaExtraTextExit();
224 	ToaExitGP9001();
225 	SekExit();				// Deallocate 68000s
226 
227 	BurnFree(Mem);
228 
229 	return 0;
230 }
231 
DrvDoReset()232 static INT32 DrvDoReset()
233 {
234 	SekOpen(0);
235 	nIRQPending = 0;
236 	SekSetIRQLine(0, CPU_IRQSTATUS_NONE);
237 	SekReset();
238 	SekClose();
239 
240 	MSM6295Reset(0);
241 	oki_bankswitch(0);
242 	BurnYM2151Reset();
243 
244 	HiscoreReset();
245 
246 	return 0;
247 }
248 
DrvDraw()249 static INT32 DrvDraw()
250 {
251 	ToaClearScreen(0);
252 
253 	ToaGetBitmap();
254 	ToaRenderGP9001();						// Render GP9001 graphics
255 
256 	ToaPalUpdate();							// Update the palette
257 
258 	return 0;
259 }
260 
DrvFrame()261 static INT32 DrvFrame()
262 {
263 	INT32 nInterleave = 8;
264 
265 	if (DrvReset) {														// Reset machine
266 		DrvDoReset();
267 	}
268 
269 	// Compile digital inputs
270 	DrvInput[0] = 0x00;													// Buttons
271 	DrvInput[1] = 0x00;													// Player 1
272 	DrvInput[2] = 0x00;													// Player 2
273 	for (INT32 i = 0; i < 8; i++) {
274 		DrvInput[0] |= (DrvJoy1[i] & 1) << i;
275 		DrvInput[1] |= (DrvJoy2[i] & 1) << i;
276 		DrvInput[2] |= (DrvButton[i] & 1) << i;
277 	}
278 	ToaClearOpposites(&DrvInput[0]);
279 	ToaClearOpposites(&DrvInput[1]);
280 
281 	SekNewFrame();
282 
283 	nCyclesTotal[0] = (INT32)((INT64)10000000 * nBurnCPUSpeedAdjust / (0x0100 * 60));
284 	nCyclesDone[0] = 0;
285 
286 	SekOpen(0);
287 
288 	SekSetCyclesScanline(nCyclesTotal[0] / 262);
289 	nToaCyclesDisplayStart = nCyclesTotal[0] - ((nCyclesTotal[0] * (TOA_VBLANK_LINES + 240)) / 262);
290 	nToaCyclesVBlankStart = nCyclesTotal[0] - ((nCyclesTotal[0] * TOA_VBLANK_LINES) / 262);
291 	bool bVBlank = false;
292 
293 	INT32 nSoundBufferPos = 0;
294 
295 	for (INT32 i = 0; i < nInterleave; i++) {
296     	INT32 nCurrentCPU;
297 		INT32 nNext;
298 
299 		// Run 68000
300 
301 		nCurrentCPU = 0;
302 		nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave;
303 
304 		// Trigger VBlank interrupt
305 		if (!bVBlank && nNext > nToaCyclesVBlankStart) {
306 			if (nCyclesDone[nCurrentCPU] < nToaCyclesVBlankStart) {
307 				nCyclesSegment = nToaCyclesVBlankStart - nCyclesDone[nCurrentCPU];
308 				nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
309 			}
310 
311 			nIRQPending  = 1;
312 			SekSetIRQLine(4, CPU_IRQSTATUS_AUTO);
313 
314 			ToaBufferGP9001Sprites();
315 
316 			bVBlank = true;
317 		}
318 
319 		nCyclesSegment = nNext - nCyclesDone[nCurrentCPU];
320 		nIRQPending = 0;
321 		nCyclesDone[nCurrentCPU] += SekRun(nCyclesSegment);
322 
323 		if ((i & 1) == 0) {
324 			// Render sound segment
325 			if (pBurnSoundOut) {
326 				INT32 nSegmentLength = (nBurnSoundLen * i / nInterleave) - nSoundBufferPos;
327 				INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
328 				BurnYM2151Render(pSoundBuf, nSegmentLength);
329 				MSM6295Render(0, pSoundBuf, nSegmentLength);
330 				nSoundBufferPos += nSegmentLength;
331 			}
332 		}
333 	}
334 
335 	{
336 		// Make sure the buffer is entirely filled.
337 		if (pBurnSoundOut) {
338 			INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos;
339 			INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
340 			if (nSegmentLength) {
341 				BurnYM2151Render(pSoundBuf, nSegmentLength);
342 				MSM6295Render(0, pSoundBuf, nSegmentLength);
343 			}
344 		}
345 	}
346 
347 	SekClose();
348 
349 	if (pBurnDraw != NULL) {
350 		DrvDraw();												// Draw screen if needed
351 	}
352 
353 	return 0;
354 }
355 
356 // This routine is called first to determine how much memory is needed (MemEnd-(UINT8 *)0),
357 // and then afterwards to set up all the pointers
MemIndex()358 static INT32 MemIndex()
359 {
360 	UINT8 *Next; Next = Mem;
361 
362 	Rom01		= Next; Next += 0x080000;		//
363 	GP9001ROM[0]	= Next; Next += nGP9001ROMSize[0];	// GP9001 tile data
364 	MSM6295ROM	= Next; Next += 0x1800000;
365 
366 	RamStart	= Next;
367 	Ram01		= Next; Next += 0x010000;		// CPU #0 work RAM
368 	RamPal		= Next; Next += 0x001000;		// palette
369 	GP9001RAM[0]	= Next; Next += 0x004000;
370 	GP9001Reg[0]	= (UINT16*)Next; Next += 0x01000 * sizeof(UINT16);
371 	RamEnd		= Next;
372 
373 	ToaPalette	= (UINT32 *)Next; Next += nColCount * sizeof(UINT32);
374 
375 	MemEnd		= Next;
376 
377 	return 0;
378 }
379 
LoadRoms()380 static INT32 LoadRoms()
381 {
382 	// Load 68000 ROM
383 	BurnLoadRom(Rom01, 0, 1);
384 	//BurnByteswap(Rom01, 0x80000);
385 
386 	// Load GP9001 tile data
387 	ToaLoadGP9001Tiles(GP9001ROM[0], 1, 2, nGP9001ROMSize[0]);
388 
389 	// Load MSM6295 ADPCM data
390 	BurnLoadRom(MSM6295ROM + 0x0000000,  3, 1);
391 	BurnLoadRom(MSM6295ROM + 0x0200000,  4, 1);
392 	BurnLoadRom(MSM6295ROM + 0x0400000,  5, 1);
393 	BurnLoadRom(MSM6295ROM + 0x0600000,  6, 1);
394 	BurnLoadRom(MSM6295ROM + 0x0800000,  7, 1);
395 	BurnLoadRom(MSM6295ROM + 0x0a00000,  8, 1);
396 	BurnLoadRom(MSM6295ROM + 0x0c00000,  9, 1);
397 	BurnLoadRom(MSM6295ROM + 0x0e00000, 10, 1);
398 	BurnLoadRom(MSM6295ROM + 0x1000000, 11, 1);
399 	BurnLoadRom(MSM6295ROM + 0x1200000, 12, 1);
400 	BurnLoadRom(MSM6295ROM + 0x1400000, 13, 1);
401 	BurnLoadRom(MSM6295ROM + 0x1600000, 14, 1);
402 
403 	return 0;
404 }
405 
406 // Scan ram
DrvScan(INT32 nAction,INT32 * pnMin)407 static INT32 DrvScan(INT32 nAction, INT32* pnMin)
408 {
409 	if (pnMin) {						// Return minimum compatible version
410 		*pnMin = 0x029497;
411 	}
412 
413 	if (nAction & ACB_VOLATILE) {		// Scan volatile data
414 		struct BurnArea ba;
415 
416 		memset(&ba, 0, sizeof(ba));
417 		ba.Data		= RamStart;
418 		ba.nLen		= RamEnd - RamStart;
419 		ba.szName	= "RAM";
420 		BurnAcb(&ba);
421 
422 		SekScan(nAction);				// scan 68000 states
423 
424 		MSM6295Scan(nAction, pnMin);
425 		BurnYM2151Scan(nAction, pnMin);
426 
427 		ToaScanGP9001(nAction, pnMin);
428 
429 		SCAN_VAR(DrvInput);
430 		SCAN_VAR(nIRQPending);
431 		SCAN_VAR(bankaddress);
432 	}
433 
434 	if (nAction & ACB_WRITE) {
435 		oki_bankswitch(bankaddress);
436 	}
437 
438 	return 0;
439 }
440 
DrvInit()441 static INT32 DrvInit()
442 {
443 	INT32 nLen;
444 
445 #ifdef DRIVER_ROTATION
446 	bToaRotateScreen = false;
447 #endif
448 
449 	nGP9001ROMSize[0] = 0x200000;
450 
451 	// Find out how much memory is needed
452 	Mem = NULL;
453 	MemIndex();
454 	nLen = MemEnd - (UINT8 *)0;
455 	if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) {
456 		return 1;
457 	}
458 	memset(Mem, 0, nLen);										// blank all memory
459 	MemIndex();													// Index the allocated memory
460 
461 	// Load the roms into memory
462 	if (LoadRoms()) {
463 		return 1;
464 	}
465 
466 	{
467 		SekInit(0, 0x68000);										// Allocate 68000
468 		SekOpen(0);
469 
470 		// Map 68000 memory:
471 		SekMapMemory(Rom01,		0x000000, 0x07FFFF, MAP_ROM);	// CPU 0 ROM
472 		SekMapMemory(Ram01,		0x100000, 0x10FFFF, MAP_RAM);
473 		SekMapMemory(RamPal,	0x300000, 0x300FFF, MAP_RAM);	// Palette RAM
474 		SekSetReadWordHandler(0, enmadaioReadWord);
475 		SekSetReadByteHandler(0, enmadaioReadByte);
476 		SekSetWriteWordHandler(0, enmadaioWriteWord);
477 		SekSetWriteByteHandler(0, enmadaioWriteByte);
478 
479 		SekClose();
480 	}
481 
482 	nLayer0XOffset = -0x01D6;
483 	nLayer1XOffset = -0x01D8;
484 	nLayer2XOffset = -0x01DA;
485 
486 	nSpriteYOffset = 0x0001;
487 	ToaInitGP9001();
488 
489 	//ToaExtraTextInit();
490 
491 	nToaPalLen = nColCount;
492 	ToaPalSrc = RamPal;
493 	ToaPalInit();
494 
495 	BurnYM2151Init(27000000 / 8);
496 	BurnYM2151SetRoute(BURN_SND_YM2151_YM2151_ROUTE_1, 1.00, BURN_SND_ROUTE_LEFT);
497 	BurnYM2151SetRoute(BURN_SND_YM2151_YM2151_ROUTE_2, 1.00, BURN_SND_ROUTE_RIGHT);
498 
499 	MSM6295Init(0, 4000000 / 132, 1);
500 	MSM6295SetRoute(0, 1.00, BURN_SND_ROUTE_BOTH);
501 
502 	DrvDoReset(); // Reset machine
503 
504 	return 0;
505 }
506 
507 
508 // Enma Daio (Japan)
509 
510 static struct BurnRomInfo enmadaioRomDesc[] = {
511 	{ "03n_u53.c8",		0x080000, 0x1a6ca2ee, BRF_PRG | BRF_ESS }, //  0 CPU #0 code
512 
513 	{ "rom4_u30.c19",	0x100000, 0x7a012d8b, BRF_GRA },           //  1 GP9001 Tile data
514 	{ "rom5_u31.c18",	0x100000, 0x60b127ab, BRF_GRA },           //  2
515 
516 	{ "rom6_u65.a1",	0x200000, 0xf33c6c0b, BRF_SND },           //  3 MSM6295 ADPCM data
517 	{ "rom7_u66.a3",	0x200000, 0x1306f8b3, BRF_SND },           //  4
518 	{ "rom8_u61.a4",	0x200000, 0x4f211c00, BRF_SND },           //  5
519 	{ "rom9_u62.a6",	0x200000, 0x292d3ef6, BRF_SND },           //  6
520 	{ "rom10_u67.a8",	0x200000, 0x5219bf86, BRF_SND },           //  7
521 	{ "rom11_u68.a10",	0x200000, 0x56fe4b1d, BRF_SND },           //  8
522 	{ "rom12_u63.a11",	0x200000, 0xcc48ff18, BRF_SND },           //  9
523 	{ "rom13_u64.a13",	0x200000, 0xa3cd181a, BRF_SND },           // 10
524 	{ "rom14_u69.a14",	0x200000, 0x5d8cddec, BRF_SND },           // 11
525 	{ "rom15_u70.a16",	0x200000, 0xc75012f5, BRF_SND },           // 12
526 	{ "rom16_u71.a18",	0x200000, 0xefd02b0d, BRF_SND },           // 13
527 	{ "rom17_u72.a19",	0x200000, 0x6b8717c3, BRF_SND },           // 14
528 };
529 
530 STD_ROM_PICK(enmadaio)
531 STD_ROM_FN(enmadaio)
532 
533 struct BurnDriver BurnDrvEnmadaio = {
534 	"enmadaio", NULL, NULL, NULL, "1993",
535 	"Enma Daio (Japan)\0", "Game unplayable.", "Toaplan / Taito", "Toaplan GP9001 based",
536 	NULL, NULL, NULL, NULL,
537 	BDF_GAME_NOT_WORKING, 2, HARDWARE_TOAPLAN_68K_ONLY, GBF_MISC, 0,
538 	NULL, enmadaioRomInfo, enmadaioRomName, NULL, NULL, NULL, NULL, EnmadaioInputInfo, EnmadaioDIPInfo,
539 	DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &ToaRecalcPalette, 0x800,
540 	320, 240, 4, 3
541 };
542