1 // FB Alpha Shadow Force driver module
2 // Based on MAME driver by David Haywood
3 // port to Finalburn Alpha by OopsWare. 2007
4
5 #include "tiles_generic.h"
6 #include "m68000_intf.h"
7 #include "z80_intf.h"
8 #include "burn_ym2151.h"
9 #include "msm6295.h"
10
11 static UINT8 *Mem = NULL, *MemEnd = NULL;
12 static UINT8 *RamStart, *RamEnd;
13
14 static UINT8 *Rom68K;
15 static UINT8 *RomZ80;
16 static UINT8 *RomGfx01;
17 static UINT8 *RomGfx02;
18 static UINT8 *RomGfx03;
19 static UINT8 *DrvOkiROM;
20 static UINT8 *Ram68K;
21 static UINT16 *RamBg00;
22 static UINT16 *RamBg01;
23 static UINT16 *RamFg;
24 static UINT16 *RamSpr;
25 static UINT16 *SprBuf;
26 static UINT16 *RamPal;
27 static UINT8 *RamZ80;
28
29 static UINT32 *RamCurPal;
30
31 static UINT8 DrvButton[8] = {0, 0, 0, 0, 0, 0, 0, 0};
32 static UINT8 DrvJoy1[8] = {0, 0, 0, 0, 0, 0, 0, 0};
33 static UINT8 DrvJoy2[8] = {0, 0, 0, 0, 0, 0, 0, 0};
34 static UINT8 DrvDipBtn[8] = {0, 0, 0, 0, 0, 0, 0, 0};
35
36 static UINT8 DrvInput[8] = {0, 0, 0, 0, 0, 0, 0, 0};
37 static UINT8 DrvReset = 0;
38 static UINT8 nBrightness = 0xFF;
39
40 static UINT8 okibank;
41 static UINT8 video_enable;
42 static UINT8 irqs_enable;
43 static UINT16 raster_scanline;
44 static UINT8 raster_irq_enable;
45 static UINT8 previous_irq_value;
46 static UINT8 bVBlank = 0;
47 static UINT16 bg0scrollx, bg0scrolly, bg1scrollx, bg1scrolly;
48 static UINT8 nSoundlatch = 0;
49 static UINT8 bRecalcPalette = 0;
50
51 static INT32 nZ80Cycles;
52
53 static struct BurnInputInfo shadfrceInputList[] = {
54 {"P1 Coin", BIT_DIGITAL, DrvDipBtn + 0, "p1 coin" },
55 {"P1 Start", BIT_DIGITAL, DrvJoy1 + 7, "p1 start" },
56
57 {"P1 Right", BIT_DIGITAL, DrvJoy1 + 0, "p1 right" },
58 {"P1 Left", BIT_DIGITAL, DrvJoy1 + 1, "p1 left" },
59 {"P1 Up", BIT_DIGITAL, DrvJoy1 + 2, "p1 up" },
60 {"P1 Down", BIT_DIGITAL, DrvJoy1 + 3, "p1 down" },
61 {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 4, "p1 fire 1" },
62 {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" },
63 {"P1 Button 3", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 3" },
64 {"P1 Button 4", BIT_DIGITAL, DrvButton + 0, "p1 fire 4" },
65 {"P1 Button 5", BIT_DIGITAL, DrvButton + 1, "p1 fire 5" },
66 {"P1 Button 6", BIT_DIGITAL, DrvButton + 2, "p1 fire 6" },
67
68 {"P2 Coin", BIT_DIGITAL, DrvDipBtn + 1, "p2 coin" },
69 {"P2 Start", BIT_DIGITAL, DrvJoy2 + 7, "p2 start" },
70
71 {"P2 Right", BIT_DIGITAL, DrvJoy2 + 0, "p2 right" },
72 {"P2 Left", BIT_DIGITAL, DrvJoy2 + 1, "p2 left" },
73 {"P2 Up", BIT_DIGITAL, DrvJoy2 + 2, "p2 up" },
74 {"P2 Down", BIT_DIGITAL, DrvJoy2 + 3, "p2 down" },
75 {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p2 fire 1" },
76 {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" },
77 {"P2 Button 3", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 3" },
78 {"P2 Button 4", BIT_DIGITAL, DrvButton + 3, "p2 fire 4" },
79 {"P2 Button 5", BIT_DIGITAL, DrvButton + 4, "p2 fire 5" },
80 {"P2 Button 6", BIT_DIGITAL, DrvButton + 5, "p2 fire 6" },
81
82 {"Reset", BIT_DIGITAL, &DrvReset, "reset" },
83 {"Dip A", BIT_DIPSWITCH, DrvInput + 1, "dip" },
84 {"Dip B", BIT_DIPSWITCH, DrvInput + 3, "dip" },
85 {"Dip C", BIT_DIPSWITCH, DrvInput + 5, "dip" },
86 {"Dip D", BIT_DIPSWITCH, DrvInput + 7, "dip" },
87 };
88
89 STDINPUTINFO(shadfrce)
90
91 static struct BurnDIPInfo shadfrceDIPList[] =
92 {
93 {0x19, 0xFF, 0xFF, 0x00, NULL },
94 {0x1A, 0xFF, 0xFF, 0x00, NULL },
95 {0x1B, 0xFF, 0xFF, 0x00, NULL },
96 {0x1C, 0xFF, 0xFF, 0x00, NULL },
97
98 {0, 0xFE, 0, 2, "Service1" }, // only available when you are in "test mode"
99 {0x19, 0x01, 0x04, 0x00, "Off" },
100 {0x19, 0x01, 0x04, 0x04, "On" },
101
102 {0, 0xFE, 0, 4, "Difficulty" },
103 {0x1A, 0x01, 0x03, 0x00, "Normal" },
104 {0x1A, 0x01, 0x03, 0x01, "Hard" },
105 {0x1A, 0x01, 0x03, 0x02, "Easy" },
106 {0x1A, 0x01, 0x03, 0x03, "Hardest" },
107
108 {0, 0xFE, 0, 4, "Stage Clear Energy Regain" },
109 {0x1A, 0x01, 0x0C, 0x00, "25%" },
110 {0x1A, 0x01, 0x0C, 0x04, "10%" },
111 {0x1A, 0x01, 0x0C, 0x08, "50%" },
112 {0x1A, 0x01, 0x0C, 0x0C, "0%" },
113
114 {0, 0xFE, 0, 4, "Coinage" },
115 {0x1B, 0x01, 0x06, 0x00, "1 Coin 1 Credit" },
116 {0x1B, 0x01, 0x06, 0x02, "1 Coin 2 Credits" },
117 {0x1B, 0x01, 0x06, 0x04, "2 Coins 1 Credit" },
118 {0x1B, 0x01, 0x06, 0x06, "3 Coins 1 Credit" },
119
120 {0, 0xFE, 0, 2, "Continue Price" },
121 {0x1B, 0x01, 0x08, 0x00, "Off" },
122 {0x1B, 0x01, 0x08, 0x80, "On" },
123
124 {0, 0xFE, 0, 2, "Free Play" },
125 {0x1B, 0x01, 0x10, 0x00, "Off" },
126 {0x1B, 0x01, 0x10, 0x10, "On" },
127
128 {0, 0xFE, 0, 2, "Flip Screen" },
129 {0x1B, 0x01, 0x20, 0x00, "Off" },
130 {0x1B, 0x01, 0x20, 0x20, "On" },
131
132 {0, 0xFE, 0, 2,"Demo Sounds" },
133 {0x1C, 0x01, 0x01, 0x00, "Off" },
134 {0x1C, 0x01, 0x01, 0x01, "On" },
135
136 {0, 0xFE, 0, 2, "Test Mode" },
137 {0x1C, 0x01, 0x02, 0x00, "Off" },
138 {0x1C, 0x01, 0x02, 0x02, "On" },
139 };
140
STDDIPINFO(shadfrce)141 STDDIPINFO(shadfrce)
142
143 inline static void CalcCol(INT32 idx)
144 {
145 UINT16 nColour = RamPal[idx];
146 INT32 r = (nColour & 0x001F) << 3; r |= r >> 5; // Red
147 INT32 g = (nColour & 0x03E0) >> 2; g |= g >> 5; // Green
148 INT32 b = (nColour & 0x7C00) >> 7; b |= b >> 5; // Blue
149 r = (r * nBrightness) >> 8;
150 g = (g * nBrightness) >> 8;
151 b = (b * nBrightness) >> 8;
152 RamCurPal[idx] = BurnHighCol(r, g, b, 0);
153 }
154
shadfrceReadByte(UINT32 sekAddress)155 static UINT8 __fastcall shadfrceReadByte(UINT32 sekAddress)
156 {
157 switch (sekAddress)
158 {
159 case 0x1D0020:
160 return (~DrvInput[1] & 0x3F);
161
162 case 0x1D0021:
163 return ~DrvInput[0];
164
165 case 0x1D0022:
166 return (~DrvInput[3] & 0x3F);
167
168 case 0x1D0023:
169 return ~DrvInput[2];
170
171 case 0x1D0024:
172 return (~DrvInput[5] & 0x3F);
173
174 case 0x1D0025:
175 return ~DrvInput[4];
176
177 case 0x1D0026:
178 return ~(DrvInput[7] | (bVBlank << 2));
179
180 case 0x1D0027:
181 return ~DrvInput[6];
182
183 case 0x1C000B:
184 return 0;
185
186 case 0x1D000D:
187 return nBrightness;
188
189 // default:
190 // bprintf(PRINT_NORMAL, _T("Attempt to read byte value of location %x\n"), sekAddress);
191 }
192
193 return 0;
194 }
195
shadfrceReadWord(UINT32 sekAddress)196 static UINT16 __fastcall shadfrceReadWord(UINT32 sekAddress)
197 {
198 switch (sekAddress)
199 {
200 case 0x1D0020:
201 return ~(DrvInput[0] | (DrvInput[1] << 8)) & 0x3FFF;
202
203 case 0x1D0022:
204 return ~(DrvInput[2] | (DrvInput[3] << 8)) & 0x3FFF;
205
206 case 0x1D0024:
207 return ~(DrvInput[4] | (DrvInput[5] << 8)) & 0x3FFF;
208
209 case 0x1D0026:
210 return ~(DrvInput[6] | ( (DrvInput[7] | (bVBlank << 2))<< 8));
211
212 // default:
213 // bprintf(PRINT_NORMAL, _T("Attempt to read word value of location %x\n"), sekAddress);
214 }
215
216 return 0;
217 }
218
shadfrceWriteByte(UINT32 sekAddress,UINT8 byteValue)219 static void __fastcall shadfrceWriteByte(UINT32 sekAddress, UINT8 byteValue)
220 {
221 switch (sekAddress)
222 {
223 case 0x1C000B:
224 // shadfrce_flip_screen
225 break;
226
227 case 0x1D0000:
228 case 0x1D0001:
229 case 0x1D0002:
230 case 0x1D0003:
231 case 0x1D0004:
232 case 0x1D0005:
233 SekSetIRQLine(((sekAddress/2) & 3) ^ 3, CPU_IRQSTATUS_NONE);
234 break;
235
236 case 0x1D0007:
237 {
238 irqs_enable = byteValue & 1;
239 video_enable = byteValue & 0x08;
240
241 if ((previous_irq_value & 4) == 0 && (byteValue & 4) == 4) {
242 raster_irq_enable = 1;
243 GenericTilemapSetScrollRows(1, 16*32);
244 }
245 if ((previous_irq_value & 4) == 4 && (byteValue & 4) == 0) {
246 raster_irq_enable = 0;
247 GenericTilemapSetScrollRows(1, 1);
248 }
249
250 previous_irq_value = byteValue;
251 }
252 break;
253
254 case 0x1D0009:
255 case 0x1D0008:
256 raster_scanline = 0;
257 break;
258
259 case 0x1D000C:
260 nSoundlatch = byteValue;
261 ZetNmi();
262 break;
263
264 case 0x1D000D:
265 nBrightness = byteValue;
266 for(INT32 i=0;i<0x4000;i++) CalcCol(i);
267 break;
268
269 case 0x1C000D:
270 case 0x1D0011:
271 case 0x1D0013:
272 case 0x1D0015:
273 case 0x1D0017: // NOP
274 break;
275
276 // default:
277 // bprintf(PRINT_NORMAL, _T("Attempt to write byte value %x to location %x\n"), byteValue, sekAddress);
278 }
279 }
280
shadfrceWriteWord(UINT32 sekAddress,UINT16 wordValue)281 static void __fastcall shadfrceWriteWord(UINT32 sekAddress, UINT16 wordValue)
282 {
283 switch (sekAddress)
284 {
285 case 0x1C0000: bg0scrollx = wordValue & 0x1FF; break;
286 case 0x1C0002: bg0scrolly = wordValue & 0x1FF; break;
287 case 0x1C0004: bg1scrollx = wordValue & 0x1FF; break;
288 case 0x1C0006: bg1scrolly = wordValue & 0x1FF; break;
289
290 case 0x1D000D:
291 //nBrightness = byteValue;
292 break;
293
294 case 0x1D0016:
295 // wait v-blink dip change call back ???
296 break;
297
298 case 0x1D0006:
299 {
300 irqs_enable = wordValue & 1;
301 video_enable = wordValue & 0x08;
302
303 if ((previous_irq_value & 4) == 0 && (wordValue & 4) == 4) {
304 raster_irq_enable = 1;
305 GenericTilemapSetScrollRows(1, 16*32);
306 }
307 if ((previous_irq_value & 4) == 4 && (wordValue & 4) == 0) {
308 raster_irq_enable = 0;
309 GenericTilemapSetScrollRows(1, 1);
310 }
311
312 previous_irq_value = wordValue;
313 }
314 break;
315
316 case 0x1D0000:
317 case 0x1D0002:
318 case 0x1D0004:
319 SekSetIRQLine(((sekAddress/2) & 3) ^ 3, CPU_IRQSTATUS_NONE);
320 break;
321
322 case 0x1D0008:
323 raster_scanline = 0;
324 break;
325
326 // default:
327 // bprintf(PRINT_NORMAL, _T("Attempt to write word value %x to location %x\n"), wordValue, sekAddress);
328 }
329 }
330
shadfrceWriteWordPalette(UINT32 sekAddress,UINT16 wordValue)331 static void __fastcall shadfrceWriteWordPalette(UINT32 sekAddress, UINT16 wordValue)
332 {
333 sekAddress &= 0x7FFF;
334 sekAddress >>= 1;
335 RamPal[sekAddress] = wordValue;
336 CalcCol(sekAddress);
337 }
338
shadfrceZRead(UINT16 a)339 static UINT8 __fastcall shadfrceZRead(UINT16 a)
340 {
341 switch (a)
342 {
343 case 0xC801:
344 return BurnYM2151Read();
345
346 case 0xD800:
347 return MSM6295Read(0);
348
349 case 0xE000:
350 return nSoundlatch;
351
352 // default:
353 // bprintf(PRINT_NORMAL, _T("Z80 address %04X read.\n"), a);
354 }
355
356 return 0;
357 }
358
shadfrceZWrite(UINT16 a,UINT8 d)359 void __fastcall shadfrceZWrite(UINT16 a, UINT8 d)
360 {
361 switch (a)
362 {
363 case 0xC800:
364 BurnYM2151SelectRegister(d);
365 break;
366
367 case 0xC801:
368 BurnYM2151WriteRegister(d);
369 break;
370
371 case 0xD800:
372 MSM6295Write(0, d);
373 break;
374
375 case 0xE800:
376 okibank = (d & 1);
377 MSM6295SetBank(0, DrvOkiROM + okibank * 0x40000, 0, 0x3ffff);
378 break;
379
380 // default:
381 // bprintf(PRINT_NORMAL, _T("Z80 address %04X -> %02X.\n"), a, d);
382 }
383 }
384
shadfrceYM2151IRQHandler(INT32 nStatus)385 static void shadfrceYM2151IRQHandler(INT32 nStatus)
386 {
387 if (nStatus) {
388 ZetSetIRQLine(0xFF, CPU_IRQSTATUS_ACK);
389 ZetRun(1024);
390 } else {
391 ZetSetIRQLine(0, CPU_IRQSTATUS_NONE);
392 }
393 }
394
DrvDoReset()395 static INT32 DrvDoReset()
396 {
397 SekOpen(0);
398 SekSetIRQLine(0, CPU_IRQSTATUS_NONE);
399 SekReset();
400 SekClose();
401
402 ZetOpen(0);
403 ZetReset();
404 ZetClose();
405
406 MSM6295Reset(0);
407 shadfrceZWrite(0xe800, 0); // set initial oki bank
408 BurnYM2151Reset();
409
410 video_enable = 0;
411 irqs_enable = 0;
412 raster_scanline = 0;
413 raster_irq_enable = 0;
414 previous_irq_value = 0;
415
416 return 0;
417 }
418
MemIndex()419 static INT32 MemIndex()
420 {
421 UINT8 *Next; Next = Mem;
422
423 Rom68K = Next; Next += 0x100000; // 68000 ROM
424 RomZ80 = Next; Next += 0x010000; // Z80 ROM
425 RomGfx01 = Next; Next += 0x020000 / 4 * 8; // fg 8x8x4
426 RomGfx02 = Next; Next += 0xA00000 / 5 * 8; // spr 16x16x5 sprite
427 RomGfx03 = Next; Next += 0x300000 / 6 * 8; // bg 16x16x6 tile
428
429 MSM6295ROM = Next;
430 DrvOkiROM = Next; Next += 0x080000;
431
432 RamStart = Next;
433
434 RamBg00 = (UINT16 *) Next; Next += 0x001000 * sizeof(UINT16);
435 RamBg01 = (UINT16 *) Next; Next += 0x001000 * sizeof(UINT16);
436 RamFg = (UINT16 *) Next; Next += 0x001000 * sizeof(UINT16);
437 RamSpr = (UINT16 *) Next; Next += 0x001000 * sizeof(UINT16);
438 SprBuf = (UINT16 *) Next; Next += 0x001000 * sizeof(UINT16);
439 RamPal = (UINT16 *) Next; Next += 0x004000 * sizeof(UINT16);
440 Ram68K = Next; Next += 0x010000;
441 RamZ80 = Next; Next += 0x001800;
442 RamEnd = Next;
443
444 RamCurPal = (UINT32 *) Next; Next += 0x004000 * sizeof(UINT32);
445
446 MemEnd = Next;
447
448 return 0;
449 }
450
DrvGfxDecode()451 static INT32 DrvGfxDecode()
452 {
453 INT32 Plane0[4] = { STEP4(0,2) };
454 INT32 XOffs0[8] = { 1, 0, 8*8+1, 8*8+0, 16*8+1, 16*8+0, 24*8+1, 24*8+0 };
455 INT32 YOffs0[8] = { STEP8(0,8) };
456
457 INT32 Plane1[5] = { (0x200000*8*4), (0x200000*8*3), (0x200000*8*2), (0x200000*8*1), (0x200000*8*0) };
458 INT32 XOffs1[16] = { STEP8(0,1), STEP8(16*8,1) };
459 INT32 YOffs1[16] = { STEP16(0,8) };
460
461 INT32 Plane2[6] = { (0x100000*8*0)+8, (0x100000*8*0), (0x100000*8*1)+8, (0x100000*8*1), (0x100000*8*2)+8, (0x100000*8*2) };
462 INT32 XOffs2[16] = { STEP8(0,1), STEP8(16*16,1) };
463 INT32 YOffs2[16] = { STEP16(0,16) };
464
465 UINT8 *tmp = (UINT8*)BurnMalloc(0xa00000);
466 if (tmp == NULL) {
467 return 1;
468 }
469
470 memcpy (tmp, RomGfx01, 0x20000);
471
472 GfxDecode(0x01000, 4, 8, 8, Plane0, XOffs0, YOffs0, 0x100, tmp, RomGfx01);
473
474 memcpy (tmp, RomGfx02, 0xa00000);
475
476 GfxDecode(0x10000, 5, 16, 16, Plane1, XOffs1, YOffs1, 0x100, tmp, RomGfx02);
477
478 memcpy (tmp, RomGfx03, 0x300000);
479
480 GfxDecode(0x04000, 6, 16, 16, Plane2, XOffs2, YOffs2, 0x200, tmp, RomGfx03);
481
482 BurnFree(tmp);
483
484 return 0;
485 }
486
tilemap_callback(background0)487 static tilemap_callback( background0 )
488 {
489 INT32 attr = RamBg00[offs * 2 + 0];
490 INT32 color = (attr & 0x1f);
491 if (color & 0x10) color ^= 0x30;
492
493 TILE_SET_INFO(1, RamBg00[offs * 2 + 1] & 0x3fff, color, TILE_FLIPYX((attr >> 6) & 3));
494 }
495
tilemap_callback(background1)496 static tilemap_callback( background1 )
497 {
498 INT32 attr = RamBg01[offs];
499
500 TILE_SET_INFO(1, attr & 0xfff, (attr >> 12) + 0x40, 0);
501 }
502
tilemap_callback(foreground)503 static tilemap_callback( foreground )
504 {
505 INT32 attr = RamFg[offs * 2 + 1] & 0xff;
506
507 TILE_SET_INFO(0, (RamFg[offs * 2] & 0xff) + (attr << 8), attr >> 4, 0);
508 }
509
shadfrceInit()510 static INT32 shadfrceInit()
511 {
512 INT32 nRet;
513
514 Mem = NULL;
515 MemIndex();
516 INT32 nLen = MemEnd - (UINT8 *)0;
517 if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1;
518 memset(Mem, 0, nLen);
519 MemIndex();
520
521 {
522 nRet = BurnLoadRom(Rom68K + 0x000000, 0, 2); if (nRet != 0) return 1;
523 nRet = BurnLoadRom(Rom68K + 0x000001, 1, 2); if (nRet != 0) return 1;
524 nRet = BurnLoadRom(Rom68K + 0x080000, 2, 2); if (nRet != 0) return 1;
525 nRet = BurnLoadRom(Rom68K + 0x080001, 3, 2); if (nRet != 0) return 1;
526
527 nRet = BurnLoadRom(RomZ80 + 0x000000, 4, 1); if (nRet != 0) return 1;
528
529 nRet = BurnLoadRom(RomGfx01 + 0x000000, 5, 1); if (nRet != 0) return 1;
530
531 nRet = BurnLoadRom(RomGfx02 + 0x000000, 6, 1); if (nRet != 0) return 1;
532 nRet = BurnLoadRom(RomGfx02 + 0x200000, 7, 1); if (nRet != 0) return 1;
533 nRet = BurnLoadRom(RomGfx02 + 0x400000, 8, 1); if (nRet != 0) return 1;
534 nRet = BurnLoadRom(RomGfx02 + 0x600000, 9, 1); if (nRet != 0) return 1;
535 nRet = BurnLoadRom(RomGfx02 + 0x800000, 10, 1); if (nRet != 0) return 1;
536
537 nRet = BurnLoadRom(RomGfx03 + 0x000000, 11, 1); if (nRet != 0) return 1;
538 nRet = BurnLoadRom(RomGfx03 + 0x100000, 12, 1); if (nRet != 0) return 1;
539 nRet = BurnLoadRom(RomGfx03 + 0x200000, 13, 1); if (nRet != 0) return 1;
540
541 nRet = BurnLoadRom(DrvOkiROM, 14, 1); if (nRet != 0) return 1;
542
543 DrvGfxDecode();
544 }
545
546 SekInit(0, 0x68000);
547 SekOpen(0);
548 SekMapMemory(Rom68K, 0x000000, 0x0FFFFF, MAP_ROM);
549 SekMapMemory((UINT8 *)RamBg00, 0x100000, 0x101FFF, MAP_RAM);
550 SekMapMemory((UINT8 *)RamBg01, 0x102000, 0x103FFF, MAP_RAM);
551 SekMapMemory((UINT8 *)RamFg, 0x140000, 0x141FFF, MAP_RAM);
552 SekMapMemory((UINT8 *)RamSpr, 0x142000, 0x143FFF, MAP_RAM);
553 SekMapMemory((UINT8 *)RamPal, 0x180000, 0x187FFF, MAP_ROM);
554 SekMapMemory(Ram68K, 0x1F0000, 0x1FFFFF, MAP_RAM);
555 SekMapHandler(1, 0x180000, 0x187FFF, MAP_WRITE);
556 SekSetReadWordHandler(0, shadfrceReadWord);
557 SekSetReadByteHandler(0, shadfrceReadByte);
558 SekSetWriteWordHandler(0, shadfrceWriteWord);
559 SekSetWriteByteHandler(0, shadfrceWriteByte);
560 //SekSetWriteByteHandler(1, shadfrceWriteBytePalette);
561 SekSetWriteWordHandler(1, shadfrceWriteWordPalette);
562 SekClose();
563
564 ZetInit(0);
565 ZetOpen(0);
566 ZetMapMemory(RomZ80, 0x0000, 0xbfff, MAP_ROM);
567 ZetMapMemory(RamZ80, 0xc000, 0xc7ff, MAP_RAM);
568 ZetMapMemory(RamZ80 + 0x0800, 0xf000, 0xffff, MAP_RAM);
569 ZetSetReadHandler(shadfrceZRead);
570 ZetSetWriteHandler(shadfrceZWrite);
571 ZetClose();
572
573 BurnYM2151Init(3579545); // 3.5795 MHz
574 YM2151SetIrqHandler(0, &shadfrceYM2151IRQHandler);
575 BurnYM2151SetRoute(BURN_SND_YM2151_YM2151_ROUTE_1, 0.50, BURN_SND_ROUTE_LEFT);
576 BurnYM2151SetRoute(BURN_SND_YM2151_YM2151_ROUTE_2, 0.50, BURN_SND_ROUTE_RIGHT);
577 MSM6295Init(0, 12000, 1); // 12.000 KHz
578 MSM6295SetRoute(0, 0.50, BURN_SND_ROUTE_BOTH);
579 nZ80Cycles = 3579545 * 100 / nBurnFPS;
580
581 GenericTilesInit();
582 GenericTilemapInit(0, TILEMAP_SCAN_ROWS, foreground_map_callback, 8, 8, 64, 32);
583 GenericTilemapInit(1, TILEMAP_SCAN_ROWS, background0_map_callback, 16, 16, 32, 32);
584 GenericTilemapInit(2, TILEMAP_SCAN_ROWS, background1_map_callback, 16, 16, 32, 32);
585 GenericTilemapSetGfx(0, RomGfx01, 6 /*actually 4*/, 8, 8, 0x040000, 0x0000, 0xff);
586 GenericTilemapSetGfx(1, RomGfx03, 6, 16, 16, 0x400000, 0x2000, 0x7f);
587 // GenericTilemapSetOffsets(TMAP_GLOBAL, 0, -8);
588 GenericTilemapSetTransparent(0, 0);
589 GenericTilemapSetTransparent(1, 0);
590
591 DrvDoReset();
592
593 return 0;
594 }
595
shadfrceExit()596 static INT32 shadfrceExit()
597 {
598 GenericTilesExit();
599
600 MSM6295Exit(0);
601 BurnYM2151Exit();
602
603 SekExit();
604 ZetExit();
605
606 BurnFree(Mem);
607
608 return 0;
609 }
610
drawSprites()611 static void drawSprites()
612 {
613 UINT16 * finish = SprBuf;
614 UINT16 * source = finish + 0x2000/2 - 8;
615
616 while (source>=finish)
617 {
618 INT32 ypos = 0x100 - (((source[0] & 0x0003) << 8) | (source[1] & 0x00ff));
619 INT32 xpos = (((source[4] & 0x0001) << 8) | (source[5] & 0x00ff)) + 1;
620 INT32 tile = ((source[2] & 0x00ff) << 8) | (source[3] & 0x00ff);
621 INT32 height = ((source[0] & 0x00e0) >> 5) + 1;
622 INT32 enable = ((source[0] & 0x0004));
623 INT32 flipx = ((source[0] & 0x0010) >> 4);
624 INT32 flipy = ((source[0] & 0x0008) >> 3);
625 INT32 color = ((source[4] & 0x003e));
626 INT32 pri_mask = (source[4] & 0x0040) ? 0x02 : 0x00;
627
628 if (color & 0x20) color ^= 0x60; // skip hole
629 color <<= 5;
630
631 if (enable)
632 {
633 for (INT32 hcount = 0; hcount < height; hcount++)
634 {
635 RenderPrioSprite(pTransDraw, RomGfx02, tile+hcount, 0x1000 + color, 0, xpos, ypos-hcount*16-16, flipx, flipy, 16, 16, pri_mask);
636 RenderPrioSprite(pTransDraw, RomGfx02, tile+hcount, 0x1000 + color, 0, xpos-0x200, ypos-hcount*16-16, flipx, flipy, 16, 16, pri_mask);
637 RenderPrioSprite(pTransDraw, RomGfx02, tile+hcount, 0x1000 + color, 0, xpos, ypos-hcount*16-16+0x200, flipx, flipy, 16, 16, pri_mask);
638 RenderPrioSprite(pTransDraw, RomGfx02, tile+hcount, 0x1000 + color, 0, xpos-0x200, ypos-hcount*16-16+0x200, flipx, flipy, 16, 16, pri_mask);
639 }
640 }
641
642 source-=8;
643 }
644 }
645
draw_line(INT32 line)646 static void draw_line(INT32 line)
647 {
648 GenericTilesSetScanline(line);
649
650 if (video_enable)
651 {
652 // GenericTilemapSetScrollX(1, bg0scrollx);
653 GenericTilemapSetScrollRow(1, line, bg0scrollx);
654 GenericTilemapSetScrollY(1, bg0scrolly);
655
656 if (nBurnLayer & 2) GenericTilemapDraw(1, pTransDraw, 1);
657 }
658 }
659
draw_bg_layer_raster()660 static void draw_bg_layer_raster()
661 {
662 GenericTilesClearClip();
663
664 if (video_enable)
665 {
666 GenericTilemapSetScrollX(2, bg1scrollx);
667 GenericTilemapSetScrollY(2, bg1scrolly);
668
669 if (nBurnLayer & 1) GenericTilemapDraw(2, pTransDraw, 0);
670 }
671 else
672 {
673 BurnTransferClear();
674 }
675 }
676
shadfrceDraw()677 static INT32 shadfrceDraw()
678 {
679 if (bRecalcPalette) {
680 for(INT32 i=0;i<0x4000;i++) CalcCol(i);
681 bRecalcPalette = 0;
682 }
683
684 GenericTilesClearClip();
685
686 if (video_enable)
687 {
688 if (raster_irq_enable == 0) {
689 GenericTilemapSetScrollX(1, bg0scrollx);
690 GenericTilemapSetScrollY(1, bg0scrolly);
691 GenericTilemapSetScrollX(2, bg1scrollx);
692 GenericTilemapSetScrollY(2, bg1scrolly);
693
694 if (nBurnLayer & 1) GenericTilemapDraw(2, pTransDraw, 0);
695 if (nBurnLayer & 2) GenericTilemapDraw(1, pTransDraw, 1);
696 }
697
698 if (nBurnLayer & 4) drawSprites();
699
700 if (nBurnLayer & 8) GenericTilemapDraw(0, pTransDraw, 0);
701 }
702 else
703 {
704 if (raster_irq_enable == 0) {
705 BurnTransferClear();
706 }
707 }
708
709 BurnTransferCopy(RamCurPal);
710
711 return 0;
712 }
713
shadfrceFrame()714 static INT32 shadfrceFrame()
715 {
716 if (DrvReset) {
717 DrvDoReset();
718 }
719
720 {
721 DrvInput[0] = 0x00;
722 DrvInput[2] = 0x00;
723 DrvInput[4] = 0x00;
724 for (INT32 i = 0; i < 8; i++) {
725 DrvInput[0] |= (DrvJoy1[i] & 1) << i;
726 DrvInput[2] |= (DrvJoy2[i] & 1) << i;
727 DrvInput[4] |= (DrvButton[i] & 1) << i;
728 }
729 DrvInput[1] = (DrvInput[1] & 0xFC) | (DrvDipBtn[0] & 1) | ((DrvDipBtn[1] & 1) << 1);
730 }
731
732 SekNewFrame();
733 ZetNewFrame();
734
735 INT32 nInterleave = 272;
736 INT32 nCyclesTotal[2] = { 14000000 / 60, 3579545 / 60 };
737 INT32 nCyclesDone[2] = { 0, 0 };
738 INT32 nSoundBufferPos = 0;
739
740 SekOpen(0);
741 ZetOpen(0);
742
743 bVBlank = 1;
744
745 for (INT32 scanline = 0; scanline < nInterleave; scanline++)
746 {
747 nCyclesDone[0] += SekRun(nCyclesTotal[0] / nInterleave);
748
749 nCyclesDone[1] += ZetRun(nCyclesTotal[1] / nInterleave);
750
751 if (raster_irq_enable && (scanline == raster_scanline)) {
752 raster_scanline = (raster_scanline + 1) % 240;
753 if (raster_scanline > 0) {
754 SekSetIRQLine(1, CPU_IRQSTATUS_ACK);
755 }
756 }
757
758 if (irqs_enable) {
759 if ((scanline & 0xf) == 0 && (scanline > 0)) {
760 SekSetIRQLine(2, CPU_IRQSTATUS_ACK);
761 }
762
763 if (scanline == 248) {
764 SekSetIRQLine(3, CPU_IRQSTATUS_ACK);
765 }
766 }
767
768 if (scanline == 247) {
769 bVBlank = 0;
770 }
771
772 if (scanline == 0 && raster_irq_enable) {
773 draw_bg_layer_raster();
774 }
775
776 if (scanline < 256 && raster_irq_enable) {
777 draw_line(scanline);
778 }
779
780 if (pBurnSoundOut) {
781 INT32 nSegmentLength = (nBurnSoundLen / nInterleave) - nSoundBufferPos;
782 INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos * 2);
783 BurnYM2151Render(pSoundBuf, nSegmentLength);
784 MSM6295Render(0, pSoundBuf, nSegmentLength);
785 nSoundBufferPos += nSegmentLength;
786 }
787 }
788
789 if (pBurnSoundOut) {
790 INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos;
791 INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
792 BurnYM2151Render(pSoundBuf, nSegmentLength);
793 MSM6295Render(0, pSoundBuf, nSegmentLength);
794 nSoundBufferPos += nSegmentLength;
795 }
796
797 ZetClose();
798 SekClose();
799
800 if (pBurnDraw) {
801 shadfrceDraw();
802 }
803
804 memcpy (SprBuf, RamSpr, 0x2000); // buffer one frame
805
806 return 0;
807 }
808
shadfrceScan(INT32 nAction,INT32 * pnMin)809 static INT32 shadfrceScan(INT32 nAction,INT32 *pnMin)
810 {
811 struct BurnArea ba;
812
813 if (pnMin)
814 *pnMin = 0x029671;
815
816 if (nAction & ACB_MEMORY_RAM) {
817 memset(&ba, 0, sizeof(ba));
818 ba.Data = RamStart;
819 ba.nLen = RamEnd-RamStart;
820 ba.szName = "All Ram";
821 BurnAcb(&ba);
822 }
823
824 if (nAction & ACB_DRIVER_DATA) {
825 SekScan(nAction);
826 ZetScan(nAction);
827
828 MSM6295Scan(nAction, pnMin);
829 BurnYM2151Scan(nAction, pnMin);
830
831 SCAN_VAR(DrvInput);
832 SCAN_VAR(nBrightness);
833 SCAN_VAR(bg0scrollx);
834 SCAN_VAR(bg0scrolly);
835 SCAN_VAR(bg1scrollx);
836 SCAN_VAR(bg1scrolly);
837 SCAN_VAR(nSoundlatch);
838 SCAN_VAR(video_enable);
839 SCAN_VAR(okibank);
840 }
841
842 if (nAction & ACB_WRITE) {
843 // recalc palette and brightness
844 for(INT32 i=0;i<0x4000;i++) CalcCol(i);
845
846 shadfrceZWrite(0xe800, okibank); // set oki bank
847 }
848
849 return 0;
850 }
851
852
853 // Shadow Force (World, Version 3)
854
855 static struct BurnRomInfo shadfrceRomDesc[] = {
856 { "32a12-011.34", 0x040000, 0x0c041e08, BRF_ESS | BRF_PRG }, // 68000 code
857 { "32a13-010.26", 0x040000, 0x00985361, BRF_ESS | BRF_PRG },
858 { "32a14-010.33", 0x040000, 0xea03ca25, BRF_ESS | BRF_PRG },
859 { "32j15-01.14", 0x040000, 0x3dc3a84a, BRF_ESS | BRF_PRG },
860
861 { "32j10-0.42", 0x010000, 0x65daf475, BRF_ESS | BRF_PRG }, // Z80 code
862
863 { "32j11-0.55", 0x020000, 0x7252d993, BRF_GRA }, // gfx 1 chars
864
865 { "32j4-0.12", 0x200000, 0x1ebea5b6, BRF_GRA }, // gfx 2 sprite
866 { "32j5-0.13", 0x200000, 0x600026b5, BRF_GRA },
867 { "32j6-0.24", 0x200000, 0x6cde8ebe, BRF_GRA },
868 { "32j7-0.25", 0x200000, 0xbcb37922, BRF_GRA },
869 { "32j8-0.32", 0x200000, 0x201bebf6, BRF_GRA },
870
871 { "32j1-0.4", 0x100000, 0xf1cca740, BRF_GRA }, // gfx 3 bg
872 { "32j2-0.5", 0x100000, 0x5fac3e01, BRF_GRA },
873 { "32j3-0.6", 0x100000, 0xd297925e, BRF_GRA },
874
875 { "32j9-0.76", 0x080000, 0x16001e81, BRF_SND }, // PCM
876 };
877
878 STD_ROM_PICK(shadfrce)
879 STD_ROM_FN(shadfrce)
880
881 struct BurnDriver BurnDrvShadfrce = {
882 "shadfrce", NULL, NULL, NULL, "1993",
883 "Shadow Force (World, Version 3)\0", NULL, "Technos Japan", "Miscellaneous",
884 NULL, NULL, NULL, NULL,
885 BDF_GAME_WORKING, 2, HARDWARE_TECHNOS, GBF_SCRFIGHT, 0,
886 NULL, shadfrceRomInfo, shadfrceRomName, NULL, NULL, NULL, NULL, shadfrceInputInfo, shadfrceDIPInfo,
887 shadfrceInit, shadfrceExit, shadfrceFrame, shadfrceDraw, shadfrceScan, &bRecalcPalette, 0x4000,
888 320, 256, 4, 3
889 };
890
891
892 // Shadow Force (US, Version 2)
893
894 static struct BurnRomInfo shadfrceuRomDesc[] = {
895 { "32a12-01.34", 0x040000, 0x04501198, BRF_ESS | BRF_PRG }, // 68000 code
896 { "32a13-01.26", 0x040000, 0xb8f8a05c, BRF_ESS | BRF_PRG },
897 { "32a14-0.33", 0x040000, 0x08279be9, BRF_ESS | BRF_PRG },
898 { "32a15-0.14", 0x040000, 0xbfcadfea, BRF_ESS | BRF_PRG },
899
900 { "32j10-0.42", 0x010000, 0x65daf475, BRF_ESS | BRF_PRG }, // Z80 code
901
902 { "32a11-0.55", 0x020000, 0xcfaf5e77, BRF_GRA }, // gfx 1 chars
903
904 { "32j4-0.12", 0x200000, 0x1ebea5b6, BRF_GRA }, // gfx 2 sprite
905 { "32j5-0.13", 0x200000, 0x600026b5, BRF_GRA },
906 { "32j6-0.24", 0x200000, 0x6cde8ebe, BRF_GRA },
907 { "32j7-0.25", 0x200000, 0xbcb37922, BRF_GRA },
908 { "32j8-0.32", 0x200000, 0x201bebf6, BRF_GRA },
909
910 { "32j1-0.4", 0x100000, 0xf1cca740, BRF_GRA }, // gfx 3 bg
911 { "32j2-0.5", 0x100000, 0x5fac3e01, BRF_GRA },
912 { "32j3-0.6", 0x100000, 0xd297925e, BRF_GRA },
913
914 { "32j9-0.76", 0x080000, 0x16001e81, BRF_SND }, // PCM
915 };
916
917 STD_ROM_PICK(shadfrceu)
918 STD_ROM_FN(shadfrceu)
919
920 struct BurnDriver BurnDrvShadfrceu = {
921 "shadfrceu", "shadfrce", NULL, NULL, "1993",
922 "Shadow Force (US, Version 2)\0", NULL, "Technos Japan", "Miscellaneous",
923 NULL, NULL, NULL, NULL,
924 BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TECHNOS, GBF_SCRFIGHT, 0,
925 NULL, shadfrceuRomInfo, shadfrceuRomName, NULL, NULL, NULL, NULL, shadfrceInputInfo, shadfrceDIPInfo,
926 shadfrceInit, shadfrceExit, shadfrceFrame, shadfrceDraw, shadfrceScan, &bRecalcPalette, 0x4000,
927 320, 256, 4, 3
928 };
929
930
931 // Shadow Force (Japan, Version 2)
932
933 static struct BurnRomInfo shadfrcejRomDesc[] = {
934 { "32j12-01.34", 0x040000, 0x38fdbe1d, BRF_ESS | BRF_PRG }, // 68000 code
935 { "32j13-01.26", 0x040000, 0x6e1df6f1, BRF_ESS | BRF_PRG },
936 { "32j14-01.33", 0x040000, 0x89e3fb60, BRF_ESS | BRF_PRG },
937 { "32j15-01.14", 0x040000, 0x3dc3a84a, BRF_ESS | BRF_PRG },
938
939 { "32j10-0.42", 0x010000, 0x65daf475, BRF_ESS | BRF_PRG }, // Z80 code
940
941 { "32j11-0.55", 0x020000, 0x7252d993, BRF_GRA }, // gfx 1 chars
942
943 { "32j4-0.12", 0x200000, 0x1ebea5b6, BRF_GRA }, // gfx 2 sprite
944 { "32j5-0.13", 0x200000, 0x600026b5, BRF_GRA },
945 { "32j6-0.24", 0x200000, 0x6cde8ebe, BRF_GRA },
946 { "32j7-0.25", 0x200000, 0xbcb37922, BRF_GRA },
947 { "32j8-0.32", 0x200000, 0x201bebf6, BRF_GRA },
948
949 { "32j1-0.4", 0x100000, 0xf1cca740, BRF_GRA }, // gfx 3 bg
950 { "32j2-0.5", 0x100000, 0x5fac3e01, BRF_GRA },
951 { "32j3-0.6", 0x100000, 0xd297925e, BRF_GRA },
952
953 { "32j9-0.76", 0x080000, 0x16001e81, BRF_SND }, // PCM
954 };
955
956 STD_ROM_PICK(shadfrcej)
957 STD_ROM_FN(shadfrcej)
958
959 struct BurnDriver BurnDrvShadfrcej = {
960 "shadfrcej", "shadfrce", NULL, NULL, "1993",
961 "Shadow Force (Japan, Version 2)\0", NULL, "Technos Japan", "Miscellaneous",
962 NULL, NULL, NULL, NULL,
963 BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TECHNOS, GBF_SCRFIGHT, 0,
964 NULL, shadfrcejRomInfo, shadfrcejRomName, NULL, NULL, NULL, NULL, shadfrceInputInfo, shadfrceDIPInfo,
965 shadfrceInit, shadfrceExit, shadfrceFrame, shadfrceDraw, shadfrceScan, &bRecalcPalette, 0x4000,
966 320, 256, 4, 3
967 };
968