summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/segacrpt_device.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/segacrpt_device.cpp')
-rw-r--r--src/devices/machine/segacrpt_device.cpp1068
1 files changed, 1068 insertions, 0 deletions
diff --git a/src/devices/machine/segacrpt_device.cpp b/src/devices/machine/segacrpt_device.cpp
new file mode 100644
index 00000000000..b7ab782499f
--- /dev/null
+++ b/src/devices/machine/segacrpt_device.cpp
@@ -0,0 +1,1068 @@
+// license:BSD-3-Clause
+// copyright-holders:Nicola Salmoria, David Haywood
+/******************************************************************************
+
+ 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, D2, 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
+ 315-5006 Monster Bash same encryption scheme as 315-5096 - Spatter
+ 315-5010 Pengo unencrypted version available
+ 315-5013 Super Zaxxon used Zaxxon for known plaintext attack
+ 315-5014 Buck Rogers / Zoom 909 unencrypted version available
+ 315-5015 Super Locomotive
+ 315-5018 Yamato seems to have been copied by Falcon for Falcons Wild - World Wide Poker
+ ???-???? Top Roller same key as Yamato
+ 315-5028 Sindbad Mystery
+ 315-5030 Up'n Down unencrypted version available
+ ???-???? M120 Razzmatazz same key as Up'n Down
+ 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
+ 315-5084 Jongkyo TABLE INCOMPLETE game by Kiwako; also has a simple bitswap on top
+ 315-5093 Pitfall II
+ 315-5096 Spatter same encryption scheme is used by the Falcon 03155096 CPU (Z80)
+ 315-5098 Ninja Princess unencrypted version available; same key as Up'n Down
+ 315-5099 Spatter
+ 315-5102 Sega Ninja unencrypted version available
+ 315-5110 I'm Sorry used My Hero for k.p.a.
+ 315-5111 TeddyBoy Blues same as 315-5006
+ 315-5114 Champion Pro Wrestling same key as Regulus
+ 315-5115 TeddyBoy Blues
+ 315-5128 Pinball Action game by Tehkan; also has a simple bitswap on top
+ 315-5132 My Hero
+ 315-5133 Ninja Princess exactly the same as Sega 315-5048?
+ 315-5135 Heavy Metal &
+ Wonder Boy (set 1a & 3; bootlegs?)
+ 315-5155 TeddyBoy Blues
+
+
+ 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 "emu.h"
+#include "segacrpt_device.h"
+
+
+#if 0
+static void lfkp(int mask)
+{
+ int A;
+ uint8_t *RAM = machine.root_device().memregion("maincpu")->base();
+
+
+ for (A = 0x0000;A < 0x8000-14;A++)
+ {
+ static const 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 decode(uint8_t *data, uint8_t *opcodes, int size, const uint8_t convtable[32][4], int bank_count, int bank_size)
+{
+ for (int A = 0x0000;A < size + bank_count*bank_size;A++)
+ {
+ int xorval = 0;
+
+ uint8_t src = data[A];
+ int adr;
+ if(A < size || !bank_count)
+ adr = A;
+ else
+ adr = size + ((A - size) % bank_size);
+
+ /* pick the translation table from bits 0, 4, 8 and 12 of the address */
+ int row = (adr & 1) + (((adr >> 4) & 1) << 1) + (((adr >> 8) & 1) << 2) + (((adr >> 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;
+ xorval = 0xa8;
+ }
+
+ /* decode the opcodes */
+ opcodes[A] = (src & ~0xa8) | (convtable[2*row][col] ^ xorval);
+
+ /* decode the data */
+ data[A] = (src & ~0xa8) | (convtable[2*row+1][col] ^ xorval);
+
+ if (convtable[2*row][col] == 0xff) /* table incomplete! (for development) */
+ opcodes[A] = 0xee;
+ if (convtable[2*row+1][col] == 0xff) /* table incomplete! (for development) */
+ data[A] = 0xee;
+ }
+}
+
+
+
+DEFINE_DEVICE_TYPE(SEGA_315_5006, sega_315_5006_device, "sega_315_5006", "Sega 315-5006")
+DEFINE_DEVICE_TYPE(SEGA_315_5010, sega_315_5010_device, "sega_315_5010", "Sega 315-5010")
+DEFINE_DEVICE_TYPE(SEGA_315_5013, sega_315_5013_device, "sega_315_5013", "Sega 315-5013")
+DEFINE_DEVICE_TYPE(SEGA_315_5014, sega_315_5014_device, "sega_315_5014", "Sega 315-5014")
+DEFINE_DEVICE_TYPE(SEGA_315_5015, sega_315_5015_device, "sega_315_5015", "Sega 315-5015")
+DEFINE_DEVICE_TYPE(SEGA_315_5018, sega_315_5018_device, "sega_315_5018", "Sega 315-5018")
+DEFINE_DEVICE_TYPE(SEGA_315_5028, sega_315_5028_device, "sega_315_5028", "Sega 315-5028")
+DEFINE_DEVICE_TYPE(SEGA_315_5033, sega_315_5033_device, "sega_315_5033", "Sega 315-5033")
+DEFINE_DEVICE_TYPE(SEGA_315_5041, sega_315_5041_device, "sega_315_5041", "Sega 315-5041")
+DEFINE_DEVICE_TYPE(SEGA_315_5048, sega_315_5048_device, "sega_315_5048", "Sega 315-5048")
+DEFINE_DEVICE_TYPE(SEGA_315_5051, sega_315_5051_device, "sega_315_5051", "Sega 315-5051")
+DEFINE_DEVICE_TYPE(SEGA_315_5061, sega_315_5061_device, "sega_315_5061", "Sega 315-5061")
+DEFINE_DEVICE_TYPE(SEGA_315_5064, sega_315_5064_device, "sega_315_5064", "Sega 315-5064")
+DEFINE_DEVICE_TYPE(SEGA_315_5065, sega_315_5065_device, "sega_315_5065", "Sega 315-5065")
+DEFINE_DEVICE_TYPE(SEGA_315_5084, sega_315_5084_device, "sega_315_5084", "Sega 315-5084")
+DEFINE_DEVICE_TYPE(SEGA_315_5093, sega_315_5093_device, "sega_315_5093", "Sega 315-5093")
+DEFINE_DEVICE_TYPE(SEGA_315_5096, sega_315_5096_device, "sega_315_5096", "Sega 315-5096") // exactly the same as Sega 315-5006?
+DEFINE_DEVICE_TYPE(SEGA_315_5098, sega_315_5098_device, "sega_315_5098", "Sega 315-5098") // also 315-5030 ?
+DEFINE_DEVICE_TYPE(SEGA_315_5099, sega_315_5099_device, "sega_315_5099", "Sega 315-5099")
+DEFINE_DEVICE_TYPE(SEGA_315_5102, sega_315_5102_device, "sega_315_5102", "Sega 315-5102")
+DEFINE_DEVICE_TYPE(SEGA_315_5110, sega_315_5110_device, "sega_315_5110", "Sega 315-5110")
+DEFINE_DEVICE_TYPE(SEGA_315_5111, sega_315_5111_device, "sega_315_5111", "Sega 315-5111") // exactly the same as Sega 315-5006?
+DEFINE_DEVICE_TYPE(SEGA_315_5128, sega_315_5128_device, "sega_315_5128", "Sega 315-5128")
+DEFINE_DEVICE_TYPE(SEGA_315_5132, sega_315_5132_device, "sega_315_5132", "Sega 315-5132")
+DEFINE_DEVICE_TYPE(SEGA_315_5133, sega_315_5133_device, "sega_315_5133", "Sega 315-5133") // exactly the same as Sega 315-5048?
+DEFINE_DEVICE_TYPE(SEGA_315_5135, sega_315_5135_device, "sega_315_5135", "Sega 315-5135")
+DEFINE_DEVICE_TYPE(SEGA_315_5155, sega_315_5155_device, "sega_315_5155", "Sega 315-5155")
+
+
+
+
+segacrpt_z80_device::segacrpt_z80_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ z80_device(mconfig, type, tag, owner, clock),
+ m_decrypted_ptr(nullptr),
+ m_region_ptr(nullptr),
+ m_decode_size(0x8000),
+ m_numbanks(0),
+ m_banksize(0),
+ m_decryption_done(false)
+{
+}
+
+void segacrpt_z80_device::device_start()
+{
+ z80_device::device_start();
+}
+
+void segacrpt_z80_device::device_reset()
+{
+ // decrypt on reset, makes sure DRIVER_INIT stuff happens first (for myherok)
+ // actual CPU would be decrypting in realtime anyway
+ if (m_decrypted_ptr == nullptr)
+ {
+ m_decrypted_ptr = (uint8_t*)memshare(m_decrypted_tag)->ptr();
+ }
+
+ if (m_region_ptr == nullptr)
+ {
+ m_region_ptr = (uint8_t*)memregion(tag())->base();
+ }
+
+ if (m_decryption_done == false)
+ {
+ decrypt();
+ m_decryption_done = true;
+ }
+ z80_device::device_reset();
+}
+
+void segacrpt_z80_device::set_region_p(uint8_t* ptr)
+{
+ m_region_ptr = ptr;
+}
+
+void segacrpt_z80_device::set_decrypted_p(uint8_t* ptr)
+{
+ m_decrypted_ptr = ptr;
+}
+
+
+
+
+sega_315_5132_device::sega_315_5132_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5132, tag, owner, clock) {}
+void sega_315_5132_device::decrypt()
+{
+ static const uint8_t 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 */
+ };
+
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+}
+
+
+
+
+sega_315_5155_device::sega_315_5155_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5155, tag, owner, clock) {}
+void sega_315_5155_device::decrypt()
+{
+ static const uint8_t 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 */
+ };
+
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+}
+
+
+
+
+sega_315_5110_device::sega_315_5110_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5110, tag, owner, clock) {}
+void sega_315_5110_device::decrypt()
+{
+ static const uint8_t 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 */
+ };
+
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+}
+
+
+
+sega_315_5135_device::sega_315_5135_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5135, tag, owner, clock) {}
+void sega_315_5135_device::decrypt()
+{
+ static const uint8_t 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 */
+ };
+
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+}
+
+
+
+
+sega_315_5051_device::sega_315_5051_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5051, tag, owner, clock) {}
+void sega_315_5051_device::decrypt()
+{
+ static const uint8_t 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 */
+ };
+
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+}
+
+
+
+sega_315_5098_device::sega_315_5098_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5098, tag, owner, clock) {}
+void sega_315_5098_device::decrypt()
+{
+ // also 315-5030 ?
+ static const uint8_t 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 */
+ };
+
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+}
+
+
+
+
+sega_315_5102_device::sega_315_5102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5102, tag, owner, clock) {}
+void sega_315_5102_device::decrypt()
+{
+ static const uint8_t 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 */
+ };
+
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+}
+
+
+sega_315_5065_device::sega_315_5065_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5065, tag, owner, clock) {}
+void sega_315_5065_device::decrypt()
+{
+ static const uint8_t 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 */
+ };
+
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+}
+
+
+sega_315_5064_device::sega_315_5064_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5064, tag, owner, clock) {}
+void sega_315_5064_device::decrypt()
+{
+ static const uint8_t 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 */
+ };
+
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+}
+
+
+
+sega_315_5033_device::sega_315_5033_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5033, tag, owner, clock) {}
+void sega_315_5033_device::decrypt()
+{
+ static const uint8_t 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 */
+ };
+
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+}
+
+
+sega_315_5041_device::sega_315_5041_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5041, tag, owner, clock) {}
+void sega_315_5041_device::decrypt()
+{
+ static const uint8_t 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 */
+ };
+
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+}
+
+
+
+sega_315_5048_device::sega_315_5048_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5048, tag, owner, clock) {}
+sega_315_5048_device::sega_315_5048_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, type, tag, owner, clock) {}
+void sega_315_5048_device::decrypt()
+{
+ static const uint8_t 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 */
+ };
+
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+}
+
+
+sega_315_5093_device::sega_315_5093_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5093, tag, owner, clock) {}
+void sega_315_5093_device::decrypt()
+{
+ static const uint8_t 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 */
+ };
+
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+}
+
+
+
+sega_315_5099_device::sega_315_5099_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5099, tag, owner, clock) {}
+void sega_315_5099_device::decrypt()
+{
+ static const uint8_t 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 */
+ };
+
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+}
+
+
+
+
+sega_315_5006_device::sega_315_5006_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5006, tag, owner, clock) {}
+sega_315_5006_device::sega_315_5006_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, type, tag, owner, clock) {}
+void sega_315_5006_device::decrypt()
+{
+ static const uint8_t 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 */
+ };
+
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+}
+
+sega_315_5096_device::sega_315_5096_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : sega_315_5006_device(mconfig, SEGA_315_5096, tag, owner, clock) {}
+// == sega_315_5006_device
+
+sega_315_5111_device::sega_315_5111_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : sega_315_5006_device(mconfig, SEGA_315_5111, tag, owner, clock) {}
+// == sega_315_5006_device
+
+sega_315_5015_device::sega_315_5015_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5015, tag, owner, clock) {}
+void sega_315_5015_device::decrypt()
+{
+ static const uint8_t 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 */
+ };
+
+ /* decrypt program ROMs */
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+}
+
+
+sega_315_5133_device::sega_315_5133_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : sega_315_5048_device(mconfig, SEGA_315_5133, tag, owner, clock) {}
+// == sega_315_5048_device
+
+
+sega_315_5014_device::sega_315_5014_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5014, tag, owner, clock) {}
+void sega_315_5014_device::decrypt()
+{
+ static const uint8_t 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 */
+ };
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+}
+
+
+
+sega_315_5013_device::sega_315_5013_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5013, tag, owner, clock) {}
+void sega_315_5013_device::decrypt()
+{
+ static const uint8_t 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 */
+ };
+
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+}
+
+
+sega_315_5061_device::sega_315_5061_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5061, tag, owner, clock) {}
+void sega_315_5061_device::decrypt()
+{
+ static const uint8_t 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 */
+ };
+
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+}
+
+
+
+sega_315_5018_device::sega_315_5018_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5018, tag, owner, clock) {}
+void sega_315_5018_device::decrypt()
+{
+ static const uint8_t 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 */
+ };
+
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+
+}
+
+
+sega_315_5010_device::sega_315_5010_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5010, tag, owner, clock) {}
+void sega_315_5010_device::decrypt()
+{
+ static const uint8_t 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 */
+ };
+
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+}
+
+
+
+
+sega_315_5128_device::sega_315_5128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5128, tag, owner, clock) {}
+void sega_315_5128_device::decrypt()
+{
+ static const uint8_t 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 */
+ };
+
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+}
+
+
+sega_315_5028_device::sega_315_5028_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5028, tag, owner, clock) {}
+void sega_315_5028_device::decrypt()
+{
+ static const uint8_t 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 */
+ };
+
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+}
+
+
+sega_315_5084_device::sega_315_5084_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : segacrpt_z80_device(mconfig, SEGA_315_5084, tag, owner, clock) {}
+void sega_315_5084_device::decrypt()
+{
+ static const uint8_t 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 */
+ };
+ decode(m_region_ptr, m_decrypted_ptr, m_decode_size, convtable, m_numbanks, m_banksize);
+}