1 // FB Alpha Renegade driver module
2 // Based on MAME driver by Phil Stroffolino, Carlos A. Lozano, Rob Rosenbrock
3 
4 #include "tiles_generic.h"
5 #include "m6502_intf.h"
6 #include "m6805_intf.h"
7 #include "m6809_intf.h"
8 #include "burn_ym3526.h"
9 #include "msm5205.h"
10 
11 static UINT8 DrvInputPort0[8] = {0, 0, 0, 0, 0, 0, 0, 0};
12 static UINT8 DrvInputPort1[8] = {0, 0, 0, 0, 0, 0, 0, 0};
13 static UINT8 DrvInputPort2[8] = {0, 0, 0, 0, 0, 0, 0, 0};
14 static UINT8 DrvDip[2]        = {0, 0};
15 static UINT8 DrvInput[3]      = {0x00, 0x00, 0x00};
16 static UINT8 DrvReset         = 0;
17 
18 static UINT8 *Mem                 = NULL;
19 static UINT8 *MemEnd              = NULL;
20 static UINT8 *RamStart            = NULL;
21 static UINT8 *RamEnd              = NULL;
22 static UINT8 *DrvM6502Rom         = NULL;
23 static UINT8 *DrvM6809Rom         = NULL;
24 static UINT8 *DrvM68705Rom        = NULL;
25 static UINT8 *DrvM68705Ram        = NULL;
26 static UINT8 *DrvADPCMRom         = NULL;
27 static UINT8 *DrvM6502Ram         = NULL;
28 static UINT8 *DrvM6809Ram         = NULL;
29 static UINT8 *DrvVideoRam1        = NULL;
30 static UINT8 *DrvVideoRam2        = NULL;
31 static UINT8 *DrvSpriteRam        = NULL;
32 static UINT8 *DrvPaletteRam1      = NULL;
33 static UINT8 *DrvPaletteRam2      = NULL;
34 static UINT8 *DrvChars            = NULL;
35 static UINT8 *DrvTiles            = NULL;
36 static UINT8 *DrvSprites          = NULL;
37 static UINT8 *DrvTempRom          = NULL;
38 static UINT32 *DrvPalette         = NULL;
39 
40 static UINT8 DrvRomBank;
41 static UINT8 DrvVBlank;
42 static UINT8 DrvScrollX[2];
43 static UINT8 DrvSoundLatch;
44 static UINT8 DrvADPCMPlaying = 0;
45 static UINT32 DrvADPCMPos = 0;
46 static UINT32 DrvADPCMEnd = 0;
47 
48 // MCU Simulation Variables
49 #define MCU_TYPE_NONE		0
50 #define MCU_TYPE_MCU		1
51 
52 static INT32 DisableMCUEmulation = 0;
53 
54 // MCU Emulation Variables
55 static INT32 MCUFromMain;
56 static INT32 MCUFromMcu;
57 static INT32 MCUMainSent;
58 static INT32 MCUMcuSent;
59 static UINT8 MCUDdrA;
60 static UINT8 MCUDdrB;
61 static UINT8 MCUDdrC;
62 static UINT8 MCUPortAOut;
63 static UINT8 MCUPortBOut;
64 static UINT8 MCUPortCOut;
65 static UINT8 MCUPortAIn;
66 static UINT8 MCUPortBIn;
67 static UINT8 MCUPortCIn;
68 
69 static struct BurnInputInfo DrvInputList[] =
70 {
71 	{"P1 Coin"           , BIT_DIGITAL  , DrvInputPort1 + 6, "p1 coin"   },
72 	{"P1 Start"          , BIT_DIGITAL  , DrvInputPort0 + 6, "p1 start"  },
73 	{"P1 Up"             , BIT_DIGITAL  , DrvInputPort0 + 2, "p1 up"     },
74 	{"P1 Down"           , BIT_DIGITAL  , DrvInputPort0 + 3, "p1 down"   },
75 	{"P1 Left"           , BIT_DIGITAL  , DrvInputPort0 + 1, "p1 left"   },
76 	{"P1 Right"          , BIT_DIGITAL  , DrvInputPort0 + 0, "p1 right"  },
77 	{"P1 Fire 1"         , BIT_DIGITAL  , DrvInputPort0 + 4, "p1 fire 1" },
78 	{"P1 Fire 2"         , BIT_DIGITAL  , DrvInputPort0 + 5, "p1 fire 2" },
79 	{"P1 Fire 3"         , BIT_DIGITAL  , DrvInputPort2 + 2, "p1 fire 3" },
80 
81 	{"P2 Coin"           , BIT_DIGITAL  , DrvInputPort1 + 7, "p2 coin"   },
82 	{"P2 Start"          , BIT_DIGITAL  , DrvInputPort0 + 7, "p2 start"  },
83 	{"P2 Up"             , BIT_DIGITAL  , DrvInputPort1 + 2, "p2 up"     },
84 	{"P2 Down"           , BIT_DIGITAL  , DrvInputPort1 + 3, "p2 down"   },
85 	{"P2 Left"           , BIT_DIGITAL  , DrvInputPort1 + 1, "p2 left"   },
86 	{"P2 Right"          , BIT_DIGITAL  , DrvInputPort1 + 0, "p2 right"  },
87 	{"P2 Fire 1"         , BIT_DIGITAL  , DrvInputPort1 + 4, "p2 fire 1" },
88 	{"P2 Fire 2"         , BIT_DIGITAL  , DrvInputPort1 + 5, "p2 fire 2" },
89 	{"P2 Fire 3"         , BIT_DIGITAL  , DrvInputPort2 + 3, "p2 fire 3" },
90 
91 	{"Reset"             , BIT_DIGITAL  , &DrvReset        , "reset"     },
92 	{"Service"           , BIT_DIGITAL  , DrvInputPort2 + 7, "service"   },
93 	{"Dip 1"             , BIT_DIPSWITCH, DrvDip + 0       , "dip"       },
94 	{"Dip 2"             , BIT_DIPSWITCH, DrvDip + 1       , "dip"       },
95 };
96 
97 
STDINPUTINFO(Drv)98 STDINPUTINFO(Drv)
99 
100 static inline void DrvMakeInputs()
101 {
102 	// Reset Inputs
103 	DrvInput[0] = DrvInput[1] = 0xff;
104 	DrvInput[2] = 0x9c;
105 
106 	// Compile Digital Inputs
107 	for (INT32 i = 0; i < 8; i++) {
108 		DrvInput[0] -= (DrvInputPort0[i] & 1) << i;
109 		DrvInput[1] -= (DrvInputPort1[i] & 1) << i;
110 		DrvInput[2] -= (DrvInputPort2[i] & 1) << i;
111 	}
112 }
113 
114 static struct BurnDIPInfo DrvDIPList[]=
115 {
116 	// Default Values
117 	{0x14, 0xff, 0xff, 0xbf, NULL                     },
118 	{0x15, 0xff, 0xff, 0x03, NULL                     },
119 
120 	// Dip 1
121 	{0   , 0xfe, 0   , 4   , "Coin A"                 },
122 	{0x14, 0x01, 0x03, 0x00, "2 Coins 1 Play"         },
123 	{0x14, 0x01, 0x03, 0x03, "1 Coin  1 Play"         },
124 	{0x14, 0x01, 0x03, 0x02, "1 Coin  2 Plays"        },
125 	{0x14, 0x01, 0x03, 0x01, "1 Coin  3 Plays"        },
126 
127 	{0   , 0xfe, 0   , 4   , "Coin B"                 },
128 	{0x14, 0x01, 0x0c, 0x00, "2 Coins 1 Play"         },
129 	{0x14, 0x01, 0x0c, 0x0c, "1 Coin  1 Play"         },
130 	{0x14, 0x01, 0x0c, 0x08, "1 Coin  2 Plays"        },
131 	{0x14, 0x01, 0x0c, 0x04, "1 Coin  3 Plays"        },
132 
133 	{0   , 0xfe, 0   , 2   , "Lives"                  },
134 	{0x14, 0x01, 0x10, 0x10, "1"                      },
135 	{0x14, 0x01, 0x10, 0x00, "2"                      },
136 
137 	{0   , 0xfe, 0   , 2   , "Bonus"                  },
138 	{0x14, 0x01, 0x20, 0x20, "30k"                    },
139 	{0x14, 0x01, 0x20, 0x00, "None"                   },
140 
141 	{0   , 0xfe, 0   , 2   , "Cabinet"                },
142 	{0x14, 0x01, 0x40, 0x00, "Upright"                },
143 	{0x14, 0x01, 0x40, 0x40, "Cocktail"               },
144 
145 	{0   , 0xfe, 0   , 2   , "Flip Screen"            },
146 	{0x14, 0x01, 0x80, 0x80, "Off"                    },
147 	{0x14, 0x01, 0x80, 0x00, "On"                     },
148 
149 	// Dip 2
150 	{0   , 0xfe, 0   , 4   , "Difficulty"             },
151 	{0x15, 0x01, 0x03, 0x02, "Easy"                   },
152 	{0x15, 0x01, 0x03, 0x03, "Normal"                 },
153 	{0x15, 0x01, 0x03, 0x01, "Hard"                   },
154 	{0x15, 0x01, 0x03, 0x00, "Very Hard"              },
155 };
156 
157 STDDIPINFO(Drv)
158 
159 static struct BurnRomInfo DrvRomDesc[] = {
160 	{ "nb-5.ic51",     0x08000, 0xba683ddf, BRF_ESS | BRF_PRG }, //  0	M6502 Program Code
161 	{ "na-5.ic52",     0x08000, 0xde7e7df4, BRF_ESS | BRF_PRG }, //	 1
162 
163 	{ "n0-5.ic13",     0x08000, 0x3587de3b, BRF_ESS | BRF_PRG }, //  2	M6809 Program Code
164 
165 	{ "nc-5.bin",      0x08000, 0x9adfaa5d, BRF_GRA },	     //  3	Characters
166 
167 	{ "n1-5.ic1",      0x08000, 0x4a9f47f3, BRF_GRA },	     //  4	Tiles
168 	{ "n6-5.ic28",     0x08000, 0xd62a0aa8, BRF_GRA },	     //  5
169 	{ "n7-5.ic27",     0x08000, 0x7ca5a532, BRF_GRA },	     //  6
170 	{ "n2-5.ic14",     0x08000, 0x8d2e7982, BRF_GRA },	     //  7
171 	{ "n8-5.ic26",     0x08000, 0x0dba31d3, BRF_GRA },	     //  8
172 	{ "n9-5.ic25",     0x08000, 0x5b621b6a, BRF_GRA },	     //  9
173 
174 	{ "nh-5.bin",      0x08000, 0xdcd7857c, BRF_GRA },	     //  10	Sprites
175 	{ "nd-5.bin",      0x08000, 0x2de1717c, BRF_GRA },	     //  11
176 	{ "nj-5.bin",      0x08000, 0x0f96a18e, BRF_GRA },	     //  12
177 	{ "nn-5.bin",      0x08000, 0x1bf15787, BRF_GRA },	     //  13
178 	{ "ne-5.bin",      0x08000, 0x924c7388, BRF_GRA },	     //  14
179 	{ "nk-5.bin",      0x08000, 0x69499a94, BRF_GRA },	     //  15
180 	{ "ni-5.bin",      0x08000, 0x6f597ed2, BRF_GRA },	     //  16
181 	{ "nf-5.bin",      0x08000, 0x0efc8d45, BRF_GRA },	     //  17
182 	{ "nl-5.bin",      0x08000, 0x14778336, BRF_GRA },	     //  18
183 	{ "no-5.bin",      0x08000, 0x147dd23b, BRF_GRA },	     //  19
184 	{ "ng-5.bin",      0x08000, 0xa8ee3720, BRF_GRA },	     //  20
185 	{ "nm-5.bin",      0x08000, 0xc100258e, BRF_GRA },	     //  21
186 
187 	{ "n3-5.ic33",     0x08000, 0x78fd6190, BRF_GRA },	     //  22	ADPCM
188 	{ "n4-5.ic32",     0x08000, 0x6557564c, BRF_GRA },	     //  23
189 	{ "n5-5.ic31",     0x08000, 0x7ee43a3c, BRF_GRA },	     //  24
190 
191 	{ "nz-5.ic97",     0x00800, 0x32e47560, BRF_ESS | BRF_PRG },	// 25 MCU
192 };
193 
194 STD_ROM_PICK(Drv)
195 STD_ROM_FN(Drv)
196 
197 static struct BurnRomInfo DrvjRomDesc[] = {
198 	{ "nb-01.bin",     0x08000, 0x93fcfdf5, BRF_ESS | BRF_PRG }, //  0	M6502 Program Code
199 	{ "ta18-11.bin",   0x08000, 0xf240f5cd, BRF_ESS | BRF_PRG }, //	 1
200 
201 	{ "n0-5.bin",      0x08000, 0x3587de3b, BRF_ESS | BRF_PRG }, //  2	M6809 Program Code
202 
203 	{ "ta18-25.bin",   0x08000, 0x9bd2bea3, BRF_GRA },	     //  3	Characters
204 
205 	{ "ta18-01.bin",   0x08000, 0xdaf15024, BRF_GRA },	     //  4	Tiles
206 	{ "ta18-06.bin",   0x08000, 0x1f59a248, BRF_GRA },	     //  5
207 	{ "n7-5.bin",      0x08000, 0x7ca5a532, BRF_GRA },	     //  6
208 	{ "ta18-02.bin",   0x08000, 0x994c0021, BRF_GRA },	     //  7
209 	{ "ta18-04.bin",   0x08000, 0x55b9e8aa, BRF_GRA },	     //  8
210 	{ "ta18-03.bin",   0x08000, 0x0475c99a, BRF_GRA },	     //  9
211 
212 	{ "ta18-20.bin",   0x08000, 0xc7d54139, BRF_GRA },	     //  10	Sprites
213 	{ "ta18-24.bin",   0x08000, 0x84677d45, BRF_GRA },	     //  11
214 	{ "ta18-18.bin",   0x08000, 0x1c770853, BRF_GRA },	     //  12
215 	{ "ta18-14.bin",   0x08000, 0xaf656017, BRF_GRA },	     //  13
216 	{ "ta18-23.bin",   0x08000, 0x3fd19cf7, BRF_GRA },	     //  14
217 	{ "ta18-17.bin",   0x08000, 0x74c64c6e, BRF_GRA },	     //  15
218 	{ "ta18-19.bin",   0x08000, 0xc8795fd7, BRF_GRA },	     //  16
219 	{ "ta18-22.bin",   0x08000, 0xdf3a2ff5, BRF_GRA },	     //  17
220 	{ "ta18-16.bin",   0x08000, 0x7244bad0, BRF_GRA },	     //  18
221 	{ "ta18-13.bin",   0x08000, 0xb6b14d46, BRF_GRA },	     //  19
222 	{ "ta18-21.bin",   0x08000, 0xc95e009b, BRF_GRA },	     //  20
223 	{ "ta18-15.bin",   0x08000, 0xa5d61d01, BRF_GRA },	     //  21
224 
225 	{ "ta18-09.bin",   0x08000, 0x07ed4705, BRF_GRA },	     //  22	ADPCM
226 	{ "ta18-08.bin",   0x08000, 0xc9312613, BRF_GRA },	     //  23
227 	{ "ta18-07.bin",   0x08000, 0x02e3f3ed, BRF_GRA },	     //  24
228 
229 	{ "nz-0.bin",      0x00800, 0x98a39880, BRF_ESS | BRF_PRG },	// 25 MCU
230 };
231 
232 STD_ROM_PICK(Drvj)
233 STD_ROM_FN(Drvj)
234 
235 static struct BurnRomInfo DrvbRomDesc[] = {
236 	{ "ta18-10.bin",   0x08000, 0xa90cf44a, BRF_ESS | BRF_PRG }, //  0	M6502 Program Code
237 	{ "ta18-11.bin",   0x08000, 0xf240f5cd, BRF_ESS | BRF_PRG }, //	 1
238 
239 	{ "n0-5.bin",      0x08000, 0x3587de3b, BRF_ESS | BRF_PRG }, //  2	M6809 Program Code
240 
241 	{ "ta18-25.bin",   0x08000, 0x9bd2bea3, BRF_GRA },	     //  3	Characters
242 
243 	{ "ta18-01.bin",   0x08000, 0xdaf15024, BRF_GRA },	     //  4	Tiles
244 	{ "ta18-06.bin",   0x08000, 0x1f59a248, BRF_GRA },	     //  5
245 	{ "n7-5.bin",      0x08000, 0x7ca5a532, BRF_GRA },	     //  6
246 	{ "ta18-02.bin",   0x08000, 0x994c0021, BRF_GRA },	     //  7
247 	{ "ta18-04.bin",   0x08000, 0x55b9e8aa, BRF_GRA },	     //  8
248 	{ "ta18-03.bin",   0x08000, 0x0475c99a, BRF_GRA },	     //  9
249 
250 	{ "ta18-20.bin",   0x08000, 0xc7d54139, BRF_GRA },	     //  10	Sprites
251 	{ "ta18-24.bin",   0x08000, 0x84677d45, BRF_GRA },	     //  11
252 	{ "ta18-18.bin",   0x08000, 0x1c770853, BRF_GRA },	     //  12
253 	{ "ta18-14.bin",   0x08000, 0xaf656017, BRF_GRA },	     //  13
254 	{ "ta18-23.bin",   0x08000, 0x3fd19cf7, BRF_GRA },	     //  14
255 	{ "ta18-17.bin",   0x08000, 0x74c64c6e, BRF_GRA },	     //  15
256 	{ "ta18-19.bin",   0x08000, 0xc8795fd7, BRF_GRA },	     //  16
257 	{ "ta18-22.bin",   0x08000, 0xdf3a2ff5, BRF_GRA },	     //  17
258 	{ "ta18-16.bin",   0x08000, 0x7244bad0, BRF_GRA },	     //  18
259 	{ "ta18-13.bin",   0x08000, 0xb6b14d46, BRF_GRA },	     //  19
260 	{ "ta18-21.bin",   0x08000, 0xc95e009b, BRF_GRA },	     //  20
261 	{ "ta18-15.bin",   0x08000, 0xa5d61d01, BRF_GRA },	     //  21
262 
263 	{ "ta18-09.bin",   0x08000, 0x07ed4705, BRF_GRA },	     //  22	ADPCM
264 	{ "ta18-08.bin",   0x08000, 0xc9312613, BRF_GRA },	     //  23
265 	{ "ta18-07.bin",   0x08000, 0x02e3f3ed, BRF_GRA },	     //  24
266 };
267 
268 STD_ROM_PICK(Drvb)
STD_ROM_FN(Drvb)269 STD_ROM_FN(Drvb)
270 
271 static INT32 MemIndex()
272 {
273 	UINT8 *Next; Next = Mem;
274 
275 	DrvM6502Rom            = Next; Next += 0x10000;
276 	DrvM6809Rom            = Next; Next += 0x08000;
277 	DrvM68705Rom           = Next; Next += 0x00800;
278 	DrvADPCMRom            = Next; Next += 0x18000;
279 
280 	RamStart               = Next;
281 
282 	DrvM6502Ram            = Next; Next += 0x01800;
283 	DrvM6809Ram            = Next; Next += 0x01000;
284 	DrvM68705Ram           = Next; Next += 0x00070;
285 	DrvSpriteRam           = Next; Next += 0x00800;
286 	DrvVideoRam1           = Next; Next += 0x00800;
287 	DrvVideoRam2           = Next; Next += 0x00800;
288 	DrvPaletteRam1         = Next; Next += 0x00100;
289 	DrvPaletteRam2         = Next; Next += 0x00100;
290 
291 	RamEnd                 = Next;
292 
293 	DrvChars               = Next; Next += 0x0400 * 8 * 8;
294 	DrvTiles               = Next; Next += 0x0800 * 16 * 16;
295 	DrvSprites             = Next; Next += 0x1000 * 16 * 16;
296 	DrvPalette             = (UINT32*)Next; Next += 0x00100 * sizeof(UINT32);
297 
298 	MemEnd                 = Next;
299 
300 	return 0;
301 }
302 
mcu_reset_r()303 static UINT8 mcu_reset_r()
304 {
305 	m6805Open(0);
306 	m68705Reset();
307 	m6805Close();
308 
309 	return 0;
310 }
311 
mcu_w(UINT8 data)312 static void mcu_w(UINT8 data)
313 {
314 	MCUFromMain = data;
315 	MCUMainSent = 1;
316 	m6805Open(0);
317 	m68705SetIrqLine(0, 1);
318 	m6805Close();
319 }
320 
mcu_r()321 static UINT8 mcu_r()
322 {
323 	MCUMcuSent = 0;
324 	return MCUFromMcu;
325 }
326 
mcu_status_r()327 static UINT8 mcu_status_r()
328 {
329 	UINT8 Res = 0;
330 
331 	if (DisableMCUEmulation) {
332 		Res = 1;
333 	} else {
334 		if (!MCUMainSent)
335 			Res |= 0x01;
336 		if (!MCUMcuSent)
337 			Res |= 0x02;
338 	}
339 
340 	return Res;
341 }
342 
DrvDoReset()343 static INT32 DrvDoReset()
344 {
345 	M6502Open(0);
346 	M6502Reset();
347 	M6502Close();
348 
349 	M6809Open(0);
350 	M6809Reset();
351 	M6809Close();
352 
353 	if (!DisableMCUEmulation) {
354 		m6805Open(0);
355 		m68705Reset();
356 		m6805Close();
357 
358 		MCUFromMain = 0;
359 		MCUFromMcu = 0;
360 		MCUMainSent = 0;
361 		MCUMcuSent = 0;
362 		MCUDdrA = 0;
363 		MCUDdrB = 0;
364 		MCUDdrC = 0;
365 		MCUPortAOut = 0;
366 		MCUPortBOut = 0;
367 		MCUPortCOut = 0;
368 		MCUPortAIn = 0;
369 		MCUPortBIn = 0;
370 		MCUPortCIn = 0;
371 	}
372 
373 	BurnYM3526Reset();
374 	MSM5205Reset();
375 
376 	DrvRomBank = 0;
377 	DrvVBlank = 0;
378 	memset(DrvScrollX, 0, 2);
379 	DrvSoundLatch = 0;
380 	DrvADPCMPlaying = 0;
381 	DrvADPCMPos = 0;
382 	DrvADPCMEnd = 0;
383 
384 	return 0;
385 }
386 
RenegadeReadByte(UINT16 Address)387 static UINT8 RenegadeReadByte(UINT16 Address)
388 {
389 	switch (Address) {
390 		case 0x3800: {
391 			return DrvInput[0];
392 		}
393 
394 		case 0x3801: {
395 			return DrvInput[1];
396 		}
397 
398 		case 0x3802: {
399 			UINT8 MCUStatus = mcu_status_r();
400 			if (MCUStatus) MCUStatus = (MCUStatus - 1) * 0x10;
401 			return DrvInput[2] + DrvDip[1] + (DrvVBlank ? 0x40 : 0) + MCUStatus;
402 		}
403 
404 		case 0x3803: {
405 			return DrvDip[0];
406 		}
407 
408 		case 0x3804: {
409 			if (!DisableMCUEmulation) {
410 				return mcu_r();
411 			}
412 			return 0;
413 		}
414 
415 		case 0x3805: {
416 			if (!DisableMCUEmulation) {
417 				return mcu_reset_r();
418 			}
419 		}
420 
421 		default: {
422 			bprintf(PRINT_NORMAL, _T("M6502 Read Byte %04X\n"), Address);
423 		}
424 	}
425 
426 	return 0;
427 }
428 
bankswitch(UINT8 Data)429 static void bankswitch(UINT8 Data)
430 {
431 	DrvRomBank = Data & 1;
432 	M6502MapMemory(DrvM6502Rom + 0x8000 + (DrvRomBank * 0x4000), 0x4000, 0x7fff, MAP_ROM);
433 }
434 
RenegadeWriteByte(UINT16 Address,UINT8 Data)435 static void RenegadeWriteByte(UINT16 Address, UINT8 Data)
436 {
437 	switch (Address) {
438 		case 0x3800: {
439 			DrvScrollX[0] = Data;
440 			return;
441 		}
442 
443 		case 0x3801: {
444 			DrvScrollX[1] = Data;
445 			return;
446 		}
447 
448 		case 0x3802: {
449 			DrvSoundLatch = Data;
450 			M6809Open(0);
451 			M6809SetIRQLine(M6809_IRQ_LINE, CPU_IRQSTATUS_AUTO);
452 			M6809Close();
453 			return;
454 		}
455 
456 		case 0x3803: {
457 			// flipscreen
458 			return;
459 		}
460 
461 		case 0x3804: {
462 			if (!DisableMCUEmulation) mcu_w(Data);
463 			return;
464 		}
465 
466 		case 0x3805: {
467 			bankswitch(Data);
468 			return;
469 		}
470 
471 		case 0x3806: {
472 			// nop
473 			return;
474 		}
475 
476 		case 0x3807: {
477 			// coin counter
478 			return;
479 		}
480 
481 		default: {
482 			bprintf(PRINT_NORMAL, _T("M6502 Write Byte %04X, %02X\n"), Address, Data);
483 		}
484 	}
485 }
486 
RenegadeM6809ReadByte(UINT16 Address)487 static UINT8 RenegadeM6809ReadByte(UINT16 Address)
488 {
489 	switch (Address) {
490 		case 0x1000: {
491 			return DrvSoundLatch;
492 		}
493 
494 		default: {
495 			bprintf(PRINT_NORMAL, _T("M6809 Read Byte %04X\n"), Address);
496 		}
497 	}
498 
499 	return 0;
500 }
501 
RenegadeM6809WriteByte(UINT16 Address,UINT8 Data)502 static void RenegadeM6809WriteByte(UINT16 Address, UINT8 Data)
503 {
504 	switch (Address) {
505 		case 0x1800: {
506 			MSM5205ResetWrite(0, 0);
507 			DrvADPCMPlaying = 1;
508 			return;
509 		}
510 
511 		case 0x2000: {
512 			switch (Data & 0x1c) {
513 				case 0x18: DrvADPCMPos = 0 * 0x8000 * 2; break;
514 				case 0x14: DrvADPCMPos = 1 * 0x8000 * 2; break;
515 				case 0x0c: DrvADPCMPos = 2 * 0x8000 * 2; break;
516 				default: DrvADPCMPos = DrvADPCMEnd = 0; return;
517 			}
518 			DrvADPCMPos |= (Data & 0x03) * 0x2000 * 2;
519 			DrvADPCMEnd = DrvADPCMPos + 0x2000 * 2;
520 			return;
521 		}
522 
523 		case 0x2800: {
524 			BurnYM3526Write(0, Data);
525 			return;
526 		}
527 
528 		case 0x2801: {
529 			BurnYM3526Write(1, Data);
530 			return;
531 		}
532 
533 		case 0x3000: {
534 			MSM5205ResetWrite(0, 1);
535 			DrvADPCMPlaying = 0;
536 			return;
537 		}
538 
539 		default: {
540 			bprintf(PRINT_NORMAL, _T("M6809 Write Byte %04X, %02X\n"), Address, Data);
541 		}
542 	}
543 }
544 
MCUReadByte(UINT16 address)545 static UINT8 MCUReadByte(UINT16 address)
546 {
547 	switch (address & 0x7ff) {
548 		case 0x000: {
549 			return (MCUPortAOut & MCUDdrA) | (MCUPortAIn & ~MCUDdrA);
550 		}
551 
552 		case 0x001: {
553 			return (MCUPortBOut & MCUDdrB) | (MCUPortBIn & ~MCUDdrB);
554 		}
555 
556 		case 0x002: {
557 			MCUPortCIn = 0;
558 			if (MCUMainSent) MCUPortCIn |= 0x01;
559 			if (!MCUMcuSent) MCUPortCIn |= 0x02;
560 
561 			return (MCUPortCOut & MCUDdrC) | (MCUPortCIn & ~MCUDdrC);
562 		}
563 
564 		default: {
565 			bprintf(PRINT_NORMAL, _T("MCU Read %x\n"), address);
566 		}
567 	}
568 
569 	return 0;
570 }
571 
MCUWriteByte(UINT16 address,UINT8 data)572 static void MCUWriteByte(UINT16 address, UINT8 data)
573 {
574 	switch (address & 0x7ff) {
575 		case 0x000: {
576 			MCUPortAOut = data;
577 			break;
578 		}
579 
580 		case 0x001: {
581 			if ((MCUDdrB & 0x02) && (~data & 0x02) && (MCUPortBOut & 0x02)) {
582 				MCUPortAIn = MCUFromMain;
583 
584 				if (MCUMainSent) {
585 					m68705SetIrqLine(0, 0);
586 					MCUMainSent = 0;
587 				}
588 			}
589 
590 			if ((MCUDdrB & 0x04) && (data & 0x04) && (~MCUPortBOut & 0x04)) {
591 				MCUFromMcu = MCUPortAOut;
592 				MCUMcuSent = 1;
593 			}
594 
595 			MCUPortBOut = data;
596 			break;
597 		}
598 
599 		case 0x002: {
600 			MCUPortCOut = data;
601 			break;
602 		}
603 
604 		case 0x004: {
605 			MCUDdrA = data;
606 			break;
607 		}
608 
609 		case 0x005: {
610 			MCUDdrB = data;
611 			break;
612 		}
613 
614 		case 0x006: {
615 			MCUDdrC = data;
616 			break;
617 		}
618 
619 		default: {
620 			bprintf(PRINT_NORMAL, _T("MCU Write %x, %x\n"), address, data);
621 		}
622 	}
623 }
624 
625 static INT32 CharPlaneOffsets[3]   = { 2, 4, 6 };
626 static INT32 CharXOffsets[8]       = { 1, 0, 65, 64, 129, 128, 193, 192 };
627 static INT32 CharYOffsets[8]       = { 0, 8, 16, 24, 32, 40, 48, 56 };
628 static INT32 Tile1PlaneOffsets[3]  = { 0x00004, 0x40000, 0x40004 };
629 static INT32 Tile2PlaneOffsets[3]  = { 0x00000, 0x60000, 0x60004 };
630 static INT32 Tile3PlaneOffsets[3]  = { 0x20004, 0x80000, 0x80004 };
631 static INT32 Tile4PlaneOffsets[3]  = { 0x20000, 0xa0000, 0xa0004 };
632 static INT32 TileXOffsets[16]      = { 3, 2, 1, 0, 131, 130, 129, 128, 259, 258, 257, 256, 387, 386, 385, 384 };
633 static INT32 TileYOffsets[16]      = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 };
634 
DrvFMIRQHandler(INT32,INT32 nStatus)635 static void DrvFMIRQHandler(INT32, INT32 nStatus)
636 {
637 	M6809SetIRQLine(M6809_FIRQ_LINE, (nStatus) ? CPU_IRQSTATUS_ACK : CPU_IRQSTATUS_NONE);
638 }
639 
DrvSynchroniseStream(INT32 nSoundRate)640 static INT32 DrvSynchroniseStream(INT32 nSoundRate)
641 {
642 	return (INT64)M6809TotalCycles() * nSoundRate / 1500000;
643 }
644 
DrvMSM5205Int()645 static void DrvMSM5205Int()
646 {
647 	if (!DrvADPCMPlaying) {
648 		MSM5205ResetWrite(0, 1);
649 		return;
650 	}
651 
652 	if (DrvADPCMPos >= DrvADPCMEnd) {
653 		MSM5205ResetWrite(0, 1);
654 		DrvADPCMPlaying = false;
655 		M6809SetIRQLine(0x20, CPU_IRQSTATUS_AUTO);
656 	} else {
657 		UINT8 const data = DrvADPCMRom[DrvADPCMPos / 2];
658 		MSM5205DataWrite(0, (DrvADPCMPos & 1) ? data & 0xf : data >> 4);
659 		DrvADPCMPos++;
660 	}
661 }
662 
DrvInit(INT32 nMcuType)663 static INT32 DrvInit(INT32 nMcuType)
664 {
665 	INT32 nRet = 0, nLen;
666 
667 	Mem = NULL;
668 	MemIndex();
669 	nLen = MemEnd - (UINT8 *)0;
670 	if ((Mem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1;
671 	memset(Mem, 0, nLen);
672 	MemIndex();
673 
674 	DrvTempRom = (UINT8 *)BurnMalloc(0x60000);
675 
676 	nRet = BurnLoadRom(DrvM6502Rom + 0x00000, 0, 1); if (nRet != 0) return 1;
677 	nRet = BurnLoadRom(DrvM6502Rom + 0x08000, 1, 1); if (nRet != 0) return 1;
678 
679 	nRet = BurnLoadRom(DrvM6809Rom + 0x00000, 2, 1); if (nRet != 0) return 1;
680 
681 	nRet = BurnLoadRom(DrvTempRom, 3, 1); if (nRet != 0) return 1;
682 	GfxDecode(0x400, 3, 8, 8, CharPlaneOffsets, CharXOffsets, CharYOffsets, 0x100, DrvTempRom, DrvChars);
683 
684 	memset(DrvTempRom, 0, 0x60000);
685 	nRet = BurnLoadRom(DrvTempRom + 0x00000, 4, 1); if (nRet != 0) return 1;
686 	nRet = BurnLoadRom(DrvTempRom + 0x08000, 5, 1); if (nRet != 0) return 1;
687 	nRet = BurnLoadRom(DrvTempRom + 0x10000, 6, 1); if (nRet != 0) return 1;
688 	nRet = BurnLoadRom(DrvTempRom + 0x18000, 7, 1); if (nRet != 0) return 1;
689 	nRet = BurnLoadRom(DrvTempRom + 0x20000, 8, 1); if (nRet != 0) return 1;
690 	nRet = BurnLoadRom(DrvTempRom + 0x28000, 9, 1); if (nRet != 0) return 1;
691 	GfxDecode(0x100, 3, 16, 16, Tile1PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x00000, DrvTiles + (0x000 * 16 * 16));
692 	GfxDecode(0x100, 3, 16, 16, Tile2PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x00000, DrvTiles + (0x100 * 16 * 16));
693 	GfxDecode(0x100, 3, 16, 16, Tile3PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x00000, DrvTiles + (0x200 * 16 * 16));
694 	GfxDecode(0x100, 3, 16, 16, Tile4PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x00000, DrvTiles + (0x300 * 16 * 16));
695 	GfxDecode(0x100, 3, 16, 16, Tile1PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x18000, DrvTiles + (0x400 * 16 * 16));
696 	GfxDecode(0x100, 3, 16, 16, Tile2PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x18000, DrvTiles + (0x500 * 16 * 16));
697 	GfxDecode(0x100, 3, 16, 16, Tile3PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x18000, DrvTiles + (0x600 * 16 * 16));
698 	GfxDecode(0x100, 3, 16, 16, Tile4PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x18000, DrvTiles + (0x700 * 16 * 16));
699 
700 	memset(DrvTempRom, 0, 0x60000);
701 	nRet = BurnLoadRom(DrvTempRom + 0x00000, 10, 1); if (nRet != 0) return 1;
702 	nRet = BurnLoadRom(DrvTempRom + 0x08000, 11, 1); if (nRet != 0) return 1;
703 	nRet = BurnLoadRom(DrvTempRom + 0x10000, 12, 1); if (nRet != 0) return 1;
704 	nRet = BurnLoadRom(DrvTempRom + 0x18000, 13, 1); if (nRet != 0) return 1;
705 	nRet = BurnLoadRom(DrvTempRom + 0x20000, 14, 1); if (nRet != 0) return 1;
706 	nRet = BurnLoadRom(DrvTempRom + 0x28000, 15, 1); if (nRet != 0) return 1;
707 	nRet = BurnLoadRom(DrvTempRom + 0x30000, 16, 1); if (nRet != 0) return 1;
708 	nRet = BurnLoadRom(DrvTempRom + 0x38000, 17, 1); if (nRet != 0) return 1;
709 	nRet = BurnLoadRom(DrvTempRom + 0x40000, 18, 1); if (nRet != 0) return 1;
710 	nRet = BurnLoadRom(DrvTempRom + 0x48000, 19, 1); if (nRet != 0) return 1;
711 	nRet = BurnLoadRom(DrvTempRom + 0x50000, 20, 1); if (nRet != 0) return 1;
712 	nRet = BurnLoadRom(DrvTempRom + 0x58000, 21, 1); if (nRet != 0) return 1;
713 	GfxDecode(0x100, 3, 16, 16, Tile1PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x00000, DrvSprites + (0x000 * 16 * 16));
714 	GfxDecode(0x100, 3, 16, 16, Tile2PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x00000, DrvSprites + (0x100 * 16 * 16));
715 	GfxDecode(0x100, 3, 16, 16, Tile3PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x00000, DrvSprites + (0x200 * 16 * 16));
716 	GfxDecode(0x100, 3, 16, 16, Tile4PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x00000, DrvSprites + (0x300 * 16 * 16));
717 	GfxDecode(0x100, 3, 16, 16, Tile1PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x18000, DrvSprites + (0x400 * 16 * 16));
718 	GfxDecode(0x100, 3, 16, 16, Tile2PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x18000, DrvSprites + (0x500 * 16 * 16));
719 	GfxDecode(0x100, 3, 16, 16, Tile3PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x18000, DrvSprites + (0x600 * 16 * 16));
720 	GfxDecode(0x100, 3, 16, 16, Tile4PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x18000, DrvSprites + (0x700 * 16 * 16));
721 	GfxDecode(0x100, 3, 16, 16, Tile1PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x30000, DrvSprites + (0x800 * 16 * 16));
722 	GfxDecode(0x100, 3, 16, 16, Tile2PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x30000, DrvSprites + (0x900 * 16 * 16));
723 	GfxDecode(0x100, 3, 16, 16, Tile3PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x30000, DrvSprites + (0xa00 * 16 * 16));
724 	GfxDecode(0x100, 3, 16, 16, Tile4PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x30000, DrvSprites + (0xb00 * 16 * 16));
725 	GfxDecode(0x100, 3, 16, 16, Tile1PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x48000, DrvSprites + (0xc00 * 16 * 16));
726 	GfxDecode(0x100, 3, 16, 16, Tile2PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x48000, DrvSprites + (0xd00 * 16 * 16));
727 	GfxDecode(0x100, 3, 16, 16, Tile3PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x48000, DrvSprites + (0xe00 * 16 * 16));
728 	GfxDecode(0x100, 3, 16, 16, Tile4PlaneOffsets, TileXOffsets, TileYOffsets, 0x200, DrvTempRom + 0x48000, DrvSprites + (0xf00 * 16 * 16));
729 
730 	nRet = BurnLoadRom(DrvADPCMRom + 0x00000, 22, 1); if (nRet != 0) return 1;
731 	nRet = BurnLoadRom(DrvADPCMRom + 0x08000, 23, 1); if (nRet != 0) return 1;
732 	nRet = BurnLoadRom(DrvADPCMRom + 0x10000, 24, 1); if (nRet != 0) return 1;
733 
734 	BurnFree(DrvTempRom);
735 
736 	M6502Init(0, TYPE_M6502);
737 	M6502Open(0);
738 	M6502MapMemory(DrvM6502Ram            , 0x0000, 0x17ff, MAP_RAM);
739 	M6502MapMemory(DrvVideoRam2           , 0x1800, 0x1fff, MAP_RAM);
740 	M6502MapMemory(DrvSpriteRam           , 0x2000, 0x27ff, MAP_RAM);
741 	M6502MapMemory(DrvVideoRam1           , 0x2800, 0x2fff, MAP_RAM);
742 	M6502MapMemory(DrvPaletteRam1         , 0x3000, 0x30ff, MAP_RAM);
743 	M6502MapMemory(DrvPaletteRam2         , 0x3100, 0x31ff, MAP_RAM);
744 	M6502MapMemory(DrvM6502Rom + 0x8000   , 0x4000, 0x7fff, MAP_ROM);
745 	M6502MapMemory(DrvM6502Rom            , 0x8000, 0xffff, MAP_ROM);
746 	M6502SetReadHandler(RenegadeReadByte);
747 	M6502SetWriteHandler(RenegadeWriteByte);
748 	M6502Close();
749 
750 	M6809Init(0);
751 	M6809Open(0);
752 	M6809MapMemory(DrvM6809Ram          , 0x0000, 0x0fff, MAP_RAM);
753 	M6809MapMemory(DrvM6809Rom          , 0x8000, 0xffff, MAP_ROM);
754 	M6809SetReadHandler(RenegadeM6809ReadByte);
755 	M6809SetWriteHandler(RenegadeM6809WriteByte);
756 	M6809Close();
757 
758 	MSM5205Init(0, DrvSynchroniseStream, 12000000 / 32, DrvMSM5205Int, MSM5205_S48_4B, 1);
759 	MSM5205SetRoute(0, 1.00, BURN_SND_ROUTE_BOTH);
760 
761 	if (nMcuType == MCU_TYPE_MCU) {
762 		nRet = BurnLoadRom(DrvM68705Rom, 25, 1); if (nRet != 0) return 1;
763 
764 		m6805Init(1, 0x800);
765 		m6805Open(0);
766 		m6805MapMemory(DrvM68705Ram         , 0x0010, 0x007f, MAP_RAM);
767 		m6805MapMemory(DrvM68705Rom + 0x0080, 0x0080, 0x07ff, MAP_ROM);
768 		m6805SetWriteHandler(MCUWriteByte);
769 		m6805SetReadHandler(MCUReadByte);
770 		m6805Close();
771 	}
772 
773 	if (nMcuType == MCU_TYPE_NONE) {
774 		DisableMCUEmulation = 1;
775 	}
776 
777 	BurnYM3526Init(3000000, &DrvFMIRQHandler, &DrvSynchroniseStream, 0);
778 	BurnTimerAttachYM3526(&M6809Config, 1500000);
779 	BurnYM3526SetRoute(BURN_SND_YM3526_ROUTE, 1.00, BURN_SND_ROUTE_BOTH);
780 
781 	GenericTilesInit();
782 
783 	DrvDoReset();
784 
785 	return 0;
786 }
787 
RenegadeInit()788 static INT32 RenegadeInit()
789 {
790 	return DrvInit(MCU_TYPE_MCU);
791 }
792 
KuniokunbInit()793 static INT32 KuniokunbInit()
794 {
795 	return DrvInit(MCU_TYPE_NONE);
796 }
797 
DrvExit()798 static INT32 DrvExit()
799 {
800 	M6502Exit();
801 	M6809Exit();
802 	if (!DisableMCUEmulation) m6805Exit();
803 
804 	BurnYM3526Exit();
805 	MSM5205Exit();
806 
807 	GenericTilesExit();
808 
809 	BurnFree(Mem);
810 
811 	DisableMCUEmulation = 0;
812 
813 	MCUFromMain = 0;
814 	MCUFromMcu = 0;
815 	MCUMainSent = 0;
816 	MCUMcuSent = 0;
817 	MCUDdrA = 0;
818 	MCUDdrB = 0;
819 	MCUDdrC = 0;
820 	MCUPortAOut = 0;
821 	MCUPortBOut = 0;
822 	MCUPortCOut = 0;
823 	MCUPortAIn = 0;
824 	MCUPortBIn = 0;
825 	MCUPortCIn = 0;
826 
827 	DrvRomBank = 0;
828 	DrvVBlank = 0;
829 	memset(DrvScrollX, 0, sizeof(DrvScrollX));
830 	DrvSoundLatch = 0;
831 	DrvADPCMPlaying = 0;
832 	DrvADPCMPos = 0;
833 	DrvADPCMEnd = 0;
834 
835 	return 0;
836 }
837 
pal4bit(UINT8 bits)838 static inline UINT8 pal4bit(UINT8 bits)
839 {
840 	bits &= 0x0f;
841 	return (bits << 4) | bits;
842 }
843 
CalcCol(UINT16 nColour)844 inline static UINT32 CalcCol(UINT16 nColour)
845 {
846 	INT32 r, g, b;
847 
848 	r = pal4bit(nColour >> 0);
849 	g = pal4bit(nColour >> 4);
850 	b = pal4bit(nColour >> 8);
851 
852 	return BurnHighCol(r, g, b, 0);
853 }
854 
DrvCalcPalette()855 static void DrvCalcPalette()
856 {
857 	for (INT32 i = 0; i < 0x100; i++) {
858 		INT32 Val = DrvPaletteRam1[i] + (DrvPaletteRam2[i] << 8);
859 
860 		DrvPalette[i] = CalcCol(Val);
861 	}
862 }
863 
DrvRenderBgLayer()864 static void DrvRenderBgLayer()
865 {
866 	INT32 mx, my, Attr, Code, Colour, x, y, TileIndex = 0, xScroll;
867 
868 	xScroll = DrvScrollX[0] + (DrvScrollX[1] << 8);
869 	xScroll &= 0x3ff;
870 	xScroll -= 256;
871 
872 	for (my = 0; my < 16; my++) {
873 		for (mx = 0; mx < 64; mx++) {
874 			Attr = DrvVideoRam1[TileIndex + 0x400];
875 			Code = DrvVideoRam1[TileIndex + 0x000];
876 			Colour = Attr >> 5;
877 
878 			x = 16 * mx;
879 			y = 16 * my;
880 
881 			x -= xScroll;
882 			if (x < -16) x += 1024;
883 
884 			x -= 8;
885 
886 			if (x > 0 && x < 224 && y > 0 && y < 224) {
887 				Render16x16Tile(pTransDraw, Code, x, y, Colour, 3, 192, DrvTiles + ((Attr & 0x07) * 0x100 * 16 * 16));
888 			} else {
889 				Render16x16Tile_Clip(pTransDraw, Code, x, y, Colour, 3, 192, DrvTiles + ((Attr & 0x07) * 0x100 * 16 * 16));
890 			}
891 
892 			TileIndex++;
893 		}
894 	}
895 }
896 
DrvRenderSprites()897 static void DrvRenderSprites()
898 {
899 	UINT8 *Source = DrvSpriteRam;
900 	UINT8 *Finish = Source + 96 * 4;
901 
902 	while (Source < Finish) {
903 		INT32 sy = 240 - Source[0];
904 
905 		if (sy >= 16) {
906 			INT32 Attr = Source[1];
907 			INT32 sx = Source[3];
908 			INT32 Code = Source[2];
909 			INT32 SpriteBank = Attr & 0xf;
910 			INT32 Colour = (Attr >> 4) & 0x3;
911 			INT32 xFlip = Attr & 0x40;
912 
913 			if (sx > 248) sx -= 256;
914 
915 			sx -= 8;
916 
917 			if (Attr & 0x80) {
918 				Code &= ~1;
919 				if (sx > 16 && sx < 224 && (sy + 16) > 0 && (sy + 16) < 224) {
920 					if (xFlip) {
921 						Render16x16Tile_Mask_FlipX(pTransDraw, Code + 1, sx, sy + 16, Colour, 3, 0, 128, DrvSprites + (SpriteBank * 0x100 * 16 * 16));
922 					} else {
923 						Render16x16Tile_Mask(pTransDraw, Code + 1, sx, sy + 16, Colour, 3, 0, 128, DrvSprites + (SpriteBank * 0x100 * 16 * 16));
924 					}
925 				} else {
926 					if (xFlip) {
927 						Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code + 1, sx, sy + 16, Colour, 3, 0, 128, DrvSprites + (SpriteBank * 0x100 * 16 * 16));
928 					} else {
929 						Render16x16Tile_Mask_Clip(pTransDraw, Code + 1, sx, sy + 16, Colour, 3, 0, 128, DrvSprites + (SpriteBank * 0x100 * 16 * 16));
930 					}
931 				}
932 			} else {
933 				sy += 16;
934 			}
935 
936 			if (sx > 16 && sx < 224 && sy > 0 && sy < 224) {
937 				if (xFlip) {
938 					Render16x16Tile_Mask_FlipX(pTransDraw, Code, sx, sy, Colour, 3, 0, 128, DrvSprites + (SpriteBank * 0x100 * 16 * 16));
939 				} else {
940 					Render16x16Tile_Mask(pTransDraw, Code, sx, sy, Colour, 3, 0, 128, DrvSprites + (SpriteBank * 0x100 * 16 * 16));
941 				}
942 			} else {
943 				if (xFlip) {
944 					Render16x16Tile_Mask_FlipX_Clip(pTransDraw, Code, sx, sy, Colour, 3, 0, 128, DrvSprites + (SpriteBank * 0x100 * 16 * 16));
945 				} else {
946 					Render16x16Tile_Mask_Clip(pTransDraw, Code, sx, sy, Colour, 3, 0, 128, DrvSprites + (SpriteBank * 0x100 * 16 * 16));
947 				}
948 			}
949 		}
950 		Source += 4;
951 	}
952 }
953 
DrvRenderCharLayer()954 static void DrvRenderCharLayer()
955 {
956 	INT32 mx, my, Attr, Code, Colour, x, y, TileIndex = 0;
957 
958 	for (my = 0; my < 32; my++) {
959 		for (mx = 0; mx < 32; mx++) {
960 			Attr = DrvVideoRam2[TileIndex + 0x400];
961 			Code = ((Attr & 3) << 8) + DrvVideoRam2[TileIndex + 0x000];
962 			Colour = Attr >> 6;
963 
964 			x = 8 * mx;
965 			y = 8 * my;
966 
967 			x -= 8;
968 
969 			if (x > 0 && x < 232 && y > 0 && y < 232) {
970 				Render8x8Tile_Mask(pTransDraw, Code, x, y, Colour, 3, 0, 0, DrvChars);
971 			} else {
972 				Render8x8Tile_Mask_Clip(pTransDraw, Code, x, y, Colour, 3, 0, 0, DrvChars);
973 			}
974 
975 			TileIndex++;
976 		}
977 	}
978 }
979 
DrvDraw()980 static INT32 DrvDraw()
981 {
982 	BurnTransferClear();
983 	DrvCalcPalette();
984 	DrvRenderBgLayer();
985 	DrvRenderSprites();
986 	DrvRenderCharLayer();
987 	BurnTransferCopy(DrvPalette);
988 
989 	return 0;
990 }
991 
DrvFrame()992 static INT32 DrvFrame()
993 {
994 	INT32 nInterleave = MSM5205CalcInterleave(0, 12000000 / 8);
995 
996 	if (DrvReset) DrvDoReset();
997 
998 	DrvMakeInputs();
999 
1000 	INT32 nCyclesTotal[3] = { (12000000 / 8) / 60, (12000000 / 8) / 60, (12000000 / 4) / 60 };
1001 	INT32 nCyclesDone[3] = { 0, 0, 0 };
1002 	INT32 nCyclesSegment;
1003 
1004 	DrvVBlank = 0;
1005 
1006 	M6502NewFrame();
1007 	M6809NewFrame();
1008 
1009 	for (INT32 i = 0; i < nInterleave; i++) {
1010 		INT32 nCurrentCPU, nNext;
1011 
1012 		M6502Open(0);
1013 		nCurrentCPU = 0;
1014 		nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave;
1015 		nCyclesSegment = nNext - nCyclesDone[nCurrentCPU];
1016 		nCyclesDone[nCurrentCPU] += M6502Run(nCyclesSegment);
1017 		if (i == ((nInterleave / 10) * 7)) DrvVBlank = 1;
1018 		if (i ==  (nInterleave / 2)) M6502SetIRQLine(M6502_INPUT_LINE_NMI, CPU_IRQSTATUS_AUTO);
1019 		if (i == ((nInterleave / 10) * 9)) M6502SetIRQLine(M6502_IRQ_LINE, CPU_IRQSTATUS_HOLD);
1020 		M6502Close();
1021 
1022 		if (!DisableMCUEmulation) {
1023 			m6805Open(0);
1024 			nCurrentCPU = 2;
1025 			nNext = (i + 1) * nCyclesTotal[nCurrentCPU] / nInterleave;
1026 			nCyclesSegment = nNext - nCyclesDone[nCurrentCPU];
1027 			nCyclesDone[nCurrentCPU] += m6805Run(nCyclesSegment);
1028 			m6805Close();
1029 		}
1030 
1031 		M6809Open(0);
1032 		BurnTimerUpdateYM3526((i + 1) * (nCyclesTotal[1] / nInterleave));
1033 		MSM5205Update();
1034 		M6809Close();
1035 	}
1036 
1037 	M6809Open(0);
1038 	BurnTimerEndFrameYM3526(nCyclesTotal[1]);
1039 	BurnYM3526Update(pBurnSoundOut, nBurnSoundLen);
1040 	MSM5205Render(0, pBurnSoundOut, nBurnSoundLen);
1041 	M6809Close();
1042 
1043 	if (pBurnDraw) DrvDraw();
1044 
1045 	return 0;
1046 }
1047 
DrvScan(INT32 nAction,INT32 * pnMin)1048 static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
1049 {
1050 	struct BurnArea ba;
1051 
1052 	if (pnMin != NULL) {			// Return minimum compatible version
1053 		*pnMin = 0x029696;
1054 	}
1055 
1056 	if (nAction & ACB_MEMORY_RAM) {
1057 		memset(&ba, 0, sizeof(ba));
1058 		ba.Data	  = RamStart;
1059 		ba.nLen	  = RamEnd-RamStart;
1060 		ba.szName = "All Ram";
1061 		BurnAcb(&ba);
1062 	}
1063 
1064 	if (nAction & ACB_DRIVER_DATA) {
1065 		M6502Scan(nAction);
1066 		m6805Scan(nAction);
1067 		M6809Scan(nAction);
1068 
1069 		BurnYM3526Scan(nAction, pnMin);
1070 		MSM5205Scan(nAction, pnMin);
1071 
1072 		SCAN_VAR(DrvRomBank);
1073 		SCAN_VAR(DrvScrollX);
1074 		SCAN_VAR(DrvSoundLatch);
1075 		SCAN_VAR(DrvADPCMPlaying);
1076 		SCAN_VAR(DrvADPCMPos);
1077 		SCAN_VAR(DrvADPCMEnd);
1078 		SCAN_VAR(MCUFromMain);
1079 		SCAN_VAR(MCUFromMcu);
1080 		SCAN_VAR(MCUMainSent);
1081 		SCAN_VAR(MCUMcuSent);
1082 		SCAN_VAR(MCUDdrA);
1083 		SCAN_VAR(MCUDdrB);
1084 		SCAN_VAR(MCUDdrC);
1085 		SCAN_VAR(MCUPortAOut);
1086 		SCAN_VAR(MCUPortBOut);
1087 		SCAN_VAR(MCUPortCOut);
1088 		SCAN_VAR(MCUPortAIn);
1089 		SCAN_VAR(MCUPortBIn);
1090 		SCAN_VAR(MCUPortCIn);
1091 	}
1092 
1093 	if (nAction & ACB_WRITE) {
1094 		M6502Open(0);
1095 		bankswitch(DrvRomBank);
1096 		M6502Close();
1097 	}
1098 
1099 	return 0;
1100 }
1101 
1102 struct BurnDriver BurnDrvRenegade = {
1103 	"renegade", NULL, NULL, NULL, "1986",
1104 	"Renegade (US)\0", NULL, "Technos (Taito America license)", "Miscellaneous",
1105 	NULL, NULL, NULL, NULL,
1106 	BDF_GAME_WORKING, 2, HARDWARE_TECHNOS, GBF_SCRFIGHT, 0,
1107 	NULL, DrvRomInfo, DrvRomName, NULL, NULL, NULL, NULL, DrvInputInfo, DrvDIPInfo,
1108 	RenegadeInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
1109 	NULL, 0x100, 240, 240, 4, 3
1110 };
1111 
1112 struct BurnDriver BurnDrvKuniokun = {
1113 	"kuniokun", "renegade", NULL, NULL, "1986",
1114 	"Nekketsu Kouha Kunio-kun (Japan)\0", NULL, "Technos", "Miscellaneous",
1115 	NULL, NULL, NULL, NULL,
1116 	BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_TECHNOS, GBF_SCRFIGHT, 0,
1117 	NULL, DrvjRomInfo, DrvjRomName, NULL, NULL, NULL, NULL, DrvInputInfo, DrvDIPInfo,
1118 	RenegadeInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
1119 	NULL, 0x100, 240, 240, 4, 3
1120 };
1121 
1122 struct BurnDriver BurnDrvKuniokunb = {
1123 	"kuniokunb", "renegade", NULL, NULL, "1986",
1124 	"Nekketsu Kouha Kunio-kun (Japan bootleg)\0", NULL, "bootleg", "Miscellaneous",
1125 	NULL, NULL, NULL, NULL,
1126 	BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_TECHNOS, GBF_SCRFIGHT, 0,
1127 	NULL, DrvbRomInfo, DrvbRomName, NULL, NULL, NULL, NULL, DrvInputInfo, DrvDIPInfo,
1128 	KuniokunbInit, DrvExit, DrvFrame, DrvDraw, DrvScan,
1129 	NULL, 0x100, 240, 240, 4, 3
1130 };
1131