1 // FB Alpha Midway MCR-3 system driver module
2 // Based on MAME driver by Christopher Kirmse, Aaron Giles
3 
4 // demoderm		- good
5 // sarge		- good
6 // maxrpm		- good
7 // rampage		- good
8 // rampage2		- good
9 // powerdrv		- good
10 // stargrds		- good
11 // spyhunt		- good
12 // spyhuntp		- good
13 // crater		- graphics issues (unfixable offset? weird.)
14 // turbotag		- should we bother? looks like a buggy mess
15 
16 #include "tiles_generic.h"
17 #include "z80_intf.h"
18 #include "m68000_intf.h"
19 #include "m6809_intf.h"
20 #include "midsg.h"
21 #include "midtcs.h"
22 #include "midcsd.h"
23 #include "midssio.h"
24 #include "dac.h"
25 #include "ay8910.h"
26 #include "watchdog.h"
27 #include "burn_pal.h"
28 #include "burn_gun.h" // for dial (crater) etc.
29 #include "burn_shift.h"
30 #include "flt_rc.h" // spyhunt mixing
31 #include "lowpass2.h" // fur spyhunt beefy-engine v1.0 -dink
32 
33 static UINT8 *AllMem;
34 static UINT8 *MemEnd;
35 static UINT8 *AllRam;
36 static UINT8 *RamEnd;
37 static UINT8 *DrvZ80ROM0;
38 static UINT8 *DrvZ80ROM1;
39 static UINT8 *Drv68KROM;
40 static UINT8 *DrvSndROM;
41 static UINT8 *DrvGfxROM0;
42 static UINT8 *DrvGfxROM1;
43 static UINT8 *DrvGfxROM2;
44 static UINT8 *DrvSndPROM;
45 static UINT8 *DrvNVRAM;
46 static UINT8 *DrvSprRAM;
47 static UINT8 *DrvVidRAM;
48 static UINT8 *DrvSndRAM;
49 static UINT8 *Drv68KRAM;
50 static UINT8 *DrvTxtRAM;
51 static UINT8 *DrvZ80RAM1;
52 static UINT16 *DrvPalRAM16;
53 static UINT8 *DrvTransTab[2];
54 
55 static UINT32 *DrvPalette;
56 static UINT8 DrvRecalc;
57 
58 static INT32 flipscreen;
59 static INT32 scrollx;
60 static INT32 scrolly;
61 static INT32 input_mux;
62 static INT32 latched_input;
63 static UINT8 maxrpm_adc_control;
64 static UINT8 maxrpm_adc_select;
65 static UINT8 maxrpm_p1_shift;
66 static UINT8 maxrpm_p2_shift;
67 static UINT8 maxrpm_last_shift;
68 static UINT8 lamp;
69 static UINT8 last_op4;
70 
71 static INT32 sound_status_bit = 8; // default to disabled
72 static INT32 sound_input_bank = 0;
73 static INT32 (*port_write_handler)(UINT8 address, UINT8 data) = NULL;
74 static INT32 (*port_read_handler)(UINT8 address) = NULL;
75 static INT32 sprite_color_mask = 0;
76 static INT32 flip_screen_x = 0;
77 static INT32 nGraphicsLen[3];
78 
79 static INT32 nExtraCycles[3];
80 
81 static UINT8 DrvJoy1[8];
82 static UINT8 DrvJoy2[8];
83 static UINT8 DrvJoy3[8];
84 static UINT8 DrvJoy4[8];
85 static UINT8 DrvJoy5[8];
86 static UINT8 DrvJoy6[8];
87 static UINT8 DrvDips[6];
88 static UINT8 DrvInputs[6];
89 static UINT8 DrvReset;
90 static UINT8 dip_service = 0x20;
91 
92 static UINT8 pd_shift[3];
93 static UINT8 pd_shift_prev[3];
94 
95 static INT32 is_demoderm = 0;
96 static INT32 is_spyhunt = 0;
97 static INT32 is_powerdrv = 0;
98 static INT32 is_maxrpm = 0;
99 
100 static INT32 has_shift = 0;
101 static INT32 has_dial = 0;
102 static UINT8 DrvJoy4f[8]; // fake, for digital-dial
103 static UINT8 DrvInputs4f;
104 static INT16 DrvAnalogPort0 = 0;
105 static INT16 DrvAnalogPort1 = 0;
106 static INT16 DrvAnalogPort2 = 0;
107 static INT16 DrvAnalogPort3 = 0;
108 
109 // For spyhunt's engine effect
110 static class LowPass2 *LP1 = NULL;
111 #define SampleFreq 44100.0
112 #define CutFreq 1000.0
113 #define Q 0.4
114 #define Gain 1.3
115 #define CutFreq2 1000.0
116 #define Q2 0.3
117 #define Gain2 1.475
118 
119 #define A(a, b, c, d) {a, b, (UINT8*)(c), d}
120 static struct BurnInputInfo RampageInputList[] = {
121 	{"P1 Coin",				BIT_DIGITAL,	DrvJoy1 + 0,	"p1 coin"	},
122 	{"P1 Up",				BIT_DIGITAL,	DrvJoy2 + 0,	"p1 up"		},
123 	{"P1 Down",				BIT_DIGITAL,	DrvJoy2 + 2,	"p1 down"	},
124 	{"P1 Left",				BIT_DIGITAL,	DrvJoy2 + 3,	"p1 left"	},
125 	{"P1 Right",			BIT_DIGITAL,	DrvJoy2 + 1,	"p1 right"	},
126 	{"P1 Button 1",			BIT_DIGITAL,	DrvJoy2 + 4,	"p1 fire 1"	},
127 	{"P1 Button 2",			BIT_DIGITAL,	DrvJoy2 + 5,	"p1 fire 2"	},
128 
129 	{"P2 Coin",				BIT_DIGITAL,	DrvJoy1 + 1,	"p2 coin"	},
130 	{"P2 Up",				BIT_DIGITAL,	DrvJoy3 + 0,	"p2 up"		},
131 	{"P2 Down",				BIT_DIGITAL,	DrvJoy3 + 2,	"p2 down"	},
132 	{"P2 Left",				BIT_DIGITAL,	DrvJoy3 + 3,	"p2 left"	},
133 	{"P2 Right",			BIT_DIGITAL,	DrvJoy3 + 1,	"p2 right"	},
134 	{"P2 Button 1",			BIT_DIGITAL,	DrvJoy3 + 4,	"p2 fire 1"	},
135 	{"P2 Button 2",			BIT_DIGITAL,	DrvJoy3 + 5,	"p2 fire 2"	},
136 
137 	{"P3 Up",				BIT_DIGITAL,	DrvJoy5 + 0,	"p3 up"		},
138 	{"P3 Down",				BIT_DIGITAL,	DrvJoy5 + 2,	"p3 down"	},
139 	{"P3 Left",				BIT_DIGITAL,	DrvJoy5 + 3,	"p3 left"	},
140 	{"P3 Right",			BIT_DIGITAL,	DrvJoy5 + 1,	"p3 right"	},
141 	{"P3 Button 1",			BIT_DIGITAL,	DrvJoy5 + 4,	"p3 fire 1"	},
142 	{"P3 Button 2",			BIT_DIGITAL,	DrvJoy5 + 5,	"p3 fire 2"	},
143 
144 	{"Reset",				BIT_DIGITAL,	&DrvReset,		"reset"		},
145 	{"Service",				BIT_DIGITAL,	DrvJoy1 + 6,	"service"	},
146 	{"Tilt",				BIT_DIGITAL,	DrvJoy1 + 4,	"tilt"		},
147 	{"Dip A",				BIT_DIPSWITCH,	DrvDips + 0,	"dip"		},
148 	{"Dip B",				BIT_DIPSWITCH,	DrvDips + 1,	"dip"		},
149 	{"Dip C",				BIT_DIPSWITCH,	DrvDips + 2,	"dip"		},
150 	{"Dip D",				BIT_DIPSWITCH,	DrvDips + 3,	"dip"		},
151 	{"Dip E",				BIT_DIPSWITCH,	DrvDips + 4,	"dip"		},
152 	{"Dip F",				BIT_DIPSWITCH,	DrvDips + 5,	"dip"		},
153 };
154 
155 STDINPUTINFO(Rampage)
156 
157 static struct BurnInputInfo PowerdrvInputList[] = {
158 	{"P1 Coin",				BIT_DIGITAL,	DrvJoy1 + 0,	"p1 coin"	},
159 	{"P1 Wheel Left",		BIT_DIGITAL,	DrvJoy2 + 2,	"p1 fire 1"	},
160 	{"P1 Wheel Right",		BIT_DIGITAL,	DrvJoy2 + 3,	"p1 fire 2"	},
161 	{"P1 Wheelie",			BIT_DIGITAL,	DrvJoy2 + 0,	"p1 fire 3"	},
162 	{"P1 Shift",			BIT_DIGITAL,	DrvJoy2 + 1,	"p1 fire 4"	},
163 
164 	{"P2 Coin",				BIT_DIGITAL,	DrvJoy1 + 1,	"p2 coin"	},
165 	{"P2 Wheel Left",		BIT_DIGITAL,	DrvJoy2 + 6,	"p2 fire 1"	},
166 	{"P2 Wheel Right",		BIT_DIGITAL,	DrvJoy2 + 7,	"p2 fire 2"	},
167 	{"P2 Wheelie",			BIT_DIGITAL,	DrvJoy2 + 4,	"p2 fire 3"	},
168 	{"P2 Shift",			BIT_DIGITAL,	DrvJoy2 + 5,	"p2 fire 4"	},
169 
170 	{"P3 Coin",				BIT_DIGITAL,	DrvJoy1 + 2,	"p3 coin"	},
171 	{"P3 Wheel Left",		BIT_DIGITAL,	DrvJoy3 + 2,	"p3 fire 1"	},
172 	{"P3 Wheel Right",		BIT_DIGITAL,	DrvJoy3 + 3,	"p3 fire 2"	},
173 	{"P3 Wheelie",			BIT_DIGITAL,	DrvJoy3 + 0,	"p3 fire 3"	},
174 	{"P3 Shift",			BIT_DIGITAL,	DrvJoy3 + 1,	"p3 fire 4"	},
175 
176 	{"Reset",				BIT_DIGITAL,	&DrvReset,		"reset"		},
177 	{"Service",				BIT_DIGITAL,	DrvJoy1 + 6,	"service"	},
178 	{"Service Mode",		BIT_DIGITAL,	DrvJoy1 + 5,	"diag"		},
179 	{"Tilt",				BIT_DIGITAL,	DrvJoy1 + 4,	"tilt"		},
180 	{"Dip A",				BIT_DIPSWITCH,	DrvDips + 0,	"dip"		},
181 	{"Dip B",				BIT_DIPSWITCH,	DrvDips + 1,	"dip"		},
182 	{"Dip C",				BIT_DIPSWITCH,	DrvDips + 2,	"dip"		},
183 	{"Dip D",				BIT_DIPSWITCH,	DrvDips + 3,	"dip"		},
184 	{"Dip E",				BIT_DIPSWITCH,	DrvDips + 4,	"dip"		},
185 	{"Dip F",				BIT_DIPSWITCH,	DrvDips + 5,	"dip"		},
186 };
187 
188 STDINPUTINFO(Powerdrv)
189 
190 static struct BurnInputInfo DemodermInputList[] = {
191 	{"P1 Coin",			BIT_DIGITAL,	DrvJoy1 + 0,	"p1 coin"	},
192 	{"P1 Start",		BIT_DIGITAL,	DrvJoy1 + 2,	"p1 start"	},
193 	A("P1 Dial", 		BIT_ANALOG_REL, &DrvAnalogPort0,"p1 x-axis"),
194 	{"P1 Button 1",		BIT_DIGITAL,	DrvJoy2 + 0,	"p1 fire 1"	},
195 	{"P1 Button 2",		BIT_DIGITAL,	DrvJoy2 + 1,	"p1 fire 2"	},
196 
197 	{"P2 Coin",			BIT_DIGITAL,	DrvJoy1 + 1,	"p2 coin"	},
198 	{"P2 Start",		BIT_DIGITAL,	DrvJoy1 + 3,	"p2 start"	},
199 	A("P2 Dial", 		BIT_ANALOG_REL, &DrvAnalogPort1,"p2 x-axis"),
200 	{"P2 Button 1",		BIT_DIGITAL,	DrvJoy3 + 0,	"p2 fire 1"	},
201 	{"P2 Button 2",		BIT_DIGITAL,	DrvJoy3 + 1,	"p2 fire 2"	},
202 
203 	{"P3 Coin",			BIT_DIGITAL,	DrvJoy5 + 0,	"p3 coin"	},
204 	{"P3 Start",		BIT_DIGITAL,	DrvJoy5 + 2,	"p3 start"	},
205 	A("P3 Dial", 		BIT_ANALOG_REL, &DrvAnalogPort2,"p3 x-axis"),
206 	{"P3 Button 1",		BIT_DIGITAL,	DrvJoy5 + 4,	"p3 fire 1"	},
207 	{"P3 Button 2",		BIT_DIGITAL,	DrvJoy5 + 5,	"p3 fire 2"	},
208 
209 	{"P4 Coin",			BIT_DIGITAL,	DrvJoy5 + 1,	"p4 coin"	},
210 	{"P4 Start",		BIT_DIGITAL,	DrvJoy5 + 3,	"p4 start"	},
211 	A("P4 Dial", 		BIT_ANALOG_REL, &DrvAnalogPort3,"p4 x-axis"),
212 	{"P4 Button 1",		BIT_DIGITAL,	DrvJoy5 + 6,	"p4 fire 1"	},
213 	{"P4 Button 2",		BIT_DIGITAL,	DrvJoy5 + 7,	"p4 fire 2"	},
214 
215 	{"Reset",			BIT_DIGITAL,	&DrvReset,		"reset"		},
216 	{"Tilt",			BIT_DIGITAL,	DrvJoy1 + 6,	"tilt"		},
217 	{"Dip A",			BIT_DIPSWITCH,	DrvDips + 0,	"dip"		},
218 	{"Dip B",			BIT_DIPSWITCH,	DrvDips + 1,	"dip"		},
219 	{"Dip C",			BIT_DIPSWITCH,	DrvDips + 2,	"dip"		},
220 	{"Dip D",			BIT_DIPSWITCH,	DrvDips + 3,	"dip"		},
221 	{"Dip E",			BIT_DIPSWITCH,	DrvDips + 4,	"dip"		},
222 	{"Dip F",			BIT_DIPSWITCH,	DrvDips + 5,	"dip"		},
223 };
224 
225 STDINPUTINFO(Demoderm)
226 
227 static struct BurnInputInfo SargeInputList[] = {
228 	{"P1 Coin",				BIT_DIGITAL,	DrvJoy1 + 0,	"p1 coin"	},
229 	{"P1 Start",			BIT_DIGITAL,	DrvJoy1 + 2,	"p1 start"	},
230 	{"P1 Left Stick Up",	BIT_DIGITAL,	DrvJoy2 + 0,	"p1 up"		},
231 	{"P1 Left Stick Down",	BIT_DIGITAL,	DrvJoy2 + 1,	"p1 down"	},
232 	{"P1 Right Stick Up",	BIT_DIGITAL,	DrvJoy2 + 2,	"p1 up 2"	},
233 	{"P1 Right Stick Down",	BIT_DIGITAL,	DrvJoy2 + 3,	"p1 down 2"	},
234 	{"P1 Button 1",			BIT_DIGITAL,	DrvJoy2 + 4,	"p1 fire 1"	},
235 	{"P1 Button 2",			BIT_DIGITAL,	DrvJoy2 + 6,	"p1 fire 2"	},
236 
237 	{"P2 Coin",				BIT_DIGITAL,	DrvJoy1 + 1,	"p2 coin"	},
238 	{"P2 Start",			BIT_DIGITAL,	DrvJoy1 + 3,	"p2 start"	},
239 	{"P2 Left Stick Up",	BIT_DIGITAL,	DrvJoy3 + 0,	"p2 up"		},
240 	{"P2 Left Stick Down",	BIT_DIGITAL,	DrvJoy3 + 1,	"p2 down"	},
241 	{"P2 Right Stick Up",	BIT_DIGITAL,	DrvJoy3 + 2,	"p2 up 2"	},
242 	{"P2 Right Stick Down",	BIT_DIGITAL,	DrvJoy3 + 3,	"p2 down 2"	},
243 	{"P2 Button 1",			BIT_DIGITAL,	DrvJoy3 + 4,	"p2 fire 1"	},
244 	{"P2 Button 2",			BIT_DIGITAL,	DrvJoy3 + 6,	"p2 fire 2"	},
245 
246 	{"Reset",				BIT_DIGITAL,	&DrvReset,		"reset"		},
247 	{"Service",				BIT_DIGITAL,	DrvJoy1 + 5,	"service"	},
248 	{"Tilt",				BIT_DIGITAL,	DrvJoy1 + 4,	"tilt"		},
249 	{"Dip A",				BIT_DIPSWITCH,	DrvDips + 0,	"dip"		},
250 	{"Dip B",				BIT_DIPSWITCH,	DrvDips + 1,	"dip"		},
251 	{"Dip C",				BIT_DIPSWITCH,	DrvDips + 2,	"dip"		},
252 	{"Dip D",				BIT_DIPSWITCH,	DrvDips + 3,	"dip"		},
253 	{"Dip E",				BIT_DIPSWITCH,	DrvDips + 4,	"dip"		},
254 	{"Dip F",				BIT_DIPSWITCH,	DrvDips + 5,	"dip"		},
255 };
256 
257 STDINPUTINFO(Sarge)
258 
259 static struct BurnInputInfo SpyhuntInputList[] = {
260 	{"Coin",				BIT_DIGITAL,	DrvJoy1 + 0,	"p1 coin"	},
261 	{"Weapons Van",			BIT_DIGITAL,	DrvJoy2 + 2,	"p1 start"	},
262 	{"Gear Shift",			BIT_DIGITAL,	DrvJoy4f + 4,	"p1 fire 2"	},
263 	{"Missiles",			BIT_DIGITAL,	DrvJoy2 + 1,	"p1 fire 3"	},
264 	{"Oil Slick",			BIT_DIGITAL,	DrvJoy2 + 0,	"p1 fire 4"	},
265 	{"Smoke Screen",		BIT_DIGITAL,	DrvJoy2 + 3,	"p1 fire 5"	},
266 	{"Machine Gun",			BIT_DIGITAL,	DrvJoy2 + 4,	"p1 fire 6"	},
267 
268 	A("P1 Wheel",       	BIT_ANALOG_REL, &DrvAnalogPort0, "p1 x-axis"),
269 	A("P1 Accelerator", 	BIT_ANALOG_REL, &DrvAnalogPort1, "p1 fire 1"),
270 
271 	{"Reset",				BIT_DIGITAL,	&DrvReset,		"reset"		},
272 	{"Service",				BIT_DIGITAL,	DrvJoy1 + 6,	"service"	},
273     {"Tilt",				BIT_DIGITAL,	DrvJoy1 + 5,	"tilt"		},
274 	{"Dip A",				BIT_DIPSWITCH,	DrvDips + 0,	"dip"		},
275 	{"Dip B",				BIT_DIPSWITCH,	DrvDips + 1,	"dip"		},
276 	{"Dip C",				BIT_DIPSWITCH,	DrvDips + 2,	"dip"		},
277 	{"Dip D",				BIT_DIPSWITCH,	DrvDips + 3,	"dip"		},
278 	{"Dip E",				BIT_DIPSWITCH,	DrvDips + 4,	"dip"		},
279 	{"Dip F",				BIT_DIPSWITCH,	DrvDips + 5,	"dip"		},
280 };
281 
282 STDINPUTINFO(Spyhunt)
283 
284 static struct BurnInputInfo MaxrpmInputList[] = {
285 	{"P1 Coin",				BIT_DIGITAL,	DrvJoy1 + 0,	"p1 coin"	},
286 	{"P1 Start",			BIT_DIGITAL,	DrvJoy1 + 3,	"p1 start"	},
287 	A("P1 Wheel",       	BIT_ANALOG_REL, &DrvAnalogPort0, "p1 x-axis"),
288 	A("P1 Accelerator", 	BIT_ANALOG_REL, &DrvAnalogPort1, "p1 fire 1"),
289 	{"P1 Shift Up",			BIT_DIGITAL,	DrvJoy4f + 0,	"p1 up"		},
290 	{"P1 Shift Down",		BIT_DIGITAL,	DrvJoy4f + 1,	"p1 down"	},
291 
292 	{"P2 Coin",				BIT_DIGITAL,	DrvJoy1 + 1,	"p2 coin"	},
293 	{"P2 Start",			BIT_DIGITAL,	DrvJoy1 + 2,	"p2 start"	},
294 	A("P2 Wheel",       	BIT_ANALOG_REL, &DrvAnalogPort2, "p2 x-axis"),
295 	A("P2 Accelerator", 	BIT_ANALOG_REL, &DrvAnalogPort3, "p2 fire 1"),
296 	{"P2 Shift Up",			BIT_DIGITAL,	DrvJoy4f + 2,	"p2 up"		},
297 	{"P2 Shift Down",		BIT_DIGITAL,	DrvJoy4f + 3,	"p2 down"	},
298 
299 	{"Reset",				BIT_DIGITAL,	&DrvReset,		"reset"		},
300 	{"Service",				BIT_DIGITAL,	DrvJoy1 + 6,	"service"	},
301 	{"Tilt",				BIT_DIGITAL,	DrvJoy1 + 4,	"tilt"		},
302 	{"Dip A",				BIT_DIPSWITCH,	DrvDips + 0,	"dip"		},
303 	{"Dip B",				BIT_DIPSWITCH,	DrvDips + 1,	"dip"		},
304 	{"Dip C",				BIT_DIPSWITCH,	DrvDips + 2,	"dip"		},
305 	{"Dip D",				BIT_DIPSWITCH,	DrvDips + 3,	"dip"		},
306 	{"Dip E",				BIT_DIPSWITCH,	DrvDips + 4,	"dip"		},
307 	{"Dip F",				BIT_DIPSWITCH,	DrvDips + 5,	"dip"		},
308 };
309 
310 STDINPUTINFO(Maxrpm)
311 
312 static struct BurnInputInfo CraterInputList[] = {
313 	{"P1 Coin",				BIT_DIGITAL,	DrvJoy1 + 0,	"p1 coin"	},
314 	{"P1 Start",			BIT_DIGITAL,	DrvJoy1 + 2,	"p1 start"	},
315 	{"P1 Up",				BIT_DIGITAL,	DrvJoy3 + 2,	"p1 up"		},
316 	{"P1 Down",				BIT_DIGITAL,	DrvJoy3 + 3,	"p1 down"	},
317 	{"P1 Left",		    	BIT_DIGITAL,	DrvJoy4f + 0,	"p1 left"	},
318 	{"P1 Right",			BIT_DIGITAL,	DrvJoy4f + 1,	"p1 right"	},
319 	A("P1 Dial", 			BIT_ANALOG_REL, &DrvAnalogPort0,"p1 x-axis"),
320 	{"P1 Button 1",			BIT_DIGITAL,	DrvJoy1 + 4,	"p1 fire 1"	},
321 	{"P1 Button 2",			BIT_DIGITAL,	DrvJoy3 + 6,	"p1 fire 2"	},
322 	{"P1 Button 3",			BIT_DIGITAL,	DrvJoy3 + 4,	"p1 fire 3"	},
323 
324 	{"Reset",				BIT_DIGITAL,	&DrvReset,		"reset"		},
325 	{"Service",				BIT_DIGITAL,	DrvJoy1 + 6,	"service"	},
326 	{"Tilt",				BIT_DIGITAL,	DrvJoy1 + 5,	"tilt"		},
327 	{"Dip A",				BIT_DIPSWITCH,	DrvDips + 0,	"dip"		},
328 	{"Dip B",				BIT_DIPSWITCH,	DrvDips + 1,	"dip"		},
329 	{"Dip C",				BIT_DIPSWITCH,	DrvDips + 2,	"dip"		},
330 	{"Dip D",				BIT_DIPSWITCH,	DrvDips + 3,	"dip"		},
331 	{"Dip E",				BIT_DIPSWITCH,	DrvDips + 4,	"dip"		},
332 	{"Dip F",				BIT_DIPSWITCH,	DrvDips + 5,	"dip"		},
333 };
334 
335 STDINPUTINFO(Crater)
336 #undef A
337 
338 static struct BurnInputInfo StargrdsInputList[] = {
339 	{"P1 Coin",				BIT_DIGITAL,	DrvJoy1 + 0,	"p1 coin"	},
340 	{"P1 Start / Weapon",	BIT_DIGITAL,	DrvJoy1 + 2,	"p1 start"	},
341     {"P1 Left Stick Up",	BIT_DIGITAL,	DrvJoy2 + 4,	"p1 up"		},
342 	{"P1 Left Stick Down",	BIT_DIGITAL,	DrvJoy2 + 5,	"p1 down"	},
343     {"P1 Left Stick Left",	BIT_DIGITAL,	DrvJoy2 + 6,	"p1 left"	},
344 	{"P1 Left Stick Right",	BIT_DIGITAL,	DrvJoy2 + 7,	"p1 right"	},
345     {"P1 Right Stick Up",	BIT_DIGITAL,	DrvJoy2 + 0,	"p1 up 2"	},
346 	{"P1 Right Stick Down",	BIT_DIGITAL,	DrvJoy2 + 1,	"p1 down 2"	},
347 	{"P1 Right Stick Left",	BIT_DIGITAL,	DrvJoy2 + 2,	"p1 left 2"	},
348 	{"P1 Right Stick Right",BIT_DIGITAL,	DrvJoy2 + 3,	"p1 right 2"},
349 
350 	{"P2 Coin",				BIT_DIGITAL,	DrvJoy1 + 1,	"p2 coin"	},
351 	{"P2 Start / Weapon",	BIT_DIGITAL,	DrvJoy1 + 3,	"p2 start"	},
352     {"P2 Left Stick Up",	BIT_DIGITAL,	DrvJoy3 + 4,	"p2 up"		},
353 	{"P2 Left Stick Down",	BIT_DIGITAL,	DrvJoy3 + 5,	"p2 down"	},
354     {"P2 Left Stick Left",	BIT_DIGITAL,	DrvJoy3 + 6,	"p2 left"	},
355 	{"P2 Left Stick Right",	BIT_DIGITAL,	DrvJoy3 + 7,	"p2 right"	},
356     {"P2 Right Stick Up",	BIT_DIGITAL,	DrvJoy3 + 0,	"p2 up 2"	},
357 	{"P2 Right Stick Down",	BIT_DIGITAL,	DrvJoy3 + 1,	"p2 down 2"	},
358 	{"P2 Right Stick Left",	BIT_DIGITAL,	DrvJoy3 + 2,	"p2 left 2"	},
359 	{"P2 Right Stick Right",BIT_DIGITAL,	DrvJoy3 + 3,	"p2 right 2"},
360 
361 	{"P3 Coin",				BIT_DIGITAL,	DrvJoy6 + 1,	"p3 coin"	},
362 	{"P3 Start / Weapon",	BIT_DIGITAL,	DrvJoy6 + 3,	"p3 start"	},
363     {"P3 Left Stick Up",	BIT_DIGITAL,	DrvJoy5 + 4,	"p3 up"		},
364 	{"P3 Left Stick Down",	BIT_DIGITAL,	DrvJoy5 + 5,	"p3 down"	},
365     {"P3 Left Stick Left",	BIT_DIGITAL,	DrvJoy5 + 6,	"p3 left"	},
366 	{"P3 Left Stick Right",	BIT_DIGITAL,	DrvJoy5 + 7,	"p3 right"	},
367     {"P3 Right Stick Up",	BIT_DIGITAL,	DrvJoy5 + 0,	"p3 up 2"	},
368 	{"P3 Right Stick Down",	BIT_DIGITAL,	DrvJoy5 + 1,	"p3 down 2"	},
369 	{"P3 Right Stick Left",	BIT_DIGITAL,	DrvJoy5 + 2,	"p3 left 2"	},
370 	{"P3 Right Stick Right",BIT_DIGITAL,	DrvJoy5 + 3,	"p3 right 2"},
371 
372 	{"Reset",				BIT_DIGITAL,	&DrvReset,		"reset"		},
373 	{"Service",				BIT_DIGITAL,	DrvJoy1 + 6,	"service"	},
374 	{"Tilt",				BIT_DIGITAL,	DrvJoy1 + 5,	"tilt"		},
375 	{"Dip A",				BIT_DIPSWITCH,	DrvDips + 0,	"dip"		},
376 	{"Dip B",				BIT_DIPSWITCH,	DrvDips + 1,	"dip"		},
377 	{"Dip C",				BIT_DIPSWITCH,	DrvDips + 2,	"dip"		},
378 	{"Dip D",				BIT_DIPSWITCH,	DrvDips + 3,	"dip"		},
379 	{"Dip E",				BIT_DIPSWITCH,	DrvDips + 4,	"dip"		},
380 	{"Dip F",				BIT_DIPSWITCH,	DrvDips + 5,	"dip"		},
381 };
382 
383 STDINPUTINFO(Stargrds)
384 
385 static struct BurnDIPInfo StargrdsDIPList[]=
386 {
387 	{0x21, 0xff, 0xff, 0xff, NULL							},
388 	{0x22, 0xff, 0xff, 0xff, NULL							},
389 	{0x23, 0xff, 0xff, 0xff, NULL							},
390 	{0x24, 0xff, 0xff, 0xff, NULL							},
391 	{0x25, 0xff, 0xff, 0xff, NULL							},
392 	{0x26, 0xff, 0xff, 0x80, NULL							},
393 
394 	{0   , 0xfe, 0   ,    4, "Energy Units"					},
395 	{0x24, 0x01, 0x0c, 0x08, "8"							},
396 	{0x24, 0x01, 0x0c, 0x0c, "10"							},
397 	{0x24, 0x01, 0x0c, 0x04, "12"							},
398 	{0x24, 0x01, 0x0c, 0x00, "14"							},
399 
400 	{0   , 0xfe, 0   ,    2, "Demo Sounds"					},
401 	{0x24, 0x01, 0x20, 0x00, "Off"							},
402 	{0x24, 0x01, 0x20, 0x20, "On"							},
403 
404 	{0   , 0xfe, 0   ,    4, "Difficulty"					},
405 	{0x24, 0x01, 0xc0, 0x80, "Easy"							},
406 	{0x24, 0x01, 0xc0, 0xc0, "Medium"						},
407 	{0x24, 0x01, 0xc0, 0x40, "Hard"							},
408 	{0x24, 0x01, 0xc0, 0x00, "Hardest"						},
409 
410     {0   , 0xfe, 0   ,    2, "Service Mode"					},
411 	{0x26, 0x01, 0x80, 0x80, "Off"							},
412 	{0x26, 0x01, 0x80, 0x00, "On"							},
413 };
414 
415 STDDIPINFO(Stargrds)
416 
417 static struct BurnDIPInfo PowerdrvDIPList[]=
418 {
419 	{0x13, 0xff, 0xff, 0xff, NULL							},
420 	{0x14, 0xff, 0xff, 0xff, NULL							},
421 	{0x15, 0xff, 0xff, 0xff, NULL							},
422 	{0x16, 0xff, 0xff, 0xff, NULL							},
423 	{0x17, 0xff, 0xff, 0xff, NULL							},
424 	{0x18, 0xff, 0xff, 0x20, NULL							},
425 
426 	{0   , 0xfe, 0   ,    3, "Coinage"						},
427 	{0x16, 0x01, 0x03, 0x02, "2 Coins 1 Credits"			},
428 	{0x16, 0x01, 0x03, 0x03, "1 Coin  1 Credits"			},
429 	{0x16, 0x01, 0x03, 0x01, "1 Coin  2 Credits"			},
430 
431 	{0   , 0xfe, 0   ,    4, "Difficulty"					},
432 	{0x16, 0x01, 0x30, 0x20, "Easy"							},
433 	{0x16, 0x01, 0x30, 0x30, "Factory"						},
434 	{0x16, 0x01, 0x30, 0x10, "Hard"							},
435 	{0x16, 0x01, 0x30, 0x00, "Hardest"						},
436 
437 	{0   , 0xfe, 0   ,    2, "Demo Sounds"					},
438 	{0x16, 0x01, 0x40, 0x00, "Off"							},
439 	{0x16, 0x01, 0x40, 0x40, "On"							},
440 
441 	{0   , 0xfe, 0   ,    2, "Rack Advance (Cheat)"			},
442 	{0x16, 0x01, 0x80, 0x80, "Off"							},
443 	{0x16, 0x01, 0x80, 0x00, "On"							},
444 
445     {0   , 0xfe, 0   ,    2, "Service Mode"					},
446 	{0x18, 0x01, 0x20, 0x20, "Off"							},
447 	{0x18, 0x01, 0x20, 0x00, "On"							},
448 };
449 
450 STDDIPINFO(Powerdrv)
451 
452 static struct BurnDIPInfo RampageDIPList[]=
453 {
454 	{0x17, 0xff, 0xff, 0xff, NULL							},
455 	{0x18, 0xff, 0xff, 0xff, NULL							},
456 	{0x19, 0xff, 0xff, 0xff, NULL							},
457 	{0x1a, 0xff, 0xff, 0xff, NULL							},
458 	{0x1b, 0xff, 0xff, 0xff, NULL							},
459 	{0x1c, 0xff, 0xff, 0x20, NULL							},
460 
461 	{0   , 0xfe, 0   ,    4, "Difficulty"					},
462 	{0x1a, 0x01, 0x03, 0x02, "Easy"							},
463 	{0x1a, 0x01, 0x03, 0x03, "Normal"						},
464 	{0x1a, 0x01, 0x03, 0x01, "Hard"							},
465 	{0x1a, 0x01, 0x03, 0x00, "Free Play"					},
466 
467 	{0   , 0xfe, 0   ,    2, "Score Option"					},
468 	{0x1a, 0x01, 0x04, 0x04, "Keep score when continuing"	},
469 	{0x1a, 0x01, 0x04, 0x00, "Lose score when continuing"	},
470 
471 	{0   , 0xfe, 0   ,    2, "Coin A"						},
472 	{0x1a, 0x01, 0x08, 0x00, "2 Coins 1 Credits"			},
473 	{0x1a, 0x01, 0x08, 0x08, "1 Coin  1 Credits"			},
474 
475 	{0   , 0xfe, 0   ,    8, "Coin B"						},
476 	{0x1a, 0x01, 0x70, 0x00, "3 Coins 1 Credits"			},
477 	{0x1a, 0x01, 0x70, 0x10, "2 Coins 1 Credits"			},
478 	{0x1a, 0x01, 0x70, 0x70, "1 Coin  1 Credits"			},
479 	{0x1a, 0x01, 0x70, 0x60, "1 Coin  2 Credits"			},
480 	{0x1a, 0x01, 0x70, 0x50, "1 Coin  3 Credits"			},
481 	{0x1a, 0x01, 0x70, 0x40, "1 Coin  4 Credits"			},
482 	{0x1a, 0x01, 0x70, 0x30, "1 Coin  5 Credits"			},
483 	{0x1a, 0x01, 0x70, 0x20, "1 Coin  6 Credits"			},
484 
485 	{0   , 0xfe, 0   ,    2, "Rack Advance (Cheat)"			},
486 	{0x1a, 0x01, 0x80, 0x80, "Off"							},
487 	{0x1a, 0x01, 0x80, 0x00, "On"							},
488 
489     {0   , 0xfe, 0   ,    2, "Service Mode"					},
490 	{0x1c, 0x01, 0x20, 0x20, "Off"							},
491 	{0x1c, 0x01, 0x20, 0x00, "On"							},
492 };
493 
494 STDDIPINFO(Rampage)
495 
496 static struct BurnDIPInfo DemodermDIPList[]=
497 {
498 	{0x16, 0xff, 0xff, 0xff, NULL							},
499 	{0x17, 0xff, 0xff, 0xff, NULL							},
500 	{0x18, 0xff, 0xff, 0xff, NULL							},
501 	{0x19, 0xff, 0xff, 0xff, NULL							},
502 	{0x1a, 0xff, 0xff, 0xff, NULL							},
503 	{0x1b, 0xff, 0xff, 0x20, NULL							},
504 
505 	{0   , 0xfe, 0   ,    2, "Cabinet"						},
506 	{0x19, 0x01, 0x01, 0x01, "2P Upright"					},
507 	{0x19, 0x01, 0x01, 0x00, "4P Cocktail"					},
508 
509 	{0   , 0xfe, 0   ,    2, "Difficulty"					},
510 	{0x19, 0x01, 0x02, 0x02, "Normal"						},
511 	{0x19, 0x01, 0x02, 0x00, "Harder"						},
512 
513 	{0   , 0xfe, 0   ,    2, "Free Play"					},
514 	{0x19, 0x01, 0x04, 0x04, "Off"							},
515 	{0x19, 0x01, 0x04, 0x00, "On"							},
516 
517 	{0   , 0xfe, 0   ,    2, "Reward Screen"				},
518 	{0x19, 0x01, 0x08, 0x08, "Expanded"						},
519 	{0x19, 0x01, 0x08, 0x00, "Limited"						},
520 
521 	{0   , 0xfe, 0   ,    4, "Coinage"						},
522 	{0x19, 0x01, 0x30, 0x20, "2 Coins 1 Credits"			},
523 	{0x19, 0x01, 0x30, 0x00, "2 Coins 2 Credits"			},
524 	{0x19, 0x01, 0x30, 0x30, "1 Coin  1 Credits"			},
525 	{0x19, 0x01, 0x30, 0x10, "1 Coin  2 Credits"			},
526 
527     {0   , 0xfe, 0   ,    2, "Service Mode"					},
528 	{0x1b, 0x01, 0x20, 0x20, "Off"							},
529 	{0x1b, 0x01, 0x20, 0x00, "On"							},
530 };
531 
532 STDDIPINFO(Demoderm)
533 
534 static struct BurnDIPInfo SargeDIPList[]=
535 {
536 	{0x13, 0xff, 0xff, 0xff, NULL							},
537 	{0x14, 0xff, 0xff, 0xff, NULL							},
538 	{0x15, 0xff, 0xff, 0xff, NULL							},
539 	{0x16, 0xff, 0xff, 0xff, NULL							},
540 	{0x17, 0xff, 0xff, 0xff, NULL							},
541 	{0x18, 0xff, 0xff, 0x20, NULL							},
542 
543 	{0   , 0xfe, 0   ,    2, "Free Play"					},
544 	{0x16, 0x01, 0x08, 0x08, "Off"							},
545 	{0x16, 0x01, 0x08, 0x00, "On"							},
546 
547 	{0   , 0xfe, 0   ,    3, "Coinage"						},
548 	{0x16, 0x01, 0x30, 0x20, "2 Coins 1 Credits"			},
549 	{0x16, 0x01, 0x30, 0x30, "1 Coin  1 Credits"			},
550 	{0x16, 0x01, 0x30, 0x10, "1 Coin  2 Credits"			},
551 
552     {0   , 0xfe, 0   ,    2, "Service Mode"					},
553 	{0x18, 0x01, 0x20, 0x20, "Off"							},
554 	{0x18, 0x01, 0x20, 0x00, "On"							},
555 };
556 
557 STDDIPINFO(Sarge)
558 
559 static struct BurnDIPInfo SpyhuntDIPList[]=
560 {
561 	{0x0c, 0xff, 0xff, 0xff, NULL							},
562 	{0x0d, 0xff, 0xff, 0xff, NULL							},
563 	{0x0e, 0xff, 0xff, 0xff, NULL							},
564 	{0x0f, 0xff, 0xff, 0xff, NULL							},
565 	{0x10, 0xff, 0xff, 0xff, NULL							},
566 	{0x11, 0xff, 0xff, 0x80, NULL							},
567 
568 	{0   , 0xfe, 0   ,    2, "Game Timer"					},
569 	{0x0f, 0x01, 0x01, 0x00, "1:00"							},
570 	{0x0f, 0x01, 0x01, 0x01, "1:30"							},
571 
572 	{0   , 0xfe, 0   ,    2, "Demo Sounds"					},
573 	{0x0f, 0x01, 0x02, 0x02, "Off"							},
574 	{0x0f, 0x01, 0x02, 0x00, "On"							},
575 
576     {0   , 0xfe, 0   ,    2, "Service Mode"					},
577 	{0x11, 0x01, 0x80, 0x80, "Off"							},
578 	{0x11, 0x01, 0x80, 0x00, "On"							},
579 };
580 
581 STDDIPINFO(Spyhunt)
582 
583 static struct BurnDIPInfo MaxrpmDIPList[]=
584 {
585 	{0x0f, 0xff, 0xff, 0xff, NULL							},
586 	{0x10, 0xff, 0xff, 0xff, NULL							},
587 	{0x11, 0xff, 0xff, 0xff, NULL							},
588 	{0x12, 0xff, 0xff, 0xff, NULL							},
589 	{0x13, 0xff, 0xff, 0xff, NULL							},
590 	{0x14, 0xff, 0xff, 0x80, NULL							},
591 
592 	{0   , 0xfe, 0   ,    2, "Free Play"					},
593 	{0x12, 0x01, 0x08, 0x08, "Off"							},
594 	{0x12, 0x01, 0x08, 0x00, "On"							},
595 
596 	{0   , 0xfe, 0   ,    3, "Coinage"						},
597 	{0x12, 0x01, 0x30, 0x20, "2 Coins 1 Credits"			},
598 	{0x12, 0x01, 0x30, 0x30, "1 Coin  1 Credits"			},
599 	{0x12, 0x01, 0x30, 0x10, "1 Coin  2 Credits"			},
600 
601 	{0   , 0xfe, 0   ,    2, "Service Mode"					},
602 	{0x14, 0x01, 0x80, 0x80, "Off"							},
603 	{0x14, 0x01, 0x80, 0x00, "On"							},
604 };
605 
606 STDDIPINFO(Maxrpm)
607 
608 static struct BurnDIPInfo CraterDIPList[]=
609 {
610 	{0x0d, 0xff, 0xff, 0xff, NULL							},
611 	{0x0e, 0xff, 0xff, 0xff, NULL							},
612 	{0x0f, 0xff, 0xff, 0xff, NULL							},
613 	{0x10, 0xff, 0xff, 0xff, NULL							},
614 	{0x11, 0xff, 0xff, 0xff, NULL							},
615 	{0x12, 0xff, 0xff, 0x80, NULL							},
616 
617     {0   , 0xfe, 0   ,    2, "Service Mode"					},
618 	{0x12, 0x01, 0x80, 0x80, "Off"							},
619 	{0x12, 0x01, 0x80, 0x00, "On"							},
620 };
621 
STDDIPINFO(Crater)622 STDDIPINFO(Crater)
623 
624 static UINT8 soundsgood_input_read(UINT8 address)
625 {
626 	address &= 7;
627 	UINT8 ret = DrvInputs[address];
628 
629 	if (sound_input_bank == address)
630 	{
631 		ret &= ~(1 << sound_status_bit);
632 		if (soundsgood_status_read()) ret |= 1 << sound_status_bit;
633 	}
634 
635 //	bprintf (0, _T("Input: %d, %2.2x\n"), address, ret);
636 
637 	return ret;
638 }
639 
mcrmono_write(UINT16 address,UINT8 data)640 static void __fastcall mcrmono_write(UINT16 address, UINT8 data)
641 {
642 	if ((address & 0xfc00) == 0xec00) {
643 		DrvPalRAM16[(address >> 1) & 0x3f] = data | ((address & 1) << 8);
644 		return;
645 	}
646 
647 	if ((address & 0xf000) != 0xf000)
648 		bprintf (0, _T("MW: %4.4x, %2.2x\n"), address, data);
649 }
650 
mcrmono_read(UINT16 address)651 static UINT8 __fastcall mcrmono_read(UINT16 address)
652 {
653 	bprintf (0, _T("MR: %4.4x\n"), address);
654 
655 	return 0;
656 }
657 
mcrmono_write_port(UINT16 address,UINT8 data)658 static void __fastcall mcrmono_write_port(UINT16 address, UINT8 data)
659 {
660 	address &= 0xff;
661 
662 //	bprintf (0, _T("WP: %2.2x, %2.2x\n"), address & 0xff, data);
663 
664 	if (port_write_handler) {
665 		if (port_write_handler(address, data) != -1) return;
666 	}
667 
668 	switch (address)
669 	{
670 		case 0x05:
671 			// coin counter = data & 0x01
672 			flipscreen = (data & 0x40) >> 6;
673 		return;
674 
675 		//case 0x06:
676 		//return;
677 
678 		case 0x07:
679 			BurnWatchdogWrite();
680 		return;
681 
682 		case 0xf0:
683 		case 0xf1:
684 		case 0xf2:
685 		case 0xf3:
686 			z80ctc_write(address & 3, data);
687 		return;
688 	}
689 }
690 
mcrmono_read_port(UINT16 address)691 static UINT8 __fastcall mcrmono_read_port(UINT16 address)
692 {
693 	address &= 0xff;
694 
695 //	bprintf (0, _T("RP: %2.2x\n"), address & 0xff);
696 
697 	if (port_read_handler) {
698 		INT32 ret = port_read_handler(address);
699 		if (ret != -1) return ret;
700 	}
701 
702 	switch (address & ~3)
703 	{
704 		case 0x00:
705 		case 0x04:
706 			return soundsgood_input_read(address);
707 
708 		case 0xf0:
709 			return z80ctc_read(address & 3);
710 	}
711 
712 	return 0;
713 }
spyhunt_write(UINT16 address,UINT8 data)714 static void __fastcall spyhunt_write(UINT16 address, UINT8 data)
715 {
716 	if ((address & 0xfe00) == 0xfa00) {
717 		DrvPalRAM16[(address >> 1) & 0x3f] = data | ((address & 1) << 8);
718 		return;
719 	}
720 }
721 
spyhunt_write_port(UINT16 address,UINT8 data)722 static void __fastcall spyhunt_write_port(UINT16 address, UINT8 data)
723 {
724 	switch (address & 0xff)
725 	{
726 		case 0x00:
727 		case 0x01:
728 		case 0x02:
729 		case 0x03:
730 			// coin counter = data & 0x01
731 			flipscreen = (data & 0x40) >> 6;
732 		break; // yes!
733 
734 		case 0x84:
735 			scrollx = (scrollx & 0x700) | data;
736 		return;
737 
738 		case 0x85:
739 			scrollx = (scrollx & 0x0ff) | ((data & 7) << 8);
740 			scrolly = (scrolly & 0x0ff) | ((data >> 7) << 8);
741 		return;
742 
743 		case 0x86:
744 			scrolly = (scrolly & 0x100) | data;
745 		return;
746 
747 		case 0xe0:
748 			BurnWatchdogWrite();
749 		return;
750 
751 		case 0xe8:
752 		return; // nop
753 
754 		case 0xf0:
755 		case 0xf1:
756 		case 0xf2:
757 		case 0xf3:
758 			z80ctc_write(address & 3, data);
759 		return;
760 	}
761 
762 	ssio_write_ports(address, data);
763 }
764 
spyhunt_read_port(UINT16 address)765 static UINT8 __fastcall spyhunt_read_port(UINT16 address)
766 {
767 	switch (address & ~3)
768 	{
769 		case 0xf0:
770 			return z80ctc_read(address & 3);
771 	}
772 
773 	return ssio_read_ports(address);
774 }
775 
ctc_interrupt(INT32 state)776 static void ctc_interrupt(INT32 state)
777 {
778     if (state) ZetSetIRQLine(0, CPU_IRQSTATUS_HOLD);
779     //ZetSetIRQLine(0, state ? CPU_IRQSTATUS_ACK : CPU_IRQSTATUS_NONE);
780 }
781 
tilemap_callback(bg)782 static tilemap_callback( bg )
783 {
784 	INT32 attr = DrvVidRAM[offs * 2 + 1];
785 	INT32 code = DrvVidRAM[offs * 2 + 0] | ((attr & 0x03) << 8) | ((attr & 0x40) << 4);
786 
787 	TILE_SET_INFO(0, code, (attr >> 4) ^ 3, TILE_FLIPYX(attr >> 2));
788 }
789 
tilemap_scan(spybg)790 static tilemap_scan( spybg )
791 {
792 	return (row & 0x0f) | ((col & 0x3f) << 4) | ((row & 0x10) << 6);
793 }
794 
tilemap_callback(spybg)795 static tilemap_callback( spybg )
796 {
797 	INT32 attr = DrvVidRAM[offs];
798 
799 	TILE_SET_INFO(0, (attr & 0x3f) | ((attr >> 7) << 6), 0, (attr & 0x40) ? TILE_FLIPY : 0);
800 }
801 
tilemap_callback(txt)802 static tilemap_callback( txt )
803 {
804 	TILE_SET_INFO(1, DrvTxtRAM[offs], 0, 0);
805 }
806 
DrvDoReset(INT32 clear_mem)807 static INT32 DrvDoReset(INT32 clear_mem)
808 {
809 	if (clear_mem) {
810 		memset (AllRam, 0, RamEnd - AllRam);
811 	}
812 
813 	ZetOpen(0);
814 	ZetReset();
815 	ZetClose();
816 
817 	csd_reset();
818 	tcs_reset();
819 	soundsgood_reset();
820 	ssio_reset();
821 
822 	BurnWatchdogReset();
823 
824     if (has_shift) BurnShiftReset();
825 
826 	input_mux = 0;
827 	flipscreen = 0;
828 	scrollx = 0;
829 	scrolly = 0;
830 	latched_input = 0;
831 
832     lamp = 0;
833     last_op4 = 0;
834 
835 	// powerdrv shifters
836 	memset(pd_shift, 0, sizeof(pd_shift));
837 	memset(pd_shift_prev, 0, sizeof(pd_shift_prev));
838 
839     nExtraCycles[0] = nExtraCycles[1] = nExtraCycles[2] = 0;
840 
841     return 0;
842 }
843 
MemIndex()844 static INT32 MemIndex()
845 {
846 	UINT8 *Next; Next = AllMem;
847 
848 	DrvZ80ROM0		= Next; Next += 0x010000;
849 	DrvZ80ROM1		= Next; Next += 0x010000;
850 	DrvSndROM		= Next;
851 	Drv68KROM		= Next; Next += 0x040000;
852 
853 	DrvGfxROM0		= Next; Next += 0x080000;
854 	DrvGfxROM1		= Next; Next += 0x080000 + (32 * 32 * 8);
855 	DrvGfxROM2		= Next; Next += 0x010000;
856 
857 	DrvSndPROM		= Next; Next += 0x000020;
858 
859 	DrvTransTab[0]	= Next; Next += 0x000040;
860 	DrvTransTab[1]	= Next; Next += 0x000040;
861 
862 	DrvPalette		= (UINT32*)Next; Next += 0x044 * sizeof(UINT32);
863 
864 	DrvNVRAM		= Next; Next += 0x000800;
865 
866 	AllRam			= Next;
867 
868 	DrvSprRAM		= Next; Next += 0x000400;
869 	DrvVidRAM		= Next; Next += 0x000800;
870 	DrvPalRAM16		= (UINT16*)Next; Next += 0x000040 * sizeof(UINT16);
871 	DrvSndRAM		= Next; Next += 0x001000;
872 	Drv68KRAM		= Next; Next += 0x001000;
873 	DrvTxtRAM		= Next; Next += 0x000400;
874 	DrvZ80RAM1		= Next; Next += 0x000400;
875 
876 	RamEnd			= Next;
877 
878 	MemEnd			= Next;
879 
880 	return 0;
881 }
882 
DrvBuildTransTab()883 static void DrvBuildTransTab()
884 {
885 	for (INT32 i = 0; i < 16*4; i++) { // 4bpp pixels * 4 color banks
886 		DrvTransTab[0][i] = (0x0101 & (1 << (i & 0xf))) ? 0xff : 0;
887 		DrvTransTab[1][i] = (0xfeff & (1 << (i & 0xf))) ? 0xff : 0;
888 	}
889 }
890 
copy_and_rotate(UINT8 * src,UINT8 * dst)891 static void copy_and_rotate(UINT8 *src, UINT8 *dst)
892 {
893 	for (INT32 y = 0; y < 32; y++)
894 	{
895 		for (INT32 x = 0; x < 32; x++)
896 		{
897 			dst[(y * 32) + x] = src[(31-x)*32+y];
898 		}
899 	}
900 }
901 
DrvGfxDecode()902 static INT32 DrvGfxDecode()
903 {
904 	INT32 Plane0[4]  = { (nGraphicsLen[0]/2)*8+0, (nGraphicsLen[0]/2)*8+1, 0, 1 };
905 	INT32 XOffs0[16] = { STEP8(0,2) };
906 	INT32 YOffs0[16] = { STEP8(0,16) };
907 
908 	INT32 L = (nGraphicsLen[1]/4)*8;
909 	INT32 Plane1[4]  = { STEP4(0,1) };
910 	INT32 XOffs1[32] = {
911 		L*0+0, L*0+4, L*1+0, L*1+4, L*2+0, L*2+4, L*3+0, L*3+4,
912 		L*0+0+8, L*0+4+8, L*1+0+8, L*1+4+8, L*2+0+8, L*2+4+8, L*3+0+8, L*3+4+8,
913 		L*0+0+16, L*0+4+16, L*1+0+16, L*1+4+16, L*2+0+16, L*2+4+16, L*3+0+16, L*3+4+16,
914 		L*0+0+24, L*0+4+24, L*1+0+24, L*1+4+24, L*2+0+24, L*2+4+24, L*3+0+24, L*3+4+24
915 	};
916 	INT32 YOffs1[32] = { STEP32(0,32) };
917 
918 	UINT8 *tmp = (UINT8*)BurnMalloc(0x40000);
919 	if (tmp == NULL) {
920 		return 1;
921 	}
922 
923 	GfxDecode((nGraphicsLen[0] * 2) / (8 * 8), 4, 8, 8, Plane0, XOffs0, YOffs0, 0x080, DrvGfxROM0, tmp);
924 
925 	for (INT32 i = 0; i < nGraphicsLen[0] * 2; i+=0x40) { // 2x size and invert pixel
926 		for (INT32 y = 0; y < 16; y++) {
927 			for (INT32 x = 0; x < 16; x++) {
928 				DrvGfxROM0[(i * 4) + (y * 16) + x] = tmp[i + ((y / 2) * 8) + (x / 2)] ^ 0xf;
929 			}
930 		}
931 	}
932 
933 	memcpy (tmp, DrvGfxROM1, nGraphicsLen[1]);
934 
935 	GfxDecode((nGraphicsLen[1] * 2) / (32 * 32), 4, 32, 32, Plane1, XOffs1, YOffs1, 0x400, tmp, DrvGfxROM1);
936 
937 	BurnFree(tmp);
938 
939 	return 0;
940 }
941 
SpyhuntGfxDecode()942 static INT32 SpyhuntGfxDecode()
943 {
944 	INT32 Plane0[2] = { 0, 1 };
945 	INT32 XOffs0[16] = { 0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14 };
946 	INT32 YOffs0[16] = { 0, 0, 16, 16, 32, 32, 48, 48, 64, 64, 80, 80, 96, 96, 112, 112 };
947 
948 	INT32 L = (nGraphicsLen[1]/4)*8;
949 	INT32 Plane1[4]  = { STEP4(0,1) };
950 	INT32 XOffs1[32] = {
951 		L*0+0, L*0+4, L*1+0, L*1+4, L*2+0, L*2+4, L*3+0, L*3+4,
952 		L*0+0+8, L*0+4+8, L*1+0+8, L*1+4+8, L*2+0+8, L*2+4+8, L*3+0+8, L*3+4+8,
953 		L*0+0+16, L*0+4+16, L*1+0+16, L*1+4+16, L*2+0+16, L*2+4+16, L*3+0+16, L*3+4+16,
954 		L*0+0+24, L*0+4+24, L*1+0+24, L*1+4+24, L*2+0+24, L*2+4+24, L*3+0+24, L*3+4+24
955 	};
956 	INT32 YOffs1[32] = { STEP32(0,32) };
957 
958 	INT32 Plane2[4]  = { (nGraphicsLen[0]/2)*8+0, (nGraphicsLen[0]/2)*8+1, 0, 1 };
959 	INT32 XOffs2[64] = {
960 			0,  0,  2,  2,  4,  4,  6,  6,  8,  8, 10, 10, 12, 12, 14, 14,
961 			16, 16, 18, 18, 20, 20, 22, 22, 24, 24, 26, 26, 28, 28, 30, 30,
962 			32, 32, 34, 34, 36, 36, 38, 38, 40, 40, 42, 42, 44, 44, 46, 46,
963 			48, 48, 50, 50, 52, 52, 54, 54, 56, 56, 58, 58, 60, 60, 62, 62
964 	};
965 	INT32 YOffs2[32] = {
966 			0*32,  0*32,  2*32,  2*32,  4*32,  4*32,  6*32,  6*32,
967 			8*32,  8*32, 10*32, 10*32, 12*32, 12*32, 14*32, 14*32,
968 			16*32, 16*32, 18*32, 18*32, 20*32, 20*32, 22*32, 22*32,
969 			24*32, 24*32, 26*32, 26*32, 28*32, 28*32, 30*32, 30*32
970 	};
971 
972 	UINT8 *tmp = (UINT8*)BurnMalloc(0x40000);
973 	if (tmp == NULL) {
974 		return 1;
975 	}
976 
977 	memcpy (tmp, DrvGfxROM0, nGraphicsLen[0]);
978 
979 	GfxDecode((nGraphicsLen[0] * 8) / (64 * 32), 4, 64, 32, Plane2, XOffs2, YOffs2, 0x400, tmp, DrvGfxROM0);
980 
981 	memcpy (tmp, DrvGfxROM1, nGraphicsLen[1]);
982 
983 	GfxDecode((nGraphicsLen[1] * 2) / (32 * 32), 4, 32, 32, Plane1, XOffs1, YOffs1, 0x400, tmp, DrvGfxROM1);
984 
985 	memcpy (tmp, DrvGfxROM2, nGraphicsLen[2]);
986 
987 	GfxDecode((nGraphicsLen[2] * 8 * 2) / (16 * 16), 2, 16, 16, Plane0, XOffs0, YOffs0, 0x080, tmp, DrvGfxROM2);
988 
989 	BurnFree(tmp);
990 
991 	return 0;
992 }
993 
ctc_trigger(INT32,UINT8 data)994 static void ctc_trigger(INT32 , UINT8 data)
995 {
996 	z80ctc_trg_write(1, data);
997 }
998 
sound_system_init(INT32 sound_system)999 static void sound_system_init(INT32 sound_system)
1000 {
1001 	BurnLoadRom(DrvSndPROM + 0x00000, 0x80, 1);
1002 
1003 	switch (sound_system)
1004 	{
1005 		case 0: soundsgood_init(0, 0, Drv68KROM, Drv68KRAM); break;
1006 		case 1: tcs_init(0, 0, 0, DrvSndROM, DrvSndRAM); break;
1007 
1008 		case 2:
1009 		{
1010 			csd_init(Drv68KROM, Drv68KRAM);
1011 			ssio_init(DrvZ80ROM1, DrvZ80RAM1, DrvSndPROM);
1012 		}
1013 		break;
1014 
1015 		case 3:
1016 		{
1017 			ssio_init(DrvZ80ROM1, DrvZ80RAM1, DrvSndPROM);
1018 		}
1019 		break;
1020 
1021         case 4: csd_init(Drv68KROM, Drv68KRAM); break;
1022 	}
1023 
1024 	ssio_inputs = DrvInputs;
1025 	ssio_dips = 0xff; // unused in mcr3
1026 }
1027 
DrvLoadRoms(bool bLoad)1028 static INT32 DrvLoadRoms(bool bLoad)
1029 {
1030 	char* pRomName;
1031 	struct BurnRomInfo ri;
1032 	UINT8 *pLoad[4] = { DrvZ80ROM0, DrvZ80ROM1, DrvSndROM, Drv68KROM };
1033 	UINT8 *gLoad[3] = { DrvGfxROM0, DrvGfxROM1, DrvGfxROM2 };
1034 
1035 	for (INT32 i = 0; !BurnDrvGetRomName(&pRomName, i, 0); i++)
1036 	{
1037 		BurnDrvGetRomInfo(&ri, i);
1038 
1039 		if ((ri.nType & BRF_PRG) && ((ri.nType & 7) <= 2)) {
1040 			INT32 type = (ri.nType - 1) & 1;
1041             if (bLoad) if (BurnLoadRom(pLoad[type], i, 1)) return 1;
1042 			pLoad[type] += ri.nLen;
1043 			continue;
1044 		}
1045 
1046 		if ((ri.nType & BRF_PRG) && ((ri.nType & 7) == 3)) {
1047 			INT32 type = 2;
1048             if (bLoad) {
1049 				memmove (pLoad[type], pLoad[type] + ri.nLen, 0x10000 - ri.nLen); // m6809 loaded at end of mem space
1050 				if (BurnLoadRom(pLoad[type] + 0x10000 - ri.nLen, i, 1)) return 1;
1051 			}
1052 			continue;
1053 		}
1054 
1055 		if ((ri.nType & BRF_PRG) && ((ri.nType & 7) == 4)) {
1056 			INT32 type = 3;
1057             if (bLoad) {
1058 				if (BurnLoadRom(pLoad[type] + 1, i, 2)) return 1;
1059 				if (BurnLoadRom(pLoad[type] + 0, i+1, 2)) return 1;
1060 			}
1061 			i++;
1062 			pLoad[type] += ri.nLen * 2;
1063 			continue;
1064 		}
1065 
1066 		if ((ri.nType & BRF_GRA) && ((ri.nType & 7) <= 3)) {
1067 			INT32 type = (ri.nType - 1) & 3;
1068 			if (bLoad) if (BurnLoadRom(gLoad[type], i, 1)) return 1;
1069 			gLoad[type] += ri.nLen;
1070 			continue;
1071 		}
1072 	}
1073 
1074 	nGraphicsLen[0] = gLoad[0] - DrvGfxROM0;
1075 	nGraphicsLen[1] = gLoad[1] - DrvGfxROM1;
1076 	nGraphicsLen[2] = gLoad[2] - DrvGfxROM2;
1077 
1078 	return 0;
1079 }
1080 
DrvInit(INT32 sound_system)1081 static INT32 DrvInit(INT32 sound_system)
1082 {
1083 	BurnSetRefreshRate(30.00);
1084 
1085 	AllMem = NULL;
1086 	MemIndex();
1087 	INT32 nLen = MemEnd - (UINT8 *)0;
1088 	if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1;
1089 	memset(AllMem, 0, nLen);
1090 	MemIndex();
1091 
1092 	if (DrvLoadRoms(true)) return 1;
1093 
1094 	DrvGfxDecode();
1095 	DrvBuildTransTab();
1096 
1097 	memset (DrvZ80ROM0 + 0xf800, 0xff, 0x800); // unmapped
1098 
1099 	ZetInit(0);
1100 	ZetOpen(0);
1101 	ZetMapMemory(DrvZ80ROM0,			0x0000, 0xdfff, MAP_ROM);
1102 	ZetMapMemory(DrvNVRAM,				0xe000, 0xe7ff, MAP_RAM);
1103 	ZetMapMemory(DrvSprRAM,				0xe800, 0xebff, MAP_RAM);
1104 	ZetMapMemory(DrvVidRAM,				0xf000, 0xf7ff, MAP_RAM);
1105 	ZetMapMemory(DrvZ80ROM0 + 0xf800,	0xf800, 0xffff, MAP_ROM);
1106 	ZetSetWriteHandler(mcrmono_write);
1107 	ZetSetReadHandler(mcrmono_read);
1108 	ZetSetInHandler(mcrmono_read_port);
1109 	ZetSetOutHandler(mcrmono_write_port);
1110 
1111     ZetDaisyInit(Z80_CTC, 0);
1112 	z80ctc_init(5000000, 0, ctc_interrupt, ctc_trigger, NULL, NULL);
1113 	ZetClose();
1114 
1115 	sound_system_init(sound_system);
1116 
1117 	BurnWatchdogInit(DrvDoReset, -1); // power drive doesn't like 16
1118 
1119 	GenericTilesInit();
1120 	GenericTilemapInit(0, TILEMAP_SCAN_ROWS, bg_map_callback, 16, 16, 32, 30);
1121 	GenericTilemapSetGfx(0, DrvGfxROM0, 4, 16, 16, (nGraphicsLen[0] * 2 * 2 * 2), 0, 3);
1122 
1123     BurnTrackballInit(2);
1124 
1125 	DrvDoReset(1);
1126 
1127 	return 0;
1128 }
1129 
SpyhuntCommonInit(INT32 sound_system)1130 static INT32 SpyhuntCommonInit(INT32 sound_system)
1131 {
1132 	BurnSetRefreshRate(30.00);
1133 
1134 	AllMem = NULL;
1135 	MemIndex();
1136 	INT32 nLen = MemEnd - (UINT8 *)0;
1137 	if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1;
1138 	memset(AllMem, 0, nLen);
1139 	MemIndex();
1140 
1141 	if (DrvLoadRoms(true)) return 1;
1142 
1143 	SpyhuntGfxDecode();
1144 	DrvBuildTransTab();
1145 
1146 	ZetInit(0);
1147 	ZetOpen(0);
1148 	ZetMapMemory(DrvZ80ROM0,		0x0000, 0xdfff, MAP_ROM);
1149 	ZetMapMemory(DrvVidRAM,			0xe000, 0xe7ff, MAP_RAM);
1150 	ZetMapMemory(DrvTxtRAM,			0xe800, 0xebff, MAP_RAM);
1151 	ZetMapMemory(DrvTxtRAM,			0xec00, 0xefff, MAP_RAM);
1152 	ZetMapMemory(DrvNVRAM,			0xf000, 0xf7ff, MAP_RAM);
1153 	ZetMapMemory(DrvSprRAM,			0xf800, 0xf9ff, MAP_RAM);
1154 	ZetSetWriteHandler(spyhunt_write);
1155 	ZetSetOutHandler(spyhunt_write_port);
1156 	ZetSetInHandler(spyhunt_read_port);
1157 
1158     ZetDaisyInit(Z80_CTC, 0);
1159 	z80ctc_init(5000000, 0, ctc_interrupt, ctc_trigger, NULL, NULL);
1160 	ZetClose();
1161 
1162     if (is_spyhunt) {
1163         ssio_spyhunter = 1;
1164         filter_rc_init(0, FLT_RC_LOWPASS, 1000, 5100, 0, CAP_P(0), 0);
1165         filter_rc_init(1, FLT_RC_LOWPASS, 1000, 5100, 0, CAP_P(0), 1);
1166         filter_rc_init(2, FLT_RC_LOWPASS, 1000, 5100, 0, CAP_P(0), 1);
1167         filter_rc_init(3, FLT_RC_LOWPASS, 1000, 5100, 0, CAP_P(0), 1);
1168         filter_rc_init(4, FLT_RC_LOWPASS, 1000, 5100, 0, CAP_P(0), 1);
1169         filter_rc_init(5, FLT_RC_LOWPASS, 1000, 5100, 0, CAP_P(0), 1);
1170 
1171         filter_rc_set_route(0, 1.00, FLT_RC_PANNEDLEFT);
1172         filter_rc_set_route(1, 1.00, FLT_RC_PANNEDLEFT);
1173         filter_rc_set_route(2, 1.00, FLT_RC_PANNEDLEFT);
1174         filter_rc_set_route(3, 1.00, FLT_RC_PANNEDRIGHT);
1175         filter_rc_set_route(4, 1.00, FLT_RC_PANNEDRIGHT);
1176         filter_rc_set_route(5, 1.00, FLT_RC_PANNEDRIGHT);
1177 
1178         LP1 = new LowPass2(CutFreq, SampleFreq, Q, Gain, CutFreq2, Q2, Gain2);
1179     }
1180 
1181     sound_system_init(sound_system);
1182 
1183 	BurnWatchdogInit(DrvDoReset, -1);
1184 
1185 	GenericTilesInit();
1186 	GenericTilemapInit(0, spybg_map_scan , spybg_map_callback, 64, 32, 64, 32);
1187 	GenericTilemapInit(1, TILEMAP_SCAN_COLS, txt_map_callback, 16, 16, 32, 32);
1188 	GenericTilemapSetGfx(0, DrvGfxROM0, 4, 64, 32, 0x40000, 0x30, 0);
1189 	GenericTilemapSetGfx(1, DrvGfxROM2, 2, 16, 16, 0x10000, 0x40, 0);
1190 	GenericTilemapSetTransparent(1, 0);
1191 	GenericTilemapSetOffsets(0, (sound_system == 3) ? 96-16 : -16, 0);
1192 	GenericTilemapSetOffsets(1, (sound_system == 3) ? 16 : -16, 0);
1193 
1194     if (is_spyhunt) {
1195         copy_and_rotate(DrvGfxROM1 + 0x29*0x20*0x20, DrvGfxROM1 + (0x200*0x20*0x20)+(0x20*0x20*0));
1196         copy_and_rotate(DrvGfxROM1 + 0x2a*0x20*0x20, DrvGfxROM1 + (0x200*0x20*0x20)+(0x20*0x20*1));
1197         copy_and_rotate(DrvGfxROM1 + 0x45*0x20*0x20, DrvGfxROM1 + (0x200*0x20*0x20)+(0x20*0x20*2));
1198         copy_and_rotate(DrvGfxROM1 + 0x7b*0x20*0x20, DrvGfxROM1 + (0x200*0x20*0x20)+(0x20*0x20*3));
1199         copy_and_rotate(DrvGfxROM1 + 0x0f*0x20*0x20, DrvGfxROM1 + (0x200*0x20*0x20)+(0x20*0x20*4));
1200     }
1201 
1202     BurnTrackballInit(2);
1203 
1204     if (has_shift)
1205         BurnShiftInit(SHIFT_POSITION_BOTTOM_RIGHT, SHIFT_COLOR_RED, 80);
1206 
1207     DrvDoReset(1);
1208 
1209 	return 0;
1210 }
1211 
DrvExit()1212 static INT32 DrvExit()
1213 {
1214 	GenericTilesExit();
1215 	ZetExit();
1216 
1217 	csd_exit();
1218 	tcs_exit();
1219 	soundsgood_exit();
1220 	ssio_exit();
1221 
1222     if (is_spyhunt) {
1223         filter_rc_exit();
1224         delete LP1;
1225         LP1 = NULL;
1226     }
1227 
1228 	BurnWatchdogExit();
1229 
1230     BurnTrackballExit();
1231     if (has_shift) BurnShiftExit();
1232 
1233 	sound_status_bit = 8; // default to disabled
1234 	sound_input_bank = 0;
1235 	port_write_handler = NULL;
1236 	port_read_handler = NULL;
1237 	sprite_color_mask = 0;
1238 	flip_screen_x = 0;
1239 
1240     is_demoderm = 0;
1241 	is_spyhunt = 0;
1242 	is_powerdrv = 0;
1243 	is_maxrpm = 0;
1244 
1245     has_dial = 0;
1246     has_shift = 0;
1247 
1248     dip_service = 0x20;
1249 
1250 	BurnFree(AllMem);
1251 
1252 	return 0;
1253 }
1254 
DrvPaletteUpdate()1255 static void DrvPaletteUpdate()
1256 {
1257 	for (INT32 i = 0; i < 0x40; i++)
1258 	{
1259 		UINT8 r = pal3bit(DrvPalRAM16[i] >> 6);
1260 		UINT8 g = pal3bit(DrvPalRAM16[i] & 7);
1261 		UINT8 b = pal3bit((DrvPalRAM16[i] >> 3) & 7);
1262 
1263 		DrvPalette[i] = BurnHighCol(r,g,b,0);
1264 	}
1265 
1266 	// spyhunt hardware
1267 	DrvPalette[0x40] = 0;
1268 	DrvPalette[0x41] = BurnHighCol(0x00, 0xff, 0x00, 0);
1269 	DrvPalette[0x42] = BurnHighCol(0x00, 0x00, 0xff, 0);
1270 	DrvPalette[0x43] = BurnHighCol(0xff, 0xff, 0xff, 0);
1271 }
1272 
draw_sprites(INT32 color_mask,INT32 dx,INT32 dy)1273 static void draw_sprites(INT32 color_mask, INT32 dx, INT32 dy)
1274 {
1275 	INT32 codemask = (nGraphicsLen[1] * 2) / (32 * 32);
1276 
1277 	for (INT32 offs = 0x200 - 4; offs >= 0; offs -= 4)
1278 	{
1279 		if (DrvSprRAM[offs] == 0) continue;
1280 
1281 		INT32 flags = DrvSprRAM[offs + 1];
1282 		INT32 code = DrvSprRAM[offs + 2] + 256 * ((flags >> 3) & 0x01);
1283 		INT32 color = ~flags & color_mask;
1284 		INT32 flipx = flags & 0x10;
1285 		INT32 flipy = flags & 0x20;
1286 		INT32 sx = (DrvSprRAM[offs + 3] - 3) * 2;
1287 		INT32 sy = (241 - DrvSprRAM[offs]) * 2;
1288 
1289 		sx += dx;
1290 		sy += dy;
1291 
1292 		if (flip_screen_x) {
1293 			sx = (nScreenWidth - 32) - sx;
1294 			flipx ^= 0x10;
1295 		}
1296 
1297 		if (!flipscreen)
1298 		{
1299 			if (nSpriteEnable & 2) RenderPrioMaskTranstabSprite(pTransDraw, DrvGfxROM1, code % codemask, (color * 16), 0xff, sx, sy, flipx, flipy, 32, 32, DrvTransTab[0], 0);
1300 			if (nSpriteEnable & 4) RenderPrioMaskTranstabSprite(pTransDraw, DrvGfxROM1, code % codemask, (color * 16), 0xff, sx, sy, flipx, flipy, 32, 32, DrvTransTab[1], 2);
1301 		}
1302 		else
1303 		{
1304 			RenderPrioMaskTranstabSprite(pTransDraw, DrvGfxROM1, code % codemask, (color * 16), 0xff, 480 - sx, 452 - sy, !flipx, !flipy, 32, 32, DrvTransTab[0], 0);
1305 			RenderPrioMaskTranstabSprite(pTransDraw, DrvGfxROM1, code % codemask, (color * 16), 0xff, 480 - sx, 452 - sy, !flipx, !flipy, 32, 32, DrvTransTab[1], 2);
1306 		}
1307 	}
1308 }
1309 
DrvDraw()1310 static INT32 DrvDraw()
1311 {
1312 	if (DrvRecalc) {
1313 		DrvPaletteUpdate();
1314 		DrvRecalc = 1;
1315 	}
1316 
1317     BurnTransferClear();
1318 
1319 	GenericTilemapSetFlip(0, flipscreen ? (TMAP_FLIPX | TMAP_FLIPY) : 0);
1320 
1321 	if (nBurnLayer & 1) GenericTilemapDraw(0, pTransDraw, 1/*must be this!*/);
1322 
1323 	if (nSpriteEnable & 1) draw_sprites(0x03, 0, 0);
1324 
1325 	BurnTransferCopy(DrvPalette);
1326 
1327 	return 0;
1328 }
1329 
SpyhuntDraw()1330 static INT32 SpyhuntDraw()
1331 {
1332 	if (DrvRecalc) {
1333 		DrvPaletteUpdate();
1334 		DrvRecalc = 1;
1335 	}
1336 
1337     BurnTransferClear();
1338 
1339 	GenericTilemapSetFlip(TMAP_GLOBAL, (flipscreen ? (TMAP_FLIPX | TMAP_FLIPY) : 0) ^ flip_screen_x);
1340 	GenericTilemapSetScrollX(0, scrollx * 2);
1341 	GenericTilemapSetScrollY(0, scrolly * 2);
1342 
1343 	if (nBurnLayer & 1) GenericTilemapDraw(0, pTransDraw, 0);
1344 
1345 	if (nSpriteEnable & 1) draw_sprites(sprite_color_mask, -12, 0);
1346 
1347 	if (nBurnLayer & 2) GenericTilemapDraw(1, pTransDraw, 0);
1348 
1349     if (is_spyhunt) {
1350         if (lamp&0x04) {
1351             // 29+2a, weapons van (pre-rotated)
1352             RenderZoomedTile(pTransDraw, DrvGfxROM1, 0x200, 0, 0, nScreenWidth-16, 32, 0, 0, 32, 32, 0x10000/2, 0x10000/2);
1353             RenderZoomedTile(pTransDraw, DrvGfxROM1, 0x201, 0, 0, nScreenWidth-16, 48, 0, 0, 32, 32, 0x10000/2, 0x10000/2);
1354         }
1355         if (lamp&0x01) {
1356             // oil
1357             RenderZoomedTile(pTransDraw, DrvGfxROM1, 0x016, 0, 0, nScreenWidth-16, 64, 0, 0, 32, 32, 0x10000/2, 0x10000/2);
1358         }
1359         if (lamp&0x08) {
1360             // smoke
1361             RenderZoomedTile(pTransDraw, DrvGfxROM1, 0x019, 0, 0, nScreenWidth-16, 80, 0, 0, 32, 32, 0x10000/2, 0x10000/2);
1362         }
1363         if (lamp&0x02) {
1364             // missile (pre-rotated)
1365             RenderZoomedTile(pTransDraw, DrvGfxROM1, 0x202, 0, 0, nScreenWidth-24, 96, 0, 0, 32, 32, 0x10000, 0x10000);
1366         }
1367         if (lamp&0x10) {
1368             // machine guns (pre-rotated)
1369             //RenderZoomedTile(pTransDraw, DrvGfxROM1, 0x204, 0, 0, nScreenWidth-16, 128, 1, 0, 32, 32, 0x10000/2, 0x10000/2);
1370             //RenderZoomedTile(pTransDraw, DrvGfxROM1, 0x203, 0, 0, nScreenWidth-16, 144, 1, 0, 32, 32, 0x10000/2, 0x10000/2);
1371         }
1372     }
1373 	BurnTransferCopy(DrvPalette);
1374 
1375     if (has_shift) BurnShiftRenderDoubleSize();
1376 
1377 	return 0;
1378 }
1379 
mcr_interrupt(INT32 scanline)1380 static void mcr_interrupt(INT32 scanline)
1381 {
1382 	if (scanline == 0 || scanline == 240)
1383 	{
1384 		z80ctc_trg_write(2, 1);
1385 		z80ctc_trg_write(2, 0);
1386 	}
1387 
1388 	if (scanline == 0)
1389 	{
1390 		z80ctc_trg_write(3, 1);
1391 		z80ctc_trg_write(3, 0);
1392 	}
1393 }
1394 
build_inputs()1395 static void build_inputs()
1396 {
1397 	if (is_powerdrv) {
1398 		if (DrvJoy2[1] && !pd_shift_prev[0]) { // P1
1399 			pd_shift[0] = !pd_shift[0];
1400 		}
1401 		pd_shift_prev[0] = DrvJoy2[1];
1402 		DrvJoy2[1] = pd_shift[0];
1403 
1404 		if (DrvJoy2[5] && !pd_shift_prev[1]) { // P2
1405 			pd_shift[1] = !pd_shift[1];
1406 		}
1407 		pd_shift_prev[1] = DrvJoy2[5];
1408 		DrvJoy2[5] = pd_shift[1];
1409 
1410 		if (DrvJoy3[1] && !pd_shift_prev[2]) { // P3
1411 			pd_shift[2] = !pd_shift[2];
1412 		}
1413 		pd_shift_prev[2] = DrvJoy3[1];
1414 		DrvJoy3[1] = pd_shift[2];
1415 	}
1416 
1417 	memcpy (DrvInputs, DrvDips, 5); // 0xff-filled?
1418 	DrvInputs[5] = 0xff;
1419 	DrvInputs4f = 0xff;
1420 
1421 	for (INT32 i = 0; i < 8; i++) {
1422 		DrvInputs[0] ^= (DrvJoy1[i] & 1) << i;
1423 		DrvInputs[1] ^= (DrvJoy2[i] & 1) << i;
1424 		DrvInputs[2] ^= (DrvJoy3[i] & 1) << i;
1425 		DrvInputs[3] ^= (DrvJoy4[i] & 1) << i;
1426 		DrvInputs[4] ^= (DrvJoy5[i] & 1) << i;
1427 		DrvInputs[5] ^= (DrvJoy6[i] & 1) << i;
1428 		DrvInputs4f  ^= (DrvJoy4f[i] & 1) << i; // for maxrpm
1429 	}
1430 
1431     DrvInputs[0] = (DrvInputs[0] & ~dip_service) | (DrvDips[5] & dip_service);
1432 
1433     { // analog stuff
1434         if (has_dial) { // etc
1435             BurnTrackballConfig(0, AXIS_REVERSED, AXIS_REVERSED);
1436             BurnTrackballFrame(0, DrvAnalogPort0, DrvAnalogPort1, 7, 10);
1437             BurnTrackballUDLR(0, 0, 0, DrvJoy4f[0], DrvJoy4f[1]);
1438             BurnTrackballUpdate(0);
1439         }
1440 
1441         if (is_demoderm) {
1442             BurnTrackballConfig(0, AXIS_NORMAL, AXIS_NORMAL);
1443             BurnTrackballFrame(0, DrvAnalogPort0, DrvAnalogPort1, 2, 5);
1444             BurnTrackballUpdate(0);
1445 
1446             BurnTrackballConfig(1, AXIS_NORMAL, AXIS_NORMAL);
1447             BurnTrackballFrame(1, DrvAnalogPort2, DrvAnalogPort3, 2, 5);
1448             BurnTrackballUpdate(1);
1449         }
1450 
1451         if (has_shift) { // gear shifter stuff
1452 			BurnShiftInputCheckToggle(DrvJoy4f[4]);
1453 
1454 			DrvInputs[0] &= ~0x10;
1455             DrvInputs[0] |= (bBurnShiftStatus) ? 0x00 : 0x10;
1456 		}
1457     }
1458 }
1459 
DrvFrame()1460 static INT32 DrvFrame()
1461 {
1462 	BurnWatchdogUpdate();
1463 
1464 	if (DrvReset) {
1465 		DrvDoReset(1);
1466 	}
1467 
1468 	ZetNewFrame();
1469 	SekNewFrame();
1470 
1471 	build_inputs();
1472 
1473 	INT32 nInterleave = 480;
1474 	INT32 nCyclesTotal[2] = { 5000000 / 30, 8000000 / 30 };
1475 	INT32 nCyclesDone[2] = { nExtraCycles[0], 0 };
1476 
1477 	ZetOpen(0);
1478 	SekOpen(0);
1479 
1480 	for (INT32 i = 0; i < nInterleave; i++)
1481 	{
1482 		CPU_RUN(0, Zet);
1483 		mcr_interrupt(i);
1484 
1485 		if (soundsgood_reset_status())
1486 		{
1487 			CPU_IDLE_SYNCINT(1, Sek);
1488 		}
1489 		else
1490 		{
1491 			CPU_RUN_SYNCINT(1, Sek);
1492 		}
1493 	}
1494 
1495     if (pBurnSoundOut) {
1496         BurnSoundClear();
1497         DACUpdate(pBurnSoundOut, nBurnSoundLen);
1498 	}
1499 
1500 	SekClose();
1501 	ZetClose();
1502 
1503     nExtraCycles[0] = nCyclesDone[0] - nCyclesTotal[0];
1504 
1505 	if (pBurnDraw) {
1506 		BurnDrvRedraw();
1507 	}
1508 
1509 	return 0;
1510 }
1511 
TcsFrame()1512 static INT32 TcsFrame()
1513 {
1514 	BurnWatchdogUpdate();
1515 
1516 	if (DrvReset) {
1517 		DrvDoReset(1);
1518 	}
1519 
1520 	ZetNewFrame();
1521 	M6809NewFrame();
1522 
1523 	build_inputs();
1524 
1525 	INT32 nInterleave = 480;
1526 	INT32 nCyclesTotal[2] = { 5000000 / 30, 2000000 / 30 };
1527 	INT32 nCyclesDone[2] = { nExtraCycles[0], 0 };
1528 
1529 	ZetOpen(0);
1530 	M6809Open(0);
1531 
1532 	for (INT32 i = 0; i < nInterleave; i++)
1533 	{
1534 		CPU_RUN(0, Zet);
1535         mcr_interrupt(i);
1536 
1537 		if (tcs_reset_status())
1538 		{
1539 			CPU_IDLE_SYNCINT(1, M6809);
1540 		}
1541 		else
1542 		{
1543 			CPU_RUN_SYNCINT(1, M6809);
1544 		}
1545 	}
1546 
1547 	if (pBurnSoundOut) {
1548         BurnSoundClear();
1549 		DACUpdate(pBurnSoundOut, nBurnSoundLen);
1550 	}
1551 
1552 	M6809Close();
1553 	ZetClose();
1554     nExtraCycles[0] = nCyclesDone[0] - nCyclesTotal[0];
1555 
1556 	if (pBurnDraw) {
1557 		BurnDrvRedraw();
1558 	}
1559 
1560 	return 0;
1561 }
1562 
CSDSSIOFrame()1563 static INT32 CSDSSIOFrame()
1564 {
1565 	BurnWatchdogUpdate();
1566 
1567 	if (DrvReset) {
1568 		DrvDoReset(1);
1569 	}
1570 
1571 	INT32 has_ssio = ssio_initialized();
1572 	INT32 has_csd = csd_initialized();
1573 
1574 	ZetNewFrame();
1575 	if (has_csd) SekNewFrame();
1576 
1577 	build_inputs();
1578 
1579 	INT32 nInterleave = 480;
1580 	INT32 nCyclesTotal[3] = { 5000000 / 30, 8000000 / 30, 2000000 / 30 };
1581 	INT32 nCyclesDone[3] = { nExtraCycles[0], nExtraCycles[1], nExtraCycles[2] };
1582 
1583     if (has_csd) {
1584         SekOpen(0);
1585         SekIdle(nExtraCycles[1]);
1586         nExtraCycles[1] = 0;
1587     }
1588 
1589 	for (INT32 i = 0; i < nInterleave; i++)
1590 	{
1591 		ZetOpen(0);
1592 		CPU_RUN(0, Zet);
1593         mcr_interrupt(i);
1594 
1595 		if (has_csd)
1596 		{
1597 			if (csd_reset_status())
1598 			{
1599 				CPU_IDLE_SYNCINT(1, Sek);
1600 			}
1601 			else
1602 			{
1603 				CPU_RUN_SYNCINT(1, Sek);
1604 			}
1605 		}
1606 		ZetClose();
1607 
1608 		if (has_ssio)
1609 		{
1610 			ZetOpen(1);
1611 			CPU_RUN(2, Zet);
1612 			ssio_14024_clock(nInterleave);
1613 			ZetClose();
1614 		}
1615 	}
1616 
1617     if (pBurnSoundOut) {
1618         if (is_spyhunt) {
1619 			AY8910RenderInternal(nBurnSoundLen);
1620 			filter_rc_update(0, pAY8910Buffer[0], pBurnSoundOut, nBurnSoundLen); // filter just used as a mixer
1621 			filter_rc_update(1, pAY8910Buffer[1], pBurnSoundOut, nBurnSoundLen);
1622 			filter_rc_update(2, pAY8910Buffer[2], pBurnSoundOut, nBurnSoundLen);
1623 			filter_rc_update(3, pAY8910Buffer[3], pBurnSoundOut, nBurnSoundLen);
1624 			filter_rc_update(4, pAY8910Buffer[4], pBurnSoundOut, nBurnSoundLen);
1625 			if (LP1) { // this filter actually does the filtering
1626 				LP1->FilterMono(pAY8910Buffer[5], nBurnSoundLen); // Engine
1627 			}
1628 			filter_rc_update(5, pAY8910Buffer[5], pBurnSoundOut, nBurnSoundLen);
1629 
1630 			DACUpdate(pBurnSoundOut, nBurnSoundLen);
1631 		} else {
1632 			BurnSoundClear();
1633 			if (has_ssio) AY8910Render(pBurnSoundOut, nBurnSoundLen);
1634 			if (has_csd) DACUpdate(pBurnSoundOut, nBurnSoundLen);
1635 		}
1636 	}
1637 
1638     if (has_csd) {
1639         nExtraCycles[1] = nCyclesDone[1] - SekTotalCycles();
1640         SekClose();
1641     }
1642 
1643     nExtraCycles[0] = nCyclesDone[0] - nCyclesTotal[0];
1644     nExtraCycles[2] = nCyclesDone[2] - nCyclesTotal[2];
1645 
1646 	if (pBurnDraw) {
1647 		BurnDrvRedraw();
1648 	}
1649 
1650 	return 0;
1651 }
1652 
DrvScan(INT32 nAction,INT32 * pnMin)1653 static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
1654 {
1655 	struct BurnArea ba;
1656 
1657 	if (pnMin) {
1658 		*pnMin = 0x029702;
1659 	}
1660 
1661 	if (nAction & ACB_VOLATILE) {
1662 		memset(&ba, 0, sizeof(ba));
1663 
1664 		ba.Data	  = AllRam;
1665 		ba.nLen	  = RamEnd - AllRam;
1666 		ba.szName = "All Ram";
1667 		BurnAcb(&ba);
1668 
1669         ScanVar(DrvNVRAM, 0x800, "WORK RAM"); // also nv...
1670 
1671 		ZetScan(nAction);
1672 
1673 		tcs_scan(nAction, pnMin);
1674 		csd_scan(nAction, pnMin);
1675 		soundsgood_scan(nAction, pnMin);
1676 		ssio_scan(nAction, pnMin);
1677 
1678 		BurnWatchdogScan(nAction);
1679 
1680         BurnTrackballScan();
1681 
1682         if (has_shift) BurnShiftScan(nAction);
1683 
1684 		SCAN_VAR(flipscreen);
1685 		SCAN_VAR(latched_input);
1686 		SCAN_VAR(maxrpm_adc_control);
1687 		SCAN_VAR(maxrpm_adc_select);
1688 		SCAN_VAR(maxrpm_p1_shift);
1689 		SCAN_VAR(maxrpm_p2_shift);
1690 		SCAN_VAR(maxrpm_last_shift);
1691 		SCAN_VAR(pd_shift);
1692 		SCAN_VAR(pd_shift_prev);
1693 		SCAN_VAR(scrollx);
1694 		SCAN_VAR(scrolly);
1695         SCAN_VAR(input_mux);
1696 
1697         SCAN_VAR(lamp);
1698         SCAN_VAR(last_op4);
1699 
1700         SCAN_VAR(nExtraCycles);
1701 	}
1702 
1703 	if (nAction & ACB_NVRAM) {
1704         ScanVar(DrvNVRAM, 0x800, "NV RAM");
1705 	}
1706 
1707 	return 0;
1708 }
1709 
1710 
1711 static struct BurnRomInfo emptyRomDesc[] = {
1712 	{ "",                    0,          0, 0 },
1713 };
1714 
1715 static struct BurnRomInfo SsiopromRomDesc[] = {
1716 #if !defined (ROM_VERIFY)
1717 	{ "82s123.12d",						0x0020, 0xe1281ee9, 0 | BRF_SND },
1718 #else
1719 	{ "",  0x000000, 0x00000000, BRF_ESS | BRF_PRG | BRF_BIOS },
1720 #endif
1721 };
1722 
1723 
1724 // Demolition Derby (MCR-3 Mono Board Version)
1725 
1726 static struct BurnRomInfo demodermRomDesc[] = {
1727 	{ "pro0.3b",									0x8000, 0x2e24527b, 1 | BRF_PRG | BRF_ESS }, //  0 Z80 #0 Code
1728 	{ "pro1.5b",									0x8000, 0x034c00fc, 1 | BRF_PRG | BRF_ESS }, //  1
1729 
1730 	{ "tcs_u5.bin",									0x2000, 0xeca33b2c, 3 | BRF_PRG | BRF_ESS }, //  2 M6809 Code
1731 	{ "tcs_u4.bin",									0x2000, 0x3490289a, 3 | BRF_PRG | BRF_ESS }, //  3
1732 
1733 	{ "bg0.15a",									0x2000, 0xa35d13b8, 1 | BRF_GRA },           //  4 Background Tiles
1734 	{ "bg1.14b",									0x2000, 0x22ca93f3, 1 | BRF_GRA },           //  5
1735 
1736 	{ "dd_fg-0.a4",									0x4000, 0xe57a4de6, 2 | BRF_GRA },           //  6 Sprites
1737 	{ "dd_fg-4.a3",									0x4000, 0x55aa667f, 2 | BRF_GRA },           //  7
1738 	{ "dd_fg-1.a6",									0x4000, 0x70259651, 2 | BRF_GRA },           //  8
1739 	{ "dd_fg-5.a5",									0x4000, 0x5fe99007, 2 | BRF_GRA },           //  9
1740 	{ "dd_fg-2.a8",									0x4000, 0x6cab7b95, 2 | BRF_GRA },           // 10
1741 	{ "dd_fg-6.a7",									0x4000, 0xabfb9a8b, 2 | BRF_GRA },           // 11
1742 	{ "dd_fg-3.a10",								0x4000, 0x801d9b86, 2 | BRF_GRA },           // 12
1743 	{ "dd_fg-7.a9",									0x4000, 0x0ec3f60a, 2 | BRF_GRA },           // 13
1744 };
1745 
1746 STD_ROM_PICK(demoderm)
STD_ROM_FN(demoderm)1747 STD_ROM_FN(demoderm)
1748 
1749 static INT32 demoderm_read_callback(UINT8 address)
1750 {
1751 	switch (address)
1752 	{
1753 		case 0x01:
1754 		{
1755             UINT8 ipt = DrvInputs[1] & 0x03;
1756             ipt |= (((input_mux) ? ~BurnTrackballRead(1, 0) : ~BurnTrackballRead(0, 0)) << 2) & 0x3f;
1757 
1758             BurnTrackballUpdate(input_mux);
1759 
1760             return ipt;
1761 		}
1762 
1763 		case 0x02:
1764 		{
1765             UINT8 ipt = DrvInputs[2] & 0x03;
1766             ipt |= (((input_mux) ? ~BurnTrackballRead(1, 1) : ~BurnTrackballRead(0, 1)) << 2) & 0x3f;
1767 
1768             BurnTrackballUpdate(input_mux);
1769 
1770             return ipt;
1771 		}
1772 	}
1773 
1774 	return -1;
1775 }
1776 
demoderm_write_callback(UINT8 address,UINT8 data)1777 static INT32 demoderm_write_callback(UINT8 address, UINT8 data)
1778 {
1779 	switch (address)
1780 	{
1781 		case 0x06:
1782 		{
1783 			if (data & 0x80) input_mux = 0;
1784 			if (data & 0x40) input_mux = 1;
1785 
1786 			INT32 cycles = ((ZetTotalCycles() * 2) / 5) - M6809TotalCycles();
1787 			if (cycles > 0) M6809Run(cycles);
1788 			tcs_data_write(data);
1789 		}
1790 		return 0;
1791 	}
1792 
1793 	return -1;
1794 }
1795 
DemodermInit()1796 static INT32 DemodermInit()
1797 {
1798 	port_write_handler = demoderm_write_callback;
1799 	port_read_handler = demoderm_read_callback;
1800     is_demoderm = 1;
1801 
1802 	return DrvInit(1);
1803 }
1804 
1805 struct BurnDriver BurnDrvDemoderm = {
1806 	"demoderm", "demoderb", NULL, NULL, "1984",
1807 	"Demolition Derby (MCR-3 Mono Board Version)\0", NULL, "Bally Midway", "MCR3",
1808 	NULL, NULL, NULL, NULL,
1809 	BDF_GAME_WORKING | BDF_CLONE, 4, HARDWARE_MISC_PRE90S, GBF_ACTION, 0,
1810 	NULL, demodermRomInfo, demodermRomName, NULL, NULL, NULL, NULL, DemodermInputInfo, DemodermDIPInfo,
1811 	DemodermInit, DrvExit, TcsFrame, DrvDraw, DrvScan, &DrvRecalc, 0x40,
1812 	512, 480, 4, 3
1813 };
1814 
1815 
1816 // Sarge
1817 
1818 static struct BurnRomInfo sargeRomDesc[] = {
1819 	{ "cpu_3b.bin",									0x8000, 0xda31a58f, 1 | BRF_PRG | BRF_ESS }, //  0 Z80 Code
1820 	{ "cpu_5b.bin",									0x8000, 0x6800e746, 1 | BRF_PRG | BRF_ESS }, //  1
1821 
1822 	{ "tcs_u5.bin",									0x2000, 0xa894ef8a, 3 | BRF_PRG | BRF_ESS }, //  2 M6809 Code
1823 	{ "tcs_u4.bin",									0x2000, 0x6ca6faf3, 3 | BRF_PRG | BRF_ESS }, //  3
1824 
1825 	{ "til_15a.bin",								0x2000, 0x685001b8, 1 | BRF_GRA },           //  4 Background Tiles
1826 	{ "til_14b.bin",								0x2000, 0x8449eb45, 1 | BRF_GRA },           //  5
1827 
1828 	{ "spr_8e.bin",									0x8000, 0x93fac29d, 2 | BRF_GRA },           //  6 Sprites
1829 	{ "spr_6e.bin",									0x8000, 0x7cc6fb28, 2 | BRF_GRA },           //  7
1830 	{ "spr_5e.bin",									0x8000, 0xc832375c, 2 | BRF_GRA },           //  8
1831 	{ "spr_4e.bin",									0x8000, 0xc382267d, 2 | BRF_GRA },           //  9
1832 
1833 	{ "a59a26axlcxhd.13j.bin",						0x0001, 0x00000000, 5 | BRF_NODUMP | BRF_OPT },           // 10 PALs
1834 	{ "a59a26axlbxhd.2j.bin",						0x0001, 0x00000000, 5 | BRF_NODUMP | BRF_OPT },           // 11
1835 	{ "a59a26axlaxhd.3j.bin",						0x0001, 0x00000000, 5 | BRF_NODUMP | BRF_OPT },           // 12
1836 	{ "0066-314bx-xxqx.6h.bin",						0x0001, 0x00000000, 5 | BRF_NODUMP | BRF_OPT },           // 13
1837 	{ "0066-316bx-xxqx.5h.bin",						0x0001, 0x00000000, 5 | BRF_NODUMP | BRF_OPT },           // 14
1838 	{ "0066-315bx-xxqx.5g.bin",						0x0001, 0x00000000, 5 | BRF_NODUMP | BRF_OPT },           // 15
1839 	{ "0066-313bx-xxqx.4g.bin",						0x0001, 0x00000000, 5 | BRF_NODUMP | BRF_OPT },           // 16
1840 };
1841 
1842 STD_ROM_PICK(sarge)
STD_ROM_FN(sarge)1843 STD_ROM_FN(sarge)
1844 
1845 static INT32 SargeInit()
1846 {
1847 	port_write_handler = demoderm_write_callback;
1848 
1849 	return DrvInit(1);
1850 }
1851 
1852 struct BurnDriver BurnDrvSarge = {
1853 	"sarge", NULL, NULL, NULL, "1985",
1854 	"Sarge\0", NULL, "Bally Midway", "MCR3",
1855 	NULL, NULL, NULL, NULL,
1856 	BDF_GAME_WORKING, 4, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0,
1857 	NULL, sargeRomInfo, sargeRomName, NULL, NULL, NULL, NULL, SargeInputInfo, SargeDIPInfo,
1858 	SargeInit, DrvExit, TcsFrame, DrvDraw, DrvScan, &DrvRecalc, 0x40,
1859 	512, 480, 4, 3
1860 };
1861 
1862 
1863 // Max RPM (ver 2)
1864 
1865 static struct BurnRomInfo maxrpmRomDesc[] = {
1866 	{ "pro.0",									0x8000, 0x3f9ec35f, 1 | BRF_PRG | BRF_ESS }, //  0 Z80 Code
1867 	{ "pro.1",									0x8000, 0xf628bb30, 1 | BRF_PRG | BRF_ESS }, //  1
1868 
1869 	{ "turbskwk.u5",							0x4000, 0x55c3b759, 3 | BRF_PRG | BRF_ESS }, //  2 M6809 Code
1870 	{ "turbskwk.u4",							0x4000, 0x31a2da2e, 3 | BRF_PRG | BRF_ESS }, //  3
1871 
1872 	{ "bg-0",									0x4000, 0xe3fb693a, 1 | BRF_GRA },           //  4 Background Tiles
1873 	{ "bg-1",									0x4000, 0x50d1db6c, 1 | BRF_GRA },           //  5
1874 
1875 	{ "fg-0",									0x8000, 0x1d1435c1, 2 | BRF_GRA },           //  6 Sprites
1876 	{ "fg-1",									0x8000, 0xe54b7f2a, 2 | BRF_GRA },           //  7
1877 	{ "fg-2",									0x8000, 0x38be8505, 2 | BRF_GRA },           //  8
1878 	{ "fg-3",									0x8000, 0x9ae3eb52, 2 | BRF_GRA },           //  9
1879 };
1880 
1881 STD_ROM_PICK(maxrpm)
STD_ROM_FN(maxrpm)1882 STD_ROM_FN(maxrpm)
1883 
1884 
1885 static UINT8 maxrpm_ipt2_read()
1886 {
1887 	const UINT8 shift_bits[5] = { 0x00, 0x05, 0x06, 0x01, 0x02 };
1888 	UINT8 start = DrvInputs[0];
1889 	UINT8 shift = DrvInputs4f;
1890 
1891 	if (~start & 0x08) maxrpm_p1_shift = 0;
1892 	if (~start & 0x04) maxrpm_p2_shift = 0;
1893 
1894 	if (~shift & 0x01 && maxrpm_last_shift & 0x01) {
1895 		if (maxrpm_p1_shift < 4) maxrpm_p1_shift++;
1896 	}
1897 	if (~shift & 0x02 && maxrpm_last_shift & 0x02) {
1898 		if (maxrpm_p1_shift > 0) maxrpm_p1_shift--;
1899 	}
1900 	if (~shift & 0x04 && maxrpm_last_shift & 0x04) {
1901 		if (maxrpm_p2_shift < 4) maxrpm_p2_shift++;
1902 	}
1903 	if (~shift & 0x08 && maxrpm_last_shift & 0x08) {
1904 		if (maxrpm_p2_shift > 0) maxrpm_p2_shift--;
1905 	}
1906 
1907 	maxrpm_last_shift = shift;
1908 
1909 	return ~((shift_bits[maxrpm_p1_shift] << 4) + shift_bits[maxrpm_p2_shift]);
1910 }
1911 
maxrpm_read_callback(UINT8 address)1912 static INT32 maxrpm_read_callback(UINT8 address)
1913 {
1914 	switch (address)
1915 	{
1916 		case 1:
1917 			return latched_input;
1918 
1919 		case 2:
1920 			return maxrpm_ipt2_read();
1921 	}
1922 
1923 	return -1;
1924 }
1925 
maxrpm_write_callback(UINT8 address,UINT8 data)1926 static INT32 maxrpm_write_callback(UINT8 address, UINT8 data)
1927 {
1928 	switch (address)
1929 	{
1930 		case 0x05:
1931 		{
1932 			maxrpm_adc_control = data & 0x0f;
1933 		}
1934 		return -1; // fall through
1935 
1936 		case 0x06:
1937 		{
1938 			INT16 analogs[4] = { DrvAnalogPort3, DrvAnalogPort1, DrvAnalogPort2, DrvAnalogPort0  };
1939 
1940 			if (~data & 0x80) {
1941 				if (maxrpm_adc_select < 2) { // p2 gas, p1 gas
1942 					latched_input = ProcessAnalog(analogs[maxrpm_adc_select], 1, INPUT_DEADZONE | INPUT_LINEAR | INPUT_MIGHTBEDIGITAL, 0x30, 0xff);
1943 					if (latched_input < 0x34) latched_input = 0x30; // some inputs don't go all the way
1944 					//bprintf(0, _T("inp %x:  latched input: %x (%d dec.)\n"), maxrpm_adc_select, latched_input, latched_input);
1945 				} else { // p2 wheel, p1 wheel
1946 					latched_input = ProcessAnalog(analogs[maxrpm_adc_select], (maxrpm_adc_select == 2) ? 0 : 1, INPUT_DEADZONE, 0x40, 0xb4);
1947 				}
1948 			}
1949 
1950 			if (~data & 0x40 && ~data & 0x20) {
1951 				maxrpm_adc_select = (maxrpm_adc_control >> 1) & 0x03;
1952 			}
1953 
1954 			// do sound
1955 			INT32 cycles = ((ZetTotalCycles() * 2) / 5) - M6809TotalCycles();
1956 			if (cycles > 0) M6809Run(cycles);
1957 			tcs_data_write(data);
1958 		}
1959 		return 0;
1960 	}
1961 
1962 	return -1;
1963 }
1964 
MaxrpmInit()1965 static INT32 MaxrpmInit()
1966 {
1967     dip_service = 0x80;
1968 	is_maxrpm = 1;
1969 	port_write_handler = maxrpm_write_callback;
1970 	port_read_handler = maxrpm_read_callback;
1971 
1972 	return DrvInit(1);
1973 }
1974 
1975 struct BurnDriver BurnDrvMaxrpm = {
1976 	"maxrpm", NULL, NULL, NULL, "1986",
1977 	"Max RPM (ver 2)\0", NULL, "Bally Midway", "MCR3",
1978 	NULL, NULL, NULL, NULL,
1979 	BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_RACING, 0,
1980 	NULL, maxrpmRomInfo, maxrpmRomName, NULL, NULL, NULL, NULL, MaxrpmInputInfo, MaxrpmDIPInfo,
1981 	MaxrpmInit, DrvExit, TcsFrame, DrvDraw, DrvScan, &DrvRecalc, 0x40,
1982 	512, 480, 4, 3
1983 };
1984 
1985 
1986 // Rampage (Rev 3, 8/27/86)
1987 
1988 static struct BurnRomInfo rampageRomDesc[] = {
1989 	{ "pro-0_3b_rev_3_8-27-86.3b",					0x08000, 0x2f7ca03c, 1 | BRF_PRG | BRF_ESS }, //  0 Z80 Code
1990 	{ "pro-1_5b_rev_3_8-27-86.5b",					0x08000, 0xd89bd9a4, 1 | BRF_PRG | BRF_ESS }, //  1
1991 
1992 	{ "u-7_rev.2_8-14-86.u7",						0x08000, 0xcffd7fa5, 4 | BRF_PRG | BRF_ESS }, //  2 68K Code
1993 	{ "u-17_rev.2_8-14-86.u17",						0x08000, 0xe92c596b, 4 | BRF_PRG | BRF_ESS }, //  3
1994 	{ "u-8_rev.2_8-14-86.u8",						0x08000, 0x11f787e4, 4 | BRF_PRG | BRF_ESS }, //  4
1995 	{ "u-18_rev.2_8-14-86.u18",						0x08000, 0x6b8bf5e1, 4 | BRF_PRG | BRF_ESS }, //  5
1996 
1997 	{ "bg-0_u15_7-23-86.15a",						0x04000, 0xc0d8b7a5, 1 | BRF_GRA },           //  6 Background Tiles
1998 	{ "bg-1_u14_7-23-86.14b",						0x04000, 0x2f6e3aa1, 1 | BRF_GRA },           //  7
1999 
2000 	{ "fg-0_8e_6-30-86.8e",							0x10000, 0x0974be5d, 2 | BRF_GRA },           //  8 Sprites
2001 	{ "fg-1_6e_6-30-86.6e",							0x10000, 0x8728532b, 2 | BRF_GRA },           //  9
2002 	{ "fg-2_5e_6-30-86.5e",							0x10000, 0x9489f714, 2 | BRF_GRA },           // 10
2003 	{ "fg-3_4e_6-30-86.4e",							0x10000, 0x81e1de40, 2 | BRF_GRA },           // 11
2004 
2005 	{ "e36a31axnaxqd.u15.bin",						0x00001, 0x00000000, 5 | BRF_NODUMP | BRF_OPT },           // 12 Sounds Good PAL
2006 };
2007 
2008 STD_ROM_PICK(rampage)
STD_ROM_FN(rampage)2009 STD_ROM_FN(rampage)
2010 
2011 static INT32 rampage_write_callback(UINT8 address, UINT8 data)
2012 {
2013 	switch (address)
2014 	{
2015 		case 0x06:
2016 		{
2017 			INT32 cycles = ((ZetTotalCycles() * 8) / 5) - SekTotalCycles();
2018 			if (cycles > 0) SekRun(cycles);
2019 			soundsgood_reset_write((~data & 0x20) >> 5);
2020 			soundsgood_data_write(data);
2021 		}
2022 		return 0;
2023 	}
2024 
2025 	return -1;
2026 }
2027 
RampageInit()2028 static INT32 RampageInit()
2029 {
2030 	sound_status_bit = 7;
2031 	sound_input_bank = 4;
2032 	port_write_handler = rampage_write_callback;
2033 
2034     soundsgood_rampage = 1; // for sound-cleanup in soundsgood
2035 
2036     return DrvInit(0);
2037 }
2038 
2039 struct BurnDriver BurnDrvRampage = {
2040 	"rampage", NULL, NULL, NULL, "1986",
2041 	"Rampage (Rev 3, 8/27/86)\0", NULL, "Bally Midway", "MCR3",
2042 	NULL, NULL, NULL, NULL,
2043 	BDF_GAME_WORKING, 3, HARDWARE_MISC_PRE90S, GBF_ACTION, 0,
2044 	NULL, rampageRomInfo, rampageRomName, NULL, NULL, NULL, NULL, RampageInputInfo, RampageDIPInfo,
2045 	RampageInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x40,
2046 	512, 480, 4, 3
2047 };
2048 
2049 
2050 // Rampage (Rev 2, 8/4/86)
2051 
2052 static struct BurnRomInfo rampage2RomDesc[] = {
2053 	{ "pro-0_3b_rev_2_8-4-86.3b",					0x08000, 0x3f1d0293, 1 | BRF_PRG | BRF_ESS }, //  0 Z80 Code
2054 	{ "pro-1_5b_rev_2_8-4-86.5b",					0x08000, 0x58523d75, 1 | BRF_PRG | BRF_ESS }, //  1
2055 
2056 	{ "u-7_rev.2_8-14-86.u7",						0x08000, 0xcffd7fa5, 4 | BRF_PRG | BRF_ESS }, //  2 68K Code
2057 	{ "u-17_rev.2_8-14-86.u17",						0x08000, 0xe92c596b, 4 | BRF_PRG | BRF_ESS }, //  3
2058 	{ "u-8_rev.2_8-14-86.u8",						0x08000, 0x11f787e4, 4 | BRF_PRG | BRF_ESS }, //  4
2059 	{ "u-18_rev.2_8-14-86.u18",						0x08000, 0x6b8bf5e1, 4 | BRF_PRG | BRF_ESS }, //  5
2060 
2061 	{ "bg-0_u15_7-23-86.15a",						0x04000, 0xc0d8b7a5, 1 | BRF_GRA },           //  6 Background Tiles
2062 	{ "bg-1_u14_7-23-86.14b",						0x04000, 0x2f6e3aa1, 1 | BRF_GRA },           //  7
2063 
2064 	{ "fg-0_8e_6-30-86.8e",							0x10000, 0x0974be5d, 2 | BRF_GRA },           //  8 Sprites
2065 	{ "fg-1_6e_6-30-86.6e",							0x10000, 0x8728532b, 2 | BRF_GRA },           //  9
2066 	{ "fg-2_5e_6-30-86.5e",							0x10000, 0x9489f714, 2 | BRF_GRA },           // 10
2067 	{ "fg-3_4e_6-30-86.4e",							0x10000, 0x81e1de40, 2 | BRF_GRA },           // 11
2068 
2069 	{ "e36a31axnaxqd.u15.bin",						0x00001, 0x00000000, 5 | BRF_NODUMP | BRF_OPT },           // 12 Sounds Good PAL
2070 };
2071 
2072 STD_ROM_PICK(rampage2)
2073 STD_ROM_FN(rampage2)
2074 
2075 struct BurnDriver BurnDrvRampage2 = {
2076 	"rampage2", "rampage", NULL, NULL, "1986",
2077 	"Rampage (Rev 2, 8/4/86)\0", NULL, "Bally Midway", "MCR3",
2078 	NULL, NULL, NULL, NULL,
2079 	BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_ACTION, 0,
2080 	NULL, rampage2RomInfo, rampage2RomName, NULL, NULL, NULL, NULL, RampageInputInfo, RampageDIPInfo,
2081 	RampageInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x40,
2082 	512, 480, 4, 3
2083 };
2084 
2085 
2086 // Power Drive
2087 
2088 static struct BurnRomInfo powerdrvRomDesc[] = {
2089 	{ "pdrv3b.bin",									0x08000, 0xd870b704, 1 | BRF_PRG | BRF_ESS }, //  0 Z80 Code
2090 	{ "pdrv5b.bin",									0x08000, 0xfa0544ad, 1 | BRF_PRG | BRF_ESS }, //  1
2091 
2092 	{ "power_drive_snd_u7.u7",						0x08000, 0x78713e78, 4 | BRF_PRG | BRF_ESS }, //  2 68K Code
2093 	{ "power_drive_snd_u17.u17",					0x08000, 0xc41de6e4, 4 | BRF_PRG | BRF_ESS }, //  3
2094 	{ "power_drive_snd_u8.u8",						0x08000, 0x15714036, 4 | BRF_PRG | BRF_ESS }, //  4
2095 	{ "power_drive_snd_u18.u18",					0x08000, 0xcae14c70, 4 | BRF_PRG | BRF_ESS }, //  5
2096 
2097 	{ "pdrv15a.bin",								0x04000, 0xb858b5a8, 1 | BRF_GRA },           //  6 Background Tiles
2098 	{ "pdrv14b.bin",								0x04000, 0x12ee7fc2, 1 | BRF_GRA },           //  7
2099 
2100 	{ "pdrv8e.bin",									0x10000, 0xdd3a2adc, 2 | BRF_GRA },           //  8 Sprites
2101 	{ "pdrv6e.bin",									0x10000, 0x1a1f7f81, 2 | BRF_GRA },           //  9
2102 	{ "pdrv5e.bin",									0x10000, 0x4cb4780e, 2 | BRF_GRA },           // 10
2103 	{ "pdrv4e.bin",									0x10000, 0xde400335, 2 | BRF_GRA },           // 11
2104 };
2105 
2106 STD_ROM_PICK(powerdrv)
STD_ROM_FN(powerdrv)2107 STD_ROM_FN(powerdrv)
2108 
2109 static INT32 PowerdrvInit()
2110 {
2111     is_powerdrv = 1;
2112 	sound_status_bit = 7;
2113 	sound_input_bank = 2;
2114 	port_write_handler = rampage_write_callback;
2115 
2116 	return DrvInit(0);
2117 }
2118 
2119 struct BurnDriver BurnDrvPowerdrv = {
2120 	"powerdrv", NULL, NULL, NULL, "1986",
2121 	"Power Drive\0", NULL, "Bally Midway", "MCR3",
2122 	NULL, NULL, NULL, NULL,
2123 	BDF_GAME_WORKING, 3, HARDWARE_MISC_PRE90S, GBF_RACING, 0,
2124 	NULL, powerdrvRomInfo, powerdrvRomName, NULL, NULL, NULL, NULL, PowerdrvInputInfo, PowerdrvDIPInfo,
2125 	PowerdrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x40,
2126 	512, 480, 4, 3
2127 };
2128 
2129 
2130 // Star Guards
2131 
2132 static struct BurnRomInfo stargrdsRomDesc[] = {
2133 	{ "pro-0.3b",									0x08000, 0x3ad94aa2, 1 | BRF_PRG | BRF_ESS }, //  0 Z80 Code
2134 	{ "pro-1.5b",									0x08000, 0xdba428b0, 1 | BRF_PRG | BRF_ESS }, //  1
2135 
2136 	{ "snd0.u7",									0x08000, 0x7755a493, 4 | BRF_PRG | BRF_ESS }, //  2 68K Code
2137 	{ "snd1.u17",									0x08000, 0xd98d14ae, 4 | BRF_PRG | BRF_ESS }, //  3
2138 
2139 	{ "bg-0.15a",									0x08000, 0xecfaef3e, 1 | BRF_GRA },           //  4 Background Tiles
2140 	{ "bg-1.14b",									0x08000, 0x2c75569d, 1 | BRF_GRA },           //  5
2141 
2142 	{ "fg-0.8e",									0x10000, 0x22797aaa, 2 | BRF_GRA },           //  6 Sprites
2143 	{ "fg-1.6e",									0x10000, 0x413fa119, 2 | BRF_GRA },           //  7
2144 	{ "fg-2.5e",									0x10000, 0x7036cfe6, 2 | BRF_GRA },           //  8
2145 	{ "fg-3.4e",									0x10000, 0xcc5cc003, 2 | BRF_GRA },           //  9
2146 };
2147 
2148 STD_ROM_PICK(stargrds)
STD_ROM_FN(stargrds)2149 STD_ROM_FN(stargrds)
2150 
2151 static INT32 stargrds_write_callback(UINT8 address, UINT8 data)
2152 {
2153 	switch (address)
2154 	{
2155 		case 0x05:
2156 			// coin counter = data & 0x01;
2157 			input_mux = (data & 0x02) >> 1;
2158 			// leds 0x1c
2159 			flipscreen = (data & 0x40) >> 6;
2160 		return 0;
2161 
2162 		case 0x06:
2163 		{
2164 			INT32 cycles = ((ZetTotalCycles() * 8) / 5) - SekTotalCycles();
2165 			if (cycles > 0) SekRun(cycles);
2166 			soundsgood_reset_write((~data & 0x40) >> 6);
2167 			soundsgood_data_write((data << 1) | (data >> 7));
2168 		}
2169 		return 0;
2170 	}
2171 
2172 	return -1;
2173 }
2174 
stargrds_read_callback(UINT8 address)2175 static INT32 stargrds_read_callback(UINT8 address)
2176 {
2177 	switch (address)
2178 	{
2179 		case 0x00:
2180 		{
2181 			UINT8 ret = soundsgood_input_read(0) & 0xff;
2182 			if (input_mux) ret = (ret & 0xf5) | (soundsgood_input_read(5) & 0x0a);
2183 			return ret;
2184 		}
2185 	}
2186 
2187 	return -1;
2188 }
2189 
StargrdsInit()2190 static INT32 StargrdsInit()
2191 {
2192     dip_service = 0x80;
2193 
2194 	sound_status_bit = 4;
2195 	sound_input_bank = 0;
2196 	port_write_handler = stargrds_write_callback;
2197 	port_read_handler = stargrds_read_callback;
2198 
2199 	return DrvInit(0);
2200 }
2201 
2202 struct BurnDriver BurnDrvStargrds = {
2203 	"stargrds", NULL, NULL, NULL, "1987",
2204 	"Star Guards\0", NULL, "Bally Midway", "MCR3",
2205 	NULL, NULL, NULL, NULL,
2206 	BDF_GAME_WORKING, 4, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0,
2207 	NULL, stargrdsRomInfo, stargrdsRomName, NULL, NULL, NULL, NULL, StargrdsInputInfo, StargrdsDIPInfo,
2208 	StargrdsInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x40,
2209 	512, 480, 4, 3
2210 };
2211 
2212 
2213 
2214 // Spy Hunter
2215 
2216 static struct BurnRomInfo spyhuntRomDesc[] = {
2217 	{ "spy-hunter_cpu_pg0_2-9-84.6d",				0x2000, 0x1721b88f, 1 | BRF_PRG | BRF_ESS }, //  0 Z80 #0 Code
2218 	{ "spy-hunter_cpu_pg1_2-9-84.7d",				0x2000, 0x909d044f, 1 | BRF_PRG | BRF_ESS }, //  1
2219 	{ "spy-hunter_cpu_pg2_2-9-84.8d",				0x2000, 0xafeeb8bd, 1 | BRF_PRG | BRF_ESS }, //  2
2220 	{ "spy-hunter_cpu_pg3_2-9-84.9d",				0x2000, 0x5e744381, 1 | BRF_PRG | BRF_ESS }, //  3
2221 	{ "spy-hunter_cpu_pg4_2-9-84.10d",				0x2000, 0xa3033c15, 1 | BRF_PRG | BRF_ESS }, //  4
2222 	{ "spy-hunter_cpu_pg5_2-9-84.11d",				0x4000, 0x88aa1e99, 1 | BRF_PRG | BRF_ESS }, //  5
2223 
2224 	{ "spy-hunter_snd_0_sd_11-18-83.a7",			0x1000, 0xc95cf31e, 2 | BRF_PRG | BRF_ESS }, //  6 Z80 #1 Code (SSIO)
2225 	{ "spy-hunter_snd_1_sd_11-18-83.a8",			0x1000, 0x12aaa48e, 2 | BRF_PRG | BRF_ESS }, //  7
2226 
2227 	{ "spy-hunter_cs_deluxe_u7_a_11-18-83.u7",		0x2000, 0x6e689fe7, 4 | BRF_PRG | BRF_ESS }, //  8 68K Code
2228 	{ "spy-hunter_cs_deluxe_u17_b_11-18-83.u17",	0x2000, 0x0d9ddce6, 4 | BRF_PRG | BRF_ESS }, //  9
2229 	{ "spy-hunter_cs_deluxe_u8_c_11-18-83.u8",		0x2000, 0x35563cd0, 4 | BRF_PRG | BRF_ESS }, // 10
2230 	{ "spy-hunter_cs_deluxe_u18_d_11-18-83.u18",	0x2000, 0x63d3f5b1, 4 | BRF_PRG | BRF_ESS }, // 11
2231 
2232 	{ "spy-hunter_cpu_bg0_11-18-83.3a",				0x2000, 0xdea34fed, 1 | BRF_GRA },           // 12 Background Tiles
2233 	{ "spy-hunter_cpu_bg1_11-18-83.4a",				0x2000, 0x8f64525f, 1 | BRF_GRA },           // 13
2234 	{ "spy-hunter_cpu_bg2_11-18-83.5a",				0x2000, 0xba0fd626, 1 | BRF_GRA },           // 14
2235 	{ "spy-hunter_cpu_bg3_11-18-83.6a",				0x2000, 0x7b482d61, 1 | BRF_GRA },           // 15
2236 
2237 	{ "spy-hunter_video_1fg_11-18-83.a7",			0x4000, 0x9fe286ec, 2 | BRF_GRA },           // 16 Sprites
2238 	{ "spy-hunter_video_0fg_11-18-83.a8",			0x4000, 0x292c5466, 2 | BRF_GRA },           // 17
2239 	{ "spy-hunter_video_3fg_11-18-83.a5",			0x4000, 0xb894934d, 2 | BRF_GRA },           // 18
2240 	{ "spy-hunter_video_2fg_11-18-83.a6",			0x4000, 0x62c8bfa5, 2 | BRF_GRA },           // 19
2241 	{ "spy-hunter_video_5fg_11-18-83.a3",			0x4000, 0x2d9fbcec, 2 | BRF_GRA },           // 20
2242 	{ "spy-hunter_video_4fg_11-18-83.a4",			0x4000, 0x7ca4941b, 2 | BRF_GRA },           // 21
2243 	{ "spy-hunter_video_7fg_11-18-83.a1",			0x4000, 0x940fe17e, 2 | BRF_GRA },           // 22
2244 	{ "spy-hunter_video_6fg_11-18-83.a2",			0x4000, 0x8cb8a066, 2 | BRF_GRA },           // 23
2245 
2246 	{ "spy-hunter_cpu_alpha-n_11-18-83",			0x1000, 0x936dc87f, 3 | BRF_GRA },           // 24 Characters
2247 };
2248 
STDROMPICKEXT(spyhunt,spyhunt,Ssioprom)2249 STDROMPICKEXT(spyhunt, spyhunt, Ssioprom)
2250 STD_ROM_FN(spyhunt)
2251 
2252 static UINT8 spyhunt_ip1_read(UINT8)
2253 {
2254 	return (DrvInputs[1] & ~0x60) | (csd_status_read() << 5);
2255 }
2256 
spyhunt_ip2_read(UINT8)2257 static UINT8 spyhunt_ip2_read(UINT8)
2258 {
2259     UINT8 temp = 0;
2260 
2261     switch (input_mux) {
2262         case 1: {
2263             temp = ProcessAnalog(DrvAnalogPort0, 0, INPUT_DEADZONE, 0x34, 0xb4);
2264             break;
2265         }
2266         case 0: {
2267             temp = ProcessAnalog(DrvAnalogPort1, 0, INPUT_LINEAR | INPUT_MIGHTBEDIGITAL | INPUT_DEADZONE, 0x30, 0xff);
2268             break;
2269         }
2270     }
2271     return temp;
2272 }
2273 
spyhunt_op4_write(UINT8,UINT8 data)2274 static void spyhunt_op4_write(UINT8 , UINT8 data)
2275 {
2276     if (last_op4 & 0x20 && ~data & 0x20) {
2277         if (data&8) lamp |= 1<<(data&7);
2278         if (~data&8) lamp &= ~(1<<(data&7));
2279     }
2280     last_op4 = data;
2281 
2282     input_mux = data >> 7;
2283 
2284     csd_data_write(data);
2285 }
2286 
spyhunt_rom_swap()2287 static void spyhunt_rom_swap()
2288 {
2289 	for (INT32 i = 0; i < 0x2000; i++) { // swap halves of last program rom
2290 		INT32 t = DrvZ80ROM0[0xa000 + i];
2291 		DrvZ80ROM0[0xa000 + i] = DrvZ80ROM0[0xc000 + i];
2292 		DrvZ80ROM0[0xc000 + i] = t;
2293 	}
2294 }
2295 
SpyhuntInit()2296 static INT32 SpyhuntInit()
2297 {
2298     dip_service = 0x80;
2299 
2300     sprite_color_mask = 0;
2301     has_shift = 1; // must be before init!
2302     is_spyhunt = 1;
2303 	INT32 nRet = SpyhuntCommonInit(2);
2304 
2305 	if (nRet == 0)
2306 	{
2307 		ssio_set_custom_input(1, 0x60, spyhunt_ip1_read);
2308 		ssio_set_custom_input(2, 0xff, spyhunt_ip2_read);
2309 		ssio_set_custom_output(4, 0xff, spyhunt_op4_write);
2310 
2311 		spyhunt_rom_swap();
2312 	}
2313 
2314 	return nRet;
2315 }
2316 
2317 struct BurnDriver BurnDrvSpyhunt = {
2318 	"spyhunt", NULL, "midssio", NULL, "1983",
2319 	"Spy Hunter\0", NULL, "Bally Midway", "MCR3",
2320 	NULL, NULL, NULL, NULL,
2321 	BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_ACTION | GBF_SHOOT, 0,
2322 	NULL, spyhuntRomInfo, spyhuntRomName, NULL, NULL, NULL, NULL, SpyhuntInputInfo, SpyhuntDIPInfo,
2323 	SpyhuntInit, DrvExit, CSDSSIOFrame, SpyhuntDraw, DrvScan, &DrvRecalc, 0x40,
2324 	480, 480, 3, 4
2325 };
2326 
2327 
2328 // Spy Hunter (Playtronic license)
2329 
2330 static struct BurnRomInfo spyhuntpRomDesc[] = {
2331 	{ "sh_mb_2.bin",								0x2000, 0xdf6cd642, 1 | BRF_PRG | BRF_ESS }, //  0 Z80 #0 Code
2332 	{ "spy-hunter_cpu_pg1_2-9-84.7d",				0x2000, 0x909d044f, 1 | BRF_PRG | BRF_ESS }, //  1
2333 	{ "spy-hunter_cpu_pg2_2-9-84.8d",				0x2000, 0xafeeb8bd, 1 | BRF_PRG | BRF_ESS }, //  2
2334 	{ "spy-hunter_cpu_pg3_2-9-84.9d",				0x2000, 0x5e744381, 1 | BRF_PRG | BRF_ESS }, //  3
2335 	{ "sh_mb_6.bin",								0x2000, 0x8cbf04d8, 1 | BRF_PRG | BRF_ESS }, //  4
2336 	{ "spy-hunter_cpu_pg5_2-9-84.11d",				0x4000, 0x88aa1e99, 1 | BRF_PRG | BRF_ESS }, //  5
2337 
2338 	{ "spy-hunter_snd_0_sd_11-18-83.a7",			0x1000, 0xc95cf31e, 2 | BRF_PRG | BRF_ESS }, //  6 Z80 #1 Code (SSIO)
2339 	{ "spy-hunter_snd_1_sd_11-18-83.a8",			0x1000, 0x12aaa48e, 2 | BRF_PRG | BRF_ESS }, //  7
2340 
2341 	{ "spy-hunter_cs_deluxe_u7_a_11-18-83.u7",		0x2000, 0x6e689fe7, 4 | BRF_PRG | BRF_ESS }, //  8 68K Code
2342 	{ "spy-hunter_cs_deluxe_u17_b_11-18-83.u17",	0x2000, 0x0d9ddce6, 4 | BRF_PRG | BRF_ESS }, //  9
2343 	{ "spy-hunter_cs_deluxe_u8_c_11-18-83.u8",		0x2000, 0x35563cd0, 4 | BRF_PRG | BRF_ESS }, // 10
2344 	{ "spy-hunter_cs_deluxe_u18_d_11-18-83.u18",	0x2000, 0x63d3f5b1, 4 | BRF_PRG | BRF_ESS }, // 11
2345 
2346 	{ "spy-hunter_cpu_bg0_11-18-83.3a",				0x2000, 0xdea34fed, 1 | BRF_GRA },           // 12 Background Tiles
2347 	{ "spy-hunter_cpu_bg1_11-18-83.4a",				0x2000, 0x8f64525f, 1 | BRF_GRA },           // 13
2348 	{ "spy-hunter_cpu_bg2_11-18-83.5a",				0x2000, 0xba0fd626, 1 | BRF_GRA },           // 14
2349 	{ "spy-hunter_cpu_bg3_11-18-83.6a",				0x2000, 0x7b482d61, 1 | BRF_GRA },           // 15
2350 
2351 	{ "spy-hunter_video_1fg_11-18-83.a7",			0x4000, 0x9fe286ec, 2 | BRF_GRA },           // 16 Sprites
2352 	{ "spy-hunter_video_0fg_11-18-83.a8",			0x4000, 0x292c5466, 2 | BRF_GRA },           // 17
2353 	{ "spy-hunter_video_3fg_11-18-83.a5",			0x4000, 0xb894934d, 2 | BRF_GRA },           // 18
2354 	{ "spy-hunter_video_2fg_11-18-83.a6",			0x4000, 0x62c8bfa5, 2 | BRF_GRA },           // 19
2355 	{ "spy-hunter_video_5fg_11-18-83.a3",			0x4000, 0x2d9fbcec, 2 | BRF_GRA },           // 20
2356 	{ "spy-hunter_video_4fg_11-18-83.a4",			0x4000, 0x7ca4941b, 2 | BRF_GRA },           // 21
2357 	{ "spy-hunter_video_7fg_11-18-83.a1",			0x4000, 0x940fe17e, 2 | BRF_GRA },           // 22
2358 	{ "spy-hunter_video_6fg_11-18-83.a2",			0x4000, 0x8cb8a066, 2 | BRF_GRA },           // 23
2359 
2360 	{ "sh_mb_1.bin",								0x0800, 0x5c74c9f0, 3 | BRF_GRA },           // 24 Characters
2361 };
2362 
2363 STDROMPICKEXT(spyhuntp, spyhuntp, Ssioprom)
2364 STD_ROM_FN(spyhuntp)
2365 
2366 struct BurnDriver BurnDrvSpyhuntp = {
2367 	"spyhuntp", "spyhunt", "midssio", NULL, "1983",
2368 	"Spy Hunter (Playtronic license)\0", NULL, "Bally Midway (Playtronic license)", "MCR3",
2369 	NULL, NULL, NULL, NULL,
2370 	BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 2, HARDWARE_MISC_PRE90S, GBF_ACTION | GBF_SHOOT, 0,
2371 	NULL, spyhuntpRomInfo, spyhuntpRomName, NULL, NULL, NULL, NULL, SpyhuntInputInfo, SpyhuntDIPInfo,
2372 	SpyhuntInit, DrvExit, CSDSSIOFrame, SpyhuntDraw, DrvScan, &DrvRecalc, 0x40,
2373 	480, 480, 3, 4
2374 };
2375 
2376 
2377 // Crater Raider
2378 
2379 static struct BurnRomInfo craterRomDesc[] = {
2380 	{ "crcpu.6d",									0x2000, 0xad31f127, 1 | BRF_PRG | BRF_ESS }, //  0 Z80 #0 Code
2381 	{ "crcpu.7d",									0x2000, 0x3743c78f, 1 | BRF_PRG | BRF_ESS }, //  1
2382 	{ "crcpu.8d",									0x2000, 0xc95f9088, 1 | BRF_PRG | BRF_ESS }, //  2
2383 	{ "crcpu.9d",									0x2000, 0xa03c4b11, 1 | BRF_PRG | BRF_ESS }, //  3
2384 	{ "crcpu.10d",									0x2000, 0x44ae4cbd, 1 | BRF_PRG | BRF_ESS }, //  4
2385 
2386 	{ "crsnd4.a7",									0x1000, 0xfd666cb5, 2 | BRF_PRG | BRF_ESS }, //  5 Z80 #1 Code (SSIO)
2387 	{ "crsnd1.a8",									0x1000, 0x90bf2c4c, 2 | BRF_PRG | BRF_ESS }, //  6
2388 	{ "crsnd2.a9",									0x1000, 0x3b8deef1, 2 | BRF_PRG | BRF_ESS }, //  7
2389 	{ "crsnd3.a10",									0x1000, 0x05803453, 2 | BRF_PRG | BRF_ESS }, //  8
2390 
2391 	{ "crcpu.3a",									0x2000, 0x9d73504a, 1 | BRF_GRA },           //  9 Background Tiles
2392 	{ "crcpu.4a",									0x2000, 0x42a47dff, 1 | BRF_GRA },           // 10
2393 	{ "crcpu.5a",									0x2000, 0x2fe4a6e1, 1 | BRF_GRA },           // 11
2394 	{ "crcpu.6a",									0x2000, 0xd0659042, 1 | BRF_GRA },           // 12
2395 
2396 	{ "crvid.a4",									0x4000, 0x579a8e36, 2 | BRF_GRA },           // 13 Sprites
2397 	{ "crvid.a3",									0x4000, 0x2c2f5b29, 2 | BRF_GRA },           // 14
2398 	{ "crvid.a6",									0x4000, 0x5bf954e0, 2 | BRF_GRA },           // 15
2399 	{ "crvid.a5",									0x4000, 0x9bdec312, 2 | BRF_GRA },           // 16
2400 	{ "crvid.a8",									0x4000, 0x4b913498, 2 | BRF_GRA },           // 17
2401 	{ "crvid.a7",									0x4000, 0x9fa307d5, 2 | BRF_GRA },           // 18
2402 	{ "crvid.a10",									0x4000, 0x7a22d6bc, 2 | BRF_GRA },           // 19
2403 	{ "crvid.a9",									0x4000, 0x811f152d, 2 | BRF_GRA },           // 20
2404 
2405 	{ "crcpu.10g",									0x1000, 0x6fe53c8d, 3 | BRF_GRA },           // 21 Characters
2406 };
2407 
STDROMPICKEXT(crater,crater,Ssioprom)2408 STDROMPICKEXT(crater, crater, Ssioprom)
2409 STD_ROM_FN(crater)
2410 
2411 static UINT8 crater_ip1_read(UINT8)
2412 {
2413     return BurnTrackballRead(0, 0);
2414 }
2415 
CraterInit()2416 static INT32 CraterInit()
2417 {
2418     dip_service = 0x80;
2419 
2420 	INT32 nRet = SpyhuntCommonInit(3);
2421 
2422 	if (nRet == 0)
2423 	{
2424         flip_screen_x = TMAP_FLIPX;
2425         sprite_color_mask = 3;
2426         has_dial = 1;
2427 
2428         ssio_set_custom_input(1, 0xff, crater_ip1_read);
2429     }
2430 
2431     return nRet;
2432 }
2433 
2434 struct BurnDriverD BurnDrvCrater = {
2435 	"crater", NULL, "midssio", NULL, "1984",
2436 	"Crater Raider\0", "Graphics Issues", "Bally Midway", "MCR3",
2437 	NULL, NULL, NULL, NULL,
2438 	BDF_GAME_NOT_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0,
2439 	NULL, craterRomInfo, craterRomName, NULL, NULL, NULL, NULL, CraterInputInfo, CraterDIPInfo,
2440 	CraterInit, DrvExit, CSDSSIOFrame, SpyhuntDraw, DrvScan, &DrvRecalc, 0x40,
2441 	480, 480, 4, 3
2442 };
2443