/****************************************************************************** Sega encryption emulation by Nicola Salmoria Several Sega Z80 games have program ROMs encrypted using a common algorithm (but with a different key). The hardware used to implement this encryption is either a custom CPU, or an epoxy block which probably contains a standard Z80 + PALs. The encryption affects D3, D5, and D7, and depends on M1, A0, A4, A8 and A12. D0, D1, D3, D4 and D6 are always unaffected. The encryption consists of a permutation of the three bits, which can also be inverted. Therefore there are 3! * 2^3 = 48 different possible encryptions. For simplicity, the decryption is implemented using conversion tables. We need 32 of these tables, one for every possible combination of M1, A0, A4, A8 and A12. However, all the games currently known are full of repetitions and only use 6 different tables, the only exceptions being Pengo, Yamato and Spatter which have 7 (but one of them is the identity: { 0x00, 0x08, 0x20, 0x28 } ). This is most likely a limitation of the hardware. Some of the early games are even weaker: of the 6 different tables, they use 3 for opcodes and 3 for data, and always coupled in the same way. In all games currently known, only bytes in the memory range 0x0000-0x7fff (A15 = 0) are encrypted. My guess is that this was done to allow games to copy code to RAM (in the memory range 0x8000-0xffff) and execute it from there without the CPU trying to decrypt it and messing everything up. However Zaxxon has RAM at 0x6000, and the CPU doesn't seem to interfere with it; but it doesn't execute code from there, so it's possible that the CPU is encrypting the data while writing it and decrypting it while reading (that would seem kind of strange though). Video and sprite RAM and memory mapped ports are all placed above 0x8000. Given its strict limitations, this encryption is reasonably easy to break, and very vulnerable to known plaintext attacks. Ninja Princess: there is a (bootleg?) board which has a standard Z80 + 2 bipolar PROMs instead of the custom CPU. The encryption table is different from the original Ninja Princess; it is actually the same as Flicky. The first PROM is 32x8 and contains the number (0..5) of the table to use depending on M1, A0, A4, A8, A12: 00: 11 00 33 22 00 44 44 00 11 33 33 22 44 44 44 22 10: 11 55 55 33 44 22 55 22 11 33 55 33 44 44 11 22 The second PROM is 256x4 and contains the 6 different XOR tables: A D B C C B D A 00: 09 09 0A 0A 0A 0A 09 09 08: 0E 08 0B 0D 0D 0B 08 0E 10: 0A 0C 0A 0C 0C 0A 0C 0A 18: 0B 0E 0E 0B 0B 0E 0E 0B 20: 0C 0C 0F 0F 0F 0F 0C 0C 28: 08 0D 0B 0E 0E 0B 0D 08 [the remaining bytes are all 0F] bit 3 is not used. bits 0-2 is the XOR code inverted (0 = 0xa8, 1 = 0xa0 ... 6 = 0x08 7 = 0x00) Here is a diagram showing how it works: data to XOR decode value A --- D7 --------------- 0| | D3 --------------- 1| | D5 --------------- 2| P |D A --- D | R |0 ---|>--- D3 M1 --- 0| P |0 --- 3| O |1 ---|>--- D5 A0 --- 1| R |1 --- 4| M |2 ---|>--- D7 A4 --- 2| O |2 --- 5| 2 |3 --- A8 --- 3| M |3 --- 6| | A12 --- 4| 1 |4 --- 7| | --- --- My Hero: the bootleg does the decryption using a single 256x4 PROM, mapped in the obvious way: data to XOR decode value A --- D3 --- 0| | D5 --- 1| |D D7 --- 2| P |0 --- D3 A0 --- 3| R |1 --- D5 A4 --- 4| O |2 --- D7 A8 --- 5| M |3 --- A12 --- 6| | M1 --- 7| | --- List of encrypted games currently known: CPU Part # Game Comments ???-???? Buck Rogers unencrypted version available 315-5010 Pengo unencrypted version available 315-5013 Super Zaxxon used Zaxxon for known plaintext attack ???-???? Super Locomotive 315-5018 Yamato ???-???? Top Roller same key as Yamato 315-5028 Sindbad Mystery 315-5030 Up'n Down & unencrypted version available ???-???? M120 Razzmatazz 315-5033 Regulus unencrypted version available 315-5041 M140 Mister Viking 315-5048 SWAT used Bull Fight for k.p.a. 315-5051 Flicky & Ninja Princess (bootleg) 315-5061 Future Spy 315-5064 Water Match used Mister Viking for k.p.a. 315-5065 Bull Fight 315-5069 Star Force game by Tehkan; same key as Super Locomotive ???-???? Pinball Action game by Tehkan; also has a simple bitswap on top ???-???? Spatter 315-5084 Jongkyo TABLE INCOMPLETE game by Kiwako; also has a simple bitswap on top 315-5093 Pitfall II 315-5098 Ninja Princess unencrypted version available; same key as Up'n Down 315-5102 Sega Ninja unencrypted version available 315-5110 I'm Sorry used My Hero for k.p.a. 315-5114 ?? pcb 834-5492 same key as Regulus 315-5115 TeddyBoy Blues 315-5132 My Hero 315-5135 Heavy Metal & Wonder Boy (set 1a & 3; bootlegs?) ???-???? Lovely Cards The following games use a different encryption algorithm: 315-5162 4D Warriors & used I'm Sorry for k.p.a. Rafflesia & Wonder Boy (set 4) 315-5177 Astro Flash & Wonder Boy (set 1) 315-5178 Wonder Boy (set 2) unencrypted version available 315-5179 Robo-Wrestle 2001 The following games seem to use the same algorithm as the above ones, but using a key which almost doesn't change 317-0004 Calorie Kun unencrypted bootleg available 317-0005 Space Position 317-0006 Gardia (set 1) 317-0007 Gardia (set 2) Some text found in the ROMs: Buck Rogers SECULITY BY MASATOSHI,MIZUNAGA Super Locomotive SEGA FUKUMURA MIZUNAGA Yamato SECULITY BY M,MIZUNAGA Regulus SECULITY BY SYUICHI,KATAGI Up'n Down 19/SEP 1983 MASATOSHI,MIZUNAGA Mister Viking SECURITY BY S.KATAGI CONTROL CHIP M140 SWAT SECURITY BY S.KATAGI Flicky SECURITY BY S.KATAGI Water Match PROGRAMED BY KAWAHARA&NAKAGAWA Star Force STAR FORCE TEHKAN. SECURITY BY SEGA ENTERPRISESE ******************************************************************************/ #include "driver.h" #include "segacrpt.h" #if 0 static void lfkp(int mask) { int A; UINT8 *RAM = memory_region(REGION_CPU1); for (A = 0x0000;A < 0x8000-14;A++) { static char text[] = "INSERT COIN"; int i; if ( (RAM[A+0] & mask) == (0x21 & mask) && /* LD HL,$xxxx */ (RAM[A+3] & mask) == (0x11 & mask) && /* LD DE,$xxxx */ (RAM[A+6] & mask) == (0x01 & mask)) /* LD BC,$xxxx */ { if ( (RAM[A+ 9] & mask) == (0x36 & mask) && /* LD (HL),$xx */ (RAM[A+11] & mask) == (0xed & mask) && (RAM[A+12] & mask) == (0xb0 & mask)) /* LDIR */ logerror("%04x: hl de bc (hl),xx ldir\n",A); if ( (RAM[A+ 9] & mask) == (0x77 & mask) && /* LD (HL),A */ (RAM[A+10] & mask) == (0xed & mask) && (RAM[A+11] & mask) == (0xb0 & mask)) /* LDIR */ logerror("%04x: hl de bc (hl),a ldir\n",A); if ( (RAM[A+ 9] & mask) == (0xed & mask) && (RAM[A+10] & mask) == (0xb0 & mask)) /* LDIR */ logerror("%04x: hl de bc ldir\n",A); } /* the following can also be PUSH IX, PUSH IY - need better checking */ if ( (RAM[A+0] & mask) == (0xf5 & mask) && /* PUSH AF */ (RAM[A+1] & mask) == (0xc5 & mask) && /* PUSH BC */ (RAM[A+2] & mask) == (0xd5 & mask) && /* PUSH DE */ (RAM[A+3] & mask) == (0xe5 & mask)) /* PUSH HL */ logerror("%04x: push af bc de hl\n",A); if ( (RAM[A+0] & mask) == (0xe1 & mask) && /* POP HL */ (RAM[A+1] & mask) == (0xd1 & mask) && /* POP DE */ (RAM[A+2] & mask) == (0xc1 & mask) && /* POP BC */ (RAM[A+3] & mask) == (0xf1 & mask)) /* POP AF */ logerror("%04x: pop hl de bc af\n",A); for (i = 0;i < strlen(text);i++) if ((RAM[A+i] & mask) != (text[i] & mask)) break; if (i == strlen(text)) logerror("%04x: INSERT COIN\n",A); } } static void look_for_known_plaintext(void) { lfkp(0x57); } #endif static void sega_decode(const UINT8 convtable[32][4]) { int A; int length = memory_region_length(REGION_CPU1); int cryptlen = MIN(length, 0x8000); UINT8 *rom = memory_region(REGION_CPU1); UINT8 *decrypted = auto_malloc(0xc000); memory_set_decrypted_region(0, 0x0000, cryptlen - 1, decrypted); for (A = 0x0000;A < cryptlen;A++) { int xor = 0; UINT8 src = rom[A]; /* pick the translation table from bits 0, 4, 8 and 12 of the address */ int row = (A & 1) + (((A >> 4) & 1) << 1) + (((A >> 8) & 1) << 2) + (((A >> 12) & 1) << 3); /* pick the offset in the table from bits 3 and 5 of the source data */ int col = ((src >> 3) & 1) + (((src >> 5) & 1) << 1); /* the bottom half of the translation table is the mirror image of the top */ if (src & 0x80) { col = 3 - col; xor = 0xa8; } /* decode the opcodes */ decrypted[A] = (src & ~0xa8) | (convtable[2*row][col] ^ xor); /* decode the data */ rom[A] = (src & ~0xa8) | (convtable[2*row+1][col] ^ xor); if (convtable[2*row][col] == 0xff) /* table incomplete! (for development) */ decrypted[A] = 0xee; if (convtable[2*row+1][col] == 0xff) /* table incomplete! (for development) */ rom[A] = 0xee; } /* this is a kludge to catch anyone who has code that crosses the encrypted/ */ /* decrypted boundary. ssanchan does it */ if (length > 0x8000) { int bytes = MIN(length - 0x8000, 0x4000); memcpy(&decrypted[0x8000], &rom[0x8000], bytes); } } void buckrog_decode(void) { static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...0...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...0...0...1 */ { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...1...0 */ { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...1...1 */ { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...1...0...0 */ { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...0...1 */ { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...1...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...1...1...1 */ { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...0...0...0 */ { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...0...1 */ { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...1...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...1...1 */ { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...1...0...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...1 */ { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...1...0 */ { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 } /* ...1...1...1...1 */ }; sega_decode(convtable); } void pengo_decode(void) { static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0xa0,0x80,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...0...0 */ { 0x28,0xa8,0x08,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...0...1 */ { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...0...1...0 */ { 0x08,0x28,0x88,0xa8 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...1 */ { 0x08,0x00,0x88,0x80 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...1...0...0 */ { 0xa0,0x80,0x20,0x00 }, { 0x08,0x00,0x88,0x80 }, /* ...0...1...0...1 */ { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...1...1...0 */ { 0xa0,0x80,0x20,0x00 }, { 0x00,0x08,0x20,0x28 }, /* ...0...1...1...1 */ { 0x88,0x80,0x08,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...0...0 */ { 0x88,0x80,0x08,0x00 }, { 0x00,0x08,0x20,0x28 }, /* ...1...0...0...1 */ { 0x08,0x28,0x88,0xa8 }, { 0x08,0x28,0x88,0xa8 }, /* ...1...0...1...0 */ { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...1...1 */ { 0x08,0x00,0x88,0x80 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...0 */ { 0x00,0x08,0x20,0x28 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...1 */ { 0x08,0x28,0x88,0xa8 }, { 0x08,0x28,0x88,0xa8 }, /* ...1...1...1...0 */ { 0x08,0x00,0x88,0x80 }, { 0xa0,0x80,0x20,0x00 } /* ...1...1...1...1 */ }; sega_decode(convtable); } void szaxxon_decode(void) { static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...0...0 */ { 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...1 */ { 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 }, /* ...0...0...1...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...1...1 */ { 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...0...1 */ { 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 }, /* ...0...1...1...0 */ { 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...1...1 */ { 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...0...1 */ { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...1...0 */ { 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 }, /* ...1...0...1...1 */ { 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 }, /* ...1...1...0...0 */ { 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 }, /* ...1...1...0...1 */ { 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...1...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 } /* ...1...1...1...1 */ }; sega_decode(convtable); } void suprloco_decode(void) { static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...0...0 */ { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...0...1 */ { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...1...0 */ { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...1 */ { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...1...0...0 */ { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...0...1 */ { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...1...1...0 */ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...1...1 */ { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...0...0...0 */ { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...0...1 */ { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...1...0 */ { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...0...1...1 */ { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...1...0...0 */ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...1 */ { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...1...1...0 */ { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 } /* ...1...1...1...1 */ }; sega_decode(convtable); } void yamato_decode(void) { static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0x88,0xa8,0x08,0x28 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...0 */ { 0x20,0xa0,0x28,0xa8 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...1 */ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...1...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0x20,0xa0,0x28,0xa8 }, /* ...0...0...1...1 */ { 0x88,0xa8,0x08,0x28 }, { 0x88,0xa8,0x08,0x28 }, /* ...0...1...0...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...1...0...1 */ { 0x20,0xa0,0x28,0xa8 }, { 0x20,0xa0,0x28,0xa8 }, /* ...0...1...1...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...1...1...1 */ { 0x20,0xa0,0x28,0xa8 }, { 0x88,0xa8,0x08,0x28 }, /* ...1...0...0...0 */ { 0x20,0xa0,0x28,0xa8 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...0...1 */ { 0xa0,0x20,0x80,0x00 }, { 0x20,0xa0,0x28,0xa8 }, /* ...1...0...1...0 */ { 0x28,0x20,0xa8,0xa0 }, { 0x20,0xa0,0x28,0xa8 }, /* ...1...0...1...1 */ { 0x20,0xa0,0x28,0xa8 }, { 0x88,0xa8,0x08,0x28 }, /* ...1...1...0...0 */ { 0x88,0xa8,0x08,0x28 }, { 0x88,0xa8,0x08,0x28 }, /* ...1...1...0...1 */ { 0xa0,0x20,0x80,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...1...1...1...0 */ { 0x20,0xa0,0x28,0xa8 }, { 0x00,0x08,0x20,0x28 } /* ...1...1...1...1 */ }; sega_decode(convtable); } void toprollr_decode(void) { /* same tables as in Yamato, but encrypted ROM is banked */ UINT8 *decrypted; static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0x88,0xa8,0x08,0x28 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...0 */ { 0x20,0xa0,0x28,0xa8 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...1 */ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...1...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0x20,0xa0,0x28,0xa8 }, /* ...0...0...1...1 */ { 0x88,0xa8,0x08,0x28 }, { 0x88,0xa8,0x08,0x28 }, /* ...0...1...0...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...1...0...1 */ { 0x20,0xa0,0x28,0xa8 }, { 0x20,0xa0,0x28,0xa8 }, /* ...0...1...1...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...1...1...1 */ { 0x20,0xa0,0x28,0xa8 }, { 0x88,0xa8,0x08,0x28 }, /* ...1...0...0...0 */ { 0x20,0xa0,0x28,0xa8 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...0...1 */ { 0xa0,0x20,0x80,0x00 }, { 0x20,0xa0,0x28,0xa8 }, /* ...1...0...1...0 */ { 0x28,0x20,0xa8,0xa0 }, { 0x20,0xa0,0x28,0xa8 }, /* ...1...0...1...1 */ { 0x20,0xa0,0x28,0xa8 }, { 0x88,0xa8,0x08,0x28 }, /* ...1...1...0...0 */ { 0x88,0xa8,0x08,0x28 }, { 0x88,0xa8,0x08,0x28 }, /* ...1...1...0...1 */ { 0xa0,0x20,0x80,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...1...1...1...0 */ { 0x20,0xa0,0x28,0xa8 }, { 0x00,0x08,0x20,0x28 } /* ...1...1...1...1 */ }; int A; UINT8 *rom = memory_region(REGION_USER1); int bankstart; decrypted = auto_malloc(0x6000*3); for(bankstart=0;bankstart<0x6000*3;bankstart+=0x6000) for (A = 0x0000;A < 0x6000;A++) { int xor = 0; UINT8 src = rom[A+bankstart]; /* pick the translation table from bits 0, 4, 8 and 12 of the address */ int row = (A & 1) + (((A >> 4) & 1) << 1) + (((A >> 8) & 1) << 2) + (((A >> 12) & 1) << 3); /* pick the offset in the table from bits 3 and 5 of the source data */ int col = ((src >> 3) & 1) + (((src >> 5) & 1) << 1); /* the bottom half of the translation table is the mirror image of the top */ if (src & 0x80) { col = 3 - col; xor = 0xa8; } /* decode the opcodes */ decrypted[A+bankstart] = (src & ~0xa8) | (convtable[2*row][col] ^ xor); /* decode the data */ rom[A+bankstart] = (src & ~0xa8) | (convtable[2*row+1][col] ^ xor); } memory_configure_bank(1,0,3, memory_region(REGION_USER1),0x6000); memory_configure_bank_decrypted(1,0,3,decrypted,0x6000); memory_set_decrypted_region(0, 0x0000, 0x5fff, decrypted); memory_set_bank(1, 0); } void sindbadm_decode(void) { static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...0 */ { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...0...0...1 */ { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...0...1...0 */ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...1...1 */ { 0xa8,0x88,0xa0,0x80 }, { 0xa0,0x20,0xa8,0x28 }, /* ...0...1...0...0 */ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...1 */ { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...1...1...0 */ { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...1...1...1 */ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...0 */ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...1 */ { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...1...0...1...0 */ { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...1...0...1...1 */ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...0 */ { 0xa8,0x88,0xa0,0x80 }, { 0xa0,0x20,0xa8,0x28 }, /* ...1...1...0...1 */ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...1...0 */ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 } /* ...1...1...1...1 */ }; sega_decode(convtable); } void regulus_decode(void) { static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0x28,0x08,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...0 */ { 0x28,0x08,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...0...1 */ { 0x88,0x80,0x08,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...0 */ { 0x88,0x08,0x80,0x00 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...1...1 */ { 0x28,0x08,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...0 */ { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...1 */ { 0x88,0x08,0x80,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...1...1...0 */ { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...1...1...1 */ { 0x80,0xa0,0x00,0x20 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...0...0 */ { 0x28,0xa8,0x08,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...0...1 */ { 0x80,0xa0,0x00,0x20 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...1...0 */ { 0x28,0xa8,0x08,0x88 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...1...1 */ { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...1...0...0 */ { 0x80,0xa0,0x00,0x20 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...1...0...1 */ { 0xa0,0x80,0xa8,0x88 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...1...1...0 */ { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 } /* ...1...1...1...1 */ }; sega_decode(convtable); } void mrviking_decode(void) { static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...0 */ { 0x88,0x08,0x80,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...1 */ { 0x28,0x08,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...1...0 */ { 0x88,0x08,0x80,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...1 */ { 0x28,0x08,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...0 */ { 0x88,0x80,0x08,0x00 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...1...0...1 */ { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...0 */ { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...1...1...1 */ { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...0 */ { 0x88,0x08,0x80,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...1 */ { 0xa0,0x80,0x20,0x00 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...1...0 */ { 0xa0,0x80,0x20,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...1...0...1...1 */ { 0x28,0x08,0xa8,0x88 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...0 */ { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...1 */ { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...1...1...0 */ { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0xa8,0x88 } /* ...1...1...1...1 */ }; sega_decode(convtable); } void swat_decode(void) { static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0x88,0x08,0x80,0x00 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...0...0...0 */ { 0x88,0x08,0x80,0x00 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...1 */ { 0xa0,0x80,0x20,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...0 */ { 0xa0,0xa8,0x80,0x88 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...1 */ { 0x28,0x20,0xa8,0xa0 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...1...0...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...0...1 */ { 0xa0,0x80,0x20,0x00 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...1...1...0 */ { 0x28,0x20,0xa8,0xa0 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...1...1...1 */ { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...0...0 */ { 0xa0,0x20,0x80,0x00 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...1 */ { 0xa0,0x20,0x80,0x00 }, { 0xa0,0x20,0x80,0x00 }, /* ...1...0...1...0 */ { 0xa0,0x20,0x80,0x00 }, { 0xa0,0x20,0x80,0x00 }, /* ...1...0...1...1 */ { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...1...0...1 */ { 0xa0,0xa8,0x80,0x88 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...1...0 */ { 0x28,0x20,0xa8,0xa0 }, { 0xa0,0xa8,0x80,0x88 } /* ...1...1...1...1 */ }; sega_decode(convtable); } void flicky_decode(void) { static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0x08,0x88,0x00,0x80 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...0...0 */ { 0x80,0x00,0xa0,0x20 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...1 */ { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0x20,0x00 }, /* ...0...0...1...0 */ { 0x28,0x08,0x20,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...1 */ { 0x08,0x88,0x00,0x80 }, { 0x80,0x00,0xa0,0x20 }, /* ...0...1...0...0 */ { 0x80,0x00,0xa0,0x20 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...1 */ { 0x28,0x08,0x20,0x00 }, { 0x28,0x08,0x20,0x00 }, /* ...0...1...1...0 */ { 0x28,0x08,0x20,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...1...1 */ { 0x08,0x88,0x00,0x80 }, { 0xa8,0x88,0x28,0x08 }, /* ...1...0...0...0 */ { 0xa8,0x88,0x28,0x08 }, { 0x80,0x00,0xa0,0x20 }, /* ...1...0...0...1 */ { 0x28,0x08,0x20,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...1...0 */ { 0xa8,0x88,0x28,0x08 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...1...1 */ { 0x08,0x88,0x00,0x80 }, { 0x80,0x00,0xa0,0x20 }, /* ...1...1...0...0 */ { 0xa8,0x88,0x28,0x08 }, { 0x80,0x00,0xa0,0x20 }, /* ...1...1...0...1 */ { 0x28,0x08,0x20,0x00 }, { 0x28,0x08,0x20,0x00 }, /* ...1...1...1...0 */ { 0x08,0x88,0x00,0x80 }, { 0x88,0x80,0x08,0x00 } /* ...1...1...1...1 */ }; sega_decode(convtable); } void futspy_decode(void) { static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0x28,0x08,0x20,0x00 }, { 0x28,0x08,0x20,0x00 }, /* ...0...0...0...0 */ { 0x80,0x00,0xa0,0x20 }, { 0x08,0x88,0x00,0x80 }, /* ...0...0...0...1 */ { 0x80,0x00,0xa0,0x20 }, { 0x08,0x88,0x00,0x80 }, /* ...0...0...1...0 */ { 0xa0,0x80,0x20,0x00 }, { 0x20,0x28,0xa0,0xa8 }, /* ...0...0...1...1 */ { 0x28,0x08,0x20,0x00 }, { 0x88,0x80,0xa8,0xa0 }, /* ...0...1...0...0 */ { 0x80,0x00,0xa0,0x20 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...0...1 */ { 0x80,0x00,0xa0,0x20 }, { 0x20,0x28,0xa0,0xa8 }, /* ...0...1...1...0 */ { 0x20,0x28,0xa0,0xa8 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...1...1 */ { 0x88,0x80,0xa8,0xa0 }, { 0x28,0x08,0x20,0x00 }, /* ...1...0...0...0 */ { 0x80,0x00,0xa0,0x20 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...0...1 */ { 0x20,0x28,0xa0,0xa8 }, { 0x08,0x88,0x00,0x80 }, /* ...1...0...1...0 */ { 0x80,0x00,0xa0,0x20 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...0...1...1 */ { 0x88,0x80,0xa8,0xa0 }, { 0x88,0x80,0xa8,0xa0 }, /* ...1...1...0...0 */ { 0x80,0x00,0xa0,0x20 }, { 0x08,0x88,0x00,0x80 }, /* ...1...1...0...1 */ { 0x80,0x00,0xa0,0x20 }, { 0x28,0x08,0x20,0x00 }, /* ...1...1...1...0 */ { 0x20,0x28,0xa0,0xa8 }, { 0xa0,0x80,0x20,0x00 } /* ...1...1...1...1 */ }; sega_decode(convtable); } void wmatch_decode(void) { static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...0...0...0 */ { 0x08,0x88,0x00,0x80 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...1 */ { 0x20,0x00,0xa0,0x80 }, { 0x20,0x28,0xa0,0xa8 }, /* ...0...0...1...0 */ { 0x20,0x28,0xa0,0xa8 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...0...1...1 */ { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 }, /* ...0...1...0...0 */ { 0x08,0x88,0x00,0x80 }, { 0xa8,0x28,0x88,0x08 }, /* ...0...1...0...1 */ { 0xa8,0x28,0x88,0x08 }, { 0x20,0x28,0xa0,0xa8 }, /* ...0...1...1...0 */ { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 }, /* ...0...1...1...1 */ { 0x20,0x28,0xa0,0xa8 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...0...0...1 */ { 0x20,0x28,0xa0,0xa8 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...1...0 */ { 0x20,0x28,0xa0,0xa8 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...0...1...1 */ { 0x20,0x00,0xa0,0x80 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...1...0...0 */ { 0xa8,0x28,0x88,0x08 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...1 */ { 0x20,0x28,0xa0,0xa8 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...1...1...0 */ { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 } /* ...1...1...1...1 */ }; sega_decode(convtable); } void bullfgtj_decode(void) { static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0xa0,0xa8,0x20,0x28 }, { 0x80,0xa0,0x00,0x20 }, /* ...0...0...0...0 */ { 0x20,0x28,0x00,0x08 }, { 0x20,0x28,0x00,0x08 }, /* ...0...0...0...1 */ { 0xa0,0xa8,0x20,0x28 }, { 0x08,0x28,0x00,0x20 }, /* ...0...0...1...0 */ { 0x88,0x08,0xa8,0x28 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...0...1...1 */ { 0xa0,0xa8,0x20,0x28 }, { 0x20,0x28,0x00,0x08 }, /* ...0...1...0...0 */ { 0x28,0xa8,0x20,0xa0 }, { 0x20,0x28,0x00,0x08 }, /* ...0...1...0...1 */ { 0xa0,0xa8,0x20,0x28 }, { 0x08,0x28,0x00,0x20 }, /* ...0...1...1...0 */ { 0x88,0x08,0xa8,0x28 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...1...1...1 */ { 0x28,0xa8,0x20,0xa0 }, { 0xa0,0xa8,0x20,0x28 }, /* ...1...0...0...0 */ { 0x88,0x08,0xa8,0x28 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...0...1 */ { 0x28,0xa8,0x20,0xa0 }, { 0x08,0x28,0x00,0x20 }, /* ...1...0...1...0 */ { 0x28,0xa8,0x20,0xa0 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...1...1 */ { 0x20,0x28,0x00,0x08 }, { 0x20,0x28,0x00,0x08 }, /* ...1...1...0...0 */ { 0x88,0x08,0xa8,0x28 }, { 0x20,0x28,0x00,0x08 }, /* ...1...1...0...1 */ { 0x08,0x28,0x00,0x20 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...1...1...0 */ { 0x08,0x28,0x00,0x20 }, { 0x88,0x08,0xa8,0x28 } /* ...1...1...1...1 */ }; sega_decode(convtable); } void pbaction_decode(void) { static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0xa8,0xa0,0x88,0x80 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...0...0 */ { 0x28,0x08,0xa8,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...0...1 */ { 0x28,0x20,0xa8,0xa0 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...1...0 */ { 0x28,0x08,0xa8,0x88 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...1...1 */ { 0xa8,0xa0,0x88,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...0...0 */ { 0x28,0x20,0xa8,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...0...1 */ { 0x28,0x20,0xa8,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...1...0 */ { 0xa8,0xa0,0x88,0x80 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...1...1 */ { 0xa8,0xa0,0x88,0x80 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...0...0 */ { 0x28,0x20,0xa8,0xa0 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...0...0...1 */ { 0x28,0x20,0xa8,0xa0 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...1...0 */ { 0x28,0x08,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...1...1 */ { 0xa0,0x80,0xa8,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...1...0...0 */ { 0x28,0x20,0xa8,0xa0 }, { 0xa8,0x28,0xa0,0x20 }, /* ...1...1...0...1 */ { 0xa0,0x80,0xa8,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...1...1...0 */ { 0xa8,0xa0,0x88,0x80 }, { 0xa8,0x28,0xa0,0x20 } /* ...1...1...1...1 */ }; sega_decode(convtable); } void spatter_decode(void) { static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0x88,0x08,0x80,0x00 }, { 0x00,0x08,0x20,0x28 }, /* ...0...0...0...0 */ { 0x28,0xa8,0x08,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...0...1 */ { 0x28,0x20,0xa8,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...1...0 */ { 0x88,0x08,0x80,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...1 */ { 0x00,0x08,0x20,0x28 }, { 0x88,0x08,0x80,0x00 }, /* ...0...1...0...0 */ { 0xa0,0x80,0x20,0x00 }, { 0x80,0x88,0x00,0x08 }, /* ...0...1...0...1 */ { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...1...1...0 */ { 0x88,0x08,0x80,0x00 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...1...1 */ { 0x28,0xa8,0x08,0x88 }, { 0x80,0x88,0x00,0x08 }, /* ...1...0...0...0 */ { 0x80,0x88,0x00,0x08 }, { 0x00,0x08,0x20,0x28 }, /* ...1...0...0...1 */ { 0x28,0x20,0xa8,0xa0 }, { 0x28,0xa8,0x08,0x88 }, /* ...1...0...1...0 */ { 0x00,0x08,0x20,0x28 }, { 0x80,0xa0,0x88,0xa8 }, /* ...1...0...1...1 */ { 0x80,0x88,0x00,0x08 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...0 */ { 0x80,0xa0,0x88,0xa8 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...1 */ { 0xa0,0x80,0x20,0x00 }, { 0x80,0xa0,0x88,0xa8 }, /* ...1...1...1...0 */ { 0x28,0x20,0xa8,0xa0 }, { 0x00,0x08,0x20,0x28 } /* ...1...1...1...1 */ }; sega_decode(convtable); } void jongkyo_decode(void) { /* encrypted ROM is banked */ UINT8 *decrypted; static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0x28,0x08,0xa8,0x88 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...0...0...0 */ { 0x80,0x88,0xa0,0xa8 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...0...0...1 */ { 0xa0,0xa8,0x20,0x28 }, { 0x20,0xa0,0x00,0x80 }, /* ...0...0...1...0 */ { 0xa0,0xa8,0x20,0x28 }, { 0x80,0x88,0xa0,0xa8 }, /* ...0...0...1...1 */ { 0x08,0x88,0x00,0x80 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...0...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...0...1 */ { 0x20,0xa0,0x00,0x80 }, { 0x20,0xa0,0x00,0x80 }, /* ...0...1...1...0 */ { 0x08,0x88,0x00,0x80 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...1...1 */ { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0xa8,0x20,0x28 }, /* ...1...0...0...0 */ { 0x80,0x88,0xa0,0xa8 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...0...0...1 */ { 0xa0,0xa8,0x20,0x28 }, { 0x20,0xa0,0x00,0x80 }, /* ...1...0...1...0 */ { 0xa0,0xa8,0x20,0x28 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...0...1...1 */ { 0x08,0x88,0x00,0x80 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...1...0...0 */ { 0x08,0x88,0x00,0x80 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...1...0...1 */ { 0x28,0x08,0xa8,0x88 }, { 0x20,0xa0,0x00,0x80 }, /* ...1...1...1...0 */ { 0x80,0x88,0xa0,0xa8 }, { 0x08,0x88,0x00,0x80 } /* ...1...1...1...1 */ }; int A; UINT8 *rom = memory_region(REGION_CPU1); decrypted = auto_malloc(0x9000); for (A = 0x0000;A < 0x9000;A++) { int xor = 0; UINT8 src = rom[A]; /* pick the translation table from bits 0, 4, 8 and 12 of the address */ int row = (A & 1) + (((A >> 4) & 1) << 1) + (((A >> 8) & 1) << 2) + (((A >> 12) & 1) << 3); /* pick the offset in the table from bits 3 and 5 of the source data */ int col = ((src >> 3) & 1) + (((src >> 5) & 1) << 1); /* the bottom half of the translation table is the mirror image of the top */ if (src & 0x80) { col = 3 - col; xor = 0xa8; } /* special handling for banked area */ if (A >= 0x7000) row = (A & 1) + (((A >> 4) & 1) << 1) + (((A >> 8) & 1) << 2); /* decode the opcodes */ decrypted[A] = (src & ~0xa8) | (convtable[2*row][col] ^ xor); /* decode the data */ rom[A] = (src & ~0xa8) | (convtable[2*row+1][col] ^ xor); } memory_configure_bank(1,0,8, memory_region(REGION_CPU1)+0x7000,0x0400); memory_configure_bank_decrypted(1,0,8,decrypted+0x7000,0x0400); memory_set_decrypted_region(0, 0x0000, 0x6bff, decrypted); memory_set_bank(1, 0); } void pitfall2_decode(void) { static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...0...0 */ { 0x08,0x88,0x28,0xa8 }, { 0x28,0xa8,0x20,0xa0 }, /* ...0...0...0...1 */ { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...0 */ { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...0...1...1 */ { 0xa0,0x80,0xa8,0x88 }, { 0x20,0x00,0xa0,0x80 }, /* ...0...1...0...0 */ { 0x28,0xa8,0x20,0xa0 }, { 0x20,0x00,0xa0,0x80 }, /* ...0...1...0...1 */ { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...1...1...0 */ { 0x28,0xa8,0x20,0xa0 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...1...1...1 */ { 0x20,0x00,0xa0,0x80 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...0...0...0 */ { 0x80,0x88,0xa0,0xa8 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...0...0...1 */ { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...1...0 */ { 0x80,0x88,0xa0,0xa8 }, { 0x28,0xa8,0x20,0xa0 }, /* ...1...0...1...1 */ { 0x20,0x00,0xa0,0x80 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...1...0...0 */ { 0x80,0x88,0xa0,0xa8 }, { 0x20,0x00,0xa0,0x80 }, /* ...1...1...0...1 */ { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...1...1...0 */ { 0x80,0x88,0xa0,0xa8 }, { 0x28,0xa8,0x20,0xa0 } /* ...1...1...1...1 */ }; sega_decode(convtable); } void nprinces_decode(void) { static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0x08,0x88,0x00,0x80 }, { 0xa0,0x20,0x80,0x00 }, /* ...0...0...0...0 */ { 0xa8,0xa0,0x28,0x20 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...1 */ { 0x88,0x80,0x08,0x00 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...0...1...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...0...1...1 */ { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x20,0x80,0x00 }, /* ...0...1...0...0 */ { 0xa8,0xa0,0x28,0x20 }, { 0xa8,0xa0,0x28,0x20 }, /* ...0...1...0...1 */ { 0x88,0x80,0x08,0x00 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...1...1...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...1...1...1 */ { 0xa0,0x20,0x80,0x00 }, { 0xa0,0x20,0x80,0x00 }, /* ...1...0...0...0 */ { 0x08,0x88,0x00,0x80 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...0...1 */ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...1...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...1...1 */ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...1...0...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...1...0...1 */ { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...1...0 */ { 0x08,0x88,0x00,0x80 }, { 0x28,0x08,0xa8,0x88 } /* ...1...1...1...1 */ }; sega_decode(convtable); } void seganinj_decode(void) { static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...0...0 */ { 0x28,0xa8,0x08,0x88 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...0...0...1 */ { 0xa8,0xa0,0x28,0x20 }, { 0xa8,0xa0,0x28,0x20 }, /* ...0...0...1...0 */ { 0x28,0xa8,0x08,0x88 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...0...1...1 */ { 0x28,0x08,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...0...0 */ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x08,0x80,0x00 }, /* ...0...1...0...1 */ { 0x28,0x08,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...0 */ { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x28,0x20 }, /* ...0...1...1...1 */ { 0x88,0x08,0x80,0x00 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...0 */ { 0xa0,0xa8,0x80,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...1...0...0...1 */ { 0xa8,0xa0,0x28,0x20 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...1...0 */ { 0xa8,0xa0,0x28,0x20 }, { 0x28,0xa8,0x08,0x88 }, /* ...1...0...1...1 */ { 0x28,0x08,0xa8,0x88 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...1...0...0 */ { 0x28,0x08,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...1...0...1 */ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...1...1...0 */ { 0xa8,0xa0,0x28,0x20 }, { 0x28,0x08,0xa8,0x88 } /* ...1...1...1...1 */ }; sega_decode(convtable); } void imsorry_decode(void) { static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0x88,0x08,0x80,0x00 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...0...0...0 */ { 0x00,0x20,0x80,0xa0 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...0...1 */ { 0x88,0x08,0xa8,0x28 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...0...1...0 */ { 0x00,0x20,0x80,0xa0 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...0...1...1 */ { 0x00,0x20,0x80,0xa0 }, { 0x08,0x00,0x88,0x80 }, /* ...0...1...0...0 */ { 0x00,0x20,0x80,0xa0 }, { 0x20,0x28,0xa0,0xa8 }, /* ...0...1...0...1 */ { 0x20,0x28,0xa0,0xa8 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...1...1...0 */ { 0x20,0x28,0xa0,0xa8 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...1...1...1 */ { 0x88,0x08,0x80,0x00 }, { 0x08,0x00,0x88,0x80 }, /* ...1...0...0...0 */ { 0x08,0x00,0x88,0x80 }, { 0x88,0x08,0x80,0x00 }, /* ...1...0...0...1 */ { 0x08,0x28,0x00,0x20 }, { 0x08,0x28,0x00,0x20 }, /* ...1...0...1...0 */ { 0x88,0x08,0x80,0x00 }, { 0x08,0x28,0x00,0x20 }, /* ...1...0...1...1 */ { 0x08,0x28,0x00,0x20 }, { 0x08,0x00,0x88,0x80 }, /* ...1...1...0...0 */ { 0x08,0x28,0x00,0x20 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...1...0...1 */ { 0x20,0x28,0xa0,0xa8 }, { 0x08,0x28,0x00,0x20 }, /* ...1...1...1...0 */ { 0x20,0x28,0xa0,0xa8 }, { 0x08,0x28,0x00,0x20 } /* ...1...1...1...1 */ }; sega_decode(convtable); } void teddybb_decode(void) { static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0x20,0x28,0x00,0x08 }, { 0x80,0x00,0xa0,0x20 }, /* ...0...0...0...0 */ { 0x20,0x28,0x00,0x08 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...0...0...1 */ { 0x28,0x08,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...0 */ { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...1 */ { 0x20,0x28,0x00,0x08 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...0...0 */ { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...1...0...1 */ { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...0 */ { 0xa0,0xa8,0x20,0x28 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...1 */ { 0x80,0x00,0xa0,0x20 }, { 0x80,0x00,0xa0,0x20 }, /* ...1...0...0...0 */ { 0xa0,0x20,0xa8,0x28 }, { 0xa0,0xa8,0x20,0x28 }, /* ...1...0...0...1 */ { 0xa0,0x20,0xa8,0x28 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...1...0 */ { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...1...1 */ { 0x80,0x00,0xa0,0x20 }, { 0x20,0x28,0x00,0x08 }, /* ...1...1...0...0 */ { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x20,0xa8,0x28 }, /* ...1...1...0...1 */ { 0x80,0x00,0xa0,0x20 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...1...1...0 */ { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x20,0xa8,0x28 } /* ...1...1...1...1 */ }; sega_decode(convtable); } void myheroj_decode(void) { static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0x20,0x00,0xa0,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...0...0...0...0 */ { 0x20,0x00,0xa0,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...0...0...0...1 */ { 0xa8,0xa0,0x88,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...1...0 */ { 0x08,0x88,0x00,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...0...0...1...1 */ { 0x20,0x00,0xa0,0x80 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...1...0...0 */ { 0x20,0x00,0xa0,0x80 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...0...1 */ { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...1...0 */ { 0x08,0x88,0x00,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...1...1 */ { 0x28,0xa8,0x08,0x88 }, { 0x20,0x00,0xa0,0x80 }, /* ...1...0...0...0 */ { 0x80,0xa0,0x88,0xa8 }, { 0x20,0x00,0xa0,0x80 }, /* ...1...0...0...1 */ { 0x80,0xa0,0x88,0xa8 }, { 0x80,0xa0,0x88,0xa8 }, /* ...1...0...1...0 */ { 0xa8,0xa0,0x88,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...1...0...1...1 */ { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...0 */ { 0x88,0x80,0x08,0x00 }, { 0x08,0x88,0x00,0x80 }, /* ...1...1...0...1 */ { 0x88,0x80,0x08,0x00 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...1...1...0 */ { 0x88,0x80,0x08,0x00 }, { 0xa8,0xa0,0x88,0x80 } /* ...1...1...1...1 */ }; sega_decode(convtable); } void hvymetal_decode(void) { static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...0...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...1 */ { 0xa0,0x80,0xa8,0x88 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...1...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...1...1 */ { 0xa0,0x80,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...0 */ { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...1 */ { 0xa0,0x80,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...1...0 */ { 0x88,0x80,0x08,0x00 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...1 */ { 0xa0,0x20,0xa8,0x28 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...0 */ { 0xa0,0x20,0xa8,0x28 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...1 */ { 0xa0,0x20,0xa8,0x28 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...1...0 */ { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...1...1 */ { 0x28,0xa8,0x08,0x88 }, { 0xa0,0x20,0xa8,0x28 }, /* ...1...1...0...0 */ { 0xa0,0x20,0xa8,0x28 }, { 0x28,0xa8,0x08,0x88 }, /* ...1...1...0...1 */ { 0x28,0xa8,0x08,0x88 }, { 0xa0,0x20,0xa8,0x28 }, /* ...1...1...1...0 */ { 0x28,0x08,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 } /* ...1...1...1...1 */ }; sega_decode(convtable); } void lvcards_decode(void) { static const UINT8 convtable[32][4] = { /* opcode data address */ /* A B C D A B C D */ { 0xa8,0x88,0xa0,0x80 }, { 0xa8,0x28,0x88,0x08 }, /* ...0...0...0...0 */ { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 }, /* ...0...0...0...1 */ { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...0...1...0 */ { 0xa8,0xa0,0x88,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...1...1 */ { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0xa0,0x20 }, /* ...0...1...0...0 */ { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 }, /* ...0...1...0...1 */ { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...1...1...0 */ { 0xa8,0x88,0xa0,0x80 }, { 0xa8,0x88,0xa0,0x80 }, /* ...0...1...1...1 */ { 0xa8,0x88,0xa0,0x80 }, { 0xa8,0x28,0x88,0x08 }, /* ...1...0...0...0 */ { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...1 */ { 0xa8,0x28,0x88,0x08 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...1...0 */ { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 }, /* ...1...0...1...1 */ { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x88,0xa0,0x80 }, /* ...1...1...0...0 */ { 0xa8,0x88,0xa0,0x80 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...1 */ { 0x88,0x80,0x08,0x00 }, { 0xa8,0x28,0x88,0x08 }, /* ...1...1...1...0 */ { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x88,0xa0,0x80 } /* ...1...1...1...1 */ }; sega_decode(convtable); } /****************************************************************************** New encryption This encryption is quite different from the older one. It permutates bits D0, D2, D4 and D6, then inverts some of them. The permutation and inversion depend on A0, A3, A6, A9, A12, and A14. ******************************************************************************/ static void sega_decode_2(const UINT8 opcode_xor[64],const int opcode_swap_select[64], const UINT8 data_xor[64],const int data_swap_select[64]) { int A; static const UINT8 swaptable[24][4] = { { 6,4,2,0 }, { 4,6,2,0 }, { 2,4,6,0 }, { 0,4,2,6 }, { 6,2,4,0 }, { 6,0,2,4 }, { 6,4,0,2 }, { 2,6,4,0 }, { 4,2,6,0 }, { 4,6,0,2 }, { 6,0,4,2 }, { 0,6,4,2 }, { 4,0,6,2 }, { 0,4,6,2 }, { 6,2,0,4 }, { 2,6,0,4 }, { 0,6,2,4 }, { 2,0,6,4 }, { 0,2,6,4 }, { 4,2,0,6 }, { 2,4,0,6 }, { 4,0,2,6 }, { 2,0,4,6 }, { 0,2,4,6 }, }; UINT8 *rom = memory_region(REGION_CPU1); UINT8 *decrypted = auto_malloc(0x8000); memory_set_decrypted_region(0, 0x0000, 0x7fff, decrypted); for (A = 0x0000;A < 0x8000;A++) { int row; UINT8 src; const UINT8 *tbl; src = rom[A]; /* pick the translation table from bits 0, 3, 6, 9, 12 and 14 of the address */ row = (A & 1) + (((A >> 3) & 1) << 1) + (((A >> 6) & 1) << 2) + (((A >> 9) & 1) << 3) + (((A >> 12) & 1) << 4) + (((A >> 14) & 1) << 5); /* decode the opcodes */ tbl = swaptable[opcode_swap_select[row]]; decrypted[A] = BITSWAP8(src,7,tbl[0],5,tbl[1],3,tbl[2],1,tbl[3]) ^ opcode_xor[row]; /* decode the data */ tbl = swaptable[data_swap_select[row]]; rom[A] = BITSWAP8(src,7,tbl[0],5,tbl[1],3,tbl[2],1,tbl[3]) ^ data_xor[row]; } } void fdwarrio_decode(void) { static const UINT8 opcode_xor[64] = { 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55, 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55, 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55, 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55, 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55, 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55, 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55, 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55, }; static const UINT8 data_xor[64] = { 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00, 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00, 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00, 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00, 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00, 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00, 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00, 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00, }; static const int opcode_swap_select[64] = { 4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7, 8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9, 10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11, }; static const int data_swap_select[64] = { 4,4,4,4,4,4,4,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7, 8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9, 10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11, 12, }; sega_decode_2(opcode_xor,opcode_swap_select,data_xor,data_swap_select); } void astrofl_decode(void) { static const UINT8 opcode_xor[64] = { 0x04,0x51,0x40,0x01,0x55,0x44,0x05,0x50,0x41,0x00,0x54,0x45, 0x04,0x51,0x40,0x01,0x55,0x44,0x05,0x50,0x41,0x00,0x54,0x45, 0x04,0x51,0x40,0x01,0x55,0x44,0x05,0x50, 0x04,0x51,0x40,0x01,0x55,0x44,0x05,0x50,0x41,0x00,0x54,0x45, 0x04,0x51,0x40,0x01,0x55,0x44,0x05,0x50,0x41,0x00,0x54,0x45, 0x04,0x51,0x40,0x01,0x55,0x44,0x05,0x50, }; static const UINT8 data_xor[64] = { 0x54,0x15,0x44,0x51,0x10,0x41,0x55,0x14,0x45,0x50,0x11,0x40, 0x54,0x15,0x44,0x51,0x10,0x41,0x55,0x14,0x45,0x50,0x11,0x40, 0x54,0x15,0x44,0x51,0x10,0x41,0x55,0x14, 0x54,0x15,0x44,0x51,0x10,0x41,0x55,0x14,0x45,0x50,0x11,0x40, 0x54,0x15,0x44,0x51,0x10,0x41,0x55,0x14,0x45,0x50,0x11,0x40, 0x54,0x15,0x44,0x51,0x10,0x41,0x55,0x14, }; static const int opcode_swap_select[64] = { 0,0,1,1,1,2,2,3,3,4,4,4,5,5,6,6, 6,7,7,8,8,9,9,9,10,10,11,11,11,12,12,13, 8,8,9,9,9,10,10,11,11,12,12,12,13,13,14,14, 14,15,15,16,16,17,17,17,18,18,19,19,19,20,20,21, }; static const int data_swap_select[64] = { 0,0,1,1,2,2,2,3,3,4,4,5,5,5,6,6, 7,7,7,8,8,9,9,10,10,10,11,11,12,12,12,13, 8,8,9,9,10,10,10,11,11,12,12,13,13,13,14,14, 15,15,15,16,16,17,17,18,18,18,19,19,20,20,20,21, }; sega_decode_2(opcode_xor,opcode_swap_select,data_xor,data_swap_select); } void wboy2_decode(void) { static const UINT8 opcode_xor[64] = { 0x00,0x45,0x11,0x01,0x44,0x10,0x55,0x05,0x41,0x14,0x04,0x40,0x15,0x51, 0x01,0x44,0x10,0x00,0x45,0x11,0x54,0x04,0x40,0x15,0x05,0x41,0x14,0x50, 0x00,0x45,0x11,0x01, 0x00,0x45,0x11,0x01,0x44,0x10,0x55,0x05,0x41,0x14,0x04,0x40,0x15,0x51, 0x01,0x44,0x10,0x00,0x45,0x11,0x54,0x04,0x40,0x15,0x05,0x41,0x14,0x50, 0x00,0x45,0x11,0x01, }; static const UINT8 data_xor[64] = { 0x55,0x05,0x41,0x14,0x50,0x00,0x15,0x51,0x01,0x44,0x10,0x55,0x05,0x11, 0x54,0x04,0x40,0x15,0x51,0x01,0x14,0x50,0x00,0x45,0x11,0x54,0x04,0x10, 0x55,0x05,0x41,0x14, 0x55,0x05,0x41,0x14,0x50,0x00,0x15,0x51,0x01,0x44,0x10,0x55,0x05,0x11, 0x54,0x04,0x40,0x15,0x51,0x01,0x14,0x50,0x00,0x45,0x11,0x54,0x04,0x10, 0x55,0x05,0x41,0x14, }; static const int opcode_swap_select[64] = { 2, 5,1,5,1,5, 0,4,0,4,0,4, 7,3,7,3,7,3, 6,2,6,2,6, 1,5,1,5,1,5, 0,4,0, 10, 13,9,13,9,13, 8,12,8,12,8,12, 15,11,15,11,15,11, 14,10,14,10,14, 9,13,9,13,9,13, 8,12,8, }; static const int data_swap_select[64] = { 3,7,3,7,3,7, 2,6,2,6,2, 5,1,5,1,5,1, 4,0,4,0,4, 8, 3,7,3,7,3, 6,2,6,2, 11,15,11,15,11,15, 10,14,10,14,10, 13,9,13,9,13,9, 12,8,12,8,12, 16, 11,15,11,15,11, 14,10,14,10, }; sega_decode_2(opcode_xor,opcode_swap_select,data_xor,data_swap_select); } void robowres_decode(void) { static const UINT8 opcode_xor[64] = { 0x00,0x41,0x10,0x51,0x04,0x45,0x14, 0x00,0x41,0x10,0x51,0x04,0x45,0x14, 0x55, 0x01,0x40,0x11,0x50,0x05,0x44,0x15, 0x01,0x40,0x11,0x50,0x05,0x44,0x15, 0x54, 0x00,0x41, 0x50,0x05,0x44,0x15,0x54,0x00,0x41, 0x50,0x05,0x44,0x15,0x54,0x00,0x41, 0x10, 0x51,0x04,0x45,0x14,0x55,0x01,0x40, 0x51,0x04,0x45,0x14,0x55,0x01,0x40, 0x11, 0x50,0x05 }; static const UINT8 data_xor[64] = { 0x45,0x14,0x55,0x01,0x40,0x11,0x50, 0x05,0x44,0x15,0x54,0x00,0x41,0x10, 0x05, 0x44,0x15,0x54,0x00,0x41,0x10,0x51, 0x04,0x45,0x14,0x55,0x01,0x40,0x11, 0x04, 0x45,0x14, 0x00,0x41,0x10,0x51,0x04,0x45,0x14, 0x55,0x01,0x40,0x11,0x50,0x05,0x44, 0x55, 0x01,0x40,0x11,0x50,0x05,0x44,0x15, 0x54,0x00,0x41,0x10,0x51,0x04,0x45, 0x54, 0x00,0x41 }; static const int opcode_swap_select[64] = { 8,11,15,2,6, 9,13,1,4,8,11,15,2,6, 9,13,1,4,8,11,15,2,6, 10,13,1,4,8,11,15,3,6, 7,2,6,1,5, 1,4,0,3,7,2,6,2,5, 1,4,0,3,7,2,6,2,5, 1,4,0,3,7,3,6,2,5, }; static const int data_swap_select[64] = { 9,13,0,4,8,11,15,2,6, 9,13,1,4,8,11,15,2,6, 10,13,1,4,8,11,15,2,6, 10,13,1,4,8, 1,4,0,3,7,2,6,1,5, 1,4,0,3,7,2,6,2,5, 1,4,0,3,7,3,6,2,5, 1,4,0,4,7, }; sega_decode_2(opcode_xor,opcode_swap_select,data_xor,data_swap_select); } /****************************************************************************** These games (all 317-xxxx CPUs) use the same algorithm, but the key doesn't change much - just one or two positions shift in the table. ******************************************************************************/ static void sega_decode_317(int order, int opcode_shift, int data_shift) { static const UINT8 xor1_317[1+64] = { 0x54, 0x14,0x15,0x41,0x14,0x50,0x55,0x05,0x41,0x01,0x10,0x51,0x05,0x11,0x05,0x14,0x55, 0x41,0x05,0x04,0x41,0x14,0x10,0x45,0x50,0x00,0x45,0x00,0x00,0x00,0x45,0x00,0x00, 0x54,0x04,0x15,0x10,0x04,0x05,0x11,0x44,0x04,0x01,0x05,0x00,0x44,0x15,0x40,0x45, 0x10,0x15,0x51,0x50,0x00,0x15,0x51,0x44,0x15,0x04,0x44,0x44,0x50,0x10,0x04,0x04, }; static const UINT8 xor2_317[2+64] = { 0x04, 0x44, 0x15,0x51,0x41,0x10,0x15,0x54,0x04,0x51,0x05,0x55,0x05,0x54,0x45,0x04,0x10,0x01, 0x51,0x55,0x45,0x55,0x45,0x04,0x55,0x40,0x11,0x15,0x01,0x40,0x01,0x11,0x45,0x44, 0x40,0x05,0x15,0x15,0x01,0x50,0x00,0x44,0x04,0x50,0x51,0x45,0x50,0x54,0x41,0x40, 0x14,0x40,0x50,0x45,0x10,0x05,0x50,0x01,0x40,0x01,0x50,0x50,0x50,0x44,0x40,0x10, }; static const int swap1_317[1+64] = { 7, 1,11,23,17,23, 0,15,19, 20,12,10, 0,18,18, 5,20, 13, 0,18,14, 5, 6,10,21, 1,11, 9, 3,21, 4, 1,17, 5, 7,16,13,19,23,20, 2, 10,23,23,15,10,12, 0,22, 14, 6,15,11,17,15,21, 0, 6, 1, 1,18, 5,15,15,20, }; static const int swap2_317[2+64] = { 7, 12, 18, 8,21, 0,22,21,13,21, 20,13,20,14, 6, 3, 5,20, 8,20, 4, 8,17,22, 0, 0, 6,17,17, 9, 0,16,13,21, 3, 2,18, 6,11, 3, 3,18, 18,19, 3, 0, 5, 0,11, 8, 8, 1, 7, 2,10, 8,10, 2, 1, 3,12,16, 0,17,10, 1, }; if (order) sega_decode_2( xor2_317+opcode_shift, swap2_317+opcode_shift, xor1_317+data_shift, swap1_317+data_shift ); else sega_decode_2( xor1_317+opcode_shift, swap1_317+opcode_shift, xor2_317+data_shift, swap2_317+data_shift ); } void spcpostn_decode(void) { sega_decode_317( 0, 0, 1 ); } void calorie_decode(void) { sega_decode_317( 1, 0, 0 ); } void gardia_decode(void) { sega_decode_317( 1, 1, 1 ); } void gardiab_decode(void) { sega_decode_317( 0, 1, 2 ); }