summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/segacrpt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/machine/segacrpt.c')
-rw-r--r--src/mame/machine/segacrpt.c1422
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 ); }