1 // FB Alpha Battlezone / Bradley Tank Trainer / Red Baron driver module
2 // Based on MAME driver by Brad Oliver and Nicola Salmoria
3 
4 #include "tiles_generic.h"
5 #include "m6502_intf.h"
6 #include "burn_gun.h"
7 #include "mathbox.h"
8 #include "vector.h"
9 #include "avgdvg.h"
10 #include "pokey.h"
11 #include "watchdog.h"
12 #include "earom.h"
13 #include "redbaron.h" // audio custom
14 #include "bzone.h" // audio custom
15 
16 static UINT8 *AllMem;
17 static UINT8 *MemEnd;
18 static UINT8 *AllRam;
19 static UINT8 *RamEnd;
20 static UINT8 *DrvM6502ROM;
21 static UINT8 *DrvM6502RAM;
22 static UINT8 *DrvVectorRAM;
23 static UINT8 *DrvVectorROM;
24 
25 static UINT32 *DrvPalette;
26 static UINT8 DrvRecalc;
27 
28 static INT32 nExtraCycles;
29 static INT32 avgletsgo = 0;
30 static UINT8 analog_data = 0;
31 static INT32 input_select = 0;
32 
33 static UINT8 DrvJoy1[8];
34 static UINT8 DrvJoy2[8];
35 static UINT8 DrvJoy3[8];
36 static UINT8 DrvJoy4[8];
37 static UINT8 DrvJoy5[8];
38 static UINT8 DrvFakeInput[4];
39 static UINT8 DrvDips[4];
40 static UINT8 DrvInputs[5];
41 static UINT8 DrvReset;
42 
43 static INT16 DrvAnalogPort0 = 0;
44 static INT16 DrvAnalogPort1 = 0;
45 static INT16 DrvAnalogPort2 = 0;
46 
47 static INT32 x_target, y_target; // for smooth moves between analog values
48 static INT32 x_adder, y_adder;
49 
50 static INT32 bradley = 0;
51 static INT32 redbaron = 0;
52 static INT32 redbarona = 0;
53 
54 static struct BurnInputInfo BzoneInputList[] = {
55 	{"P1 Coin",				BIT_DIGITAL,	DrvJoy1 + 0,		"p1 coin"	},
56 	{"P2 Coin",				BIT_DIGITAL,	DrvJoy1 + 1,		"p2 coin"	},
57 	{"Start 1",				BIT_DIGITAL,	DrvJoy2 + 5,		"p1 start"	},
58 	{"Start 2",				BIT_DIGITAL,	DrvJoy2 + 6,		"p2 start"	},
59 	{"Fire",				BIT_DIGITAL,	DrvJoy2 + 4,		"p1 fire 1"	},
60 	{"P1 Left Stick Up",	BIT_DIGITAL,	DrvJoy2 + 3,		"p1 fire 2"	},
61 	{"P1 Left Stick Down",	BIT_DIGITAL,	DrvJoy2 + 2,		"p1 fire 3"	},
62 	{"P1 Right Stick Up",	BIT_DIGITAL,	DrvJoy2 + 1,		"p1 fire 4"	},
63 	{"P1 Right Stick Down",	BIT_DIGITAL,	DrvJoy2 + 0,		"p1 fire 5"	},
64 	{"P1 Up (Fake)",		BIT_DIGITAL,	DrvFakeInput + 0,	"p1 up"		},
65 	{"P1 Down (Fake)",		BIT_DIGITAL,	DrvFakeInput + 1,	"p1 down"	},
66 	{"P1 Left (Fake)",		BIT_DIGITAL,	DrvFakeInput + 2,	"p1 left"	},
67 	{"P1 Right (Fake)",		BIT_DIGITAL,	DrvFakeInput + 3,	"p1 right"	},
68 
69 	{"Reset",				BIT_DIGITAL,	&DrvReset,			"reset"		},
70 	{"Dip A",				BIT_DIPSWITCH,	DrvDips + 0,		"dip"		},
71 	{"Dip B",				BIT_DIPSWITCH,	DrvDips + 1,		"dip"		},
72 	{"Dip C",				BIT_DIPSWITCH,	DrvDips + 2,		"dip"		},
73 	{"Dip D",				BIT_DIPSWITCH,	DrvDips + 3,		"dip"		},
74 };
75 
76 STDINPUTINFO(Bzone)
77 
78 #define A(a, b, c, d) {a, b, (UINT8*)(c), d}
79 static struct BurnInputInfo RedbaronInputList[] = {
80 	{"P1 Coin",				BIT_DIGITAL,	DrvJoy1 + 0,	"p1 coin"	},
81 	{"P1 Start",			BIT_DIGITAL,	DrvJoy3 + 6,	"p1 start"	},
82 	{"P1 Up",				BIT_DIGITAL,	DrvJoy2 + 2,	"p1 up"		},
83 	{"P1 Down",				BIT_DIGITAL,	DrvJoy2 + 3,	"p1 down"	},
84 	{"P1 Left",				BIT_DIGITAL,	DrvJoy2 + 0,	"p1 left"	},
85 	{"P1 Right",			BIT_DIGITAL,	DrvJoy2 + 1,	"p1 right"	},
86 	{"P1 Button 1",			BIT_DIGITAL,	DrvJoy3 + 7,	"p1 fire 1"	},
87 
88 	A("P1 Stick X",         BIT_ANALOG_REL, &DrvAnalogPort0,"p1 x-axis" ),
89 	A("P1 Stick Y",         BIT_ANALOG_REL, &DrvAnalogPort1,"p1 y-axis" ),
90 
91 	{"Reset",				BIT_DIGITAL,	&DrvReset,		"reset"		},
92 	{"Diagnostic Step",		BIT_DIGITAL,	DrvJoy1 + 5,	"service2"	},
93 	{"Dip A",				BIT_DIPSWITCH,	DrvDips + 0,	"dip"		},
94 	{"Dip B",				BIT_DIPSWITCH,	DrvDips + 1,	"dip"		},
95 	{"Dip C",				BIT_DIPSWITCH,	DrvDips + 2,	"dip"		},
96 	{"Dip D",				BIT_DIPSWITCH,	DrvDips + 3,	"dip"		},
97 };
98 #undef A
99 
100 STDINPUTINFO(Redbaron)
101 
102 #define A(a, b, c, d) {a, b, (UINT8*)(c), d}
103 static struct BurnInputInfo BradleyInputList[] = {
104 	{"Coin 1",			BIT_DIGITAL,	DrvJoy1 + 0,	"p1 coin"	},
105 	{"Coin 2",			BIT_DIGITAL,	DrvJoy1 + 1,	"p2 coin"	},
106 	{"P1 Start",		BIT_DIGITAL,	DrvJoy2 + 5,	"p1 start"	},
107 	{"P1 Button 1",		BIT_DIGITAL,	DrvJoy3 + 1,	"p1 fire 1"	},
108 	{"P1 Button 2",		BIT_DIGITAL,	DrvJoy3 + 2,	"p1 fire 2"	},
109 	{"P1 Button 3",		BIT_DIGITAL,	DrvJoy3 + 3,	"p1 fire 3"	},
110 	{"P1 Button 4",		BIT_DIGITAL,	DrvJoy3 + 4,	"p1 fire 4"	},
111 	{"P1 Button 5",		BIT_DIGITAL,	DrvJoy3 + 5,	"p1 fire 5"	},
112 	{"P1 Button 6",		BIT_DIGITAL,	DrvJoy3 + 6,	"p1 fire 6"	},
113 	{"P1 Button 7",		BIT_DIGITAL,	DrvJoy3 + 7,	"p1 fire 7"	},
114 	{"P1 Button 8",		BIT_DIGITAL,	DrvJoy4 + 3,	"p1 fire 8"	},
115 	{"P1 Button 9",		BIT_DIGITAL,	DrvJoy4 + 2,	"p1 fire 9"	},
116 	{"P1 Button 10",	BIT_DIGITAL,	DrvJoy4 + 4,	"p1 fire 10"},
117 
118 	A("P1 Stick X",     BIT_ANALOG_REL, &DrvAnalogPort0,"p1 x-axis" ),
119 	A("P1 Stick Y",     BIT_ANALOG_REL, &DrvAnalogPort1,"p1 y-axis" ),
120 	A("P1 Stick Z",     BIT_ANALOG_REL, &DrvAnalogPort2,"p1 z-axis" ),
121 
122 	{"Reset",			BIT_DIGITAL,	&DrvReset,		"reset"		},
123 	{"Service",			BIT_DIGITAL,	DrvJoy1 + 5,	"service"	},
124 	{"Dip A",			BIT_DIPSWITCH,	DrvDips + 0,	"dip"		},
125 	{"Dip B",			BIT_DIPSWITCH,	DrvDips + 1,	"dip"		},
126 	{"Dip C",			BIT_DIPSWITCH,	DrvDips + 2,	"dip"		},
127 	{"Dip D",			BIT_DIPSWITCH,	DrvDips + 3,	"dip"		},
128 };
129 #undef A
130 
131 STDINPUTINFO(Bradley)
132 
133 static struct BurnDIPInfo BzoneDIPList[]=
134 {
135 	DIP_OFFSET(0x0e)
136 
137 	{0x00, 0xff, 0xff, 0x15, NULL					},
138 	{0x01, 0xff, 0xff, 0x02, NULL					},
139 	{0x02, 0xff, 0xff, 0x10, NULL					},
140 	{0x03, 0xff, 0xff, 0x00, NULL					},
141 
142 	{0   , 0xfe, 0   ,    4, "Lives"				},
143 	{0x00, 0x01, 0x03, 0x00, "2"					},
144 	{0x00, 0x01, 0x03, 0x01, "3"					},
145 	{0x00, 0x01, 0x03, 0x02, "4"					},
146 	{0x00, 0x01, 0x03, 0x03, "5"					},
147 
148 	{0   , 0xfe, 0   ,    4, "Missile appears at"	},
149 	{0x00, 0x01, 0x0c, 0x00, "5000"					},
150 	{0x00, 0x01, 0x0c, 0x04, "10000"				},
151 	{0x00, 0x01, 0x0c, 0x08, "20000"				},
152 	{0x00, 0x01, 0x0c, 0x0c, "30000"				},
153 
154 	{0   , 0xfe, 0   ,    4, "Bonus Life"			},
155 	{0x00, 0x01, 0x30, 0x10, "15k and 100k"			},
156 	{0x00, 0x01, 0x30, 0x20, "25k and 100k"			},
157 	{0x00, 0x01, 0x30, 0x30, "50k and 100k"			},
158 	{0x00, 0x01, 0x30, 0x00, "None"					},
159 
160 	{0   , 0xfe, 0   ,    4, "Language"				},
161 	{0x00, 0x01, 0xc0, 0x00, "English"				},
162 	{0x00, 0x01, 0xc0, 0x40, "German"				},
163 	{0x00, 0x01, 0xc0, 0x80, "French"				},
164 	{0x00, 0x01, 0xc0, 0xc0, "Spanish"				},
165 
166 	{0   , 0xfe, 0   ,    4, "Coinage"				},
167 	{0x01, 0x01, 0x03, 0x03, "2 Coins 1 Credits"	},
168 	{0x01, 0x01, 0x03, 0x02, "1 Coin  1 Credits"	},
169 	{0x01, 0x01, 0x03, 0x01, "1 Coin  2 Credits"	},
170 	{0x01, 0x01, 0x03, 0x00, "Free Play"			},
171 
172 	{0   , 0xfe, 0   ,    4, "Coin B"				},
173 	{0x01, 0x01, 0x0c, 0x00, "*1"					},
174 	{0x01, 0x01, 0x0c, 0x04, "*4"					},
175 	{0x01, 0x01, 0x0c, 0x08, "*5"					},
176 	{0x01, 0x01, 0x0c, 0x0c, "*6"					},
177 
178 	{0   , 0xfe, 0   ,    2, "Coin A"				},
179 	{0x01, 0x01, 0x10, 0x00, "*1"					},
180 	{0x01, 0x01, 0x10, 0x10, "*2"					},
181 
182 	{0   , 0xfe, 0   ,    5, "Bonus Coins"			},
183 	{0x01, 0x01, 0xe0, 0x00, "None"					},
184 	{0x01, 0x01, 0xe0, 0x20, "3 credits/2 coins"	},
185 	{0x01, 0x01, 0xe0, 0x40, "5 credits/4 coins"	},
186 	{0x01, 0x01, 0xe0, 0x60, "6 credits/4 coins"	},
187 	{0x01, 0x01, 0xe0, 0x80, "6 credits/5 coins"	},
188 
189 	{0   , 0xfe, 0   ,    2, "Service Mode"			},
190 	{0x02, 0x01, 0x10, 0x00, "On"					},
191 	{0x02, 0x01, 0x10, 0x10, "Off"					},
192 
193 	{0   , 0xfe, 0   ,    2, "Hires Mode"			},
194 	{0x03, 0x01, 0x01, 0x00, "No"					},
195 	{0x03, 0x01, 0x01, 0x01, "Yes"					},
196 };
197 
198 STDDIPINFO(Bzone)
199 
200 static struct BurnDIPInfo RedbaronDIPList[]=
201 {
202 	{0x0b, 0xff, 0xff, 0xfd, NULL					},
203 	{0x0c, 0xff, 0xff, 0xe7, NULL					},
204 	{0x0d, 0xff, 0xff, 0x10, NULL					},
205 	{0x0e, 0xff, 0xff, 0x00, NULL					},
206 
207 	{0   , 0xfe, 0   ,    1, "Coinage"				},
208 	{0x0b, 0x01, 0xff, 0xfd, "Normal"				},
209 
210 	{0   , 0xfe, 0   ,    4, "Language"				},
211 	{0x0c, 0x01, 0x03, 0x00, "German"				},
212 	{0x0c, 0x01, 0x03, 0x01, "French"				},
213 	{0x0c, 0x01, 0x03, 0x02, "Spanish"				},
214 	{0x0c, 0x01, 0x03, 0x03, "English"				},
215 
216 	{0   , 0xfe, 0   ,    4, "Bonus Life"			},
217 	{0x0c, 0x01, 0x0c, 0x0c, "2k 10k 30k"			},
218 	{0x0c, 0x01, 0x0c, 0x08, "4k 15k 40k"			},
219 	{0x0c, 0x01, 0x0c, 0x04, "6k 20k 50k"			},
220 	{0x0c, 0x01, 0x0c, 0x00, "None"					},
221 
222 	{0   , 0xfe, 0   ,    4, "Lives"				},
223 	{0x0c, 0x01, 0x30, 0x30, "2"					},
224 	{0x0c, 0x01, 0x30, 0x20, "3"					},
225 	{0x0c, 0x01, 0x30, 0x10, "4"					},
226 	{0x0c, 0x01, 0x30, 0x00, "5"					},
227 
228 	{0   , 0xfe, 0   ,    2, "One Play Minimum"		},
229 	{0x0c, 0x01, 0x40, 0x40, "Off"					},
230 	{0x0c, 0x01, 0x40, 0x00, "On"					},
231 
232 	{0   , 0xfe, 0   ,    2, "Self Adjust Diff"		},
233 	{0x0c, 0x01, 0x80, 0x80, "Off"					},
234 	{0x0c, 0x01, 0x80, 0x00, "On"					},
235 
236 	{0   , 0xfe, 0   ,    2, "Service Mode"			},
237 	{0x0d, 0x01, 0x10, 0x00, "On"					},
238 	{0x0d, 0x01, 0x10, 0x10, "Off"					},
239 
240 	{0   , 0xfe, 0   ,    2, "Hires Mode"			},
241 	{0x0e, 0x01, 0x01, 0x00, "No"					},
242 	{0x0e, 0x01, 0x01, 0x01, "Yes"					},
243 };
244 
245 STDDIPINFO(Redbaron)
246 
247 static struct BurnDIPInfo BradleyDIPList[]=
248 {
249 	{0x12, 0xff, 0xff, 0x15, NULL					},
250 	{0x13, 0xff, 0xff, 0x02, NULL					},
251 	{0x14, 0xff, 0xff, 0x10, NULL					},
252 	{0x15, 0xff, 0xff, 0x00, NULL					},
253 
254 	{0   , 0xfe, 0   ,    4, "Lives"				},
255 	{0x12, 0x01, 0x03, 0x00, "2"					},
256 	{0x12, 0x01, 0x03, 0x01, "3"					},
257 	{0x12, 0x01, 0x03, 0x02, "4"					},
258 	{0x12, 0x01, 0x03, 0x03, "5"					},
259 
260 	{0   , 0xfe, 0   ,    4, "Missile appears at"	},
261 	{0x12, 0x01, 0x0c, 0x00, "5000"					},
262 	{0x12, 0x01, 0x0c, 0x04, "10000"				},
263 	{0x12, 0x01, 0x0c, 0x08, "20000"				},
264 	{0x12, 0x01, 0x0c, 0x0c, "30000"				},
265 
266 	{0   , 0xfe, 0   ,    4, "Bonus Life"			},
267 	{0x12, 0x01, 0x30, 0x10, "15k and 100k"			},
268 	{0x12, 0x01, 0x30, 0x20, "25k and 100k"			},
269 	{0x12, 0x01, 0x30, 0x30, "50k and 100k"			},
270 	{0x12, 0x01, 0x30, 0x00, "None"					},
271 
272 	{0   , 0xfe, 0   ,    4, "Language"				},
273 	{0x12, 0x01, 0xc0, 0x00, "English"				},
274 	{0x12, 0x01, 0xc0, 0x40, "German"				},
275 	{0x12, 0x01, 0xc0, 0x80, "French"				},
276 	{0x12, 0x01, 0xc0, 0xc0, "Spanish"				},
277 
278 	{0   , 0xfe, 0   ,    4, "Coinage"				},
279 	{0x13, 0x01, 0x03, 0x03, "2 Coins 1 Credits"	},
280 	{0x13, 0x01, 0x03, 0x02, "1 Coin  1 Credits"	},
281 	{0x13, 0x01, 0x03, 0x01, "1 Coin  2 Credits"	},
282 	{0x13, 0x01, 0x03, 0x00, "Free Play"			},
283 
284 	{0   , 0xfe, 0   ,    4, "Coin B"				},
285 	{0x13, 0x01, 0x0c, 0x00, "*1"					},
286 	{0x13, 0x01, 0x0c, 0x04, "*4"					},
287 	{0x13, 0x01, 0x0c, 0x08, "*5"					},
288 	{0x13, 0x01, 0x0c, 0x0c, "*6"					},
289 
290 	{0   , 0xfe, 0   ,    2, "Coin A"				},
291 	{0x13, 0x01, 0x10, 0x00, "*1"					},
292 	{0x13, 0x01, 0x10, 0x10, "*2"					},
293 
294 	{0   , 0xfe, 0   ,    5, "Bonus Coins"			},
295 	{0x13, 0x01, 0xe0, 0x00, "None"					},
296 	{0x13, 0x01, 0xe0, 0x20, "3 credits/2 coins"	},
297 	{0x13, 0x01, 0xe0, 0x40, "5 credits/4 coins"	},
298 	{0x13, 0x01, 0xe0, 0x60, "6 credits/4 coins"	},
299 	{0x13, 0x01, 0xe0, 0x80, "6 credits/5 coins"	},
300 
301 	{0   , 0xfe, 0   ,    2, "Service Mode"			},
302 	{0x14, 0x01, 0x10, 0x00, "On"					},
303 	{0x14, 0x01, 0x10, 0x10, "Off"					},
304 
305 	{0   , 0xfe, 0   ,    2, "Hires Mode"			},
306 	{0x15, 0x01, 0x01, 0x00, "No"					},
307 	{0x15, 0x01, 0x01, 0x01, "Yes"					},
308 };
309 
STDDIPINFO(Bradley)310 STDDIPINFO(Bradley)
311 
312 
313 static UINT8 bzone_read(UINT16 address)
314 {
315 	if ((address & 0xfff0) == 0x1820) {
316 		return pokey_read(0, address & 0x0f);
317 	}
318 
319 	if ((address & 0xffe0) == 0x1860) {
320 		return 0; // reads a lot from here.. why? writes are mathbox_go_write (same as tempest)
321 	}
322 
323 	switch (address)
324 	{
325 		case 0x0800: {
326 			UINT8 ret = DrvInputs[0] ^ 0xff;
327 			ret &= ~0x10;
328 			ret |= DrvDips[2] & 0x10; // 0x10 as a test!
329 			ret &= ~0x40;
330 			ret |= (avgdvg_done() ? 0x40 : 0);
331 			ret &= ~0x80;
332 			ret |= (M6502TotalCycles() & 0x100) ? 0x80 : 0;
333 			return ret;
334 		}
335 
336 		case 0x0a00:
337 			return DrvDips[0];
338 
339 		case 0x0c00:
340 			return DrvDips[1];
341 
342 		case 0x1800:
343 			return mathbox_status_read();
344 
345 		case 0x1808:
346 			return DrvInputs[2]; // bradley
347 
348 		case 0x1809:
349 			return DrvInputs[3]; // bradley
350 
351 		case 0x180a:
352 			return analog_data; // bradley
353 
354 		case 0x1810:
355 			return mathbox_lo_read();
356 
357 		case 0x1818:
358 			return mathbox_hi_read();
359 
360 		case 0x1848:  // bradley (?)
361 		case 0x1849:
362 		case 0x184a:
363 			return 0;
364 	}
365 
366 	return 0;
367 }
368 
bzone_write(UINT16 address,UINT8 data)369 static void bzone_write(UINT16 address, UINT8 data)
370 {
371 	if ((address & 0xfff0) == 0x1820) {
372 		pokey_write(0, address & 0x0f, data);
373 		return;
374 	}
375 
376 	if ((address & 0xffe0) == 0x1860) {
377 		mathbox_go_write(address & 0x1f, data);
378 		return;
379 	}
380 
381 	switch (address)
382 	{
383 		case 0x1000:
384 			// coin counter
385 		return;
386 
387 		case 0x1200:
388 			avgdvg_go();
389 			avgletsgo = 1;
390 		return;
391 
392 		case 0x1400:
393 			BurnWatchdogWrite();
394 		return;
395 
396 		case 0x1600:
397 			avgdvg_reset();
398 		return;
399 
400 		case 0x1808: // bradley (?)
401 		return;
402 
403 		case 0x1840:
404 			bzone_sound_write(data);
405 		return;
406 
407 		// bradley analog select
408 		case 0x1848: analog_data = x_adder; break;
409 		case 0x1849: analog_data = y_adder; break;
410 		case 0x184a: analog_data = ProcessAnalog(DrvAnalogPort2, 1, 1, 0x10, 0xf0); break;
411 
412 		case 0x184b:
413 		case 0x184c:
414 		case 0x184d:
415 		case 0x184e:
416 		case 0x184f:
417 		case 0x1850:
418 		return; // nop's
419 	}
420 }
421 
redbaron_read(UINT16 address)422 static UINT8 redbaron_read(UINT16 address)
423 {
424 	if ((address & 0xfff0) == 0x1810) {
425 		return pokey_read(0, address & 0x0f);
426 	}
427 
428 	if (address >= 0x1820 && address <= 0x185f) {
429 		return earom_read(address - 0x1820);
430 	}
431 
432 	if ((address & 0xffe0) == 0x1860) {
433 		return 0; // reads a lot from here.. why? writes are mathbox_go_write (tempest does this, too)
434 	}
435 
436 	switch (address)
437 	{
438 		case 0x0800: {
439 			UINT8 ret = DrvInputs[0] ^ 0xff;
440 			ret &= ~0x10;
441 			ret |= DrvDips[2] & 0x10; // 0x10 as a test!
442 			ret &= ~0x40;
443 			ret |= (avgdvg_done() ? 0x40 : 0);
444 			ret &= ~0x80;
445 			ret |= (M6502TotalCycles() & 0x100) ? 0x80 : 0;
446 			return ret;
447 		}
448 
449 		case 0x0a00:
450 			return DrvDips[0];
451 
452 		case 0x0c00:
453 			return DrvDips[1];
454 
455 		case 0x1800:
456 			return mathbox_status_read();
457 
458 		case 0x1802:
459 			return DrvInputs[2]; // in4
460 
461 		case 0x1804:
462 			return mathbox_lo_read();
463 
464 		case 0x1806:
465 			return mathbox_hi_read();
466 	}
467 
468 	return 0;
469 }
470 
redbaron_write(UINT16 address,UINT8 data)471 static void redbaron_write(UINT16 address, UINT8 data)
472 {
473 	if ((address & 0xfff0) == 0x1810) {
474 		pokey_write(0, address & 0x0f, data);
475 		return;
476 	}
477 
478 	if (address >= 0x1820 && address <= 0x185f) {
479 		earom_write(address - 0x1820, data);
480 		return;
481 	}
482 
483 	if ((address & 0xffe0) == 0x1860) {
484 		mathbox_go_write(address & 0x1f, data);
485 		return;
486 	}
487 
488 	switch (address)
489 	{
490 		case 0x1000:
491 		return;
492 
493 		case 0x1200:
494 			avgdvg_go();
495 			avgletsgo = 1;
496 		return;
497 
498 		case 0x1400:
499 			BurnWatchdogWrite();
500 		return;
501 
502 		case 0x1600:
503 			avgdvg_reset();
504 		return;
505 
506 		case 0x1808:
507 			redbaron_sound_write(data);
508 			input_select = data & 1;
509 		return;
510 
511 		case 0x180a:
512 		return; // nop
513 
514 		case 0x180c:
515 			earom_ctrl_write(address, data);
516 		return;
517 	}
518 }
519 
update_analog()520 static void update_analog()
521 {
522     #define XY_RATE 8
523 	if (x_adder != x_target) {
524 		if (x_adder+XY_RATE <= x_target) x_adder += XY_RATE;
525 		else if (x_adder+1 <= x_target) x_adder += 1;
526 
527 		else if (x_adder-XY_RATE >= x_target) x_adder -= XY_RATE;
528 		else if (x_adder-1 >= x_target) x_adder -= 1;
529 	}
530 
531 	if (y_adder != y_target) {
532 		if (y_adder+XY_RATE <= y_target) y_adder += XY_RATE;
533 		else if (y_adder+1 <= y_target) y_adder += 1;
534 
535 		else if (y_adder-XY_RATE >= y_target) y_adder -= XY_RATE;
536 		else if (y_adder-1 >= y_target) y_adder -= 1;
537 	}
538 }
539 
bzone_port0_read(INT32)540 static INT32 bzone_port0_read(INT32 /*offset*/)
541 {
542 	return DrvInputs[1];
543 }
544 
redbaron_port0_read(INT32)545 static INT32 redbaron_port0_read(INT32 /*offset*/)
546 {
547 	update_analog(); // pseudo-simulate the counters according to schematics
548 
549 	INT32 analog[2] = { (y_adder-8) & 0xff, (x_adder+12) & 0xff};
550 	return analog[input_select];
551 }
552 
res_check()553 static INT32 res_check()
554 {
555 	if (DrvDips[3] & 1) {
556 		INT32 Width, Height;
557 		BurnDrvGetVisibleSize(&Width, &Height);
558 
559 		if (Height != 1080) {
560 			vector_rescale(1440, 1080);
561 			return 1;
562 		}
563 	} else {
564 		INT32 Width, Height;
565 		BurnDrvGetVisibleSize(&Width, &Height);
566 
567 		if (Height != 480) {
568 			vector_rescale(640, 480);
569 			return 1;
570 		}
571 	}
572 	return 0;
573 }
574 
DrvDoReset(INT32 clear_mem)575 static INT32 DrvDoReset(INT32 clear_mem)
576 {
577 	if (clear_mem) {
578 		memset (AllRam, 0, RamEnd - AllRam);
579 	}
580 
581 	M6502Open(0);
582 	M6502Reset();
583 	M6502Close();
584 
585 	if (redbaron) {
586 		redbaron_sound_reset();
587 	} else {
588 		bzone_sound_reset();
589 	}
590 
591 	PokeyReset();
592 
593 	BurnWatchdogReset();
594 
595 	mathbox_reset();
596 	avgdvg_reset();
597 
598 	earom_reset();
599 
600 	avgletsgo = 0;
601 	analog_data = 0;
602 	nExtraCycles = 0;
603 	input_select = 0;
604 
605 	x_target = y_target = 0x80;
606 	x_adder = y_adder = 0x80;
607 
608 	res_check();
609 
610 	return 0;
611 }
612 
MemIndex()613 static INT32 MemIndex()
614 {
615 	UINT8 *Next; Next = AllMem;
616 
617 	DrvM6502ROM		= Next; Next += 0x008000;
618 
619 	DrvPalette		= (UINT32*)Next; Next += 0x20 * 256 * sizeof(UINT32);
620 
621 	AllRam			= Next;
622 
623 	DrvM6502RAM		= Next; Next += 0x000800;
624 	DrvVectorRAM	= Next; Next += 0x001000;
625 
626 	RamEnd			= Next;
627 
628 	DrvVectorROM	= Next; Next += 0x001000; // needs to be after DrvVectorRAM(!)
629 
630 	MemEnd			= Next;
631 
632 	return 0;
633 }
634 
635 // Driver "NewFrame" support
636 // AVG and Pokey needs linear cycles for their timers, so we use this for the
637 // buffered sound customs.
638 static INT32 drv_cycles = 0;
639 
DrvM6502TotalCycles()640 static INT32 DrvM6502TotalCycles()
641 {
642 	return M6502TotalCycles() - drv_cycles;
643 }
644 
DrvM6502NewFrame()645 static void DrvM6502NewFrame()
646 {
647 	drv_cycles = M6502TotalCycles();
648 }
649 
BzoneInit()650 static INT32 BzoneInit()
651 {
652 	BurnSetRefreshRate(60.00);
653 
654 	AllMem = NULL;
655 	MemIndex();
656 	INT32 nLen = MemEnd - (UINT8 *)0;
657 	if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1;
658 	memset(AllMem, 0, nLen);
659 	MemIndex();
660 
661 	{
662 		INT32 k = 0;
663 
664 		if (strstr(BurnDrvGetTextA(DRV_NAME), "bzonec")) {
665 			if (BurnLoadRom(DrvM6502ROM  + 0x4800,  k++, 1)) return 1;
666 		}
667 
668 		if (BurnLoadRom(DrvM6502ROM  + 0x5000,  k++, 1)) return 1;
669 		if (BurnLoadRom(DrvM6502ROM  + 0x5800,  k++, 1)) return 1;
670 		if (BurnLoadRom(DrvM6502ROM  + 0x6000,  k++, 1)) return 1;
671 		if (BurnLoadRom(DrvM6502ROM  + 0x6800,  k++, 1)) return 1;
672 		if (BurnLoadRom(DrvM6502ROM  + 0x7000,  k++, 1)) return 1;
673 		if (BurnLoadRom(DrvM6502ROM  + 0x7800,  k++, 1)) return 1;
674 
675 		if (BurnLoadRom(DrvVectorROM + 0x0000,  k++, 1)) return 1;
676 		if (BurnLoadRom(DrvVectorROM + 0x0800,  k++, 1)) return 1;
677 	}
678 
679 	M6502Init(0, TYPE_M6502);
680 	M6502Open(0);
681 	M6502SetAddressMask(0x7fff);
682 	M6502MapMemory(DrvM6502RAM,		        0x0000, 0x07ff, MAP_RAM);
683 	M6502MapMemory(DrvVectorRAM,		    0x2000, 0x2fff, MAP_RAM);
684 	M6502MapMemory(DrvVectorROM,            0x3000, 0x3fff, MAP_ROM);
685 	M6502MapMemory(DrvM6502ROM + 0x4000,	0x4000, 0x7fff, MAP_ROM);
686 	M6502SetWriteHandler(bzone_write);
687 	M6502SetReadHandler(bzone_read);
688 	M6502Close();
689 
690 	earom_init(); // not used in bzone
691 
692 	BurnWatchdogInit(DrvDoReset, -1);
693 
694 	PokeyInit(12096000/8, 2, 2.40, 0);
695 	PokeySetTotalCyclesCB(M6502TotalCycles);
696 	PokeyAllPotCallback(0, bzone_port0_read);
697 
698 	bzone_sound_init(DrvM6502TotalCycles, 1512000);
699 
700 	avgdvg_init(USE_AVG_BZONE, DrvVectorRAM, 0x5000, M6502TotalCycles, 580, 400);
701 
702 	DrvDoReset(1);
703 
704 	return 0;
705 }
706 
BradleyInit()707 static INT32 BradleyInit()
708 {
709 	BurnSetRefreshRate(60.00);
710 
711 	AllMem = NULL;
712 	MemIndex();
713 	INT32 nLen = MemEnd - (UINT8 *)0;
714 	if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1;
715 	memset(AllMem, 0, nLen);
716 	MemIndex();
717 
718 	{
719 		if (BurnLoadRom(DrvM6502ROM  + 0x4000,  0, 1)) return 1;
720 		if (BurnLoadRom(DrvM6502ROM  + 0x4800,  1, 1)) return 1;
721 		if (BurnLoadRom(DrvM6502ROM  + 0x5000,  2, 1)) return 1;
722 		if (BurnLoadRom(DrvM6502ROM  + 0x5800,  3, 1)) return 1;
723 		if (BurnLoadRom(DrvM6502ROM  + 0x6000,  4, 1)) return 1;
724 		if (BurnLoadRom(DrvM6502ROM  + 0x6800,  5, 1)) return 1;
725 		if (BurnLoadRom(DrvM6502ROM  + 0x7000,  6, 1)) return 1;
726 		if (BurnLoadRom(DrvM6502ROM  + 0x7800,  7, 1)) return 1;
727 
728 		if (BurnLoadRom(DrvVectorROM + 0x0000,  8, 1)) return 1;
729 		if (BurnLoadRom(DrvVectorROM + 0x0800,  9, 1)) return 1;
730 	}
731 
732 	M6502Init(0, TYPE_M6502);
733 	M6502Open(0);
734 	M6502SetAddressMask(0x7fff);
735 	M6502MapMemory(DrvM6502RAM,		        0x0000, 0x07ff, MAP_RAM);
736 	M6502MapMemory(DrvVectorRAM,		    0x2000, 0x2fff, MAP_RAM);
737 	M6502MapMemory(DrvVectorROM,            0x3000, 0x3fff, MAP_ROM);
738 	M6502MapMemory(DrvM6502ROM + 0x4000,	0x4000, 0x7fff, MAP_ROM);
739 	M6502SetWriteHandler(bzone_write);
740 	M6502SetReadHandler(bzone_read);
741 	M6502Close();
742 
743 	earom_init(); // not used in bzone
744 
745 	BurnWatchdogInit(DrvDoReset, -1);
746 
747 	PokeyInit(12096000/8, 2, 2.40, 0);
748 	PokeySetTotalCyclesCB(M6502TotalCycles);
749 	PokeyAllPotCallback(0, bzone_port0_read);
750 
751 	bzone_sound_init(DrvM6502TotalCycles, 1512000);
752 
753 	avgdvg_init(USE_AVG_BZONE, DrvVectorRAM, 0x5000, M6502TotalCycles, 580, 400);
754 
755 	bradley = 1;
756 
757 	DrvDoReset(1);
758 
759 	return 0;
760 }
761 
RedbaronInit()762 static INT32 RedbaronInit()
763 {
764 	BurnSetRefreshRate(60.00);
765 
766 	AllMem = NULL;
767 	MemIndex();
768 	INT32 nLen = MemEnd - (UINT8 *)0;
769 	if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1;
770 	memset(AllMem, 0, nLen);
771 	MemIndex();
772 
773 	{
774 		if (redbarona) {
775 			if (BurnLoadRom(DrvM6502ROM  + 0x4800,  0, 1)) return 1;
776 			if (BurnLoadRom(DrvM6502ROM  + 0x5000,  1, 1)) return 1;
777 			if (BurnLoadRom(DrvM6502ROM  + 0x5800,  2, 1)) return 1;
778 			if (BurnLoadRom(DrvM6502ROM  + 0x6000,  3, 1)) return 1;
779 			if (BurnLoadRom(DrvM6502ROM  + 0x6800,  4, 1)) return 1;
780 			if (BurnLoadRom(DrvM6502ROM  + 0x7000,  5, 1)) return 1;
781 			if (BurnLoadRom(DrvM6502ROM  + 0x7800,  6, 1)) return 1;
782 			if (BurnLoadRom(DrvVectorROM + 0x0000,  7, 1)) return 1;
783 			if (BurnLoadRom(DrvVectorROM + 0x0800,  8, 1)) return 1;
784 		} else {
785 			if (BurnLoadRom(DrvM6502ROM  + 0x4800,  0, 1)) return 1;
786 			memcpy (DrvM6502ROM + 0x5800, DrvM6502ROM + 0x5000, 0x0800);
787 			if (BurnLoadRom(DrvM6502ROM  + 0x5000,  1, 1)) return 1;
788 			if (BurnLoadRom(DrvM6502ROM  + 0x6000,  2, 1)) return 1;
789 			if (BurnLoadRom(DrvM6502ROM  + 0x6800,  3, 1)) return 1;
790 			if (BurnLoadRom(DrvM6502ROM  + 0x7000,  4, 1)) return 1;
791 			if (BurnLoadRom(DrvM6502ROM  + 0x7800,  5, 1)) return 1;
792 			if (BurnLoadRom(DrvVectorROM + 0x0000,  6, 1)) return 1;
793 			if (BurnLoadRom(DrvVectorROM + 0x0800,  7, 1)) return 1;
794 		}
795 	}
796 
797 	M6502Init(0, TYPE_M6502);
798 	M6502Open(0);
799 	M6502SetAddressMask(0x7fff);
800 	M6502MapMemory(DrvM6502RAM,		        0x0000, 0x03ff, MAP_RAM);
801 	M6502MapMemory(DrvVectorRAM,		    0x2000, 0x2fff, MAP_RAM);
802 	M6502MapMemory(DrvVectorROM,            0x3000, 0x3fff, MAP_ROM);
803 	M6502MapMemory(DrvM6502ROM + 0x4000,	0x4000, 0x7fff, MAP_ROM);
804 	M6502SetWriteHandler(redbaron_write);
805 	M6502SetReadHandler(redbaron_read);
806 	M6502Close();
807 
808 	earom_init();
809 
810 	BurnWatchdogInit(DrvDoReset, 180); // why is this being triggered?
811 
812 	PokeyInit(12096000/8, 2, 2.40, 0);
813 	PokeySetTotalCyclesCB(M6502TotalCycles);
814 	PokeyAllPotCallback(0, redbaron_port0_read);
815 
816 	redbaron_sound_init(DrvM6502TotalCycles, 1512000);
817 
818 	avgdvg_init(USE_AVG_RBARON, DrvVectorRAM, 0x5000, M6502TotalCycles, 520, 400);
819 
820 	redbaron = 1;
821 
822 	DrvDoReset(1);
823 
824 	return 0;
825 }
826 
DrvExit()827 static INT32 DrvExit()
828 {
829 	avgdvg_exit();
830 
831 	PokeyExit();
832 	if (redbaron) {
833 		redbaron_sound_exit();
834 		redbaron = 0;
835 	} else {
836 		bzone_sound_exit();
837 	}
838 
839 	M6502Exit();
840 
841 	earom_exit();
842 
843 	BurnFree(AllMem);
844 
845 	redbarona = 0;
846 	bradley = 0;
847 
848 	return 0;
849 }
850 
DrvPaletteInit()851 static void DrvPaletteInit()
852 {
853     for (INT32 i = 0; i < 0x20; i++) // color
854 	{
855 		for (INT32 j = 0; j < 256; j++) // intensity
856 		{
857 			INT32 c = (0xff * j) / 0xff;
858 
859 			DrvPalette[i * 256 + j] = (c << 16) | (c << 8) | c; // must be 32bit palette! -dink (see vector.cpp)
860 		}
861 	}
862 }
863 
DrvDraw()864 static INT32 DrvDraw()
865 {
866 	if (DrvRecalc) {
867 		DrvPaletteInit();
868 		DrvRecalc = 0;
869 	}
870 
871 	if (res_check()) return 0; // resolution was changed
872 
873 	vector_set_clip(0x20, nScreenWidth-0x20, 0, nScreenHeight);
874 
875 	draw_vector(DrvPalette);
876 
877 	return 0;
878 }
879 
DrvFrame()880 static INT32 DrvFrame()
881 {
882 	BurnWatchdogUpdate();
883 
884 	if (DrvReset) {
885 		DrvDoReset(1);
886 	}
887 
888 	{
889 		memset (DrvInputs, 0, 5);
890 		if (redbaron) DrvInputs[2] = 0x40; // active low
891 		if (bradley) {
892 			DrvInputs[2] = 0xff; // active low
893 			DrvInputs[3] = 0x04 + 0x08 + 0x10; // ""
894 		}
895 
896 		// hack to map 8-ways to the 8 different combinations
897 		if      (DrvFakeInput[0] && DrvFakeInput[2]) { DrvJoy2[0] = 0; DrvJoy2[1] = 1; }
898 		else if (DrvFakeInput[0] && DrvFakeInput[3]) { DrvJoy2[3] = 1; DrvJoy2[2] = 0; }
899 		else if (DrvFakeInput[1] && DrvFakeInput[2]) { DrvJoy2[0] = 1; DrvJoy2[1] = 0; }
900 		else if (DrvFakeInput[1] && DrvFakeInput[3]) { DrvJoy2[3] = 0; DrvJoy2[2] = 1; }
901 		else if (DrvFakeInput[0]) { DrvJoy2[3] = 1; DrvJoy2[1] = 1; }
902 		else if (DrvFakeInput[1]) { DrvJoy2[2] = 1; DrvJoy2[0] = 1; }
903 		else if (DrvFakeInput[2]) { DrvJoy2[2] = 1; DrvJoy2[1] = 1; }
904 		else if (DrvFakeInput[3]) { DrvJoy2[3] = 1; DrvJoy2[0] = 1; }
905 
906 		for (INT32 i = 0; i < 8; i++) {
907 			DrvInputs[0] ^= (DrvJoy1[i] & 1) << i;
908 			DrvInputs[1] ^= (DrvJoy2[i] & 1) << i;
909 			DrvInputs[2] ^= (DrvJoy3[i] & 1) << i;
910 			DrvInputs[3] ^= (DrvJoy4[i] & 1) << i;
911 			DrvInputs[4] ^= (DrvJoy5[i] & 1) << i;
912 		}
913 
914 		if (redbaron) {
915 			//INT16 analog[2] = { DrvAnalogPort0, DrvAnalogPort1 };
916 			// UINT8 rc = ProcessAnalog(analog[input_select], 0, 1, 0x40, 0xc0);
917 			x_target = ProcessAnalog(DrvAnalogPort0, 0, 1, 0x50, 0xb0);
918 			y_target = ProcessAnalog(DrvAnalogPort1, 0, 1, 0x50, 0xb0);
919 			update_analog();
920 		}
921 
922 		if (bradley) {
923 			x_target = ProcessAnalog(DrvAnalogPort0, 0, 1, 0x48, 0xc8);
924 			y_target = ProcessAnalog(DrvAnalogPort1, 0, 1, 0x46, 0xc6);
925 			update_analog();
926 		}
927 	}
928 	INT32 nCyclesTotal[1] = { 1512000 / ((redbaron) ? 61 : 41) };
929 	INT32 nInterleave = 256;
930 	INT32 nCyclesDone[1] = { nExtraCycles };
931 	INT32 nSoundBufferPos = 0;
932 
933 	M6502Open(0);
934 	DrvM6502NewFrame(); // see comments above in DrvM6502NewFrame() for explanation.
935 
936 	for (INT32 i = 0; i < nInterleave; i++)
937 	{
938 		CPU_RUN(0, M6502);
939 		if ((i % 64) == 63 && (DrvDips[2] & 0x10)) {
940 			M6502SetIRQLine(0x20, CPU_IRQSTATUS_AUTO);
941 		}
942 
943 		// Render Sound Segment
944 		if (pBurnSoundOut) {
945 			INT32 nSegmentLength = nBurnSoundLen / nInterleave;
946 			INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
947 			pokey_update(pSoundBuf, nSegmentLength);
948 			nSoundBufferPos += nSegmentLength;
949 		}
950 	}
951 
952 	nExtraCycles = nCyclesDone - nCyclesTotal;
953 
954 	// Make sure the buffer is entirely filled.
955 	if (pBurnSoundOut) {
956 		INT32 nSegmentLength = nBurnSoundLen - nSoundBufferPos;
957 		INT16* pSoundBuf = pBurnSoundOut + (nSoundBufferPos << 1);
958 		if (nSegmentLength) {
959 			pokey_update(pSoundBuf, nSegmentLength);
960 		}
961 
962 		if (redbaron) {
963 			redbaron_sound_update(pBurnSoundOut, nBurnSoundLen);
964 		} else {
965 			bzone_sound_update(pBurnSoundOut, nBurnSoundLen);
966 			if (!bzone_sound_enable)
967 				BurnSoundClear();
968 		}
969 		BurnSoundDCFilter();
970 	}
971 
972 	if (pBurnDraw) {
973 		BurnDrvRedraw();
974 	}
975 
976 	M6502Close();
977 
978 	return 0;
979 }
980 
DrvScan(INT32 nAction,INT32 * pnMin)981 static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
982 {
983 	struct BurnArea ba;
984 
985 	if (pnMin) {
986 		*pnMin = 0x029722;
987 	}
988 
989 	if (nAction & ACB_VOLATILE) {
990 		memset(&ba, 0, sizeof(ba));
991 		ba.Data	  = AllRam;
992 		ba.nLen	  = RamEnd - AllRam;
993 		ba.szName = "All Ram";
994 		BurnAcb(&ba);
995 
996 		M6502Scan(nAction);
997 
998 		mathbox_scan(nAction, pnMin);
999 		avgdvg_scan(nAction, pnMin);
1000 		BurnWatchdogScan(nAction);
1001 
1002 		pokey_scan(nAction, pnMin);
1003 		redbaron_sound_scan(nAction, pnMin);
1004 		bzone_sound_scan(nAction, pnMin);
1005 
1006 		SCAN_VAR(nExtraCycles);
1007 		SCAN_VAR(avgletsgo);
1008 		SCAN_VAR(analog_data);
1009 		SCAN_VAR(input_select);
1010 		SCAN_VAR(x_target);
1011 		SCAN_VAR(y_target);
1012 		SCAN_VAR(x_adder);
1013 		SCAN_VAR(y_adder);
1014 	}
1015 
1016 	earom_scan(nAction, pnMin); // here.
1017 
1018 	return 0;
1019 }
1020 
1021 
1022 // Battle Zone (rev 2)
1023 
1024 static struct BurnRomInfo bzoneRomDesc[] = {
1025 	{ "036414-02.e1",	0x0800, 0x13de36d5, 1 | BRF_PRG | BRF_ESS }, //  0 M6502 Code
1026 	{ "036413-01.h1",	0x0800, 0x5d9d9111, 1 | BRF_PRG | BRF_ESS }, //  1
1027 	{ "036412-01.j1",	0x0800, 0xab55cbd2, 1 | BRF_PRG | BRF_ESS }, //  2
1028 	{ "036411-01.k1",	0x0800, 0xad281297, 1 | BRF_PRG | BRF_ESS }, //  3
1029 	{ "036410-01.lm1",	0x0800, 0x0b7bfaa4, 1 | BRF_PRG | BRF_ESS }, //  4
1030 	{ "036409-01.n1",	0x0800, 0x1e14e919, 1 | BRF_PRG | BRF_ESS }, //  5
1031 
1032 	{ "036422-01.bc3",	0x0800, 0x7414177b, 2 | BRF_PRG | BRF_ESS }, //  6 Vector Data
1033 	{ "036421-01.a3",	0x0800, 0x8ea8f939, 2 | BRF_PRG | BRF_ESS }, //  7
1034 
1035 	{ "036408-01.k7",	0x0100, 0x5903af03, 3 | BRF_GRA },           //  8 AVG PROM
1036 
1037 	{ "036174-01.b1",	0x0020, 0x8b04f921, 4 | BRF_GRA },           //  9 Mathbox PROM
1038 
1039 	{ "036175-01.m1",	0x0100, 0x2af82e87, 5 | BRF_GRA },           // 10 user3
1040 	{ "036176-01.l1",	0x0100, 0xb31f6e24, 5 | BRF_GRA },           // 11
1041 	{ "036177-01.k1",	0x0100, 0x8119b847, 5 | BRF_GRA },           // 12
1042 	{ "036178-01.j1",	0x0100, 0x09f5a4d5, 5 | BRF_GRA },           // 13
1043 	{ "036179-01.h1",	0x0100, 0x823b61ae, 5 | BRF_GRA },           // 14
1044 	{ "036180-01.f1",	0x0100, 0x276eadd5, 5 | BRF_GRA },           // 15
1045 };
1046 
1047 STD_ROM_PICK(bzone)
1048 STD_ROM_FN(bzone)
1049 
1050 struct BurnDriver BurnDrvBzone = {
1051 	"bzone", NULL, NULL, NULL, "1980",
1052 	"Battle Zone (rev 2)\0", "GFX/Sound Issues", "Atari", "Miscellaneous",
1053 	NULL, NULL, NULL, NULL,
1054 	BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0,
1055 	NULL, bzoneRomInfo, bzoneRomName, NULL, NULL, NULL, NULL, BzoneInputInfo, BzoneDIPInfo,
1056 	BzoneInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x2000,
1057 	640, 480, 4, 3
1058 };
1059 
1060 
1061 // Battle Zone (rev 1)
1062 
1063 static struct BurnRomInfo bzoneaRomDesc[] = {
1064 	{ "036414-01.e1",	0x0800, 0xefbc3fa0, 1 | BRF_PRG | BRF_ESS }, //  0 M6502 Code
1065 	{ "036413-01.h1",	0x0800, 0x5d9d9111, 1 | BRF_PRG | BRF_ESS }, //  1
1066 	{ "036412-01.j1",	0x0800, 0xab55cbd2, 1 | BRF_PRG | BRF_ESS }, //  2
1067 	{ "036411-01.k1",	0x0800, 0xad281297, 1 | BRF_PRG | BRF_ESS }, //  3
1068 	{ "036410-01.lm1",	0x0800, 0x0b7bfaa4, 1 | BRF_PRG | BRF_ESS }, //  4
1069 	{ "036409-01.n1",	0x0800, 0x1e14e919, 1 | BRF_PRG | BRF_ESS }, //  5
1070 
1071 	{ "036422-01.bc3",	0x0800, 0x7414177b, 1 | BRF_PRG | BRF_ESS }, //  6 Vector Data
1072 	{ "036421-01.a3",	0x0800, 0x8ea8f939, 1 | BRF_PRG | BRF_ESS }, //  7
1073 
1074 	{ "036408-01.k7",	0x0100, 0x5903af03, 2 | BRF_GRA },           //  8 AVG PROM
1075 
1076 	{ "036174-01.b1",	0x0020, 0x8b04f921, 3 | BRF_GRA },           //  9 Mathbox PROM
1077 
1078 	{ "036175-01.m1",	0x0100, 0x2af82e87, 4 | BRF_GRA },           // 10 user3
1079 	{ "036176-01.l1",	0x0100, 0xb31f6e24, 4 | BRF_GRA },           // 11
1080 	{ "036177-01.k1",	0x0100, 0x8119b847, 4 | BRF_GRA },           // 12
1081 	{ "036178-01.j1",	0x0100, 0x09f5a4d5, 4 | BRF_GRA },           // 13
1082 	{ "036179-01.h1",	0x0100, 0x823b61ae, 4 | BRF_GRA },           // 14
1083 	{ "036180-01.f1",	0x0100, 0x276eadd5, 4 | BRF_GRA },           // 15
1084 };
1085 
1086 STD_ROM_PICK(bzonea)
1087 STD_ROM_FN(bzonea)
1088 
1089 struct BurnDriver BurnDrvBzonea = {
1090 	"bzonea", "bzone", NULL, NULL, "1980",
1091 	"Battle Zone (rev 1)\0", "GFX/Sound Issues", "Atari", "Miscellaneous",
1092 	NULL, NULL, NULL, NULL,
1093 	BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0,
1094 	NULL, bzoneaRomInfo, bzoneaRomName, NULL, NULL, NULL, NULL, BzoneInputInfo, BzoneDIPInfo,
1095 	BzoneInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x2000,
1096 	640, 480, 4, 3
1097 };
1098 
1099 
1100 // Battle Zone (cocktail)
1101 
1102 static struct BurnRomInfo bzonecRomDesc[] = {
1103 	{ "bz1g4800",		0x0800, 0xe228dd64, 1 | BRF_PRG | BRF_ESS }, //  0 M6502 Code
1104 	{ "bz1f5000",		0x0800, 0xdddfac9a, 1 | BRF_PRG | BRF_ESS }, //  1
1105 	{ "bz1e5800",		0x0800, 0x7e00e823, 1 | BRF_PRG | BRF_ESS }, //  2
1106 	{ "bz1d6000",		0x0800, 0xc0f8c068, 1 | BRF_PRG | BRF_ESS }, //  3
1107 	{ "bz1c6800",		0x0800, 0x5adc64bd, 1 | BRF_PRG | BRF_ESS }, //  4
1108 	{ "bz1b7000",		0x0800, 0xed8a860e, 1 | BRF_PRG | BRF_ESS }, //  5
1109 	{ "bz1a7800",		0x0800, 0x04babf45, 1 | BRF_PRG | BRF_ESS }, //  6
1110 
1111 	{ "036422-01.bc3",	0x0800, 0x7414177b, 1 | BRF_PRG | BRF_ESS }, //  7 Vector Data
1112 	{ "bz3b3800",		0x0800, 0x76cf57f6, 1 | BRF_PRG | BRF_ESS }, //  8
1113 
1114 	{ "036408-01.k7",	0x0100, 0x5903af03, 2 | BRF_GRA },           //  9 AVG PROM
1115 
1116 	{ "036174-01.b1",	0x0020, 0x8b04f921, 3 | BRF_GRA },           // 10 Mathbox PROM
1117 
1118 	{ "036175-01.m1",	0x0100, 0x2af82e87, 4 | BRF_GRA },           // 11 user3
1119 	{ "036176-01.l1",	0x0100, 0xb31f6e24, 4 | BRF_GRA },           // 12
1120 	{ "036177-01.k1",	0x0100, 0x8119b847, 4 | BRF_GRA },           // 13
1121 	{ "036178-01.j1",	0x0100, 0x09f5a4d5, 4 | BRF_GRA },           // 14
1122 	{ "036179-01.h1",	0x0100, 0x823b61ae, 4 | BRF_GRA },           // 15
1123 	{ "036180-01.f1",	0x0100, 0x276eadd5, 4 | BRF_GRA },           // 16
1124 };
1125 
1126 STD_ROM_PICK(bzonec)
1127 STD_ROM_FN(bzonec)
1128 
1129 struct BurnDriver BurnDrvBzonec = {
1130 	"bzonec", "bzone", NULL, NULL, "1980",
1131 	"Battle Zone (cocktail)\0", "GFX/Sound Issues", "Atari", "Miscellaneous",
1132 	NULL, NULL, NULL, NULL,
1133 	BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0,
1134 	NULL, bzonecRomInfo, bzonecRomName, NULL, NULL, NULL, NULL, BzoneInputInfo, BzoneDIPInfo,
1135 	BzoneInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x2000,
1136 	640, 480, 4, 3
1137 };
1138 
1139 
1140 // Bradley Trainer
1141 
1142 static struct BurnRomInfo bradleyRomDesc[] = {
1143 	{ "btc1.bin",		0x0800, 0x0bb8e049, 1 | BRF_PRG | BRF_ESS }, //  0 M6502 Code
1144 	{ "btd1.bin",		0x0800, 0x9e0566d4, 1 | BRF_PRG | BRF_ESS }, //  1
1145 	{ "bte1.bin",		0x0800, 0x64ee6a42, 1 | BRF_PRG | BRF_ESS }, //  2
1146 	{ "bth1.bin",		0x0800, 0xbaab67be, 1 | BRF_PRG | BRF_ESS }, //  3
1147 	{ "btj1.bin",		0x0800, 0x036adde4, 1 | BRF_PRG | BRF_ESS }, //  4
1148 	{ "btk1.bin",		0x0800, 0xf5c2904e, 1 | BRF_PRG | BRF_ESS }, //  5
1149 	{ "btlm.bin",		0x0800, 0x7d0313bf, 1 | BRF_PRG | BRF_ESS }, //  6
1150 	{ "btn1.bin",		0x0800, 0x182c8c64, 1 | BRF_PRG | BRF_ESS }, //  7
1151 
1152 	{ "btb3.bin",		0x0800, 0x88206304, 1 | BRF_PRG | BRF_ESS }, //  8 Vector Data
1153 	{ "bta3.bin",		0x0800, 0xd669d796, 1 | BRF_PRG | BRF_ESS }, //  9
1154 
1155 	{ "036408-01.k7",	0x0100, 0x5903af03, 2 | BRF_GRA },           // 10 AVG PROM
1156 
1157 	{ "036174-01.b1",	0x0020, 0x8b04f921, 3 | BRF_GRA },           // 11 Mathbox PROM
1158 
1159 	{ "036175-01.m1",	0x0100, 0x2af82e87, 4 | BRF_GRA },           // 12 user3
1160 	{ "036176-01.l1",	0x0100, 0xb31f6e24, 4 | BRF_GRA },           // 13
1161 	{ "036177-01.k1",	0x0100, 0x8119b847, 4 | BRF_GRA },           // 14
1162 	{ "036178-01.j1",	0x0100, 0x09f5a4d5, 4 | BRF_GRA },           // 15
1163 	{ "036179-01.h1",	0x0100, 0x823b61ae, 4 | BRF_GRA },           // 16
1164 	{ "036180-01.f1",	0x0100, 0x276eadd5, 4 | BRF_GRA },           // 17
1165 };
1166 
1167 STD_ROM_PICK(bradley)
1168 STD_ROM_FN(bradley)
1169 
1170 struct BurnDriver BurnDrvBradley = {
1171 	"bradley", NULL, NULL, NULL, "1980",
1172 	"Bradley Trainer\0", "GFX/Sound Issues", "Atari", "Miscellaneous",
1173 	NULL, NULL, NULL, NULL,
1174 	BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0,
1175 	NULL, bradleyRomInfo, bradleyRomName, NULL, NULL, NULL, NULL, BradleyInputInfo, BradleyDIPInfo,
1176 	BradleyInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x2000,
1177 	640, 480, 4, 3
1178 };
1179 
1180 
1181 // Red Baron (Revised Hardware)
1182 
1183 static struct BurnRomInfo redbaronRomDesc[] = {
1184 	{ "037587-01.fh1",	0x1000, 0x60f23983, 1 | BRF_PRG | BRF_ESS }, //  0 M6502 Code
1185 	{ "037000-01.e1",	0x0800, 0x69bed808, 1 | BRF_PRG | BRF_ESS }, //  1
1186 	{ "036998-01.j1",	0x0800, 0xd1104dd7, 1 | BRF_PRG | BRF_ESS }, //  2
1187 	{ "036997-01.k1",	0x0800, 0x7434acb4, 1 | BRF_PRG | BRF_ESS }, //  3
1188 	{ "036996-01.lm1",	0x0800, 0xc0e7589e, 1 | BRF_PRG | BRF_ESS }, //  4
1189 	{ "036995-01.n1",	0x0800, 0xad81d1da, 1 | BRF_PRG | BRF_ESS }, //  5
1190 
1191 	{ "037006-01.bc3",	0x0800, 0x9fcffea0, 1 | BRF_PRG | BRF_ESS }, //  6 Vector Data
1192 	{ "037007-01.a3",	0x0800, 0x60250ede, 1 | BRF_PRG | BRF_ESS }, //  7
1193 
1194 	{ "036408-01.k7",	0x0100, 0x5903af03, 2 | BRF_GRA },           //  8 AVG PROM
1195 
1196 	{ "036174-01.a1",	0x0020, 0x8b04f921, 3 | BRF_GRA },           //  9 user2
1197 
1198 	{ "036175-01.e1",	0x0100, 0x2af82e87, 4 | BRF_GRA },           // 10 Mathbox PROM
1199 	{ "036176-01.f1",	0x0100, 0xb31f6e24, 4 | BRF_GRA },           // 11
1200 	{ "036177-01.h1",	0x0100, 0x8119b847, 4 | BRF_GRA },           // 12
1201 	{ "036178-01.j1",	0x0100, 0x09f5a4d5, 4 | BRF_GRA },           // 13
1202 	{ "036179-01.k1",	0x0100, 0x823b61ae, 4 | BRF_GRA },           // 14
1203 	{ "036180-01.l1",	0x0100, 0x276eadd5, 4 | BRF_GRA },           // 15
1204 
1205 	{ "036464-01.a5",	0x0020, 0x42875b18, 5 | BRF_GRA },           // 16 prom
1206 };
1207 
1208 STD_ROM_PICK(redbaron)
1209 STD_ROM_FN(redbaron)
1210 
1211 struct BurnDriver BurnDrvRedbaron = {
1212 	"redbaron", NULL, NULL, NULL, "1980",
1213 	"Red Baron (Revised Hardware)\0", NULL, "Atari", "Miscellaneous",
1214 	NULL, NULL, NULL, NULL,
1215 	BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0,
1216 	NULL, redbaronRomInfo, redbaronRomName, NULL, NULL, NULL, NULL, RedbaronInputInfo, RedbaronDIPInfo,
1217 	RedbaronInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x2000,
1218 	640, 480, 4, 3
1219 };
1220 
RedbaronaInit()1221 static INT32 RedbaronaInit()
1222 {
1223 	redbarona = 1;
1224 
1225 	return RedbaronInit();
1226 }
1227 
1228 // Red Baron
1229 
1230 static struct BurnRomInfo redbaronaRomDesc[] = {
1231 	{ "037001-01e.e1",	0x0800, 0xb9486a6a, 1 | BRF_PRG | BRF_ESS }, //  0 M6502 Code
1232 	{ "037000-01e.fh1",	0x0800, 0x69bed808, 1 | BRF_PRG | BRF_ESS }, //  1
1233 	{ "036999-01e.j1",	0x0800, 0x48d49819, 1 | BRF_PRG | BRF_ESS }, //  2
1234 	{ "036998-01e.k1",	0x0800, 0xd1104dd7, 1 | BRF_PRG | BRF_ESS }, //  3
1235 	{ "036997-01e.lm1",	0x0800, 0x7434acb4, 1 | BRF_PRG | BRF_ESS }, //  4
1236 	{ "036996-01e.n1",	0x0800, 0xc0e7589e, 1 | BRF_PRG | BRF_ESS }, //  5
1237 	{ "036995-01e.p1",	0x0800, 0xad81d1da, 1 | BRF_PRG | BRF_ESS }, //  6
1238 
1239 	{ "037006-01e.bc3",	0x0800, 0x9fcffea0, 1 | BRF_PRG | BRF_ESS }, //  7 Vector Data
1240 	{ "037007-01e.a3",	0x0800, 0x60250ede, 1 | BRF_PRG | BRF_ESS }, //  8
1241 
1242 	{ "036408-01.k7",	0x0100, 0x5903af03, 2 | BRF_GRA },           //  9 AVG PROM
1243 
1244 	{ "036174-01.a1",	0x0020, 0x8b04f921, 3 | BRF_GRA },           // 10 Mathbox PROM
1245 
1246 	{ "036175-01.e1",	0x0100, 0x2af82e87, 4 | BRF_GRA },           // 11 user3
1247 	{ "036176-01.f1",	0x0100, 0xb31f6e24, 4 | BRF_GRA },           // 12
1248 	{ "036177-01.h1",	0x0100, 0x8119b847, 4 | BRF_GRA },           // 13
1249 	{ "036178-01.j1",	0x0100, 0x09f5a4d5, 4 | BRF_GRA },           // 14
1250 	{ "036179-01.k1",	0x0100, 0x823b61ae, 4 | BRF_GRA },           // 15
1251 	{ "036180-01.l1",	0x0100, 0x276eadd5, 4 | BRF_GRA },           // 16
1252 
1253 	{ "036464-01.a5",	0x0020, 0x42875b18, 5 | BRF_GRA },           // 17 Timing PROM
1254 };
1255 
1256 STD_ROM_PICK(redbarona)
1257 STD_ROM_FN(redbarona)
1258 
1259 struct BurnDriver BurnDrvRedbarona = {
1260 	"redbarona", "redbaron", NULL, NULL, "1980",
1261 	"Red Baron\0", NULL, "Atari", "Miscellaneous",
1262 	NULL, NULL, NULL, NULL,
1263 	BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_PRE90S, GBF_SHOOT, 0,
1264 	NULL, redbaronaRomInfo, redbaronaRomName, NULL, NULL, NULL, NULL, RedbaronInputInfo, RedbaronDIPInfo,
1265 	RedbaronaInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x2000,
1266 	640, 480, 4, 3
1267 };
1268