1 // FinalBurn Neo Limenko Power System 2 hardware driver module
2 // Based on MAME driver by Pierpaolo Prazzoli, Tomasz Slanina
3 
4 #include "tiles_generic.h"
5 #include "e132xs_intf.h"
6 #include "mcs51.h"
7 #include "qs1000.h"
8 #include "msm6295.h"
9 #include "eeprom.h"
10 #include "burn_pal.h"
11 
12 static UINT8 *AllMem;
13 static UINT8 *AllRam;
14 static UINT8 *RamEnd;
15 static UINT8 *MemEnd;
16 static UINT8 *DrvMainROM;
17 static UINT8 *DrvBootROM;
18 static UINT8 *DrvQSROM;
19 static UINT8 *DrvGfxROM;
20 static UINT8 *DrvSndROM;
21 static UINT8 *DrvMainRAM;
22 static UINT8 *DrvFgRAM;
23 static UINT8 *DrvMdRAM;
24 static UINT8 *DrvBgRAM;
25 static UINT8 *DrvSprRAM;
26 static UINT8 *DrvRegRAM;
27 
28 static UINT8 DrvRecalc;
29 
30 static UINT32 *video_regs;
31 
32 static INT32 audiocpu_data[4];
33 static INT32 soundlatch;
34 static INT32 spriteram_bit;
35 static UINT32 prev_sprites_count;
36 
37 static UINT32 security_bit_config	= 0x00400000;
38 static UINT32 eeprom_bit_config		= 0x00800000;
39 static UINT32 spriteram_bit_config	= 0x80000000;
40 static INT32 sound_type;
41 static INT32 graphicsrom_len;
42 static UINT32 speedhack_address = 0xffffffff;
43 static UINT32 speedhack_pc = 0;
44 static INT32 cpu_clock;
45 
46 void limenko_draw_sprites();
47 
48 static UINT8 DrvJoy1[16];
49 static UINT8 DrvJoy2[16];
50 static UINT8 DrvJoy3[16];
51 static UINT8 DrvDips[1];
52 static UINT8 DrvReset;
53 static UINT16 DrvInputs[3];
54 
55 static struct BurnInputInfo LegendohInputList[] = {
56 	{"P1 Coin",			BIT_DIGITAL,	DrvJoy3 + 2,	"p1 coin"	},
57 	{"P1 Start",		BIT_DIGITAL,	DrvJoy3 + 0,	"p1 start"	},
58 	{"P1 Up",			BIT_DIGITAL,	DrvJoy1 + 0,	"p1 up"		},
59 	{"P1 Down",			BIT_DIGITAL,	DrvJoy1 + 1,	"p1 down"	},
60 	{"P1 Left",			BIT_DIGITAL,	DrvJoy1 + 2,	"p1 left"	},
61 	{"P1 Right",		BIT_DIGITAL,	DrvJoy1 + 3,	"p1 right"	},
62 	{"P1 Button 1",		BIT_DIGITAL,	DrvJoy1 + 4,	"p1 fire 1"	},
63 	{"P1 Button 2",		BIT_DIGITAL,	DrvJoy1 + 5,	"p1 fire 2"	},
64 	{"P1 Button 3",		BIT_DIGITAL,	DrvJoy1 + 6,	"p1 fire 3"	},
65 	{"P1 Button 4",		BIT_DIGITAL,	DrvJoy1 + 7,	"p1 fire 4"	},
66 
67 	{"P2 Coin",			BIT_DIGITAL,	DrvJoy3 + 3,	"p2 coin"	},
68 	{"P2 Start",		BIT_DIGITAL,	DrvJoy3 + 1,	"p2 start"	},
69 	{"P2 Up",			BIT_DIGITAL,	DrvJoy2 + 0,	"p2 up"		},
70 	{"P2 Down",			BIT_DIGITAL,	DrvJoy2 + 1,	"p2 down"	},
71 	{"P2 Left",			BIT_DIGITAL,	DrvJoy2 + 2,	"p2 left"	},
72 	{"P2 Right",		BIT_DIGITAL,	DrvJoy2 + 3,	"p2 right"	},
73 	{"P2 Button 1",		BIT_DIGITAL,	DrvJoy2 + 4,	"p2 fire 1"	},
74 	{"P2 Button 2",		BIT_DIGITAL,	DrvJoy2 + 5,	"p2 fire 2"	},
75 	{"P2 Button 3",		BIT_DIGITAL,	DrvJoy2 + 6,	"p2 fire 3"	},
76 	{"P2 Button 4",		BIT_DIGITAL,	DrvJoy2 + 7,	"p2 fire 4"	},
77 
78 	{"P3 Coin",			BIT_DIGITAL,	DrvJoy3 + 10,	"p3 coin"	},
79 	{"P3 Start",		BIT_DIGITAL,	DrvJoy3 + 8,	"p3 start"	},
80 	{"P3 Up",			BIT_DIGITAL,	DrvJoy1 + 8,	"p3 up"		},
81 	{"P3 Down",			BIT_DIGITAL,	DrvJoy1 + 9,	"p3 down"	},
82 	{"P3 Left",			BIT_DIGITAL,	DrvJoy1 + 10,	"p3 left"	},
83 	{"P3 Right",		BIT_DIGITAL,	DrvJoy1 + 11,	"p3 right"	},
84 	{"P3 Button 1",		BIT_DIGITAL,	DrvJoy1 + 12,	"p3 fire 1"	},
85 	{"P3 Button 2",		BIT_DIGITAL,	DrvJoy1 + 13,	"p3 fire 2"	},
86 	{"P3 Button 3",		BIT_DIGITAL,	DrvJoy1 + 14,	"p3 fire 3"	},
87 	{"P3 Button 4",		BIT_DIGITAL,	DrvJoy1 + 15,	"p3 fire 4"	},
88 
89 	{"P4 Coin",			BIT_DIGITAL,	DrvJoy3 + 11,	"p4 coin"	},
90 	{"P4 Start",		BIT_DIGITAL,	DrvJoy3 + 9,	"p4 start"	},
91 	{"P4 Up",			BIT_DIGITAL,	DrvJoy2 + 8,	"p4 up"		},
92 	{"P4 Down",			BIT_DIGITAL,	DrvJoy2 + 9,	"p4 down"	},
93 	{"P4 Left",			BIT_DIGITAL,	DrvJoy2 + 10,	"p4 left"	},
94 	{"P4 Right",		BIT_DIGITAL,	DrvJoy2 + 11,	"p4 right"	},
95 	{"P4 Button 1",		BIT_DIGITAL,	DrvJoy2 + 12,	"p4 fire 1"	},
96 	{"P4 Button 2",		BIT_DIGITAL,	DrvJoy2 + 13,	"p4 fire 2"	},
97 	{"P4 Button 3",		BIT_DIGITAL,	DrvJoy2 + 14,	"p4 fire 3"	},
98 	{"P4 Button 4",		BIT_DIGITAL,	DrvJoy2 + 15,	"p4 fire 4"	},
99 
100 	{"Reset",			BIT_DIGITAL,	&DrvReset,		"reset"		},
101 	{"Service",			BIT_DIGITAL,	DrvJoy3 + 4,	"service"	},
102 	{"Service Mode",	BIT_DIGITAL,	DrvJoy3 + 5,	"diag"		},
103 	{"Dip A",			BIT_DIPSWITCH,	DrvDips + 0,	"dip"		},
104 };
105 
106 STDINPUTINFO(Legendoh)
107 
108 static struct BurnInputInfo Sb2003InputList[] = {
109 	{"P1 Coin",			BIT_DIGITAL,	DrvJoy3 + 2,	"p1 coin"	},
110 	{"P1 Start",		BIT_DIGITAL,	DrvJoy3 + 0,	"p1 start"	},
111 	{"P1 Up",			BIT_DIGITAL,	DrvJoy1 + 0,	"p1 up"		},
112 	{"P1 Down",			BIT_DIGITAL,	DrvJoy1 + 1,	"p1 down"	},
113 	{"P1 Left",			BIT_DIGITAL,	DrvJoy1 + 2,	"p1 left"	},
114 	{"P1 Right",		BIT_DIGITAL,	DrvJoy1 + 3,	"p1 right"	},
115 	{"P1 Button 1",		BIT_DIGITAL,	DrvJoy1 + 4,	"p1 fire 1"	},
116 	{"P1 Button 2",		BIT_DIGITAL,	DrvJoy1 + 5,	"p1 fire 2"	},
117 	{"P1 Button 3",		BIT_DIGITAL,	DrvJoy1 + 6,	"p1 fire 3"	},
118 	{"P1 Button 4",		BIT_DIGITAL,	DrvJoy1 + 7,	"p1 fire 4"	},
119 
120 	{"P2 Coin",			BIT_DIGITAL,	DrvJoy3 + 3,	"p2 coin"	},
121 	{"P2 Start",		BIT_DIGITAL,	DrvJoy3 + 1,	"p2 start"	},
122 	{"P2 Up",			BIT_DIGITAL,	DrvJoy2 + 0,	"p2 up"		},
123 	{"P2 Down",			BIT_DIGITAL,	DrvJoy2 + 1,	"p2 down"	},
124 	{"P2 Left",			BIT_DIGITAL,	DrvJoy2 + 2,	"p2 left"	},
125 	{"P2 Right",		BIT_DIGITAL,	DrvJoy2 + 3,	"p2 right"	},
126 	{"P2 Button 1",		BIT_DIGITAL,	DrvJoy2 + 4,	"p2 fire 1"	},
127 	{"P2 Button 2",		BIT_DIGITAL,	DrvJoy2 + 5,	"p2 fire 2"	},
128 	{"P2 Button 3",		BIT_DIGITAL,	DrvJoy2 + 6,	"p2 fire 3"	},
129 	{"P2 Button 4",		BIT_DIGITAL,	DrvJoy2 + 7,	"p2 fire 4"	},
130 
131 	{"Reset",			BIT_DIGITAL,	&DrvReset,		"reset"		},
132 	{"Service",			BIT_DIGITAL,	DrvJoy3 + 4,	"service"	},
133 	{"Service Mode",	BIT_DIGITAL,	DrvJoy3 + 5,	"diag"		},
134 	{"Dip A",			BIT_DIPSWITCH,	DrvDips + 0,	"dip"		},
135 };
136 
137 STDINPUTINFO(Sb2003)
138 
139 static struct BurnInputInfo SpottyInputList[] = {
140 	{"P1 Coin",			BIT_DIGITAL,	DrvJoy3 + 2,	"p1 coin"	},
141 	{"P1 Start",		BIT_DIGITAL,	DrvJoy3 + 0,	"p1 start"	},
142 	{"P1 Up",			BIT_DIGITAL,	DrvJoy1 + 0,	"p1 up"		},
143 	{"P1 Down",			BIT_DIGITAL,	DrvJoy1 + 1,	"p1 down"	},
144 	{"P1 Left",			BIT_DIGITAL,	DrvJoy1 + 2,	"p1 left"	},
145 	{"P1 Right",		BIT_DIGITAL,	DrvJoy1 + 3,	"p1 right"	},
146 	{"P1 Button 1",		BIT_DIGITAL,	DrvJoy1 + 4,	"p1 fire 1"	},
147 	{"P1 Button 2",		BIT_DIGITAL,	DrvJoy1 + 5,	"p1 fire 2"	},
148 	{"P1 Button 3",		BIT_DIGITAL,	DrvJoy1 + 6,	"p1 fire 3"	},
149 	{"P1 Button 4",		BIT_DIGITAL,	DrvJoy2 + 4,	"p1 fire 4"	},
150 	{"P1 Button 5",		BIT_DIGITAL,	DrvJoy2 + 5,	"p1 fire 5"	},
151 	{"P1 Button 6",		BIT_DIGITAL,	DrvJoy2 + 6,	"p1 fire 6"	},
152 
153 	{"Reset",			BIT_DIGITAL,	&DrvReset,		"reset"		},
154 	{"Service Mode",	BIT_DIGITAL,	DrvJoy3 + 5,	"diag"		},
155 	{"Dip A",			BIT_DIPSWITCH,	DrvDips + 0,	"dip"		},
156 };
157 
158 STDINPUTINFO(Spotty)
159 
160 static struct BurnDIPInfo LegendohDIPList[]=
161 {
162 	{0x2b, 0xff, 0xff, 0x00, NULL				},
163 
164 	{0   , 0xfe, 0   ,    2, "Sound Enable"		},
165 	{0x2b, 0x01, 0x20, 0x20, "Off"				},
166 	{0x2b, 0x01, 0x20, 0x00, "On"				},
167 };
168 
169 STDDIPINFO(Legendoh)
170 
171 static struct BurnDIPInfo Sb2003DIPList[]=
172 {
173 	{0x17, 0xff, 0xff, 0x00, NULL				},
174 
175 	{0   , 0xfe, 0   ,    2, "Sound Enable"		},
176 	{0x17, 0x01, 0x20, 0x20, "Off"				},
177 	{0x17, 0x01, 0x20, 0x00, "On"				},
178 };
179 
180 STDDIPINFO(Sb2003)
181 
182 static struct BurnDIPInfo SpottyDIPList[]=
183 {
184 	{0x0e, 0xff, 0xff, 0x20, NULL				},
185 
186 	{0   , 0xfe, 0   ,    2, "Demo Sounds"		},
187 	{0x0e, 0x01, 0x20, 0x00, "Off"				},
188 	{0x0e, 0x01, 0x20, 0x20, "On"				},
189 };
190 
STDDIPINFO(Spotty)191 STDDIPINFO(Spotty)
192 
193 static void sprite_buffer()
194 {
195 	spriteram_bit ^= 1;
196 	limenko_draw_sprites();
197 	prev_sprites_count = (BURN_ENDIAN_SWAP_INT32(video_regs[0]) >> 0) & 0x1ff; // reg0
198 }
199 
limenko_write_long(UINT32 address,UINT32 data)200 static void limenko_write_long(UINT32 address, UINT32 data)
201 {
202 	switch (address)
203 	{
204 		case 0x8003e000:
205 			sprite_buffer();
206 		return;
207 	}
208 }
209 
limenko_write_word(UINT32 address,UINT16 data)210 static void limenko_write_word(UINT32 address, UINT16 data)
211 {
212 	switch (address & ~3)
213 	{
214 		case 0x8003e000:
215 			sprite_buffer();
216 		return;
217 	}
218 }
219 
limenko_write_byte(UINT32 address,UINT8 data)220 static void limenko_write_byte(UINT32 address, UINT8 data)
221 {
222 	switch (address & ~3)
223 	{
224 		case 0x8003e000:
225 			sprite_buffer();
226 		return;
227 	}
228 }
229 
speedhack_callback(UINT32 address)230 static inline void speedhack_callback(UINT32 address)
231 {
232 	if (address == speedhack_address) {
233 		if (E132XSGetPC(0) == speedhack_pc) {
234 			E132XSBurnCycles(50);
235 		}
236 	}
237 }
238 
limenko_read_long(UINT32 address)239 static UINT32 limenko_read_long(UINT32 address)
240 {
241 	if (address < 0x200000) {
242 		speedhack_callback(address);
243 		UINT32 ret = BURN_ENDIAN_SWAP_INT32(*((UINT32*)(DrvMainRAM + address)));
244 		return (ret << 16) | (ret >> 16);
245 	}
246 
247 	return 0;
248 }
249 
limenko_read_word(UINT32 address)250 static UINT16 limenko_read_word(UINT32 address)
251 {
252 	if (address < 0x200000) {
253 		speedhack_callback(address);
254 		return BURN_ENDIAN_SWAP_INT16(*((UINT16*)(DrvMainRAM + address)));
255 	}
256 
257 	return 0;
258 }
259 
limenko_read_byte(UINT32 address)260 static UINT8 limenko_read_byte(UINT32 address)
261 {
262 	if (address < 0x200000) {
263 		speedhack_callback(address);
264 		return DrvMainRAM[address^1];
265 	}
266 
267 	return 0;
268 }
269 
DrvMCUSync()270 static inline void DrvMCUSync()
271 {
272 	INT32 todo = ((double)E132XSTotalCycles() * (24000000/12) / 80000000) - mcs51TotalCycles();
273 
274 	if (todo > 0) mcs51Run(todo);
275 }
276 
limenko_io_write(UINT32 address,UINT32 data)277 static void limenko_io_write(UINT32 address, UINT32 data)
278 {
279 	switch (address)
280 	{
281 		case 0x4000:
282 			// coin counter / hopper?
283 		return;
284 
285 		case 0x4800:
286 			EEPROMWriteBit((data & 0x40000));
287 			EEPROMSetCSLine((data & 0x10000) ? EEPROM_CLEAR_LINE : EEPROM_ASSERT_LINE );
288 			EEPROMSetClockLine((data & 0x20000) ? EEPROM_ASSERT_LINE : EEPROM_CLEAR_LINE );
289 		return;
290 
291 		case 0x5000:
292 			soundlatch = (data >> 16) & 0xff;
293 			switch (sound_type)
294 			{
295 				case 0: DrvMCUSync(); qs1000_set_irq(1); break;
296 				case 1: soundlatch |= 0x100; break; // spotty
297 			}
298 		return;
299 	}
300 }
301 
limenko_io_read(UINT32 address)302 static UINT32 limenko_io_read(UINT32 address)
303 {
304 	switch (address)
305 	{
306 		case 0x0000:
307 			return (DrvInputs[0] << 16) | 0xffff;
308 
309 		case 0x0800:
310 			return (DrvInputs[1] << 16) | 0xffff;
311 
312 		case 0x1000:
313 		{
314 			UINT32 ret = (DrvInputs[2] << 16) | 0xffff;
315 
316 			ret &= security_bit_config ^ 0xffffffff;
317 			ret &= eeprom_bit_config ^ 0xffffffff;
318 			ret &= 0x20000000 ^ 0xffffffff;
319 			ret &= spriteram_bit_config ^ 0xffffffff;
320 
321 			if (spriteram_bit) ret |= spriteram_bit_config;
322 			if (EEPROMRead()) ret |= eeprom_bit_config;
323 			ret |= (DrvDips[0] & 0x20) << 24;
324 
325 			return ret;
326 		}
327 	}
328 
329 	return 0;
330 }
331 
tilemap_callback(bg)332 static tilemap_callback( bg )
333 {
334 	UINT32 attr = BURN_ENDIAN_SWAP_INT32(*((UINT32*)(DrvBgRAM + offs * 4)));
335 	attr = (attr << 16) | (attr >> 16);
336 
337 	TILE_SET_INFO(0, attr & 0x7ffff, attr >> 28, 0);
338 }
339 
tilemap_callback(md)340 static tilemap_callback( md )
341 {
342 	UINT32 attr = BURN_ENDIAN_SWAP_INT32(*((UINT32*)(DrvMdRAM + offs * 4)));
343 	attr = (attr << 16) | (attr >> 16);
344 
345 	TILE_SET_INFO(0, attr & 0x7ffff, attr >> 28, 0);
346 }
347 
tilemap_callback(fg)348 static tilemap_callback( fg )
349 {
350 	UINT32 attr = BURN_ENDIAN_SWAP_INT32(*((UINT32*)(DrvFgRAM + offs * 4)));
351 	attr = (attr << 16) | (attr >> 16);
352 
353 	TILE_SET_INFO(0, attr & 0x7ffff, attr >> 28, 0);
354 }
355 
qs1000_p3_write(UINT8 data)356 static void qs1000_p3_write(UINT8 data)
357 {
358 	qs1000_set_bankedrom(DrvQSROM + (data & 7) * 0x10000);
359 
360 	if (~data & 0x20)
361 		qs1000_set_irq(0);
362 }
363 
spotty_sound_write(INT32 port,UINT8 data)364 static void spotty_sound_write(INT32 port, UINT8 data)
365 {
366 	switch (port)
367 	{
368 		case MCS51_PORT_P1:
369 			audiocpu_data[0] = data;
370 		return;
371 
372 		case MCS51_PORT_P3:
373 		{
374 			if ((audiocpu_data[3] & 0x01) == 0x01 && (data & 0x81) == 0) audiocpu_data[0] = MSM6295Read(0);
375 			if ((audiocpu_data[3] & 0x02) == 0x02 && (data & 0x82) == 0) MSM6295Write(0,  audiocpu_data[0]);
376 			if ((audiocpu_data[3] & 0x08) == 0x08 && (data & 0x08) == 0) { audiocpu_data[0] = soundlatch; soundlatch &= 0xff; }
377 			audiocpu_data[3] = data;
378 		}
379 		return;
380 	}
381 }
382 
spotty_sound_read(INT32 port)383 static UINT8 spotty_sound_read(INT32 port)
384 {
385 	switch (port)
386 	{
387 		case MCS51_PORT_P1:
388 			return audiocpu_data[0];
389 
390 		case MCS51_PORT_P3:
391 			return (soundlatch & 0x100) ? 0 : 4;
392 	}
393 
394 	return 0;
395 }
396 
qs1000_p1_read()397 static UINT8 qs1000_p1_read()
398 {
399 	return soundlatch;
400 }
401 
DrvDoReset()402 static INT32 DrvDoReset()
403 {
404 	memset (AllRam, 0, RamEnd - AllRam);
405 
406 	E132XSOpen(0);
407 	E132XSReset();
408 	E132XSClose();
409 
410 	switch (sound_type)
411 	{
412 		case 0: qs1000_reset(); break;
413 
414 		case 1: // spotty
415 		{
416 			mcs51Open(0);
417 			mcs51_reset();
418 			mcs51Close();
419 			MSM6295Reset();
420 		}
421 		break;
422 	}
423 
424 	EEPROMReset();
425 
426 	soundlatch = 0;
427 	spriteram_bit = 1;
428 	prev_sprites_count = 0;
429 	memset (audiocpu_data, 0, sizeof(audiocpu_data)); // spotty
430 
431 	return 0;
432 }
433 
MemIndex()434 static INT32 MemIndex()
435 {
436 	UINT8 *Next; Next = AllMem;
437 
438 	DrvMainROM	= Next; Next += 0x400000;
439 	DrvBootROM	= Next; Next += 0x200000;
440 
441 	DrvQSROM	= Next; Next += 0x080000;
442 
443 	DrvGfxROM	= Next; Next += graphicsrom_len;
444 
445 	MSM6295ROM	= Next;
446 	DrvSndROM	= Next; Next += 0x400000;
447 
448 	BurnPalette	= (UINT32*)Next; Next += 0x1000 * sizeof(UINT32);
449 
450 	AllRam		= Next;
451 
452 	DrvMainRAM	= Next; Next += 0x200000;
453 	DrvFgRAM	= Next; Next += 0x008000;
454 	DrvMdRAM	= Next; Next += 0x008000;
455 	DrvBgRAM	= Next; Next += 0x008000;
456 	DrvSprRAM	= Next; Next += 0x002000;
457 	BurnPalRAM	= Next; Next += 0x002000;
458 	DrvRegRAM	= Next; Next += 0x002000;
459 
460 	video_regs = (UINT32*)(DrvRegRAM + 0x1fec);
461 
462 	RamEnd		= Next;
463 
464 	MemEnd		= Next;
465 
466 	return 0;
467 }
468 
LimenkoCommonInit(INT32 cputype,INT32 cpuclock,INT32 (* pLoadRoms)(),INT32 graphics_size,INT32 soundtype)469 static INT32 LimenkoCommonInit(INT32 cputype, INT32 cpuclock, INT32 (*pLoadRoms)(), INT32 graphics_size, INT32 soundtype)
470 {
471 	graphicsrom_len = graphics_size;
472 
473 	BurnAllocMemIndex();
474 
475 	memset (DrvMainROM, 0xff, 0x400000);
476 	memset (DrvQSROM, 0xff, 0x80000);
477 
478 	if (pLoadRoms) {
479 		if (pLoadRoms()) return 1;
480 	}
481 
482 	cpu_clock = cpuclock;
483 
484 	E132XSInit(0, cputype, cpu_clock);
485 	E132XSOpen(0);
486 	E132XSMapMemory(DrvMainRAM,			0x00000000, 0x001fffff, MAP_RAM);
487 	E132XSMapMemory(DrvMainROM,			0x40000000, 0x403fffff, MAP_ROM);
488 	E132XSMapMemory(DrvFgRAM,			0x80000000, 0x80007fff, MAP_RAM);
489 	E132XSMapMemory(DrvMdRAM,			0x80008000, 0x8000ffff, MAP_RAM);
490 	E132XSMapMemory(DrvBgRAM,			0x80010000, 0x80017fff, MAP_RAM);
491 	E132XSMapMemory(DrvSprRAM,			0x80018000, 0x80019fff, MAP_RAM);
492 	E132XSMapMemory(BurnPalRAM,			0x8001c000, 0x8001dfff, MAP_RAM);
493 	E132XSMapMemory(DrvRegRAM,			0x8001e000, 0x8001ffff, MAP_RAM);
494 	E132XSMapMemory(DrvBootROM,			0xffe00000, 0xffffffff, MAP_ROM);
495 	E132XSSetWriteLongHandler(limenko_write_long);
496 	E132XSSetWriteWordHandler(limenko_write_word);
497 	E132XSSetWriteByteHandler(limenko_write_byte);
498 	E132XSSetIOWriteHandler(limenko_io_write);
499 	E132XSSetIOReadHandler(limenko_io_read);
500 
501 	if (speedhack_pc)
502 	{
503 		E132XSMapMemory(NULL,			speedhack_address & ~0xfff, speedhack_address | 0xfff, MAP_ROM);
504 		E132XSSetReadLongHandler(limenko_read_long);
505 		E132XSSetReadWordHandler(limenko_read_word);
506 		E132XSSetReadByteHandler(limenko_read_byte);
507 	}
508 	E132XSClose();
509 
510 	EEPROMInit(&eeprom_interface_93C46);
511 
512 	switch(soundtype)
513 	{
514 		case 0:
515 		{
516 			qs1000_init(DrvQSROM, DrvSndROM, 0x400000);
517 			qs1000_set_write_handler(3, qs1000_p3_write);
518 			qs1000_set_read_handler(1, qs1000_p1_read);
519 			qs1000_set_volume(3.00);
520 
521 			sound_type = 0;
522 		}
523 		break;
524 
525 		case 1:
526 		{
527 			i80c51_init();
528 			mcs51Open(0);
529 			mcs51_set_program_data(DrvQSROM); // not really qs!
530 			mcs51_set_write_handler(spotty_sound_write);
531 			mcs51_set_read_handler(spotty_sound_read);
532 			mcs51Close();
533 
534 			MSM6295Init(0, 1000000 / MSM6295_PIN7_HIGH, 0);
535 			MSM6295SetRoute(0, 1.00, BURN_SND_ROUTE_BOTH);
536 
537 			sound_type = 1;
538 		}
539 		break;
540 	}
541 
542 	GenericTilesInit();
543 	GenericTilemapInit(0, TILEMAP_SCAN_ROWS, bg_map_callback, 8, 8, 128, 64);
544 	GenericTilemapInit(1, TILEMAP_SCAN_ROWS, md_map_callback, 8, 8, 128, 64);
545 	GenericTilemapInit(2, TILEMAP_SCAN_ROWS, fg_map_callback, 8, 8, 128, 64);
546 	GenericTilemapSetGfx(0, DrvGfxROM, 8, 8, 8, graphicsrom_len, 0, 0xf);
547 	GenericTilemapSetTransparent(1, 0);
548 	GenericTilemapSetTransparent(2, 0);
549 	BurnBitmapAllocate(1, 512, 512, true);
550 
551 	DrvDoReset();
552 
553 	return 0;
554 }
555 
LegendohLoadCallback()556 static INT32 LegendohLoadCallback()
557 {
558 	INT32 k = 0;
559 	if (BurnLoadRom(DrvBootROM + 0x0180000, k++, 1)) return 1;
560 
561 	if (BurnLoadRom(DrvMainROM + 0x0000000, k++, 1)) return 1;
562 	if (BurnLoadRom(DrvMainROM + 0x0200000, k++, 1)) return 1;
563 
564 	if (BurnLoadRom(DrvGfxROM  + 0x0000000, k++, 4)) return 1;
565 	if (BurnLoadRom(DrvGfxROM  + 0x0000001, k++, 4)) return 1;
566 	if (BurnLoadRom(DrvGfxROM  + 0x0000002, k++, 4)) return 1;
567 	if (BurnLoadRom(DrvGfxROM  + 0x0000003, k++, 4)) return 1;
568 	if (BurnLoadRom(DrvGfxROM  + 0x0800000, k++, 4)) return 1;
569 	if (BurnLoadRom(DrvGfxROM  + 0x0800001, k++, 4)) return 1;
570 	if (BurnLoadRom(DrvGfxROM  + 0x0800002, k++, 4)) return 1;
571 	if (BurnLoadRom(DrvGfxROM  + 0x0800003, k++, 4)) return 1;
572 	if (BurnLoadRom(DrvGfxROM  + 0x1000000, k++, 4)) return 1;
573 	if (BurnLoadRom(DrvGfxROM  + 0x1000001, k++, 4)) return 1;
574 	if (BurnLoadRom(DrvGfxROM  + 0x1000002, k++, 4)) return 1;
575 	if (BurnLoadRom(DrvGfxROM  + 0x1000003, k++, 4)) return 1;
576 
577 	if (BurnLoadRom(DrvQSROM   + 0x0000000, k++, 1)) return 1;
578 
579 	if (BurnLoadRom(DrvSndROM  + 0x0000000, k++, 1)) return 1;
580 	if (BurnLoadRom(DrvSndROM  + 0x0080000, k++, 1)) return 1;
581 	if (BurnLoadRom(DrvSndROM  + 0x0200000, k++, 1)) return 1;
582 
583 	security_bit_config	= ~0 & 0x00400000; // = bit is high
584 
585 	return 0;
586 }
587 
DynabombLoadCallback()588 static INT32 DynabombLoadCallback()
589 {
590 	INT32 k = 0;
591 	if (BurnLoadRom(DrvBootROM + 0x0000000, k++, 1)) return 1;
592 
593 	if (BurnLoadRom(DrvMainROM + 0x0000000, k++, 1)) return 1;
594 
595 	if (BurnLoadRom(DrvQSROM   + 0x0000000, k++, 1)) return 1;
596 
597 	if (BurnLoadRom(DrvGfxROM  + 0x0000000, k++, 4)) return 1;
598 	if (BurnLoadRom(DrvGfxROM  + 0x0000001, k++, 4)) return 1;
599 	if (BurnLoadRom(DrvGfxROM  + 0x0000002, k++, 4)) return 1;
600 	if (BurnLoadRom(DrvGfxROM  + 0x0000003, k++, 4)) return 1;
601 
602 	if (BurnLoadRom(DrvSndROM  + 0x0000000, k++, 1)) return 1;
603 	if (BurnLoadRom(DrvSndROM  + 0x0080000, k++, 1)) return 1;
604 	if (BurnLoadRom(DrvSndROM  + 0x0200000, k++, 1)) return 1;
605 
606 	security_bit_config	= 0 & 0x00400000; // = bit is low
607 
608 	return 0;
609 }
610 
Sb2003LoadCallback()611 static INT32 Sb2003LoadCallback()
612 {
613 	INT32 k = 0;
614 	if (BurnLoadRom(DrvBootROM + 0x0000000, k++, 1)) return 1;
615 
616 	if (BurnLoadRom(DrvQSROM   + 0x0000000, k++, 1)) return 1;
617 
618 	if (BurnLoadRom(DrvGfxROM  + 0x0000000, k++, 4)) return 1;
619 	if (BurnLoadRom(DrvGfxROM  + 0x0000001, k++, 4)) return 1;
620 	if (BurnLoadRom(DrvGfxROM  + 0x0000002, k++, 4)) return 1;
621 	if (BurnLoadRom(DrvGfxROM  + 0x0000003, k++, 4)) return 1;
622 
623 	if (BurnLoadRom(DrvSndROM  + 0x0000000, k++, 1)) return 1;
624 	if (BurnLoadRom(DrvSndROM  + 0x0200000, k++, 1)) return 1;
625 
626 	security_bit_config	= 0 & 0x00400000; // = bit is low
627 
628 	return 0;
629 }
630 
SpottyLoadCallback()631 static INT32 SpottyLoadCallback()
632 {
633 	INT32 k = 0;
634 	if (BurnLoadRom(DrvBootROM + 0x0180000, k++, 1)) return 1;
635 
636 	if (BurnLoadRom(DrvQSROM   + 0x0000000, k++, 1)) return 1; // not qs
637 
638 	if (BurnLoadRom(DrvGfxROM + 0x0000000, k++, 4)) return 1;
639 	if (BurnLoadRom(DrvGfxROM + 0x0000002, k++, 4)) return 1;
640 
641 	if (BurnLoadRom(DrvSndROM  + 0x0000000, k++, 1)) return 1;
642 
643 	{
644 		for (INT32 x = 0; x < 0x200000; x += 2)
645 		{
646 			DrvGfxROM[x+1] = (DrvGfxROM[x]&0xf0) >> 4;
647 			DrvGfxROM[x+0] = (DrvGfxROM[x]&0x0f) >> 0;
648 		}
649 	}
650 
651 	security_bit_config		= 0 & 0x00400000; // = bit is low
652 	eeprom_bit_config		= 0x00800000;
653 	spriteram_bit_config	= 0x00080000; // different
654 
655 	return 0;
656 }
657 
DrvExit()658 static INT32 DrvExit()
659 {
660 	GenericTilesExit();
661 
662 	E132XSExit();
663 	EEPROMExit();
664 
665 	switch (sound_type)
666 	{
667 		case 0: qs1000_exit(); break;
668 		case 1: // spotty
669 		{
670 			mcs51_exit();
671 			MSM6295Exit();
672 		}
673 		break;
674 	}
675 
676 	BurnFreeMemIndex();
677 
678 	security_bit_config		= 0x00400000;
679 	eeprom_bit_config		= 0x00800000;
680 	spriteram_bit_config	= 0x80000000;
681 	sound_type = 0;
682 
683 	speedhack_address = 0xffffffff;
684 	speedhack_pc = 0;
685 
686 	MSM6295ROM = NULL;
687 
688 	return 0;
689 }
690 
draw_single_sprite(UINT8 width,UINT8 height,UINT32 code,UINT32 color,bool flipx,bool flipy,int offsx,int offsy,UINT8 transparent_color,UINT8 priority)691 static void draw_single_sprite(UINT8 width, UINT8 height, UINT32 code, UINT32 color,bool flipx,bool flipy,int offsx,int offsy, UINT8 transparent_color, UINT8 priority)
692 {
693 	UINT16 pal = color << 8;
694 	UINT8 *source_base = DrvGfxROM + code;
695 
696 	int xinc = flipx ? -1 : 1;
697 	int yinc = flipy ? -1 : 1;
698 
699 	int x_index_base = flipx ? width - 1 : 0;
700 	int y_index = flipy ? height - 1 : 0;
701 
702 	int sx = offsx;
703 	int sy = offsy;
704 
705 	int ex = sx + width;
706 	int ey = sy + height;
707 
708 	if (sx < 0)
709 	{
710 		int pixels = 0 - sx;
711 		sx += pixels;
712 		x_index_base += xinc * pixels;
713 	}
714 
715 	if (sy < 0)
716 	{
717 		int pixels = 0 - sy;
718 		sy += pixels;
719 		y_index += yinc * pixels;
720 	}
721 
722 	if (ex > 512) ey = 512;
723 	if (ex > 512) ex = 512;
724 
725 	if (ex > sx)
726 	{
727 		for (int y = sy; y < ey; y++)
728 		{
729 			const UINT8 *source = source_base + y_index * width;
730 			UINT16 *dest = BurnBitmapGetPosition(1, 0, y);
731 			UINT8 *pri = BurnBitmapGetPrimapPosition(1, 0, y);
732 			int x_index = x_index_base;
733 			for (int x = sx; x < ex; x++)
734 			{
735 				const UINT8 c = source[x_index];
736 				if (c != transparent_color)
737 				{
738 						if (pri[x] < priority)
739 						{
740 							dest[x] = BURN_ENDIAN_SWAP_INT16(pal + c);
741 							pri[x] = priority;
742 						}
743 				}
744 				x_index += xinc;
745 			}
746 			y_index += yinc;
747 		}
748 	}
749 }
750 
limenko_draw_sprites()751 void limenko_draw_sprites()
752 {
753 	BurnBitmapFill(1, 0);
754 	BurnBitmapPrimapClear(1);
755 
756 	UINT32 *sprites = (UINT32*)(DrvSprRAM + (0x1000  * spriteram_bit));
757 
758 	for (UINT32 i = 0; i <= prev_sprites_count * 2; i += 2)
759 	{
760 		UINT32 sprites0 = BURN_ENDIAN_SWAP_INT32(sprites[i + 0]);
761 		UINT32 sprites1 = BURN_ENDIAN_SWAP_INT32(sprites[i + 1]);
762 
763 		sprites0 = (sprites0 << 16) | (sprites0 >> 16);
764 		sprites1 = (sprites1 << 16) | (sprites1 >> 16);
765 
766 		if (~sprites0 & 0x80000000) continue;
767 
768 		int x      =  ((sprites0 & 0x01ff0000) >> 16);
769 		int width  = (((sprites0 & 0x0e000000) >> 25) + 1) * 8;
770 		bool flipx =    sprites0 & 0x10000000;
771 		int y      =    sprites0 & 0x000001ff;
772 		int height = (((sprites0 & 0x00000e00) >> 9) + 1) * 8;
773 		bool flipy =    sprites0 & 0x00001000;
774 		UINT32 code=   (sprites1 & 0x0007ffff) << 6;
775 		UINT32 color=  (sprites1 & 0xf0000000) >> 28;
776 
777 		int pri = 0;
778 		if (sprites1 & 0x04000000)
779 		{
780 			pri = 1;
781 		}
782 		else
783 		{
784 			pri = 2;
785 		}
786 
787 		/* Bounds checking */
788 		if ((code + (width * height)) > (UINT32)graphicsrom_len)
789 			continue;
790 
791 		draw_single_sprite(width,height,code,color,flipx,flipy,x,y,0,pri);
792 
793 		// wrap around x
794 		draw_single_sprite(width,height,code,color,flipx,flipy,x-512,y,0,pri);
795 
796 		// wrap around y
797 		draw_single_sprite(width,height,code,color,flipx,flipy,x,y-512,0,pri);
798 
799 		// wrap around x and y
800 		draw_single_sprite(width,height,code,color,flipx,flipy,x-512,y-512,0,pri);
801 	}
802 }
803 
copy_sprites()804 static void copy_sprites()
805 {
806 	for (INT32 y = 0; y < nScreenHeight; y++)
807 	{
808 		UINT16 *dest = BurnBitmapGetPosition(0, 0, y);
809 		UINT16 *source = BurnBitmapGetPosition(1, 0, y);
810 		UINT8 *dest_pri = BurnBitmapGetPrimapPosition(0, 0, y);
811 		UINT8 *source_pri = BurnBitmapGetPrimapPosition(1, 0, y);
812 
813 		for (INT32 x = 0; x < nScreenWidth; x++)
814 		{
815 			if (source[x] != 0)
816 			{
817 				if (dest_pri[x] < source_pri[x])
818 					dest[x] = BURN_ENDIAN_SWAP_INT16(source[x]);
819 			}
820 		}
821 	}
822 }
823 
DrvDraw()824 static INT32 DrvDraw()
825 {
826 	if (DrvRecalc) {
827 		BurnPaletteUpdate_xBBBBBGGGGGRRRRR();
828 		DrvRecalc = 1; // force update
829 	}
830 
831 	GenericTilemapSetEnable(0, (BURN_ENDIAN_SWAP_INT32(video_regs[0]) >> 16) & 0x04);
832 	GenericTilemapSetEnable(1, (BURN_ENDIAN_SWAP_INT32(video_regs[0]) >> 16) & 0x02);
833 	GenericTilemapSetEnable(2, (BURN_ENDIAN_SWAP_INT32(video_regs[0]) >> 16) & 0x01);
834 
835 	GenericTilemapSetScrollX(0, BURN_ENDIAN_SWAP_INT32(video_regs[3]) >> 0);
836 	GenericTilemapSetScrollX(1, BURN_ENDIAN_SWAP_INT32(video_regs[2]) >> 0);
837 	GenericTilemapSetScrollX(2, BURN_ENDIAN_SWAP_INT32(video_regs[1]) >> 0);
838 	GenericTilemapSetScrollY(0, BURN_ENDIAN_SWAP_INT32(video_regs[3]) >> 16);
839 	GenericTilemapSetScrollY(1, BURN_ENDIAN_SWAP_INT32(video_regs[2]) >> 16);
840 	GenericTilemapSetScrollY(2, BURN_ENDIAN_SWAP_INT32(video_regs[1]) >> 16);
841 
842 	BurnTransferClear();
843 
844 	if (nBurnLayer & 1) GenericTilemapDraw(0, pTransDraw, 0);
845 	if (nBurnLayer & 2) GenericTilemapDraw(1, pTransDraw, 0);
846 	if (nBurnLayer & 4) GenericTilemapDraw(2, pTransDraw, 1);
847 
848 	if ((BURN_ENDIAN_SWAP_INT32(video_regs[0]) >> 16) & 0x08)
849 		if (nSpriteEnable & 1) copy_sprites();
850 
851 	BurnTransferCopy(BurnPalette);
852 
853 	return 0;
854 }
855 
DrvFrame()856 static INT32 DrvFrame()
857 {
858 	if (DrvReset) {
859 		DrvDoReset();
860 	}
861 
862 	E132XSNewFrame();
863 	mcs51NewFrame();
864 
865 	{
866 		memset (DrvInputs, 0xff, sizeof(DrvInputs));
867 
868 		for (INT32 i = 0; i < 16; i++) {
869 			DrvInputs[0] ^= (DrvJoy1[i] & 1) << i;
870 			DrvInputs[1] ^= (DrvJoy2[i] & 1) << i;
871 			DrvInputs[2] ^= (DrvJoy3[i] & 1) << i;
872 		}
873 	}
874 
875 	INT32 nInterleave = 10;
876 	INT32 nCyclesTotal[2] = { cpu_clock / 60, (sound_type ? 4000000 : 2000000) / 60 };
877 	INT32 nCyclesDone[2] = { 0, 0 };
878 
879 	E132XSOpen(0);
880 	mcs51Open(0);
881 
882 	for (INT32 i = 0; i < nInterleave; i++)
883 	{
884 		CPU_RUN(0, E132XS);
885 		if (i == (nInterleave - 1)) E132XSSetIRQLine(0, CPU_IRQSTATUS_HOLD);
886 
887 		CPU_RUN_SYNCINT(1, mcs51);
888 	}
889 
890 	if (pBurnSoundOut) {
891 		switch (sound_type)
892 		{
893 			case 0: qs1000_update(pBurnSoundOut, nBurnSoundLen); break;
894 			case 1: MSM6295Render(pBurnSoundOut, nBurnSoundLen); break;
895 		}
896 	}
897 
898 	mcs51Close();
899 	E132XSClose();
900 
901 	if (pBurnDraw) {
902 		BurnDrvRedraw();
903 	}
904 
905 	return 0;
906 }
907 
DrvScan(INT32 nAction,INT32 * pnMin)908 static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
909 {
910 	struct BurnArea ba;
911 
912 	if (pnMin != NULL) {
913 		*pnMin = 0x029698;
914 	}
915 
916 	if (nAction & ACB_MEMORY_RAM) {
917 		memset(&ba, 0, sizeof(ba));
918 		ba.Data	  = AllRam;
919 		ba.nLen	  = RamEnd-AllRam;
920 		ba.szName = "All Ram";
921 		BurnAcb(&ba);
922 	}
923 
924 	if (nAction & ACB_DRIVER_DATA) {
925 		E132XSScan(nAction);
926 		mcs51_scan(nAction);
927 
928 		switch (sound_type)
929 		{
930 			case 0: qs1000_scan(nAction, pnMin); break;
931 			case 1: MSM6295Scan(nAction, pnMin); break;
932 		}
933 
934 		SCAN_VAR(audiocpu_data);
935 		SCAN_VAR(soundlatch);
936 		SCAN_VAR(spriteram_bit);
937 		SCAN_VAR(prev_sprites_count);
938 	}
939 
940 	if (nAction & ACB_NVRAM) {
941 		EEPROMScan(nAction, pnMin);
942 	}
943 
944 	return 0;
945 }
946 
947 
948 // Dynamite Bomber (Korea, Rev 1.5)
949 
950 static struct BurnRomInfo dynabombRomDesc[] = {
951 	{ "rom.u6",			0x200000, 0x457e015d, 1 | BRF_PRG | BRF_ESS }, //  0 Hyperstone Boot ROM
952 
953 	{ "rom.u5",			0x200000, 0x7e837adf, 2 | BRF_PRG | BRF_ESS }, //  1 Hyperstone Main ROM
954 
955 	{ "rom.u16",		0x020000, 0xf66d7e4d, 3 | BRF_PRG | BRF_ESS }, //  2 qs1000:cpu
956 
957 	{ "rom.u1",			0x200000, 0xbf33eff6, 4 | BRF_GRA },           //  3 Graphics
958 	{ "rom.u2",			0x200000, 0x790bbcd5, 4 | BRF_GRA },           //  4
959 	{ "rom.u3",			0x200000, 0xec094b12, 4 | BRF_GRA },           //  5
960 	{ "rom.u4",			0x200000, 0x88b24e3c, 4 | BRF_GRA },           //  6
961 
962 	{ "rom.u18",		0x080000, 0x50d76732, 5 | BRF_SND },           //  7 QS1000 Samples
963 	{ "rom.u17",		0x080000, 0x20f2417c, 5 | BRF_SND },           //  8
964 	{ "qs1003.u4",		0x200000, 0x19e4b469, 5 | BRF_SND },           //  9
965 };
966 
967 STD_ROM_PICK(dynabomb)
STD_ROM_FN(dynabomb)968 STD_ROM_FN(dynabomb)
969 
970 static INT32 DynabombInit()
971 {
972 	speedhack_address = 0xe2784;
973 	speedhack_pc = 0xc25b8;
974 
975 	security_bit_config		= 0x00400000 & 0; // low
976 	eeprom_bit_config		= 0x00800000;
977 	spriteram_bit_config	= 0x80000000;
978 
979 	return LimenkoCommonInit(TYPE_E132XN, 80000000, DynabombLoadCallback, 0x800000, 0);
980 }
981 
982 struct BurnDriver BurnDrvDynabomb = {
983 	"dynabomb", NULL, NULL, NULL, "2000",
984 	"Dynamite Bomber (Korea, Rev 1.5)\0", NULL, "Limenko", "Miscellaneous",
985 	NULL, NULL, NULL, NULL,
986 	BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_MAZE, 0,
987 	NULL, dynabombRomInfo, dynabombRomName, NULL, NULL, NULL, NULL, Sb2003InputInfo, Sb2003DIPInfo,
988 	DynabombInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000,
989 	384, 240, 4, 3
990 };
991 
992 
993 // Super Bubble 2003 (World, Ver 1.0)
994 
995 static struct BurnRomInfo sb2003RomDesc[] = {
996 	{ "sb2003_05.u6",	0x200000, 0x8aec4554, 1 | BRF_PRG | BRF_ESS }, //  0 Hyperstone Boot ROM
997 
998 	{ "07.u16",			0x020000, 0x78acc607, 3 | BRF_PRG | BRF_ESS }, //  1 QS1000 Code
999 
1000 	{ "01.u1",			0x200000, 0xd2c7091a, 4 | BRF_GRA },           //  2 Graphics
1001 	{ "02.u2",			0x200000, 0xa0734195, 4 | BRF_GRA },           //  3
1002 	{ "03.u3",			0x200000, 0x0f020280, 4 | BRF_GRA },           //  4
1003 	{ "04.u4",			0x200000, 0xfc2222b9, 4 | BRF_GRA },           //  5
1004 
1005 	{ "06.u18",			0x200000, 0xb6ad0d32, 5 | BRF_SND },           //  6 QS1000 Samples
1006 	{ "qs1003.u4",		0x200000, 0x19e4b469, 5 | BRF_SND },           //  7
1007 };
1008 
1009 STD_ROM_PICK(sb2003)
STD_ROM_FN(sb2003)1010 STD_ROM_FN(sb2003)
1011 
1012 static INT32 Sb2003Init()
1013 {
1014 	speedhack_address = 0x135800;
1015 	speedhack_pc = 0x26da4;
1016 
1017 	security_bit_config		= 0x00400000 & 0; // low
1018 	eeprom_bit_config		= 0x00800000;
1019 	spriteram_bit_config	= 0x80000000;
1020 
1021 	return LimenkoCommonInit(TYPE_E132XN, 80000000, Sb2003LoadCallback, 0x800000, 0);
1022 }
1023 
1024 struct BurnDriver BurnDrvSb2003 = {
1025 	"sb2003", NULL, NULL, NULL, "2003",
1026 	"Super Bubble 2003 (World, Ver 1.0)\0", NULL, "Limenko", "Miscellaneous",
1027 	NULL, NULL, NULL, NULL,
1028 	BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0,
1029 	NULL, sb2003RomInfo, sb2003RomName, NULL, NULL, NULL, NULL, Sb2003InputInfo, Sb2003DIPInfo,
1030 	Sb2003Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000,
1031 	384, 240, 4, 3
1032 };
1033 
1034 
1035 // Super Bubble 2003 (Asia, Ver 1.0)
1036 
1037 static struct BurnRomInfo sb2003aRomDesc[] = {
1038 	{ "sb2003a_05.u6",	0x200000, 0x265e45a7, 1 | BRF_PRG | BRF_ESS }, //  0 Hyperstone Boot ROM
1039 
1040 	{ "07.u16",			0x020000, 0x78acc607, 3 | BRF_PRG | BRF_ESS }, //  1 QS1000 Code
1041 
1042 	{ "01.u1",			0x200000, 0xd2c7091a, 4 | BRF_GRA },           //  2 Graphics
1043 	{ "02.u2",			0x200000, 0xa0734195, 4 | BRF_GRA },           //  3
1044 	{ "03.u3",			0x200000, 0x0f020280, 4 | BRF_GRA },           //  4
1045 	{ "04.u4",			0x200000, 0xfc2222b9, 4 | BRF_GRA },           //  5
1046 
1047 	{ "06.u18",			0x200000, 0xb6ad0d32, 5 | BRF_SND },           //  6 QS1000 Samples
1048 	{ "qs1003.u4",		0x200000, 0x19e4b469, 5 | BRF_SND },           //  7
1049 };
1050 
1051 STD_ROM_PICK(sb2003a)
1052 STD_ROM_FN(sb2003a)
1053 
1054 struct BurnDriver BurnDrvSb2003a = {
1055 	"sb2003a", "sb2003", NULL, NULL, "2003",
1056 	"Super Bubble 2003 (Asia, Ver 1.0)\0", NULL, "Limenko", "Miscellaneous",
1057 	NULL, NULL, NULL, NULL,
1058 	BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_PLATFORM, 0,
1059 	NULL, sb2003aRomInfo, sb2003aRomName, NULL, NULL, NULL, NULL, Sb2003InputInfo, Sb2003DIPInfo,
1060 	Sb2003Init, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000,
1061 	384, 240, 4, 3
1062 };
1063 
1064 
1065 // Legend of Heroes
1066 
1067 static struct BurnRomInfo legendohRomDesc[] = {
1068 	{ "01.sys_rom4",	0x080000, 0x49b4a91f, 1 | BRF_PRG | BRF_ESS }, //  0 Hyperstone Boot ROM
1069 
1070 	{ "sys_rom6",		0x200000, 0x5c13d467, 2 | BRF_PRG | BRF_ESS }, //  1 Hyperstone Main ROM
1071 	{ "sys_rom5",		0x200000, 0x19dc8d23, 2 | BRF_PRG | BRF_ESS }, //  2
1072 
1073 	{ "cg_rom10",		0x200000, 0x93a48489, 4 | BRF_GRA },           //  3 Graphics
1074 	{ "cg_rom20",		0x200000, 0x1a6c0258, 4 | BRF_GRA },           //  4
1075 	{ "cg_rom30",		0x200000, 0xa0559ef4, 4 | BRF_GRA },           //  5
1076 	{ "cg_rom40",		0x200000, 0xa607b2b5, 4 | BRF_GRA },           //  6
1077 	{ "cg_rom11",		0x200000, 0xa9fd5a50, 4 | BRF_GRA },           //  7
1078 	{ "cg_rom21",		0x200000, 0xb05cdeb2, 4 | BRF_GRA },           //  8
1079 	{ "cg_rom31",		0x200000, 0xa9a0d386, 4 | BRF_GRA },           //  9
1080 	{ "cg_rom41",		0x200000, 0x1c014f45, 4 | BRF_GRA },           // 10
1081 	{ "02.cg_rom12",	0x080000, 0x8b2e8cbc, 4 | BRF_GRA },           // 11
1082 	{ "03.cg_rom22",	0x080000, 0xa35960c8, 4 | BRF_GRA },           // 12
1083 	{ "04.cg_rom32",	0x080000, 0x3f486cab, 4 | BRF_GRA },           // 13
1084 	{ "05.cg_rom42",	0x080000, 0x5d807bec, 4 | BRF_GRA },           // 14
1085 
1086 	{ "sou_prg.06",		0x080000, 0xbfafe7aa, 3 | BRF_PRG | BRF_ESS }, // 15 QS1000 Code
1087 
1088 	{ "sou_rom.07",		0x080000, 0x4c6eb6d2, 5 | BRF_SND },           // 16 QS1000 Samples
1089 	{ "sou_rom.08",		0x080000, 0x42c32dd5, 5 | BRF_SND },           // 17
1090 	{ "qs1003.u4",		0x200000, 0x19e4b469, 5 | BRF_SND },           // 18
1091 };
1092 
1093 STD_ROM_PICK(legendoh)
STD_ROM_FN(legendoh)1094 STD_ROM_FN(legendoh)
1095 
1096 static INT32 LegendohInit()
1097 {
1098 	speedhack_address = 0x32ab0;
1099 	speedhack_pc = 0x23e32;
1100 
1101 	security_bit_config		= 0x00400000; // high
1102 	eeprom_bit_config		= 0x00800000;
1103 	spriteram_bit_config	= 0x80000000;
1104 
1105 	return LimenkoCommonInit(TYPE_E132XN, 80000000, LegendohLoadCallback, 0x1200000, 0);
1106 }
1107 
1108 struct BurnDriver BurnDrvLegendoh = {
1109 	"legendoh", NULL, NULL, NULL, "2000",
1110 	"Legend of Heroes\0", NULL, "Limenko", "Miscellaneous",
1111 	NULL, NULL, NULL, NULL,
1112 	BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0,
1113 	NULL, legendohRomInfo, legendohRomName, NULL, NULL, NULL, NULL, LegendohInputInfo, LegendohDIPInfo,
1114 	LegendohInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000,
1115 	384, 240, 4, 3
1116 };
1117 
1118 
1119 // Spotty (Ver. 2.0.2)
1120 
1121 static struct BurnRomInfo spottyRomDesc[] = {
1122 	{ "sys_rom2",		0x80000, 0x6ded8d9b, 1 | BRF_PRG | BRF_ESS }, //  0 Hyperstone Boot ROM
1123 
1124 	{ "at89c4051.mcu",	0x01000, 0x82ceab26, 3 | BRF_PRG | BRF_ESS }, //  1 at89c4051 Code
1125 
1126 	{ "gc_rom1",		0x80000, 0xea03f9c5, 2 | BRF_PRG | BRF_ESS }, //  2 Hyperstone Main ROM / Graphics
1127 	{ "gc_rom3",		0x80000, 0x0ddac0b9, 2 | BRF_PRG | BRF_ESS }, //  3
1128 
1129 	{ "sou_rom1",		0x40000, 0x5791195b, 4 | BRF_SND },           //  4 OKI Samples
1130 };
1131 
1132 STD_ROM_PICK(spotty)
STD_ROM_FN(spotty)1133 STD_ROM_FN(spotty)
1134 
1135 static INT32 SpottyInit()
1136 {
1137 	speedhack_address = 0x6626c;
1138 	speedhack_pc = 0x8560;
1139 
1140 	security_bit_config		= 0x00400000 & 0; // low
1141 	eeprom_bit_config		= 0x00800000;
1142 	spriteram_bit_config	= 0x00080000;
1143 
1144 	return LimenkoCommonInit(TYPE_GMS30C2232, 20000000, SpottyLoadCallback, 0x200000, 1);
1145 }
1146 
1147 struct BurnDriver BurnDrvSpotty = {
1148 	"spotty", NULL, NULL, NULL, "2001",
1149 	"Spotty (Ver. 2.0.2)\0", NULL, "Prince Co.", "Miscellaneous",
1150 	NULL, NULL, NULL, NULL,
1151 	BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_CASINO, 0,
1152 	NULL, spottyRomInfo, spottyRomName, NULL, NULL, NULL, NULL, SpottyInputInfo, SpottyDIPInfo,
1153 	SpottyInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0x1000,
1154 	384, 240, 4, 3
1155 };
1156