1 /******************************************************************************
2 
3   Sega encryption emulation                                 by Nicola Salmoria
4 
5 
6   Several Sega Z80 games have program ROMs encrypted using a common algorithm
7   (but with a different key).
8   The hardware used to implement this encryption is either a custom CPU, or an
9   epoxy block which probably contains a standard Z80 + PALs.
10 
11   The encryption affects D3, D5, and D7, and depends on M1, A0, A4, A8 and A12.
12   D0, D1, D3, D4 and D6 are always unaffected.
13 
14   The encryption consists of a permutation of the three bits, which can also be
15   inverted. Therefore there are 3! * 2^3 = 48 different possible encryptions.
16 
17   For simplicity, the decryption is implemented using conversion tables.
18   We need 32 of these tables, one for every possible combination of M1, A0, A4,
19   A8 and A12. However, all the games currently known are full of repetitions
20   and only use 6 different tables, the only exceptions being Pengo, Yamato and
21   Spatter which have 7 (but one of them is the identity: { 0x00, 0x08, 0x20, 0x28 } ).
22   This is most likely a limitation of the hardware.
23   Some of the early games are even weaker: of the 6 different tables, they use
24   3 for opcodes and 3 for data, and always coupled in the same way.
25 
26   In all games currently known, only bytes in the memory range 0x0000-0x7fff
27   (A15 = 0) are encrypted. My guess is that this was done to allow games to
28   copy code to RAM (in the memory range 0x8000-0xffff) and execute it from
29   there without the CPU trying to decrypt it and messing everything up.
30   However Zaxxon has RAM at 0x6000, and the CPU doesn't seem to interfere with
31   it; but it doesn't execute code from there, so it's possible that the CPU is
32   encrypting the data while writing it and decrypting it while reading (that
33   would seem kind of strange though). Video and sprite RAM and memory mapped
34   ports are all placed above 0x8000.
35 
36   Given its strict limitations, this encryption is reasonably easy to break,
37   and very vulnerable to known plaintext attacks.
38 
39 
40 
41   Ninja Princess:
42 
43   there is a (bootleg?) board which has a standard Z80 + 2 bipolar PROMs
44   instead of the custom CPU. The encryption table is different from the
45   original Ninja Princess; it is actually the same as Flicky.
46 
47   The first PROM is 32x8 and contains the number (0..5) of the table to
48   use depending on M1, A0, A4, A8, A12:
49 
50   00: 11 00 33 22 00 44 44 00 11 33 33 22 44 44 44 22
51   10: 11 55 55 33 44 22 55 22 11 33 55 33 44 44 11 22
52 
53   The second PROM is 256x4 and contains the 6 different XOR tables:
54 
55        A  D  B  C  C  B  D  A
56   00: 09 09 0A 0A 0A 0A 09 09
57   08: 0E 08 0B 0D 0D 0B 08 0E
58   10: 0A 0C 0A 0C 0C 0A 0C 0A
59   18: 0B 0E 0E 0B 0B 0E 0E 0B
60   20: 0C 0C 0F 0F 0F 0F 0C 0C
61   28: 08 0D 0B 0E 0E 0B 0D 08
62   [the remaining bytes are all 0F]
63   bit 3 is not used.
64   bits 0-2 is the XOR code inverted (0 = 0xa8, 1 = 0xa0 ... 6 = 0x08 7 = 0x00)
65 
66   Here is a diagram showing how it works:
67 
68   data to                             XOR
69   decode                             value
70                       A ---
71   D7  --------------- 0|   |
72   D3  --------------- 1|   |
73   D5  --------------- 2| P |D
74           A --- D      | R |0 ---|>--- D3
75   M1  --- 0| P |0 --- 3| O |1 ---|>--- D5
76   A0  --- 1| R |1 --- 4| M |2 ---|>--- D7
77   A4  --- 2| O |2 --- 5| 2 |3 ---
78   A8  --- 3| M |3 --- 6|   |
79   A12 --- 4| 1 |4 --- 7|   |
80             ---         ---
81 
82 
83   My Hero:
84 
85   the bootleg does the decryption using a single 256x4 PROM, mapped in the
86   obvious way:
87 
88   data to            XOR
89   decode            value
90           A ---
91   D3  --- 0|   |
92   D5  --- 1|   |D
93   D7  --- 2| P |0 --- D3
94   A0  --- 3| R |1 --- D5
95   A4  --- 4| O |2 --- D7
96   A8  --- 5| M |3 ---
97   A12 --- 6|   |
98   M1  --- 7|   |
99             ---
100 
101 
102 
103   List of encrypted games currently known:
104 
105  CPU Part #         Game                   Comments
106   ???-????      Buck Rogers            unencrypted version available
107   315-5010      Pengo                  unencrypted version available
108   315-5013      Super Zaxxon           used Zaxxon for known plaintext attack
109   ???-????      Super Locomotive
110   315-5018      Yamato
111   315-5028      Sindbad Mystery
112   315-5030      Up'n Down &            unencrypted version available
113            M120 Razzmatazz
114   315-5033      Regulus                unencrypted version available
115   315-5041 M140 Mister Viking
116   315-5048      SWAT                   used Bull Fight for k.p.a.
117   315-5051      Flicky &
118                 Ninja Princess (bootleg)
119   315-5061      Future Spy
120   315-5064      Water Match            used Mister Viking for k.p.a.
121   315-5065      Bull Fight
122   315-5069      Star Force             game by Tehkan; same key as Super Locomotive
123   ???-????      Spatter
124   315-5093      Pitfall II
125   315-5098      Ninja Princess         unencrypted version available; same key as Up'n Down
126   315-5102      Sega Ninja             unencrypted version available
127   315-5110      I'm Sorry              used My Hero for k.p.a.
128   315-5114      ?? pcb 834-5492        same key as Regulus
129   315-5115      TeddyBoy Blues
130   315-5132      My Hero
131   315-5135      Heavy Metal &
132                 Wonder Boy (set 1a & 3; bootlegs?)
133   ???-????      Lovely Cards
134 
135 
136   The following games use a different encryption algorithm:
137 
138   315-5162      4D Warriors &          used I'm Sorry for k.p.a.
139                 Rafflesia
140   315-5177      Astro Flash &
141                 Wonder Boy (set 1)
142   315-5178      Wonder Boy (set 2)     unencrypted version available
143   315-5179      Robo-Wrestle 2001      not decoded yet
144 
145 
146   The following games use another different encryption algorithm, much more
147   secure than the previous ones, which has not been broken yet. It might be
148   similar to the one used in System 16 games.
149 
150   317-5012      Ganbare Chinsan Ooshoubu  MC-8123A
151   317-0014      DakkoChan Jansoh
152   317-0029      Block Gal              NEC MC8123B 651 packaged like System16's 68000
153   317-0030      Perfect Billiard
154   317-0042      Opa Opa
155   317-0043      Wonder Boy Monster Land
156   317-0054      Shinobi (sound CPU)    NEC MC8123B 651
157   317-0057      Fantasy Zone 2
158   317-0064      Ufo Senshi Yohko Chan
159                 Ninja Kid II sound program also seems to use this encryption
160 
161 
162   Some text found in the ROMs:
163 
164   Buck Rogers      SECULITY BY MASATOSHI,MIZUNAGA
165   Super Locomotive SEGA FUKUMURA MIZUNAGA
166   Yamato           SECULITY BY M,MIZUNAGA
167   Regulus          SECULITY BY SYUICHI,KATAGI
168   Up'n Down        19/SEP 1983   MASATOSHI,MIZUNAGA
169   Mister Viking    SECURITY BY S.KATAGI  CONTROL CHIP M140
170   SWAT             SECURITY BY S.KATAGI
171   Flicky           SECURITY BY S.KATAGI
172   Water Match      PROGRAMED BY KAWAHARA&NAKAGAWA
173   Star Force       STAR FORCE TEHKAN. SECURITY BY SEGA ENTERPRISESE
174 
175 ******************************************************************************/
176 
177 #include "driver.h"
178 
179 
180 #ifdef MAME_DEBUG
lfkp(int mask)181 static void lfkp(int mask)
182 {
183 	int A;
184 	unsigned char *RAM = memory_region(REGION_CPU1);
185 
186 
187 	for (A = 0x0000;A < 0x8000-14;A++)
188 	{
189 		static char text[] = "INSERT COIN";
190 		int i;
191 
192 
193 		if (	(RAM[A+0] & mask) == (0x21 & mask) &&	/* LD HL,$xxxx */
194 				(RAM[A+3] & mask) == (0x11 & mask) &&	/* LD DE,$xxxx */
195 				(RAM[A+6] & mask) == (0x01 & mask))		/* LD BC,$xxxx */
196 		{
197 			if (	(RAM[A+ 9] & mask) == (0x36 & mask) &&	/* LD (HL),$xx */
198 					(RAM[A+11] & mask) == (0xed & mask) &&
199 					(RAM[A+12] & mask) == (0xb0 & mask))	/* LDIR */
200 				log_cb(RETRO_LOG_DEBUG, LOGPRE "%04x: hl de bc (hl),xx ldir\n",A);
201 
202 			if (	(RAM[A+ 9] & mask) == (0x77 & mask) &&	/* LD (HL),A */
203 					(RAM[A+10] & mask) == (0xed & mask) &&
204 					(RAM[A+11] & mask) == (0xb0 & mask))	/* LDIR */
205 				log_cb(RETRO_LOG_DEBUG, LOGPRE "%04x: hl de bc (hl),a ldir\n",A);
206 
207 			if (	(RAM[A+ 9] & mask) == (0xed & mask) &&
208 					(RAM[A+10] & mask) == (0xb0 & mask))	/* LDIR */
209 				log_cb(RETRO_LOG_DEBUG, LOGPRE "%04x: hl de bc ldir\n",A);
210 		}
211 
212 		/* the following can also be PUSH IX, PUSH IY - need better checking */
213 		if (	(RAM[A+0] & mask) == (0xf5 & mask) &&	/* PUSH AF */
214 				(RAM[A+1] & mask) == (0xc5 & mask) &&	/* PUSH BC */
215 				(RAM[A+2] & mask) == (0xd5 & mask) &&	/* PUSH DE */
216 				(RAM[A+3] & mask) == (0xe5 & mask))		/* PUSH HL */
217 			log_cb(RETRO_LOG_DEBUG, LOGPRE "%04x: push af bc de hl\n",A);
218 
219 		if (	(RAM[A+0] & mask) == (0xe1 & mask) &&	/* POP HL */
220 				(RAM[A+1] & mask) == (0xd1 & mask) &&	/* POP DE */
221 				(RAM[A+2] & mask) == (0xc1 & mask) &&	/* POP BC */
222 				(RAM[A+3] & mask) == (0xf1 & mask))		/* POP AF */
223 			log_cb(RETRO_LOG_DEBUG, LOGPRE "%04x: pop hl de bc af\n",A);
224 
225 		for (i = 0;i < strlen(text);i++)
226 			if ((RAM[A+i] & mask) != (text[i] & mask)) break;
227 		if (i == strlen(text))
228 			log_cb(RETRO_LOG_DEBUG, LOGPRE "%04x: INSERT COIN\n",A);
229 	}
230 }
231 
look_for_known_plaintext(void)232 static void look_for_known_plaintext(void)
233 {
234 	lfkp(0x57);
235 }
236 
read_table_from_disk(unsigned char * xortable)237 static void read_table_from_disk(unsigned char *xortable)
238 {
239 	FILE *f;
240 
241 
242 	f = fopen("table","rb");
243 
244 	if (f) fread(xortable,1,128,f);
245 
246 	fclose(f);
247 }
248 #endif
249 
sega_decode(const unsigned char convtable[32][4])250 static void sega_decode(const unsigned char convtable[32][4])
251 {
252 	int A;
253 	unsigned char *rom = memory_region(REGION_CPU1);
254 	int diff = memory_region_length(REGION_CPU1) / 2;
255 
256 {
257 	int i;
258 	for (i = 0;i < 32;i++)
259 	{
260 		if ((convtable[i][0] & 8) != (convtable[i][1] & 8) &&
261 				(convtable[i][1] & 8) == (convtable[i][2] & 8))
262 		{
263 			printf("%02x %02x %02x %02x\n",
264 					convtable[i][0],
265 					convtable[i][1],
266 					convtable[i][2],
267 					convtable[i][3]);
268 			exit(0);
269 		}
270 	}
271 }
272 
273 	memory_set_opcode_base(0,rom+diff);
274 
275 	for (A = 0x0000;A < 0x8000;A++)
276 	{
277 		int row,col,xor = 0;
278 		unsigned char src;
279 
280 
281 		src = rom[A];
282 
283 		/* pick the translation table from bits 0, 4, 8 and 12 of the address */
284 		row = (A & 1) + (((A >> 4) & 1) << 1) + (((A >> 8) & 1) << 2) + (((A >> 12) & 1) << 3);
285 
286 		/* pick the offset in the table from bits 3 and 5 of the source data */
287 		col = ((src >> 3) & 1) + (((src >> 5) & 1) << 1);
288 		/* the bottom half of the translation table is the mirror image of the top */
289 		if (src & 0x80)
290 		{
291 			col = 3 - col;
292 			xor = 0xa8;
293 		}
294 
295 		/* decode the opcodes */
296 		rom[A + diff] = (src & ~0xa8) | (convtable[2*row][col] ^ xor);
297 
298 		/* decode the data */
299 		rom[A] = (src & ~0xa8) | (convtable[2*row+1][col] ^ xor);
300 
301 		if (convtable[2*row][col] == 0xff)	/* table incomplete! (for development) */
302 			rom[A + diff] = 0x00;
303 		if (convtable[2*row+1][col] == 0xff)	/* table incomplete! (for development) */
304 			rom[A] = 0xee;
305 	}
306 
307 	/* copy the opcodes from the not encrypted part of the ROMs */
308 	for (A = 0x8000;A < diff;A++)
309 		rom[A + diff] = rom[A];
310 }
311 
312 
313 
buckrog_decode(void)314 void buckrog_decode(void)
315 {
316 	static const unsigned char convtable[32][4] =
317 	{
318 		/*       opcode                   data                     address      */
319 		/*  A    B    C    D         A    B    C    D                           */
320 		{ 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 },	/* ...0...0...0...0 */
321 		{ 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 },	/* ...0...0...0...1 */
322 		{ 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 },	/* ...0...0...1...0 */
323 		{ 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 },	/* ...0...0...1...1 */
324 		{ 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 },	/* ...0...1...0...0 */
325 		{ 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 },	/* ...0...1...0...1 */
326 		{ 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 },	/* ...0...1...1...0 */
327 		{ 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 },	/* ...0...1...1...1 */
328 		{ 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 },	/* ...1...0...0...0 */
329 		{ 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 },	/* ...1...0...0...1 */
330 		{ 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 },	/* ...1...0...1...0 */
331 		{ 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 },	/* ...1...0...1...1 */
332 		{ 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 },	/* ...1...1...0...0 */
333 		{ 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 },	/* ...1...1...0...1 */
334 		{ 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 },	/* ...1...1...1...0 */
335 		{ 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 }	/* ...1...1...1...1 */
336 	};
337 
338 
339 	sega_decode(convtable);
340 }
341 
342 
pengo_decode(void)343 void pengo_decode(void)
344 {
345 	static const unsigned char convtable[32][4] =
346 	{
347 		/*       opcode                   data                     address      */
348 		/*  A    B    C    D         A    B    C    D                           */
349 		{ 0xa0,0x80,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 },	/* ...0...0...0...0 */
350 		{ 0x28,0xa8,0x08,0x88 }, { 0xa0,0x80,0xa8,0x88 },	/* ...0...0...0...1 */
351 		{ 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 },	/* ...0...0...1...0 */
352 		{ 0x08,0x28,0x88,0xa8 }, { 0xa0,0x80,0xa8,0x88 },	/* ...0...0...1...1 */
353 		{ 0x08,0x00,0x88,0x80 }, { 0x28,0xa8,0x08,0x88 },	/* ...0...1...0...0 */
354 		{ 0xa0,0x80,0x20,0x00 }, { 0x08,0x00,0x88,0x80 },	/* ...0...1...0...1 */
355 		{ 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 },	/* ...0...1...1...0 */
356 		{ 0xa0,0x80,0x20,0x00 }, { 0x00,0x08,0x20,0x28 },	/* ...0...1...1...1 */
357 		{ 0x88,0x80,0x08,0x00 }, { 0xa0,0x80,0x20,0x00 },	/* ...1...0...0...0 */
358 		{ 0x88,0x80,0x08,0x00 }, { 0x00,0x08,0x20,0x28 },	/* ...1...0...0...1 */
359 		{ 0x08,0x28,0x88,0xa8 }, { 0x08,0x28,0x88,0xa8 },	/* ...1...0...1...0 */
360 		{ 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0x20,0x00 },	/* ...1...0...1...1 */
361 		{ 0x08,0x00,0x88,0x80 }, { 0x88,0x80,0x08,0x00 },	/* ...1...1...0...0 */
362 		{ 0x00,0x08,0x20,0x28 }, { 0x88,0x80,0x08,0x00 },	/* ...1...1...0...1 */
363 		{ 0x08,0x28,0x88,0xa8 }, { 0x08,0x28,0x88,0xa8 },	/* ...1...1...1...0 */
364 		{ 0x08,0x00,0x88,0x80 }, { 0xa0,0x80,0x20,0x00 }	/* ...1...1...1...1 */
365 	};
366 
367 
368 	sega_decode(convtable);
369 }
370 
371 
szaxxon_decode(void)372 void szaxxon_decode(void)
373 {
374 	static const unsigned char convtable[32][4] =
375 	{
376 		/*       opcode                   data                     address      */
377 		/*  A    B    C    D         A    B    C    D                           */
378 		{ 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 },	/* ...0...0...0...0 */
379 		{ 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 },	/* ...0...0...0...1 */
380 		{ 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 },	/* ...0...0...1...0 */
381 		{ 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 },	/* ...0...0...1...1 */
382 		{ 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 },	/* ...0...1...0...0 */
383 		{ 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 },	/* ...0...1...0...1 */
384 		{ 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 },	/* ...0...1...1...0 */
385 		{ 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 },	/* ...0...1...1...1 */
386 		{ 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 },	/* ...1...0...0...0 */
387 		{ 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 },	/* ...1...0...0...1 */
388 		{ 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 },	/* ...1...0...1...0 */
389 		{ 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 },	/* ...1...0...1...1 */
390 		{ 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 },	/* ...1...1...0...0 */
391 		{ 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 },	/* ...1...1...0...1 */
392 		{ 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 },	/* ...1...1...1...0 */
393 		{ 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }	/* ...1...1...1...1 */
394 	};
395 
396 
397 	sega_decode(convtable);
398 }
399 
400 
suprloco_decode(void)401 void suprloco_decode(void)
402 {
403 	static const unsigned char convtable[32][4] =
404 	{
405 		/*       opcode                   data                     address      */
406 		/*  A    B    C    D         A    B    C    D                           */
407 		{ 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 },	/* ...0...0...0...0 */
408 		{ 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 },	/* ...0...0...0...1 */
409 		{ 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 },	/* ...0...0...1...0 */
410 		{ 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 },	/* ...0...0...1...1 */
411 		{ 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 },	/* ...0...1...0...0 */
412 		{ 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 },	/* ...0...1...0...1 */
413 		{ 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 },	/* ...0...1...1...0 */
414 		{ 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 },	/* ...0...1...1...1 */
415 		{ 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 },	/* ...1...0...0...0 */
416 		{ 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 },	/* ...1...0...0...1 */
417 		{ 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 },	/* ...1...0...1...0 */
418 		{ 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 },	/* ...1...0...1...1 */
419 		{ 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 },	/* ...1...1...0...0 */
420 		{ 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 },	/* ...1...1...0...1 */
421 		{ 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 },	/* ...1...1...1...0 */
422 		{ 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }	/* ...1...1...1...1 */
423 	};
424 
425 
426 	sega_decode(convtable);
427 }
428 
429 
yamato_decode(void)430 void yamato_decode(void)
431 {
432 	static const unsigned char convtable[32][4] =
433 	{
434 		/*       opcode                   data                     address      */
435 		/*  A    B    C    D         A    B    C    D                           */
436 		{ 0x88,0xa8,0x08,0x28 }, { 0x88,0xa8,0x80,0xa0 },	/* ...0...0...0...0 */
437 		{ 0x20,0xa0,0x28,0xa8 }, { 0x88,0xa8,0x80,0xa0 },	/* ...0...0...0...1 */
438 		{ 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 },	/* ...0...0...1...0 */
439 		{ 0x88,0xa8,0x80,0xa0 }, { 0x20,0xa0,0x28,0xa8 },	/* ...0...0...1...1 */
440 		{ 0x88,0xa8,0x08,0x28 }, { 0x88,0xa8,0x08,0x28 },	/* ...0...1...0...0 */
441 		{ 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 },	/* ...0...1...0...1 */
442 		{ 0x20,0xa0,0x28,0xa8 }, { 0x20,0xa0,0x28,0xa8 },	/* ...0...1...1...0 */
443 		{ 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 },	/* ...0...1...1...1 */
444 		{ 0x20,0xa0,0x28,0xa8 }, { 0x88,0xa8,0x08,0x28 },	/* ...1...0...0...0 */
445 		{ 0x20,0xa0,0x28,0xa8 }, { 0x28,0x20,0xa8,0xa0 },	/* ...1...0...0...1 */
446 		{ 0xa0,0x20,0x80,0x00 }, { 0x20,0xa0,0x28,0xa8 },	/* ...1...0...1...0 */
447 		{ 0x28,0x20,0xa8,0xa0 }, { 0x20,0xa0,0x28,0xa8 },	/* ...1...0...1...1 */
448 		{ 0x20,0xa0,0x28,0xa8 }, { 0x88,0xa8,0x08,0x28 },	/* ...1...1...0...0 */
449 		{ 0x88,0xa8,0x08,0x28 }, { 0x88,0xa8,0x08,0x28 },	/* ...1...1...0...1 */
450 		{ 0xa0,0x20,0x80,0x00 }, { 0x88,0x08,0x80,0x00 },	/* ...1...1...1...0 */
451 		{ 0x20,0xa0,0x28,0xa8 }, { 0x00,0x08,0x20,0x28 }	/* ...1...1...1...1 */
452 	};
453 
454 
455 	sega_decode(convtable);
456 }
457 
458 
sindbadm_decode(void)459 void sindbadm_decode(void)
460 {
461 	static const unsigned char convtable[32][4] =
462 	{
463 		/*       opcode                   data                     address      */
464 		/*  A    B    C    D         A    B    C    D                           */
465 		{ 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 },	/* ...0...0...0...0 */
466 		{ 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 },	/* ...0...0...0...1 */
467 		{ 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 },	/* ...0...0...1...0 */
468 		{ 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 },	/* ...0...0...1...1 */
469 		{ 0xa8,0x88,0xa0,0x80 }, { 0xa0,0x20,0xa8,0x28 },	/* ...0...1...0...0 */
470 		{ 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 },	/* ...0...1...0...1 */
471 		{ 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 },	/* ...0...1...1...0 */
472 		{ 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 },	/* ...0...1...1...1 */
473 		{ 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 },	/* ...1...0...0...0 */
474 		{ 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 },	/* ...1...0...0...1 */
475 		{ 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 },	/* ...1...0...1...0 */
476 		{ 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 },	/* ...1...0...1...1 */
477 		{ 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 },	/* ...1...1...0...0 */
478 		{ 0xa8,0x88,0xa0,0x80 }, { 0xa0,0x20,0xa8,0x28 },	/* ...1...1...0...1 */
479 		{ 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 },	/* ...1...1...1...0 */
480 		{ 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }	/* ...1...1...1...1 */
481 	};
482 
483 
484 	sega_decode(convtable);
485 }
486 
487 
regulus_decode(void)488 void regulus_decode(void)
489 {
490 	static const unsigned char convtable[32][4] =
491 	{
492 		/*       opcode                   data                     address      */
493 		/*  A    B    C    D         A    B    C    D                           */
494 		{ 0x28,0x08,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 },	/* ...0...0...0...0 */
495 		{ 0x28,0x08,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 },	/* ...0...0...0...1 */
496 		{ 0x88,0x80,0x08,0x00 }, { 0x88,0x08,0x80,0x00 },	/* ...0...0...1...0 */
497 		{ 0x88,0x08,0x80,0x00 }, { 0x28,0xa8,0x08,0x88 },	/* ...0...0...1...1 */
498 		{ 0x28,0x08,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 },	/* ...0...1...0...0 */
499 		{ 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 },	/* ...0...1...0...1 */
500 		{ 0x88,0x08,0x80,0x00 }, { 0x88,0x08,0x80,0x00 },	/* ...0...1...1...0 */
501 		{ 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 },	/* ...0...1...1...1 */
502 		{ 0x80,0xa0,0x00,0x20 }, { 0x28,0x08,0xa8,0x88 },	/* ...1...0...0...0 */
503 		{ 0x28,0xa8,0x08,0x88 }, { 0x28,0x08,0xa8,0x88 },	/* ...1...0...0...1 */
504 		{ 0x80,0xa0,0x00,0x20 }, { 0x80,0xa0,0x00,0x20 },	/* ...1...0...1...0 */
505 		{ 0x28,0xa8,0x08,0x88 }, { 0x80,0xa0,0x00,0x20 },	/* ...1...0...1...1 */
506 		{ 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 },	/* ...1...1...0...0 */
507 		{ 0x80,0xa0,0x00,0x20 }, { 0xa0,0x80,0xa8,0x88 },	/* ...1...1...0...1 */
508 		{ 0xa0,0x80,0xa8,0x88 }, { 0x80,0xa0,0x00,0x20 },	/* ...1...1...1...0 */
509 		{ 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }	/* ...1...1...1...1 */
510 	};
511 
512 
513 	sega_decode(convtable);
514 }
515 
516 
mrviking_decode(void)517 void mrviking_decode(void)
518 {
519 	static const unsigned char convtable[32][4] =
520 	{
521 		/*       opcode                   data                     address      */
522 		/*  A    B    C    D         A    B    C    D                           */
523 		{ 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 },	/* ...0...0...0...0 */
524 		{ 0x88,0x08,0x80,0x00 }, { 0x88,0x80,0x08,0x00 },	/* ...0...0...0...1 */
525 		{ 0x28,0x08,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 },	/* ...0...0...1...0 */
526 		{ 0x88,0x08,0x80,0x00 }, { 0x88,0x08,0x80,0x00 },	/* ...0...0...1...1 */
527 		{ 0x28,0x08,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 },	/* ...0...1...0...0 */
528 		{ 0x88,0x80,0x08,0x00 }, { 0x28,0xa8,0x08,0x88 },	/* ...0...1...0...1 */
529 		{ 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 },	/* ...0...1...1...0 */
530 		{ 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 },	/* ...0...1...1...1 */
531 		{ 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 },	/* ...1...0...0...0 */
532 		{ 0x88,0x08,0x80,0x00 }, { 0x88,0x80,0x08,0x00 },	/* ...1...0...0...1 */
533 		{ 0xa0,0x80,0x20,0x00 }, { 0x28,0x08,0xa8,0x88 },	/* ...1...0...1...0 */
534 		{ 0xa0,0x80,0x20,0x00 }, { 0x88,0x08,0x80,0x00 },	/* ...1...0...1...1 */
535 		{ 0x28,0x08,0xa8,0x88 }, { 0xa0,0x80,0x20,0x00 },	/* ...1...1...0...0 */
536 		{ 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 },	/* ...1...1...0...1 */
537 		{ 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 },	/* ...1...1...1...0 */
538 		{ 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0xa8,0x88 }	/* ...1...1...1...1 */
539 	};
540 
541 
542 	sega_decode(convtable);
543 }
544 
545 
swat_decode(void)546 void swat_decode(void)
547 {
548 	static const unsigned char convtable[32][4] =
549 	{
550 		/*       opcode                   data                     address      */
551 		/*  A    B    C    D         A    B    C    D                           */
552 		{ 0x88,0x08,0x80,0x00 }, { 0xa0,0xa8,0x80,0x88 },	/* ...0...0...0...0 */
553 		{ 0x88,0x08,0x80,0x00 }, { 0x88,0xa8,0x80,0xa0 },	/* ...0...0...0...1 */
554 		{ 0xa0,0x80,0x20,0x00 }, { 0x88,0x08,0x80,0x00 },	/* ...0...0...1...0 */
555 		{ 0xa0,0xa8,0x80,0x88 }, { 0x88,0x08,0x80,0x00 },	/* ...0...0...1...1 */
556 		{ 0x28,0x20,0xa8,0xa0 }, { 0xa0,0xa8,0x80,0x88 },	/* ...0...1...0...0 */
557 		{ 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 },	/* ...0...1...0...1 */
558 		{ 0xa0,0x80,0x20,0x00 }, { 0xa0,0xa8,0x80,0x88 },	/* ...0...1...1...0 */
559 		{ 0x28,0x20,0xa8,0xa0 }, { 0xa0,0xa8,0x80,0x88 },	/* ...0...1...1...1 */
560 		{ 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 },	/* ...1...0...0...0 */
561 		{ 0xa0,0x20,0x80,0x00 }, { 0x88,0xa8,0x80,0xa0 },	/* ...1...0...0...1 */
562 		{ 0xa0,0x20,0x80,0x00 }, { 0xa0,0x20,0x80,0x00 },	/* ...1...0...1...0 */
563 		{ 0xa0,0x20,0x80,0x00 }, { 0xa0,0x20,0x80,0x00 },	/* ...1...0...1...1 */
564 		{ 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 },	/* ...1...1...0...0 */
565 		{ 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 },	/* ...1...1...0...1 */
566 		{ 0xa0,0xa8,0x80,0x88 }, { 0xa0,0x80,0x20,0x00 },	/* ...1...1...1...0 */
567 		{ 0x28,0x20,0xa8,0xa0 }, { 0xa0,0xa8,0x80,0x88 }	/* ...1...1...1...1 */
568 	};
569 
570 
571 	sega_decode(convtable);
572 }
573 
574 
flicky_decode(void)575 void flicky_decode(void)
576 {
577 	static const unsigned char convtable[32][4] =
578 	{
579 		/*       opcode                   data                     address      */
580 		/*  A    B    C    D         A    B    C    D                           */
581 		{ 0x08,0x88,0x00,0x80 }, { 0xa0,0x80,0xa8,0x88 },	/* ...0...0...0...0 */
582 		{ 0x80,0x00,0xa0,0x20 }, { 0x88,0x80,0x08,0x00 },	/* ...0...0...0...1 */
583 		{ 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0x20,0x00 },	/* ...0...0...1...0 */
584 		{ 0x28,0x08,0x20,0x00 }, { 0xa0,0x80,0xa8,0x88 },	/* ...0...0...1...1 */
585 		{ 0x08,0x88,0x00,0x80 }, { 0x80,0x00,0xa0,0x20 },	/* ...0...1...0...0 */
586 		{ 0x80,0x00,0xa0,0x20 }, { 0x88,0x80,0x08,0x00 },	/* ...0...1...0...1 */
587 		{ 0x28,0x08,0x20,0x00 }, { 0x28,0x08,0x20,0x00 },	/* ...0...1...1...0 */
588 		{ 0x28,0x08,0x20,0x00 }, { 0x88,0x80,0x08,0x00 },	/* ...0...1...1...1 */
589 		{ 0x08,0x88,0x00,0x80 }, { 0xa8,0x88,0x28,0x08 },	/* ...1...0...0...0 */
590 		{ 0xa8,0x88,0x28,0x08 }, { 0x80,0x00,0xa0,0x20 },	/* ...1...0...0...1 */
591 		{ 0x28,0x08,0x20,0x00 }, { 0x88,0x80,0x08,0x00 },	/* ...1...0...1...0 */
592 		{ 0xa8,0x88,0x28,0x08 }, { 0x88,0x80,0x08,0x00 },	/* ...1...0...1...1 */
593 		{ 0x08,0x88,0x00,0x80 }, { 0x80,0x00,0xa0,0x20 },	/* ...1...1...0...0 */
594 		{ 0xa8,0x88,0x28,0x08 }, { 0x80,0x00,0xa0,0x20 },	/* ...1...1...0...1 */
595 		{ 0x28,0x08,0x20,0x00 }, { 0x28,0x08,0x20,0x00 },	/* ...1...1...1...0 */
596 		{ 0x08,0x88,0x00,0x80 }, { 0x88,0x80,0x08,0x00 }	/* ...1...1...1...1 */
597 	};
598 
599 
600 	sega_decode(convtable);
601 }
602 
603 
futspy_decode(void)604 void futspy_decode(void)
605 {
606 	static const unsigned char convtable[32][4] =
607 	{
608 		/*       opcode                   data                     address      */
609 		/*  A    B    C    D         A    B    C    D                           */
610 		{ 0x28,0x08,0x20,0x00 }, { 0x28,0x08,0x20,0x00 },	/* ...0...0...0...0 */
611 		{ 0x80,0x00,0xa0,0x20 }, { 0x08,0x88,0x00,0x80 },	/* ...0...0...0...1 */
612 		{ 0x80,0x00,0xa0,0x20 }, { 0x08,0x88,0x00,0x80 },	/* ...0...0...1...0 */
613 		{ 0xa0,0x80,0x20,0x00 }, { 0x20,0x28,0xa0,0xa8 },	/* ...0...0...1...1 */
614 		{ 0x28,0x08,0x20,0x00 }, { 0x88,0x80,0xa8,0xa0 },	/* ...0...1...0...0 */
615 		{ 0x80,0x00,0xa0,0x20 }, { 0x08,0x88,0x00,0x80 },	/* ...0...1...0...1 */
616 		{ 0x80,0x00,0xa0,0x20 }, { 0x20,0x28,0xa0,0xa8 },	/* ...0...1...1...0 */
617 		{ 0x20,0x28,0xa0,0xa8 }, { 0x08,0x88,0x00,0x80 },	/* ...0...1...1...1 */
618 		{ 0x88,0x80,0xa8,0xa0 }, { 0x28,0x08,0x20,0x00 },	/* ...1...0...0...0 */
619 		{ 0x80,0x00,0xa0,0x20 }, { 0xa0,0x80,0x20,0x00 },	/* ...1...0...0...1 */
620 		{ 0x20,0x28,0xa0,0xa8 }, { 0x08,0x88,0x00,0x80 },	/* ...1...0...1...0 */
621 		{ 0x80,0x00,0xa0,0x20 }, { 0x20,0x28,0xa0,0xa8 },	/* ...1...0...1...1 */
622 		{ 0x88,0x80,0xa8,0xa0 }, { 0x88,0x80,0xa8,0xa0 },	/* ...1...1...0...0 */
623 		{ 0x80,0x00,0xa0,0x20 }, { 0x08,0x88,0x00,0x80 },	/* ...1...1...0...1 */
624 		{ 0x80,0x00,0xa0,0x20 }, { 0x28,0x08,0x20,0x00 },	/* ...1...1...1...0 */
625 		{ 0x20,0x28,0xa0,0xa8 }, { 0xa0,0x80,0x20,0x00 }	/* ...1...1...1...1 */
626 	};
627 
628 
629 	sega_decode(convtable);
630 }
631 
632 
wmatch_decode(void)633 void wmatch_decode(void)
634 {
635 	static const unsigned char convtable[32][4] =
636 	{
637 		/*       opcode                   data                     address      */
638 		/*  A    B    C    D         A    B    C    D                           */
639 		{ 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 },	/* ...0...0...0...0 */
640 		{ 0x08,0x88,0x00,0x80 }, { 0x88,0xa8,0x80,0xa0 },	/* ...0...0...0...1 */
641 		{ 0x20,0x00,0xa0,0x80 }, { 0x20,0x28,0xa0,0xa8 },	/* ...0...0...1...0 */
642 		{ 0x20,0x28,0xa0,0xa8 }, { 0xa0,0x80,0x20,0x00 },	/* ...0...0...1...1 */
643 		{ 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 },	/* ...0...1...0...0 */
644 		{ 0x08,0x88,0x00,0x80 }, { 0xa8,0x28,0x88,0x08 },	/* ...0...1...0...1 */
645 		{ 0xa8,0x28,0x88,0x08 }, { 0x20,0x28,0xa0,0xa8 },	/* ...0...1...1...0 */
646 		{ 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 },	/* ...0...1...1...1 */
647 		{ 0x20,0x28,0xa0,0xa8 }, { 0x88,0xa8,0x80,0xa0 },	/* ...1...0...0...0 */
648 		{ 0x88,0xa8,0x80,0xa0 }, { 0x20,0x28,0xa0,0xa8 },	/* ...1...0...0...1 */
649 		{ 0x20,0x28,0xa0,0xa8 }, { 0xa0,0x80,0x20,0x00 },	/* ...1...0...1...0 */
650 		{ 0x20,0x28,0xa0,0xa8 }, { 0x20,0x28,0xa0,0xa8 },	/* ...1...0...1...1 */
651 		{ 0x20,0x00,0xa0,0x80 }, { 0x20,0x28,0xa0,0xa8 },	/* ...1...1...0...0 */
652 		{ 0xa8,0x28,0x88,0x08 }, { 0xa0,0x80,0x20,0x00 },	/* ...1...1...0...1 */
653 		{ 0x20,0x28,0xa0,0xa8 }, { 0x20,0x28,0xa0,0xa8 },	/* ...1...1...1...0 */
654 		{ 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 }	/* ...1...1...1...1 */
655 	};
656 
657 
658 	sega_decode(convtable);
659 }
660 
661 
bullfgtj_decode(void)662 void bullfgtj_decode(void)
663 {
664 	static const unsigned char convtable[32][4] =
665 	{
666 		/*       opcode                   data                     address      */
667 		/*  A    B    C    D         A    B    C    D                           */
668 		{ 0xa0,0xa8,0x20,0x28 }, { 0x80,0xa0,0x00,0x20 },	/* ...0...0...0...0 */
669 		{ 0x20,0x28,0x00,0x08 }, { 0x20,0x28,0x00,0x08 },	/* ...0...0...0...1 */
670 		{ 0xa0,0xa8,0x20,0x28 }, { 0x08,0x28,0x00,0x20 },	/* ...0...0...1...0 */
671 		{ 0x88,0x08,0xa8,0x28 }, { 0x88,0x08,0xa8,0x28 },	/* ...0...0...1...1 */
672 		{ 0xa0,0xa8,0x20,0x28 }, { 0x20,0x28,0x00,0x08 },	/* ...0...1...0...0 */
673 		{ 0x28,0xa8,0x20,0xa0 }, { 0x20,0x28,0x00,0x08 },	/* ...0...1...0...1 */
674 		{ 0xa0,0xa8,0x20,0x28 }, { 0x08,0x28,0x00,0x20 },	/* ...0...1...1...0 */
675 		{ 0x88,0x08,0xa8,0x28 }, { 0x88,0x08,0xa8,0x28 },	/* ...0...1...1...1 */
676 		{ 0x28,0xa8,0x20,0xa0 }, { 0xa0,0xa8,0x20,0x28 },	/* ...1...0...0...0 */
677 		{ 0x88,0x08,0xa8,0x28 }, { 0x80,0xa0,0x00,0x20 },	/* ...1...0...0...1 */
678 		{ 0x28,0xa8,0x20,0xa0 }, { 0x08,0x28,0x00,0x20 },	/* ...1...0...1...0 */
679 		{ 0x28,0xa8,0x20,0xa0 }, { 0x80,0xa0,0x00,0x20 },	/* ...1...0...1...1 */
680 		{ 0x20,0x28,0x00,0x08 }, { 0x20,0x28,0x00,0x08 },	/* ...1...1...0...0 */
681 		{ 0x88,0x08,0xa8,0x28 }, { 0x20,0x28,0x00,0x08 },	/* ...1...1...0...1 */
682 		{ 0x08,0x28,0x00,0x20 }, { 0x80,0xa0,0x00,0x20 },	/* ...1...1...1...0 */
683 		{ 0x08,0x28,0x00,0x20 }, { 0x88,0x08,0xa8,0x28 }	/* ...1...1...1...1 */
684 	};
685 
686 
687 	sega_decode(convtable);
688 }
689 
690 
spatter_decode(void)691 void spatter_decode(void)
692 {
693 	static const unsigned char convtable[32][4] =
694 	{
695 		/*       opcode                   data                     address      */
696 		/*  A    B    C    D         A    B    C    D                           */
697 		{ 0x88,0x08,0x80,0x00 }, { 0x00,0x08,0x20,0x28 },	/* ...0...0...0...0 */
698 		{ 0x28,0xa8,0x08,0x88 }, { 0x28,0xa8,0x08,0x88 },	/* ...0...0...0...1 */
699 		{ 0x28,0x20,0xa8,0xa0 }, { 0x28,0x20,0xa8,0xa0 },	/* ...0...0...1...0 */
700 		{ 0x88,0x08,0x80,0x00 }, { 0x88,0x08,0x80,0x00 },	/* ...0...0...1...1 */
701 		{ 0x00,0x08,0x20,0x28 }, { 0x88,0x08,0x80,0x00 },	/* ...0...1...0...0 */
702 		{ 0xa0,0x80,0x20,0x00 }, { 0x80,0x88,0x00,0x08 },	/* ...0...1...0...1 */
703 		{ 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0x20,0x00 },	/* ...0...1...1...0 */
704 		{ 0x88,0x08,0x80,0x00 }, { 0x28,0x20,0xa8,0xa0 },	/* ...0...1...1...1 */
705 		{ 0x28,0xa8,0x08,0x88 }, { 0x80,0x88,0x00,0x08 },	/* ...1...0...0...0 */
706 		{ 0x80,0x88,0x00,0x08 }, { 0x00,0x08,0x20,0x28 },	/* ...1...0...0...1 */
707 		{ 0x28,0x20,0xa8,0xa0 }, { 0x28,0xa8,0x08,0x88 },	/* ...1...0...1...0 */
708 		{ 0x00,0x08,0x20,0x28 }, { 0x80,0xa0,0x88,0xa8 },	/* ...1...0...1...1 */
709 		{ 0x80,0x88,0x00,0x08 }, { 0xa0,0x80,0x20,0x00 },	/* ...1...1...0...0 */
710 		{ 0x80,0xa0,0x88,0xa8 }, { 0xa0,0x80,0x20,0x00 },	/* ...1...1...0...1 */
711 		{ 0xa0,0x80,0x20,0x00 }, { 0x80,0xa0,0x88,0xa8 },	/* ...1...1...1...0 */
712 		{ 0x28,0x20,0xa8,0xa0 }, { 0x00,0x08,0x20,0x28 }	/* ...1...1...1...1 */
713 	};
714 
715 
716 	sega_decode(convtable);
717 }
718 
719 
pitfall2_decode(void)720 void pitfall2_decode(void)
721 {
722 	static const unsigned char convtable[32][4] =
723 	{
724 		/*       opcode                   data                     address      */
725 		/*  A    B    C    D         A    B    C    D                           */
726 		{ 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 },	/* ...0...0...0...0 */
727 		{ 0x08,0x88,0x28,0xa8 }, { 0x28,0xa8,0x20,0xa0 },	/* ...0...0...0...1 */
728 		{ 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 },	/* ...0...0...1...0 */
729 		{ 0xa0,0xa8,0x20,0x28 }, { 0xa0,0xa8,0x20,0x28 },	/* ...0...0...1...1 */
730 		{ 0xa0,0x80,0xa8,0x88 }, { 0x20,0x00,0xa0,0x80 },	/* ...0...1...0...0 */
731 		{ 0x28,0xa8,0x20,0xa0 }, { 0x20,0x00,0xa0,0x80 },	/* ...0...1...0...1 */
732 		{ 0xa0,0xa8,0x20,0x28 }, { 0xa0,0xa8,0x20,0x28 },	/* ...0...1...1...0 */
733 		{ 0x28,0xa8,0x20,0xa0 }, { 0xa0,0xa8,0x20,0x28 },	/* ...0...1...1...1 */
734 		{ 0x20,0x00,0xa0,0x80 }, { 0x80,0x88,0xa0,0xa8 },	/* ...1...0...0...0 */
735 		{ 0x80,0x88,0xa0,0xa8 }, { 0x80,0x88,0xa0,0xa8 },	/* ...1...0...0...1 */
736 		{ 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x80,0xa8,0x88 },	/* ...1...0...1...0 */
737 		{ 0x80,0x88,0xa0,0xa8 }, { 0x28,0xa8,0x20,0xa0 },	/* ...1...0...1...1 */
738 		{ 0x20,0x00,0xa0,0x80 }, { 0x80,0x88,0xa0,0xa8 },	/* ...1...1...0...0 */
739 		{ 0x80,0x88,0xa0,0xa8 }, { 0x20,0x00,0xa0,0x80 },	/* ...1...1...0...1 */
740 		{ 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x80,0xa8,0x88 },	/* ...1...1...1...0 */
741 		{ 0x80,0x88,0xa0,0xa8 }, { 0x28,0xa8,0x20,0xa0 }	/* ...1...1...1...1 */
742 	};
743 
744 
745 	sega_decode(convtable);
746 }
747 
748 
nprinces_decode(void)749 void nprinces_decode(void)
750 {
751 	static const unsigned char convtable[32][4] =
752 	{
753 		/*       opcode                   data                     address      */
754 		/*  A    B    C    D         A    B    C    D                           */
755 		{ 0x08,0x88,0x00,0x80 }, { 0xa0,0x20,0x80,0x00 },	/* ...0...0...0...0 */
756 		{ 0xa8,0xa0,0x28,0x20 }, { 0x88,0xa8,0x80,0xa0 },	/* ...0...0...0...1 */
757 		{ 0x88,0x80,0x08,0x00 }, { 0x28,0x08,0xa8,0x88 },	/* ...0...0...1...0 */
758 		{ 0x88,0xa8,0x80,0xa0 }, { 0x28,0x08,0xa8,0x88 },	/* ...0...0...1...1 */
759 		{ 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x20,0x80,0x00 },	/* ...0...1...0...0 */
760 		{ 0xa8,0xa0,0x28,0x20 }, { 0xa8,0xa0,0x28,0x20 },	/* ...0...1...0...1 */
761 		{ 0x88,0x80,0x08,0x00 }, { 0x88,0xa8,0x80,0xa0 },	/* ...0...1...1...0 */
762 		{ 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 },	/* ...0...1...1...1 */
763 		{ 0xa0,0x20,0x80,0x00 }, { 0xa0,0x20,0x80,0x00 },	/* ...1...0...0...0 */
764 		{ 0x08,0x88,0x00,0x80 }, { 0x28,0x08,0xa8,0x88 },	/* ...1...0...0...1 */
765 		{ 0x88,0xa8,0x80,0xa0 }, { 0x88,0x80,0x08,0x00 },	/* ...1...0...1...0 */
766 		{ 0x88,0xa8,0x80,0xa0 }, { 0x28,0x08,0xa8,0x88 },	/* ...1...0...1...1 */
767 		{ 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 },	/* ...1...1...0...0 */
768 		{ 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 },	/* ...1...1...0...1 */
769 		{ 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 },	/* ...1...1...1...0 */
770 		{ 0x08,0x88,0x00,0x80 }, { 0x28,0x08,0xa8,0x88 }	/* ...1...1...1...1 */
771 	};
772 
773 
774 	sega_decode(convtable);
775 }
776 
777 
seganinj_decode(void)778 void seganinj_decode(void)
779 {
780 	static const unsigned char convtable[32][4] =
781 	{
782 		/*       opcode                   data                     address      */
783 		/*  A    B    C    D         A    B    C    D                           */
784 		{ 0x88,0xa8,0x80,0xa0 }, { 0x88,0x08,0x80,0x00 },	/* ...0...0...0...0 */
785 		{ 0x28,0xa8,0x08,0x88 }, { 0xa0,0xa8,0x80,0x88 },	/* ...0...0...0...1 */
786 		{ 0xa8,0xa0,0x28,0x20 }, { 0xa8,0xa0,0x28,0x20 },	/* ...0...0...1...0 */
787 		{ 0x28,0xa8,0x08,0x88 }, { 0xa0,0xa8,0x80,0x88 },	/* ...0...0...1...1 */
788 		{ 0x28,0x08,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 },	/* ...0...1...0...0 */
789 		{ 0x28,0xa8,0x08,0x88 }, { 0x88,0x08,0x80,0x00 },	/* ...0...1...0...1 */
790 		{ 0x28,0x08,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 },	/* ...0...1...1...0 */
791 		{ 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x28,0x20 },	/* ...0...1...1...1 */
792 		{ 0x88,0x08,0x80,0x00 }, { 0x88,0xa8,0x80,0xa0 },	/* ...1...0...0...0 */
793 		{ 0xa0,0xa8,0x80,0x88 }, { 0x28,0xa8,0x08,0x88 },	/* ...1...0...0...1 */
794 		{ 0xa8,0xa0,0x28,0x20 }, { 0x88,0xa8,0x80,0xa0 },	/* ...1...0...1...0 */
795 		{ 0xa8,0xa0,0x28,0x20 }, { 0x28,0xa8,0x08,0x88 },	/* ...1...0...1...1 */
796 		{ 0x28,0x08,0xa8,0x88 }, { 0x88,0xa8,0x80,0xa0 },	/* ...1...1...0...0 */
797 		{ 0x28,0x08,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 },	/* ...1...1...0...1 */
798 		{ 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 },	/* ...1...1...1...0 */
799 		{ 0xa8,0xa0,0x28,0x20 }, { 0x28,0x08,0xa8,0x88 }	/* ...1...1...1...1 */
800 	};
801 
802 
803 	sega_decode(convtable);
804 }
805 
806 
imsorry_decode(void)807 void imsorry_decode(void)
808 {
809 	static const unsigned char convtable[32][4] =
810 	{
811 		/*       opcode                   data                     address      */
812 		/*  A    B    C    D         A    B    C    D                           */
813 		{ 0x88,0x08,0x80,0x00 }, { 0x00,0x20,0x80,0xa0 },	/* ...0...0...0...0 */
814 		{ 0x00,0x20,0x80,0xa0 }, { 0x88,0x08,0x80,0x00 },	/* ...0...0...0...1 */
815 		{ 0x88,0x08,0xa8,0x28 }, { 0x00,0x20,0x80,0xa0 },	/* ...0...0...1...0 */
816 		{ 0x00,0x20,0x80,0xa0 }, { 0x88,0x08,0xa8,0x28 },	/* ...0...0...1...1 */
817 		{ 0x00,0x20,0x80,0xa0 }, { 0x08,0x00,0x88,0x80 },	/* ...0...1...0...0 */
818 		{ 0x00,0x20,0x80,0xa0 }, { 0x20,0x28,0xa0,0xa8 },	/* ...0...1...0...1 */
819 		{ 0x20,0x28,0xa0,0xa8 }, { 0x00,0x20,0x80,0xa0 },	/* ...0...1...1...0 */
820 		{ 0x20,0x28,0xa0,0xa8 }, { 0x88,0x08,0xa8,0x28 },	/* ...0...1...1...1 */
821 		{ 0x88,0x08,0x80,0x00 }, { 0x08,0x00,0x88,0x80 },	/* ...1...0...0...0 */
822 		{ 0x08,0x00,0x88,0x80 }, { 0x88,0x08,0x80,0x00 },	/* ...1...0...0...1 */
823 		{ 0x08,0x28,0x00,0x20 }, { 0x08,0x28,0x00,0x20 },	/* ...1...0...1...0 */
824 		{ 0x88,0x08,0x80,0x00 }, { 0x08,0x28,0x00,0x20 },	/* ...1...0...1...1 */
825 		{ 0x08,0x28,0x00,0x20 }, { 0x08,0x00,0x88,0x80 },	/* ...1...1...0...0 */
826 		{ 0x08,0x28,0x00,0x20 }, { 0x20,0x28,0xa0,0xa8 },	/* ...1...1...0...1 */
827 		{ 0x20,0x28,0xa0,0xa8 }, { 0x08,0x28,0x00,0x20 },	/* ...1...1...1...0 */
828 		{ 0x20,0x28,0xa0,0xa8 }, { 0x08,0x28,0x00,0x20 }	/* ...1...1...1...1 */
829 	};
830 
831 
832 	sega_decode(convtable);
833 }
834 
835 
teddybb_decode(void)836 void teddybb_decode(void)
837 {
838 	static const unsigned char convtable[32][4] =
839 	{
840 		/*       opcode                   data                     address      */
841 		/*  A    B    C    D         A    B    C    D                           */
842 		{ 0x20,0x28,0x00,0x08 }, { 0x80,0x00,0xa0,0x20 },	/* ...0...0...0...0 */
843 		{ 0x20,0x28,0x00,0x08 }, { 0xa0,0xa8,0x20,0x28 },	/* ...0...0...0...1 */
844 		{ 0x28,0x08,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 },	/* ...0...0...1...0 */
845 		{ 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x80,0xa8,0x88 },	/* ...0...0...1...1 */
846 		{ 0x20,0x28,0x00,0x08 }, { 0x28,0x08,0xa8,0x88 },	/* ...0...1...0...0 */
847 		{ 0xa0,0xa8,0x20,0x28 }, { 0xa0,0xa8,0x20,0x28 },	/* ...0...1...0...1 */
848 		{ 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 },	/* ...0...1...1...0 */
849 		{ 0xa0,0xa8,0x20,0x28 }, { 0x28,0x08,0xa8,0x88 },	/* ...0...1...1...1 */
850 		{ 0x80,0x00,0xa0,0x20 }, { 0x80,0x00,0xa0,0x20 },	/* ...1...0...0...0 */
851 		{ 0xa0,0x20,0xa8,0x28 }, { 0xa0,0xa8,0x20,0x28 },	/* ...1...0...0...1 */
852 		{ 0xa0,0x20,0xa8,0x28 }, { 0xa0,0x80,0xa8,0x88 },	/* ...1...0...1...0 */
853 		{ 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 },	/* ...1...0...1...1 */
854 		{ 0x80,0x00,0xa0,0x20 }, { 0x20,0x28,0x00,0x08 },	/* ...1...1...0...0 */
855 		{ 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x20,0xa8,0x28 },	/* ...1...1...0...1 */
856 		{ 0x80,0x00,0xa0,0x20 }, { 0xa0,0x80,0xa8,0x88 },	/* ...1...1...1...0 */
857 		{ 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x20,0xa8,0x28 }	/* ...1...1...1...1 */
858 	};
859 
860 
861 	sega_decode(convtable);
862 }
863 
864 
myheroj_decode(void)865 void myheroj_decode(void)
866 {
867 	static const unsigned char convtable[32][4] =
868 	{
869 		/*       opcode                   data                     address      */
870 		/*  A    B    C    D         A    B    C    D                           */
871 		{ 0x20,0x00,0xa0,0x80 }, { 0x80,0xa0,0x88,0xa8 },	/* ...0...0...0...0 */
872 		{ 0x20,0x00,0xa0,0x80 }, { 0x80,0xa0,0x88,0xa8 },	/* ...0...0...0...1 */
873 		{ 0xa8,0xa0,0x88,0x80 }, { 0xa8,0xa0,0x88,0x80 },	/* ...0...0...1...0 */
874 		{ 0x08,0x88,0x00,0x80 }, { 0x80,0xa0,0x88,0xa8 },	/* ...0...0...1...1 */
875 		{ 0x20,0x00,0xa0,0x80 }, { 0x28,0xa8,0x08,0x88 },	/* ...0...1...0...0 */
876 		{ 0x20,0x00,0xa0,0x80 }, { 0x08,0x88,0x00,0x80 },	/* ...0...1...0...1 */
877 		{ 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 },	/* ...0...1...1...0 */
878 		{ 0x08,0x88,0x00,0x80 }, { 0xa8,0xa0,0x88,0x80 },	/* ...0...1...1...1 */
879 		{ 0x28,0xa8,0x08,0x88 }, { 0x20,0x00,0xa0,0x80 },	/* ...1...0...0...0 */
880 		{ 0x80,0xa0,0x88,0xa8 }, { 0x20,0x00,0xa0,0x80 },	/* ...1...0...0...1 */
881 		{ 0x80,0xa0,0x88,0xa8 }, { 0x80,0xa0,0x88,0xa8 },	/* ...1...0...1...0 */
882 		{ 0xa8,0xa0,0x88,0x80 }, { 0x80,0xa0,0x88,0xa8 },	/* ...1...0...1...1 */
883 		{ 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 },	/* ...1...1...0...0 */
884 		{ 0x88,0x80,0x08,0x00 }, { 0x08,0x88,0x00,0x80 },	/* ...1...1...0...1 */
885 		{ 0x88,0x80,0x08,0x00 }, { 0xa8,0xa0,0x88,0x80 },	/* ...1...1...1...0 */
886 		{ 0x88,0x80,0x08,0x00 }, { 0xa8,0xa0,0x88,0x80 }	/* ...1...1...1...1 */
887 	};
888 
889 
890 	sega_decode(convtable);
891 }
892 
893 
hvymetal_decode(void)894 void hvymetal_decode(void)
895 {
896 	static const unsigned char convtable[32][4] =
897 	{
898 		/*       opcode                   data                     address      */
899 		/*  A    B    C    D         A    B    C    D                           */
900 		{ 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0xa8,0x88 },	/* ...0...0...0...0 */
901 		{ 0x88,0xa8,0x80,0xa0 }, { 0x88,0x80,0x08,0x00 },	/* ...0...0...0...1 */
902 		{ 0xa0,0x80,0xa8,0x88 }, { 0x88,0xa8,0x80,0xa0 },	/* ...0...0...1...0 */
903 		{ 0x88,0xa8,0x80,0xa0 }, { 0x88,0x80,0x08,0x00 },	/* ...0...0...1...1 */
904 		{ 0xa0,0x80,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 },	/* ...0...1...0...0 */
905 		{ 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 },	/* ...0...1...0...1 */
906 		{ 0xa0,0x80,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 },	/* ...0...1...1...0 */
907 		{ 0x88,0x80,0x08,0x00 }, { 0x28,0x08,0xa8,0x88 },	/* ...0...1...1...1 */
908 		{ 0xa0,0x20,0xa8,0x28 }, { 0x88,0xa8,0x80,0xa0 },	/* ...1...0...0...0 */
909 		{ 0xa0,0x20,0xa8,0x28 }, { 0x88,0xa8,0x80,0xa0 },	/* ...1...0...0...1 */
910 		{ 0xa0,0x20,0xa8,0x28 }, { 0x88,0xa8,0x80,0xa0 },	/* ...1...0...1...0 */
911 		{ 0x88,0xa8,0x80,0xa0 }, { 0x28,0x08,0xa8,0x88 },	/* ...1...0...1...1 */
912 		{ 0x28,0xa8,0x08,0x88 }, { 0xa0,0x20,0xa8,0x28 },	/* ...1...1...0...0 */
913 		{ 0xa0,0x20,0xa8,0x28 }, { 0x28,0xa8,0x08,0x88 },	/* ...1...1...0...1 */
914 		{ 0x28,0xa8,0x08,0x88 }, { 0xa0,0x20,0xa8,0x28 },	/* ...1...1...1...0 */
915 		{ 0x28,0x08,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 }	/* ...1...1...1...1 */
916 	};
917 
918 
919 	sega_decode(convtable);
920 }
921 
922 
lvcards_decode(void)923 void lvcards_decode(void)
924 {
925 	static const unsigned char convtable[32][4] =
926 	{
927 		/*       opcode                   data                     address      */
928 		/*  A    B    C    D         A    B    C    D                           */
929 		{ 0xa8,0x88,0xa0,0x80 }, { 0xa8,0x28,0x88,0x08 },	/* ...0...0...0...0 */
930 		{ 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 },	/* ...0...0...0...1 */
931 		{ 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 },	/* ...0...0...1...0 */
932 		{ 0xa8,0xa0,0x88,0x80 }, { 0xa8,0xa0,0x88,0x80 },	/* ...0...0...1...1 */
933 		{ 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0xa0,0x20 },	/* ...0...1...0...0 */
934 		{ 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 },	/* ...0...1...0...1 */
935 		{ 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 },	/* ...0...1...1...0 */
936 		{ 0xa8,0x88,0xa0,0x80 }, { 0xa8,0x88,0xa0,0x80 },	/* ...0...1...1...1 */
937 		{ 0xa8,0x88,0xa0,0x80 }, { 0xa8,0x28,0x88,0x08 },	/* ...1...0...0...0 */
938 		{ 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 },	/* ...1...0...0...1 */
939 		{ 0xa8,0x28,0x88,0x08 }, { 0x88,0x80,0x08,0x00 },	/* ...1...0...1...0 */
940 		{ 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 },	/* ...1...0...1...1 */
941 		{ 0xa8,0x28,0x88,0x08 }, { 0xa8,0x88,0xa0,0x80 },	/* ...1...1...0...0 */
942 		{ 0xa8,0x88,0xa0,0x80 }, { 0x88,0x80,0x08,0x00 },	/* ...1...1...0...1 */
943 		{ 0x88,0x80,0x08,0x00 }, { 0xa8,0x28,0x88,0x08 },	/* ...1...1...1...0 */
944 		{ 0xa8,0x28,0x88,0x08 }, { 0xa8,0x88,0xa0,0x80 }	/* ...1...1...1...1 */
945 	};
946 
947 
948 	sega_decode(convtable);
949 }
950 
951 
952 /******************************************************************************
953 
954   4D Warriors
955 
956   This encryption is quite different from the standard one. It permutates bits
957   D0, D2, D4 and D6 without inverting them, and adds a XOR on top.
958 
959   The permutation depends on A9, A12, and A14, while the XOR depends on A0, A3,
960   and A6. Opcodes are XORed with an additional 0x40.
961 
962   There are no separate tables for data and opcodes; to make it a little more
963   complicated, however, to decode data you have to add 1 to [A14 A12 A9 A6 A3 A0].
964   For example if you are decoding a byte at address .1.0..1..1..1..1, you pick
965   the permutation and XOR as if it were at address .1.1..0..0..0..0
966 
967 ******************************************************************************/
968 
fdwarrio_decode(void)969 void fdwarrio_decode(void)
970 {
971 	static const unsigned char swaptable[8+1][4] =
972 	{
973 		/* note that this is a subset of the astrofl table */
974 		{ 6,2,4,0 },	/* .0.0..0..x..x..x */
975 		{ 6,0,2,4 },	/* .0.0..1..x..x..x */
976 		{ 6,4,0,2 },	/* .0.1..0..x..x..x */
977 		{ 2,6,4,0 },	/* .0.1..1..x..x..x */
978 		{ 4,2,6,0 },	/* .1.0..0..x..x..x */
979 		{ 4,6,0,2 },	/* .1.0..1..x..x..x */
980 		{ 6,0,4,2 },	/* .1.1..0..x..x..x */
981 		{ 0,6,4,2 },	/* .1.1..1..x..x..x */
982 		{ 4,0,6,2 }		/* extra line for data decode */
983 	};
984 	int A;
985 	unsigned char *rom = memory_region(REGION_CPU1);
986 	int diff = memory_region_length(REGION_CPU1) / 2;
987 
988 
989 	memory_set_opcode_base(0,rom+diff);
990 
991 	for (A = 0x0000;A < 0x8000;A++)
992 	{
993 		int row;
994 		unsigned char src;
995 		const unsigned char *tbl;
996 
997 
998 		src = rom[A];
999 
1000 		/* pick the translation table from bits 0, 3, 6, 9, 12 and 14 of the address */
1001 		row = (A & 1) + (((A >> 3) & 1) << 1) + (((A >> 6) & 1) << 2)
1002 				+ (((A >> 9) & 1) << 3) + (((A >> 12) & 1) << 4) + (((A >> 14) & 1) << 5);
1003 
1004 		/* decode the opcodes */
1005 		tbl = swaptable[row >> 3];
1006 		rom[A + diff] = BITSWAP8(src,7,tbl[0],5,tbl[1],3,tbl[2],1,tbl[3]) ^ 0x40;
1007 		if (row & 1) rom[A + diff] ^= 0x10;
1008 		if (row & 2) rom[A + diff] ^= 0x04;
1009 		if (row & 4) rom[A + diff] ^= 0x01;
1010 
1011 		/* decode the data */
1012 		row++;	/* the data permutation table is shifted by one position!!!! */
1013 		tbl = swaptable[row >> 3];
1014 		rom[A] = BITSWAP8(src,7,tbl[0],5,tbl[1],3,tbl[2],1,tbl[3]);
1015 		if (row & 1) rom[A] ^= 0x10;
1016 		if (row & 2) rom[A] ^= 0x04;
1017 		if (row & 4) rom[A] ^= 0x01;
1018 	}
1019 
1020 	/* copy the opcodes from the not encrypted part of the ROMs */
1021 	for (A = 0x8000;A < diff;A++)
1022 		rom[A + diff] = rom[A];
1023 }
1024 
1025 
1026 
1027 /******************************************************************************
1028 
1029   Astro Flash / Wonder Boy
1030 
1031   This is different again. It affects the same data bits and is selected by the
1032   same address lines as 4D Warriors, but the permutation and XOR values to use
1033   are selected in a much more complicated way. The XOR values repeat with a
1034   period of 12 (!!!), but the count restarts from 0 when A14 is set.
1035   The permutation is selected so that only 5 different permutations are used
1036   for 12 consecutive address masks.
1037   Like in 4D Warriors, the tables for opcodes and data are slightly misaligned.
1038 
1039 ******************************************************************************/
1040 
astrofl_decode(void)1041 void astrofl_decode(void)
1042 {
1043 	static unsigned char opcode_xor[32] =
1044 	{
1045 		0x04,0x51,0x40,0x01,0x55,0x44,0x05,0x50,0x41,0x00,0x54,0x45,0x04,0x51,0x40,0x01,
1046 		0x55,0x44,0x05,0x50,0x41,0x00,0x54,0x45,0x04,0x51,0x40,0x01,0x55,0x44,0x05,0x50,
1047 	};
1048 
1049 	static unsigned char data_xor[32] =
1050 	{
1051 		0x54,0x15,0x44,0x51,0x10,0x41,0x55,0x14,0x45,0x50,0x11,0x40,0x54,0x15,0x44,0x51,
1052 		0x10,0x41,0x55,0x14,0x45,0x50,0x11,0x40,0x54,0x15,0x44,0x51,0x10,0x41,0x55,0x14,
1053 	};
1054 
1055 	static const int opcode_swap_select[32] =
1056 	{
1057 		0,0,1,1,1,2,2,3,3,4,4,4,5,5,6,6,
1058 		6,7,7,8,8,9,9,9,10,10,11,11,11,12,12,13,
1059 	};
1060 
1061 	static const int data_swap_select[32] =
1062 	{
1063 		0,0,1,1,2,2,2,3,3,4,4,5,5,5,6,6,
1064 		7,7,7,8,8,9,9,10,10,10,11,11,12,12,12,13,
1065 	};
1066 
1067 	static const unsigned char swaptable[22][4] =
1068 	{
1069 		{ 6,4,2,0 },
1070 		{ 4,6,2,0 },
1071 		{ 2,4,6,0 },
1072 		{ 0,4,2,6 },
1073 		{ 6,2,4,0 },
1074 		{ 6,0,2,4 },
1075 		{ 6,4,0,2 },
1076 		{ 2,6,4,0 },
1077 
1078 		{ 4,2,6,0 },
1079 		{ 4,6,0,2 },
1080 		{ 6,0,4,2 },
1081 		{ 0,6,4,2 },
1082 		{ 4,0,6,2 },
1083 		{ 0,4,6,2 },
1084 		{ 6,2,0,4 },
1085 		{ 2,6,0,4 },
1086 
1087 		{ 0,6,2,4 },
1088 		{ 2,0,6,4 },
1089 		{ 0,2,6,4 },
1090 		{ 4,2,0,6 },
1091 		{ 2,4,0,6 },
1092 		{ 4,0,2,6 }
1093 /*		{ 2,0,4,6 }*/
1094 /*		{ 0,2,4,6 }*/
1095 	};
1096 	int A;
1097 	unsigned char *rom = memory_region(REGION_CPU1);
1098 	int diff = memory_region_length(REGION_CPU1) / 2;
1099 
1100 
1101 	memory_set_opcode_base(0,rom+diff);
1102 
1103 	for (A = 0x0000;A < 0x8000;A++)
1104 	{
1105 		int row;
1106 		unsigned char src;
1107 		const unsigned char *tbl;
1108 
1109 
1110 		src = rom[A];
1111 
1112 		/* pick the translation table from bits 0, 3, 6, 9, 12 and 14 of the address */
1113 		row = (A & 1) + (((A >> 3) & 1) << 1) + (((A >> 6) & 1) << 2)
1114 				+ (((A >> 9) & 1) << 3) + (((A >> 12) & 1) << 4) + (((A >> 14) & 1) << 5);
1115 
1116 		/* decode the opcodes */
1117 		tbl = swaptable[opcode_swap_select[row & 0x1f] + 8 * ((row & 0x20) >> 5)];
1118 		rom[A + diff] = BITSWAP8(src,7,tbl[0],5,tbl[1],3,tbl[2],1,tbl[3]) ^ opcode_xor[row & 0x1f];
1119 
1120 		/* decode the data */
1121 		tbl = swaptable[data_swap_select[row & 0x1f] + 8 * ((row & 0x20) >> 5)];
1122 		rom[A] = BITSWAP8(src,7,tbl[0],5,tbl[1],3,tbl[2],1,tbl[3]) ^ data_xor[row & 0x1f];
1123 	}
1124 
1125 	/* copy the opcodes from the not encrypted part of the ROMs */
1126 	for (A = 0x8000;A < diff;A++)
1127 		rom[A + diff] = rom[A];
1128 }
1129 
1130 
wboy2_decode(void)1131 void wboy2_decode(void)
1132 {
1133 	static unsigned char opcode_xor[32] =
1134 	{
1135 		0x00,0x45,0x11,0x01,0x44,0x10,0x55,0x05,0x41,0x14,0x04,0x40,0x15,0x51,0x01,0x44,
1136 		0x10,0x00,0x45,0x11,0x54,0x04,0x40,0x15,0x05,0x41,0x14,0x50,0x00,0x45,0x11,0x01,
1137 	};
1138 
1139 	static unsigned char data_xor[32] =
1140 	{
1141 		0x55,0x05,0x41,0x14,0x50,0x00,0x15,0x51,0x01,0x44,0x10,0x55,0x05,0x11,0x54,0x04,
1142 		0x40,0x15,0x51,0x01,0x14,0x50,0x00,0x45,0x11,0x54,0x04,0x10,0x55,0x05,0x41,0x14,
1143 	};
1144 
1145 	static const int opcode_swap_select[32] =
1146 	{
1147 		2,
1148 		5,1,5,1,5,
1149 		0,4,0,4,0,4,
1150 
1151 		7,3,7,3,7,3,
1152 		6,2,6,2,6,
1153 		1,5,1,5,1,5,
1154 		0,4,0
1155 	};
1156 
1157 	static const int data_swap_select[32] =
1158 	{
1159 		3,7,3,7,3,7,
1160 		2,6,2,6,2,
1161 		5,1,5,1,5,1,
1162 		4,0,4,0,4,
1163 
1164 		8,
1165 		3,7,3,7,3,
1166 		6,2,6,2
1167 	};
1168 
1169 	static const unsigned char swaptable[17][4] =
1170 	{
1171 		/* note that this is a subset of the astrofl table */
1172 		{ 6,4,2,0 },
1173 		{ 4,6,2,0 },
1174 		{ 2,4,6,0 },
1175 		{ 0,4,2,6 },
1176 		{ 6,2,4,0 },
1177 		{ 6,0,2,4 },
1178 		{ 6,4,0,2 },
1179 		{ 2,6,4,0 },
1180 
1181 		{ 4,2,6,0 },
1182 		{ 4,6,0,2 },
1183 		{ 6,0,4,2 },
1184 		{ 0,6,4,2 },
1185 		{ 4,0,6,2 },
1186 		{ 0,4,6,2 },
1187 		{ 6,2,0,4 },
1188 		{ 2,6,0,4 },
1189 
1190 		{ 0,6,2,4 }
1191 	};
1192 	int A;
1193 	unsigned char *rom = memory_region(REGION_CPU1);
1194 	int diff = memory_region_length(REGION_CPU1) / 2;
1195 
1196 
1197 	memory_set_opcode_base(0,rom+diff);
1198 
1199 	for (A = 0x0000;A < 0x8000;A++)
1200 	{
1201 		int row;
1202 		unsigned char src;
1203 		const unsigned char *tbl;
1204 
1205 
1206 		src = rom[A];
1207 
1208 		/* pick the translation table from bits 0, 3, 6, 9, 12 and 14 of the address */
1209 		row = (A & 1) + (((A >> 3) & 1) << 1) + (((A >> 6) & 1) << 2)
1210 				+ (((A >> 9) & 1) << 3) + (((A >> 12) & 1) << 4) + (((A >> 14) & 1) << 5);
1211 
1212 		/* decode the opcodes */
1213 		tbl = swaptable[opcode_swap_select[row & 0x1f] + 8 * ((row & 0x20) >> 5)];
1214 		rom[A + diff] = BITSWAP8(src,7,tbl[0],5,tbl[1],3,tbl[2],1,tbl[3]) ^ opcode_xor[row & 0x1f];
1215 
1216 		/* decode the data */
1217 		tbl = swaptable[data_swap_select[row & 0x1f] + 8 * ((row & 0x20) >> 5)];
1218 		rom[A] = BITSWAP8(src,7,tbl[0],5,tbl[1],3,tbl[2],1,tbl[3]) ^ data_xor[row & 0x1f];
1219 	}
1220 
1221 	/* copy the opcodes from the not encrypted part of the ROMs */
1222 	for (A = 0x8000;A < diff;A++)
1223 		rom[A + diff] = rom[A];
1224 }
1225 
1226 
1227 /* Gardia / Space Position */
1228 /******************************************************************************
1229 
1230   New encryption
1231 
1232   This encryption is quite different from the older one. It permutates bits
1233   D0, D2, D4 and D6, then inverts some of them.
1234 
1235   The permutation and inversion depend on A0, A3, A6, A9, A12, and A14.
1236 
1237 ******************************************************************************/
1238 
sega_decode_2(const unsigned char opcode_xor[64],const int opcode_swap_select[64],const unsigned char data_xor[64],const int data_swap_select[64])1239 static void sega_decode_2(const unsigned char opcode_xor[64],const int opcode_swap_select[64],
1240 		const unsigned char data_xor[64],const int data_swap_select[64])
1241 {
1242 	int A;
1243 	unsigned char *rom = memory_region(REGION_CPU1);
1244 	int diff = memory_region_length(REGION_CPU1) / 2;
1245 	static const unsigned char swaptable[24][4] =
1246 	{
1247 		{ 6,4,2,0 }, { 4,6,2,0 }, { 2,4,6,0 }, { 0,4,2,6 },
1248 		{ 6,2,4,0 }, { 6,0,2,4 }, { 6,4,0,2 }, { 2,6,4,0 },
1249 		{ 4,2,6,0 }, { 4,6,0,2 }, { 6,0,4,2 }, { 0,6,4,2 },
1250 		{ 4,0,6,2 }, { 0,4,6,2 }, { 6,2,0,4 }, { 2,6,0,4 },
1251 		{ 0,6,2,4 }, { 2,0,6,4 }, { 0,2,6,4 }, { 4,2,0,6 },
1252 		{ 2,4,0,6 }, { 4,0,2,6 }, { 2,0,4,6 }, { 0,2,4,6 },
1253 	};
1254 
1255 
1256 	memory_set_opcode_base(0,rom+diff);
1257 
1258 	for (A = 0x0000;A < 0x8000;A++)
1259 	{
1260 		int row;
1261 		unsigned char src;
1262 		const unsigned char *tbl;
1263 
1264 
1265 		src = rom[A];
1266 
1267 		/* pick the translation table from bits 0, 3, 6, 9, 12 and 14 of the address */
1268 		row = (A & 1) + (((A >> 3) & 1) << 1) + (((A >> 6) & 1) << 2)
1269 				+ (((A >> 9) & 1) << 3) + (((A >> 12) & 1) << 4) + (((A >> 14) & 1) << 5);
1270 
1271 		/* decode the opcodes */
1272 		tbl = swaptable[opcode_swap_select[row]];
1273 		rom[A + diff] = BITSWAP8(src,7,tbl[0],5,tbl[1],3,tbl[2],1,tbl[3]) ^ opcode_xor[row];
1274 
1275 		/* decode the data */
1276 		tbl = swaptable[data_swap_select[row]];
1277 		rom[A] = BITSWAP8(src,7,tbl[0],5,tbl[1],3,tbl[2],1,tbl[3]) ^ data_xor[row];
1278 	}
1279 
1280 	/* copy the opcodes from the not encrypted part of the ROMs */
1281 	for (A = 0x8000;A < diff;A++)
1282 		rom[A + diff] = rom[A];
1283 }
1284 
1285 /******************************************************************************
1286 
1287   These games (all 317-xxxx CPUs) use the same algorithm, but the key doesn't
1288   change much - just one or two positions shift in the table.
1289 
1290 ******************************************************************************/
1291 
sega_decode_317(int order,int opcode_shift,int data_shift)1292 static void sega_decode_317(int order, int opcode_shift, int data_shift)
1293 {
1294 	static const unsigned char xor1_317[1+64] =
1295 	{
1296 		0x54,
1297 		0x14,0x15,0x41,0x14,0x50,0x55,0x05,0x41,0x01,0x10,0x51,0x05,0x11,0x05,0x14,0x55,
1298 		0x41,0x05,0x04,0x41,0x14,0x10,0x45,0x50,0x00,0x45,0x00,0x00,0x00,0x45,0x00,0x00,
1299 		0x54,0x04,0x15,0x10,0x04,0x05,0x11,0x44,0x04,0x01,0x05,0x00,0x44,0x15,0x40,0x45,
1300 		0x10,0x15,0x51,0x50,0x00,0x15,0x51,0x44,0x15,0x04,0x44,0x44,0x50,0x10,0x04,0x04,
1301 	};
1302 
1303 	static const unsigned char xor2_317[2+64] =
1304 	{
1305 		0x04,
1306 		0x44,
1307 		0x15,0x51,0x41,0x10,0x15,0x54,0x04,0x51,0x05,0x55,0x05,0x54,0x45,0x04,0x10,0x01,
1308 		0x51,0x55,0x45,0x55,0x45,0x04,0x55,0x40,0x11,0x15,0x01,0x40,0x01,0x11,0x45,0x44,
1309 		0x40,0x05,0x15,0x15,0x01,0x50,0x00,0x44,0x04,0x50,0x51,0x45,0x50,0x54,0x41,0x40,
1310 		0x14,0x40,0x50,0x45,0x10,0x05,0x50,0x01,0x40,0x01,0x50,0x50,0x50,0x44,0x40,0x10,
1311 	};
1312 
1313 	static const int swap1_317[1+64] =
1314 	{
1315 		 7,
1316 		 1,11,23,17,23, 0,15,19,
1317 		20,12,10, 0,18,18, 5,20,
1318 		13, 0,18,14, 5, 6,10,21,
1319 		 1,11, 9, 3,21, 4, 1,17,
1320 		 5, 7,16,13,19,23,20, 2,
1321 		10,23,23,15,10,12, 0,22,
1322 		14, 6,15,11,17,15,21, 0,
1323 		 6, 1, 1,18, 5,15,15,20,
1324 	};
1325 
1326 	static const int swap2_317[2+64] =
1327 	{
1328 		 7,
1329 		12,
1330 		18, 8,21, 0,22,21,13,21,
1331 		20,13,20,14, 6, 3, 5,20,
1332 		 8,20, 4, 8,17,22, 0, 0,
1333 		 6,17,17, 9, 0,16,13,21,
1334 		 3, 2,18, 6,11, 3, 3,18,
1335 		18,19, 3, 0, 5, 0,11, 8,
1336 		 8, 1, 7, 2,10, 8,10, 2,
1337 		 1, 3,12,16, 0,17,10, 1,
1338 	};
1339 
1340 	if (order)
1341 		sega_decode_2( xor2_317+opcode_shift, swap2_317+opcode_shift, xor1_317+data_shift, swap1_317+data_shift );
1342 	else
1343 		sega_decode_2( xor1_317+opcode_shift, swap1_317+opcode_shift, xor2_317+data_shift, swap2_317+data_shift );
1344 }
1345 
spcpostn_decode(void)1346 void spcpostn_decode(void)	{ sega_decode_317( 0, 0, 1 ); }
gardia_decode(void)1347 void gardia_decode(void)	{ sega_decode_317( 1, 1, 1 ); }
gardiab_decode(void)1348 void gardiab_decode(void)	{ sega_decode_317( 0, 1, 2 ); }
1349