1 // FB Alpha Bomby Car driver module
2 // Based on MAME driver by Luca Elia
3
4 #include "tiles_generic.h"
5 #include "m68000_intf.h"
6 #include "msm6295.h"
7
8 static UINT8 DrvInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0};
9 static UINT8 DrvInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0};
10 static UINT8 DrvDip[2] = {0, 0};
11 static UINT8 DrvInput[2] = {0x00, 0x00};
12 static UINT8 DrvReset = 0;
13
14 static UINT8 *Mem = NULL;
15 static UINT8 *MemEnd = NULL;
16 static UINT8 *RamStart = NULL;
17 static UINT8 *RamEnd = NULL;
18 static UINT8 *Drv68KRom = NULL;
19 static UINT8 *Drv68KRam = NULL;
20 static UINT8 *DrvVRam0 = NULL;
21 static UINT8 *DrvVRam1 = NULL;
22 static UINT8 *DrvSpriteRam = NULL;
23 static UINT8 *DrvPaletteRam = NULL;
24 static UINT8 *DrvScroll0 = NULL;
25 static UINT8 *DrvScroll1 = NULL;
26 static UINT8 *DrvSprites = NULL;
27 static UINT8 *DrvTempRom = NULL;
28 static UINT32 *DrvPalette = NULL;
29
30 static UINT8 DrvEncrypted = 0;
31 static UINT8 DrvIsWatrball = 0;
32 static UINT8 BlmbyPotWheel = 0;
33 static UINT32 DrvOkiBank = 0;
34 static INT32 DrvToggle = 0;
35
36 static struct BurnInputInfo DrvInputList[] =
37 {
38 {"Coin 1" , BIT_DIGITAL , DrvInputPort0 + 6, "p1 coin" },
39 {"Start 1" , BIT_DIGITAL , DrvInputPort1 + 6, "p1 start" },
40 {"Coin 2" , BIT_DIGITAL , DrvInputPort0 + 7, "p2 coin" },
41 {"Start 2" , BIT_DIGITAL , DrvInputPort1 + 7, "p2 start" },
42
43 {"P1 Up" , BIT_DIGITAL , DrvInputPort0 + 0, "p1 up" },
44 {"P1 Down" , BIT_DIGITAL , DrvInputPort0 + 1, "p1 down" },
45 {"P1 Left" , BIT_DIGITAL , DrvInputPort0 + 3, "p1 left" },
46 {"P1 Right" , BIT_DIGITAL , DrvInputPort0 + 2, "p1 right" },
47 {"P1 Fire 1" , BIT_DIGITAL , DrvInputPort0 + 5, "p1 fire 1" },
48 {"P1 Fire 2" , BIT_DIGITAL , DrvInputPort0 + 4, "p1 fire 2" },
49
50 {"P2 Up" , BIT_DIGITAL , DrvInputPort1 + 0, "p2 up" },
51 {"P2 Down" , BIT_DIGITAL , DrvInputPort1 + 1, "p2 down" },
52 {"P2 Left" , BIT_DIGITAL , DrvInputPort1 + 3, "p2 left" },
53 {"P2 Right" , BIT_DIGITAL , DrvInputPort1 + 2, "p2 right" },
54 {"P2 Fire 1" , BIT_DIGITAL , DrvInputPort1 + 5, "p2 fire 1" },
55 {"P2 Fire 2" , BIT_DIGITAL , DrvInputPort1 + 4, "p2 fire 2" },
56
57 {"Reset" , BIT_DIGITAL , &DrvReset , "reset" },
58 {"Dip 1" , BIT_DIPSWITCH, DrvDip + 0 , "dip" },
59 {"Dip 2" , BIT_DIPSWITCH, DrvDip + 1 , "dip" },
60 };
61
STDINPUTINFO(Drv)62 STDINPUTINFO(Drv)
63
64 static inline void DrvMakeInputs()
65 {
66 DrvInput[0] = DrvInput[1] = 0xff;
67
68 for (INT32 i = 0; i < 8; i++) {
69 DrvInput[0] ^= (DrvInputPort0[i] & 1) << i;
70 DrvInput[1] ^= (DrvInputPort1[i] & 1) << i;
71 }
72 }
73
74 static struct BurnDIPInfo DrvDIPList[]=
75 {
76 // Default Values
77 {0x11, 0xff, 0xff, 0xdf, NULL },
78 {0x12, 0xff, 0xff, 0xff, NULL },
79
80 // Dip 1
81 {0 , 0xfe, 0 , 4 , "Difficulty" },
82 {0x11, 0x01, 0x03, 0x02, "Easy" },
83 {0x11, 0x01, 0x03, 0x03, "Normal" },
84 {0x11, 0x01, 0x03, 0x01, "Hard" },
85 {0x11, 0x01, 0x03, 0x00, "Hardest" },
86
87 {0 , 0xfe, 0 , 2 , "Joysticks" },
88 {0x11, 0x01, 0x04, 0x00, "1" },
89 {0x11, 0x01, 0x04, 0x04, "2" },
90
91 {0 , 0xfe, 0 , 1 , "Controls" },
92 {0x11, 0x01, 0x18, 0x18, "Joystick" },
93
94 {0 , 0xfe, 0 , 2 , "Demo Sounds" },
95 {0x11, 0x01, 0x20, 0x20, "Off" },
96 {0x11, 0x01, 0x20, 0x00, "On" },
97
98 {0 , 0xfe, 0 , 2 , "Service Mode" },
99 {0x11, 0x01, 0x80, 0x80, "Off" },
100 {0x11, 0x01, 0x80, 0x00, "On" },
101
102 // Dip 2
103 {0 , 0xfe, 0 , 8 , "Coin A" },
104 {0x12, 0x01, 0x07, 0x07, "1 Coin 1 Credit" },
105 {0x12, 0x01, 0x07, 0x00, "3 Coins 4 Credits" },
106 {0x12, 0x01, 0x07, 0x01, "2 Coins 3 Credits" },
107 {0x12, 0x01, 0x07, 0x06, "1 Coin 2 Credits" },
108 {0x12, 0x01, 0x07, 0x05, "1 Coin 3 Credits" },
109 {0x12, 0x01, 0x07, 0x04, "1 Coin 4 Credits" },
110 {0x12, 0x01, 0x07, 0x03, "1 Coin 5 Credits" },
111 {0x12, 0x01, 0x07, 0x02, "1 Coin 6 Credits" },
112
113 {0 , 0xfe, 0 , 8 , "Coin B" },
114 {0x12, 0x01, 0x38, 0x10, "6 Coins 1 Credit" },
115 {0x12, 0x01, 0x38, 0x18, "5 Coins 1 Credit" },
116 {0x12, 0x01, 0x38, 0x20, "4 Coins 1 Credit" },
117 {0x12, 0x01, 0x38, 0x28, "3 Coins 1 Credit" },
118 {0x12, 0x01, 0x38, 0x30, "2 Coins 1 Credit" },
119 {0x12, 0x01, 0x38, 0x08, "3 Coins 2 Credits" },
120 {0x12, 0x01, 0x38, 0x00, "4 Coins 3 Credits" },
121 {0x12, 0x01, 0x38, 0x38, "1 Coin 1 Credit" },
122
123 {0 , 0xfe, 0 , 2 , "Credits to Start" },
124 {0x12, 0x01, 0x40, 0x40, "1" },
125 {0x12, 0x01, 0x40, 0x00, "2" },
126
127 {0 , 0xfe, 0 , 2 , "Free Play" },
128 {0x12, 0x01, 0x80, 0x80, "Off" },
129 {0x12, 0x01, 0x80, 0x00, "On" },
130 };
131
132 STDDIPINFO(Drv)
133
134 static struct BurnDIPInfo WatrballDIPList[]=
135 {
136 // Default Values
137 {0x11, 0xff, 0xff, 0xdf, NULL },
138 {0x12, 0xff, 0xff, 0xff, NULL },
139
140 // Dip 1
141 {0 , 0xfe, 0 , 4 , "Difficulty" },
142 {0x11, 0x01, 0x03, 0x02, "Easy" },
143 {0x11, 0x01, 0x03, 0x03, "Normal" },
144 {0x11, 0x01, 0x03, 0x01, "Hard" },
145 {0x11, 0x01, 0x03, 0x00, "Hardest" },
146
147 {0 , 0xfe, 0 , 2 , "Demo Sounds" },
148 {0x11, 0x01, 0x20, 0x20, "Off" },
149 {0x11, 0x01, 0x20, 0x00, "On" },
150
151 {0 , 0xfe, 0 , 2 , "Service Mode" },
152 {0x11, 0x01, 0x80, 0x80, "Off" },
153 {0x11, 0x01, 0x80, 0x00, "On" },
154
155 // Dip 2
156 {0 , 0xfe, 0 , 8 , "Coin A" },
157 {0x12, 0x01, 0x07, 0x07, "1 Coin 1 Credit" },
158 {0x12, 0x01, 0x07, 0x00, "3 Coins 4 Credits" },
159 {0x12, 0x01, 0x07, 0x01, "2 Coins 3 Credits" },
160 {0x12, 0x01, 0x07, 0x06, "1 Coin 2 Credits" },
161 {0x12, 0x01, 0x07, 0x05, "1 Coin 3 Credits" },
162 {0x12, 0x01, 0x07, 0x04, "1 Coin 4 Credits" },
163 {0x12, 0x01, 0x07, 0x03, "1 Coin 5 Credits" },
164 {0x12, 0x01, 0x07, 0x02, "1 Coin 6 Credits" },
165
166 {0 , 0xfe, 0 , 8 , "Coin B" },
167 {0x12, 0x01, 0x38, 0x10, "6 Coins 1 Credit" },
168 {0x12, 0x01, 0x38, 0x18, "5 Coins 1 Credit" },
169 {0x12, 0x01, 0x38, 0x20, "4 Coins 1 Credit" },
170 {0x12, 0x01, 0x38, 0x28, "3 Coins 1 Credit" },
171 {0x12, 0x01, 0x38, 0x30, "2 Coins 1 Credit" },
172 {0x12, 0x01, 0x38, 0x08, "3 Coins 2 Credits" },
173 {0x12, 0x01, 0x38, 0x00, "4 Coins 3 Credits" },
174 {0x12, 0x01, 0x38, 0x38, "1 Coin 1 Credit" },
175 };
176
177 STDDIPINFO(Watrball)
178
179 static struct BurnRomInfo DrvRomDesc[] = {
180 { "bcrom4.bin", 0x80000, 0x06d490ba, BRF_ESS | BRF_PRG }, // 0 68000 Program Code
181 { "bcrom6.bin", 0x80000, 0x33aca664, BRF_ESS | BRF_PRG }, // 1
182
183 { "bc_rom7", 0x80000, 0xe55ca79b, BRF_GRA }, // 2 Sprites
184 { "bc_rom8", 0x80000, 0xcdf38c96, BRF_GRA }, // 3
185 { "bc_rom9", 0x80000, 0x0337ab3d, BRF_GRA }, // 4
186 { "bc_rom10", 0x80000, 0x5458917e, BRF_GRA }, // 5
187
188 { "bc_rom1", 0x80000, 0xac6f8ba1, BRF_SND }, // 6 Samples
189 { "bc_rom2", 0x80000, 0xa4bc31bf, BRF_SND }, // 7
190 };
191
192 STD_ROM_PICK(Drv)
193 STD_ROM_FN(Drv)
194
195 static struct BurnRomInfo DrvuRomDesc[] = {
196 { "bc_rom4", 0x80000, 0x76f054a2, BRF_ESS | BRF_PRG }, // 0 68000 Program Code
197 { "bc_rom6", 0x80000, 0x2570b4c5, BRF_ESS | BRF_PRG }, // 1
198
199 { "bc_rom7", 0x80000, 0xe55ca79b, BRF_GRA }, // 2 Sprites
200 { "bc_rom8", 0x80000, 0xcdf38c96, BRF_GRA }, // 3
201 { "bc_rom9", 0x80000, 0x0337ab3d, BRF_GRA }, // 4
202 { "bc_rom10", 0x80000, 0x5458917e, BRF_GRA }, // 5
203
204 { "bc_rom1", 0x80000, 0xac6f8ba1, BRF_SND }, // 6 Samples
205 { "bc_rom2", 0x80000, 0xa4bc31bf, BRF_SND }, // 7
206 };
207
208 STD_ROM_PICK(Drvu)
209 STD_ROM_FN(Drvu)
210
211 static struct BurnRomInfo WatrballRomDesc[] = {
212 { "rom4.bin", 0x20000, 0xbfbfa720, BRF_ESS | BRF_PRG }, // 0 68000 Program Code
213 { "rom6.bin", 0x20000, 0xacff9b01, BRF_ESS | BRF_PRG }, // 1
214
215 { "rom7.bin", 0x80000, 0xe7e5c311, BRF_GRA }, // 2 Sprites
216 { "rom8.bin", 0x80000, 0xfd27ce6e, BRF_GRA }, // 3
217 { "rom9.bin", 0x80000, 0x122cc0ad, BRF_GRA }, // 4
218 { "rom10.bin", 0x80000, 0x22a2a706, BRF_GRA }, // 5
219
220 { "rom1.bin", 0x80000, 0x7f88dee7, BRF_SND }, // 6 Samples
221 };
222
223 STD_ROM_PICK(Watrball)
STD_ROM_FN(Watrball)224 STD_ROM_FN(Watrball)
225
226 static INT32 MemIndex()
227 {
228 UINT8 *Next; Next = Mem;
229
230 Drv68KRom = Next; Next += 0x100000;
231 MSM6295ROM = Next; Next += 0x100000;
232
233 RamStart = Next;
234
235 Drv68KRam = Next; Next += 0x006000;
236 DrvVRam0 = Next; Next += 0x002000;
237 DrvVRam1 = Next; Next += 0x002000;
238 DrvSpriteRam = Next; Next += 0x002000;
239 DrvPaletteRam = Next; Next += 0x004000;
240 DrvScroll0 = Next; Next += 0x000004;
241 DrvScroll1 = Next; Next += 0x000004;
242
243 RamEnd = Next;
244
245 DrvSprites = Next; Next += 0x4000 * 16 * 16;
246 DrvPalette = (UINT32*)Next; Next += 0x04000 * sizeof(UINT32);
247
248 MemEnd = Next;
249
250 return 0;
251 }
252
DrvDoOkiBank(UINT8 Bank)253 static void DrvDoOkiBank(UINT8 Bank)
254 {
255 DrvOkiBank = Bank;
256 MSM6295SetBank(0, MSM6295ROM + (0x10000 * DrvOkiBank), 0x30000, 0x3ffff);
257 }
258
DrvDoReset()259 static INT32 DrvDoReset()
260 {
261 SekOpen(0);
262 SekReset();
263 SekClose();
264
265 MSM6295Reset(0);
266 DrvDoOkiBank(0);
267
268 BlmbyPotWheel = 0;
269 DrvToggle = 0;
270
271 return 0;
272 }
273
Blmbycar68KReadByte(UINT32 a)274 static UINT8 __fastcall Blmbycar68KReadByte(UINT32 a)
275 {
276 switch (a) {
277 case 0x700006: {
278 return 0x00;
279 }
280
281 case 0x700009: {
282 DrvToggle ^= 0x08;
283 if (DrvIsWatrball) {
284 return DrvToggle & 0xff;
285 }
286 return ((BlmbyPotWheel & 0x80) ? 0x04 : 0x00) | (DrvToggle & 0x08);
287 }
288
289 case 0x70000f: {
290 return MSM6295Read(0);
291 }
292
293 default: {
294 bprintf(PRINT_NORMAL, _T("68K Read byte => %06X\n"), a);
295 }
296 }
297
298 return 0;
299 }
300
Blmbycar68KWriteByte(UINT32 a,UINT8 d)301 static void __fastcall Blmbycar68KWriteByte(UINT32 a, UINT8 d)
302 {
303 if (a >= 0x100000 && a <= 0x103fff) {
304 // ???
305 return;
306 }
307
308 switch (a) {
309 case 0x70000a: {
310 // nop
311 return;
312 }
313
314 case 0x70000d: {
315 DrvDoOkiBank(d & 0x0f);
316 return;
317 }
318
319 default: {
320 bprintf(PRINT_NORMAL, _T("68K Write byte => %06X, %02X\n"), a, d);
321 }
322 }
323 }
324
Blmbycar68KReadWord(UINT32 a)325 static UINT16 __fastcall Blmbycar68KReadWord(UINT32 a)
326 {
327 switch (a) {
328 case 0x700000: {
329 return (DrvDip[1] << 8) | DrvDip[0];
330 }
331
332 case 0x700002: {
333 return (DrvInput[1] << 8) | DrvInput[0];
334 }
335
336 default: {
337 bprintf(PRINT_NORMAL, _T("68K Read word => %06X\n"), a);
338 }
339 }
340
341 return 0;
342 }
343
Blmbycar68KWriteWord(UINT32 a,UINT16 d)344 static void __fastcall Blmbycar68KWriteWord(UINT32 a, UINT16 d)
345 {
346 if (a >= 0x108000 && a <= 0x10bfff) {
347 // ???
348 return;
349 }
350
351 switch (a) {
352 case 0x000020:
353 case 0x000022:
354 return; // ?
355
356 case 0x10c000:
357 case 0x10c002: {
358 UINT16 *RAM = (UINT16*)DrvScroll1;
359 RAM[(a - 0x10c000) >> 1] = BURN_ENDIAN_SWAP_INT16(d);
360 return;
361 }
362
363 case 0x10c004:
364 case 0x10c006: {
365 UINT16 *RAM = (UINT16*)DrvScroll0;
366 RAM[(a - 0x10c004) >> 1] = BURN_ENDIAN_SWAP_INT16(d);
367 return;
368 }
369
370 case 0x70000e: {
371 MSM6295Write(0, d & 0xff);
372 return;
373 }
374
375 default: {
376 bprintf(PRINT_NORMAL, _T("68K Write word => %06X, %04X\n"), a, d);
377 }
378 }
379 }
380
381 static INT32 SpritePlaneOffsets[4] = { RGN_FRAC(0x200000,3,4),RGN_FRAC(0x200000,2,4),RGN_FRAC(0x200000,1,4),RGN_FRAC(0x200000,0,4) };
382 static INT32 SpriteXOffsets[16] = { STEP8(0,1), STEP8(8*8*2,1) };
383 static INT32 SpriteYOffsets[16] = { STEP8(0,8), STEP8(8*8*1,8) };
384
DrvInit()385 static INT32 DrvInit()
386 {
387 INT32 nRet = 0, nLen;
388
389 Mem = NULL;
390 MemIndex();
391 nLen = MemEnd - (UINT8 *)0;
392 if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1;
393 memset(Mem, 0, nLen);
394 MemIndex();
395
396 DrvTempRom = (UINT8 *)BurnMalloc(0x200000);
397
398 nRet = BurnLoadRom(Drv68KRom + 0x000001, 0, 2); if (nRet != 0) return 1;
399 nRet = BurnLoadRom(Drv68KRom + 0x000000, 1, 2); if (nRet != 0) return 1;
400
401 nRet = BurnLoadRom(DrvTempRom + 0x000000, 2, 1); if (nRet != 0) return 1;
402 nRet = BurnLoadRom(DrvTempRom + 0x080000, 3, 1); if (nRet != 0) return 1;
403 nRet = BurnLoadRom(DrvTempRom + 0x100000, 4, 1); if (nRet != 0) return 1;
404 nRet = BurnLoadRom(DrvTempRom + 0x180000, 5, 1); if (nRet != 0) return 1;
405 GfxDecode(0x4000, 4, 16, 16, SpritePlaneOffsets, SpriteXOffsets, SpriteYOffsets, 0x100, DrvTempRom, DrvSprites);
406
407 nRet = BurnLoadRom(MSM6295ROM + 0x000000, 6, 1); if (nRet != 0) return 1;
408 if (!DrvIsWatrball) { nRet = BurnLoadRom(MSM6295ROM + 0x080000, 7, 1); if (nRet != 0) return 1; }
409
410 BurnFree(DrvTempRom);
411
412 if (DrvEncrypted) {
413 UINT16 *RAM = (UINT16*)Drv68KRom;
414 for (INT32 i = 0; i < 0x80000; i++) {
415 UINT16 x = BURN_ENDIAN_SWAP_INT16(RAM[i]);
416 x = (x & ~0x0606) | ((x & 0x0202) << 1) | ((x & 0x0404) >> 1);
417 RAM[i] = BURN_ENDIAN_SWAP_INT16(x);
418 }
419 }
420
421 SekInit(0, 0x68000);
422 SekOpen(0);
423 SekMapMemory(Drv68KRom , 0x000000, 0x0fffff, MAP_ROM);
424 SekMapMemory(DrvVRam1 , 0x104000, 0x105fff, MAP_RAM);
425 SekMapMemory(DrvVRam0 , 0x106000, 0x107fff, MAP_RAM);
426 SekMapMemory(DrvPaletteRam , 0x200000, 0x203fff, MAP_RAM);
427 SekMapMemory(DrvPaletteRam , 0x204000, 0x207fff, MAP_RAM); // mirror
428 SekMapMemory(Drv68KRam + 0x000000, 0x440000, 0x441fff, MAP_RAM);
429 SekMapMemory(DrvSpriteRam , 0x444000, 0x445fff, MAP_RAM);
430 SekMapMemory(Drv68KRam + 0x002000, 0xfec000, 0xfeffff, MAP_RAM);
431 SekSetReadWordHandler(0, Blmbycar68KReadWord);
432 SekSetWriteWordHandler(0, Blmbycar68KWriteWord);
433 SekSetReadByteHandler(0, Blmbycar68KReadByte);
434 SekSetWriteByteHandler(0, Blmbycar68KWriteByte);
435 SekClose();
436
437 MSM6295Init(0, 1056000 / 132, 0);
438 MSM6295SetRoute(0, 1.00, BURN_SND_ROUTE_BOTH);
439 MSM6295SetBank(0, MSM6295ROM, 0, 0x3ffff);
440
441 GenericTilesInit();
442
443 DrvDoReset();
444
445 return 0;
446 }
447
BlmbycarInit()448 static INT32 BlmbycarInit()
449 {
450 DrvEncrypted = 1;
451
452 return DrvInit();
453 }
454
WatrballInit()455 static INT32 WatrballInit()
456 {
457 DrvIsWatrball = 1;
458
459 return DrvInit();
460 }
461
DrvExit()462 static INT32 DrvExit()
463 {
464 SekExit();
465
466 MSM6295Exit(0);
467
468 GenericTilesExit();
469
470 BurnFree(Mem);
471
472 DrvEncrypted = 0;
473 DrvIsWatrball = 0;
474 BlmbyPotWheel = 0;
475 DrvOkiBank = 0;
476 DrvToggle = 0;
477
478 return 0;
479 }
480
pal4bit(UINT8 bits)481 static inline UINT8 pal4bit(UINT8 bits)
482 {
483 bits &= 0x0f;
484 return (bits << 4) | bits;
485 }
486
CalcCol(UINT16 nColour)487 inline static UINT32 CalcCol(UINT16 nColour)
488 {
489 INT32 r, g, b;
490
491 r = pal4bit(nColour >> 4);
492 g = pal4bit(nColour >> 0);
493 b = pal4bit(nColour >> 8);
494
495 return BurnHighCol(r, g, b, 0);
496 }
497
DrvCalcPalette()498 static void DrvCalcPalette()
499 {
500 INT32 i;
501 UINT16* ps;
502 UINT32* pd;
503
504 for (i = 0, ps = (UINT16*)DrvPaletteRam, pd = DrvPalette; i < 0x2000; i++, ps++, pd++) {
505 *pd = CalcCol(BURN_ENDIAN_SWAP_INT16(*ps));
506 }
507 }
508
DrvRenderBgLayer(INT32 RenderCategory)509 static void DrvRenderBgLayer(INT32 RenderCategory)
510 {
511 INT32 mx, my, Attr, Code, Colour, x, y, TileIndex = 0, xFlip, yFlip, Category;
512
513 UINT16 *RAM = (UINT16*)DrvVRam0;
514 UINT16 *ScrollRAM = (UINT16*)DrvScroll0;
515
516 for (my = 0; my < 32; my++) {
517 for (mx = 0; mx < 64; mx++) {
518 Code = BURN_ENDIAN_SWAP_INT16(RAM[(TileIndex << 1) + 0]);
519 Attr = BURN_ENDIAN_SWAP_INT16(RAM[(TileIndex << 1) + 1]);
520 Colour = Attr & 0x1f;
521 xFlip = (Attr >> 6) & 0x01;
522 yFlip = (Attr >> 6) & 0x02;
523 Category = (Attr >> 5) & 0x01;
524
525 if (Category == RenderCategory) {
526 x = 16 * mx;
527 y = 16 * my;
528
529 x -= BURN_ENDIAN_SWAP_INT16(ScrollRAM[1]) & 0x3ff;
530 y -= BURN_ENDIAN_SWAP_INT16(ScrollRAM[0]) & 0x1ff;
531 if (x < -16) x += 1024;
532 if (y < -16) y += 512;
533
534 if (DrvIsWatrball) y -= 16;
535
536 Draw16x16Tile(pTransDraw, Code, x, y, xFlip, yFlip, Colour, 4, 0, DrvSprites);
537 }
538
539 TileIndex++;
540 }
541 }
542 }
543
DrvRenderFgLayer(INT32 RenderCategory)544 static void DrvRenderFgLayer(INT32 RenderCategory)
545 {
546 INT32 mx, my, Attr, Code, Colour, x, y, TileIndex = 0, xFlip, yFlip, Category;
547
548 UINT16 *RAM = (UINT16*)DrvVRam1;
549 UINT16 *ScrollRAM = (UINT16*)DrvScroll1;
550
551 for (my = 0; my < 32; my++) {
552 for (mx = 0; mx < 64; mx++) {
553 Code = BURN_ENDIAN_SWAP_INT16(RAM[(TileIndex << 1) + 0]);
554 Attr = BURN_ENDIAN_SWAP_INT16(RAM[(TileIndex << 1) + 1]);
555 Colour = Attr & 0x1f;
556 xFlip = (Attr >> 6) & 0x01;
557 yFlip = (Attr >> 6) & 0x02;
558 Category = (Attr >> 5) & 0x01;
559
560 if (Category == RenderCategory) {
561 x = 16 * mx;
562 y = 16 * my;
563
564 x -= (BURN_ENDIAN_SWAP_INT16(ScrollRAM[1]) + 5) & 0x3ff;
565 y -= (BURN_ENDIAN_SWAP_INT16(ScrollRAM[0]) + 1) & 0x1ff;
566 if (x < -16) x += 1024;
567 if (y < -16) y += 512;
568
569 if (DrvIsWatrball) y -= 16;
570
571 Draw16x16MaskTile(pTransDraw, Code, x, y, xFlip, yFlip, Colour, 4, 0, 0, DrvSprites);
572 }
573
574 TileIndex++;
575 }
576 }
577 }
578
DrawSprites(INT32 priority)579 static void DrawSprites(INT32 priority)
580 {
581 UINT16 *spriteram = (UINT16*)DrvSpriteRam;
582
583 for (INT32 i = 6/2; i < (0x1000 - 6)/2; i += 4)
584 {
585 INT32 sx = spriteram[i+3] & 0x01ff;
586 INT32 sy = spriteram[i+0];
587 sy = 0xf0 - ((sy & 0xff) - (sy & 0x100));
588
589 INT32 number = spriteram[i+1] & 0x3fff;
590 INT32 color = 0x20 + (spriteram[i+2] & 0x000f);
591 INT32 color_effect = (spriteram[i+3] & 0x4000) >> 14;
592 INT32 attr = (spriteram[i+2] & 0xfe00) >> 9;
593 INT32 xflip = attr & 0x20;
594 INT32 yflip = attr & 0x40;
595
596 if (spriteram[i+0] & 0x8000) break;
597
598 if (((~color >> 3) & 1) != priority) continue;
599
600 if (DrvIsWatrball) sy -= 16;
601
602 if (!color_effect) {
603 Draw16x16MaskTile(pTransDraw, number, sx - 0x0f, sy, xflip, yflip, color, 4, 0, 0, DrvSprites);
604 } else {
605 UINT8 *gfx_src = DrvSprites + ((number & 0x3fff) * 16 * 16);
606
607 for (INT32 py = 0; py < 16; py++)
608 {
609 INT32 ypos = ((sy + py) & 0x1ff);
610 UINT16 *srcy = pTransDraw + (ypos * nScreenWidth);
611
612 INT32 gfx_py = yflip ? (16 - 1 - py) : py;
613
614 if ((ypos < 0) || (ypos >= nScreenHeight)) continue;
615
616 for (INT32 px = 0; px < 16; px++)
617 {
618 INT32 xpos = (((sx + px) & 0x3ff) - 0x0f) & 0x3ff;
619 UINT16 *pixel = srcy + xpos;
620 INT32 src_color = *pixel;
621
622 INT32 gfx_px = xflip ? (16 - 1 - px) : px;
623 INT32 gfx_pen = gfx_src[16*gfx_py + gfx_px];
624
625 if ((gfx_pen < 8) || (gfx_pen >= 16)) continue;
626 if ((xpos < 0) || (xpos >= nScreenWidth)) continue;
627
628 *pixel = src_color + (gfx_pen - 8) * 0x400;
629 }
630 }
631 }
632 }
633 }
634
DrvDraw()635 static INT32 DrvDraw()
636 {
637 BurnTransferClear();
638 DrvCalcPalette();
639 if (nBurnLayer & 0x01) DrvRenderBgLayer(0);
640 if (nBurnLayer & 0x02) DrvRenderBgLayer(1);
641 if (nBurnLayer & 0x04) DrvRenderFgLayer(0);
642 if (nSpriteEnable & 0x01) DrawSprites(0);
643 if (nBurnLayer & 0x08) DrvRenderFgLayer(1);
644 if (nSpriteEnable & 0x02) DrawSprites(1);
645 BurnTransferCopy(DrvPalette);
646
647 return 0;
648 }
649
DrvFrame()650 static INT32 DrvFrame()
651 {
652 INT32 nCyclesTotal = 10000000 / 60;
653
654 if (DrvReset) DrvDoReset();
655
656 DrvMakeInputs();
657
658 SekNewFrame();
659 SekOpen(0);
660 SekRun(nCyclesTotal);
661 SekSetIRQLine(1, CPU_IRQSTATUS_AUTO);
662 SekClose();
663
664 if (pBurnSoundOut) MSM6295Render(0, pBurnSoundOut, nBurnSoundLen);
665
666 if (pBurnDraw) DrvDraw();
667
668 return 0;
669 }
670
DrvScan(INT32 nAction,INT32 * pnMin)671 static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
672 {
673 struct BurnArea ba;
674
675 if (pnMin != NULL) {
676 *pnMin = 0x029717;
677 }
678
679 if (nAction & ACB_MEMORY_RAM) {
680 memset(&ba, 0, sizeof(ba));
681 ba.Data = RamStart;
682 ba.nLen = RamEnd-RamStart;
683 ba.szName = "All Ram";
684 BurnAcb(&ba);
685 }
686
687 if (nAction & ACB_DRIVER_DATA) {
688 SekScan(nAction);
689 MSM6295Scan(nAction, pnMin);
690
691 SCAN_VAR(BlmbyPotWheel);
692 SCAN_VAR(DrvOkiBank);
693 SCAN_VAR(DrvToggle);
694
695 if (nAction & ACB_WRITE) {
696 DrvDoOkiBank(DrvOkiBank);
697 }
698 }
699
700 return 0;
701 }
702
703 struct BurnDriver BurnDrvBlmbycar = {
704 "blmbycar", NULL, NULL, NULL, "1994",
705 "Blomby Car\0", NULL, "ABM & Gecas", "Miscellaneous",
706 NULL, NULL, NULL, NULL,
707 BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_RACING, 0,
708 NULL, DrvRomInfo, DrvRomName, NULL, NULL, NULL, NULL, DrvInputInfo, DrvDIPInfo,
709 BlmbycarInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
710 NULL, 0x2000, 384, 256, 4, 3
711 };
712
713 struct BurnDriver BurnDrvBlmbycaru = {
714 "blmbycaru", "blmbycar", NULL, NULL, "1994",
715 "Blomby Car (not encrypted)\0", NULL, "ABM & Gecas", "Miscellaneous",
716 NULL, NULL, NULL, NULL,
717 BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_RACING, 0,
718 NULL, DrvuRomInfo, DrvuRomName, NULL, NULL, NULL, NULL, DrvInputInfo, DrvDIPInfo,
719 DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
720 NULL, 0x2000, 384, 256, 4, 3
721 };
722
723 struct BurnDriver BurnDrvWatrball = {
724 "watrball", NULL, NULL, NULL, "1996",
725 "Water Balls\0", NULL, "ABM", "Miscellaneous",
726 NULL, NULL, NULL, NULL,
727 BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PUZZLE, 0,
728 NULL, WatrballRomInfo, WatrballRomName, NULL, NULL, NULL, NULL, DrvInputInfo, WatrballDIPInfo,
729 WatrballInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
730 NULL, 0x2000, 384, 240, 4, 3
731 };
732