1 // FB Alpha S.P.Y. driver module
2 // Based on MAME driver by Nicola Salmoria and Acho A. Tang
3
4 #include "tiles_generic.h"
5 #include "z80_intf.h"
6 #include "m6809_intf.h"
7 #include "burn_ym3812.h"
8 #include "konamiic.h"
9 #include "k007232.h"
10
11 static UINT8 *AllMem;
12 static UINT8 *MemEnd;
13 static UINT8 *AllRam;
14 static UINT8 *RamEnd;
15 static UINT8 *DrvM6809ROM;
16 static UINT8 *DrvZ80ROM;
17 static UINT8 *DrvGfxROM0;
18 static UINT8 *DrvGfxROM1;
19 static UINT8 *DrvGfxROMExp0;
20 static UINT8 *DrvGfxROMExp1;
21 static UINT8 *DrvSndROM0;
22 static UINT8 *DrvSndROM1;
23 static UINT8 *DrvBankRAM;
24 static UINT8 *DrvPalRAM;
25 static UINT8 *DrvPMCRAM;
26 static UINT8 *DrvM6809RAM;
27 static UINT8 *DrvZ80RAM;
28
29 static UINT32 *DrvPalette;
30 static UINT8 DrvRecalc;
31
32 static UINT8 *soundlatch;
33
34 static UINT8 *nDrvRomBank;
35
36 static INT32 spy_video_enable;
37 static INT32 Drv3f90old;
38 static INT32 nRamBank;
39
40 static UINT8 DrvJoy1[8];
41 static UINT8 DrvJoy2[8];
42 static UINT8 DrvJoy3[8];
43 static UINT8 DrvDips[8];
44 static UINT8 DrvReset;
45 static UINT8 DrvInputs[3];
46
47 static struct BurnInputInfo SpyInputList[] = {
48 {"P1 Coin", BIT_DIGITAL, DrvJoy3 + 0, "p1 coin" },
49 {"P1 Start", BIT_DIGITAL, DrvJoy1 + 0, "p1 start" },
50 {"P1 Up", BIT_DIGITAL, DrvJoy1 + 1, "p1 up" },
51 {"P1 Down", BIT_DIGITAL, DrvJoy1 + 2, "p1 down" },
52 {"P1 Left", BIT_DIGITAL, DrvJoy1 + 3, "p1 left" },
53 {"P1 Right", BIT_DIGITAL, DrvJoy1 + 4, "p1 right" },
54 {"P1 Button 1", BIT_DIGITAL, DrvJoy1 + 6, "p1 fire 1" },
55 {"P1 Button 2", BIT_DIGITAL, DrvJoy1 + 5, "p1 fire 2" },
56
57 {"P2 Coin", BIT_DIGITAL, DrvJoy3 + 1, "p2 coin" },
58 {"P2 Start", BIT_DIGITAL, DrvJoy2 + 0, "p2 start" },
59 {"P2 Up", BIT_DIGITAL, DrvJoy2 + 1, "p2 up" },
60 {"P2 Down", BIT_DIGITAL, DrvJoy2 + 2, "p2 down" },
61 {"P2 Left", BIT_DIGITAL, DrvJoy2 + 3, "p2 left" },
62 {"P2 Right", BIT_DIGITAL, DrvJoy2 + 4, "p2 right" },
63 {"P2 Button 1", BIT_DIGITAL, DrvJoy2 + 6, "p2 fire 1" },
64 {"P2 Button 2", BIT_DIGITAL, DrvJoy2 + 5, "p2 fire 2" },
65
66 {"Reset", BIT_DIGITAL, &DrvReset, "reset" },
67 {"Service", BIT_DIGITAL, DrvJoy3 + 2, "service" },
68 {"Dip A", BIT_DIPSWITCH, DrvDips + 0, "dip" },
69 {"Dip B", BIT_DIPSWITCH, DrvDips + 1, "dip" },
70 {"Dip C", BIT_DIPSWITCH, DrvDips + 2, "dip" },
71 };
72
73 STDINPUTINFO(Spy)
74
75 static struct BurnDIPInfo SpyDIPList[]=
76 {
77 {0x12, 0xff, 0xff, 0xff, NULL },
78 {0x13, 0xff, 0xff, 0x5e, NULL },
79 {0x14, 0xff, 0xff, 0xf0, NULL },
80
81 {0 , 0xfe, 0 , 16, "Coin A" },
82 {0x12, 0x01, 0x0f, 0x02, "4 Coins 1 Credit" },
83 {0x12, 0x01, 0x0f, 0x05, "3 Coins 1 Credit" },
84 {0x12, 0x01, 0x0f, 0x08, "2 Coins 1 Credit" },
85 {0x12, 0x01, 0x0f, 0x04, "3 Coins 2 Credits" },
86 {0x12, 0x01, 0x0f, 0x01, "4 Coins 3 Credits" },
87 {0x12, 0x01, 0x0f, 0x0f, "1 Coin 1 Credit" },
88 {0x12, 0x01, 0x0f, 0x03, "3 Coins 4 Credits" },
89 {0x12, 0x01, 0x0f, 0x07, "2 Coins 3 Credits" },
90 {0x12, 0x01, 0x0f, 0x0e, "1 Coin 2 Credits" },
91 {0x12, 0x01, 0x0f, 0x06, "2 Coins 5 Credits" },
92 {0x12, 0x01, 0x0f, 0x0d, "1 Coin 3 Credits" },
93 {0x12, 0x01, 0x0f, 0x0c, "1 Coin 4 Credits" },
94 {0x12, 0x01, 0x0f, 0x0b, "1 Coin 5 Credits" },
95 {0x12, 0x01, 0x0f, 0x0a, "1 Coin 6 Credits" },
96 {0x12, 0x01, 0x0f, 0x09, "1 Coin 7 Credits" },
97 {0x12, 0x01, 0x0f, 0x00, "Free Play" },
98
99 {0 , 0xfe, 0 , 15, "Coin B" },
100 {0x12, 0x01, 0xf0, 0x20, "4 Coins 1 Credit" },
101 {0x12, 0x01, 0xf0, 0x50, "3 Coins 1 Credit" },
102 {0x12, 0x01, 0xf0, 0x80, "2 Coins 1 Credit" },
103 {0x12, 0x01, 0xf0, 0x40, "3 Coins 2 Credits" },
104 {0x12, 0x01, 0xf0, 0x10, "4 Coins 3 Credits" },
105 {0x12, 0x01, 0xf0, 0xf0, "1 Coin 1 Credit" },
106 {0x12, 0x01, 0xf0, 0x30, "3 Coins 4 Credits" },
107 {0x12, 0x01, 0xf0, 0x70, "2 Coins 3 Credits" },
108 {0x12, 0x01, 0xf0, 0xe0, "1 Coin 2 Credits" },
109 {0x12, 0x01, 0xf0, 0x60, "2 Coins 5 Credits" },
110 {0x12, 0x01, 0xf0, 0xd0, "1 Coin 3 Credits" },
111 {0x12, 0x01, 0xf0, 0xc0, "1 Coin 4 Credits" },
112 {0x12, 0x01, 0xf0, 0xb0, "1 Coin 5 Credits" },
113 {0x12, 0x01, 0xf0, 0xa0, "1 Coin 6 Credits" },
114 {0x12, 0x01, 0xf0, 0x90, "1 Coin 7 Credits" },
115
116 {0 , 0xfe, 0 , 4, "Lives" },
117 {0x13, 0x01, 0x03, 0x03, "2" },
118 {0x13, 0x01, 0x03, 0x02, "3" },
119 {0x13, 0x01, 0x03, 0x01, "5" },
120 {0x13, 0x01, 0x03, 0x00, "7" },
121
122 {0 , 0xfe, 0 , 4, "Bonus Life" },
123 {0x13, 0x01, 0x18, 0x18, "10k and every 20k" },
124 {0x13, 0x01, 0x18, 0x10, "20k and every 30k" },
125 {0x13, 0x01, 0x18, 0x08, "20k only" },
126 {0x13, 0x01, 0x18, 0x00, "30k only" },
127
128 {0 , 0xfe, 0 , 4, "Difficulty" },
129 {0x13, 0x01, 0x60, 0x60, "Easy" },
130 {0x13, 0x01, 0x60, 0x40, "Normal" },
131 {0x13, 0x01, 0x60, 0x20, "Difficult" },
132 {0x13, 0x01, 0x60, 0x00, "Very Difficult" },
133
134 {0 , 0xfe, 0 , 2, "Demo Sounds" },
135 {0x13, 0x01, 0x80, 0x80, "Off" },
136 {0x13, 0x01, 0x80, 0x00, "On" },
137
138 // {0 , 0xfe, 0 , 2, "Flip Screen" },
139 // {0x14, 0x01, 0x10, 0x10, "Off" },
140 // {0x14, 0x01, 0x10, 0x00, "On" },
141
142 {0 , 0xfe, 0 , 2, "Power" },
143 {0x14, 0x01, 0x20, 0x20, "Normal" },
144 {0x14, 0x01, 0x20, 0x00, "Strong" },
145
146 {0 , 0xfe, 0 , 2, "Service Mode" },
147 {0x14, 0x01, 0x40, 0x40, "Off" },
148 {0x14, 0x01, 0x40, 0x00, "On" },
149
150 {0 , 0xfe, 0 , 2, "Continues" },
151 {0x14, 0x01, 0x80, 0x80, "Unlimited" },
152 {0x14, 0x01, 0x80, 0x00, "5 Times" },
153 };
154
STDDIPINFO(Spy)155 STDDIPINFO(Spy)
156
157 static void DrvSetRAMBank(UINT8 bank, UINT8 data)
158 {
159 nDrvRomBank[1] = bank;
160 nDrvRomBank[2] = data;
161
162 if (data & 0x10) {
163 M6809MapMemory(DrvPalRAM, 0x0000, 0x07ff, MAP_RAM);
164 } else if (data & 0x20) {
165 if (bank & 0x80) {
166 M6809MapMemory(DrvPMCRAM, 0x0000, 0x07ff, MAP_RAM);
167 } else {
168 // unmap
169 M6809MapMemory(DrvM6809ROM + 0x800, 0x0000, 0x07ff, MAP_ROM);
170 M6809MapMemory(DrvM6809ROM + 0x000, 0x0000, 0x07ff, MAP_WRITE);
171 }
172 } else {
173 M6809MapMemory(DrvBankRAM, 0x0000, 0x07ff, MAP_RAM);
174 }
175 }
176
spy_collision()177 static void spy_collision()
178 {
179 #define MAX_SPRITES 64
180 #define DEF_NEAR_PLANE 0x6400
181 #define NEAR_PLANE_ZOOM 0x0100
182 #define FAR_PLANE_ZOOM 0x0000
183 #define pmcram DrvPMCRAM
184
185 INT32 op1, x1, w1, z1, d1, y1, h1;
186 INT32 op2, x2, w2, z2, d2, y2, h2;
187 INT32 mode, i, loopend, nearplane;
188
189 mode = pmcram[0x1];
190 op1 = pmcram[0x2];
191 if (op1 == 1)
192 {
193 x1 = (pmcram[0x3]<<8) + pmcram[0x4];
194 w1 = (pmcram[0x5]<<8) + pmcram[0x6];
195 z1 = (pmcram[0x7]<<8) + pmcram[0x8];
196 d1 = (pmcram[0x9]<<8) + pmcram[0xa];
197 y1 = (pmcram[0xb]<<8) + pmcram[0xc];
198 h1 = (pmcram[0xd]<<8) + pmcram[0xe];
199
200 for (i=16; i<14*MAX_SPRITES + 2; i+=14)
201 {
202 op2 = pmcram[i];
203 if (op2 || mode==0x0c)
204 {
205 x2 = (pmcram[i+0x1]<<8) + pmcram[i+0x2];
206 w2 = (pmcram[i+0x3]<<8) + pmcram[i+0x4];
207 z2 = (pmcram[i+0x5]<<8) + pmcram[i+0x6];
208 d2 = (pmcram[i+0x7]<<8) + pmcram[i+0x8];
209 y2 = (pmcram[i+0x9]<<8) + pmcram[i+0xa];
210 h2 = (pmcram[i+0xb]<<8) + pmcram[i+0xc];
211
212 if (w2==0x58 && d2==0x04 && h2==0x10 && y2==0x30) h2 = y2;
213
214 if ( (abs(x1-x2)<w1+w2) && (abs(z1-z2)<d1+d2) && (abs(y1-y2)<h1+h2) )
215 {
216 pmcram[0xf] = 0;
217 pmcram[i+0xd] = 0;
218 }
219 else
220 pmcram[i+0xd] = 1;
221 }
222 }
223 }
224 else if (op1 > 1)
225 {
226 loopend = (pmcram[0]<<8) + pmcram[1];
227 nearplane = (pmcram[2]<<8) + pmcram[3];
228
229 if (loopend > MAX_SPRITES) loopend = MAX_SPRITES;
230 if (!nearplane) nearplane = DEF_NEAR_PLANE;
231
232 loopend = (loopend<<1) + 4;
233
234 for (i=4; i<loopend; i+=2)
235 {
236 op2 = (pmcram[i]<<8) + pmcram[i+1];
237 op2 = (op2 * (NEAR_PLANE_ZOOM - FAR_PLANE_ZOOM)) / nearplane + FAR_PLANE_ZOOM;
238 pmcram[i] = op2 >> 8;
239 pmcram[i+1] = op2 & 0xff;
240 }
241
242 memset(pmcram+loopend, 0, 0x800-loopend);
243 }
244 }
245
spy_3f90_w(INT32 data)246 static void spy_3f90_w(INT32 data)
247 {
248 K052109RMRDLine = data & 0x04;
249
250 spy_video_enable = (~data & 0x08);
251
252 nRamBank = data & 0xb0;
253
254 DrvSetRAMBank(data & 0x80, data & 0x30);
255
256 if ((data & 0x40) && (~Drv3f90old & 0x40))
257 {
258 spy_collision();
259
260 M6809SetIRQLine(1 /*FIRQ*/, CPU_IRQSTATUS_ACK);
261 M6809Run(105); // delay or the M6809 won't read it...
262 M6809SetIRQLine(1 /*FIRQ*/, CPU_IRQSTATUS_NONE);
263 }
264
265 Drv3f90old = data;
266 }
267
bankswitch(INT32 data)268 static void bankswitch(INT32 data)
269 {
270 nDrvRomBank[0] = data;
271
272 INT32 nBank;
273 if (data & 0x10) {
274 nBank = 0x20000 + (data & 0x06) * 0x1000;
275 } else {
276 nBank = 0x10000 + (data & 0x0e) * 0x1000;
277 }
278
279 M6809MapMemory(DrvM6809ROM + nBank, 0x6000, 0x7fff, MAP_ROM);
280 }
281
spy_main_write(UINT16 address,UINT8 data)282 void spy_main_write(UINT16 address, UINT8 data)
283 {
284 switch (address)
285 {
286 case 0x3f80:
287 bankswitch(data);
288 return;
289
290 case 0x3f90:
291 spy_3f90_w(data);
292 return;
293
294 case 0x3fa0:
295 // watchdog
296 return;
297
298 case 0x3fb0:
299 *soundlatch = data;
300 return;
301
302 case 0x3fc0:
303 ZetSetIRQLine(0, CPU_IRQSTATUS_ACK);
304 return;
305 }
306
307 if (address >= 0x2000 && address <= 0x5fff) {
308 K052109_051960_w(address - 0x2000, data);
309 return;
310 }
311 }
312
spy_main_read(UINT16 address)313 UINT8 spy_main_read(UINT16 address)
314 {
315 switch (address)
316 {
317 case 0x3fd0:
318 return (DrvInputs[2] & 0x0f) | (DrvDips[2] & 0xf0);
319
320 case 0x3fd1:
321 return DrvInputs[0];
322
323 case 0x3fd2:
324 return DrvInputs[1];
325
326 case 0x3fd3:
327 return DrvDips[0];
328
329 case 0x3fe0:
330 return DrvDips[1];
331 }
332
333 if (address >= 0x2000 && address <= 0x5fff) {
334 return K052109_051960_r(address - 0x2000);
335 }
336
337 return 0;
338 }
339
sound_bankswitch(INT32 data)340 static void sound_bankswitch(INT32 data)
341 {
342 INT32 bank_A,bank_B;
343
344 bank_A = (data >> 0) & 0x03;
345 bank_B = (data >> 2) & 0x03;
346 k007232_set_bank(0,bank_A,bank_B);
347
348 bank_A = (data >> 4) & 0x03;
349 bank_B = (data >> 6) & 0x03;
350 k007232_set_bank(1,bank_A,bank_B);
351 }
352
spy_sound_write(UINT16 address,UINT8 data)353 void __fastcall spy_sound_write(UINT16 address, UINT8 data)
354 {
355 if ((address & 0xfff0) == 0xa000) {
356 K007232WriteReg(0, address & 0x0f, data);
357 return;
358 }
359
360 if ((address & 0xfff0) == 0xb000) {
361 K007232WriteReg(1, address & 0x0f, data);
362 return;
363 }
364
365 switch (address)
366 {
367 case 0x9000:
368 sound_bankswitch(data);
369 return;
370
371 case 0xc000:
372 case 0xc001:
373 BurnYM3812Write(0, address & 1, data);
374 return;
375 }
376 }
377
spy_sound_read(UINT16 address)378 UINT8 __fastcall spy_sound_read(UINT16 address)
379 {
380 if ((address & 0xfff0) == 0xa000) {
381 return K007232ReadReg(0, address & 0x0f);
382 }
383
384 if ((address & 0xfff0) == 0xb000) {
385 return K007232ReadReg(1, address & 0x0f);
386 }
387
388 switch (address)
389 {
390 case 0xc000:
391 case 0xc001:
392 return BurnYM3812Read(0, address & 1);
393
394 case 0xd000:
395 ZetSetIRQLine(0, CPU_IRQSTATUS_NONE);
396 return *soundlatch;
397 }
398
399 return 0;
400 }
401
K052109Callback(INT32 layer,INT32 bank,INT32 * code,INT32 * color,INT32 * flags,INT32 *)402 static void K052109Callback(INT32 layer, INT32 bank, INT32 *code, INT32 *color, INT32 *flags, INT32 *)
403 {
404 INT32 colorbase[3] = { 0x30, 0, 0x10 };
405
406 *flags = *color & 0x20;
407 *code |= ((*color & 0x03) << 8) | ((*color & 0x10) << 6) | ((*color & 0x0c) << 9) | (bank << 13);
408 *color = colorbase[layer] + ((*color & 0xc0) >> 6);
409 }
410
K051960Callback(INT32 * code,INT32 * color,INT32 * priority,INT32 *)411 static void K051960Callback(INT32 *code, INT32 *color, INT32 *priority, INT32 *)
412 {
413 *priority = 0x00;
414 if ( *color & 0x10) *priority = 0x0a;
415 if (~*color & 0x20) *priority = 0x0c;
416
417 *color = 0x20 | (*color & 0x0f);
418
419 *code = *code & 0x1fff;
420 }
421
DrvFMIRQHandler(INT32,INT32 nStatus)422 static void DrvFMIRQHandler(INT32, INT32 nStatus)
423 {
424 if (nStatus) ZetNmi();
425 }
426
DrvSynchroniseStream(INT32 nSoundRate)427 inline static INT32 DrvSynchroniseStream(INT32 nSoundRate)
428 {
429 return (INT64)ZetTotalCycles() * nSoundRate / 3579545;
430 }
431
DrvK007232VolCallback0(INT32 v)432 static void DrvK007232VolCallback0(INT32 v)
433 {
434 K007232SetVolume(0, 0, (v >> 4) * 0x11, 0);
435 K007232SetVolume(0, 1, 0, (v & 0x0f) * 0x11);
436 }
437
DrvK007232VolCallback1(INT32 v)438 static void DrvK007232VolCallback1(INT32 v)
439 {
440 K007232SetVolume(1, 0, (v >> 4) * 0x11, 0);
441 K007232SetVolume(1, 1, 0, (v & 0x0f) * 0x11);
442 }
443
DrvDoReset()444 static int DrvDoReset()
445 {
446 DrvReset = 0;
447
448 memset (AllRam, 0, RamEnd - AllRam);
449
450 M6809Open(0);
451 M6809Reset();
452 M6809Close();
453
454 ZetOpen(0);
455 ZetReset();
456 ZetClose();
457
458 KonamiICReset();
459
460 K007232Reset(0);
461 K007232Reset(1);
462 BurnYM3812Reset();
463
464 spy_video_enable = 0;
465 Drv3f90old = 0;
466 nRamBank = 0;
467
468 return 0;
469 }
470
MemIndex()471 static INT32 MemIndex()
472 {
473 UINT8 *Next; Next = AllMem;
474
475 DrvM6809ROM = Next; Next += 0x030000;
476 DrvZ80ROM = Next; Next += 0x010000;
477
478 DrvGfxROM0 = Next; Next += 0x080000;
479 DrvGfxROM1 = Next; Next += 0x100000;
480 DrvGfxROMExp0 = Next; Next += 0x100000;
481 DrvGfxROMExp1 = Next; Next += 0x200000;
482
483 DrvSndROM0 = Next; Next += 0x040000;
484 DrvSndROM1 = Next; Next += 0x040000;
485
486 DrvPalette = (UINT32*)Next; Next += 0x400 * sizeof(UINT32);
487
488 AllRam = Next;
489
490 DrvPMCRAM = Next; Next += 0x000800;
491 DrvBankRAM = Next; Next += 0x000800;
492 DrvPalRAM = Next; Next += 0x000800;
493 DrvM6809RAM = Next; Next += 0x001800;
494
495 DrvZ80RAM = Next; Next += 0x000800;
496
497 soundlatch = Next; Next += 0x000001;
498
499 nDrvRomBank = Next; Next += 0x000003;
500
501 RamEnd = Next;
502 MemEnd = Next;
503
504 return 0;
505 }
506
DrvInit()507 static INT32 DrvInit()
508 {
509 GenericTilesInit();
510
511 AllMem = NULL;
512 MemIndex();
513 INT32 nLen = MemEnd - (UINT8 *)0;
514 if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1;
515 memset(AllMem, 0, nLen);
516 MemIndex();
517
518 {
519 if (BurnLoadRom(DrvM6809ROM + 0x010000, 0, 1)) return 1;
520 if (BurnLoadRom(DrvM6809ROM + 0x020000, 1, 1)) return 1;
521 memcpy (DrvM6809ROM + 0x08000, DrvM6809ROM + 0x28000, 0x8000);
522
523 if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1;
524
525 if (BurnLoadRomExt(DrvGfxROM0 + 0x000000, 3, 4, 2)) return 1;
526 if (BurnLoadRomExt(DrvGfxROM0 + 0x000002, 4, 4, 2)) return 1;
527
528 if (BurnLoadRomExt(DrvGfxROM1 + 0x000000, 5, 4, 2)) return 1;
529 if (BurnLoadRomExt(DrvGfxROM1 + 0x000002, 6, 4, 2)) return 1;
530
531 if (BurnLoadRom(DrvSndROM0 + 0x000000, 7, 1)) return 1;
532
533 if (BurnLoadRom(DrvSndROM1 + 0x000000, 8, 1)) return 1;
534
535 K052109GfxDecode(DrvGfxROM0, DrvGfxROMExp0, 0x080000);
536 K051960GfxDecode(DrvGfxROM1, DrvGfxROMExp1, 0x100000);
537 }
538
539 M6809Init(0);
540 M6809Open(0);
541 M6809MapMemory(DrvM6809RAM, 0x0800, 0x1aff, MAP_RAM);
542 M6809MapMemory(DrvM6809ROM + 0x10000, 0x6000, 0x7fff, MAP_ROM);
543 M6809MapMemory(DrvM6809ROM + 0x08000, 0x8000, 0xffff, MAP_ROM);
544 M6809SetWriteHandler(spy_main_write);
545 M6809SetReadHandler(spy_main_read);
546 M6809Close();
547
548 ZetInit(0);
549 ZetOpen(0);
550 ZetMapArea(0x0000, 0x7fff, 0, DrvZ80ROM);
551 ZetMapArea(0x0000, 0x7fff, 2, DrvZ80ROM);
552 ZetMapArea(0x8000, 0x87ff, 0, DrvZ80RAM);
553 ZetMapArea(0x8000, 0x87ff, 1, DrvZ80RAM);
554 ZetMapArea(0x8000, 0x87ff, 2, DrvZ80RAM);
555 ZetSetWriteHandler(spy_sound_write);
556 ZetSetReadHandler(spy_sound_read);
557 ZetClose();
558
559 K052109Init(DrvGfxROM0, DrvGfxROMExp0, 0x07ffff);
560 K052109SetCallback(K052109Callback);
561 K052109AdjustScroll(-2, 0);
562
563 K051960Init(DrvGfxROM1, DrvGfxROMExp1, 0x0fffff);
564 K051960SetCallback(K051960Callback);
565 K051960SetSpriteOffset(0, 0);
566
567 BurnYM3812Init(1, 3579545, &DrvFMIRQHandler, DrvSynchroniseStream, 0);
568 BurnTimerAttachYM3812(&ZetConfig, 3579545);
569 BurnYM3812SetRoute(0, BURN_SND_YM3812_ROUTE, 1.00, BURN_SND_ROUTE_BOTH);
570
571 K007232Init(0, 3579545, DrvSndROM0, 0x40000);
572 K007232SetPortWriteHandler(0, DrvK007232VolCallback0);
573 K007232PCMSetAllRoutes(0, 0.20, BURN_SND_ROUTE_BOTH);
574
575 K007232Init(1, 3579545, DrvSndROM1, 0x40000);
576 K007232SetPortWriteHandler(1, DrvK007232VolCallback1);
577 K007232PCMSetAllRoutes(1, 0.20, BURN_SND_ROUTE_BOTH);
578
579 DrvDoReset();
580
581 return 0;
582 }
583
DrvExit()584 static INT32 DrvExit()
585 {
586 GenericTilesExit();
587
588 KonamiICExit();
589
590 M6809Exit();
591 ZetExit();
592
593 BurnYM3812Exit();
594
595 K007232Exit();
596
597 BurnFree (AllMem);
598
599 return 0;
600 }
601
DrvDraw()602 static INT32 DrvDraw()
603 {
604 KonamiRecalcPalette(DrvPalRAM, DrvPalette, 0x800);
605
606 K052109UpdateScroll();
607
608 if (spy_video_enable) {
609 K052109RenderLayer(1, K052109_OPAQUE, 1);
610 K052109RenderLayer(2, 0, 2);
611 K051960SpritesRender(-1, -1);
612 K052109RenderLayer(0, 0, 0);
613 } else {
614 KonamiClearBitmaps(DrvPalette[0x300]);
615 }
616
617 KonamiBlendCopy(DrvPalette);
618
619 return 0;
620 }
621
DrvFrame()622 static INT32 DrvFrame()
623 {
624
625 if (DrvReset) {
626 DrvDoReset();
627 }
628
629 ZetNewFrame();
630
631 {
632 memset (DrvInputs, 0xff, 3);
633
634 for (INT32 i = 0 ; i < 8; i++) {
635 DrvInputs[0] ^= (DrvJoy1[i] & 1) << i;
636 DrvInputs[1] ^= (DrvJoy2[i] & 1) << i;
637 DrvInputs[2] ^= (DrvJoy3[i] & 1) << i;
638 }
639
640 if ((DrvInputs[0] & 0x06) == 0) DrvInputs[0] |= 0x06;
641 if ((DrvInputs[0] & 0x18) == 0) DrvInputs[0] |= 0x18;
642 if ((DrvInputs[1] & 0x06) == 0) DrvInputs[1] |= 0x06;
643 if ((DrvInputs[1] & 0x18) == 0) DrvInputs[1] |= 0x18;
644 }
645
646 INT32 nCyclesSegment;
647 INT32 nInterleave = 100;
648 INT32 nCyclesTotal[2] = { (((3000000 / 60) * 133) / 100) /* 33% overclock */, 3579545 / 60 };
649 INT32 nCyclesDone[2] = { 0, 0 };
650
651 M6809Open(0);
652 ZetOpen(0);
653
654 for (INT32 i = 0; i < nInterleave; i++) {
655 nCyclesSegment = (nCyclesTotal[0] / nInterleave) * (i + 1);
656 nCyclesDone[0] += M6809Run(nCyclesSegment - nCyclesDone[0]);
657
658 nCyclesSegment = (nCyclesTotal[1] / nInterleave) * (i + 1);
659 nCyclesDone[1] += BurnTimerUpdateYM3812(nCyclesSegment - nCyclesDone[1]);
660 }
661
662 if (K052109_irq_enabled) M6809SetIRQLine(0, CPU_IRQSTATUS_AUTO);
663
664 BurnTimerEndFrameYM3812(nCyclesTotal[1]);
665
666 if (pBurnSoundOut) {
667 BurnYM3812Update(pBurnSoundOut, nBurnSoundLen);
668 K007232Update(0, pBurnSoundOut, nBurnSoundLen);
669 K007232Update(1, pBurnSoundOut, nBurnSoundLen);
670 }
671
672 ZetClose();
673 M6809Close();
674
675 if (pBurnDraw) {
676 DrvDraw();
677 }
678
679 return 0;
680 }
681
DrvScan(INT32 nAction,INT32 * pnMin)682 static INT32 DrvScan(INT32 nAction,INT32 *pnMin)
683 {
684 struct BurnArea ba;
685
686 if (pnMin) {
687 *pnMin = 0x029705;
688 }
689
690 if (nAction & ACB_VOLATILE) {
691 memset(&ba, 0, sizeof(ba));
692
693 ba.Data = AllRam;
694 ba.nLen = RamEnd - AllRam;
695 ba.szName = "All Ram";
696 BurnAcb(&ba);
697
698 M6809Scan(nAction);
699 ZetScan(nAction);
700
701 BurnYM3812Scan(nAction, pnMin);
702 K007232Scan(nAction, pnMin);
703
704 KonamiICScan(nAction);
705 }
706
707 if (nAction & ACB_DRIVER_DATA) {
708 SCAN_VAR(spy_video_enable);
709 SCAN_VAR(Drv3f90old);
710 SCAN_VAR(nRamBank);
711 }
712
713 if (nAction & ACB_WRITE) {
714 M6809Open(0);
715 bankswitch(nDrvRomBank[0]);
716 DrvSetRAMBank(nDrvRomBank[1], nDrvRomBank[2]);
717 M6809Close();
718 }
719
720 return 0;
721 }
722
723
724 // S.P.Y. - Special Project Y (World ver. N)
725
726 static struct BurnRomInfo spyRomDesc[] = {
727 { "857n03.bin", 0x10000, 0x97993b38, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code
728 { "857n02.bin", 0x10000, 0x31a97efe, 1 | BRF_PRG | BRF_ESS }, // 1
729
730 { "857d01.bin", 0x08000, 0xaad4210f, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code
731
732 { "857b09.bin", 0x40000, 0xb8780966, 3 | BRF_GRA }, // 3 Background Tiles
733 { "857b08.bin", 0x40000, 0x3e4d8d50, 3 | BRF_GRA }, // 4
734
735 { "857b06.bin", 0x80000, 0x7b515fb1, 4 | BRF_GRA }, // 5 Sprites
736 { "857b05.bin", 0x80000, 0x27b0f73b, 4 | BRF_GRA }, // 6
737
738 { "857b07.bin", 0x40000, 0xce3512d4, 5 | BRF_SND }, // 7 K007232 #0 Samples
739
740 { "857b04.bin", 0x40000, 0x20b83c13, 6 | BRF_SND }, // 8 K007232 #1 Samples
741
742 { "857a10.bin", 0x00100, 0x32758507, 7 | BRF_OPT }, // 9 Proms
743 };
744
745 STD_ROM_PICK(spy)
746 STD_ROM_FN(spy)
747
748 struct BurnDriver BurnDrvSpy = {
749 "spy", NULL, NULL, NULL, "1989",
750 "S.P.Y. - Special Project Y (World ver. N)\0", NULL, "Konami", "GX857",
751 NULL, NULL, NULL, NULL,
752 BDF_GAME_WORKING, 2, HARDWARE_PREFIX_KONAMI, GBF_SHOOT, 0,
753 NULL, spyRomInfo, spyRomName, NULL, NULL, NULL, NULL, SpyInputInfo, SpyDIPInfo,
754 DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400,
755 304, 216, 4, 3
756 };
757
758
759 // S.P.Y. - Special Project Y (US ver. M)
760
761 static struct BurnRomInfo spyuRomDesc[] = {
762 { "857m03.bin", 0x10000, 0x3bd87fa4, 1 | BRF_PRG | BRF_ESS }, // 0 Konami Custom Code
763 { "857m02.bin", 0x10000, 0x306cc659, 1 | BRF_PRG | BRF_ESS }, // 1
764
765 { "857d01.bin", 0x08000, 0xaad4210f, 2 | BRF_PRG | BRF_ESS }, // 2 Z80 Code
766
767 { "857b09.bin", 0x40000, 0xb8780966, 3 | BRF_GRA }, // 3 Background Tiles
768 { "857b08.bin", 0x40000, 0x3e4d8d50, 3 | BRF_GRA }, // 4
769
770 { "857b06.bin", 0x80000, 0x7b515fb1, 4 | BRF_GRA }, // 5 Sprites
771 { "857b05.bin", 0x80000, 0x27b0f73b, 4 | BRF_GRA }, // 6
772
773 { "857b07.bin", 0x40000, 0xce3512d4, 5 | BRF_SND }, // 7 K007232 #0 Samples
774
775 { "857b04.bin", 0x40000, 0x20b83c13, 6 | BRF_SND }, // 8 K007232 #1 Samples
776
777 { "857a10.bin", 0x00100, 0x32758507, 7 | BRF_OPT }, // 9 Proms
778 };
779
780 STD_ROM_PICK(spyu)
781 STD_ROM_FN(spyu)
782
783 struct BurnDriver BurnDrvSpyu = {
784 "spyu", "spy", NULL, NULL, "1989",
785 "S.P.Y. - Special Project Y (US ver. M)\0", NULL, "Konami", "GX857",
786 NULL, NULL, NULL, NULL,
787 BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_PREFIX_KONAMI, GBF_SHOOT, 0,
788 NULL, spyuRomInfo, spyuRomName, NULL, NULL, NULL, NULL, SpyInputInfo, SpyDIPInfo,
789 DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x400,
790 304, 216, 4, 3
791 };
792