1 // FB Alpha Alien Invaders driver module
2 // Based on MAME driver by David Haywood, Mariusz Wojcieszek
3 
4 #include "tiles_generic.h"
5 #include "m6502_intf.h"
6 #include "dac.h"
7 
8 static UINT8 *AllMem;
9 static UINT8 *MemEnd;
10 static UINT8 *AllRam;
11 static UINT8 *RamEnd;
12 static UINT8 *Drv6502ROM;
13 static UINT8 *DrvProtPROM;
14 static UINT8 *Drv6502RAM;
15 static UINT8 *DrvVidRAM;
16 
17 static UINT32 *DrvPalette;
18 static UINT8 DrvRecalc;
19 
20 static UINT8 previrqmask;
21 static UINT8 irqmask;
22 
23 static UINT8 DrvJoy1[6];
24 static UINT8 DrvDips[1];
25 static UINT8 DrvReset;
26 
27 static struct BurnInputInfo AlinvadeInputList[] = {
28 	{"P1 Coin",		BIT_DIGITAL,	DrvJoy1 + 0,	"p1 coin"	},
29 	{"P1 Start",		BIT_DIGITAL,	DrvJoy1 + 4,	"p1 start"	},
30 	{"P1 Left",		BIT_DIGITAL,	DrvJoy1 + 3,	"p1 left"	},
31 	{"P1 Right",		BIT_DIGITAL,	DrvJoy1 + 2,	"p1 right"	},
32 	{"P1 Button 1",		BIT_DIGITAL,	DrvJoy1 + 1,	"p1 fire 1"	},
33 
34 	{"Reset",		BIT_DIGITAL,	&DrvReset,	"reset"		},
35 	{"Dips",		BIT_DIPSWITCH,	DrvDips + 0,	"dip"		},
36 };
37 
38 STDINPUTINFO(Alinvade)
39 
40 static struct BurnDIPInfo AlinvadeDIPList[]=
41 {
42 	{0x06, 0xff, 0xff, 0x00, NULL		},
43 
44 	{0   , 0xfe, 0   ,    4, "Lives"	},
45 	{0x06, 0x01, 0x03, 0x00, "2"		},
46 	{0x06, 0x01, 0x03, 0x01, "3"		},
47 	{0x06, 0x01, 0x03, 0x02, "4"		},
48 	{0x06, 0x01, 0x03, 0x03, "5"		},
49 
50 	{0   , 0xfe, 0   ,    2, "�"		},
51 	{0x06, 0x01, 0x04, 0x00, "Off"		},
52 	{0x06, 0x01, 0x04, 0x04, "On"		},
53 };
54 
STDDIPINFO(Alinvade)55 STDDIPINFO(Alinvade)
56 
57 static UINT8 alinvade_read(UINT16 address)
58 {
59 	switch (address)
60 	{
61 		case 0x4000: return (~DrvJoy1[0] & 1) * 0x10;
62 		case 0x6000: return DrvDips[0];
63 		case 0x8000: return ( DrvJoy1[1] & 1) * 0x20;
64 		case 0x8001: return ( DrvJoy1[2] & 1) * 0x20;
65 		case 0x8002: return ( DrvJoy1[3] & 1) * 0x20;
66 		case 0x8003: return ( DrvJoy1[4] & 1) * 0x20;
67 		case 0x8004: return ( DrvJoy1[5] & 1) * 0x20;
68 
69 		case 0xe800: return 0;
70 	}
71 
72 	return 0;
73 }
74 
alinvade_write(UINT16 address,UINT8 data)75 static void alinvade_write(UINT16 address, UINT8 data)
76 {
77 	switch (address)
78 	{
79 		case 0x2000: // definitely sound writes of some sort
80 			DACWrite(0, data);
81 		return;
82 
83 		case 0xa000:
84 		return;		// nop
85 
86 		case 0xe400:
87 		return;		// nop
88 
89 		case 0xe800:
90 			if (previrqmask == 0 && (data & 1) == 1)
91 				irqmask ^= 1;
92 			previrqmask = data & 1;
93 		return;
94 	}
95 }
96 
DrvSyncDAC()97 static INT32 DrvSyncDAC()
98 {
99 	return (INT32)(float)(nBurnSoundLen * (M6502TotalCycles() / (2000000.000 / 60)));
100 }
101 
DrvDoReset()102 static INT32 DrvDoReset()
103 {
104 	memset (AllRam, 0, RamEnd - AllRam);
105 
106 	M6502Open(0);
107 	M6502Reset();
108 	M6502Close();
109 
110 	DACReset();
111 
112 	previrqmask = 0;
113 	irqmask = 1;
114 
115 	return 0;
116 }
117 
MemIndex()118 static INT32 MemIndex()
119 {
120 	UINT8 *Next; Next = AllMem;
121 
122 	Drv6502ROM		= Next; Next += 0x002000;
123 
124 	DrvProtPROM		= Next; Next += 0x000100;
125 
126 	DrvPalette		= (UINT32*)Next; Next += 0x0002 * sizeof(UINT32);
127 
128 	AllRam			= Next;
129 
130 	Drv6502RAM		= Next; Next += 0x000200;
131 	DrvVidRAM		= Next; Next += 0x000c00;
132 
133 	RamEnd			= Next;
134 
135 	MemEnd			= Next;
136 
137 	return 0;
138 }
139 
DrvInit()140 static INT32 DrvInit()
141 {
142 	AllMem = NULL;
143 	MemIndex();
144 	INT32 nLen = MemEnd - (UINT8 *)0;
145 	if ((AllMem = (UINT8 *)BurnMalloc(nLen)) == NULL) return 1;
146 	memset(AllMem, 0, nLen);
147 	MemIndex();
148 
149 	{
150 		if (BurnLoadRom(Drv6502ROM + 0x0000, 0, 1)) return 1;
151 		if (BurnLoadRom(Drv6502ROM + 0x0c00, 1, 1)) return 1;
152 		if (BurnLoadRom(Drv6502ROM + 0x1000, 2, 1)) return 1;
153 		if (BurnLoadRom(Drv6502ROM + 0x1400, 3, 1)) return 1;
154 		if (BurnLoadRom(Drv6502ROM + 0x1800, 4, 1)) return 1;
155 		if (BurnLoadRom(Drv6502ROM + 0x1c00, 5, 1)) return 1;
156 	}
157 
158 	// Protection hack, since prom isn't dumped we replace it with this
159 	{
160 		for (INT32 i = 0; i < 0x100; i++) {
161 			DrvProtPROM[i] = ((i & 0xf) == 0x0f) ? 0x60 : 0xea;
162 		}
163 	}
164 
165 	M6502Init(0, TYPE_M6502);
166 	M6502Open(0);
167 	M6502MapMemory(Drv6502RAM,	0x0000, 0x01ff, MAP_RAM);
168 	M6502MapMemory(DrvVidRAM,	0x0400, 0x0fff, MAP_RAM);
169 	for (INT32 i = 0; i < 0x1000; i+=0x100)
170 		M6502MapMemory(DrvProtPROM,	0xc000+i, 0xc0ff+i, MAP_ROM); // mirrored
171 	M6502MapMemory(Drv6502ROM,	0xe000, 0xffff, MAP_ROM);
172 	M6502SetWriteHandler(alinvade_write);
173 	M6502SetReadHandler(alinvade_read);
174 	M6502Close();
175 
176 	DACInit(0, 0, 0, DrvSyncDAC);
177 	DACSetRoute(0, 1.00, BURN_SND_ROUTE_BOTH);
178 
179 	GenericTilesInit();
180 
181 	DrvDoReset();
182 
183 	return 0;
184 }
185 
DrvExit()186 static INT32 DrvExit()
187 {
188 	GenericTilesExit();
189 
190 	DACExit();
191 
192 	M6502Exit();
193 
194 	BurnFree(AllMem);
195 
196 	return 0;
197 }
198 
draw_bitmap()199 static void draw_bitmap()
200 {
201 	for (INT32 offs = 0; offs < (128 * 128)/8; offs++)
202 	{
203 		UINT8 sx = (offs << 3) & 0x78;
204 		INT32 sy = (offs >> 4) & 0x7f;
205 		UINT8 data = DrvVidRAM[offs];
206 		UINT16 *dst = pTransDraw + (sy * nScreenWidth) + sx;
207 
208 		for (INT32 x = 0; x < 8; x++)
209 		{
210 			dst[x] = data & 1;
211 			data >>= 1;
212 		}
213 	}
214 }
215 
DrvDraw()216 static INT32 DrvDraw()
217 {
218 	DrvPalette[0] = BurnHighCol(0x00,0x00,0x00, 0);
219 	DrvPalette[1] = BurnHighCol(0xff,0xff,0xff, 0);
220 
221 	draw_bitmap();
222 
223 	BurnTransferCopy(DrvPalette);
224 
225 	return 0;
226 }
227 
DrvFrame()228 static INT32 DrvFrame()
229 {
230 	if (DrvReset) {
231 		DrvDoReset();
232 	}
233 
234 	M6502NewFrame();
235 
236 	INT32 nTotalCycles = 2000000 / 60;
237 
238 	M6502Open(0);
239 	M6502Run(nTotalCycles);
240 	if (irqmask) M6502SetIRQLine(0, CPU_IRQSTATUS_AUTO);
241 	M6502Close();
242 
243 	if (pBurnSoundOut) {
244 		DACUpdate(pBurnSoundOut, nBurnSoundLen);
245 	}
246 
247 	if (pBurnDraw) {
248 		DrvDraw();
249 	}
250 
251 	return 0;
252 }
253 
DrvScan(INT32 nAction,INT32 * pnMin)254 static INT32 DrvScan(INT32 nAction,INT32 *pnMin)
255 {
256 	struct BurnArea ba;
257 
258 	if (pnMin) {
259 		*pnMin = 0x029722;
260 	}
261 
262 	if (nAction & ACB_VOLATILE) {
263 		memset(&ba, 0, sizeof(ba));
264 		ba.Data	  = AllRam;
265 		ba.nLen	  = RamEnd - AllRam;
266 		ba.szName = "All Ram";
267 		BurnAcb(&ba);
268 
269 		M6502Scan(nAction);
270 
271 		DACScan(nAction,pnMin);
272 
273 		SCAN_VAR(previrqmask);
274 		SCAN_VAR(irqmask);
275 	}
276 
277 	return 0;
278 }
279 
280 
281 // Alien Invaders
282 
283 static struct BurnRomInfo alinvadeRomDesc[] = {
284 	{ "alien28.708",	0x0400, 0xde376295, 1 | BRF_PRG | BRF_ESS }, //  0 m6502 Code
285 	{ "alien29.708",	0x0400, 0x20212977, 1 | BRF_PRG | BRF_ESS }, //  1
286 	{ "alien30.708",	0x0400, 0x734b691c, 1 | BRF_PRG | BRF_ESS }, //  2
287 	{ "alien31.708",	0x0400, 0x5a70535c, 1 | BRF_PRG | BRF_ESS }, //  3
288 	{ "alien32.708",	0x0400, 0x332dd234, 1 | BRF_PRG | BRF_ESS }, //  4
289 	{ "alien33.708",	0x0400, 0xe0d57fc7, 1 | BRF_PRG | BRF_ESS }, //  5
290 
291 	{ "prom",		0x0010, 0x00000000, 2 | BRF_NODUMP        }, //  6 Protection prom
292 };
293 
294 STD_ROM_PICK(alinvade)
295 STD_ROM_FN(alinvade)
296 
297 struct BurnDriver BurnDrvAlinvade = {
298 	"alinvade", NULL, NULL, NULL, "198?",
299 	"Alien Invaders\0", "preliminary sound", "Forbes?", "Miscellaneous",
300 	NULL, NULL, NULL, NULL,
301 	BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL | BDF_ORIENTATION_FLIPPED, 1, HARDWARE_MISC_PRE90S, GBF_VERSHOOT, 0,
302 	NULL, alinvadeRomInfo, alinvadeRomName, NULL, NULL, NULL, NULL, AlinvadeInputInfo, AlinvadeDIPInfo,
303 	DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 2,
304 	128, 128, 4, 3
305 };
306