1 // Q-Bert emu-layer for FB Alpha by dink, based on the MAME driver by Fabrice Frances & Nicola Salmoria.
2
3 #include "tiles_generic.h"
4 #include "driver.h"
5 #include "nec_intf.h"
6 #include "m6502_intf.h"
7 #include "bitswap.h"
8 #include "dac.h"
9 #include "samples.h"
10
11 //#define QBERT_SOUND_DEBUG
12
13 static UINT8 *AllMem;
14 static UINT8 *MemEnd;
15 static UINT8 *AllRam;
16 static UINT8 *RamEnd;
17 static UINT8 *DrvV20ROM;
18 static UINT8 *Drv6502ROM;
19 static UINT8 *DrvV20RAM;
20 static UINT8 *Drv6502RAM;
21 static UINT8 *DrvVideoRAM;
22 static UINT8 *DrvCharRAM;
23 static UINT8 *DrvSpriteRAM;
24 static UINT8 *DrvPaletteRAM;
25 static UINT8 *DrvCharGFX;
26 static UINT8 *DrvSpriteGFX;
27 static UINT8 *DrvNVRAM;
28 static UINT8 *DrvDummyROM;
29
30 static UINT8 *riot_regs;
31 static UINT8 *riot_ram;
32
33 static UINT8 *background_prio;
34 static UINT8 *spritebank;
35 static UINT8 *soundlatch;
36 static UINT8 *soundcpu_do_nmi;
37
38 static char *vtqueue;
39 static UINT8 *vtqueuepos;
40 static UINT32 *vtqueuetime;
41 static UINT8 *knocker_prev;
42
43 static UINT32 *DrvPalette;
44 static UINT8 DrvRecalc;
45
46 static UINT8 DrvJoy1[8];
47 static UINT8 DrvJoy2[8];
48 static UINT8 DrvFakeInput[8]; // fake inputs for rotate buttons
49
50 static UINT8 DrvDip[2] = { 0, 0 };
51 static UINT8 DrvInput[5];
52 static UINT8 DrvReset;
53
54 static UINT8 game_type = 0; // 0 = qbert, 6 = qbertcub, 4 = mplanets
55
56 static UINT32 nRotateTime[2] = { 0, 0 };
57
58 static struct BurnInputInfo QbertInputList[] = {
59 {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 2, "p1 coin" },
60 {"P1 Start", BIT_DIGITAL, DrvJoy1 + 0, "p1 start" },
61 {"P1 Up", BIT_DIGITAL, DrvJoy2 + 2, "p1 up" },
62 {"P1 Down", BIT_DIGITAL, DrvJoy2 + 3, "p1 down" },
63 {"P1 Left", BIT_DIGITAL, DrvJoy2 + 1, "p1 left" },
64 {"P1 Right", BIT_DIGITAL, DrvJoy2 + 0, "p1 right" },
65
66 {"P2 Coin", BIT_DIGITAL, DrvJoy1 + 3, "p2 coin" },
67 {"P2 Start", BIT_DIGITAL, DrvJoy1 + 1, "p2 start" },
68 {"P2 Up", BIT_DIGITAL, DrvJoy2 + 6, "p2 up" },
69 {"P2 Down", BIT_DIGITAL, DrvJoy2 + 7, "p2 down" },
70 {"P2 Left", BIT_DIGITAL, DrvJoy2 + 5, "p2 left" },
71 {"P2 Right", BIT_DIGITAL, DrvJoy2 + 4, "p2 right" },
72
73 {"Reset", BIT_DIGITAL, &DrvReset, "reset" },
74 {"Select", BIT_DIGITAL, DrvJoy1 + 7, "select" },
75 {"Dip A", BIT_DIPSWITCH, DrvDip + 0, "dip" },
76 {"Dip B", BIT_DIPSWITCH, DrvDip + 1, "dip" },
77 };
78
79 STDINPUTINFO(Qbert)
80
81
82 static struct BurnDIPInfo QbertDIPList[]=
83 {
84 {0x0e, 0xff, 0xff, 0x02, NULL },
85 {0x0f, 0xff, 0xff, 0x40, NULL },
86
87 {0 , 0xfe, 0 , 2, "Demo Sounds" },
88 {0x0e, 0x01, 0x01, 0x01, "Off" },
89 {0x0e, 0x01, 0x01, 0x00, "On" },
90
91 {0 , 0xfe, 0 , 2, "Kicker" },
92 {0x0e, 0x01, 0x02, 0x00, "Off" },
93 {0x0e, 0x01, 0x02, 0x02, "On" },
94
95 {0 , 0xfe, 0 , 2, "Cabinet" },
96 {0x0e, 0x01, 0x04, 0x00, "Upright" },
97 {0x0e, 0x01, 0x04, 0x04, "Cocktail" },
98
99 {0 , 0xfe, 0 , 2, "Auto Round Advance (Cheat)" },
100 {0x0e, 0x01, 0x08, 0x00, "Off" },
101 {0x0e, 0x01, 0x08, 0x08, "On" },
102
103 {0 , 0xfe, 0 , 2, "Free Play" },
104 {0x0e, 0x01, 0x10, 0x00, "Off" },
105 {0x0e, 0x01, 0x10, 0x10, "On" },
106
107 {0 , 0xfe, 0 , 2, "SW5" },
108 {0x0e, 0x01, 0x20, 0x00, "Off" },
109 {0x0e, 0x01, 0x20, 0x20, "On" },
110
111 {0 , 0xfe, 0 , 2, "SW7" },
112 {0x0e, 0x01, 0x40, 0x00, "Off" },
113 {0x0e, 0x01, 0x40, 0x40, "On" },
114
115 {0 , 0xfe, 0 , 2, "SW8" },
116 {0x0e, 0x01, 0x80, 0x00, "Off" },
117 {0x0e, 0x01, 0x80, 0x80, "On" },
118
119 {0 , 0xfe, 0 , 2, "Service" },
120 {0x0f, 0x01, 0x40, 0x40, "Off" },
121 {0x0f, 0x01, 0x40, 0x00, "On" },
122 };
123
124 STDDIPINFO(Qbert)
125
126 static struct BurnInputInfo MplanetsInputList[] = {
127 {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 0, "p1 coin" },
128 {"P1 Start", BIT_DIGITAL, DrvJoy2 + 5, "p1 start" },
129 {"P1 Up", BIT_DIGITAL, DrvJoy2 + 0, "p1 up" },
130 {"P1 Down", BIT_DIGITAL, DrvJoy2 + 2, "p1 down" },
131 {"P1 Left", BIT_DIGITAL, DrvJoy2 + 3, "p1 left" },
132 {"P1 Right", BIT_DIGITAL, DrvJoy2 + 1, "p1 right" },
133 {"P1 Button 1", BIT_DIGITAL, DrvJoy2 + 4, "p1 fire 1" },
134 {"P1 Button 2", BIT_DIGITAL, DrvJoy2 + 7, "p1 fire 2" },
135 {"Rotate Left", BIT_DIGITAL, DrvFakeInput + 0, "p1 rotate left" },
136 {"Rotate Right",BIT_DIGITAL, DrvFakeInput + 1, "p1 rotate right" },
137
138 {"Reset", BIT_DIGITAL, &DrvReset, "reset" },
139 {"Select", BIT_DIGITAL, DrvJoy1 + 6, "select" },
140 {"Dip A", BIT_DIPSWITCH, DrvDip + 0, "dip" },
141 {"Dip B", BIT_DIPSWITCH, DrvDip + 1, "dip" },
142 };
143
144 STDINPUTINFO(Mplanets)
145
146
147 static struct BurnDIPInfo MplanetsDIPList[]=
148 {
149 {0x0C, 0xff, 0xff, 0x00, NULL },
150 {0x0D, 0xff, 0xff, 0x80, NULL },
151
152 {0 , 0xfe, 0 , 2, "Demo Sounds" },
153 {0x0C, 0x01, 0x01, 0x01, "Off" },
154 {0x0C, 0x01, 0x01, 0x00, "On" },
155
156 {0 , 0xfe, 0 , 2, "Bonus Life" },
157 {0x0C, 0x01, 0x02, 0x00, "10000" },
158 {0x0C, 0x01, 0x02, 0x02, "12000" },
159
160 {0 , 0xfe, 0 , 2, "Allow Round Select" },
161 {0x0C, 0x01, 0x08, 0x00, "No" },
162 {0x0C, 0x01, 0x08, 0x08, "Yes" },
163
164 {0 , 0xfe, 0 , 4, "Coinage" },
165 {0x0C, 0x01, 0x14, 0x04, "2 Coins 1 Credit" },
166 {0x0C, 0x01, 0x14, 0x00, "1 Coin 1 Credit" },
167 {0x0C, 0x01, 0x14, 0x10, "1 Coin 2 Credits" },
168 {0x0C, 0x01, 0x14, 0x14, "Free Play" },
169
170 {0 , 0xfe, 0 , 2, "Lives" },
171 {0x0C, 0x01, 0x20, 0x00, "3" },
172 {0x0C, 0x01, 0x20, 0x20, "5" },
173
174 {0 , 0xfe, 0 , 4, "Difficulty" },
175 {0x0C, 0x01, 0xc0, 0x40, "Easy" },
176 {0x0C, 0x01, 0xc0, 0x00, "Medium" },
177 {0x0C, 0x01, 0xc0, 0x80, "Hard" },
178 {0x0C, 0x01, 0xc0, 0xc0, "Hardest" },
179
180 {0 , 0xfe, 0 , 2, "Service" },
181 {0x0D, 0x01, 0x80, 0x80, "Off" },
182 {0x0D, 0x01, 0x80, 0x00, "On" },
183 };
184
185 STDDIPINFO(Mplanets)
186
187 static struct BurnInputInfo QbertqubInputList[] = {
188 {"P1 Coin", BIT_DIGITAL, DrvJoy1 + 3, "p1 coin" },
189 {"P1 Start", BIT_DIGITAL, DrvJoy1 + 0, "p1 start" },
190 {"P1 Up", BIT_DIGITAL, DrvJoy2 + 2, "p1 up" },
191 {"P1 Down", BIT_DIGITAL, DrvJoy2 + 3, "p1 down" },
192 {"P1 Left", BIT_DIGITAL, DrvJoy2 + 1, "p1 left" },
193 {"P1 Right", BIT_DIGITAL, DrvJoy2 + 0, "p1 right" },
194
195 {"Reset", BIT_DIGITAL, &DrvReset, "reset" },
196 {"Select", BIT_DIGITAL, DrvJoy1 + 7, "select" },
197 {"Dip A", BIT_DIPSWITCH, DrvDip + 0, "dip" },
198 {"Dip B", BIT_DIPSWITCH, DrvDip + 1, "dip" },
199 };
200
201 STDINPUTINFO(Qbertqub)
202
203 static struct BurnDIPInfo QbertqubDIPList[]=
204 {
205 {0x08, 0xff, 0xff, 0x00, NULL },
206 {0x09, 0xff, 0xff, 0x40, NULL },
207
208 {0 , 0xfe, 0 , 2, "Demo Sounds" },
209 {0x08, 0x01, 0x08, 0x08, "Off" },
210 {0x08, 0x01, 0x08, 0x00, "On" },
211
212 {0 , 0xfe, 0 , 13, "Coinage" },
213 {0x08, 0x01, 0x35, 0x24, "A 2/1 B 2/1" },
214 {0x08, 0x01, 0x35, 0x14, "A 1/1 B 4/1" },
215 {0x08, 0x01, 0x35, 0x30, "A 1/1 B 3/1" },
216 {0x08, 0x01, 0x35, 0x10, "A 1/1 B 2/1" },
217 {0x08, 0x01, 0x35, 0x00, "A 1/1 B 1/1" },
218 {0x08, 0x01, 0x35, 0x11, "A 2/3 B 2/1" },
219 {0x08, 0x01, 0x35, 0x15, "A 1/2 B 3/1" },
220 {0x08, 0x01, 0x35, 0x20, "A 1/2 B 2/1" },
221 {0x08, 0x01, 0x35, 0x21, "A 1/2 B 1/1" },
222 {0x08, 0x01, 0x35, 0x31, "A 1/2 B 1/5" },
223 {0x08, 0x01, 0x35, 0x04, "A 1/3 B 2/1" },
224 {0x08, 0x01, 0x35, 0x05, "A 1/3 B 1/1" },
225 {0x08, 0x01, 0x35, 0x35, "Free Play" },
226
227 {0 , 0xfe, 0 , 2, "1st Bonus Life" },
228 {0x08, 0x01, 0x02, 0x00, "10000" },
229 {0x08, 0x01, 0x02, 0x02, "15000" },
230
231 {0 , 0xfe, 0 , 2, "Additional Bonus Life" },
232 {0x08, 0x01, 0x40, 0x00, "20000" },
233 {0x08, 0x01, 0x40, 0x40, "25000" },
234
235 {0 , 0xfe, 0 , 2, "Difficulty" },
236 {0x08, 0x01, 0x80, 0x00, "Normal" },
237 {0x08, 0x01, 0x80, 0x80, "Hard" },
238
239 {0 , 0xfe, 0 , 2, "Service" },
240 {0x09, 0x01, 0x40, 0x40, "Off" },
241 {0x09, 0x01, 0x40, 0x00, "On" },
242
243 };
244
STDDIPINFO(Qbertqub)245 STDDIPINFO(Qbertqub)
246
247 static UINT8 dialRotation(int addy) {
248 if (nRotateTime[addy] > nCurrentFrame) nRotateTime[addy] = 0; // Bugfix: no rotate after savestate
249
250 if (DrvFakeInput[0] && (nCurrentFrame > nRotateTime[addy]+2)) {
251 nRotateTime[addy] = nCurrentFrame;
252
253 return 0xfe;
254 }
255 if (DrvFakeInput[1] && (nCurrentFrame > nRotateTime[addy]+2)) {
256 nRotateTime[addy] = nCurrentFrame;
257
258 return 2;
259 }
260
261 return 0;
262 }
263
gottlieb_paletteram_w(UINT16 offset,UINT8 data)264 static void gottlieb_paletteram_w(UINT16 offset, UINT8 data)
265 {
266 INT32 bit0, bit1, bit2, bit3;
267 INT32 r, g, b, val;
268
269 DrvPaletteRAM[offset] = data;
270
271 /* red component */
272
273 val = DrvPaletteRAM[offset | 1];
274
275 bit0 = (val >> 0) & 0x01;
276 bit1 = (val >> 1) & 0x01;
277 bit2 = (val >> 2) & 0x01;
278 bit3 = (val >> 3) & 0x01;
279
280 r = 0x10 * bit0 + 0x21 * bit1 + 0x46 * bit2 + 0x88 * bit3;
281
282 /* green component */
283
284 val = DrvPaletteRAM[offset & ~1];
285
286 bit0 = (val >> 4) & 0x01;
287 bit1 = (val >> 5) & 0x01;
288 bit2 = (val >> 6) & 0x01;
289 bit3 = (val >> 7) & 0x01;
290
291 g = 0x10 * bit0 + 0x21 * bit1 + 0x46 * bit2 + 0x88 * bit3;
292
293 /* blue component */
294
295 val = DrvPaletteRAM[offset & ~1];
296
297 bit0 = (val >> 0) & 0x01;
298 bit1 = (val >> 1) & 0x01;
299 bit2 = (val >> 2) & 0x01;
300 bit3 = (val >> 3) & 0x01;
301
302 b = 0x10 * bit0 + 0x21 * bit1 + 0x46 * bit2 + 0x88 * bit3;
303
304 DrvPalette[offset / 2] = BurnHighCol(r, g, b, 0);
305 }
306
qbert_palette()307 static void qbert_palette()
308 {
309 for (INT32 i = 0; i < 0x20; i++) {
310 gottlieb_paletteram_w(i, DrvPaletteRAM[i]);
311 }
312 }
313
314 static void gottlieb_sh_w(UINT16 offset, UINT8 data); //forward!
315 static void qbert_knocker(UINT8 knock);
316
main_write(UINT32 address,UINT8 data)317 static void __fastcall main_write(UINT32 address, UINT8 data)
318 {
319 address &= 0xffff;
320
321 if ((address & 0xff00) == 0x3700) address &= ~0x700; // mirror handling
322 if ((address & 0xfc00) == 0x3c00) address &= ~0x400;
323 if ((address & 0xffe0) == 0x57e0) address &= ~0x7e0;
324 if ((address & 0xffff) == 0x5ff8) address &= ~0x7f8;
325
326 if (/*address >= 0x0000 &&*/ address <= 0x0fff) {
327 DrvNVRAM[address - 0x0000] = data;
328 return;
329 }
330
331 if (address >= 0x1000 && address <= 0x2fff) {
332 //bprintf(0, _T("drw."));
333 DrvDummyROM[address - 0x1000] = data;
334 return;
335 }
336
337 if (address >= 0x3000 && address <= 0x30ff) {
338 DrvSpriteRAM[address - 0x3000] = data;
339 return;
340 }
341
342 if (address >= 0x3800 && address <= 0x3bff) {
343 DrvVideoRAM[address - 0x3800] = data;
344 return;
345 }
346
347 if (address >= 0x4000 && address <= 0x4fff) {
348 DrvCharRAM[address - 0x4000] = data;
349 return;
350 }
351
352 if (address >= 0x5000 && address <= 0x501f) {
353 gottlieb_paletteram_w(address - 0x5000, data);
354 return;
355 }
356
357 switch (address)
358 {
359 case 0x5802: gottlieb_sh_w(address, data); return;
360 case 0x5803: {
361 *background_prio = data & 0x01;
362 qbert_knocker(data >> 5 & 1);
363 if (game_type == 6) // qbertqub only
364 *spritebank = (data & 0x10) >> 4;
365 return;
366 }
367 }
368 }
369
main_read(UINT32 address)370 static UINT8 __fastcall main_read(UINT32 address)
371 {
372 address &= 0xffff;
373
374 if (address >= 0x6000 && address <= 0xffff) {
375 return DrvV20ROM[address - 0x6000];
376 }
377
378 if (/*address >= 0x0000 &&*/ address <= 0x0fff) {
379 return DrvNVRAM[address - 0x0000];
380 }
381
382 if (address >= 0x1000 && address <= 0x2fff) {
383 //bprintf(0, _T("drr."));
384 return DrvDummyROM[address - 0x1000];
385 }
386
387 if ((address & 0xff00) == 0x3700) address &= ~0x700;
388 if ((address & 0xfc00) == 0x3c00) address &= ~0x400;
389 if ((address & 0xffe0) == 0x57e0) address &= ~0x7e0;
390 if ((address & 0xffff) == 0x5ff8) address &= ~0x7f8;
391
392 if (address >= 0x3000 && address <= 0x30ff) {
393 return DrvSpriteRAM[address - 0x3000];
394 }
395
396 if (address >= 0x3800 && address <= 0x3bff) {
397 return DrvVideoRAM[address - 0x3800];
398 }
399
400 if (address >= 0x4000 && address <= 0x4fff) {
401 return DrvCharRAM[address - 0x4000];
402 }
403
404 if (address >= 0x5000 && address <= 0x501f) {
405 return DrvPaletteRAM[address - 0x5000];
406 }
407
408
409 switch (address)
410 {
411 case 0x5800: return DrvDip[0];
412 case 0x5801: return DrvInput[0] | DrvDip[1]; // DrvDip[1] (fake-dip) for service mode.
413 case 0x5803: return dialRotation(0);
414 case 0x5804: return DrvInput[1];
415 }
416
417 return 0;
418 }
419
qbert_knocker(UINT8 knock)420 static void qbert_knocker(UINT8 knock)
421 {
422 if (knock & ~*knocker_prev)
423 BurnSamplePlay(44);
424 *knocker_prev = knock;
425 }
426
gottlieb_sh_w(UINT16,UINT8 data)427 static void gottlieb_sh_w(UINT16 /*offset*/, UINT8 data)
428 {
429 static INT32 random_offset = rand()&7;
430 data &= 0x3f;
431
432 if ((data & 0x0f) != 0xf) {
433 #ifdef QBERT_SOUND_DEBUG
434 bprintf(0, _T("data %X.."), data ^ 0x3f);
435 #endif
436 switch (data ^ 0x3f) { // qbert sample player
437 case 17:
438 case 18:
439 case 19:
440 case 20:
441 case 21:
442 BurnSamplePlay(((data^0x3f)-17)*8+random_offset);
443 random_offset = (random_offset+1)&7;
444 break;
445 case 22:
446 BurnSamplePlay(40);
447 break;
448 case 23:
449 BurnSamplePlay(41);
450 break;
451 case 28:
452 BurnSamplePlay(42); // Hello, I'm turned on.
453 break;
454 case 36:
455 BurnSamplePlay(43); // Bye-Bye
456 break;
457 }
458
459 *soundlatch = data;
460
461 M6502SetIRQLine(0, CPU_IRQSTATUS_ACK);
462 M6502Run(10); //CPU_IRQSTATUS_AUTO no workie
463 M6502SetIRQLine(0, CPU_IRQSTATUS_NONE);
464 }
465 }
466
gottlieb_riot_r(UINT16 offset)467 static UINT8 gottlieb_riot_r(UINT16 offset)
468 {
469 switch (offset & 0x1f) {
470 case 0: /* port A */
471 return *soundlatch ^ 0xff; /* invert command */
472 case 2: /* port B */
473 return 0x40; /* say that PB6 is 1 (test SW1 not pressed) */
474 case 5: /* interrupt register */
475 return 0x40; /* say that edge detected on PA7 */
476 default:
477 return riot_regs[offset & 0x1f];
478 }
479 }
480
blank_queue()481 static void blank_queue()
482 {
483 #ifdef QBERT_SOUND_DEBUG
484 bprintf(0, _T("BLANK!{%X}.."), *vtqueuetime);
485 #endif
486 *vtqueuepos = 0;
487 memset(vtqueue, 0, 0x20);
488 *vtqueuetime = GetCurrentFrame();
489 }
490
add_to_queue(UINT8 data)491 static void add_to_queue(UINT8 data)
492 {
493 if (*vtqueuepos > 0x20-1 || (UINT32)GetCurrentFrame() > *vtqueuetime+2)
494 blank_queue();
495 vtqueue[(*vtqueuepos)++] = data;
496 }
497
check_queue()498 static UINT8 check_queue()
499 {
500 if (*vtqueuepos == 24 && !strncmp("\xC1\xE4\xFF\xE7\xE8\xD2\xFC\xFC\xFC\xFC\xFC\xEA\xFF\xF6\xD6\xF3\xD5\xC5\xF5\xF2\xE1\xDB\xF2\xC0", vtqueue, 24)) {
501 blank_queue(); // "Hello, I'm turned on."
502 return 1;
503 }
504
505 return 0;
506 }
507
audio_write(UINT16 address,UINT8 data)508 static void audio_write(UINT16 address, UINT8 data)
509 {
510 address &= 0x7fff; // 15bit addressing
511
512 if (address >= 0x7000 && address <= 0x7fff) {
513 bprintf(0, _T("write to audio ROM @ %X."), address);
514 Drv6502ROM[address - 0x7000] = data;
515 }
516
517 if (/*address >= 0x0000 &&*/ address <= 0x01ff) {
518 riot_ram[address & 0x7f] = data;
519 }
520
521 if (address >= 0x0200 && address <= 0x03ff) {
522 riot_regs[address & 0x1f] = data;
523 }
524
525 switch (address)
526 {
527 case 0x1fff:
528 case 0x1000: {
529 DACWrite(0, data);
530 return;
531 }
532 case 0x2000: {
533 add_to_queue(data);
534 #ifdef QBERT_SOUND_DEBUG
535 bprintf(0, _T("\\x%X"), data); //save
536 #endif
537 switch (check_queue()) {
538 case 1: BurnSamplePlay(42); break; // Say Hello
539 }
540 *soundcpu_do_nmi = 1;
541 return;
542 }
543 }
544 }
545
audio_read(UINT16 address)546 static UINT8 audio_read(UINT16 address)
547 {
548 address &= 0x7fff; // 15bit addressing
549
550 if (address >= 0x7000 && address <= 0x7fff) {
551 return Drv6502ROM[address - 0x7000];
552 }
553
554 if (/*address >= 0x0000 &&*/ address <= 0x01ff) {
555 return riot_ram[address&0x7f];
556 }
557
558 if (address >= 0x0200 && address <= 0x03ff) {
559 return gottlieb_riot_r(address - 0x200);
560 }
561
562 return 0;
563 }
564
DrvSyncDAC()565 static INT32 DrvSyncDAC()
566 {
567 return (INT32)(float)(nBurnSoundLen * (M6502TotalCycles() / ((3579545.0000/4) / (nBurnFPS / 100.0000))));
568 }
569
DrvDoReset()570 static INT32 DrvDoReset()
571 {
572 memset (AllRam, 0, RamEnd - AllRam);
573
574 VezOpen(0);
575 VezReset();
576 VezClose();
577
578 M6502Open(0);
579 M6502Reset();
580 M6502Close();
581
582 DACReset();
583 BurnSampleReset();
584
585 nRotateTime[0] = 0;
586 nRotateTime[1] = 0;
587
588 return 0;
589 }
590
591
MemIndex()592 static INT32 MemIndex()
593 {
594 UINT8 *Next; Next = AllMem;
595
596 DrvV20ROM = Next; Next += 0x10000;
597 Drv6502ROM = Next; Next += 0x10000;
598
599 DrvPalette = (UINT32*)Next; Next += 0x10 * sizeof(UINT32);
600 DrvCharGFX = Next; Next += 0x40000;
601 DrvSpriteGFX = Next; Next += 0x40000;
602
603 DrvNVRAM = Next; Next += 0x01000; // Keep in ROM section.
604
605 AllRam = Next;
606
607 DrvV20RAM = Next; Next += 0x01000;
608 Drv6502RAM = Next; Next += 0x01000;
609
610 DrvVideoRAM = Next; Next += 0x00400;
611 DrvCharRAM = Next; Next += 0x01000;
612 DrvSpriteRAM = Next; Next += 0x00100;
613 DrvPaletteRAM = Next; Next += 0x00040;
614 DrvDummyROM = Next; Next += 0x02000; // it's RAM, too.
615
616 riot_regs = Next; Next += 0x00020;
617 riot_ram = Next; Next += 0x00200;
618
619 vtqueuepos = Next; Next += 0x00001;
620 vtqueuetime = (UINT32 *)Next; Next += 0x00004;
621 vtqueue = (char *)Next; Next += 0x00020;
622 knocker_prev = Next; Next += 0x00001;
623
624 background_prio = Next; Next += 0x00001;
625 spritebank = Next; Next += 0x00001;
626 soundlatch = Next; Next += 0x00001;
627 soundcpu_do_nmi = Next; Next += 0x00001;
628
629 RamEnd = Next;
630 MemEnd = Next;
631
632 return 0;
633 }
634
DrvInit()635 static INT32 DrvInit()
636 {
637 INT32 c8PlaneOffsets[4] = { 0, 1, 2, 3 };
638 INT32 c8XOffsets[8] = { 0, 4, 8, 12, 16, 20, 24, 28 };
639 INT32 c8YOffsets[8] = { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32 };
640
641 INT32 c16PlaneOffsets[4] = { RGN_FRAC(((game_type == 6) ? 0x10000 : 0x8000), 0, 4), RGN_FRAC(((game_type == 6) ? 0x10000 : 0x8000), 1, 4), RGN_FRAC(((game_type == 6) ? 0x10000 : 0x8000), 2, 4), RGN_FRAC(((game_type == 6) ? 0x10000 : 0x8000), 3, 4) };
642 INT32 c16XOffsets[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
643 INT32 c16YOffsets[16] = { 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16, 8*16, 9*16, 10*16, 11*16, 12*16, 13*16, 14*16, 15*16 };
644 INT32 roffset = 0;
645
646 AllMem = NULL;
647 MemIndex();
648 INT32 nLen = MemEnd - (UINT8 *)0;
649 if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1;
650 memset(AllMem, 0, nLen);
651 MemIndex();
652
653 { // Load ROMS parse GFX
654 UINT8 *DrvTempRom = (UINT8 *)BurnMalloc(0x40000);
655 memset(DrvTempRom, 0, 0x40000);
656 {
657 if (game_type == 0) { // qbert
658 if (BurnLoadRom(DrvV20ROM + 0x4000, 0, 1)) return 1;
659 if (BurnLoadRom(DrvV20ROM + 0x6000, 1, 1)) return 1;
660 if (BurnLoadRom(DrvV20ROM + 0x8000, 2, 1)) return 1;
661 }
662 if (game_type == 4) { // mplanets
663 if (BurnLoadRom(DrvV20ROM + 0x0000, 0, 1)) return 1;
664 if (BurnLoadRom(DrvV20ROM + 0x2000, 1, 1)) return 1;
665 if (BurnLoadRom(DrvV20ROM + 0x4000, 2, 1)) return 1;
666 if (BurnLoadRom(DrvV20ROM + 0x6000, 3, 1)) return 1;
667 if (BurnLoadRom(DrvV20ROM + 0x8000, 4, 1)) return 1;
668 roffset = 2;
669 }
670 if (game_type == 6) { // qbertqub
671 if (BurnLoadRom(DrvV20ROM + 0x2000, 0, 1)) return 1;
672 if (BurnLoadRom(DrvV20ROM + 0x4000, 1, 1)) return 1;
673 if (BurnLoadRom(DrvV20ROM + 0x6000, 2, 1)) return 1;
674 if (BurnLoadRom(DrvV20ROM + 0x8000, 3, 1)) return 1;
675 roffset = 1;
676 }
677
678 if (BurnLoadRom(Drv6502ROM + 0x0000, 3 + roffset, 1)) return 1;
679 if (BurnLoadRom(Drv6502ROM + 0x0800, 4 + roffset, 1)) return 1;
680
681 // load & decode 8x8 tiles
682 memset(DrvTempRom, 0, 0x40000);
683 if (BurnLoadRom(DrvTempRom + 0x0000, 5 + roffset, 1)) return 1;
684 if (BurnLoadRom(DrvTempRom + 0x1000, 6 + roffset, 1)) return 1;
685 GfxDecode(0x100, 4, 8, 8, c8PlaneOffsets, c8XOffsets, c8YOffsets, 0x100, DrvTempRom, DrvCharGFX);
686
687 // load & decode 16x16 tiles
688 memset(DrvTempRom, 0, 0x40000);
689 if (game_type == 6) { // qbertqub
690 if (BurnLoadRom(DrvTempRom + 0x0000, 7 + roffset, 1)) return 1;
691 if (BurnLoadRom(DrvTempRom + 0x4000, 8 + roffset, 1)) return 1;
692 if (BurnLoadRom(DrvTempRom + 0x8000, 9 + roffset, 1)) return 1;
693 if (BurnLoadRom(DrvTempRom + 0xc000, 10 + roffset, 1)) return 1;
694 GfxDecode(0x200 /*((0x10000*8)/4)/(16*16))*/, 4, 16, 16, c16PlaneOffsets, c16XOffsets, c16YOffsets, 0x100, DrvTempRom, DrvSpriteGFX);
695 } else {
696 if (BurnLoadRom(DrvTempRom + 0x0000, 7 + roffset, 1)) return 1;
697 if (BurnLoadRom(DrvTempRom + 0x2000, 8 + roffset, 1)) return 1;
698 if (BurnLoadRom(DrvTempRom + 0x4000, 9 + roffset, 1)) return 1;
699 if (BurnLoadRom(DrvTempRom + 0x6000, 10 + roffset, 1)) return 1;
700 GfxDecode(0x100 /*((0x8000*8)/4)/(16*16))*/, 4, 16, 16, c16PlaneOffsets, c16XOffsets, c16YOffsets, 0x100, DrvTempRom, DrvSpriteGFX);
701 }
702 }
703 BurnFree(DrvTempRom);
704 }
705
706 VezInit(0, V20_TYPE);
707 VezOpen(0);
708
709 memset(DrvNVRAM, 0xff, 0x1000); // Init NVRAM
710
711 //VezMapArea(0x01000, 0x02fff, 0, DrvDummyROM); // ROM for reactor and 3stooges, used as RAM for all other games.
712 //VezMapArea(0x01000, 0x02fff, 1, DrvDummyROM); // note: moved to main_read() / main_write()
713 //VezMapArea(0x01000, 0x02fff, 2, DrvDummyROM);
714 VezSetReadHandler(main_read);
715 VezSetWriteHandler(main_write);
716
717 VezClose();
718
719 M6502Init(0, TYPE_M6502);
720 M6502Open(0);
721 M6502SetWriteHandler(audio_write);
722 M6502SetReadHandler(audio_read);
723 M6502SetReadOpArgHandler(audio_read);
724 M6502SetReadOpHandler(audio_read);
725 M6502Close();
726
727 BurnSampleInit(0);
728 BurnSampleSetAllRoutesAllSamples(0.30, BURN_SND_ROUTE_BOTH);
729
730 DACInit(0, 0, 1, DrvSyncDAC);
731 DACSetRoute(0, 0.35, BURN_SND_ROUTE_BOTH);
732
733 GenericTilesInit();
734
735 DrvDoReset();
736
737 return 0;
738 }
739
740
DrvExit()741 static INT32 DrvExit()
742 {
743 GenericTilesExit();
744
745 VezExit();
746 M6502Exit();
747 DACExit();
748 BurnSampleExit();
749
750 BurnFree(AllMem);
751
752 game_type = 0;
753
754 return 0;
755 }
756
757
RenderTileCPMP(INT32 code,INT32 color,INT32 sx,INT32 sy,INT32 flipx,INT32 flipy,INT32 width,INT32 height,INT32 offset,INT32,UINT8 * gfxrom)758 static void RenderTileCPMP(INT32 code, INT32 color, INT32 sx, INT32 sy, INT32 flipx, INT32 flipy, INT32 width, INT32 height, INT32 offset, INT32 /*mode*/, UINT8 *gfxrom)
759 {
760 UINT16 *dest = pTransDraw;
761 UINT8 *gfx = gfxrom;
762
763 INT32 flip = 0;
764 if (flipy) flip |= (height - 1) * width;
765 if (flipx) flip |= width - 1;
766
767 gfx += code * width * height;
768
769 for (INT32 y = 0; y < height; y++, sy++) {
770 if (sy < 0 || sy >= nScreenHeight) continue;
771
772 for (INT32 x = 0; x < width; x++, sx++) {
773 if (sx < 0 || sx >= nScreenWidth) continue; // blank out the top and bottom 16 pixels for status
774
775 INT32 pxl = gfx[((y * width) + x) ^ flip];
776
777 if (!pxl) continue; // transparency
778
779 dest[sy * nScreenWidth + sx] = pxl | (color << 4) | offset;
780 }
781 sx -= width;
782 }
783 }
784
785
draw_sprites()786 static void draw_sprites()
787 {
788 for (INT32 offs = 0; offs < 0x100 - 8; offs += 4) {
789 INT32 sx = ((DrvSpriteRAM[offs + 1]) - 4) + ((game_type == 4) ? 7 : 0); // mplanets has weird sx/sy offsets
790 INT32 sy = ((DrvSpriteRAM[offs]) - 13) - ((game_type == 4) ? 4 : 0); // apparent in the hiscore table.
791 INT32 code = (255 ^ DrvSpriteRAM[offs + 2]) + 256 * *spritebank;
792
793 if (DrvSpriteRAM[offs] || DrvSpriteRAM[offs + 1])
794 Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, 0, 4, 0, 0x00, DrvSpriteGFX);
795 }
796 }
797
draw_bg()798 static void draw_bg()
799 {
800 INT32 hflip = 0, vflip = 0;
801 for (INT32 offs = 0x3ff; offs >= 0; offs--)
802 {
803 INT32 sx = offs % 32;
804 INT32 sy = offs / 32;
805
806 if (hflip) sx = 31 - sx;
807 if (vflip) sy = 29 - sy;
808
809 INT32 code = DrvVideoRAM[offs];
810 INT32 color = 0;
811
812 sx = 8 * sx;
813 sy = 8 * sy;
814 if (sx >= nScreenWidth) continue;
815 if (sy >= nScreenHeight) continue;
816
817 RenderTileCPMP(code, color, sx, sy, hflip, vflip, 8, 8, 0, 0, DrvCharGFX);
818 }
819 }
820
DrvDraw()821 static INT32 DrvDraw()
822 {
823 if (DrvRecalc) {
824 qbert_palette();
825 DrvRecalc = 0;
826 }
827
828 BurnTransferClear();
829
830 if (nBurnLayer & 2 && !*background_prio) draw_bg();
831 if (nBurnLayer & 4) draw_sprites();
832 if (nBurnLayer & 2 && *background_prio) draw_bg();
833
834 BurnTransferCopy(DrvPalette);
835
836 return 0;
837 }
838
DrvMakeInputs()839 static void DrvMakeInputs()
840 {
841 // Reset Inputs (all active HIGH)
842 DrvInput[0] = 0;
843 DrvInput[1] = 0;
844
845 // Compile Digital Inputs
846 for (INT32 i = 0; i < 8; i++) {
847 DrvInput[0] |= (DrvJoy1[i] & 1) << i;
848 DrvInput[1] |= (DrvJoy2[i] & 1) << i;
849 }
850 }
851
DrvFrame()852 static INT32 DrvFrame()
853 {
854 if (DrvReset) {
855 DrvDoReset();
856 }
857
858 DrvMakeInputs();
859 M6502NewFrame();
860
861 INT32 nInterleave = 256;
862 INT32 nCyclesTotalVez = 5000000 / 60;
863 INT32 nCyclesTotal6502 = (3579545 / 4) / 60;
864
865 VezOpen(0);
866 M6502Open(0);
867 for (INT32 i = 0; i < nInterleave; i++) {
868 M6502Run(nCyclesTotal6502 / nInterleave);
869 if (*soundcpu_do_nmi) {
870 M6502SetIRQLine(M6502_INPUT_LINE_NMI, CPU_IRQSTATUS_AUTO);
871 *soundcpu_do_nmi = 0;
872 }
873
874 VezRun(nCyclesTotalVez / nInterleave);
875 if (i == (nInterleave - 1))
876 VezSetIRQLineAndVector(0x20, 0xff, CPU_IRQSTATUS_AUTO);
877 }
878 VezClose();
879 M6502Close();
880
881 if (pBurnSoundOut) {
882 BurnSampleRender(pBurnSoundOut, nBurnSoundLen);
883 DACUpdate(pBurnSoundOut, nBurnSoundLen);
884 }
885
886 if (pBurnDraw) {
887 DrvDraw();
888 }
889
890 return 0;
891 }
892
DrvScan(INT32 nAction,INT32 * pnMin)893 static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
894 {
895 struct BurnArea ba;
896
897 if (pnMin) {
898 *pnMin = 0x029735;
899 }
900
901 if (nAction & ACB_VOLATILE) {
902 memset(&ba, 0, sizeof(ba));
903 ba.Data = AllRam;
904 ba.nLen = RamEnd - AllRam;
905 ba.szName = "All Ram";
906 BurnAcb(&ba);
907
908 memset(&ba, 0, sizeof(ba)); // savestates get f*cked up, because NVRAM is also used
909 ba.Data = DrvNVRAM; // as regular memory, to fix that we will scan it both here
910 ba.nLen = 0x1000; // and in the NVRAM section.
911 ba.szName = "SSNVRAM"; // note: this is separate from "All Ram" so it doesn't get trashed in DrvDoReset();
912 BurnAcb(&ba);
913
914 VezScan(nAction);
915 M6502Scan(nAction);
916
917 DACScan(nAction, pnMin);
918 BurnSampleScan(nAction, pnMin);
919 }
920
921 if (nAction & ACB_NVRAM) {
922 memset(&ba, 0, sizeof(ba));
923 ba.Data = DrvNVRAM;
924 ba.nLen = 0x1000;
925 ba.szName = "NV RAM";
926 BurnAcb(&ba);
927 }
928
929 return 0;
930 }
931
932 static struct BurnSampleInfo qbertSampleDesc[] = {
933 #if !defined (ROM_VERIFY)
934 {"fx_17a", SAMPLE_NOLOOP },
935 {"fx_17b", SAMPLE_NOLOOP },
936 {"fx_17c", SAMPLE_NOLOOP },
937 {"fx_17d", SAMPLE_NOLOOP },
938 {"fx_17e", SAMPLE_NOLOOP },
939 {"fx_17f", SAMPLE_NOLOOP },
940 {"fx_17g", SAMPLE_NOLOOP },
941 {"fx_17h", SAMPLE_NOLOOP },
942 {"fx_18a", SAMPLE_NOLOOP },
943 {"fx_18b", SAMPLE_NOLOOP },
944 {"fx_18c", SAMPLE_NOLOOP },
945 {"fx_18d", SAMPLE_NOLOOP },
946 {"fx_18e", SAMPLE_NOLOOP },
947 {"fx_18f", SAMPLE_NOLOOP },
948 {"fx_18g", SAMPLE_NOLOOP },
949 {"fx_18h", SAMPLE_NOLOOP },
950 {"fx_19a", SAMPLE_NOLOOP },
951 {"fx_19b", SAMPLE_NOLOOP },
952 {"fx_19c", SAMPLE_NOLOOP },
953 {"fx_19d", SAMPLE_NOLOOP },
954 {"fx_19e", SAMPLE_NOLOOP },
955 {"fx_19f", SAMPLE_NOLOOP },
956 {"fx_19g", SAMPLE_NOLOOP },
957 {"fx_19h", SAMPLE_NOLOOP },
958 {"fx_20a", SAMPLE_NOLOOP },
959 {"fx_20b", SAMPLE_NOLOOP },
960 {"fx_20c", SAMPLE_NOLOOP },
961 {"fx_20d", SAMPLE_NOLOOP },
962 {"fx_20e", SAMPLE_NOLOOP },
963 {"fx_20f", SAMPLE_NOLOOP },
964 {"fx_20g", SAMPLE_NOLOOP },
965 {"fx_20h", SAMPLE_NOLOOP },
966 {"fx_21a", SAMPLE_NOLOOP },
967 {"fx_21b", SAMPLE_NOLOOP },
968 {"fx_21c", SAMPLE_NOLOOP },
969 {"fx_21d", SAMPLE_NOLOOP },
970 {"fx_21e", SAMPLE_NOLOOP },
971 {"fx_21f", SAMPLE_NOLOOP },
972 {"fx_21g", SAMPLE_NOLOOP },
973 {"fx_21h", SAMPLE_NOLOOP },
974 {"fx_22", SAMPLE_NOLOOP },
975 {"fx_23", SAMPLE_NOLOOP },
976 {"fx_28", SAMPLE_NOLOOP },
977 {"fx_36", SAMPLE_NOLOOP },
978 #endif
979 {"knocker", SAMPLE_NOLOOP },
980 {"", 0 }
981 };
982
983 STD_SAMPLE_PICK(qbert)
984 STD_SAMPLE_FN(qbert)
985
986 // Q*bert (US set 1)
987
988 static struct BurnRomInfo qbertRomDesc[] = {
989 { "qb-rom2.bin", 0x2000, 0xfe434526, 1 | BRF_PRG | BRF_ESS }, // 0 maincpu
990 { "qb-rom1.bin", 0x2000, 0x55635447, 1 | BRF_PRG | BRF_ESS }, // 1
991 { "qb-rom0.bin", 0x2000, 0x8e318641, 1 | BRF_PRG | BRF_ESS }, // 2
992
993 { "qb-snd1.bin", 0x0800, 0x15787c07, 2 | BRF_PRG | BRF_ESS }, // 3 audiocpu
994 { "qb-snd2.bin", 0x0800, 0x58437508, 2 | BRF_PRG | BRF_ESS }, // 4
995
996 { "qb-bg0.bin", 0x1000, 0x7a9ba824, 3 | BRF_GRA }, // 5 bgtiles
997 { "qb-bg1.bin", 0x1000, 0x22e5b891, 3 | BRF_GRA }, // 6
998
999 { "qb-fg3.bin", 0x2000, 0xdd436d3a, 4 | BRF_GRA }, // 7 sprites
1000 { "qb-fg2.bin", 0x2000, 0xf69b9483, 4 | BRF_GRA }, // 8
1001 { "qb-fg1.bin", 0x2000, 0x224e8356, 4 | BRF_GRA }, // 9
1002 { "qb-fg0.bin", 0x2000, 0x2f695b85, 4 | BRF_GRA }, // 10
1003 };
1004
1005 STD_ROM_PICK(qbert)
1006 STD_ROM_FN(qbert)
1007
1008 struct BurnDriver BurnDrvQbert = {
1009 "qbert", NULL, NULL, "qbert", "1982",
1010 "Q*bert (US set 1)\0", NULL, "Gottlieb", "Miscellaneous",
1011 NULL, NULL, NULL, NULL,
1012 BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_ACTION, 0,
1013 NULL, qbertRomInfo, qbertRomName, NULL, NULL, qbertSampleInfo, qbertSampleName, QbertInputInfo, QbertDIPInfo,
1014 DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x10,
1015 240, 256, 3, 4
1016 };
1017
1018
1019 // Q*bert (US set 2)
1020
1021 static struct BurnRomInfo qbertaRomDesc[] = {
1022 { "qrom_2.bin", 0x2000, 0xb54a8ffc, 1 | BRF_PRG | BRF_ESS }, // 0 maincpu
1023 { "qrom_1.bin", 0x2000, 0x19d924e3, 1 | BRF_PRG | BRF_ESS }, // 1
1024 { "qrom_0.bin", 0x2000, 0x2e7fad1b, 1 | BRF_PRG | BRF_ESS }, // 2
1025
1026 { "qb-snd1.bin", 0x0800, 0x15787c07, 2 | BRF_PRG | BRF_ESS }, // 3 audiocpu
1027 { "qb-snd2.bin", 0x0800, 0x58437508, 2 | BRF_PRG | BRF_ESS }, // 4
1028
1029 { "qb-bg0.bin", 0x1000, 0x7a9ba824, 3 | BRF_GRA }, // 5 bgtiles
1030 { "qb-bg1.bin", 0x1000, 0x22e5b891, 3 | BRF_GRA }, // 6
1031
1032 { "qb-fg3.bin", 0x2000, 0xdd436d3a, 4 | BRF_GRA }, // 7 sprites
1033 { "qb-fg2.bin", 0x2000, 0xf69b9483, 4 | BRF_GRA }, // 8
1034 { "qb-fg1.bin", 0x2000, 0x224e8356, 4 | BRF_GRA }, // 9
1035 { "qb-fg0.bin", 0x2000, 0x2f695b85, 4 | BRF_GRA }, // 10
1036 };
1037
1038 STD_ROM_PICK(qberta)
1039 STD_ROM_FN(qberta)
1040
1041 struct BurnDriver BurnDrvQberta = {
1042 "qberta", "qbert", NULL, "qbert", "1982",
1043 "Q*bert (US set 2)\0", NULL, "Gottlieb", "Miscellaneous",
1044 NULL, NULL, NULL, NULL,
1045 BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_ACTION, 0,
1046 NULL, qbertaRomInfo, qbertaRomName, NULL, NULL, qbertSampleInfo, qbertSampleName, QbertInputInfo, QbertDIPInfo,
1047 DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x10,
1048 240, 256, 3, 4
1049 };
1050
1051
1052 // Q*bert (Japan)
1053
1054 static struct BurnRomInfo qbertjRomDesc[] = {
1055 { "qbj-rom2.bin", 0x2000, 0x67bb1cb2, 1 | BRF_PRG | BRF_ESS }, // 0 maincpu
1056 { "qbj-rom1.bin", 0x2000, 0xc61216e7, 1 | BRF_PRG | BRF_ESS }, // 1
1057 { "qbj-rom0.bin", 0x2000, 0x69679d5c, 1 | BRF_PRG | BRF_ESS }, // 2
1058
1059 { "qb-snd1.bin", 0x0800, 0x15787c07, 2 | BRF_PRG | BRF_ESS }, // 3 audiocpu
1060 { "qb-snd2.bin", 0x0800, 0x58437508, 2 | BRF_PRG | BRF_ESS }, // 4
1061
1062 { "qb-bg0.bin", 0x1000, 0x7a9ba824, 3 | BRF_GRA }, // 5 bgtiles
1063 { "qb-bg1.bin", 0x1000, 0x22e5b891, 3 | BRF_GRA }, // 6
1064
1065 { "qb-fg3.bin", 0x2000, 0xdd436d3a, 4 | BRF_GRA }, // 7 sprites
1066 { "qb-fg2.bin", 0x2000, 0xf69b9483, 4 | BRF_GRA }, // 8
1067 { "qb-fg1.bin", 0x2000, 0x224e8356, 4 | BRF_GRA }, // 9
1068 { "qb-fg0.bin", 0x2000, 0x2f695b85, 4 | BRF_GRA }, // 10
1069 };
1070
1071 STD_ROM_PICK(qbertj)
1072 STD_ROM_FN(qbertj)
1073
1074 struct BurnDriver BurnDrvQbertj = {
1075 "qbertj", "qbert", NULL, "qbert", "1982",
1076 "Q*bert (Japan)\0", NULL, "Gottlieb (Konami license)", "Miscellaneous",
1077 NULL, NULL, NULL, NULL,
1078 BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_ACTION, 0,
1079 NULL, qbertjRomInfo, qbertjRomName, NULL, NULL, qbertSampleInfo, qbertSampleName, QbertInputInfo, QbertDIPInfo,
1080 DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x10,
1081 240, 256, 3, 4
1082 };
1083
1084
1085 // Mello Yello Q*bert
1086
1087 static struct BurnRomInfo myqbertRomDesc[] = {
1088 { "mqb-rom2.bin", 0x2000, 0x6860f957, 1 | BRF_PRG | BRF_ESS }, // 0 maincpu
1089 { "mqb-rom1.bin", 0x2000, 0x11f0a4e4, 1 | BRF_PRG | BRF_ESS }, // 1
1090 { "mqb-rom0.bin", 0x2000, 0x12a90cb2, 1 | BRF_PRG | BRF_ESS }, // 2
1091
1092 { "mqb-snd1.bin", 0x0800, 0x495ffcd2, 2 | BRF_PRG | BRF_ESS }, // 3 audiocpu
1093 { "mqb-snd2.bin", 0x0800, 0x9bbaa945, 2 | BRF_PRG | BRF_ESS }, // 4
1094
1095 { "qb-bg0.bin", 0x1000, 0x7a9ba824, 3 | BRF_GRA }, // 5 bgtiles
1096 { "qb-bg1.bin", 0x1000, 0x22e5b891, 3 | BRF_GRA }, // 6
1097
1098 { "mqb-fg3.bin", 0x2000, 0x8b5d0852, 4 | BRF_GRA }, // 7 sprites
1099 { "mqb-fg2.bin", 0x2000, 0x823f1e57, 4 | BRF_GRA }, // 8
1100 { "mqb-fg1.bin", 0x2000, 0x05343ae6, 4 | BRF_GRA }, // 9
1101 { "mqb-fg0.bin", 0x2000, 0xabc71bdd, 4 | BRF_GRA }, // 10
1102 };
1103
1104 STD_ROM_PICK(myqbert)
1105 STD_ROM_FN(myqbert)
1106
1107 struct BurnDriver BurnDrvMyqbert = {
1108 "myqbert", "qbert", NULL, "qbert", "1982",
1109 "Mello Yello Q*bert\0", NULL, "Gottlieb", "Miscellaneous",
1110 NULL, NULL, NULL, NULL,
1111 BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_ACTION, 0,
1112 NULL, myqbertRomInfo, myqbertRomName, NULL, NULL, qbertSampleInfo, qbertSampleName, QbertInputInfo, QbertDIPInfo,
1113 DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x10,
1114 240, 256, 3, 4
1115 };
1116
DrvInitMplanets()1117 static INT32 DrvInitMplanets()
1118 {
1119 game_type = 4;
1120
1121 return DrvInit();
1122 }
1123
1124
1125 // Faster, Harder, More Challenging Q*bert (prototype)
1126
1127 static struct BurnRomInfo sqbertRomDesc[] = {
1128 { "qb-rom2.bin", 0x2000, 0x1e3d4038, 1 | BRF_PRG | BRF_ESS }, // 0 maincpu
1129 { "qb-rom1.bin", 0x2000, 0xeaf3076c, 1 | BRF_PRG | BRF_ESS }, // 1
1130 { "qb-rom0.bin", 0x2000, 0x61260a7e, 1 | BRF_PRG | BRF_ESS }, // 2
1131
1132 { "qb-snd1.bin", 0x0800, 0x15787c07, 2 | BRF_PRG | BRF_ESS }, // 3 audiocpu
1133 { "qb-snd2.bin", 0x0800, 0x58437508, 2 | BRF_PRG | BRF_ESS }, // 4
1134
1135 { "qb-bg0.bin", 0x1000, 0xc3118eef, 3 | BRF_GRA }, // 5 bgtiles
1136 { "qb-bg1.bin", 0x1000, 0x4f6d8075, 3 | BRF_GRA }, // 6
1137
1138 { "qb-fg3.bin", 0x2000, 0xee595eda, 4 | BRF_GRA }, // 7 sprites
1139 { "qb-fg2.bin", 0x2000, 0x59884c78, 4 | BRF_GRA }, // 8
1140 { "qb-fg1.bin", 0x2000, 0x2a60e3ad, 4 | BRF_GRA }, // 9
1141 { "qb-fg0.bin", 0x2000, 0xb11ad9d8, 4 | BRF_GRA }, // 10
1142 };
1143
1144 STD_ROM_PICK(sqbert)
1145 STD_ROM_FN(sqbert)
1146
1147 struct BurnDriver BurnDrvSqbert = {
1148 "sqbert", NULL, NULL, "qbert", "1983",
1149 "Faster, Harder, More Challenging Q*bert (prototype)\0", NULL, "Mylstar", "Miscellaneous",
1150 NULL, NULL, NULL, NULL,
1151 BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_ACTION, 0,
1152 NULL, sqbertRomInfo, sqbertRomName, NULL, NULL, qbertSampleInfo, qbertSampleName, QbertInputInfo, QbertDIPInfo,
1153 DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x10,
1154 240, 256, 3, 4
1155 };
1156
1157 // Mad Planets
1158
1159 static struct BurnRomInfo mplanetsRomDesc[] = {
1160 { "rom4.c16", 0x2000, 0x5402077f, 1 | BRF_PRG | BRF_ESS }, // 0 maincpu
1161 { "rom3.c14-15", 0x2000, 0x5d18d740, 1 | BRF_PRG | BRF_ESS }, // 1
1162 { "rom2.c13-14", 0x2000, 0x960c3bb1, 1 | BRF_PRG | BRF_ESS }, // 2
1163 { "rom1.c12-13", 0x2000, 0xeb515f10, 1 | BRF_PRG | BRF_ESS }, // 3
1164 { "rom0.c11-12", 0x2000, 0x74de78aa, 1 | BRF_PRG | BRF_ESS }, // 4
1165
1166 { "snd1", 0x0800, 0x453193a1, 2 | BRF_PRG | BRF_ESS }, // 5 audiocpu
1167 { "snd2", 0x0800, 0xf5ffc98f, 2 | BRF_PRG | BRF_ESS }, // 6
1168
1169 { "bg0.e11-12", 0x1000, 0x709aa24c, 3 | BRF_GRA }, // 7 bgtiles
1170 { "bg1.e13", 0x1000, 0x4921e345, 3 | BRF_GRA }, // 8
1171
1172 { "fg3.k7-8", 0x2000, 0xc990b39f, 4 | BRF_GRA }, // 9 sprites
1173 { "fg2.k6", 0x2000, 0x735e2522, 4 | BRF_GRA }, // 10
1174 { "fg1.k5", 0x2000, 0x6456cc1c, 4 | BRF_GRA }, // 11
1175 { "fg0.k4", 0x2000, 0xa920e325, 4 | BRF_GRA }, // 12
1176 };
1177
1178 STD_ROM_PICK(mplanets)
1179 STD_ROM_FN(mplanets)
1180
1181 struct BurnDriver BurnDrvMplanets = {
1182 "mplanets", NULL, NULL, NULL, "1983",
1183 "Mad Planets\0", NULL, "Gottlieb", "Miscellaneous",
1184 NULL, NULL, NULL, NULL,
1185 BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0,
1186 NULL, mplanetsRomInfo, mplanetsRomName, NULL, NULL, NULL, NULL, MplanetsInputInfo, MplanetsDIPInfo,
1187 DrvInitMplanets, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x10,
1188 240, 256, 3, 4
1189 };
1190
1191
1192 // Mad Planets (UK)
1193
1194 static struct BurnRomInfo mplanetsukRomDesc[] = {
1195 { "mpt_rom4.bin", 0x2000, 0xcd88e23c, 1 | BRF_PRG | BRF_ESS }, // 0 maincpu
1196 { "mpt_rom3.bin", 0x2000, 0xdc355b2d, 1 | BRF_PRG | BRF_ESS }, // 1
1197 { "mpt_rom2.bin", 0x2000, 0x846ddc23, 1 | BRF_PRG | BRF_ESS }, // 2
1198 { "mpt_rom1.bin", 0x2000, 0x94d67b87, 1 | BRF_PRG | BRF_ESS }, // 3
1199 { "mpt_rom0.bin", 0x2000, 0xa9e30ad2, 1 | BRF_PRG | BRF_ESS }, // 4
1200
1201 { "mpt_snd1.bin", 0x0800, 0x453193a1, 2 | BRF_PRG | BRF_ESS }, // 5 audiocpu
1202 { "mpt_snd2.bin", 0x0800, 0xf5ffc98f, 2 | BRF_PRG | BRF_ESS }, // 6
1203
1204 { "mpt_bg0.bin", 0x1000, 0x709aa24c, 3 | BRF_GRA }, // 7 bgtiles
1205 { "mpt_bg1.bin", 0x1000, 0x4921e345, 3 | BRF_GRA }, // 8
1206
1207 { "mpt_fg3.bin", 0x2000, 0xc990b39f, 4 | BRF_GRA }, // 9 sprites
1208 { "mpt_fg2.bin", 0x2000, 0x735e2522, 4 | BRF_GRA }, // 10
1209 { "mpt_fg1.bin", 0x2000, 0x6456cc1c, 4 | BRF_GRA }, // 11
1210 { "mpt_fg0.bin", 0x2000, 0xa920e325, 4 | BRF_GRA }, // 12
1211 };
1212
1213 STD_ROM_PICK(mplanetsuk)
1214 STD_ROM_FN(mplanetsuk)
1215
1216 struct BurnDriver BurnDrvMplanetsuk = {
1217 "mplanetsuk", "mplanets", NULL, NULL, "1983",
1218 "Mad Planets (UK)\0", NULL, "Gottlieb (Taitel license)", "Miscellaneous",
1219 NULL, NULL, NULL, NULL,
1220 BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0,
1221 NULL, mplanetsukRomInfo, mplanetsukRomName, NULL, NULL, NULL, NULL, MplanetsInputInfo, MplanetsDIPInfo,
1222 DrvInitMplanets, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x10,
1223 240, 256, 3, 4
1224 };
1225
DrvInitCube()1226 static INT32 DrvInitCube()
1227 {
1228 game_type = 6;
1229
1230 return DrvInit();
1231 }
1232
1233 // Q*bert's Qubes
1234
1235 static struct BurnRomInfo qbertqubRomDesc[] = {
1236 { "qq-rom3.bin", 0x2000, 0xc4dbdcd7, 1 | BRF_PRG | BRF_ESS }, // 0 maincpu
1237 { "qq-rom2.bin", 0x2000, 0x21a6c6cc, 1 | BRF_PRG | BRF_ESS }, // 1
1238 { "qq-rom1.bin", 0x2000, 0x63e6c43d, 1 | BRF_PRG | BRF_ESS }, // 2
1239 { "qq-rom0.bin", 0x2000, 0x8ddbe438, 1 | BRF_PRG | BRF_ESS }, // 3
1240
1241 { "qq-snd1.bin", 0x0800, 0xe704b450, 2 | BRF_PRG | BRF_ESS }, // 4 audiocpu
1242 { "qq-snd2.bin", 0x0800, 0xc6a98bf8, 2 | BRF_PRG | BRF_ESS }, // 5
1243
1244 { "qq-bg0.bin", 0x1000, 0x050badde, 3 | BRF_GRA }, // 6 bgtiles
1245 { "qq-bg1.bin", 0x1000, 0x8875902f, 3 | BRF_GRA }, // 7
1246
1247 { "qq-fg3.bin", 0x4000, 0x91a949cc, 4 | BRF_GRA }, // 8 sprites
1248 { "qq-fg2.bin", 0x4000, 0x782d9431, 4 | BRF_GRA }, // 9
1249 { "qq-fg1.bin", 0x4000, 0x71c3ac4c, 4 | BRF_GRA }, // 10
1250 { "qq-fg0.bin", 0x4000, 0x6192853f, 4 | BRF_GRA }, // 11
1251 };
1252
1253 STD_ROM_PICK(qbertqub)
1254 STD_ROM_FN(qbertqub)
1255
1256 struct BurnDriver BurnDrvQbertqub = {
1257 "qbertqub", NULL, NULL, "qbert", "1983",
1258 "Q*bert's Qubes\0", NULL, "Mylstar", "Miscellaneous",
1259 NULL, NULL, NULL, NULL,
1260 BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_PRE90S, GBF_ACTION, 0,
1261 NULL, qbertqubRomInfo, qbertqubRomName, NULL, NULL, qbertSampleInfo, qbertSampleName, QbertqubInputInfo, QbertqubDIPInfo,
1262 DrvInitCube, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x10,
1263 240, 256, 3, 4
1264 };
1265
1266