diff options
Diffstat (limited to 'src/mame/machine/segacrpt.c')
-rw-r--r-- | src/mame/machine/segacrpt.c | 1422 |
1 files changed, 1422 insertions, 0 deletions
diff --git a/src/mame/machine/segacrpt.c b/src/mame/machine/segacrpt.c new file mode 100644 index 00000000000..66c682adf94 --- /dev/null +++ b/src/mame/machine/segacrpt.c @@ -0,0 +1,1422 @@ +/****************************************************************************** + + 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 ); } |