1 // FB Alpha Jackal driver module
2 // Based on MAME driver by Kenneth Lin
3 
4 #include "tiles_generic.h"
5 #include "m6809_intf.h"
6 #include "burn_ym2151.h"
7 
8 static UINT8 *AllMem;
9 static UINT8 *DrvM6809ROM0;
10 static UINT8 *DrvM6809ROM1;
11 static UINT8 *DrvGfxROM0;
12 static UINT8 *DrvGfxROM1;
13 static UINT8 *DrvGfxROM2;
14 static UINT8 *DrvColPROM;
15 static UINT8 *DrvPalRAM;
16 static UINT32 *DrvPaletteTab;
17 static UINT32 *DrvPalette;
18 static UINT8 DrvRecalc;
19 static UINT8 *AllRam;
20 static UINT8 *DrvShareRAM;
21 static UINT8 *DrvSprRAM;
22 static UINT8 *DrvZRAM;
23 static UINT8 *DrvVORAM;
24 static UINT8 *DrvVidControl;
25 static UINT8 *RamEnd;
26 static UINT8 *MemEnd;
27 
28 static INT32 DrvZRAMBank;
29 static INT32 DrvVORAMBank;
30 static INT32 DrvSprRAMBank;
31 static INT32 DrvROMBank;
32 static INT32 DrvIRQEnable;
33 static INT32 flipscreen;
34 
35 static UINT8 DrvJoy1[8];
36 static UINT8 DrvJoy2[8];
37 static UINT8 DrvJoy3[8];
38 static UINT8 DrvInputs[3];
39 static UINT8 DrvDips[3];
40 static UINT8 DrvReset;
41 
42 static INT32 watchdog;
43 static INT32 layer_offset_x = 8;
44 static INT32 layer_offset_y = 16;
45 
46 static INT32 bootleg = 0;
47 
48 //static INT32 nRotate[2] = { 0, 0 };
49 //static UINT32 nRotateTime[2] = { 0, 0 };
50 //static UINT8 DrvFakeInput[4] = { 0, 0, 0, 0 };
51 // Rotation stuff! -dink
52 static UINT8  DrvFakeInput[6]       = {0, 0, 0, 0, 0, 0};
53 static UINT8  nRotateHoldInput[2]   = {0, 0};
54 static INT32  nRotate[2]            = {0, 0};
55 static INT32  nRotateTarget[2]      = {0, 0};
56 static INT32  nRotateTry[2]         = {0, 0};
57 static UINT32 nRotateTime[2]        = {0, 0};
58 static UINT8  game_rotates = 0;
59 
60 static struct BurnInputInfo DrvInputList[] = {
61 	{"P1 Coin",		BIT_DIGITAL,	DrvJoy3 + 0,	"p1 coin"	},
62 	{"P1 Start",		BIT_DIGITAL,	DrvJoy3 + 3,	"p1 start"	},
63 	{"P1 Left",		BIT_DIGITAL,	DrvJoy1 + 0,	"p1 left"	},
64 	{"P1 Right",		BIT_DIGITAL,	DrvJoy1 + 1,	"p1 right"	},
65 	{"P1 Up",		BIT_DIGITAL,	DrvJoy1 + 2,	"p1 up"		},
66 	{"P1 Down",		BIT_DIGITAL,	DrvJoy1 + 3,	"p1 down"	},
67 	{"P1 Button 1",		BIT_DIGITAL,	DrvJoy1 + 4,	"p1 fire 1"	},
68 	{"P1 Button 2",		BIT_DIGITAL,	DrvJoy1 + 5,	"p1 fire 2"	},
69 
70 	{"P2 Coin",		BIT_DIGITAL,	DrvJoy3 + 1,	"p2 coin"	},
71 	{"P2 Start",		BIT_DIGITAL,	DrvJoy3 + 4,	"p2 start"	},
72 	{"P2 Left",		BIT_DIGITAL,	DrvJoy2 + 0,	"p2 left"	},
73 	{"P2 Right",		BIT_DIGITAL,	DrvJoy2 + 1,	"p2 right"	},
74 	{"P2 Up",		BIT_DIGITAL,	DrvJoy2 + 2,	"p2 up"		},
75 	{"P2 Down",		BIT_DIGITAL,	DrvJoy2 + 3,	"p2 down"	},
76 	{"P2 Button 1",		BIT_DIGITAL,	DrvJoy2 + 4,	"p2 fire 1"	},
77 	{"P2 Button 2",		BIT_DIGITAL,	DrvJoy2 + 5,	"p2 fire 2"	},
78 
79 	{"Reset",		BIT_DIGITAL,	&DrvReset,	"reset"		},
80 	{"Service",		BIT_DIGITAL,	DrvJoy3 + 2,	"service"	},
81 	{"Dip A",		BIT_DIPSWITCH,	DrvDips + 0,	"dip"		},
82 	{"Dip B",		BIT_DIPSWITCH,	DrvDips + 1,	"dip"		},
83 	{"Dip C",		BIT_DIPSWITCH,	DrvDips + 2,	"dip"		},
84 };
85 
86 STDINPUTINFO(Drv)
87 
88 static struct BurnInputInfo DrvrotateInputList[] = {
89 	{"P1 Coin",		BIT_DIGITAL,	DrvJoy3 + 0,	"p1 coin"	},
90 	{"P1 Start",		BIT_DIGITAL,	DrvJoy3 + 3,	"p1 start"	},
91 	{"P1 Left",		    BIT_DIGITAL,	DrvJoy1 + 0,	"p1 left"	},
92 	{"P1 Right",		BIT_DIGITAL,	DrvJoy1 + 1,	"p1 right"	},
93 	{"P1 Up",		    BIT_DIGITAL,	DrvJoy1 + 2,	"p1 up"		},
94 	{"P1 Down",		    BIT_DIGITAL,	DrvJoy1 + 3,	"p1 down"	},
95 	{"P1 Button 1",		BIT_DIGITAL,	DrvJoy1 + 4,	"p1 fire 1"	},
96 	{"P1 Button 2",		BIT_DIGITAL,	DrvJoy1 + 5,	"p1 fire 2"	},
97 	{"P1 Rotate Left",     BIT_DIGITAL, DrvFakeInput + 0, "p1 rotate left" },
98 	{"P1 Rotate Right",    BIT_DIGITAL, DrvFakeInput + 1, "p1 rotate right" },
99 	{"P1 Button 3 (rotate)" , BIT_DIGITAL  , DrvFakeInput + 4,  "p1 fire 3" },
100 
101 	{"P2 Coin",		BIT_DIGITAL,	DrvJoy3 + 1,	"p2 coin"	},
102 	{"P2 Start",		BIT_DIGITAL,	DrvJoy3 + 4,	"p2 start"	},
103 	{"P2 Left",		BIT_DIGITAL,	DrvJoy2 + 0,	"p2 left"	},
104 	{"P2 Right",		BIT_DIGITAL,	DrvJoy2 + 1,	"p2 right"	},
105 	{"P2 Up",		BIT_DIGITAL,	DrvJoy2 + 2,	"p2 up"		},
106 	{"P2 Down",		BIT_DIGITAL,	DrvJoy2 + 3,	"p2 down"	},
107 	{"P2 Button 1",		BIT_DIGITAL,	DrvJoy2 + 4,	"p2 fire 1"	},
108 	{"P2 Button 2",		BIT_DIGITAL,	DrvJoy2 + 5,	"p2 fire 2"	},
109 	{"P2 Rotate Left",     BIT_DIGITAL, DrvFakeInput + 2, "p2 rotate left" },
110 	{"P2 Rotate Right",    BIT_DIGITAL, DrvFakeInput + 3, "p2 rotate right" },
111 	{"P2 Button 3 (rotate)" , BIT_DIGITAL  , DrvFakeInput + 5,  "p2 fire 3" },
112 
113 	{"Reset",		BIT_DIGITAL,	&DrvReset,	"reset"		},
114 	{"Service",		BIT_DIGITAL,	DrvJoy3 + 2,	"service"	},
115 	{"Dip A",		BIT_DIPSWITCH,	DrvDips + 0,	"dip"		},
116 	{"Dip B",		BIT_DIPSWITCH,	DrvDips + 1,	"dip"		},
117 	{"Dip C",		BIT_DIPSWITCH,	DrvDips + 2,	"dip"		},
118 };
119 
120 STDINPUTINFO(Drvrotate)
121 
122 static struct BurnDIPInfo DrvDIPList[]=
123 {
124 	{0x12, 0xff, 0xff, 0xff, NULL					},
125 	{0x13, 0xff, 0xff, 0xff, NULL					},
126 	{0x14, 0xff, 0xff, 0x20, NULL					},
127 
128 	{0   , 0xfe, 0   ,   16, "Coin A"				},
129 	{0x12, 0x01, 0x0f, 0x02, "4 Coins 1 Credit"			},
130 	{0x12, 0x01, 0x0f, 0x05, "3 Coins 1 Credit"			},
131 	{0x12, 0x01, 0x0f, 0x06, "2 Coins 1 Credit"			},
132 	{0x12, 0x01, 0x0f, 0x04, "3 Coins 2 Credits"			},
133 	{0x12, 0x01, 0x0f, 0x01, "4 Coins 3 Credits"			},
134 	{0x12, 0x01, 0x0f, 0x0f, "1 Coin  1 Credit"			},
135 	{0x12, 0x01, 0x0f, 0x03, "3 Coins 4 Credits"			},
136 	{0x12, 0x01, 0x0f, 0x07, "2 Coins 3 Credits"			},
137 	{0x12, 0x01, 0x0f, 0x0e, "1 Coin  2 Credits"			},
138 	{0x12, 0x01, 0x0f, 0x06, "2 Coins 5 Credits"			},
139 	{0x12, 0x01, 0x0f, 0x0d, "1 Coin  3 Credits"			},
140 	{0x12, 0x01, 0x0f, 0x0c, "1 Coin  4 Credits"			},
141 	{0x12, 0x01, 0x0f, 0x0b, "1 Coin  5 Credits"			},
142 	{0x12, 0x01, 0x0f, 0x0a, "1 Coin  6 Credits"			},
143 	{0x12, 0x01, 0x0f, 0x09, "1 Coin  7 Credits"			},
144 	{0x12, 0x01, 0x0f, 0x00, "Free Play"				},
145 
146 	{0   , 0xfe, 0   ,   16, "Coin B"				},
147 	{0x12, 0x01, 0xf0, 0x20, "4 Coins 1 Credit"			},
148 	{0x12, 0x01, 0xf0, 0x50, "3 Coins 1 Credit"			},
149 	{0x12, 0x01, 0xf0, 0x60, "2 Coins 1 Credit"			},
150 	{0x12, 0x01, 0xf0, 0x40, "3 Coins 2 Credits"			},
151 	{0x12, 0x01, 0xf0, 0x10, "4 Coins 3 Credits"			},
152 	{0x12, 0x01, 0xf0, 0xf0, "1 Coin  1 Credit"			},
153 	{0x12, 0x01, 0xf0, 0x30, "3 Coins 4 Credits"			},
154 	{0x12, 0x01, 0xf0, 0x70, "2 Coins 3 Credits"			},
155 	{0x12, 0x01, 0xf0, 0xe0, "1 Coin  2 Credits"			},
156 	{0x12, 0x01, 0xf0, 0x60, "2 Coins 5 Credits"			},
157 	{0x12, 0x01, 0xf0, 0xd0, "1 Coin  3 Credits"			},
158 	{0x12, 0x01, 0xf0, 0xc0, "1 Coin  4 Credits"			},
159 	{0x12, 0x01, 0xf0, 0xb0, "1 Coin  5 Credits"			},
160 	{0x12, 0x01, 0xf0, 0xa0, "1 Coin  6 Credits"			},
161 	{0x12, 0x01, 0xf0, 0x90, "1 Coin  7 Credits"			},
162 	{0x12, 0x01, 0xf0, 0x00, "No Coin B"				},
163 
164 	{0   , 0xfe, 0   ,    4, "Lives"				},
165 	{0x13, 0x01, 0x03, 0x03, "2"					},
166 	{0x13, 0x01, 0x03, 0x02, "3"					},
167 	{0x13, 0x01, 0x03, 0x01, "4"					},
168 	{0x13, 0x01, 0x03, 0x00, "7"					},
169 
170 	{0   , 0xfe, 0   ,    4, "Bonus Life"				},
171 	{0x13, 0x01, 0x18, 0x18, "30k 150k"				},
172 	{0x13, 0x01, 0x18, 0x10, "50k 200k"				},
173 	{0x13, 0x01, 0x18, 0x08, "30k"					},
174 	{0x13, 0x01, 0x18, 0x00, "50k"					},
175 
176 	{0   , 0xfe, 0   ,    4, "Difficulty"				},
177 	{0x13, 0x01, 0x60, 0x60, "Easy"					},
178 	{0x13, 0x01, 0x60, 0x40, "Normal"				},
179 	{0x13, 0x01, 0x60, 0x20, "Difficult"				},
180 	{0x13, 0x01, 0x60, 0x00, "Very Difficult"			},
181 
182 	{0   , 0xfe, 0   ,    2, "Demo Sounds"				},
183 	{0x13, 0x01, 0x80, 0x80, "Off"					},
184 	{0x13, 0x01, 0x80, 0x00, "On"					},
185 
186 	{0   , 0xfe, 0   ,    2, "Flip Screen"				},
187 	{0x14, 0x01, 0x20, 0x20, "Off"					},
188 	{0x14, 0x01, 0x20, 0x00, "On"					},
189 
190 	{0   , 0xfe, 0   ,    2, "Sound Adjustment"			},
191 	{0x14, 0x01, 0x40, 0x00, "Upright"				},
192 	{0x14, 0x01, 0x40, 0x40, "Cocktail"				},
193 
194 	{0   , 0xfe, 0   ,    2, "Sound Mode"				},
195 	{0x14, 0x01, 0x80, 0x00, "Stereo"				},
196 	{0x14, 0x01, 0x80, 0x80, "Mono"					},
197 };
198 
199 STDDIPINFO(Drv)
200 
201 static struct BurnDIPInfo DrvrotateDIPList[]=
202 {
203 	{0x18, 0xff, 0xff, 0xff, NULL					},
204 	{0x19, 0xff, 0xff, 0xff, NULL					},
205 	{0x1a, 0xff, 0xff, 0x20, NULL					},
206 
207 	{0   , 0xfe, 0   ,   16, "Coin A"				},
208 	{0x18, 0x01, 0x0f, 0x02, "4 Coins 1 Credit"			},
209 	{0x18, 0x01, 0x0f, 0x05, "3 Coins 1 Credit"			},
210 	{0x18, 0x01, 0x0f, 0x06, "2 Coins 1 Credit"			},
211 	{0x18, 0x01, 0x0f, 0x04, "3 Coins 2 Credits"			},
212 	{0x18, 0x01, 0x0f, 0x01, "4 Coins 3 Credits"			},
213 	{0x18, 0x01, 0x0f, 0x0f, "1 Coin  1 Credit"			},
214 	{0x18, 0x01, 0x0f, 0x03, "3 Coins 4 Credits"			},
215 	{0x18, 0x01, 0x0f, 0x07, "2 Coins 3 Credits"			},
216 	{0x18, 0x01, 0x0f, 0x0e, "1 Coin  2 Credits"			},
217 	{0x18, 0x01, 0x0f, 0x06, "2 Coins 5 Credits"			},
218 	{0x18, 0x01, 0x0f, 0x0d, "1 Coin  3 Credits"			},
219 	{0x18, 0x01, 0x0f, 0x0c, "1 Coin  4 Credits"			},
220 	{0x18, 0x01, 0x0f, 0x0b, "1 Coin  5 Credits"			},
221 	{0x18, 0x01, 0x0f, 0x0a, "1 Coin  6 Credits"			},
222 	{0x18, 0x01, 0x0f, 0x09, "1 Coin  7 Credits"			},
223 	{0x18, 0x01, 0x0f, 0x00, "Free Play"				},
224 
225 	{0   , 0xfe, 0   ,   16, "Coin B"				},
226 	{0x18, 0x01, 0xf0, 0x20, "4 Coins 1 Credit"			},
227 	{0x18, 0x01, 0xf0, 0x50, "3 Coins 1 Credit"			},
228 	{0x18, 0x01, 0xf0, 0x60, "2 Coins 1 Credit"			},
229 	{0x18, 0x01, 0xf0, 0x40, "3 Coins 2 Credits"			},
230 	{0x18, 0x01, 0xf0, 0x10, "4 Coins 3 Credits"			},
231 	{0x18, 0x01, 0xf0, 0xf0, "1 Coin  1 Credit"			},
232 	{0x18, 0x01, 0xf0, 0x30, "3 Coins 4 Credits"			},
233 	{0x18, 0x01, 0xf0, 0x70, "2 Coins 3 Credits"			},
234 	{0x18, 0x01, 0xf0, 0xe0, "1 Coin  2 Credits"			},
235 	{0x18, 0x01, 0xf0, 0x60, "2 Coins 5 Credits"			},
236 	{0x18, 0x01, 0xf0, 0xd0, "1 Coin  3 Credits"			},
237 	{0x18, 0x01, 0xf0, 0xc0, "1 Coin  4 Credits"			},
238 	{0x18, 0x01, 0xf0, 0xb0, "1 Coin  5 Credits"			},
239 	{0x18, 0x01, 0xf0, 0xa0, "1 Coin  6 Credits"			},
240 	{0x18, 0x01, 0xf0, 0x90, "1 Coin  7 Credits"			},
241 	{0x18, 0x01, 0xf0, 0x00, "No Coin B"				},
242 
243 	{0   , 0xfe, 0   ,    4, "Lives"				},
244 	{0x19, 0x01, 0x03, 0x03, "2"					},
245 	{0x19, 0x01, 0x03, 0x02, "3"					},
246 	{0x19, 0x01, 0x03, 0x01, "4"					},
247 	{0x19, 0x01, 0x03, 0x00, "7"					},
248 
249 	{0   , 0xfe, 0   ,    4, "Bonus Life"				},
250 	{0x19, 0x01, 0x18, 0x18, "30k 150k"				},
251 	{0x19, 0x01, 0x18, 0x10, "50k 200k"				},
252 	{0x19, 0x01, 0x18, 0x08, "30k"					},
253 	{0x19, 0x01, 0x18, 0x00, "50k"					},
254 
255 	{0   , 0xfe, 0   ,    4, "Difficulty"				},
256 	{0x19, 0x01, 0x60, 0x60, "Easy"					},
257 	{0x19, 0x01, 0x60, 0x40, "Normal"				},
258 	{0x19, 0x01, 0x60, 0x20, "Difficult"				},
259 	{0x19, 0x01, 0x60, 0x00, "Very Difficult"			},
260 
261 	{0   , 0xfe, 0   ,    2, "Demo Sounds"				},
262 	{0x19, 0x01, 0x80, 0x80, "Off"					},
263 	{0x19, 0x01, 0x80, 0x00, "On"					},
264 
265 	{0   , 0xfe, 0   ,    2, "Flip Screen"				},
266 	{0x1a, 0x01, 0x20, 0x20, "Off"					},
267 	{0x1a, 0x01, 0x20, 0x00, "On"					},
268 
269 	{0   , 0xfe, 0   ,    2, "Sound Adjustment"			},
270 	{0x1a, 0x01, 0x40, 0x00, "Upright"				},
271 	{0x1a, 0x01, 0x40, 0x40, "Cocktail"				},
272 
273 	{0   , 0xfe, 0   ,    2, "Sound Mode"				},
274 	{0x1a, 0x01, 0x80, 0x00, "Stereo"				},
275 	{0x1a, 0x01, 0x80, 0x80, "Mono"					},
276 };
277 
STDDIPINFO(Drvrotate)278 STDDIPINFO(Drvrotate)
279 
280 // Rotation-handler code
281 
282 static void RotateReset() {
283 	for (INT32 playernum = 0; playernum < 2; playernum++) {
284 		nRotate[playernum] = 0; // start out pointing straight up (0=up)
285 		nRotateTarget[playernum] = -1;
286 		nRotateTime[playernum] = 0;
287 		nRotateHoldInput[0] = nRotateHoldInput[1] = 0;
288 	}
289 }
290 
RotationTimer(void)291 static UINT32 RotationTimer(void) {
292     return nCurrentFrame;
293 }
294 
RotateRight(INT32 * v)295 static void RotateRight(INT32 *v) {
296     (*v)++;
297     if (*v > 7) *v = 0;
298 }
299 
RotateLeft(INT32 * v)300 static void RotateLeft(INT32 *v) {
301     (*v)--;
302     if (*v < 0) *v = 7;
303 }
304 
Joy2Rotate(UINT8 * joy)305 static UINT8 Joy2Rotate(UINT8 *joy) { // ugly code, but the effect is awesome. -dink
306 	if (joy[2] && joy[0]) return 7;    // up left
307 	if (joy[2] && joy[1]) return 1;    // up right
308 
309 	if (joy[3] && joy[0]) return 5;    // down left
310 	if (joy[3] && joy[1]) return 3;    // down right
311 
312 	if (joy[2]) return 0;    // up
313 	if (joy[3]) return 4;    // down
314 	if (joy[0]) return 6;    // left
315 	if (joy[1]) return 2;    // right
316 
317 	return 0xff;
318 }
319 
dialRotation(INT32 playernum)320 static int dialRotation(INT32 playernum) {
321     // p1 = 0, p2 = 1
322 	UINT8 player[2] = { 0, 0 };
323 	static UINT8 lastplayer[2][2] = { { 0, 0 }, { 0, 0 } };
324 
325     if ((playernum != 0) && (playernum != 1)) {
326         bprintf(PRINT_NORMAL, _T("Strange Rotation address => %06X\n"), playernum);
327         return 0;
328     }
329     if (playernum == 0) {
330         player[0] = DrvFakeInput[0]; player[1] = DrvFakeInput[1];
331     }
332     if (playernum == 1) {
333         player[0] = DrvFakeInput[2]; player[1] = DrvFakeInput[3];
334     }
335 
336     if (player[0] && (player[0] != lastplayer[playernum][0] || (RotationTimer() > nRotateTime[playernum]+0xf))) {
337 		RotateLeft(&nRotate[playernum]);
338         //bprintf(PRINT_NORMAL, _T("Player %d Rotate Left => %06X\n"), playernum+1, nRotate[playernum]);
339 		nRotateTime[playernum] = RotationTimer();
340 		nRotateTarget[playernum] = -1;
341     }
342 
343 	if (player[1] && (player[1] != lastplayer[playernum][1] || (RotationTimer() > nRotateTime[playernum]+0xf))) {
344         RotateRight(&nRotate[playernum]);
345         //bprintf(PRINT_NORMAL, _T("Player %d Rotate Right => %06X\n"), playernum+1, nRotate[playernum]);
346         nRotateTime[playernum] = RotationTimer();
347 		nRotateTarget[playernum] = -1;
348 	}
349 
350 	lastplayer[playernum][0] = player[0];
351 	lastplayer[playernum][1] = player[1];
352 
353 	return ~(1 << nRotate[playernum]);
354 }
355 
356 static UINT8 *rotate_gunpos[2] = {NULL, NULL};
357 static UINT8 rotate_gunpos_multiplier = 1;
358 
359 // Gun-rotation memory locations - do not remove this tag. - dink :)
360 // game     p1           p2           clockwise value in memory  multiplier
361 // jackal   0xbd8        0xc00        0  1  2  3  4  5  6  7     1
362 // topgunbl SAME
363 
RotateSetGunPosRAM(UINT8 * p1,UINT8 * p2,UINT8 multiplier)364 static void RotateSetGunPosRAM(UINT8 *p1, UINT8 *p2, UINT8 multiplier) {
365 	rotate_gunpos[0] = p1;
366 	rotate_gunpos[1] = p2;
367 	rotate_gunpos_multiplier = multiplier;
368 }
369 
get_distance(INT32 from,INT32 to)370 static INT32 get_distance(INT32 from, INT32 to) {
371 // this function finds the easiest way to get from "from" to "to", wrapping at 0 and 7
372 	INT32 countA = 0;
373 	INT32 countB = 0;
374 	INT32 fromtmp = from / rotate_gunpos_multiplier;
375 	INT32 totmp = to / rotate_gunpos_multiplier;
376 
377 	while (1) {
378 		fromtmp++;
379 		countA++;
380 		if(fromtmp>7) fromtmp = 0;
381 		if(fromtmp == totmp || countA > 32) break;
382 	}
383 
384 	fromtmp = from / rotate_gunpos_multiplier;
385 	totmp = to / rotate_gunpos_multiplier;
386 
387 	while (1) {
388 		fromtmp--;
389 		countB++;
390 		if(fromtmp<0) fromtmp = 7;
391 		if(fromtmp == totmp || countB > 32) break;
392 	}
393 
394 	if (countA > countB) {
395 		return 1; // go negative
396 	} else {
397 		return 0; // go positive
398 	}
399 }
400 
RotateDoTick()401 static void RotateDoTick() {
402 	// since the game only allows for 1 rotation every other frame, we have to
403 	// do this.
404 	if (nCurrentFrame&1) return;
405 
406 	for (INT32 i = 0; i < 2; i++) {
407 		if (rotate_gunpos[i] && (nRotateTarget[i] != -1) && (nRotateTarget[i] != (*rotate_gunpos[i] & 0xff))) {
408 			if (get_distance(nRotateTarget[i], *rotate_gunpos[i] & 0xff)) {
409 				RotateRight(&nRotate[i]); // --
410 			} else {
411 				RotateLeft(&nRotate[i]);  // ++
412 			}
413 			bprintf(0, _T("p%X target %X mempos %X nRotate %X.\n"), i, nRotateTarget[i], *rotate_gunpos[i] & 0xff, nRotate[i]);
414 			nRotateTry[i]++;
415 			if (nRotateTry[i] > 10) nRotateTarget[i] = -1; // don't get stuck in a loop if something goes horribly wrong here.
416 		} else {
417 			nRotateTarget[i] = -1;
418 		}
419 	}
420 }
421 
SuperJoy2Rotate()422 static void SuperJoy2Rotate() {
423 	for (INT32 i = 0; i < 2; i++) { // p1 = 0, p2 = 1
424 		if (DrvFakeInput[4 + i]) { //  rotate-button had been pressed
425 			UINT8 rot = Joy2Rotate(((!i) ? &DrvJoy1[0] : &DrvJoy2[0]));
426 			if (rot != 0xff) {
427 				nRotateTarget[i] = rot * rotate_gunpos_multiplier;
428 			}
429 			//DrvInput[i] &= ~0xf; // cancel out directionals since they are used to rotate here.
430 			DrvInputs[i] = (DrvInputs[i] & ~0xf) | (nRotateHoldInput[i] & 0xf); // for midnight resistance! be able to duck + change direction of gun.
431 			nRotateTry[i] = 0;
432 		} else { // cache joystick UDLR if the rotate button isn't pressed.
433 			// This feature is for Midnight Resistance, if you are crawling on the
434 			// ground and need to rotate your gun WITHOUT getting up.
435 			nRotateHoldInput[i] = DrvInputs[i];
436 		}
437 	}
438 
439 	RotateDoTick();
440 }
441 
442 // end Rotation-handler
443 
bankswitch()444 static void bankswitch()
445 {
446 	INT32 banks[3] = { DrvVORAMBank * 0x1000, DrvSprRAMBank * 0x1000, DrvROMBank * 0x8000 };
447 
448 	M6809MapMemory(DrvVORAM + banks[0],			0x2000, 0x2fff, MAP_RAM);
449 	M6809MapMemory(DrvSprRAM + banks[1],			0x3000, 0x3fff, MAP_RAM);
450 	M6809MapMemory(DrvM6809ROM0 + 0x10000 + banks[2],	0x4000, 0xbfff, MAP_ROM);
451 }
452 
jackal_main_write(UINT16 address,UINT8 data)453 static void jackal_main_write(UINT16 address, UINT8 data)
454 {
455 	if (address >= 0x0020 && address <= 0x005f) {
456 		DrvZRAM[(address - 0x20) + DrvZRAMBank] = data;
457 		return;
458 	}
459 
460 	if (address >= 0x0060 && address <= 0x1fff) {
461 		DrvShareRAM[address] = data;
462 		return;
463 	}
464 
465 	switch (address)
466 	{
467 		case 0x0000:
468 		case 0x0001:
469 		case 0x0002:
470 		case 0x0003:
471 			DrvVidControl[address] = data;
472 		return;
473 
474 		case 0x0004:
475 			flipscreen = data & 0x08;
476 			DrvIRQEnable = data & 0x02;
477 		return;
478 
479 		case 0x0019:
480 			watchdog = 0;
481 		return;
482 
483 		case 0x001c:
484 			DrvSprRAMBank = (data & 0x08) >> 3;
485 			DrvZRAMBank = (data & 0x10) << 2; // 0x40
486 			DrvROMBank = (data & 0x20) >> 5;
487 			DrvVORAMBank = (data & 0x10) >> 4;
488 			bankswitch();
489 		return;
490 	}
491 }
492 
jackal_main_read(UINT16 address)493 static UINT8 jackal_main_read(UINT16 address)
494 {
495 	if (address >= 0x0020 && address <= 0x005f) {
496 		return DrvZRAM[(address - 0x20) + DrvZRAMBank];
497 	}
498 
499 	if (address >= 0x0060 && address <= 0x1fff) {
500 		return DrvShareRAM[address];
501 	}
502 
503 	switch (address)
504 	{
505 		case 0x0000: // actually read?
506 		case 0x0001:
507 		case 0x0002:
508 		case 0x0003:
509 			return DrvVidControl[address];
510 
511 		case 0x0010:
512 			return DrvDips[0];
513 
514 		case 0x0011:
515 			return DrvInputs[0];
516 
517 		case 0x0012:
518 			return DrvInputs[1];
519 
520 		case 0x0013:
521 			return (DrvInputs[2] & 0x1f) | (DrvDips[2] & 0xe0);
522 
523 		case 0x0014:
524 		case 0x0015:
525 			return dialRotation(address - 0x14); // rotary
526 
527 		case 0x0018:
528 			return DrvDips[1];
529 	}
530 
531 	return 0;
532 }
533 
jackal_sub_write(UINT16 address,UINT8 data)534 static void jackal_sub_write(UINT16 address, UINT8 data)
535 {
536 	switch (address)
537 	{
538 		case 0x2000:
539 			BurnYM2151SelectRegister(data);
540 		return;
541 
542 		case 0x2001:
543 			BurnYM2151WriteRegister(data);
544 		return;
545 	}
546 }
547 
jackal_sub_read(UINT16 address)548 static UINT8 jackal_sub_read(UINT16 address)
549 {
550 	switch (address)
551 	{
552 		case 0x2000:
553 		case 0x2001:
554 			return BurnYM2151Read();
555 	}
556 
557 	return 0;
558 }
559 
DrvDoReset(INT32 clear_mem)560 static INT32 DrvDoReset(INT32 clear_mem)
561 {
562 	if (clear_mem) {
563 		memset (AllRam, 0, RamEnd - AllRam);
564 	}
565 
566 	DrvZRAMBank = 0;
567 	DrvVORAMBank = 0;
568 	DrvSprRAMBank = 0;
569 	DrvROMBank = 0;
570 	DrvIRQEnable = 0;
571 	flipscreen = 0;
572 
573 	M6809Open(0);
574 	bankswitch();
575 	M6809Reset();
576 	M6809Close();
577 
578 	M6809Open(1);
579 	M6809Reset();
580 	M6809Close();
581 
582 	BurnYM2151Reset();
583 
584 	RotateReset();
585 
586 	watchdog = 0;
587 
588 	HiscoreReset();
589 
590 	return 0;
591 }
592 
MemIndex()593 static INT32 MemIndex()
594 {
595 	UINT8 *Next; Next = AllMem;
596 
597 	DrvM6809ROM0	= Next; Next += 0x020000;
598 	DrvM6809ROM1	= Next; Next += 0x010000;
599 
600 	DrvGfxROM0		= Next; Next += 0x140000;
601 	DrvGfxROM1		= Next; Next += 0x180000;
602 	DrvGfxROM2		= Next; Next += 0x180000;
603 
604 	DrvColPROM		= Next; Next += 0x000200;
605 
606 	DrvPaletteTab   = (UINT32*)Next; Next += 0x0300 * sizeof(UINT32);
607 	DrvPalette		= (UINT32*)Next; Next += 0x0300 * sizeof(UINT32);
608 
609 	AllRam			= Next;
610 
611 	DrvShareRAM		= Next; Next += 0x002000;
612 	DrvSprRAM		= Next; Next += 0x004000;
613 	DrvZRAM			= Next; Next += 0x000080;
614 	DrvVORAM		= Next; Next += 0x002000;
615 	DrvPalRAM		= Next; Next += 0x000400;
616 
617 	DrvVidControl	= Next; Next += 0x000004;
618 
619 	RamEnd			= Next;
620 
621 	MemEnd			= Next;
622 
623 	return 0;
624 }
625 
DrvGfxDecode()626 static INT32 DrvGfxDecode()
627 {
628 	INT32 Planes[8] = { STEP4(0,1), STEP4(0x40000*8, 1) };
629 	INT32 XOffs[16] = {  0*4, 1*4, 2*4, 3*4, 4*4, 5*4, 6*4, 7*4, 32*8+0*4, 32*8+1*4, 32*8+2*4, 32*8+3*4, 32*8+4*4, 32*8+5*4, 32*8+6*4, 32*8+7*4 };
630 	//STEP8(0,4), STEP8(32*8, ??)
631 	INT32 YOffs[16] = { STEP8(0,32), STEP8(16*32,32) };
632 
633 	UINT8 *tmp = (UINT8*)BurnMalloc(0x80000);
634 	if (tmp == NULL) {
635 		return 1;
636 	}
637 
638 	memcpy (tmp, DrvGfxROM2, 0x80000);
639 
640 	GfxDecode(0x1000, 8,  8,  8, Planes, XOffs, YOffs, 0x100, tmp, DrvGfxROM0);
641 
642 	memcpy (tmp + 0x00000, tmp + 0x20000, 0x20000);
643 	memcpy (tmp + 0x20000, tmp + 0x60000, 0x20000);
644 
645 	GfxDecode(0x0800, 4, 16, 16, Planes, XOffs, YOffs, 0x400, tmp, DrvGfxROM1);
646 	GfxDecode(0x2000, 4,  8,  8, Planes, XOffs, YOffs, 0x100, tmp, DrvGfxROM2);
647 
648 	BurnFree(tmp);
649 
650 	return 0;
651 }
652 
DrvPaletteInit()653 static void DrvPaletteInit()
654 {
655 	for (INT32 i = 0; i < 0x100; i++) {
656 		DrvPaletteTab[0x000 + i] = i + 0x100;
657 		DrvPaletteTab[0x100 + i] =  DrvColPROM[0x000 + i] & 0xf;
658 		DrvPaletteTab[0x200 + i] = (DrvColPROM[0x100 + i] & 0xf) + 0x10;
659 	}
660 }
661 
DrvInit()662 static INT32 DrvInit()
663 {
664 	AllMem = NULL;
665 	MemIndex();
666 	INT32 nLen = MemEnd - (UINT8 *)0;
667 	if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1;
668 	memset(AllMem, 0, nLen);
669 	MemIndex();
670 
671 	if (!bootleg) {
672 		// Jackal
673 		if (BurnLoadRom(DrvM6809ROM0 + 0x10000,   0, 1)) return 1;
674 		if (BurnLoadRom(DrvM6809ROM0 + 0x0c000,   1, 1)) return 1;
675 
676 		if (BurnLoadRom(DrvM6809ROM1 + 0x08000,   2, 1)) return 1;
677 
678 		if (BurnLoadRom(DrvGfxROM2   + 0x00000,   3, 2)) return 1;
679 		if (BurnLoadRom(DrvGfxROM2   + 0x00001,   4, 2)) return 1;
680 		if (BurnLoadRom(DrvGfxROM2   + 0x40000,   5, 2)) return 1;
681 		if (BurnLoadRom(DrvGfxROM2   + 0x40001,   6, 2)) return 1;
682 
683 		if (BurnLoadRom(DrvColPROM   + 0x00000,   7, 1)) return 1;
684 		if (BurnLoadRom(DrvColPROM   + 0x00100,   8, 1)) return 1;
685 	} else {
686 		// Bootleg
687 		if (BurnLoadRom(DrvM6809ROM0 + 0x10000,   0, 1)) return 1;
688 		if (BurnLoadRom(DrvM6809ROM0 + 0x18000,   1, 1)) return 1;
689 		if (BurnLoadRom(DrvM6809ROM0 + 0x0c000,   2, 1)) return 1;
690 
691 		if (BurnLoadRom(DrvM6809ROM1 + 0x08000,   3, 1)) return 1;
692 
693 		if (BurnLoadRom(DrvGfxROM2   + 0x00000,   4, 1)) return 1;
694 		if (BurnLoadRom(DrvGfxROM2   + 0x08000,   5, 1)) return 1;
695 		if (BurnLoadRom(DrvGfxROM2   + 0x10000,   6, 1)) return 1;
696 		if (BurnLoadRom(DrvGfxROM2   + 0x18000,   7, 1)) return 1;
697 		if (BurnLoadRom(DrvGfxROM2   + 0x20000,   8, 1)) return 1;
698 		if (BurnLoadRom(DrvGfxROM2   + 0x28000,   9, 1)) return 1;
699 		if (BurnLoadRom(DrvGfxROM2   + 0x30000,  10, 1)) return 1;
700 		if (BurnLoadRom(DrvGfxROM2   + 0x38000,  11, 1)) return 1;
701 		if (BurnLoadRom(DrvGfxROM2   + 0x40000,  12, 1)) return 1;
702 		if (BurnLoadRom(DrvGfxROM2   + 0x48000,  13, 1)) return 1;
703 		if (BurnLoadRom(DrvGfxROM2   + 0x50000,  14, 1)) return 1;
704 		if (BurnLoadRom(DrvGfxROM2   + 0x58000,  15, 1)) return 1;
705 		if (BurnLoadRom(DrvGfxROM2   + 0x60000,  16, 1)) return 1;
706 		if (BurnLoadRom(DrvGfxROM2   + 0x68000,  17, 1)) return 1;
707 		if (BurnLoadRom(DrvGfxROM2   + 0x70000,  18, 1)) return 1;
708 		if (BurnLoadRom(DrvGfxROM2   + 0x78000,  19, 1)) return 1;
709 
710 		if (BurnLoadRom(DrvColPROM   + 0x00000,  20, 1)) return 1;
711 		if (BurnLoadRom(DrvColPROM   + 0x00100,  21, 1)) return 1;
712 		BurnByteswap(DrvGfxROM2, 0x80000);
713 	}
714 
715 	DrvGfxDecode();
716 	DrvPaletteInit();
717 
718 	M6809Init(0);
719 	M6809Open(0);
720 	M6809MapMemory(DrvShareRAM + 0x100,	0x0100, 0x1fff, MAP_RAM);
721 	M6809MapMemory(DrvVORAM,		0x2000, 0x2fff, MAP_RAM);
722 	M6809MapMemory(DrvSprRAM,		0x3000, 0x3fff, MAP_RAM);
723 	M6809MapMemory(DrvM6809ROM0 + 0x0c000,	0xc000, 0xffff, MAP_ROM);
724 	M6809SetWriteHandler(jackal_main_write);
725 	M6809SetReadHandler(jackal_main_read);
726 	M6809Close();
727 
728 	M6809Init(1);
729 	M6809Open(1);
730 	M6809MapMemory(DrvPalRAM,		0x4000, 0x43ff, MAP_RAM);
731 	M6809MapMemory(DrvShareRAM,		0x6000, 0x7fff, MAP_RAM);
732 	M6809MapMemory(DrvM6809ROM1 + 0x08000,	0x8000, 0xffff, MAP_ROM);
733 	M6809SetWriteHandler(jackal_sub_write);
734 	M6809SetReadHandler(jackal_sub_read);
735 	M6809Close();
736 
737 	BurnYM2151Init(3580000);
738 	BurnYM2151SetRoute(BURN_SND_YM2151_YM2151_ROUTE_1, 0.50, BURN_SND_ROUTE_LEFT);
739 	BurnYM2151SetRoute(BURN_SND_YM2151_YM2151_ROUTE_2, 0.50, BURN_SND_ROUTE_RIGHT);
740 
741 	GenericTilesInit();
742 	if (game_rotates)
743 		RotateSetGunPosRAM(DrvShareRAM + 0xbd8, DrvShareRAM + 0xc00, 1);
744 	DrvDoReset(1);
745 
746 	return 0;
747 }
748 
DrvExit()749 static INT32 DrvExit()
750 {
751 	M6809Exit();
752 
753 	BurnYM2151Exit();
754 
755 	GenericTilesExit();
756 
757 	BurnFree(AllMem);
758 
759 	bootleg = 0;
760 	game_rotates = 1;
761 
762 	return 0;
763 }
764 
DrvPaletteUpdate()765 static void DrvPaletteUpdate()
766 {
767 	UINT32 pens[0x200];
768 
769 	for (INT32 i = 0; i < 0x200; i++) {
770 		if (i >= 0x20 && i < 0x100) continue; // not used, save cycles
771 
772 		UINT16 p = (DrvPalRAM[(i * 2)] | (DrvPalRAM[(i * 2) + 1] << 8));
773 
774 		UINT8 r = (p >>  0) & 0x1f;
775 		UINT8 g = (p >>  5) & 0x1f;
776 		UINT8 b = (p >> 10) & 0x1f;
777 
778 		r = (r << 3) | (r >> 2);
779 		g = (g << 3) | (g >> 2);
780 		b = (b << 3) | (b >> 2);
781 
782 		pens[i] = BurnHighCol(r,g,b,0);
783 	}
784 
785 	for (INT32 i = 0; i < 0x300; i++) {
786 		DrvPalette[i] = pens[DrvPaletteTab[i]];
787 	}
788 }
789 
draw_layer()790 static void draw_layer()
791 {
792 	INT32 layer_control = DrvVidControl[2];
793 
794 	INT32 xscroll = DrvVidControl[1];
795 	INT32 yscroll = DrvVidControl[0];
796 
797 	UINT8 *scrollram = DrvZRAM;
798 
799 	for (INT32 offs = 0; offs < 32 * 32; offs++)
800 	{
801 		INT32 attr  = DrvVORAM[0x0000 + offs];
802 		INT32 code  = DrvVORAM[0x0400 + offs] + ((attr & 0xc0) << 2) + ((attr & 0x30) << 6);
803 
804 		INT32 flipx = attr & 0x10;
805 		INT32 flipy = attr & 0x20;
806 
807 		INT32 sy = (((offs / 0x20) & 0x1f) * 8) - layer_offset_y;
808 		INT32 sx = ((offs & 0x1f) * 8) - layer_offset_x;
809 
810 		if (layer_control & 0x02) {
811 			if (layer_control & 0x08) {
812 				sx -= scrollram[(sy + layer_offset_y)/8]; // maybe apply the offset here? I guess we'll know for sure after playtesting. -dink
813 				sy -= yscroll;
814 			}
815 			else if (layer_control & 0x04) {
816 				sy -= scrollram[(sx + layer_offset_x)/8]; // offset applied here fixes the konami logo on the titlescreen. -dink
817 				sx -= xscroll;
818 			}
819 		} else {
820 			sy -= yscroll;
821 			sx -= xscroll;
822 		}
823 		if (sy < -7) sy += 256;
824 		if (sx < -7) sx += 256;
825 
826 		if (flipy) {
827 			if (flipx) {
828 				Render8x8Tile_FlipXY_Clip(pTransDraw, code, sx, sy, 0, 8, 0, DrvGfxROM0);
829 			} else {
830 				Render8x8Tile_FlipY_Clip(pTransDraw, code, sx, sy, 0, 8, 0, DrvGfxROM0);
831 			}
832 		} else {
833 			if (flipx) {
834 				Render8x8Tile_FlipX_Clip(pTransDraw, code, sx, sy, 0, 8, 0, DrvGfxROM0);
835 			} else {
836 				Render8x8Tile_Clip(pTransDraw, code, sx, sy, 0, 8, 0, DrvGfxROM0);
837 			}
838 		}
839 	}
840 }
841 
draw_sprite(INT32 bank,INT32 code,INT32 color,INT32 sx,INT32 sy,INT32 flipx,INT32 flipy)842 static void draw_sprite(INT32 bank, INT32 code, INT32 color, INT32 sx, INT32 sy, INT32 flipx, INT32 flipy)
843 {
844 	sx -= layer_offset_x;
845 	sy -= layer_offset_y;
846 	color += (bank & 2) ? 0x20 : 0x10;
847 
848 	if (bank & 8) // 8x8
849 	{
850 		if (flipy) {
851 			if (flipx) {
852 				Render8x8Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM2);
853 			} else {
854 				Render8x8Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM2);
855 			}
856 		} else {
857 			if (flipx) {
858 				Render8x8Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM2);
859 			} else {
860 				Render8x8Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM2);
861 			}
862 		}
863 	}
864 	else // 16x16
865 	{
866 		if (flipy) {
867 			if (flipx) {
868 				Render16x16Tile_Mask_FlipXY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM1);
869 			} else {
870 				Render16x16Tile_Mask_FlipY_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM1);
871 			}
872 		} else {
873 			if (flipx) {
874 				Render16x16Tile_Mask_FlipX_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM1);
875 			} else {
876 				Render16x16Tile_Mask_Clip(pTransDraw, code, sx, sy, color, 4, 0, 0, DrvGfxROM1);
877 			}
878 		}
879 	}
880 }
881 
draw_sprites(INT32 rambase,INT32 length,INT32 bank)882 static void draw_sprites(INT32 rambase, INT32 length, INT32 bank)
883 {
884 	const UINT8 *sram = DrvSprRAM + rambase + ((DrvVidControl[3] & 0x08) ? 0x0800 : 0);
885 
886 	for (INT32 offs = 0; offs < length; offs += 5)
887 	{
888 		INT32 attr  = sram[offs + 4];
889 		INT32 sn1   = sram[offs];
890 		INT32 sn2   = sram[offs + 1];
891 		INT32 sy    = sram[offs + 2];
892 		INT32 sx    = sram[offs + 3] - ((attr & 1) << 8);
893 		INT32 flipx = attr & 0x20;
894 		INT32 flipy = attr & 0x40;
895 		INT32 color = sn2 >> 4;
896 
897 		if (sy > 0xf0)	sy -= 256;
898 
899 		if (flipscreen)
900 		{
901 			sx = 240 - sx;
902 			sy = 240 - sy;
903 			flipx = !flipx;
904 			flipy = !flipy;
905 		}
906 
907 		if (attr & 0x0c)
908 		{
909 			INT32 spritenum = sn1 * 4 + ((sn2 & 0x0c) >> 2) + ((sn2 & 3) << 10) + ((bank & 2) << 11); // was << 12 -dink
910 
911 			INT32 mod = -8;
912 
913 			if (flipscreen)
914 			{
915 				sx += 8;
916 				sy -= 8;
917 				mod = 8;
918 			}
919 
920 			if ((attr & 0x0c) == 0x0C) // 1x1
921 			{
922 				if (flipscreen) sy += 16;
923 				draw_sprite(bank+8, spritenum, color, sx, sy, flipx, flipy);
924 			}
925 
926 			if ((attr & 0x0c) == 0x08) // 1x2
927 			{
928 				sy += 8;
929 				draw_sprite(bank+8, spritenum,     color, sx, sy,       flipx, flipy);
930 				draw_sprite(bank+8, spritenum - 2, color, sx, sy + mod, flipx, flipy);
931 			}
932 
933 			if ((attr & 0x0c) == 0x04) // 2x1
934 			{
935 				draw_sprite(bank+8, spritenum,     color, sx,       sy, flipx, flipy);
936 				draw_sprite(bank+8, spritenum + 1, color, sx + mod, sy, flipx, flipy);
937 			}
938 		}
939 		else
940 		{
941 			INT32 spritenum = sn1 + (((sn2 & 0x03) << 8) + ((bank & 2) << 9));
942 
943 			if (attr & 0x10) // 2x2
944 			{
945 				if (flipscreen)
946 				{
947 					sx -= 16;
948 					sy -= 16;
949 				}
950 
951 				draw_sprite(bank, spritenum,     color, flipx ? sx+16 : sx, flipy ? sy+16 : sy, flipx, flipy);
952 				draw_sprite(bank, spritenum + 1, color, flipx ? sx : sx+16, flipy ? sy+16 : sy, flipx, flipy);
953 				draw_sprite(bank, spritenum + 2, color, flipx ? sx+16 : sx, flipy ? sy : sy+16, flipx, flipy);
954 				draw_sprite(bank, spritenum + 3, color, flipx ? sx : sx+16, flipy ? sy : sy+16, flipx, flipy);
955 			}
956 			else // 1x1
957 			{
958 				draw_sprite(bank, spritenum, color, sx, sy, flipx, flipy);
959 			}
960 		}
961 	}
962 }
963 
DrvDraw()964 static INT32 DrvDraw()
965 {
966 	//if (DrvRecalc) {
967 		DrvPaletteUpdate();
968 		DrvRecalc = 0;
969 	//}
970 	BurnTransferClear();
971 	if (nBurnLayer & 2) draw_layer();
972 
973 	if (nBurnLayer & 4) draw_sprites(0x1000, 0x0f5, 2);
974 	if (nBurnLayer & 8) draw_sprites(0x0000, 0x500, 0);
975 
976 	BurnTransferCopy(DrvPalette);
977 
978 	return 0;
979 }
980 
DrvFrame()981 static INT32 DrvFrame()
982 {
983 	watchdog++;
984 	if (watchdog >= 180) {
985 		DrvDoReset(0);
986 	}
987 
988 	if (DrvReset) {
989 		DrvDoReset(1);
990 	}
991 
992 	{
993 		memset (DrvInputs, 0xff, 3);
994 		for (INT32 i = 0; i < 8; i++) {
995 			DrvInputs[0] ^= (DrvJoy1[i] & 1) << i;
996 			DrvInputs[1] ^= (DrvJoy2[i] & 1) << i;
997 			DrvInputs[2] ^= (DrvJoy3[i] & 1) << i;
998 		}
999 
1000 		if (game_rotates) {
1001 			SuperJoy2Rotate();
1002 		}
1003 	}
1004 
1005 	INT32 nInterleave = 100;
1006 	INT32 nCyclesTotal[2] = { 1536000 / 60, ((1536000 * 12) / 10) / 60 };
1007 	INT32 nSoundBufferPos = 0;
1008 
1009 	M6809NewFrame();
1010 
1011 	for (INT32 i = 0; i < nInterleave; i++)
1012 	{
1013 		M6809Open(0);
1014 		M6809Run(nCyclesTotal[0] / nInterleave);
1015 		if (i == (nInterleave - 1) && DrvIRQEnable)
1016 			M6809SetIRQLine(0x00, CPU_IRQSTATUS_AUTO);
1017 		M6809Close();
1018 
1019 		M6809Open(1);
1020 		M6809Run(nCyclesTotal[1] / nInterleave);
1021 		if (i == (nInterleave - 1) && DrvIRQEnable)
1022 			M6809SetIRQLine(0x20, CPU_IRQSTATUS_AUTO); // nmi
1023 		M6809Close();
1024 
1025 		if (pBurnSoundOut) {
1026 			INT32 nSegmentLength = nBurnSoundLen / nInterleave;
1027 			INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
1028 			BurnYM2151Render(pSoundBuf, nSegmentLength);
1029 			nSoundBufferPos += nSegmentLength;
1030 		}
1031 	}
1032 
1033 	if (pBurnSoundOut) {
1034 		INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos;
1035 		if (nSegmentLength) {
1036 			INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
1037 			BurnYM2151Render(pSoundBuf, nSegmentLength);
1038 		}
1039 	}
1040 
1041 	if (pBurnDraw) {
1042 		DrvDraw();
1043 	}
1044 
1045 	return 0;
1046 }
1047 
DrvScan(INT32 nAction,INT32 * pnMin)1048 static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
1049 {
1050 	struct BurnArea ba;
1051 
1052 	if (pnMin) {
1053 		*pnMin = 0x029737;
1054 	}
1055 
1056 	if (nAction & ACB_VOLATILE) {
1057 		memset(&ba, 0, sizeof(ba));
1058 		ba.Data	  = AllRam;
1059 		ba.nLen	  = RamEnd - AllRam;
1060 		ba.szName = "All Ram";
1061 		BurnAcb(&ba);
1062 
1063 		M6809Scan(nAction);
1064 
1065 		BurnYM2151Scan(nAction, pnMin);
1066 
1067 		SCAN_VAR(DrvZRAMBank);
1068 		SCAN_VAR(DrvVORAMBank);
1069 		SCAN_VAR(DrvSprRAMBank);
1070 		SCAN_VAR(DrvROMBank);
1071 		SCAN_VAR(DrvIRQEnable);
1072 	}
1073 
1074 	if (nAction & ACB_WRITE) {
1075 		M6809Open(0);
1076 		bankswitch();
1077 		M6809Close();
1078 	}
1079 
1080 	return 0;
1081 }
1082 
1083 // Jackal (World, 8-way Joystick)
1084 
1085 static struct BurnRomInfo jackalRomDesc[] = {
1086 	{ "631_v02.15d",	0x10000, 0x0b7e0584, 0 | BRF_PRG | BRF_ESS }, // 0 - M6809 #0 Code
1087 	{ "631_v03.16d",	0x04000, 0x3e0dfb83, 0 | BRF_PRG | BRF_ESS }, // 1
1088 
1089 	{ "631_t01.11d",	0x08000, 0xb189af6a, 1 | BRF_PRG | BRF_ESS }, // 2 - M6809 #1 Code
1090 
1091 	{ "631t04.7h",  	0x20000, 0x457f42f0, 2 | BRF_GRA },           // 3 - Graphics Tiles
1092 	{ "631t05.8h",		0x20000, 0x732b3fc1, 2 | BRF_GRA },           // 4
1093 	{ "631t06.12h",		0x20000, 0x2d10e56e, 2 | BRF_GRA },           // 5
1094 	{ "631t07.13h",		0x20000, 0x4961c397, 2 | BRF_GRA },           // 6
1095 
1096 	{ "631r08.9h",		0x00100, 0x7553a172, 3 | BRF_GRA },           // 7 - Color PROMs
1097 	{ "631r09.14h",		0x00100, 0xa74dd86c, 3 | BRF_GRA },           // 8
1098 };
1099 
1100 STD_ROM_PICK(jackal)
1101 STD_ROM_FN(jackal)
1102 
1103 // Jackal (World, Rotary Joystick)
1104 
1105 static struct BurnRomInfo jackalrRomDesc[] = {
1106 	{ "631_q02.15d",	0x10000, 0xed2a7d66, 0 | BRF_PRG | BRF_ESS }, // 0 - M6809 #0 Code
1107 	{ "631_q03.16d",	0x04000, 0xb9d34836, 0 | BRF_PRG | BRF_ESS }, // 1
1108 
1109 	{ "631_q01.11d",	0x08000, 0x54aa2d29, 1 | BRF_PRG | BRF_ESS }, // 2 - M6809 #1 Code
1110 
1111 	{ "631t04.7h",		0x20000, 0x457f42f0, 2 | BRF_GRA },           // 3 - Graphics Tiles
1112 	{ "631t05.8h",		0x20000, 0x732b3fc1, 2 | BRF_GRA },           // 4
1113 	{ "631t06.12h",		0x20000, 0x2d10e56e, 2 | BRF_GRA },           // 5
1114 	{ "631t07.13h",		0x20000, 0x4961c397, 2 | BRF_GRA },           // 6
1115 
1116 	{ "631r08.9h",		0x00100, 0x7553a172, 3 | BRF_GRA },           // 7 - Color PROMs
1117 	{ "631r09.14h",		0x00100, 0xa74dd86c, 3 | BRF_GRA },           // 7 - Color PROMs
1118 };
1119 
1120 STD_ROM_PICK(jackalr)
1121 STD_ROM_FN(jackalr)
1122 
1123 // Tokushu Butai Jackal (Japan, 8-way Joystick)
1124 
1125 static struct BurnRomInfo jackaljRomDesc[] = {
1126 	{ "631_t02.15d",	0x10000, 0x14db6b1a, 0 | BRF_PRG | BRF_ESS }, // 0 - M6809 #0 Code
1127 	{ "631_t03.16d",	0x04000, 0xfd5f9624, 0 | BRF_PRG | BRF_ESS }, // 1
1128 
1129 	{ "631_t01.11d",	0x08000, 0xb189af6a, 1 | BRF_PRG | BRF_ESS }, // 2 - M6809 #1 Code
1130 
1131 	{ "631t04.7h",  	0x20000, 0x457f42f0, 2 | BRF_GRA },           // 3 - Graphics Tiles
1132 	{ "631t05.8h",		0x20000, 0x732b3fc1, 2 | BRF_GRA },           // 4
1133 	{ "631t06.12h",		0x20000, 0x2d10e56e, 2 | BRF_GRA },           // 5
1134 	{ "631t07.13h",		0x20000, 0x4961c397, 2 | BRF_GRA },           // 6
1135 
1136 	{ "631r08.9h",		0x00100, 0x7553a172, 3 | BRF_GRA },           // 7 - Color PROMs
1137 	{ "631r09.14h",		0x00100, 0xa74dd86c, 3 | BRF_GRA },           // 8
1138 };
1139 
1140 STD_ROM_PICK(jackalj)
1141 STD_ROM_FN(jackalj)
1142 
1143 // Jackal (bootleg, Rotary Joystick)
1144 // This is based on jackalr. Was dumped from 2 different PCBs.
1145 
1146 static struct BurnRomInfo jackalblRomDesc[] = {
1147 	{ "epr-a-3.bin",	0x8000, 0x5fffee27, 0 | BRF_PRG | BRF_ESS }, 		// 0 - M6809 #0 Code
1148 	{ "epr-a-4.bin",	0x8000, 0x976c8431, 0 | BRF_PRG | BRF_ESS }, 		// 1
1149 	{ "epr-a-2.bin",	0x4000, 0xae2a290a, 0 | BRF_PRG | BRF_ESS }, 		// 2
1150 
1151 	{ "epr-a-1.bin",	0x8000, 0x54aa2d29, 1 | BRF_PRG | BRF_ESS }, 		// 3 - M6809 #1 Code
1152 
1153 	{ "epr-a-17.bin",	0x8000, 0xa96720b6, 2 | BRF_GRA },           		// 4 - Graphics Tiles
1154 	{ "epr-a-18.bin",	0x8000, 0x932d0ecb, 2 | BRF_GRA },           		// 5
1155 	{ "epr-a-19.bin",	0x8000, 0x1e3412e7, 2 | BRF_GRA },           		// 6
1156 	{ "epr-a-20.bin",	0x8000, 0x4b0d15be, 2 | BRF_GRA },           		// 7
1157 	{ "epr-a-6.bin",	0x8000, 0xec7141ad, 2 | BRF_GRA },           		// 8
1158 	{ "epr-a-5.bin",	0x8000, 0xc6375c74, 2 | BRF_GRA },           		// 9
1159 	{ "epr-a-7.bin",	0x8000, 0x03e1de04, 2 | BRF_GRA },           		// 10
1160 	{ "epr-a-8.bin",	0x8000, 0xf946ada7, 2 | BRF_GRA },           		// 11
1161 	{ "epr-a-13.bin",	0x8000, 0x7c29c59e, 2 | BRF_GRA },           		// 12
1162 	{ "epr-a-14.bin",	0x8000, 0xf2bbff39, 2 | BRF_GRA },           		// 13
1163 	{ "epr-a-15.bin",	0x8000, 0x594dbaaf, 2 | BRF_GRA },           		// 14
1164 	{ "epr-a-16.bin",	0x8000, 0x069bf945, 2 | BRF_GRA },           		// 15
1165 	{ "epr-a-9.bin",	0x8000, 0xc00cef79, 2 | BRF_GRA },           		// 16
1166 	{ "epr-a-10.bin",	0x8000, 0x0aed6cd7, 2 | BRF_GRA },           		// 17
1167 	{ "epr-a-11.bin",	0x8000, 0xa48e9f60, 2 | BRF_GRA },           		// 18
1168 	{ "epr-a-12.bin",	0x8000, 0x79b7c71c, 2 | BRF_GRA },           		// 19
1169 
1170 	{ "n82s129n.prom2",	0x0100, 0x7553a172, 3 | BRF_GRA },           		// 20 - Color PROMs
1171 	{ "n82s129n.prom1",	0x0100, 0xa74dd86c, 3 | BRF_GRA },           		// 21
1172 
1173 	/* currently not used by the emulation */
1174 	{ "pal16r6cn.pal1", 	0x0104, 0x9bba948f, 4 | BRF_OPT },		 		// 22 - Pals
1175 	{ "ampal16l8pc.pal2", 	0x0104, 0x17c9de2f, 4 | BRF_OPT },		 		// 23
1176 	{ "ampal16r4pc.pal3", 	0x0104, 0xe54cd288, 4 | BRF_OPT },		 		// 24
1177 	{ "pal16r8acn.pal4", 	0x0104, 0x5cc45e00, 4 | BRF_OPT },		 		// 25
1178 	{ "pal20l8a-2cns.pal5", 0x0144, 0x00000000, 4 | BRF_OPT | BRF_NODUMP },	// 26
1179 	{ "pal20l8acns.pal6", 	0x0144, 0x00000000, 4 | BRF_OPT | BRF_NODUMP },	// 27
1180 	{ "pal16l8pc.pal7", 	0x0104, 0xe8cdc259, 4 | BRF_OPT },		 		// 28
1181 	{ "d5c121.ep1200", 		0x0200, 0x00000000, 4 | BRF_OPT | BRF_NODUMP },	// 29
1182 };
1183 
1184 STD_ROM_PICK(jackalbl)
1185 STD_ROM_FN(jackalbl)
1186 
1187 // Top Gunner (US, 8-way Joystick)
1188 
1189 static struct BurnRomInfo topgunrRomDesc[] = {
1190 	{ "631_u02.15d",	0x10000, 0xf7e28426, 0 | BRF_PRG | BRF_ESS }, // 0 - M6809 #0 Code
1191 	{ "631_u03.16d",	0x04000, 0xc086844e, 0 | BRF_PRG | BRF_ESS }, // 1
1192 
1193 	{ "631_t01.11d",	0x08000, 0xb189af6a, 1 | BRF_PRG | BRF_ESS }, // 2 - M6809 #1 Code
1194 
1195 	{ "631u04.7h",		0x20000, 0x50122a12, 2 | BRF_GRA },           // 3 - Graphics Tiles
1196 	{ "631u05.8h",		0x20000, 0x6943b1a4, 2 | BRF_GRA },           // 4
1197 	{ "631u06.12h",		0x20000, 0x37dbbdb0, 2 | BRF_GRA },           // 5
1198 	{ "631u07.13h",		0x20000, 0x22effcc8, 2 | BRF_GRA },           // 6
1199 
1200 	{ "631r08.9h",		0x00100, 0x7553a172, 3 | BRF_GRA },           // 7 - Color PROMs
1201 	{ "631r09.14h",		0x00100, 0xa74dd86c, 3 | BRF_GRA },           // 8
1202 };
1203 
1204 STD_ROM_PICK(topgunr)
1205 STD_ROM_FN(topgunr)
1206 
1207 // Top Gunner (bootleg, Rotary Joystick)
1208 
1209 static struct BurnRomInfo topgunblRomDesc[] = {
1210 	{ "t-3.c5",	    0x8000, 0x7826ad38, 0 | BRF_PRG | BRF_ESS }, // 0 - M6809 #0 Code
1211 	{ "t-4.c4",	    0x8000, 0x976c8431, 0 | BRF_PRG | BRF_ESS }, // 1
1212 	{ "t-2.c6",	    0x4000, 0xd53172e5, 0 | BRF_PRG | BRF_ESS }, // 2
1213 
1214 	{ "t-1.c14",	0x8000, 0x54aa2d29, 1 | BRF_PRG | BRF_ESS }, // 3 - M6809 #1 Code
1215 
1216 	{ "t-17.n12",	0x8000, 0xe8875110, 2 | BRF_GRA },           // 4 - Graphics Tiles
1217 	{ "t-18.n13",	0x8000, 0xcf14471d, 2 | BRF_GRA },           // 5
1218 	{ "t-19.n14",	0x8000, 0x46ee5dd2, 2 | BRF_GRA },           // 6
1219 	{ "t-20.n15",	0x8000, 0x3f472344, 2 | BRF_GRA },           // 7
1220 	{ "t-6.n1",	    0x8000, 0x539cc48c, 2 | BRF_GRA },           // 8
1221 	{ "t-5.m1",	    0x8000, 0xdbc26afe, 2 | BRF_GRA },           // 9
1222 	{ "t-7.n2",	    0x8000, 0x0ecd31b1, 2 | BRF_GRA },           // 10
1223 	{ "t-8.n3",	    0x8000, 0xf946ada7, 2 | BRF_GRA },           // 11
1224 	{ "t-13.n8",	0x8000, 0x5d669abb, 2 | BRF_GRA },           // 12
1225 	{ "t-14.n9",	0x8000, 0xf349369b, 2 | BRF_GRA },           // 13
1226 	{ "t-15.n10",	0x8000, 0x7c5a91dd, 2 | BRF_GRA },           // 14
1227 	{ "t-16.n11",	0x8000, 0x5ec46d8e, 2 | BRF_GRA },           // 15
1228 	{ "t-9.n4",	    0x8000, 0x8269caca, 2 | BRF_GRA },           // 16
1229 	{ "t-10.n5",	0x8000, 0x25393e4f, 2 | BRF_GRA },           // 17
1230 	{ "t-11.n6",	0x8000, 0x7895c22d, 2 | BRF_GRA },           // 18
1231 	{ "t-12.n7",	0x8000, 0x15606dfc, 2 | BRF_GRA },           // 19
1232 
1233 	{ "631r08.bpr",	0x0100, 0x7553a172, 3 | BRF_GRA },           // 20 - Color PROMs
1234 	{ "631r09.bpr",	0x0100, 0xa74dd86c, 3 | BRF_GRA },           // 21
1235 };
1236 
1237 STD_ROM_PICK(topgunbl)
STD_ROM_FN(topgunbl)1238 STD_ROM_FN(topgunbl)
1239 
1240 INT32 DrvInitbl()
1241 {
1242 	bootleg = 1;
1243 	game_rotates = 1;
1244 
1245 	return DrvInit();
1246 }
1247 
DrvInitRo()1248 INT32 DrvInitRo()
1249 {
1250 	game_rotates = 1;
1251 
1252 	return DrvInit();
1253 }
1254 
1255 struct BurnDriver BurnDrvJackal = {
1256 	"jackal", NULL, NULL, NULL, "1986",
1257 	"Jackal (World, 8-way Joystick)\0", NULL, "Konami", "Miscellaneous",
1258 	NULL, NULL, NULL, NULL,
1259 	BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_PREFIX_KONAMI, GBF_RUNGUN, 0,
1260 	NULL, jackalRomInfo, jackalRomName, NULL, NULL, NULL, NULL, DrvInputInfo, DrvDIPInfo,
1261 	DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x300,
1262 	224, 240, 3, 4
1263 };
1264 
1265 struct BurnDriver BurnDrvJackalr = {
1266 	"jackalr", "jackal", NULL, NULL, "1986",
1267 	"Jackal (World, Rotary Joystick)\0", NULL, "Konami", "Miscellaneous",
1268 	NULL, NULL, NULL, NULL,
1269 	BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_PREFIX_KONAMI, GBF_RUNGUN, 0,
1270 	NULL, jackalrRomInfo, jackalrRomName, NULL, NULL, NULL, NULL, DrvrotateInputInfo, DrvrotateDIPInfo,
1271 	DrvInitRo, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x300,
1272 	224, 240, 3, 4
1273 };
1274 
1275 struct BurnDriver BurnDrvJackalj = {
1276 	"jackalj", "jackal", NULL, NULL, "1986",
1277 	"Tokushu Butai Jackal (Japan, 8-way Joystick)\0", NULL, "Konami", "Miscellaneous",
1278 	NULL, NULL, NULL, NULL,
1279 	BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_PREFIX_KONAMI, GBF_RUNGUN, 0,
1280 	NULL, jackaljRomInfo, jackaljRomName, NULL, NULL, NULL, NULL, DrvInputInfo, DrvDIPInfo,
1281 	DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x300,
1282 	224, 240, 3, 4
1283 };
1284 
1285 struct BurnDriver BurnDrvJackalbl = {
1286 	"jackalbl", "jackal", NULL, NULL, "1986",
1287 	"Jackal (bootleg, Rotary Joystick)\0", NULL, "bootleg", "Miscellaneous",
1288 	NULL, NULL, NULL, NULL,
1289 	BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_PREFIX_KONAMI, GBF_RUNGUN, 0,
1290 	NULL, jackalblRomInfo, jackalblRomName, NULL, NULL, NULL, NULL, DrvrotateInputInfo, DrvrotateDIPInfo,
1291 	DrvInitbl, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x300,
1292 	224, 240, 3, 4
1293 };
1294 
1295 struct BurnDriver BurnDrvTopgunr = {
1296 	"topgunr", "jackal", NULL, NULL, "1986",
1297 	"Top Gunner (US, 8-way Joystick)\0", NULL, "Konami", "Miscellaneous",
1298 	NULL, NULL, NULL, NULL,
1299 	BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_PREFIX_KONAMI, GBF_RUNGUN, 0,
1300 	NULL, topgunrRomInfo, topgunrRomName, NULL, NULL, NULL, NULL, DrvInputInfo, DrvDIPInfo,
1301 	DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x300,
1302 	224, 240, 3, 4
1303 };
1304 
1305 struct BurnDriver BurnDrvTopgunbl = {
1306 	"topgunbl", "jackal", NULL, NULL, "1986",
1307 	"Top Gunner (bootleg, Rotary Joystick)\0", NULL, "bootleg", "Miscellaneous",
1308 	NULL, NULL, NULL, NULL,
1309 	BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED | BDF_HISCORE_SUPPORTED, 2, HARDWARE_PREFIX_KONAMI, GBF_RUNGUN, 0,
1310 	NULL, topgunblRomInfo, topgunblRomName, NULL, NULL, NULL, NULL, DrvrotateInputInfo, DrvrotateDIPInfo,
1311 	DrvInitbl, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x300,
1312 	224, 240, 3, 4
1313 };
1314