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