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