summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/igs/igs017.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/igs/igs017.cpp')
-rw-r--r--src/mame/igs/igs017.cpp6257
1 files changed, 6257 insertions, 0 deletions
diff --git a/src/mame/igs/igs017.cpp b/src/mame/igs/igs017.cpp
new file mode 100644
index 00000000000..6daced93f00
--- /dev/null
+++ b/src/mame/igs/igs017.cpp
@@ -0,0 +1,6257 @@
+// license:BSD-3-Clause
+// copyright-holders:Pierpaolo Prazzoli, Luca Elia
+/************************************************************************************************************
+
+ -= IGS017 / IGS031 Based Hardware =-
+
+ driver by Pierpaolo Prazzoli, Luca Elia (l.elia@tin.it)
+
+CPU: Z180 or 68000
+Video: IGS017 or IGS031 (2 tilemaps, variable size sprites, protection)
+Other: IGS025 (8255), IGS022 (protection, MCU), IGS029 (protection)
+Sound: M6295(K668/AR17961) + [YM2413(U3567)]
+
+--------------------------------------------------------------------------------------------------------------
+Year + Game PCB CPU Sound Custom Other
+--------------------------------------------------------------------------------------------------------------
+96 Shuzi Leyuan (V127M) NO-0131-4 Z180 AR17961 U3567 IGS017 8255 Battery
+97 Chaoji Da Manguan II (V754C) NO-0147-6 68000 K668 IGS031 8255 Battery
+97 Tian Jiang Shen Bing (V137C) NO-0157-2 Z180 AR17961 U3567 IGS017 IGS025 Battery
+97 Manguan Daheng (V123T1) NO-0252 68000 M6295 IGS031 IGS025 IGS???* Battery
+98 Genius 6 (V110F) NO-0131-4 Z180 K668 U3567 IGS017 IGS003c Battery
+98 Long Hu Zhengba 2 (set 1) NO-0206 68000 K668 IGS031 IGS025 IGS022* Battery
+98 Long Hu Zhengba 2 (VS105M) NO-0182-2 68000 M6295 IGS031 IGS025 IGS022 Battery
+98 Shuang Long Qiang Zhu 2 VS (VS203J) NO-0207 68000 K668 IGS031 IGS025 IGS022 Battery
+98 Manguan Caishen (V103CS) NO-0192-1 68000 K668 IGS017 IGS025 IGS029 Battery
+98 Manguan Caishen (V106CS) NO-0208 68000 M6295 IGS031 IGS025 IGS029 Battery
+98 Manguan Caishen (V110C) NO-0266 68000 M6295 IGS031 IGS025 IGS026 Battery
+99 Tarzan (V107) NO-0228? Z180 U6295 IGS031 IGS025 IGS029 Battery
+99 Tarzan (V109C) NO-0248-1 Z180 U6295 IGS031 IGS025 Battery
+00 Chaoji Da Manguan 2 - Jiaqiang Ban (V100C) NO-0271 68000 K668 IGS031 IGS025 Battery
+00? Jungle King (V103A) NO-0230-1 Z180 U6295 IGS031 IGS025 (N9) Battery
+00? Super Tarzan (V100I) NO-0230-1 Z180 K668 IGS031 IGS025 Battery
+00? Happy Skill (V611IT) NO-0281 Z180 K668 IGS031 IGS025 Battery
+00? Champion Poker 2 (V100A) unreadable Z180 M6295 IGS031 IGS025 Battery
+00? Super Poker (V100xD03) / Formosa NO-0187 Z180 K668 U3567 IGS017 IGS025 Battery
+00? Jungle King (V302US) NO-0214-7 68000 K668 IGS031 IGS025 IGS029 Battery
+--------------------------------------------------------------------------------------------------------------
+ not present in another set *
+To Do:
+
+- Protection emulation in some games, instead of patching the ROMs.
+- Do iqblocka and clones, genius6 and clones, tjsb support NVRAM?
+- mgcs: Finish IGS029 protection simulation.
+- jking302us: IGS025 and IGS029 protection simulation.
+- sdmg2: different protection that kicks in after several dozens of hands
+
+Notes:
+
+- Test mode is usually accessed by keeping test (F2) pressed during boot.
+- The sound test is often accessed by holding test (F2) and bookkeeping (0) at the I/O test screen.
+- The default bookkeeping password is often Start eight times.
+- Some games (e.g. Tarzan Chuan Tian Guan) refer to the double-up game as 续玩 (literally "Continue Play"),
+ so settings like 续玩有无 refer to the double-up game, not a conventional "continue" feature.
+- iqblocka: keep start (1) pressed during boot for DSWs & input test. Keep test (F2) pressed for bookkeeping / setup [pass: press deal (2)].
+- iqblockf/genius6: press service1 (9) then press deal (2) eight times to switch to gambling. Then test (F2) enters book-keeping / setup.
+- lhzb2, mgcs, slqz2, tjsb: press test (F2) + book (0) during inputs test for sound test.
+- mgdh, sdmg2: press keys A + B during test mode for sound test (B1 + B2 + B3 when using a joystick in mgdh).
+- spkrform: to switch from poker to Formosa press service1 (9). To switch back, press in sequence:
+ service3 (right of 0) then Bet (M) then press "Hold 1".."Hold 5" (Z, X, C, V, B)
+- Tarzan Chuang Tian Guan mahjong controls:
+ Mahjong keyboard:
+ Start Start Stop All Take Score
+ Mahjong Bet Bet
+ Mahjong A Show Odds Stop 1 Double Up (twice winnings)
+ Mahjong B Stop 2
+ Mahjong C Stop 3 Double Up (winnings)
+ Mahjong D Stop 4
+ Mahjong E Double Up (half winnings)
+ Mahjong K Big
+ Mahjong M Small
+ Joystick:
+ Up Stop 1
+ Down Stop 2
+ Left Stop 3
+ Right Stop 4
+ Start Start Stop All Take Score
+ Button 1 Show Odds Big Double Up (twice winnings)
+ Button 2 Bet Double Up (winnings)
+ Button 3 Small Double Up (half winnings)
+
+************************************************************************************************************/
+
+#include "emu.h"
+
+#include "igs017_igs031.h"
+#include "igs022.h"
+#include "igsmahjong.h"
+
+#include "cpu/m68000/m68000.h"
+#include "cpu/z180/z180.h"
+#include "machine/i8255.h"
+#include "machine/nvram.h"
+#include "machine/ticket.h"
+#include "machine/timer.h"
+#include "sound/okim6295.h"
+#include "sound/ymopl.h"
+
+#include "emupal.h"
+#include "screen.h"
+#include "speaker.h"
+
+#include "multibyte.h"
+
+#include "igspoker.lh"
+#include "igsslot.lh"
+
+#define LOG_PROT_STRING (1U << 1)
+#define LOG_PROT_BITSWAP (1U << 2)
+#define LOG_PROT_INCDEC (1U << 3)
+#define LOG_PROT_INC (1U << 4)
+#define LOG_PROT_SCRAMBLE (1U << 5)
+#define LOG_PROT_REMAP (1U << 6)
+#define LOG_PROT_IGS022 (1U << 7)
+#define LOG_PROT_IGS029 (1U << 8)
+
+//#define VERBOSE (LOG_GENERAL | LOG_PROT_STRING | LOG_PROT_BITSWAP | LOG_PROT_INCDEC | LOG_PROT_INC | LOG_PROT_SCRAMBLE | LOG_PROT_REMAP | LOG_PROT_IGS022 | LOG_PROT_IGS029)
+#define VERBOSE (0)
+#include "logmacro.h"
+
+/***************************************************************************
+
+ ---- IGS Multiplexer ----
+
+***************************************************************************/
+
+class igs_mux_device :
+ public device_t,
+ public device_memory_interface
+{
+public:
+ igs_mux_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ void address_w(u8 data);
+ void data_w(u8 data);
+ u8 data_r();
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual space_config_vector memory_space_config() const override;
+
+private:
+ address_space_config m_space_config;
+ u8 m_address = 0;
+};
+
+device_memory_interface::space_config_vector igs_mux_device::memory_space_config() const
+{
+ return space_config_vector {
+ std::make_pair(0, &m_space_config)
+ };
+}
+
+DEFINE_DEVICE_TYPE(IGS_MUX, igs_mux_device, "igs_mux", "IGS I/O Multiplexer")
+
+igs_mux_device::igs_mux_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, IGS_MUX, tag, owner, clock)
+ , device_memory_interface(mconfig, *this)
+ , m_space_config("igs_mux", ENDIANNESS_LITTLE, 8, 8, 0)
+{ }
+
+void igs_mux_device::device_start()
+{
+ save_item(NAME(m_address));
+}
+
+void igs_mux_device::device_reset()
+{
+}
+
+void igs_mux_device::address_w(u8 data)
+{
+ m_address = data;
+}
+
+void igs_mux_device::data_w(u8 data)
+{
+ space().write_byte(m_address, data);
+}
+
+u8 igs_mux_device::data_r()
+{
+ return space().read_byte(m_address);
+}
+
+/***************************************************************************
+
+ ---- IGS String Protection ----
+
+***************************************************************************/
+
+class igs_string_device : public device_t
+{
+public:
+ igs_string_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ u8 result_r(); // 0x05: result_r
+ void do_bitswap_w(offs_t offset, u8 data); // 0x20-0x27: do_bitswap_w
+ u8 advance_string_offs_r(address_space &space); // 0x40: advance_string_offs_r
+
+ // Call after decryption, e.g. at the end of init_<gamename>
+ void dump(const char *filename, u32 string_addr, u32 xor_addr, bool is_16bits) const;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ required_memory_region m_region_key;
+
+ u16 m_string_word = 0, m_word = 0;
+ u8 m_string_offs = 0;
+};
+
+DEFINE_DEVICE_TYPE(IGS_STRING, igs_string_device, "igs_string", "IGS String Protection")
+
+igs_string_device::igs_string_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, IGS_STRING, tag, owner, clock)
+ , m_region_key(*this, DEVICE_SELF)
+{ }
+
+void igs_string_device::dump(const char *filename, u32 string_addr, u32 xor_addr, bool is_16bits) const
+{
+ FILE *f = fopen(filename, "wb");
+ if (!f)
+ {
+ printf("Error opening igs_string dump file %s\n", filename);
+ fclose(f);
+ return;
+ }
+
+ printf("igs_string addr = %x, %x (%d bits)\n", string_addr, xor_addr, is_16bits ? 16 : 8);
+
+ const u8 * const string_base = (const u8 *)memregion(":maincpu")->base() + string_addr;
+ const u8 * const xor_base = (const u8 *)memregion(":maincpu")->base() + xor_addr;
+ for (u32 i = 0; i < 0xec; ++i)
+ {
+ const u32 addr = is_16bits ? BYTE_XOR_BE(i) : i;
+ const u8 data = string_base[addr] ^ xor_base[addr];
+ fwrite(&data, 1, 1, f);
+ }
+
+ fclose(f);
+}
+
+void igs_string_device::device_start()
+{
+ save_item(NAME(m_string_offs));
+ save_item(NAME(m_string_word));
+ save_item(NAME(m_word));
+}
+
+void igs_string_device::device_reset()
+{
+ m_string_word = m_word = 0;
+ m_string_offs = 0;
+}
+
+u8 igs_string_device::result_r()
+{
+ const u8 res = bitswap<8>(m_word, 5, 2, 9, 7, 10, 13, 12, 15);
+ LOGMASKED(LOG_PROT_STRING, "%s: read bitswap - word %04x -> %02x\n", machine().describe_context(), m_word, res);
+ return res;
+}
+
+void igs_string_device::do_bitswap_w(offs_t offset, u8 data)
+{
+ const u16 x = m_word;
+
+ m_word = 0;
+
+ m_word |= (BIT( x, 0) ^ BIT(m_string_word, 0)) << 1; // bit 1
+ m_word |= (BIT(~x, 1) ^ BIT(m_string_word, 1)) << 2; // bit 2
+ m_word |= (BIT(~x, 2) ^ BIT(m_string_word, 2)) << 3; // bit 3
+ m_word |= (BIT(~x, 13) ^ BIT( x, 3)) << 4; // bit 4
+ m_word |= (BIT(~x, 4) ^ BIT(m_string_word, 4)) << 5; // bit 5
+ m_word |= (BIT( x, 5) ^ BIT(m_string_word, 5)) << 6; // bit 6
+ m_word |= (BIT(~x, 6) ^ BIT(m_string_word, 6)) << 7; // bit 7
+ m_word |= (BIT(~x, 7) ^ BIT(m_string_word, 7)) << 8; // bit 8
+ m_word |= (BIT(~x, 8) ^ BIT(m_string_word, 8)) << 9; // bit 9
+ m_word |= (BIT( x, 9) ^ BIT(m_string_word, 9)) << 10; // bit 10
+ m_word |= (BIT(~x, 10) ^ BIT( x, 3)) << 11; // bit 11
+ m_word |= (BIT( x, 11) ^ BIT(m_string_word, 11)) << 12; // bit 12
+ m_word |= (BIT(~x, 12) ^ BIT(m_string_word, 12)) << 13; // bit 13
+ m_word |= (BIT( x, 13) ^ BIT(m_string_word, 13)) << 14; // bit 14
+ m_word |= (BIT( x, 14) ^ BIT(m_string_word, 14)) << 15; // bit 15
+
+ // bit 0
+ const u16 bit0 = BIT(~x, 15) ^ BIT(x, 7);
+
+ // bit 0 is further xor'd with bit x of the data written to this address
+ const u16 xor0 = BIT(data, offset & 7);
+ m_word |= bit0 ^ xor0;
+
+ LOGMASKED(LOG_PROT_STRING, "%s: exec bitswap on port %02x = %02x - bit0 %x, xor0 %x, word %04x -> %04x\n", machine().describe_context(),
+ offset, data, bit0, xor0, x, m_word);
+}
+
+u8 igs_string_device::advance_string_offs_r(address_space &space)
+{
+ const u8 next_string_offs = ((m_string_offs + 1) < 0xec ? (m_string_offs + 1) : 0);
+
+ const u8 shift = (next_string_offs & 1) ? 8 : 0;
+
+ const u8 next_string_byte = m_region_key ? m_region_key->base()[next_string_offs] : 0;
+
+ const u16 next_string_word = (m_string_word & (0xff << (8 - shift))) | (next_string_byte << shift);
+
+ LOGMASKED(LOG_PROT_STRING, "%s: advance string offs %02x -> %02x, string data = %02x, string word %04x -> %04x\n", machine().describe_context(),
+ m_string_offs, next_string_offs, next_string_byte, m_string_word, next_string_word);
+
+ m_string_offs = next_string_offs;
+ m_string_word = next_string_word;
+
+ return space.unmap();
+}
+
+// Similar protection to that found in igs011.cpp:
+
+/***************************************************************************
+
+ ---- IGS Parametric Bitswaps Protection ----
+
+ The protection involves an internal 16-bit value (val), two mode registers
+ (mode_f = 0..f, mode_3 = 0..3) and 8 x 16-bit registers (word).
+
+ The two modes affect the bitswap, and are set by loading the (same) mode-specific value
+ to all the word registers, and then writing to the mode_f or mode_3 trigger register.
+
+ The bitswap of the internal value is then performed writing to one of 8 trigger registers,
+ according to the modes, trigger register and value written.
+
+ The result is read through a fixed bitswap of the internal value.
+
+***************************************************************************/
+
+class igs_bitswap_device : public device_t
+{
+public:
+ igs_bitswap_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ u8 result_r(); // 0x03: result_r
+ void word_w(u8 data); // 0x40-0x47: word_w
+ void mode_f_w(u8 data); // 0x48: mode_f_w
+ void mode_3_w(u8 data); // 0x50: mode_3_w
+ void do_bitswap_w(offs_t offset, u8 data); // 0x80-0x87: do_bitswap_w
+ void reset_w(u8 data); // 0xa0: reset_w
+
+ template <unsigned N> void set_m3_bits(u8 b0, u8 b1, u8 b2, u8 b3);
+ void set_mf_bits(u8 b0, u8 b1, u8 b2, u8 b3);
+ void set_val_xor(u16 val_xor);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ u8 m_m3 = 0, m_mf = 0;
+ u16 m_val = 0, m_word = 0;
+
+ u8 m_m3_bits[4][4] = { {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0} };
+ u8 m_mf_bits[4] = {0,0,0,0};
+ u16 m_val_xor = 0;
+};
+
+template <unsigned N> void igs_bitswap_device::set_m3_bits(u8 b0, u8 b1, u8 b2, u8 b3)
+{
+ m_m3_bits[N][0] = b0;
+ m_m3_bits[N][1] = b1;
+ m_m3_bits[N][2] = b2;
+ m_m3_bits[N][3] = b3;
+
+#if 0
+ printf("igs_bitswap: INIT m3_bits[%x] =", N);
+ for (int i = 0; i < 4; ++i)
+ {
+ u8 bit = m_m3_bits[N][i];
+ printf(" %c%d", BIT(bit, 7) ? '~' : ' ', BIT(bit, 7) ? (bit ^ 0xff) : bit);
+ }
+ printf("\n");
+#endif
+}
+
+void igs_bitswap_device::set_mf_bits(u8 b0, u8 b1, u8 b2, u8 b3)
+{
+ m_mf_bits[0] = b0;
+ m_mf_bits[1] = b1;
+ m_mf_bits[2] = b2;
+ m_mf_bits[3] = b3;
+
+#if 0
+ printf("igs_bitswap: INIT mf_bits = %d %d %d %d\n", m_mf_bits[0], m_mf_bits[1], m_mf_bits[2], m_mf_bits[3]);
+#endif
+}
+
+void igs_bitswap_device::set_val_xor(u16 val_xor)
+{
+ m_val_xor = val_xor;
+
+#if 0
+ printf("igs_bitswap: INIT val_xor = %04x\n", m_val_xor);
+#endif
+}
+
+DEFINE_DEVICE_TYPE(IGS_BITSWAP, igs_bitswap_device, "igs_bitswap", "IGS Bitswap Protection")
+
+igs_bitswap_device::igs_bitswap_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, IGS_BITSWAP, tag, owner, clock)
+{ }
+
+void igs_bitswap_device::device_start()
+{
+ save_item(NAME(m_m3));
+ save_item(NAME(m_mf));
+ save_item(NAME(m_val));
+ save_item(NAME(m_word));
+}
+
+void igs_bitswap_device::device_reset()
+{
+ m_m3 = m_mf = 0;
+ m_val = m_word = 0;
+}
+
+u8 igs_bitswap_device::result_r()
+{
+ u8 res = bitswap<8>(m_val, 5, 2, 9, 7, 10, 13, 12, 15);
+ LOGMASKED(LOG_PROT_BITSWAP, "%s: read bitswap - val %04x -> %02x\n", machine().describe_context(), m_val, res);
+ return res;
+}
+
+void igs_bitswap_device::word_w(u8 data)
+{
+ m_word = (m_word << 8) | data;
+ LOGMASKED(LOG_PROT_BITSWAP, "%s: word = %02x\n", machine().describe_context(), m_word);
+}
+
+void igs_bitswap_device::mode_f_w(u8 data)
+{
+ m_mf = 0;
+ if ((m_word & 0x0f00) != 0x0a00) m_mf |= 0x08;
+ if ((m_word & 0xf000) != 0x9000) m_mf |= 0x04;
+ if ((m_word & 0x000f) != 0x0006) m_mf |= 0x02;
+ if ((m_word & 0x00f0) != 0x0090) m_mf |= 0x01;
+
+ LOGMASKED(LOG_PROT_BITSWAP, "%s: mode_f = %x (word = %04x)\n", machine().describe_context(), m_mf, m_word);
+}
+
+void igs_bitswap_device::mode_3_w(u8 data)
+{
+ m_m3 = 0;
+ if ((m_word & 0x000f) != 0x0003) m_m3 |= 0x02;
+ if ((m_word & 0x00f0) != 0x0050) m_m3 |= 0x01;
+
+ LOGMASKED(LOG_PROT_BITSWAP, "%s: mode_3 = %x (word = %04x)\n", machine().describe_context(), m_m3, m_word);
+}
+
+void igs_bitswap_device::do_bitswap_w(offs_t offset, u8 data)
+{
+ u16 x = m_val;
+
+ // bits 1-15 come from inverting some bits, xor-ing 4 bits (they change per game) with the mf bits, then shifting to the left
+ m_val ^= m_val_xor;
+ for (int i = 0; i < 4; ++i)
+ m_val ^= BIT(m_mf, i) << m_mf_bits[i];
+ m_val <<= 1;
+
+ // bit 0 is the xor of 4 bits from val (some inverted). The 4 bits are picked based on m3 (and they change per game)
+ u16 bit0 = 0;
+ for (int i = 0; i < 4; ++i)
+ {
+ u8 bit = m_m3_bits[m_m3][i];
+ bit0 ^= BIT(bit, 7) ? (BIT(x, bit ^ 0xff) ^ 1) : BIT(x, bit);
+ }
+
+ // bit 0 is further xor'd with bit x of the data written to this address (8x)
+ u16 xor0 = BIT(data, offset & 7);
+ m_val |= bit0 ^ xor0;
+
+ LOGMASKED(LOG_PROT_BITSWAP, "%s: exec bitswap on port %02x = %02x - mode_3 %02x, mode_f %02x, bit0 %x, xor0 %x, val %04x -> %04x\n", machine().describe_context(), offset, data, m_m3, m_mf, bit0, xor0, x, m_val);
+ return;
+}
+
+void igs_bitswap_device::reset_w(u8 data)
+{
+ LOGMASKED(LOG_PROT_BITSWAP, "%s: reset bitswap - val %04x -> 0\n", machine().describe_context(), m_val);
+ m_val = 0;
+}
+
+/***************************************************************************
+
+ ---- IGS Inc/Dec Protection ----
+
+ The chip holds an internal 4-bit value. It is manipulated by issuing commands,
+ where each command is assigned a specific address range, and is triggered
+ by writing to that range. Possible commands:
+
+ - [offset 0] RESET: value = 0
+ - [offset 1] DEC: decrement value
+ - [offset 3] INC: increment value
+
+ The protection value is read from an additional address range:
+
+ - [offset 5] READ: read bitswap(value). Only 4 bits are checked (0-32-1--, i.e. mask $B4)
+
+***************************************************************************/
+
+class igs_incdec_device : public device_t
+{
+public:
+ igs_incdec_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ u8 result_r();
+ void reset_w(u8 data);
+ void inc_w(u8 data);
+ void dec_w(u8 data);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ u8 m_val = 0;
+};
+
+u8 igs_incdec_device::result_r()
+{
+ u8 res = (BIT(m_val, 0) << 7) |
+ (BIT(m_val, 3) << 5) |
+ (BIT(m_val, 2) << 4) |
+ (BIT(m_val, 1) << 2) ;
+
+ LOGMASKED(LOG_PROT_INCDEC, "%s: value read, %02x -> %02x\n", machine().describe_context(), m_val, res);
+ return res;
+}
+
+void igs_incdec_device::reset_w(u8 data)
+{
+ m_val = 0x00;
+ LOGMASKED(LOG_PROT_INCDEC, "%s: reset -> %02x\n", machine().describe_context(), m_val);
+}
+
+void igs_incdec_device::inc_w(u8 data)
+{
+ m_val++;
+ LOGMASKED(LOG_PROT_INCDEC, "%s: inc -> %02x\n", machine().describe_context(), m_val);
+}
+
+void igs_incdec_device::dec_w(u8 data)
+{
+ m_val--;
+ LOGMASKED(LOG_PROT_INCDEC, "%s: dec -> %02x\n", machine().describe_context(), m_val);
+}
+
+DEFINE_DEVICE_TYPE(IGS_INCDEC, igs_incdec_device, "igs_incdec", "IGS Inc/Dec Protection")
+
+igs_incdec_device::igs_incdec_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, IGS_INCDEC, tag, owner, clock)
+{ }
+
+void igs_incdec_device::device_start()
+{
+ save_item(NAME(m_val));
+}
+
+void igs_incdec_device::device_reset()
+{
+ m_val = 0;
+}
+
+/***************************************************************************
+
+ ---- IGS Inc Protection ----
+
+***************************************************************************/
+
+class igs_inc_device : public device_t
+{
+public:
+ igs_inc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ u8 result_r();
+ void reset_w(u8 data);
+ void inc_w(u8 data);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ u8 m_val = 0;
+};
+
+u8 igs_inc_device::result_r()
+{
+ const u8 res = (BIT(~m_val, 0) | (BIT(m_val, 1) & BIT(m_val, 2))) << 5;
+
+ LOGMASKED(LOG_PROT_INC, "%s: value read, %02x -> %02x\n", machine().describe_context(), m_val, res);
+ return res;
+}
+
+void igs_inc_device::reset_w(u8 data)
+{
+ m_val = 0x00;
+ LOGMASKED(LOG_PROT_INC, "%s: reset -> %02x\n", machine().describe_context(), m_val);
+}
+
+void igs_inc_device::inc_w(u8 data)
+{
+ m_val++;
+ LOGMASKED(LOG_PROT_INC, "%s: inc -> %02x\n", machine().describe_context(), m_val);
+}
+
+DEFINE_DEVICE_TYPE(IGS_INC, igs_inc_device, "igs_inc", "IGS Inc Protection")
+
+igs_inc_device::igs_inc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, IGS_INC, tag, owner, clock)
+{ }
+
+void igs_inc_device::device_start()
+{
+ save_item(NAME(m_val));
+}
+
+void igs_inc_device::device_reset()
+{
+ m_val = 0;
+}
+
+
+namespace {
+
+// igs017_state
+
+class igs017_state : public driver_device
+{
+public:
+ igs017_state(const machine_config &mconfig, device_type type, const char *tag)
+ : driver_device(mconfig, type, tag)
+ , m_remap_addr(-1)
+ , m_maincpu(*this, "maincpu")
+ , m_screen(*this, "screen")
+ , m_igs017_igs031(*this, "igs017_igs031")
+ , m_oki(*this, "oki")
+ , m_igs_mux(*this, "igs_mux")
+ , m_ppi(*this, "ppi8255")
+ // Optional shared pointers
+ , m_decrypted_opcodes(*this, "decrypted_opcodes")
+ // Optional devices
+ , m_hopper(*this, "hopper")
+ , m_igs_bitswap(*this, "igs_bitswap")
+ , m_igs_string(*this, "igs_string")
+ , m_igs_incdec(*this, "igs_incdec")
+ , m_igs_inc(*this, "igs_inc")
+ , m_igs022(*this,"igs022")
+ // Optional I/O
+ , m_io_coins(*this, "COINS")
+ , m_io_joy(*this, "JOY")
+ , m_io_key(*this, "KEY%u", 0U)
+ , m_io_dsw(*this, "DSW%u", 1U)
+ , m_lamps(*this, "lamp%u", 1U)
+ { }
+
+ // Z180
+ void cpoker2(machine_config &config) ATTR_COLD;
+ void genius6(machine_config &config) ATTR_COLD;
+ void happyskl(machine_config &config) ATTR_COLD;
+ void iqblocka(machine_config &config) ATTR_COLD;
+ void iqblockf(machine_config &config) ATTR_COLD;
+ void spkrform(machine_config &config) ATTR_COLD;
+ void starzan(machine_config &config) ATTR_COLD;
+ void tarzan(machine_config &config) ATTR_COLD;
+ void tjsb(machine_config &config) ATTR_COLD;
+ // 68000
+ void jking302us(machine_config &config) ATTR_COLD;
+ void lhzb2(machine_config &config) ATTR_COLD;
+ void lhzb2a(machine_config &config) ATTR_COLD;
+ void mgcs(machine_config &config) ATTR_COLD;
+ void mgcsa(machine_config &config) ATTR_COLD;
+ void mgcsb(machine_config &config) ATTR_COLD;
+ void mgdh(machine_config &config) ATTR_COLD;
+ void mgdha(machine_config &config) ATTR_COLD;
+ void sdmg2(machine_config &config) ATTR_COLD;
+ void sdmg2p(machine_config &config) ATTR_COLD;
+ void slqz2(machine_config &config) ATTR_COLD;
+
+ // Init
+ void init_cpoker2() ATTR_COLD;
+ void init_happyskl() ATTR_COLD;
+ void init_iqblocka() ATTR_COLD;
+ void init_jking103a() ATTR_COLD;
+ void init_jking200pr() ATTR_COLD;
+ void init_jking302us() ATTR_COLD;
+ void init_lhzb2() ATTR_COLD;
+ void init_lhzb2a() ATTR_COLD;
+ void init_mgcs() ATTR_COLD;
+ void init_mgcsa() ATTR_COLD;
+ void init_mgcsb() ATTR_COLD;
+ void init_mgdh() ATTR_COLD;
+ void init_mgdha() ATTR_COLD;
+ void init_sdmg2() ATTR_COLD;
+ void init_sdmg2754ca() ATTR_COLD;
+ void init_sdmg2754cb() ATTR_COLD;
+ void init_sdmg2p() ATTR_COLD;
+ void init_slqz2() ATTR_COLD;
+ void init_spkrform() ATTR_COLD;
+ void init_starzan() ATTR_COLD;
+ void init_tarzan() ATTR_COLD;
+ void init_tarzana() ATTR_COLD;
+ void init_tarzanc() ATTR_COLD;
+ void init_tjsb() ATTR_COLD;
+
+ template <typename T = ioport_value, unsigned B = 0, unsigned R = 0>
+ T keys_ipt_r();
+
+protected:
+ virtual void machine_start() override ATTR_COLD;
+ virtual void machine_reset() override ATTR_COLD;
+ virtual void video_start() override ATTR_COLD;
+
+private:
+ int m_remap_addr;
+ required_device<cpu_device> m_maincpu;
+ required_device<screen_device> m_screen;
+ required_device<igs017_igs031_device> m_igs017_igs031;
+ required_device<okim6295_device> m_oki;
+ required_device<igs_mux_device> m_igs_mux;
+ required_device<i8255_device> m_ppi;
+
+ // Optional shared pointers
+ optional_shared_ptr<u8> m_decrypted_opcodes;
+
+ // Optional devices
+ optional_device<hopper_device> m_hopper;
+ optional_device<igs_bitswap_device> m_igs_bitswap;
+ optional_device<igs_string_device> m_igs_string;
+ optional_device<igs_incdec_device> m_igs_incdec;
+ optional_device<igs_inc_device> m_igs_inc;
+ optional_device<igs022_device> m_igs022;
+
+ // Optional I/O
+ optional_ioport m_io_coins;
+ optional_ioport m_io_joy;
+ optional_ioport_array<5> m_io_key;
+ optional_ioport_array<3> m_io_dsw;
+
+ output_finder<6> m_lamps;
+
+ u8 m_input_select;
+ u8 m_dsw_select;
+ u8 m_scramble_data;
+ u8 m_igs022_latch;
+
+ // IGS029 protection (communication)
+ u8 m_igs029_send_data, m_igs029_recv_data;
+ u8 m_igs029_send_buf[256], m_igs029_recv_buf[256];
+ int m_igs029_send_len, m_igs029_recv_len;
+ // IGS029 protection (mgcs)
+ u32 m_igs029_mgcs_long;
+
+ void dsw_select_w(u8 data);
+ u8 dsw_r();
+
+ template<u8 WarnMask>
+ void input_select_w(u8 data)
+ {
+ m_input_select = data;
+
+ if (data & WarnMask)
+ logerror("%s: warning, unknown bits written in input_select_w = %02x\n", machine().describe_context(), data);
+ }
+
+ template<u8 Bit, u8 WarnMask>
+ void oki_sound_bank_w(u8 data)
+ {
+ m_oki->set_rom_bank(BIT(data, Bit));
+
+ if (data & WarnMask)
+ logerror("%s: warning, unknown bits written in oki_sound_bank_w = %02x\n", machine().describe_context(), data);
+ }
+
+ template<u8 Bit, u8 WarnMask>
+ void hopper_motor_w(u8 data)
+ {
+ m_hopper->motor_w(BIT(data, Bit));
+
+ if (data & WarnMask)
+ logerror("%s: warning, unknown bits written in hopper_motor_w = %02x\n", machine().describe_context(), data);
+ }
+
+ template<u8 Bit, u8 WarnMask, int Counter>
+ void counter_w(u8 data)
+ {
+ machine().bookkeeping().coin_counter_w(Counter, BIT(data, Bit));
+// popmessage("COUNTER %d: %02X", Counter, data);
+ if (data & WarnMask)
+ logerror("%s: warning, unknown bits written in counter_w = %02x\n", machine().describe_context(), data);
+ }
+
+ template<u8 Bit, u8 WarnMask>
+ void igs022_execute_w(u8 data)
+ {
+ if (!BIT(m_igs022_latch, Bit) && BIT(data, Bit)) // 0 -> 1 executes
+ {
+ m_igs022->handle_command();
+
+ const u8 new_scramble_data = (m_scramble_data + 1) & 0x7f;
+ LOGMASKED(LOG_PROT_IGS022, "%s: IGS022 scrambled data %02x -> %02x\n", machine().describe_context(), m_scramble_data, new_scramble_data);
+ m_scramble_data = new_scramble_data;
+ }
+
+ if (data & WarnMask)
+ logerror("%s: warning, unknown bits written in igs022_execute_w = %02x\n", machine().describe_context(), data);
+
+ m_igs022_latch = data;
+ }
+
+ // Palette
+ u16 lhzb2a_palette_bitswap(u16 bgr) const;
+ u16 mgcs_palette_bitswap(u16 bgr) const;
+ u16 slqz2_palette_bitswap(u16 bgr) const;
+ u16 tarzan_palette_bitswap(u16 bgr) const;
+ u16 tjsb_palette_bitswap(u16 bgr) const;
+
+ // Game Specific I/O
+ void incdec_remap_addr_w(offs_t offset, u8 data);
+
+ void cpoker2_lamps_sound_w(u8 data);
+
+ void happyskl_lamps_sound_w(u8 data);
+
+ u8 lhzb2_keys_r();
+ void lhzb2_keys_hopper_w(u8 data);
+ u8 lhzb2_scramble_data_r();
+ void lhzb2_igs022_execute_w(u8 data);
+
+ void lhzb2a_keys_hopper_w(offs_t offset, u16 data, u16 mem_mask = ~0);
+ u16 lhzb2a_input_r(offs_t offset);
+ void lhzb2a_remap_addr_w(address_space &space, u16 data);
+
+ u8 mgcs_keys_joy_r();
+ void mgcs_keys_hopper_igs029_w(u8 data);
+ u8 mgcs_scramble_data_r();
+ void mgcs_scramble_data_w(u8 data);
+ u8 mgcs_igs029_data_r();
+ void mgcs_igs029_data_w(u8 data);
+
+ void mgdh_keys_hopper_w(u8 data);
+ void mgdh_counter_w(u8 data);
+
+ void sdmg2_keys_hopper_w(u8 data);
+
+ void slqz2_sound_hopper_w(u8 data);
+ u8 slqz2_scramble_data_r();
+
+ void starzan_counter_w(u8 data);
+ void starzan_lamps_sound_w(u8 data);
+
+ void tarzan_counter_w(u8 data);
+ void tarzan_dsw_sound_w(u8 data);
+ void tarzan_incdec_remap_addr_w(offs_t offset, u8 data);
+
+ // Machine
+ DECLARE_MACHINE_RESET(lhzb2a);
+
+ TIMER_DEVICE_CALLBACK_MEMBER(iqblocka_interrupt);
+ TIMER_DEVICE_CALLBACK_MEMBER(mgcs_interrupt);
+ TIMER_DEVICE_CALLBACK_MEMBER(mgdh_interrupt);
+
+ // Decrypt
+ void decrypt_program_rom(int mask, int a7, int a6, int a5, int a4, int a3, int a2, int a1, int a0) ATTR_COLD;
+
+ void jking200pr_decrypt_program_rom() ATTR_COLD;
+ void mgcs_decrypt_program_rom() ATTR_COLD;
+ void mgcsa_decrypt_program_rom() ATTR_COLD;
+ void mgcsb_decrypt_program_rom() ATTR_COLD;
+ void mgcs_igs029_run() ATTR_COLD;
+ void starzan_decrypt_program_rom() ATTR_COLD;
+ void tarzan_decrypt_program_rom() ATTR_COLD;
+ void tarzana_decrypt_program_rom() ATTR_COLD;
+
+ // ROM Patches
+// void lhzb2_patch_rom() ATTR_COLD;
+// void mgcs_patch_rom() ATTR_COLD;
+// void slqz2_patch_rom() ATTR_COLD;
+ void mgdh_patch_rom() ATTR_COLD;
+ void spkrform_patch_rom() ATTR_COLD;
+
+ // Construct
+ void base_machine_oki(machine_config &config, const XTAL &xtal_oki) ATTR_COLD;
+
+ // Memory maps
+ void decrypted_opcodes_map(address_map &map) ATTR_COLD;
+
+ void igs_bitswap_mux_map(address_map &map) ATTR_COLD;
+ void igs_fixed_data_mux_map(address_map &map) ATTR_COLD;
+ void igs_string_mux_map(address_map &map) ATTR_COLD;
+
+ void cpoker2_io(address_map &map) ATTR_COLD;
+ void cpoker2_map(address_map &map) ATTR_COLD;
+ void cpoker2_mux_map(address_map &map) ATTR_COLD;
+ void happyskl_map(address_map &map) ATTR_COLD;
+ void happyskl_io(address_map &map) ATTR_COLD;
+ void happyskl_mux_map(address_map &map) ATTR_COLD;
+ void iqblocka_io(address_map &map) ATTR_COLD;
+ void iqblocka_map(address_map &map) ATTR_COLD;
+ void iqblocka_mux_map(address_map &map) ATTR_COLD;
+ void iqblockf_mux_map(address_map &map) ATTR_COLD;
+ void jking302us_map(address_map &map) ATTR_COLD;
+ void jking302us_mux_map(address_map &map) ATTR_COLD;
+ void lhzb2_map(address_map &map) ATTR_COLD;
+ void lhzb2_mux_map(address_map &map) ATTR_COLD;
+ void lhzb2a_map(address_map &map) ATTR_COLD;
+ void lhzb2a_mux_map(address_map &map) ATTR_COLD;
+ void mgcs_map(address_map &map) ATTR_COLD;
+ void mgcs_mux_map(address_map &map) ATTR_COLD;
+ void mgcsa_map(address_map &map) ATTR_COLD;
+ void mgcsb_map(address_map &map) ATTR_COLD;
+ void mgcsb_mux_map(address_map &map) ATTR_COLD;
+ void mgdh_mux_map(address_map &map) ATTR_COLD;
+ void mgdh_map(address_map &map) ATTR_COLD;
+ void mgdha_mux_map(address_map &map) ATTR_COLD;
+ void sdmg2_map(address_map &map) ATTR_COLD;
+ void sdmg2_mux_map(address_map &map) ATTR_COLD;
+ void sdmg2p_map(address_map &map) ATTR_COLD;
+ void sdmg2p_mux_map(address_map &map) ATTR_COLD;
+ void slqz2_map(address_map &map) ATTR_COLD;
+ void slqz2_mux_map(address_map &map) ATTR_COLD;
+ void spkrform_io(address_map &map) ATTR_COLD;
+ void spkrform_mux_map(address_map &map) ATTR_COLD;
+ void starzan_io(address_map &map) ATTR_COLD;
+ void starzan_mux_map(address_map &map) ATTR_COLD;
+ void tarzan_io(address_map &map) ATTR_COLD;
+ void tarzan_mux_map(address_map &map) ATTR_COLD;
+ void tjsb_io(address_map &map) ATTR_COLD;
+ void tjsb_map(address_map &map) ATTR_COLD;
+ void tjsb_mux_map(address_map &map) ATTR_COLD;
+};
+
+void igs017_state::machine_start()
+{
+ m_lamps.resolve();
+
+ save_item(NAME(m_remap_addr));
+ save_item(NAME(m_input_select));
+ save_item(NAME(m_dsw_select));
+ save_item(NAME(m_scramble_data));
+ save_item(NAME(m_igs022_latch));
+
+ save_item(NAME(m_igs029_send_data));
+ save_item(NAME(m_igs029_recv_data));
+ save_item(NAME(m_igs029_send_buf));
+ save_item(NAME(m_igs029_recv_buf));
+ save_item(NAME(m_igs029_send_len));
+ save_item(NAME(m_igs029_recv_len));
+ save_item(NAME(m_igs029_mgcs_long));
+}
+
+void igs017_state::machine_reset()
+{
+ m_input_select = m_dsw_select = 0xff;
+ m_scramble_data = 0;
+
+ m_igs029_send_len = m_igs029_recv_len = 0;
+ m_igs029_mgcs_long = 0;
+}
+
+void igs017_state::dsw_select_w(u8 data)
+{
+ m_dsw_select = data;
+}
+
+u8 igs017_state::dsw_r()
+{
+ u8 ret = 0xff;
+ if (!BIT(m_dsw_select, 0)) ret &= m_io_dsw[0]->read();
+ if (!BIT(m_dsw_select, 1)) ret &= m_io_dsw[1]->read();
+ if (!BIT(m_dsw_select, 2)) ret &= m_io_dsw[2]->read();
+ return ret;
+}
+
+/***************************************************************************
+ Video Hardware
+***************************************************************************/
+
+void igs017_state::video_start()
+{
+ m_igs017_igs031->video_start();
+}
+
+// palette bitswap callbacks
+u16 igs017_state::mgcs_palette_bitswap(u16 bgr) const
+{
+ bgr = ((bgr & 0xff00) >> 8) | ((bgr & 0x00ff) << 8);
+
+ return bitswap<16>(bgr, 7, 8, 9, 2, 14, 3, 13, 15, 12, 11, 10, 0, 1, 4, 5, 6);
+}
+
+u16 igs017_state::lhzb2a_palette_bitswap(u16 bgr) const
+{
+ return bitswap<16>(bgr, 15,9,13,12,11,5,4,8,7,6,0,14,3,2,1,10);
+}
+
+u16 igs017_state::tjsb_palette_bitswap(u16 bgr) const
+{
+ return bitswap<16>(bgr, 15,12,3,6,10,5,4,2,9,13,8,7,11,1,0,14);
+}
+
+u16 igs017_state::slqz2_palette_bitswap(u16 bgr) const
+{
+ return bitswap<16>(bgr, 15,14,9,4,11,10,12,3,7,6,5,8,13,2,1,0);
+}
+
+u16 igs017_state::tarzan_palette_bitswap(u16 bgr) const
+{
+ return bitswap<16>(bgr, 15, 0,1,2,3,4, 10,11,12,13,14, 5,6,7,8,9);
+}
+
+/***************************************************************************
+ Decryption
+***************************************************************************/
+
+[[maybe_unused]] void save_decrypted_rom(const u8 * const rom, int rom_size)
+{
+ FILE *f = fopen("igs017_decrypted.bin", "wb");
+ fwrite(rom, 1, rom_size, f);
+ fclose(f);
+}
+
+void igs017_state::decrypt_program_rom(int mask, int a7, int a6, int a5, int a4, int a3, int a2, int a1, int a0)
+{
+ const int rom_size = memregion("maincpu")->bytes();
+ u8 * const rom = memregion("maincpu")->base();
+ std::unique_ptr<u8[]> tmp = std::make_unique<u8[]>(rom_size);
+
+ // decrypt the program ROM
+
+ // XOR layer
+ for (int i = 0; i < rom_size; i++)
+ {
+ if (i & 0x2000)
+ {
+ if ((i & mask) == mask)
+ rom[i] ^= 0x01;
+ }
+ else
+ {
+ if (i & 0x0100)
+ {
+ if ((i & mask) == mask)
+ rom[i] ^= 0x01;
+ }
+ else
+ {
+ if (i & 0x0080)
+ {
+ if ((i & mask) == mask)
+ rom[i] ^= 0x01;
+ }
+ else
+ {
+ if ((i & mask) != mask)
+ rom[i] ^= 0x01;
+ }
+ }
+ }
+ }
+
+ memcpy(tmp.get(),rom,rom_size);
+
+ // address lines swap
+ for (int i = 0; i < rom_size; i++)
+ {
+ int addr = (i & ~0xff) | bitswap<8>(i,a7,a6,a5,a4,a3,a2,a1,a0);
+ rom[i] = tmp[addr];
+ }
+
+// save_decrypted_rom(rom, rom_size);
+}
+
+// iqblocka, iqblockf, genius6
+
+void igs017_state::init_iqblocka()
+{
+ decrypt_program_rom(0x11, 7, 6, 5, 4, 3, 2, 1, 0);
+}
+
+// tjsb
+
+
+void igs017_state::init_tjsb()
+{
+ decrypt_program_rom(0x05, 7, 6, 3, 2, 5, 4, 1, 0);
+
+ m_igs017_igs031->tjsb_decrypt_sprites();
+
+// m_igs_string->dump("tjsb_string.key", 0x1d24a, 0x1db4, false);
+}
+
+
+// mgcs
+
+void igs017_state::mgcs_decrypt_program_rom()
+{
+ const int rom_size = memregion("maincpu")->bytes();
+ u16 * const rom = (u16 *)memregion("maincpu")->base();
+
+ for (int i = 0; i < rom_size / 2; i++)
+ {
+ u16 x = rom[i];
+
+ // bit 0 xor layer
+
+ if (i & 0x20/2)
+ {
+ if (i & 0x02/2)
+ {
+ x ^= 0x0001;
+ }
+ }
+
+ if (!(i & 0x4000/2))
+ {
+ if (!(i & 0x300/2))
+ {
+ x ^= 0x0001;
+ }
+ }
+
+ // bit 8 xor layer
+
+ if ((i & 0x2000/2) || !(i & 0x80/2))
+ {
+ if (i & 0x100/2)
+ {
+ if (!(i & 0x20/2) || (i & 0x400/2))
+ {
+ x ^= 0x0100;
+ }
+ }
+ }
+ else
+ {
+ x ^= 0x0100;
+ }
+
+ rom[i] = x;
+ }
+}
+
+void igs017_state::mgcsa_decrypt_program_rom()
+{
+ const int rom_size = memregion("maincpu")->bytes();
+ u16 * const rom = (u16 *)memregion("maincpu")->base();
+
+ for (int i = 0; i < rom_size / 2; i++)
+ {
+ u16 x = rom[i];
+
+ if (i & 0x20 / 2)
+ {
+ if (i & 0x02 / 2)
+ {
+ x ^= 0x0001;
+ }
+ }
+
+ if (!(i & 0x4000 / 2))
+ {
+ if (!(i & 0x300 / 2))
+ {
+ x ^= 0x0001;
+ }
+ }
+
+ if (!(i & 0x1000 / 2) && !(i & 0x100 / 2))
+ {
+ if (!(i & 0x20 / 2))
+ {
+ x ^= 0x0100;
+ }
+ }
+ else if (i & 0x1000 / 2)
+ {
+ if ((!(i & 0x100 / 2)) || ((i & 0x20 / 2) && (!(i & 0x400 / 2))))
+ {
+ x ^= 0x0100;
+ }
+ }
+
+ rom[i] = x;
+ }
+}
+
+void igs017_state::mgcsb_decrypt_program_rom()
+{
+ const int rom_size = memregion("maincpu")->bytes();
+ u16 * const rom = (u16 *)memregion("maincpu")->base();
+
+ for (int i = 0; i < rom_size / 2; i++)
+ {
+ u16 x = rom[i];
+
+ if (i & 0x20 / 2)
+ {
+ if (i & 0x02 / 2)
+ {
+ x ^= 0x0001;
+ }
+ }
+
+ if (!(i & 0x4000 / 2))
+ {
+ if (!(i & 0x300 / 2))
+ {
+ x ^= 0x0001;
+ }
+ }
+
+ if ((i & 0x50100 / 2) == 0x10100 / 2) // TODO: maybe incomplete
+ {
+ x ^= 0x0200;
+ }
+ if ((i & 0x50300 / 2) == 0x100 / 2) // TODO: maybe incomplete
+ {
+ x ^= 0x0200;
+ }
+
+ rom[i] = x;
+ }
+}
+
+
+#if 0
+void igs017_state::mgcs_patch_rom()
+{
+ u16 * const rom = (u16 *)memregion("maincpu")->base();
+
+ rom[0x20666/2] = 0x601e; // 020666: 671E beq $20686 (rom check)
+
+ // IGS029 send command
+ rom[0x4dfce/2] = 0x6010; // 04DFCE: 6610 bne $4dfe0
+ rom[0x4e00e/2] = 0x4e75;
+ rom[0x4e036/2] = 0x6006; // 04E036: 6306 bls $4e03e
+}
+#endif
+
+void igs017_state::init_mgcs()
+{
+ mgcs_decrypt_program_rom();
+// mgcs_patch_rom();
+
+ m_igs017_igs031->mgcs_decrypt_tiles();
+ m_igs017_igs031->mgcs_flip_sprites(0);
+
+// m_igs_string->dump("mgcs_string.key", 0x1424, 0x1338, true);
+}
+
+void igs017_state::init_mgcsa()
+{
+ mgcsa_decrypt_program_rom();
+
+ m_igs017_igs031->mgcs_decrypt_tiles();
+ m_igs017_igs031->mgcs_flip_sprites(0);
+}
+
+void igs017_state::init_mgcsb()
+{
+ mgcsb_decrypt_program_rom();
+
+ m_igs017_igs031->mgcs_decrypt_tiles();
+ m_igs017_igs031->mgcs_flip_sprites(0);
+}
+
+
+// tarzan, tarzana
+
+
+void igs017_state::tarzan_decrypt_program_rom()
+{
+ const int rom_size = memregion("maincpu")->bytes();
+ u8 * const rom = memregion("maincpu")->base();
+
+ for (int i = 0; i < rom_size; i++)
+ {
+ u8 x = rom[i];
+
+ if ((i & 0x00011) == 0x00011) x ^= 0x01;
+ if ((i & 0x02180) == 0x00000) x ^= 0x01;
+ if ((i & 0x001a0) != 0x00020) x ^= 0x04;
+ if ((i & 0x00080) != 0x00080) x ^= 0x10;
+ if ((i & 0x000e0) == 0x000c0) x ^= 0x10;
+
+ m_decrypted_opcodes[i] = x;
+ }
+
+ for (int i = 0; i < rom_size; i++)
+ {
+ u8 x = rom[i];
+
+ if ((i & 0x00011) == 0x00011) x ^= 0x01;
+ if ((i & 0x02180) == 0x00000) x ^= 0x01;
+ if (((i & 0x00020) == 0x00020) || ((i & 0x000260) == 0x00040)) x ^= 0x04;
+ if ((i & 0x001a0) != 0x00020) x ^= 0x10;
+
+ rom[i] = x;
+ }
+}
+
+void igs017_state::init_tarzanc()
+{
+ tarzan_decrypt_program_rom();
+ m_igs017_igs031->tarzan_decrypt_tiles(1);
+ m_igs017_igs031->tarzan_decrypt_sprites(0, 0);
+
+// m_igs_string->dump("tarzan_string.key", 0xa98a, 0xab01, false); // tarzan / tarzanc (same program rom)
+}
+
+void igs017_state::tarzana_decrypt_program_rom()
+{
+ const int rom_size = memregion("maincpu")->bytes();
+ u8 * const rom = memregion("maincpu")->base();
+
+ for (int i = 0; i < rom_size; i++)
+ {
+ u8 x = rom[i];
+
+ if ((i & 0x00011) == 0x00011) x ^= 0x01;
+ if ((i & 0x02180) == 0x00000) x ^= 0x01;
+ if ((i & 0x00080) != 0x00080) x ^= 0x20;
+ if ((i & 0x000e0) == 0x000c0) x ^= 0x20;
+ if ((i & 0x00280) != 0x00080) x ^= 0x40;
+ if ((i & 0x001a0) != 0x00020) x ^= 0x80;
+
+ m_decrypted_opcodes[i] = x;
+ }
+
+ for (int i = 0; i < rom_size; i++) // by iq_132
+ {
+ u8 x = rom[i];
+
+ if ((i & 0x00011) == 0x00011) x ^= 0x01;
+ if ((i & 0x02180) == 0x00000) x ^= 0x01;
+ if ((i & 0x001a0) != 0x00020) x ^= 0x20;
+ if ((i & 0x00260) != 0x00200) x ^= 0x40;
+ if ((i & 0x00060) != 0x00000 && (i & 0x00260) != 0x00240) x ^= 0x80;
+
+ rom[i] = x;
+ }
+
+// save_decrypted_rom(rom, rom_size);
+// save_decrypted_rom(m_decrypted_opcodes, rom_size);
+}
+
+void igs017_state::init_tarzan()
+{
+ tarzan_decrypt_program_rom();
+ m_igs017_igs031->tarzan_decrypt_tiles(0);
+
+// m_igs_string->dump("tarzan_string.key", 0xa98a, 0xab01, false); // tarzan / tarzanc (same program rom)
+}
+
+void igs017_state::init_tarzana()
+{
+ tarzana_decrypt_program_rom();
+ m_igs017_igs031->tarzan_decrypt_tiles(0);
+
+// m_igs_string->dump("tarzana_string.key", 0xaa64, 0xabdb, false); // same data as tarzan / tarzanc
+}
+
+
+// starzan
+
+void igs017_state::starzan_decrypt_program_rom()
+{
+ const int rom_size = memregion("maincpu")->bytes();
+ u8 * const rom = memregion("maincpu")->base();
+
+ for (int i = 0; i < rom_size; i++)
+ {
+ u8 x = rom[i];
+
+ if ((i & 0x00011) == 0x00011) x ^= 0x01;
+ if ((i & 0x02180) == 0x00000) x ^= 0x01;
+ if ((i & 0x00020) != 0x00020) x ^= 0x20;
+ if ((i & 0x002a0) == 0x00220) x ^= 0x20;
+ if ((i & 0x00220) != 0x00200) x ^= 0x40;
+ if ((i & 0x001c0) != 0x00040) x ^= 0x80;
+
+ m_decrypted_opcodes[i] = x;
+ }
+
+ for (int i = 0; i < rom_size; i++) // by iq_132
+ {
+ u8 x = rom[i];
+
+ if ((i & 0x00011) == 0x00011) x ^= 0x01;
+ if ((i & 0x02180) == 0x00000) x ^= 0x01;
+ if ((i & 0x000a0) != 0x00000) x ^= 0x20;
+ if ((i & 0x001a0) == 0x00000) x ^= 0x20;
+ if ((i & 0x00060) != 0x00020) x ^= 0x40;
+ if ((i & 0x00260) == 0x00220) x ^= 0x40;
+ if ((i & 0x00020) == 0x00020) x ^= 0x80;
+ if ((i & 0x001a0) == 0x00080) x ^= 0x80;
+
+ rom[i] = x;
+ }
+}
+
+void igs017_state::init_starzan()
+{
+ starzan_decrypt_program_rom();
+ m_igs017_igs031->tarzan_decrypt_tiles(1);
+ m_igs017_igs031->starzan_decrypt_sprites(0x200000, 0x400000);
+
+// m_igs_string->dump("starzan_string.key", 0xa86f, 0xa966, false);
+}
+
+void igs017_state::init_jking103a()
+{
+ starzan_decrypt_program_rom();
+ m_igs017_igs031->tarzan_decrypt_tiles(1);
+ m_igs017_igs031->tarzan_decrypt_sprites(0, 0);
+
+// m_igs_string->dump("jking103a_string.key", 0xb14d, 0xb244, false);
+}
+
+void igs017_state::jking200pr_decrypt_program_rom()
+{
+ const int rom_size = memregion("maincpu")->bytes();
+ u8 * const rom = memregion("maincpu")->base();
+
+ for (int i = 0; i < rom_size; i++)
+ {
+ u8 x = rom[i];
+
+ if ((i & 0x00011) == 0x00011) x ^= 0x01;
+ if ((i & 0x02180) == 0x00000) x ^= 0x01;
+ if (((i & 0x00220) == 0x00020) || ((i & 0x002a0) == 0x002a0)) x ^= 0x20;
+ if (((i & 0x00200) == 0x00000) || ((i & 0x00220) == 0x00220)) x ^= 0x40;
+ if ((i & 0x001c0) != 0x00040) x ^= 0x80;
+
+ m_decrypted_opcodes[i] = x;
+ }
+
+ for (int i = 0; i < rom_size; i++) // by iq_132
+ {
+ u8 x = rom[i];
+
+ if ((i & 0x00011) == 0x00011) x ^= 0x01;
+ if ((i & 0x02180) == 0x00000) x ^= 0x01;
+ if (((i & 0x001e0) == 0x00100) || ((i & 0x001e0) == 0x00140)) x ^= 0x20;
+ if ((i & 0x00260) != 0x00020) x ^= 0x40;
+ if (((i & 0x00020) == 0x00020) || ((i & 0x00180) == 0x00080)) x ^= 0x80;
+
+ rom[i] = x;
+ }
+
+// save_decrypted_rom(rom, rom_size);
+// save_decrypted_rom(m_decrypted_opcodes, rom_size);
+}
+
+void igs017_state::init_jking200pr()
+{
+ jking200pr_decrypt_program_rom();
+ m_igs017_igs031->tarzan_decrypt_tiles(1);
+ m_igs017_igs031->tarzan_decrypt_sprites(0, 0);
+
+// m_igs_string->dump("jking200pr_string.key", 0xb14d, 0xb244, false);
+}
+
+void igs017_state::init_happyskl()
+{
+ const int rom_size = memregion("maincpu")->bytes();
+ u8 * const rom = memregion("maincpu")->base();
+
+ for (int i = 0; i < rom_size; i++)
+ {
+ u8 x = rom[i];
+
+ if ((i & 0x00011) == 0x00011) x ^= 0x01;
+ if ((i & 0x02180) == 0x00000) x ^= 0x01;
+ if ((i & 0x0280) != 0x00080) x ^= 0x20;
+ if ((i & 0x02a0) == 0x00280) x ^= 0x20;
+ if ((i & 0x0280) != 0x00080) x ^= 0x40;
+ if ((i & 0x01a0) != 0x00080) x ^= 0x80;
+
+ m_decrypted_opcodes[i] = x;
+ }
+
+ for (int i = 0; i < rom_size; i++) // adapted from starzan
+ {
+ u8 x = rom[i];
+
+ if ((i & 0x00011) == 0x00011) x ^= 0x01;
+ if ((i & 0x02180) == 0x00000) x ^= 0x01;
+ if ((i & 0x000a0) != 0x00000) x ^= 0x20;
+ if ((i & 0x001a0) == 0x00000) x ^= 0x20;
+ if ((i & 0x00060) != 0x00040) x ^= 0x40;
+ if ((i & 0x00260) == 0x00240) x ^= 0x40;
+ if ((i & 0x00020) == 0x00020) x ^= 0x80;
+ if ((i & 0x00260) == 0x00040) x ^= 0x80;
+
+ rom[i] = x;
+ }
+
+ m_igs017_igs031->tarzan_decrypt_tiles(1);
+ m_igs017_igs031->starzan_decrypt_sprites(0x200000, 0);
+}
+
+
+void igs017_state::init_cpoker2()
+{
+ const int rom_size = memregion("maincpu")->bytes();
+ u8 * const rom = memregion("maincpu")->base();
+
+ for (int i = 0; i < rom_size; i++)
+ {
+ u8 x = rom[i];
+
+ if ((i & 0x00011) == 0x00011) x ^= 0x01;
+ if ((i & 0x02180) == 0x00000) x ^= 0x01;
+ if ((i & 0x001a0) != 0x00020) x ^= 0x20;
+ if ((i & 0x00260) != 0x00020) x ^= 0x40;
+ if ((i & 0x00020) == 0x00020) x ^= 0x80;
+ if ((i & 0x00260) == 0x00240) x ^= 0x80;
+
+ // this hasn't got split data / opcodes encryption
+ rom[i] = x;
+ }
+
+ m_igs017_igs031->tarzan_decrypt_tiles(1);
+ m_igs017_igs031->tarzan_decrypt_sprites(0, 0);
+}
+
+
+// sdmg2
+
+void igs017_state::init_sdmg2754ca()
+{
+ const int rom_size = memregion("maincpu")->bytes();
+ u16 * const rom = (u16 *)memregion("maincpu")->base();
+
+ for (int i = 0; i < rom_size / 2; i++)
+ {
+ u16 x = rom[i];
+
+ // bit 0 xor layer
+
+ if (i & 0x20/2)
+ {
+ if (i & 0x02/2)
+ {
+ x ^= 0x0001;
+ }
+ }
+
+ if (!(i & 0x4000/2))
+ {
+ if (!(i & 0x300/2))
+ {
+ x ^= 0x0001;
+ }
+ }
+
+ // bit 9 xor layer
+ if (i & 0x20000/2)
+ {
+ x ^= 0x0200;
+ }
+ else
+ {
+ if (!(i & 0x400/2))
+ {
+ x ^= 0x0200;
+ }
+ }
+
+ // bit 12 xor layer
+ if (i & 0x20000/2)
+ {
+ x ^= 0x1000;
+ }
+
+ rom[i] = x;
+ }
+}
+
+//
+void igs017_state::init_sdmg2754cb()
+{
+ const int rom_size = memregion("maincpu")->bytes();
+ u16 * const rom = (u16 *)memregion("maincpu")->base();
+
+ for (int i = 0; i < rom_size / 2; i++)
+ {
+ u16 x = rom[i];
+
+ // bit 0 xor layer
+
+ if (i & 0x20/2)
+ {
+ if (i & 0x02/2)
+ {
+ x ^= 0x0001;
+ }
+ }
+
+ if (!(i & 0x4000/2))
+ {
+ if (!(i & 0x300/2))
+ {
+ x ^= 0x0001;
+ }
+ }
+
+ // bit 9 xor layer
+ if (i & 0x20000/2)
+ {
+ x ^= 0x0200;
+ }
+ else
+ {
+ if (!(i & 0x200/2))
+ {
+ x ^= 0x0200;
+ }
+ }
+
+ // bit 12 xor layer
+ if (i & 0x20000/2)
+ {
+ x ^= 0x1000;
+ }
+
+ rom[i] = x;
+ }
+}
+
+void igs017_state::init_sdmg2()
+{
+ const int rom_size = memregion("maincpu")->bytes();
+ u16 * const rom = (u16 *)memregion("maincpu")->base();
+
+ for (int i = 0; i < rom_size / 2; i++)
+ {
+ u16 x = rom[i];
+
+ // bit 0 xor layer
+ if (i & 0x20 / 2)
+ if (i & 0x02 / 2)
+ x ^= 0x0001;
+
+ if (!(i & 0x4000 / 2))
+ if (!(i & 0x300 / 2))
+ x ^= 0x0001;
+
+ // bit 9 xor layer
+ if (!(i & 0x20000 / 2))
+ if (i & 0x400 / 2)
+ x ^= 0x0200;
+
+ // bit 12 xor layer
+ if (i & 0x20000 / 2)
+ x ^= 0x1000;
+
+ rom[i] = x;
+ }
+}
+
+// sdmg2p
+
+void igs017_state::init_sdmg2p()
+{
+ const int rom_size = memregion("maincpu")->bytes();
+ u16 * const rom = (u16 *)memregion("maincpu")->base();
+
+ for (int i = 0; i < rom_size / 2; i++)
+ {
+ u16 x = rom[i];
+
+ // bit 0 xor layer
+ if (((i & 0x4320 / 2) == (0x0000 / 2)) || ((i & 0x4322 / 2) == (0x0020 / 2)) || ((i & 0x0122 / 2) == (0x0122 / 2)) || ((i & 0x0222 / 2) == (0x0222 / 2)) || ((i & 0x4322 / 2) == (0x4022 / 2)))
+ x ^= 0x0001;
+
+ // bit 6 xor layer
+ if ((i & 0x4000 / 2) || (i & 0x0200 / 2) || ((i & 0x4b68 / 2) == (0x0048 / 2)) || ((i & 0x4b40 / 2) == (0x0840 / 2)))
+ x ^= 0x0040;
+
+ // bit 13 xor layer
+ if (((i & 0x60000 / 2 ) == (0x00000 / 2)) || ((i & 0x60000 / 2 ) == (0x60000 / 2)))
+ x ^= 0x2000;
+
+ rom[i] = x;
+ }
+
+// m_igs_string->dump("sdmg2p_string.key", 0x7f512, 0x?????, true);
+}
+
+// mgdh, mgdha
+
+void igs017_state::init_mgdha()
+{
+ const int rom_size = memregion("maincpu")->bytes();
+ u16 * const rom = (u16 *)memregion("maincpu")->base();
+
+ for (int i = 0; i < rom_size / 2; i++)
+ {
+ u16 x = rom[i];
+
+ if ((i & 0x20/2) && (i & 0x02/2))
+ {
+ if ((i & 0x300/2) || (i & 0x4000/2))
+ x ^= 0x0001;
+ }
+ else
+ {
+ if (!(i & 0x300/2) && !(i & 0x4000/2))
+ x ^= 0x0001;
+ }
+
+ if ((i & 0x60000/2))
+ x ^= 0x0100;
+
+ if ((i & 0x1000/2) || ((i & 0x4000/2) && (i & 0x40/2) && (i & 0x80/2)) || ((i & 0x2000/2) && (i & 0x400/2)))
+ x ^= 0x0800;
+
+ rom[i] = x;
+ }
+
+ m_igs017_igs031->mgcs_flip_sprites(0);
+
+// m_igs_string->dump("mgdh_string.key", 0x7b214, 0x7b128, true); // mgdh, mgdha (0x7c5ba, ???)
+}
+
+void igs017_state::mgdh_patch_rom()
+{
+ u16 * const rom = (u16 *)memregion("maincpu")->base();
+
+ // game id check
+ rom[0x4ad50/2] = 0x4e71;
+}
+
+void igs017_state::init_mgdh()
+{
+ init_mgdha();
+
+ mgdh_patch_rom();
+}
+
+
+// lhzb2
+
+#if 0
+void igs017_state::lhzb2_patch_rom()
+{
+ u16 * const rom = (u16 *)memregion("maincpu")->base();
+
+ // Prot. checks:
+ rom[0x14786/2] = 0x6044; // 014786: 6744 beq $147cc
+
+ // ROM check:
+ rom[0x0b48a/2] = 0x604e; // 00B48A: 674E beq $b4da
+}
+#endif
+
+void igs017_state::init_lhzb2()
+{
+ const int rom_size = memregion("maincpu")->bytes();
+ u16 * const rom = (u16 *)memregion("maincpu")->base();
+
+ for (int i = 0; i < rom_size / 2; i++)
+ {
+ u16 x = rom[i];
+
+ // bit 0 xor layer
+ if (i & 0x20/2)
+ {
+ if (i & 0x02/2)
+ {
+ x ^= 0x0001;
+ }
+ }
+
+ if (!(i & 0x4000/2))
+ {
+ if (!(i & 0x300/2))
+ {
+ x ^= 0x0001;
+ }
+ }
+
+ // bit 13 xor layer
+
+ if (!(i & 0x1000/2))
+ {
+ if (i & 0x2000/2)
+ {
+ if (i & 0x8000/2)
+ {
+ if (!(i & 0x100/2))
+ {
+ if (i & 0x200/2)
+ {
+ if (!(i & 0x40/2))
+ {
+ x ^= 0x2000;
+ }
+ }
+ else
+ {
+ x ^= 0x2000;
+ }
+ }
+ }
+ else
+ {
+ if (!(i & 0x100/2))
+ {
+ x ^= 0x2000;
+ }
+ }
+ }
+ else
+ {
+ if (i & 0x8000/2)
+ {
+ if (i & 0x200/2)
+ {
+ if (!(i & 0x40/2))
+ {
+ x ^= 0x2000;
+ }
+ }
+ else
+ {
+ x ^= 0x2000;
+ }
+ }
+ else
+ {
+ x ^= 0x2000;
+ }
+ }
+ }
+
+ rom[i] = x;
+ }
+
+ m_igs017_igs031->lhzb2_decrypt_tiles();
+ m_igs017_igs031->lhzb2_decrypt_sprites();
+
+// lhzb2_patch_rom();
+
+// m_igs_string->dump("lhzb2_string.key", 0x7b214, 0x7b128, true);
+}
+
+
+// lhzb2a
+
+void igs017_state::init_lhzb2a()
+{
+ const int rom_size = memregion("maincpu")->bytes();
+ u16 * const rom = (u16 *)memregion("maincpu")->base();
+
+ for (int i = 0; i < rom_size / 2; i++)
+ {
+ u16 x = rom[i];
+
+ // bit 0 xor layer
+ if (i & 0x20/2)
+ {
+ if (i & 0x02/2)
+ {
+ x ^= 0x0001;
+ }
+ }
+
+ if (!(i & 0x4000/2))
+ {
+ if (!(i & 0x300/2))
+ {
+ x ^= 0x0001;
+ }
+ }
+
+ // bit 5 xor layer
+
+ if (i & 0x4000/2)
+ {
+ if (i & 0x8000/2)
+ {
+ if (i & 0x2000/2)
+ {
+ if (i & 0x200/2)
+ {
+ if (!(i & 0x40/2) || (i & 0x800/2))
+ {
+ x ^= 0x0020;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (!(i & 0x40/2) || (i & 0x800/2))
+ {
+ x ^= 0x0020;
+ }
+ }
+ }
+
+ rom[i] = x;
+ }
+
+ m_igs017_igs031->lhzb2_decrypt_tiles();
+ m_igs017_igs031->lhzb2_decrypt_sprites();
+
+// m_igs_string->dump("lhzb2a_string.key", 0x6e11c, 0x6e030, true); // same data as lhzb2
+}
+
+
+// slqz2
+
+#if 0
+void igs017_state::slqz2_patch_rom()
+{
+ u16 * const rom = (u16 *)memregion("maincpu")->base();
+
+ // Prot. checks:
+ rom[0x1489c/2] = 0x6044; // 01489C: 6744 beq $148e2
+
+ // ROM check:
+ rom[0x0b77a/2] = 0x604e; // 00B77A: 674E beq $b7ca
+}
+#endif
+
+void igs017_state::init_slqz2()
+{
+ const int rom_size = memregion("maincpu")->bytes();
+ u16 * const rom = (u16 *)memregion("maincpu")->base();
+
+ for (int i = 0; i < rom_size / 2; i++)
+ {
+ u16 x = rom[i];
+
+ // bit 0 xor layer
+
+ if (i & 0x20/2)
+ {
+ if (i & 0x02/2)
+ {
+ x ^= 0x0001;
+ }
+ }
+
+ if (!(i & 0x4000/2))
+ {
+ if (!(i & 0x300/2))
+ {
+ x ^= 0x0001;
+ }
+ }
+
+ // bit 14 xor layer
+
+ if (i & 0x1000/2)
+ {
+ if (i & 0x800/2)
+ {
+ x ^= 0x4000;
+ }
+ else
+ {
+ if (i & 0x200/2)
+ {
+ if (!(i & 0x100/2))
+ {
+ if (i & 0x40/2)
+ {
+ x ^= 0x4000;
+ }
+ }
+ }
+ else
+ {
+ x ^= 0x4000;
+ }
+ }
+ }
+ else
+ {
+ if (i & 0x800/2)
+ {
+ x ^= 0x4000;
+ }
+ else
+ {
+ if (!(i & 0x100/2))
+ {
+ if (i & 0x40/2)
+ {
+ x ^= 0x4000;
+ }
+ }
+ }
+ }
+
+ rom[i] = x;
+ }
+
+ m_igs017_igs031->slqz2_decrypt_tiles();
+ m_igs017_igs031->lhzb2_decrypt_sprites();
+
+// slqz2_patch_rom();
+
+// m_igs_string->dump("slqz2_string.key", 0x7b214, 0x7b128, true);
+}
+
+
+// spkrform
+
+void igs017_state::spkrform_patch_rom()
+{
+ u8 * const rom = memregion("maincpu")->base();
+
+ rom[0x32ea9] = 0; // enable poker ($e9be = 0)
+ rom[0x32ef9] = 0; // start with poker ($e9bf = 0)
+}
+
+void igs017_state::init_spkrform()
+{
+ decrypt_program_rom(0x14, 7, 6, 5, 4, 3, 0, 1, 2);
+
+ m_igs017_igs031->spkrform_decrypt_sprites();
+
+ spkrform_patch_rom();
+
+// m_igs_string->dump("spkrform_string.key", 0x9dec, 0x9d00, false);
+}
+
+
+void igs017_state::init_jking302us()
+{
+ const int rom_size = memregion("maincpu")->bytes();
+ u16 * const rom = (u16 *)memregion("maincpu")->base();
+
+ for (int i = 0; i < rom_size / 2; i++)
+ {
+ u16 x = rom[i];
+
+ // bit 0 xor layer
+
+ if (i & 0x0020 / 2)
+ if (i & 0x0002/ 2)
+ x ^= 0x0001;
+
+ if (!(i & 0x4000 / 2))
+ if (!(i & 0x0300 / 2))
+ x ^= 0x0001;
+
+ // bit 9 xor layer
+
+ if (i & 0x1000 / 2)
+ {
+ if (i & 0x0400 / 2)
+ if (i & 0x0008 / 2)
+ x ^= 0x0200;
+ }
+ else
+ {
+ if (i & 0x4000 / 2)
+ {
+ if (i & 0x0080 / 2)
+ x ^= 0x0200;
+ else
+ {
+ if (i & 0x0400 / 2)
+ if (i & 0x0008 / 2)
+ x ^= 0x0200;
+ }
+ }
+ else
+ {
+ if (!(i & 0x0400 / 2))
+ {
+ if (i & 0x0080 / 2)
+ if (i & 0x0004/ 2)
+ x ^= 0x0200;
+ }
+ else
+ {
+ if ((i & 0x0008 / 2) || ((i & 0x008c / 2) == 0x0084 /2))
+ x ^= 0x0200;
+ }
+ }
+ }
+
+ rom[i] = x;
+ }
+
+ m_igs017_igs031->tarzan_decrypt_tiles(1); // TODO: verify once it works
+ m_igs017_igs031->tarzan_decrypt_sprites(0, 0); // TODO: verify once it works
+
+// m_igs_string->dump("jking103a_string.key", 0xb14d, 0xb244, false); // TODO
+}
+
+/***************************************************************************
+ Memory Maps
+***************************************************************************/
+
+// Common MUX maps
+
+// 0x03 r, 0x40 - 0x47 w, 0x48 w, 0x50 w, 0x80 - 0x87 w, 0xa0 w
+void igs017_state::igs_bitswap_mux_map(address_map &map)
+{
+ map(0x03, 0x03).r(m_igs_bitswap, FUNC(igs_bitswap_device::result_r));
+ map(0x40, 0x40).w(m_igs_bitswap, FUNC(igs_bitswap_device::word_w));
+ map(0x41, 0x47).nopw();
+ map(0x48, 0x48).w(m_igs_bitswap, FUNC(igs_bitswap_device::mode_f_w));
+ map(0x50, 0x50).w(m_igs_bitswap, FUNC(igs_bitswap_device::mode_3_w));
+ map(0x80, 0x87).w(m_igs_bitswap, FUNC(igs_bitswap_device::do_bitswap_w));
+ map(0xa0, 0xa0).w(m_igs_bitswap, FUNC(igs_bitswap_device::reset_w));
+}
+
+// 0x05 r, 0x20 - 0x27 w, 0x40 r
+void igs017_state::igs_string_mux_map(address_map &map)
+{
+ map(0x05, 0x05).r(m_igs_string, FUNC(igs_string_device::result_r));
+ map(0x20, 0x27).w(m_igs_string, FUNC(igs_string_device::do_bitswap_w));
+ map(0x40, 0x40).r(m_igs_string, FUNC(igs_string_device::advance_string_offs_r));
+}
+
+// 0x20 - 0x34: read fixed data
+void igs017_state::igs_fixed_data_mux_map(address_map &map)
+{
+ map(0x20, 0x34).rom().region("igs_fixed_data", 0);
+ map(0x23, 0x23).unmapr();
+ map(0x29, 0x29).unmapr();
+ map(0x2f, 0x2f).unmapr();
+}
+
+
+// iqblocka, iqblockf, genius6
+
+void igs017_state::iqblocka_map(address_map &map)
+{
+ map(0x00000, 0x0dfff).rom();
+ map(0x0e000, 0x0efff).ram().share("nvram");
+ map(0x0f000, 0x0ffff).ram();
+ map(0x10000, 0x3ffff).rom();
+}
+
+void igs017_state::decrypted_opcodes_map(address_map &map)
+{
+ map(0x00000, 0x3ffff).readonly().share(m_decrypted_opcodes);
+}
+
+void igs017_state::incdec_remap_addr_w(offs_t offset, u8 data)
+{
+ if (offset == 0)
+ {
+ // Unmap previous address ranges
+ if (m_remap_addr != -1)
+ {
+ address_space &prg_space = m_maincpu->space(AS_PROGRAM);
+ prg_space.unmap_write(m_remap_addr + 0x0, m_remap_addr + 0x0);
+ prg_space.unmap_write(m_remap_addr + 0x1, m_remap_addr + 0x1);
+ prg_space.unmap_write(m_remap_addr + 0x3, m_remap_addr + 0x3);
+ prg_space.unmap_read (m_remap_addr + 0x5, m_remap_addr + 0x5);
+
+ LOGMASKED(LOG_PROT_REMAP, "%s: incdec protection unmapped from %04x\n", machine().describe_context(), m_remap_addr);
+ }
+
+ m_remap_addr = (m_remap_addr & 0xff00) | data;
+ }
+ else
+ {
+ m_remap_addr = (m_remap_addr & 0x00ff) | (data << 8);
+
+ // Add new memory ranges
+ address_space &prg_space = m_maincpu->space(AS_PROGRAM);
+ prg_space.install_write_handler(m_remap_addr + 0x0, m_remap_addr + 0x0, write8smo_delegate(*m_igs_incdec, FUNC(igs_incdec_device::reset_w)));
+ prg_space.install_write_handler(m_remap_addr + 0x1, m_remap_addr + 0x1, write8smo_delegate(*m_igs_incdec, FUNC(igs_incdec_device::dec_w)));
+ prg_space.install_write_handler(m_remap_addr + 0x3, m_remap_addr + 0x3, write8smo_delegate(*m_igs_incdec, FUNC(igs_incdec_device::inc_w)));
+ prg_space.install_read_handler (m_remap_addr + 0x5, m_remap_addr + 0x5, read8smo_delegate (*m_igs_incdec, FUNC(igs_incdec_device::result_r)));
+
+ LOGMASKED(LOG_PROT_REMAP, "%s: incdec protection remapped at %04x\n", machine().describe_context(), m_remap_addr);
+ }
+}
+
+void igs017_state::iqblocka_io(address_map &map)
+{
+ map(0x0000, 0x7fff).rw(m_igs017_igs031, FUNC(igs017_igs031_device::read), FUNC(igs017_igs031_device::write));
+ map(0x0000, 0x003f).ram(); // internal regs
+
+ map(0x2010, 0x2011).w(FUNC(igs017_state::incdec_remap_addr_w));
+
+ map(0x8000, 0x8000).w (m_igs_mux, FUNC(igs_mux_device::address_w));
+ map(0x8001, 0x8001).rw(m_igs_mux, FUNC(igs_mux_device::data_r), FUNC(igs_mux_device::data_w));
+
+ map(0x9000, 0x9000).rw(m_oki, FUNC(okim6295_device::read), FUNC(okim6295_device::write));
+
+ map(0xa000, 0xa000).portr("BUTTONS");
+
+ map(0xb000, 0xb001).w("ymsnd", FUNC(ym2413_device::write));
+}
+
+void igs017_state::iqblocka_mux_map(address_map &map)
+{
+ map(0x00, 0x00).portr("PLAYER1").w(NAME((&igs017_state::counter_w<7, 0x7f, 0>))); // coin in
+ map(0x01, 0x01).portr("PLAYER2");
+ map(0x02, 0x02).portr("COINS");
+
+ igs_bitswap_mux_map(map); // 0x03 r, 0x40 - 0x47 w, 0x48 w, 0x50 w, 0x80 - 0x87 w, 0xa0 w
+
+ igs_fixed_data_mux_map(map); // 0x20 - 0x34: read fixed data
+}
+
+void igs017_state::iqblockf_mux_map(address_map &map)
+{
+ iqblocka_mux_map(map);
+
+ map(0x01, 0x01).w(NAME((&igs017_state::counter_w<7, 0x7f, 1>))); // coin out (in gambling mode, only iqblockf/genius6)
+}
+
+// starzan
+
+void igs017_state::starzan_io(address_map &map)
+{
+ map(0x0000, 0x7fff).rw(m_igs017_igs031, FUNC(igs017_igs031_device::read), FUNC(igs017_igs031_device::write));
+ map(0x0000, 0x003f).ram(); // internal regs
+
+ map(0x2010, 0x2011).w(FUNC(igs017_state::incdec_remap_addr_w));
+
+ map(0x8000, 0x8000).w (m_igs_mux, FUNC(igs_mux_device::address_w));
+ map(0x8001, 0x8001).rw(m_igs_mux, FUNC(igs_mux_device::data_r), FUNC(igs_mux_device::data_w));
+
+ map(0x9000, 0x9000).rw(m_oki, FUNC(okim6295_device::read), FUNC(okim6295_device::write));
+}
+
+// cpoker2, happyksl, starzan
+void igs017_state::starzan_counter_w(u8 data)
+{
+ // BIT(data, 0) // always on in cpoker2/happyskl?
+ m_hopper->motor_w( BIT(data, 1)); // hopper
+ // BIT(data, 2) // unused?
+ machine().bookkeeping().coin_counter_w(0, BIT(data, 3)); // key out
+ machine().bookkeeping().coin_counter_w(1, BIT(data, 4)); // payout
+ machine().bookkeeping().coin_counter_w(2, BIT(data, 5)); // coin C
+ machine().bookkeeping().coin_counter_w(3, BIT(data, 6)); // key in
+ machine().bookkeeping().coin_counter_w(4, BIT(data, 7)); // coin A
+// popmessage("COUNTER %02X", data);
+ if (BIT(data, 2))
+ logerror("%s: warning, unknown bits written in counter_w = %02x\n", machine().describe_context(), data);
+}
+
+void igs017_state::starzan_lamps_sound_w(u8 data)
+{
+ m_lamps[0] = BIT(data, 2); // stop 1
+ m_lamps[1] = BIT(data, 0); // stop 2
+ m_lamps[2] = BIT(data, 4); // stop 3
+ m_lamps[3] = BIT(data, 1); // stop 4
+ m_lamps[4] = BIT(data, 3); // bet/stop
+ m_lamps[5] = BIT(data, 5); // start
+// BIT(data, 6); // unused?
+ m_oki->set_rom_bank(BIT(data, 7));
+
+// popmessage("LAMPS/SOUND %02X", data);
+
+ if (BIT(data, 6))
+ logerror("%s: warning, unknown bits written in lamps_sound_w = %02x\n", machine().describe_context(), data);
+}
+
+void igs017_state::starzan_mux_map(address_map &map)
+{
+ map(0x00, 0x00).w(FUNC(igs017_state::starzan_counter_w));
+ map(0x01, 0x01).portr("PLAYER2");
+ map(0x02, 0x02).w(FUNC(igs017_state::starzan_lamps_sound_w));
+ map(0x03, 0x03).w(FUNC(igs017_state::dsw_select_w));
+
+ igs_string_mux_map(map); // 0x05 r, 0x20 - 0x27 w, 0x40 r
+}
+
+
+// happyksl
+
+void igs017_state::happyskl_map(address_map &map)
+{
+ map(0x00000, 0x0dfff).rom();
+ map(0x0e000, 0x0ffff).ram().share("nvram");
+ map(0x10000, 0x3ffff).rom();
+}
+
+void igs017_state::happyskl_io(address_map &map)
+{
+ map(0x0000, 0x7fff).rw(m_igs017_igs031, FUNC(igs017_igs031_device::read), FUNC(igs017_igs031_device::write));
+ map(0x0000, 0x003f).ram(); // internal regs
+
+ map(0x8000, 0x8000).w (m_igs_mux, FUNC(igs_mux_device::address_w));
+ map(0x8001, 0x8001).rw(m_igs_mux, FUNC(igs_mux_device::data_r), FUNC(igs_mux_device::data_w));
+
+ map(0x9000, 0x9000).rw(m_oki, FUNC(okim6295_device::read), FUNC(okim6295_device::write));
+}
+
+void igs017_state::happyskl_lamps_sound_w(u8 data)
+{
+ m_lamps[0] = BIT(data, 4); // hold 1
+ m_lamps[1] = BIT(data, 0); // hold 2
+ m_lamps[2] = BIT(data, 1); // hold 3
+ m_lamps[3] = BIT(data, 2); // hold 4
+ m_lamps[4] = BIT(data, 3); // hold 5
+ m_lamps[5] = BIT(data, 5); // start
+// BIT(data, 6); // unused?
+ m_oki->set_rom_bank(BIT(data, 7));
+
+// popmessage("LAMPS/SOUND %02X", data);
+
+ if (BIT(data, 6))
+ logerror("%s: warning, unknown bits written in lamps_sound_w = %02x\n", machine().describe_context(), data);
+}
+
+void igs017_state::happyskl_mux_map(address_map &map)
+{
+ map(0x00, 0x00).w(FUNC(igs017_state::starzan_counter_w));
+ map(0x01, 0x01).portr("PLAYER2");
+ map(0x02, 0x02).w(FUNC(igs017_state::happyskl_lamps_sound_w));
+ map(0x03, 0x03).w(FUNC(igs017_state::dsw_select_w));
+}
+
+
+// cpoker2
+
+void igs017_state::cpoker2_map(address_map &map)
+{
+ iqblocka_map(map);
+
+ map(0x0a400, 0x0a400).w(m_igs_inc, FUNC(igs_inc_device::inc_w));
+ map(0x0a420, 0x0a420).w(m_igs_inc, FUNC(igs_inc_device::reset_w));
+ map(0x0a460, 0x0a460).r(m_igs_inc, FUNC(igs_inc_device::result_r));
+}
+
+void igs017_state::cpoker2_io(address_map &map)
+{
+ map(0x0000, 0x7fff).rw(m_igs017_igs031, FUNC(igs017_igs031_device::read), FUNC(igs017_igs031_device::write));
+ map(0x0000, 0x003f).ram(); // internal regs
+
+ map(0x2010, 0x2011).w(FUNC(igs017_state::incdec_remap_addr_w));
+
+ map(0x8000, 0x8000).w (m_igs_mux, FUNC(igs_mux_device::address_w));
+ map(0x8001, 0x8001).rw(m_igs_mux, FUNC(igs_mux_device::data_r), FUNC(igs_mux_device::data_w));
+
+ map(0x9000, 0x9000).rw(m_oki, FUNC(okim6295_device::read), FUNC(okim6295_device::write));
+}
+
+void igs017_state::cpoker2_lamps_sound_w(u8 data)
+{
+ m_lamps[0] = BIT(data, 0); // hold 1
+ m_lamps[1] = BIT(data, 1); // hold 2
+ m_lamps[2] = BIT(data, 4); // hold 3
+ m_lamps[3] = BIT(data, 2); // hold 4
+ m_lamps[4] = BIT(data, 3); // hold 5
+ m_lamps[5] = BIT(data, 5); // start
+// BIT(data, 6); // unused?
+ m_oki->set_rom_bank(BIT(data, 7));
+
+// popmessage("LAMPS/SOUND %02X", data);
+
+ if (BIT(data, 6))
+ logerror("%s: warning, unknown bits written in lamps_sound_w = %02x\n", machine().describe_context(), data);
+}
+
+void igs017_state::cpoker2_mux_map(address_map &map)
+{
+ map(0x00, 0x00).w(FUNC(igs017_state::starzan_counter_w));
+ map(0x01, 0x01).portr("PLAYER2");
+ map(0x02, 0x02).w(FUNC(igs017_state::cpoker2_lamps_sound_w));
+ map(0x03, 0x03).w(FUNC(igs017_state::dsw_select_w));
+}
+
+
+// tarzan
+
+void igs017_state::tarzan_incdec_remap_addr_w(offs_t offset, u8 data)
+{
+ incdec_remap_addr_w(offset, data ^ ((offset == 1) ? 0x40 : 0));
+}
+
+void igs017_state::tarzan_io(address_map &map)
+{
+ starzan_io(map);
+
+ map(0x2010, 0x2011).w(FUNC(igs017_state::tarzan_incdec_remap_addr_w));
+}
+
+void igs017_state::tarzan_counter_w(u8 data)
+{
+ m_hopper->motor_w( BIT(data, 1)); // hopper
+ machine().bookkeeping().coin_counter_w(0, BIT(data, 2)); // key out
+ machine().bookkeeping().coin_counter_w(1, BIT(data, 3)); // key in
+// popmessage("COUNTER %02X", data);
+ if (data & ~0x0c)
+ logerror("%s: warning, unknown bits written in counter_w = %02x\n", machine().describe_context(), data);
+}
+
+void igs017_state::tarzan_dsw_sound_w(u8 data)
+{
+ // bits 0,1,2: DSW select
+ // bit 7: Sound bank
+ m_dsw_select = data;
+ m_oki->set_rom_bank(BIT(data, 7));
+// popmessage("DSW %02X", data);
+ if (data & ~0x87)
+ logerror("%s: warning, unknown bits written in dsw_sound_w = %02x\n", machine().describe_context(), data);
+}
+
+void igs017_state::tarzan_mux_map(address_map &map)
+{
+ map(0x00, 0x00).w(FUNC(igs017_state::input_select_w<0x07>));
+ map(0x01, 0x01).w(FUNC(igs017_state::tarzan_counter_w));
+ map(0x02, 0x02).r(FUNC(igs017_state::dsw_r));
+ map(0x03, 0x03).w(FUNC(igs017_state::tarzan_dsw_sound_w));
+
+ igs_string_mux_map(map); // 0x05 r, 0x20 - 0x27 w, 0x40 r
+}
+
+
+// mgcs
+
+// IGS029 appears to be an MCU that receives commands (write port with value, read port, etc.)
+// Sound banking and DSW are accessed through it. It also performs some game specific calculations.
+void igs017_state::mgcs_igs029_run()
+{
+ LOGMASKED(LOG_PROT_IGS029, "%s: running igs029 command ", machine().describe_context());
+ for (int i = 0; i < m_igs029_send_len; i++)
+ LOGMASKED(LOG_PROT_IGS029, "%02x ", m_igs029_send_buf[i]);
+
+ if (m_igs029_send_buf[0] == 0x05 && m_igs029_send_buf[1] == 0x5a) // 'Z'
+ {
+ u8 data = m_igs029_send_buf[2];
+ u8 port = m_igs029_send_buf[3];
+
+ LOGMASKED(LOG_PROT_IGS029, "PORT %02x = %02x\n", port, data);
+
+ switch (port)
+ {
+ case 0x01:
+ m_oki->set_rom_bank( BIT(data, 4)); // oki
+ machine().bookkeeping().coin_counter_w(0, !BIT(data, 5)); // coin in
+ machine().bookkeeping().coin_counter_w(1, !BIT(data, 6)); // coin out
+
+// popmessage("PORT1 %02X", data);
+
+ if (data & ~0x70)
+ logerror("%s: warning, unknown bits written in port %02x = %02x\n", machine().describe_context(), port, data);
+
+ break;
+
+ case 0x03:
+ m_dsw_select = data;
+
+// popmessage("PORT3 %02X", data);
+
+ if (data & ~0x03)
+ logerror("%s: warning, unknown bits written in port %02x = %02x\n", machine().describe_context(), port, data);
+
+ break;
+
+ default:
+ logerror("%s: warning, unknown port %02x written with %02x\n", machine().describe_context(), port, data);
+ }
+
+ m_igs029_recv_len = 0;
+ m_igs029_recv_buf[m_igs029_recv_len++] = 0x01;
+ }
+ else if (m_igs029_send_buf[0] == 0x03 && m_igs029_send_buf[1] == 0x55) // 'U'
+ {
+ LOGMASKED(LOG_PROT_IGS029, "MIN BET?\n");
+
+ // No inputs. Returns 1 long
+
+ u8 min_bets[4] = {1, 2, 3, 5};
+
+ m_igs029_recv_len = 0;
+ m_igs029_recv_buf[m_igs029_recv_len++] = 0x00;
+ m_igs029_recv_buf[m_igs029_recv_len++] = 0x00;
+ m_igs029_recv_buf[m_igs029_recv_len++] = 0x00;
+ m_igs029_recv_buf[m_igs029_recv_len++] = min_bets[ (~m_io_dsw[1]->read()) & 3 ];
+ m_igs029_recv_buf[m_igs029_recv_len++] = 0x05;
+ }
+ else if (m_igs029_send_buf[0] == 0x03 && m_igs029_send_buf[1] == 0x39) // '9'
+ {
+ LOGMASKED(LOG_PROT_IGS029, "READ DSW\n");
+
+ u8 ret = 0xff;
+ if (!BIT(m_dsw_select, 0)) ret &= m_io_dsw[0]->read();
+ else if (!BIT(m_dsw_select, 1)) ret &= m_io_dsw[1]->read();
+ else logerror("%s: warning, reading dsw with dsw_select = %02x\n", machine().describe_context(), m_dsw_select);
+
+ m_igs029_recv_len = 0;
+ m_igs029_recv_buf[m_igs029_recv_len++] = ret;
+ m_igs029_recv_buf[m_igs029_recv_len++] = 0x02;
+ }
+ else if (m_igs029_send_buf[0] == 0x07 && m_igs029_send_buf[1] == 0x2c) // ','
+ {
+ LOGMASKED(LOG_PROT_IGS029, "?? (2C)\n"); // ??
+
+ // 4 inputs. Returns 1 long
+
+ // called when pressing start without betting.
+ // Returning high values produces an overflow causing a division by 0, and then the game hangs.
+ m_igs029_recv_len = 0;
+ m_igs029_recv_buf[m_igs029_recv_len++] = 0x00;
+ m_igs029_recv_buf[m_igs029_recv_len++] = 0x00;
+ m_igs029_recv_buf[m_igs029_recv_len++] = 0x00;
+ m_igs029_recv_buf[m_igs029_recv_len++] = 0x01; // ??
+ m_igs029_recv_buf[m_igs029_recv_len++] = 0x05;
+ }
+ else if (m_igs029_send_buf[0] == 0x07 && m_igs029_send_buf[1] == 0x15)
+ {
+ LOGMASKED(LOG_PROT_IGS029, "SET LONG\n");
+
+ m_igs029_mgcs_long = get_u32be(&m_igs029_send_buf[2]);
+
+ m_igs029_recv_len = 0;
+ m_igs029_recv_buf[m_igs029_recv_len++] = 0x01;
+ }
+ else if (m_igs029_send_buf[0] == 0x03 && m_igs029_send_buf[1] == 0x04)
+ {
+ LOGMASKED(LOG_PROT_IGS029, "GET LONG\n");
+
+ m_igs029_recv_len = 0;
+ put_u32le(&m_igs029_recv_buf[m_igs029_recv_len], m_igs029_mgcs_long);
+ m_igs029_recv_len += 4;
+ m_igs029_recv_buf[m_igs029_recv_len++] = 0x05;
+ }
+ else
+ {
+ LOGMASKED(LOG_PROT_IGS029, "UNKNOWN\n");
+
+ m_igs029_recv_len = 0;
+ m_igs029_recv_buf[m_igs029_recv_len++] = 0x01;
+ }
+
+ m_igs029_send_len = 0;
+}
+
+void igs017_state::mgcs_keys_hopper_igs029_w(u8 data)
+{
+ // 7654 3--- Keys
+ // ---- -2-- IRQ on IGS029
+ // ---- --1-
+ // ---- ---0 Hopper Motor
+ const bool igs029_irq = !BIT(m_input_select, 2) && BIT(data, 2); // 0 -> 1
+ m_input_select = data;
+ m_hopper->motor_w(BIT(data, 0));
+
+ if (igs029_irq)
+ {
+ if (!m_igs029_recv_len)
+ {
+ // SEND
+ if (m_igs029_send_len < sizeof(m_igs029_send_buf))
+ m_igs029_send_buf[m_igs029_send_len++] = m_igs029_send_data;
+
+ LOGMASKED(LOG_PROT_IGS029, "%s: igs029 send", machine().describe_context());
+ for (int i = 0; i < m_igs029_send_len; i++)
+ LOGMASKED(LOG_PROT_IGS029, " %02x", m_igs029_send_buf[i]);
+ LOGMASKED(LOG_PROT_IGS029, "\n");
+
+ if (m_igs029_send_buf[0] == m_igs029_send_len)
+ mgcs_igs029_run();
+ }
+
+ if (m_igs029_recv_len)
+ {
+ // RECV
+ LOGMASKED(LOG_PROT_IGS029, "%s: igs029 recv", machine().describe_context());
+ for (int i = 0; i < m_igs029_recv_len; i++)
+ LOGMASKED(LOG_PROT_IGS029, " %02x", m_igs029_recv_buf[i]);
+ LOGMASKED(LOG_PROT_IGS029, "\n");
+
+ if (m_igs029_recv_len)
+ --m_igs029_recv_len;
+
+ m_igs029_recv_data = m_igs029_recv_buf[m_igs029_recv_len];
+ }
+ }
+
+ if (m_input_select & ~0xfd)
+ logerror("%s: warning, unknown bits written in input_select = %02x\n", machine().describe_context(), m_input_select);
+}
+
+void igs017_state::mgcs_scramble_data_w(u8 data)
+{
+ m_scramble_data = data;
+ LOGMASKED(LOG_PROT_SCRAMBLE, "%s: writing scrambled data %02x to igs_mux\n", machine().describe_context(), data);
+}
+
+u8 igs017_state::mgcs_scramble_data_r()
+{
+ u8 ret = bitswap<8>( (bitswap<8>(m_scramble_data, 0,1,2,3,4,5,6,7) + 1) & 3, 4,5,6,7, 0,1,2,3 );
+ LOGMASKED(LOG_PROT_SCRAMBLE, "%s: reading scrambled data %02x from igs_mux\n", machine().describe_context(), ret);
+ return ret;
+}
+
+u8 igs017_state::mgcs_igs029_data_r()
+{
+ u8 ret = m_igs029_recv_data;
+ LOGMASKED(LOG_PROT_IGS029, "%s: reading IGS029 data %02x from igs_mux\n", machine().describe_context(), ret);
+ return ret;
+}
+
+void igs017_state::mgcs_igs029_data_w(u8 data)
+{
+ m_igs029_send_data = data;
+ LOGMASKED(LOG_PROT_IGS029, "%s: writing %02x to igs_mux\n", machine().describe_context(), data & 0xff);
+}
+
+u8 igs017_state::mgcs_keys_joy_r()
+{
+ u8 ret = 0xff;
+ if (!BIT(m_input_select, 0, 3)) ret &= (m_io_joy->read() | 0x3f); // f8 (joystick mode, top 2 bits)
+ if (!BIT(m_input_select, 3)) ret &= m_io_key[0]->read(); // f7 (keyboard mode)
+ if (!BIT(m_input_select, 4)) ret &= m_io_key[1]->read(); // ef ""
+ if (!BIT(m_input_select, 5)) ret &= m_io_key[2]->read(); // df ""
+ if (!BIT(m_input_select, 6)) ret &= m_io_key[3]->read(); // bf ""
+ if (!BIT(m_input_select, 7)) ret &= m_io_key[4]->read(); // f7 ""
+ return ret;
+}
+
+void igs017_state::mgcs_map(address_map &map)
+{
+ map(0x000000, 0x07ffff).rom();
+ map(0x300000, 0x303fff).ram().share("nvram");
+
+ map(0x49c000, 0x49c001).nopr().w(m_igs_mux, FUNC(igs_mux_device::address_w)).umask16(0x00ff); // clr.w dummy read
+ map(0x49c002, 0x49c003).rw(m_igs_mux, FUNC(igs_mux_device::data_r), FUNC(igs_mux_device::data_w)).umask16(0x00ff);
+
+ map(0xa00000, 0xa0ffff).rw(m_igs017_igs031, FUNC(igs017_igs031_device::read), FUNC(igs017_igs031_device::write)).umask16(0x00ff);
+
+ map(0xa12001, 0xa12001).rw(m_oki, FUNC(okim6295_device::read), FUNC(okim6295_device::write));
+ // oki banking through protection (code at $1a350)
+}
+
+void igs017_state::mgcs_mux_map(address_map &map)
+{
+ map(0x00, 0x00).lr8(NAME([this](){ return m_input_select | 0x02; })).w(FUNC(igs017_state::mgcs_keys_hopper_igs029_w));
+ map(0x01, 0x01).r(FUNC(igs017_state::mgcs_scramble_data_r)).w(FUNC(igs017_state::mgcs_scramble_data_w));
+ map(0x02, 0x02).r(FUNC(igs017_state::mgcs_igs029_data_r));
+ map(0x03, 0x03).w(FUNC(igs017_state::mgcs_igs029_data_w));
+
+ igs_string_mux_map(map); // 0x05 r, 0x20 - 0x27 w, 0x40 r
+}
+
+void igs017_state::mgcsa_map(address_map &map)
+{
+ map(0x000000, 0x07ffff).rom();
+ map(0x100000, 0x103fff).ram().share("nvram");
+
+ map(0x49c000, 0x49c001).nopr().w(m_igs_mux, FUNC(igs_mux_device::address_w)).umask16(0x00ff); // clr.w dummy read
+ map(0x49c002, 0x49c003).rw(m_igs_mux, FUNC(igs_mux_device::data_r), FUNC(igs_mux_device::data_w)).umask16(0x00ff);
+
+ map(0x900000, 0x90ffff).rw(m_igs017_igs031, FUNC(igs017_igs031_device::read), FUNC(igs017_igs031_device::write)).umask16(0x00ff);
+
+ map(0x912001, 0x912001).rw(m_oki, FUNC(okim6295_device::read), FUNC(okim6295_device::write));
+ // oki banking through protection (code at $1a350)
+}
+
+void igs017_state::mgcsb_map(address_map &map)
+{
+ map(0x000000, 0x07ffff).rom();
+ map(0x300000, 0x303fff).ram().share("nvram");
+
+ map(0x49c000, 0x49c001).nopr().w(m_igs_mux, FUNC(igs_mux_device::address_w)).umask16(0x00ff); // clr.w dummy read
+ map(0x49c002, 0x49c003).rw(m_igs_mux, FUNC(igs_mux_device::data_r), FUNC(igs_mux_device::data_w)).umask16(0x00ff);
+
+ map(0xa00000, 0xa0ffff).rw(m_igs017_igs031, FUNC(igs017_igs031_device::read), FUNC(igs017_igs031_device::write)).umask16(0x00ff);
+
+ map(0xa10001, 0xa10001).rw(m_oki, FUNC(okim6295_device::read), FUNC(okim6295_device::write));
+}
+
+void igs017_state::mgcsb_mux_map(address_map &map) // TODO
+{
+ //map(0x00, 0x00).lr8(NAME([this](){ return m_input_select | 0x02; })).w(FUNC(igs017_state::mgcs_keys_hopper_igs029_w));
+ //map(0x01, 0x01).r(FUNC(igs017_state::mgcs_scramble_data_r)).w(FUNC(igs017_state::mgcs_scramble_data_w));
+ //map(0x02, 0x02).r(FUNC(igs017_state::mgcs_igs029_data_r));
+ //map(0x03, 0x03).w(FUNC(igs017_state::mgcs_igs029_data_w));
+
+ //igs_string_mux_map(map); // 0x05 r, 0x20 - 0x27 w, 0x40 r
+}
+
+// sdmg2
+
+void igs017_state::sdmg2_map(address_map &map)
+{
+ map(0x000000, 0x07ffff).rom();
+
+ // incdec protection
+ map(0x002001, 0x002001).w(m_igs_incdec, FUNC(igs_incdec_device::reset_w));
+ map(0x002003, 0x002003).w(m_igs_incdec, FUNC(igs_incdec_device::dec_w));
+ map(0x002007, 0x002007).w(m_igs_incdec, FUNC(igs_incdec_device::inc_w));
+ map(0x00200b, 0x00200b).r(m_igs_incdec, FUNC(igs_incdec_device::result_r));
+
+ map(0x1f0000, 0x1fffff).ram().share("nvram");
+
+ map(0x200000, 0x20ffff).rw(m_igs017_igs031, FUNC(igs017_igs031_device::read), FUNC(igs017_igs031_device::write)).umask16(0x00ff);
+
+ map(0x210001, 0x210001).rw(m_oki, FUNC(okim6295_device::read), FUNC(okim6295_device::write));
+
+ map(0x300000, 0x300001).nopr().w(m_igs_mux, FUNC(igs_mux_device::address_w)).umask16(0x00ff); // clr.w dummy read
+ map(0x300002, 0x300003).rw(m_igs_mux, FUNC(igs_mux_device::data_r), FUNC(igs_mux_device::data_w)).umask16(0x00ff);
+}
+
+template <typename T, unsigned B, unsigned R>
+T igs017_state::keys_ipt_r()
+{
+ ioport_value result = 0xff;
+ for (unsigned i = 0; std::size(m_io_key) > i; ++i)
+ {
+ if (!BIT(m_input_select, B + i))
+ result &= m_io_key[i].read_safe(0xff);
+ }
+ return T((result >> (8 - R)) | (result << R));
+}
+
+void igs017_state::sdmg2_keys_hopper_w(u8 data)
+{
+ m_input_select = BIT(data, 0, 5); // keys
+ machine().bookkeeping().coin_counter_w(0, BIT(data, 5)); // coin in
+ machine().bookkeeping().coin_counter_w(1, BIT(data, 6)); // coin out
+ m_hopper->motor_w( BIT(data, 7)); // hopper
+}
+
+void igs017_state::sdmg2_mux_map(address_map &map)
+{
+ map(0x00, 0x00).portr("COINS");
+ map(0x01, 0x01).w(FUNC(igs017_state::sdmg2_keys_hopper_w));
+ map(0x02, 0x02).portr("MATRIX").w(NAME((&igs017_state::oki_sound_bank_w<7, 0x7f>)));
+}
+
+// mgdh, mgdha
+
+void igs017_state::mgdh_map(address_map &map)
+{
+ map(0x000000, 0x07ffff).rom();
+ map(0x600000, 0x603fff).ram().share("nvram");
+
+ map(0x876000, 0x876001).nopr().w(m_igs_mux, FUNC(igs_mux_device::address_w)).umask16(0x00ff); // clr.w dummy read
+ map(0x876002, 0x876003).rw(m_igs_mux, FUNC(igs_mux_device::data_r), FUNC(igs_mux_device::data_w)).umask16(0x00ff);
+
+ map(0xa00000, 0xa0ffff).rw(m_igs017_igs031, FUNC(igs017_igs031_device::read), FUNC(igs017_igs031_device::write)).umask16(0x00ff);
+
+ map(0xa10001, 0xa10001).rw(m_oki, FUNC(okim6295_device::read), FUNC(okim6295_device::write));
+}
+
+void igs017_state::mgdh_keys_hopper_w(u8 data)
+{
+ m_input_select = data;
+ m_hopper->motor_w(BIT(data, 0));
+
+ if (m_input_select & ~0xfd)
+ logerror("%s: warning, unknown bits written in keys_hopper_w = %02x\n", machine().describe_context(), data);
+}
+
+void igs017_state::mgdh_counter_w(u8 data)
+{
+ machine().bookkeeping().coin_counter_w(0, BIT(data, 6)); // coin out
+ machine().bookkeeping().coin_counter_w(1, BIT(data, 7)); // coin in
+
+ if (data & ~0xc0)
+ logerror("%s: warning, unknown bits written in counter_w = %02x\n", machine().describe_context(), data);
+}
+
+void igs017_state::mgdha_mux_map(address_map &map)
+{
+ map(0x00, 0x00).portr("MATRIX").w(FUNC(igs017_state::mgdh_counter_w));
+ map(0x01, 0x01).portr("BUTTONS").w(FUNC(igs017_state::mgdh_keys_hopper_w));
+ map(0x02, 0x02).lr8(NAME([this](){ return bitswap<8>(m_io_dsw[1]->read(), 0,1,2,3,4,5,6,7); }));
+ map(0x03, 0x03).portr("COINS").w(NAME((&igs017_state::oki_sound_bank_w<6, 0x3f>))); // bit 7? always on
+}
+
+void igs017_state::mgdh_mux_map(address_map &map)
+{
+ mgdha_mux_map(map);
+
+// igs_string_mux_map(map); // 0x05 r, 0x20 - 0x27 w, 0x40 r (actually unused except for the game id check?)
+}
+
+// sdmg2p
+
+void igs017_state::sdmg2p_map(address_map &map)
+{
+ map(0x000000, 0x07ffff).rom();
+
+ map(0x100000, 0x103fff).ram().share("nvram");
+
+ map(0x38d000, 0x38d001).nopr().w(m_igs_mux, FUNC(igs_mux_device::address_w)).umask16(0x00ff); // clr.w dummy read
+ map(0x38d002, 0x38d003).rw(m_igs_mux, FUNC(igs_mux_device::data_r), FUNC(igs_mux_device::data_w)).umask16(0x00ff);
+
+ map(0xb00000, 0xb0ffff).rw(m_igs017_igs031, FUNC(igs017_igs031_device::read), FUNC(igs017_igs031_device::write)).umask16(0x00ff);
+
+ map(0xb10001, 0xb10001).rw(m_oki, FUNC(okim6295_device::read), FUNC(okim6295_device::write));
+}
+
+void igs017_state::sdmg2p_mux_map(address_map &map) // TODO: hopper motor w
+{
+ map.unmap_value_high();
+ map(0x00, 0x00).r(NAME((&igs017_state::keys_ipt_r<u8, 2, 2>)));
+ map(0x01, 0x01).portr("JOY");
+ map(0x02, 0x02).portr("BUTTONS").w(FUNC(igs017_state::mgdh_keys_hopper_w));
+ map(0x03, 0x03).portr("COINS").w(FUNC(igs017_state::mgdh_counter_w));
+
+ igs_string_mux_map(map);
+}
+
+// tjsb
+
+void igs017_state::tjsb_map(address_map &map)
+{
+ map(0x00000, 0x0dfff).rom();
+
+ map(0x0e000, 0x0e000).w (m_igs_mux, FUNC(igs_mux_device::address_w));
+ map(0x0e001, 0x0e001).rw(m_igs_mux, FUNC(igs_mux_device::data_r), FUNC(igs_mux_device::data_w));
+
+ map(0x0e002, 0x0efff).ram();
+ map(0x0f000, 0x0ffff).ram();
+ map(0x10000, 0x3ffff).rom();
+}
+
+void igs017_state::tjsb_io(address_map &map)
+{
+ map(0x0000, 0x7fff).rw(m_igs017_igs031, FUNC(igs017_igs031_device::read), FUNC(igs017_igs031_device::write));
+ map(0x0000, 0x003f).ram(); // internal regs
+
+ map(0x9000, 0x9000).rw(m_oki, FUNC(okim6295_device::read), FUNC(okim6295_device::write));
+
+ map(0xb000, 0xb001).w("ymsnd", FUNC(ym2413_device::write));
+}
+
+void igs017_state::tjsb_mux_map(address_map &map)
+{
+ map(0x00, 0x00).portr("PLAYER1").w(NAME((&igs017_state::counter_w<7, 0x7f, 0>))); // coin in
+ map(0x01, 0x01).portr("PLAYER2").w(NAME((&igs017_state::counter_w<0, 0xfe, 1>))); // coin out
+ map(0x02, 0x02).portr("COINS").w(NAME((&igs017_state::oki_sound_bank_w<4, 0xcf>))); // oki bank (0x20/0x30)
+ map(0x03, 0x03).portr("BUTTONS").w(NAME((&igs017_state::hopper_motor_w<6, 0xbf>)));
+
+ // used ?
+ igs_string_mux_map(map); // 0x05 r, 0x20 - 0x27 w, 0x40 r
+}
+
+
+// spkrform
+
+void igs017_state::spkrform_io(address_map &map)
+{
+ map(0x0000, 0x7fff).rw(m_igs017_igs031, FUNC(igs017_igs031_device::read), FUNC(igs017_igs031_device::write));
+ map(0x0000, 0x003f).ram(); // internal regs
+
+ map(0x2010, 0x2011).w(FUNC(igs017_state::incdec_remap_addr_w));
+
+ map(0x8000, 0x8000).rw(m_oki, FUNC(okim6295_device::read), FUNC(okim6295_device::write));
+
+ map(0x9000, 0x9001).w("ymsnd", FUNC(ym2413_device::write));
+
+// map(0xa000, 0xa0??).ram(); // read/written during poker game enabling at boot (patched out)
+
+ map(0xb000, 0xb000).w (m_igs_mux, FUNC(igs_mux_device::address_w));
+ map(0xb001, 0xb001).rw(m_igs_mux, FUNC(igs_mux_device::data_r), FUNC(igs_mux_device::data_w));
+}
+
+void igs017_state::spkrform_mux_map(address_map &map)
+{
+ map(0x00, 0x00).portr("PLAYER1").w(NAME((&igs017_state::counter_w<7, 0x7f, 0>))); // coin in
+ map(0x01, 0x01).portr("PLAYER2").w(NAME((&igs017_state::counter_w<7, 0x7f, 1>))); // coin out
+ map(0x02, 0x02).portr("COINS").w(NAME((&igs017_state::hopper_motor_w<4, 0xef>))); // bit 5 is related to poker game enabling
+ map(0x03, 0x03).portr("BUTTONS");
+
+ igs_string_mux_map(map); // 0x05 r, 0x20 - 0x27 w, 0x40 r
+}
+
+
+// lhzb2
+
+void igs017_state::lhzb2_map(address_map &map)
+{
+ map(0x000000, 0x07ffff).rom();
+
+ map(0x100000, 0x103fff).ram().share("igs022:sharedprotram"); // Shared with protection device
+
+ map(0x500000, 0x503fff).ram().share("nvram");
+
+ map(0x910000, 0x910001).nopr().w(m_igs_mux, FUNC(igs_mux_device::address_w)).umask16(0x00ff); // clr.w dummy read
+ map(0x910002, 0x910003).rw(m_igs_mux, FUNC(igs_mux_device::data_r), FUNC(igs_mux_device::data_w)).umask16(0x00ff);
+
+ map(0xb00000, 0xb0ffff).rw(m_igs017_igs031, FUNC(igs017_igs031_device::read), FUNC(igs017_igs031_device::write)).umask16(0x00ff);
+
+ map(0xb10001, 0xb10001).rw(m_oki, FUNC(okim6295_device::read), FUNC(okim6295_device::write));
+}
+
+u8 igs017_state::lhzb2_keys_r()
+{
+ u8 ret = 0xff;
+ if (!BIT(m_input_select, 0)) ret &= m_io_key[0]->read();
+ if (!BIT(m_input_select, 1)) ret &= m_io_key[1]->read();
+ if (!BIT(m_input_select, 2)) ret &= m_io_key[2]->read();
+ if (!BIT(m_input_select, 3)) ret &= m_io_key[3]->read();
+ if (!BIT(m_input_select, 4)) ret &= m_io_key[4]->read();
+ return ret;
+}
+
+void igs017_state::lhzb2_keys_hopper_w(u8 data)
+{
+ m_input_select = BIT(data, 0, 5); // keys
+ m_hopper->motor_w( BIT(data, 5)); // hopper
+ machine().bookkeeping().coin_counter_w(1, BIT(data, 6)); // coin out counter
+ machine().bookkeeping().coin_counter_w(0, BIT(data, 7)); // coin in counter
+}
+
+u8 igs017_state::lhzb2_scramble_data_r()
+{
+ u8 ret = bitswap<8>(m_scramble_data, 0,1,2,3,4,5,6,7);
+ LOGMASKED(LOG_PROT_SCRAMBLE, "%s: reading scrambled data %02x from igs_mux\n", machine().describe_context(), ret);
+ return ret;
+}
+
+void igs017_state::lhzb2_igs022_execute_w(u8 data)
+{
+ m_oki->set_rom_bank(BIT(data, 7));
+ igs022_execute_w<6, 0x3f>(data);
+}
+
+void igs017_state::lhzb2_mux_map(address_map &map)
+{
+ map(0x00, 0x00).w(FUNC(igs017_state::lhzb2_keys_hopper_w));
+ map(0x01, 0x01).r(FUNC(igs017_state::lhzb2_keys_r)).w(FUNC(igs017_state::lhzb2_igs022_execute_w));
+ map(0x02, 0x02).r(FUNC(igs017_state::lhzb2_scramble_data_r));
+ map(0x03, 0x03).w(FUNC(igs017_state::mgcs_scramble_data_w));
+
+ igs_string_mux_map(map); // 0x05 r, 0x20 - 0x27 w, 0x40 r
+}
+
+
+// lhzb2a
+// To do: what devices are on this PCB?
+
+u16 igs017_state::lhzb2a_input_r(offs_t offset)
+{
+ switch (offset * 2)
+ {
+ case 0x00: // Keys
+ return (lhzb2_keys_r() << 8) | 0xff;
+
+ case 0x02:
+ return (m_io_dsw[0]->read() << 8) | m_io_coins->read();
+
+ case 0x04:
+ return 0xff00 | m_io_dsw[1]->read();
+ }
+
+ return 0xffff;
+}
+
+/***************************************************************************
+
+ An address base register (xx = F0 at reset) determines where the bitswap protection device,
+ as well as game inputs and the address base register itself are mapped in memory:
+ inputs are mapped at xx8000, protection at xx4000 and address base register at xxc000.
+
+***************************************************************************/
+
+void igs017_state::lhzb2a_remap_addr_w(address_space &space, u16 data)
+{
+ // Unmap previous address ranges
+ if (m_remap_addr != -1)
+ {
+ space.unmap_write (m_remap_addr * 0x10000 + 0x4000, m_remap_addr * 0x10000 + 0x4001);
+ space.unmap_readwrite(m_remap_addr * 0x10000 + 0x4002, m_remap_addr * 0x10000 + 0x4003);
+
+ space.unmap_read (m_remap_addr * 0x10000 + 0x8000, m_remap_addr * 0x10000 + 0x8005);
+ space.unmap_write (m_remap_addr * 0x10000 + 0xc000, m_remap_addr * 0x10000 + 0xc001);
+ }
+
+ m_remap_addr = data & 0xff;
+
+ // Add new memory ranges
+ space.install_write_handler (m_remap_addr * 0x10000 + 0x4001, m_remap_addr * 0x10000 + 0x4001, write8smo_delegate(*m_igs_mux, FUNC(igs_mux_device::address_w)));
+ space.install_readwrite_handler(m_remap_addr * 0x10000 + 0x4003, m_remap_addr * 0x10000 + 0x4003, read8smo_delegate (*m_igs_mux, FUNC(igs_mux_device::data_r)), write8smo_delegate(*m_igs_mux, FUNC(igs_mux_device::data_w)));
+
+ space.install_read_handler (m_remap_addr * 0x10000 + 0x8000, m_remap_addr * 0x10000 + 0x8005, read16sm_delegate (*this, FUNC(igs017_state::lhzb2a_input_r)));
+ space.install_write_handler (m_remap_addr * 0x10000 + 0xc000, m_remap_addr * 0x10000 + 0xc001, write16mo_delegate(*this, FUNC(igs017_state::lhzb2a_remap_addr_w)));
+
+ LOGMASKED(LOG_PROT_REMAP, "%s: inputs and protection remapped at %02xxxxx\n", machine().describe_context(), m_remap_addr);
+}
+
+void igs017_state::lhzb2a_keys_hopper_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ if (ACCESSING_BITS_0_7)
+ {
+ m_input_select = BIT(data, 0, 5); // keys
+ m_hopper->motor_w( BIT(data, 5)); // hopper
+ machine().bookkeeping().coin_counter_w(0, BIT(data, 6)); // coin out counter
+ machine().bookkeeping().coin_counter_w(1, BIT(data, 7)); // coin in counter
+ }
+ if (ACCESSING_BITS_8_15)
+ {
+ m_oki->set_rom_bank(BIT(data, 7));
+
+ if (data & 0xfe00)
+ logerror("%s: warning, unknown bits written in keys_hopper_w = %04x\n", machine().describe_context(), data);
+ }
+}
+
+void igs017_state::lhzb2a_map(address_map &map)
+{
+ map(0x000000, 0x07ffff).rom();
+
+ // incdec protection
+ map(0x003201, 0x003201).w(m_igs_incdec, FUNC(igs_incdec_device::reset_w));
+ map(0x003203, 0x003203).w(m_igs_incdec, FUNC(igs_incdec_device::dec_w));
+ map(0x003207, 0x003207).w(m_igs_incdec, FUNC(igs_incdec_device::inc_w));
+ map(0x00320b, 0x00320b).r(m_igs_incdec, FUNC(igs_incdec_device::result_r));
+
+ map(0x500000, 0x503fff).ram().share("nvram");
+// map(0x910000, 0x910003) accesses appear to be from leftover code where the final checks were disabled
+
+ map(0xb00000, 0xb0ffff).rw(m_igs017_igs031, FUNC(igs017_igs031_device::read), FUNC(igs017_igs031_device::write)).umask16(0x00ff);
+
+ map(0xb10001, 0xb10001).rw(m_oki, FUNC(okim6295_device::read), FUNC(okim6295_device::write));
+
+ map(0xb12000, 0xb12001).w(FUNC(igs017_state::lhzb2a_keys_hopper_w));
+
+ // Inputs dynamically mapped at xx8000, protection at xx4000 (xx = f0 initially). xx written to xxc000
+}
+
+void igs017_state::lhzb2a_mux_map(address_map &map)
+{
+ igs_bitswap_mux_map(map); // 0x03 r, 0x40 - 0x47 w, 0x48 w, 0x50 w, 0x80 - 0x87 w, 0xa0 w
+
+ // used ?
+ igs_string_mux_map(map); // 0x05 r, 0x20 - 0x27 w, 0x40 r
+}
+
+
+// slqz2
+
+void igs017_state::slqz2_map(address_map &map)
+{
+ map(0x000000, 0x07ffff).rom();
+ map(0x100000, 0x103fff).ram().share("nvram");
+
+ map(0x300000, 0x303fff).ram().share("igs022:sharedprotram"); // Shared with protection device
+
+ map(0x602000, 0x602001).nopr().w(m_igs_mux, FUNC(igs_mux_device::address_w)).umask16(0x00ff); // clr.w dummy read
+ map(0x602002, 0x602003).rw(m_igs_mux, FUNC(igs_mux_device::data_r), FUNC(igs_mux_device::data_w)).umask16(0x00ff);
+
+ map(0x900000, 0x90ffff).rw(m_igs017_igs031, FUNC(igs017_igs031_device::read), FUNC(igs017_igs031_device::write)).umask16(0x00ff);
+
+ map(0x910001, 0x910001).rw(m_oki, FUNC(okim6295_device::read), FUNC(okim6295_device::write));
+}
+
+void igs017_state::slqz2_sound_hopper_w(u8 data)
+{
+ m_oki->set_rom_bank( BIT(data, 0));
+ //
+ m_hopper->motor_w( BIT(data, 5)); // hopper
+ machine().bookkeeping().coin_counter_w(1, BIT(data, 6)); // coin out counter
+ machine().bookkeeping().coin_counter_w(0, BIT(data, 7)); // coin in counter
+
+ if (data & 0x1e)
+ logerror("%s: warning, unknown bits written in sound_hopper_w = %04x\n", machine().describe_context(), data);
+}
+
+u8 igs017_state::slqz2_scramble_data_r()
+{
+ u8 ret = m_scramble_data;
+ LOGMASKED(LOG_PROT_SCRAMBLE, "%s: reading scrambled data %02x from igs_mux\n", machine().describe_context(), ret);
+ return ret;
+}
+
+void igs017_state::slqz2_mux_map(address_map &map)
+{
+ map(0x00, 0x00).portr("PLAYER2").w(FUNC(igs017_state::slqz2_sound_hopper_w));
+ map(0x01, 0x01).portr("PLAYER1").w(NAME((&igs017_state::igs022_execute_w<6, 0xbf>)));
+ map(0x02, 0x02).r(FUNC(igs017_state::slqz2_scramble_data_r));
+ map(0x03, 0x03).w(FUNC(igs017_state::mgcs_scramble_data_w));
+
+ igs_string_mux_map(map); // 0x05 r, 0x20 - 0x27 w, 0x40 r
+}
+
+
+// jking302us
+
+void igs017_state::jking302us_map(address_map &map)
+{
+ map(0x000000, 0x07ffff).rom();
+ map(0x100000, 0x103fff).ram().share("nvram"); // TODO: verify once it works
+
+ map(0x638000, 0x638001).nopr().w(m_igs_mux, FUNC(igs_mux_device::address_w)).umask16(0x00ff); // clr.w dummy read
+ map(0x638002, 0x638003).rw(m_igs_mux, FUNC(igs_mux_device::data_r), FUNC(igs_mux_device::data_w)).umask16(0x00ff);
+
+ map(0xb00000, 0xb0ffff).rw(m_igs017_igs031, FUNC(igs017_igs031_device::read), FUNC(igs017_igs031_device::write)).umask16(0x00ff);
+
+ // map(0x912001, 0x912001).rw(m_oki, FUNC(okim6295_device::read), FUNC(okim6295_device::write)); // TODO
+
+ // map(0xfff000, 0xf00003).rw(); // TODO
+}
+
+void igs017_state::jking302us_mux_map(address_map &map)
+{
+ // TODO
+
+ igs_string_mux_map(map); // 0x05 r, 0x20 - 0x27 w, 0x40 r
+}
+
+
+/***************************************************************************
+ Input Ports
+***************************************************************************/
+
+static INPUT_PORTS_START( iqblocka )
+ PORT_START("DSW1")
+ PORT_DIPNAME( 0x01, 0x00, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW1:1")
+ PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x02, 0x02, "Hold Mode" ) PORT_DIPLOCATION("SW1:2")
+ PORT_DIPSETTING( 0x02, "In Win" )
+ PORT_DIPSETTING( 0x00, "Always" )
+ PORT_DIPNAME( 0x04, 0x04, "Max Credit" ) PORT_DIPLOCATION("SW1:3")
+ PORT_DIPSETTING( 0x04, "4000" )
+ PORT_DIPSETTING( 0x00, DEF_STR( None ) )
+ PORT_DIPNAME( 0x38, 0x38, "Cigarette Bet" ) PORT_DIPLOCATION("SW1:4,5,6")
+ PORT_DIPSETTING( 0x38, "1" )
+ PORT_DIPSETTING( 0x30, "10" )
+ PORT_DIPSETTING( 0x28, "20" )
+ PORT_DIPSETTING( 0x20, "50" )
+ PORT_DIPSETTING( 0x18, "80" )
+ PORT_DIPSETTING( 0x10, "100" )
+ PORT_DIPSETTING( 0x08, "120" )
+ PORT_DIPSETTING( 0x00, "150" )
+ PORT_DIPNAME( 0xc0, 0xc0, "Minimum Bet" ) PORT_DIPLOCATION("SW1:7,8")
+ PORT_DIPSETTING( 0xc0, "1" )
+ PORT_DIPSETTING( 0x80, "10" )
+ PORT_DIPSETTING( 0x40, "20" )
+ PORT_DIPSETTING( 0x00, "50" )
+
+ PORT_START("DSW2")
+ PORT_DIPNAME( 0x07, 0x07, "Key In" ) PORT_DIPLOCATION("SW2:1,2,3")
+ PORT_DIPSETTING( 0x07, "10" )
+ PORT_DIPSETTING( 0x06, "20" )
+ PORT_DIPSETTING( 0x05, "40" )
+ PORT_DIPSETTING( 0x04, "50" )
+ PORT_DIPSETTING( 0x03, "100" )
+ PORT_DIPSETTING( 0x02, "200" )
+ PORT_DIPSETTING( 0x01, "250" )
+ PORT_DIPSETTING( 0x00, "500" )
+ PORT_DIPNAME( 0x08, 0x08, "Key Out" ) PORT_DIPLOCATION("SW2:4")
+ PORT_DIPSETTING( 0x08, "10" )
+ PORT_DIPSETTING( 0x00, "100" )
+ PORT_DIPNAME( 0x10, 0x10, "Open Mode" ) PORT_DIPLOCATION("SW2:5")
+ PORT_DIPSETTING( 0x10, "Gaming (Gambling)" )
+ PORT_DIPSETTING( 0x00, "Amuse" )
+ PORT_DIPNAME( 0x20, 0x00, "Demo Game" ) PORT_DIPLOCATION("SW2:6")
+ PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0xc0, 0xc0, "Bonus Base" ) PORT_DIPLOCATION("SW2:7,8")
+ PORT_DIPSETTING( 0xc0, "100" )
+ PORT_DIPSETTING( 0x80, "200" )
+ PORT_DIPSETTING( 0x40, "300" )
+ PORT_DIPSETTING( 0x00, "400" )
+
+ PORT_START("DSW3")
+ PORT_DIPNAME( 0x03, 0x03, "Win Up Pool" ) PORT_DIPLOCATION("SW3:1,2")
+ PORT_DIPSETTING( 0x03, "300" )
+ PORT_DIPSETTING( 0x02, "500" )
+ PORT_DIPSETTING( 0x01, "800" )
+ PORT_DIPSETTING( 0x00, "1000" )
+ PORT_DIPNAME( 0x0c, 0x0c, "Max Double Up" ) PORT_DIPLOCATION("SW3:3,4")
+ PORT_DIPSETTING( 0x0c, "20000" )
+ PORT_DIPSETTING( 0x08, "30000" )
+ PORT_DIPSETTING( 0x04, "40000" )
+ PORT_DIPSETTING( 0x00, "50000" )
+ PORT_DIPNAME( 0x10, 0x10, "Number Type" ) PORT_DIPLOCATION("SW3:5")
+ PORT_DIPSETTING( 0x10, "A,J,Q,K" )
+ PORT_DIPSETTING( 0x00, "Number" )
+ PORT_DIPNAME( 0x20, 0x20, "Show Title" ) PORT_DIPLOCATION("SW3:6")
+ PORT_DIPSETTING( 0x20, DEF_STR( Yes ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( No ) )
+ PORT_DIPNAME( 0x40, 0x40, "Double Up" ) PORT_DIPLOCATION("SW3:7")
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x40, DEF_STR( On ) )
+ PORT_DIPNAME( 0x80, 0x80, "CG Select" ) PORT_DIPLOCATION("SW3:8") // Switches CG ROM (sprites). Unpopulated in this set
+ PORT_DIPSETTING( 0x80, DEF_STR( Low ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( High ) )
+
+ PORT_START("PLAYER1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 ) // start, in videogame mode (keep pressed while booting for DSW and inputs test)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_UP )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_NAME("%p Down / Collect Win")
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_POKER_HOLD1 ) PORT_NAME("Hold 1 / Big / Help") // (1P A in test mode) help = next tile becomes a wildcard (in videogame mode)
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_POKER_HOLD2 ) PORT_NAME("Hold 2 / Double Up") // (1P B in test mode)
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+
+ PORT_START("PLAYER2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_GAMBLE_DEAL ) PORT_NAME("Deal / Last Bet") // play current bet or, if null, the last bet (START2 in test mode)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) // unused? shown in test mode
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) // ""
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) // ""
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) // ""
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_POKER_HOLD4 ) PORT_NAME("Hold 4 / Half Double") // (2P A in test mode)
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_POKER_HOLD5 ) PORT_NAME("Hold 5 / Tile in Double Up?") // (2P B in test mode)
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+
+ PORT_START("COINS")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_GAMBLE_KEYIN )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(5) // impulse prevents coin error in gambling mode
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_SERVICE_NO_TOGGLE( 0x40, IP_ACTIVE_LOW ) // keep pressed while booting
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_SERVICE1 ) PORT_NAME("Toggle Gambling") // this toggles between videogame and gambling
+
+ PORT_START("BUTTONS")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_POKER_HOLD3 ) PORT_NAME("Hold 3 / Small") // (1P C in test mode)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_IMPULSE(5) // no coin. Hopper sensor? impulse prevents coin error in gambling mode (1P D in test mode)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON4 ) // unused? (1P E in test mode)
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_BET ) // Bet 1 credit (2P C in test mode)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2) // unused? (2P D in test mode)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(2) // unused? (2P E in test mode)
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( iqblockf )
+ PORT_INCLUDE( iqblocka )
+
+ PORT_MODIFY("DSW1")
+ PORT_DIPNAME( 0x01, 0x00, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW1:1")
+ PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x02, 0x02, "Hold Mode" ) PORT_DIPLOCATION("SW1:2")
+ PORT_DIPSETTING( 0x02, "In Win" )
+ PORT_DIPSETTING( 0x00, "Always" )
+ PORT_DIPNAME( 0x0c, 0x0c, "Coin In" ) PORT_DIPLOCATION("SW1:3,4")
+ PORT_DIPSETTING( 0x0c, "1" )
+ PORT_DIPSETTING( 0x08, "5" )
+ PORT_DIPSETTING( 0x04, "10" )
+ PORT_DIPSETTING( 0x00, "20" )
+ PORT_DIPNAME( 0x30, 0x30, "Key In" ) PORT_DIPLOCATION("SW1:5,6")
+ PORT_DIPSETTING( 0x30, "10" )
+ PORT_DIPSETTING( 0x20, "100" )
+ PORT_DIPSETTING( 0x10, "200" )
+ PORT_DIPSETTING( 0x00, "500" )
+ PORT_DIPNAME( 0xc0, 0xc0, "Minimum Bet" ) PORT_DIPLOCATION("SW1:7,8")
+ PORT_DIPSETTING( 0xc0, "1" )
+ PORT_DIPSETTING( 0x80, "2" )
+ PORT_DIPSETTING( 0x40, "5" )
+ PORT_DIPSETTING( 0x00, "10" )
+
+ PORT_MODIFY("DSW2")
+ PORT_DIPNAME( 0x03, 0x03, "Max Bet" ) PORT_DIPLOCATION("SW2:1,2")
+ PORT_DIPSETTING( 0x03, "5" )
+ PORT_DIPSETTING( 0x02, "10" )
+ PORT_DIPSETTING( 0x01, "20" )
+ PORT_DIPSETTING( 0x00, "50" )
+ PORT_DIPNAME( 0x04, 0x04, "Register" ) PORT_DIPLOCATION("SW2:3")
+ PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x08, 0x08, "Key Out Base" ) PORT_DIPLOCATION("SW2:4")
+ PORT_DIPSETTING( 0x08, "1" )
+ PORT_DIPSETTING( 0x00, "10" )
+ PORT_DIPNAME( 0x10, 0x10, "Open Mode" ) PORT_DIPLOCATION("SW2:5")
+ PORT_DIPSETTING( 0x10, "Gaming (Gambling)" )
+ PORT_DIPSETTING( 0x00, "Amuse" )
+ PORT_DIPNAME( 0x20, 0x00, "Demo Game" ) PORT_DIPLOCATION("SW2:6")
+ PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPUNUSED_DIPLOC( 0x40, 0x40, "SW2:7" )
+ PORT_DIPUNUSED_DIPLOC( 0x80, 0x80, "SW2:8" )
+
+ PORT_MODIFY("DSW3")
+ PORT_DIPUNUSED_DIPLOC( 0x01, 0x01, "SW3:1" )
+ PORT_DIPUNUSED_DIPLOC( 0x02, 0x02, "SW3:2" )
+ PORT_DIPUNUSED_DIPLOC( 0x04, 0x04, "SW3:3" )
+ PORT_DIPUNUSED_DIPLOC( 0x08, 0x08, "SW3:4" )
+ PORT_DIPNAME( 0x10, 0x10, "Number Type" ) PORT_DIPLOCATION("SW3:5")
+ PORT_DIPSETTING( 0x10, "A,J,Q,K" )
+ PORT_DIPSETTING( 0x00, "Number" )
+ PORT_DIPUNUSED_DIPLOC( 0x20, 0x20, "SW3:6" )
+ PORT_DIPUNUSED_DIPLOC( 0x40, 0x40, "SW3:7" )
+ PORT_DIPNAME( 0x80, 0x80, "CG Select" ) PORT_DIPLOCATION("SW3:8") // Switches CG ROM (sprites). Unpopulated in this set
+ PORT_DIPSETTING( 0x80, DEF_STR( Low ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( High ) )
+
+ PORT_MODIFY("PLAYER2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_GAMBLE_DEAL ) PORT_NAME("Deal / Last Bet / Toggle Gambling (8 Times)") // play current bet or, if null, bet as last time (START2 in test mode)
+
+ PORT_MODIFY("COINS")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(5) // impulse prevents coin error in gambling mode
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_GAMBLE_KEYIN )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_SERVICE_NO_TOGGLE( 0x40, IP_ACTIVE_LOW ) // book-keeping after switching to gambling (TEST in test mode)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_SERVICE1 ) PORT_NAME("Start Gambling Toggle (Then Deal x 8)") // this starts toggling between videogame and gambling
+
+ PORT_MODIFY("BUTTONS")
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT ) // (1P E in test mode)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT ) // (2P E in test mode)
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( genius6 )
+ PORT_INCLUDE( iqblockf )
+
+ PORT_MODIFY("DSW1")
+ PORT_DIPNAME( 0x01, 0x00, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW1:1")
+ PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x02, 0x02, "Auto Hold" ) PORT_DIPLOCATION("SW1:2")
+ PORT_DIPSETTING( 0x02, DEF_STR( No ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( Yes ) )
+ PORT_DIPNAME( 0x0c, 0x0c, "Coin In" ) PORT_DIPLOCATION("SW1:3,4")
+ PORT_DIPSETTING( 0x0c, "1" )
+ PORT_DIPSETTING( 0x08, "10" )
+ PORT_DIPSETTING( 0x04, "20" )
+ PORT_DIPSETTING( 0x00, "50" )
+ PORT_DIPNAME( 0x30, 0x30, "Key In" ) PORT_DIPLOCATION("SW1:5,6")
+ PORT_DIPSETTING( 0x30, "10" )
+ PORT_DIPSETTING( 0x20, "100" )
+ PORT_DIPSETTING( 0x10, "200" )
+ PORT_DIPSETTING( 0x00, "500" )
+ PORT_DIPNAME( 0xc0, 0xc0, "Minimum Bet" ) PORT_DIPLOCATION("SW1:7,8")
+ PORT_DIPSETTING( 0xc0, "1" )
+ PORT_DIPSETTING( 0x80, "2" )
+ PORT_DIPSETTING( 0x40, "5" )
+ PORT_DIPSETTING( 0x00, "10" )
+
+ PORT_MODIFY("DSW2")
+ PORT_DIPNAME( 0x03, 0x03, "Max Bet" ) PORT_DIPLOCATION("SW2:1,2")
+ PORT_DIPSETTING( 0x03, "5" )
+ PORT_DIPSETTING( 0x02, "10" )
+ PORT_DIPSETTING( 0x01, "20" )
+ PORT_DIPSETTING( 0x00, "50" )
+ PORT_DIPUNUSED_DIPLOC( 0x04, 0x04, "SW2:3" )
+ PORT_DIPNAME( 0x08, 0x08, "Key Out" ) PORT_DIPLOCATION("SW2:4")
+ PORT_DIPSETTING( 0x08, "1" )
+ PORT_DIPSETTING( 0x00, "10" )
+ PORT_DIPNAME( 0x10, 0x10, "Open Mode" ) PORT_DIPLOCATION("SW2:5")
+ PORT_DIPSETTING( 0x10, "Gaming (Gambling)" )
+ PORT_DIPSETTING( 0x00, "Amuse" )
+ PORT_DIPNAME( 0x20, 0x00, "Demo Game" ) PORT_DIPLOCATION("SW2:6")
+ PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPUNUSED_DIPLOC( 0x40, 0x40, "SW2:7" )
+ PORT_DIPUNUSED_DIPLOC( 0x80, 0x80, "SW2:8" )
+
+ PORT_MODIFY("DSW3")
+ PORT_DIPUNUSED_DIPLOC( 0x01, 0x01, "SW3:1" ) // the input test screen prints garbage when not all off
+ PORT_DIPUNUSED_DIPLOC( 0x02, 0x02, "SW3:2" ) // ""
+ PORT_DIPUNUSED_DIPLOC( 0x04, 0x04, "SW3:3" ) // ""
+ PORT_DIPUNUSED_DIPLOC( 0x08, 0x08, "SW3:4" ) // ""
+ PORT_DIPNAME( 0x10, 0x10, "Number Type" ) PORT_DIPLOCATION("SW3:5")
+ PORT_DIPSETTING( 0x10, "A,J,Q,K" )
+ PORT_DIPSETTING( 0x00, "Number" )
+ PORT_DIPUNUSED_DIPLOC( 0x20, 0x20, "SW3:6" )
+ PORT_DIPUNUSED_DIPLOC( 0x40, 0x40, "SW3:7" )
+ PORT_DIPUNUSED_DIPLOC( 0x80, 0x80, "SW3:8" )
+
+ PORT_MODIFY("PLAYER2")
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_POKER_HOLD5 ) // (2P B in test mode)
+INPUT_PORTS_END
+
+#define CREDIT_SETTINGS_COMMON \
+ PORT_DIPNAME( 0x03, 0x03, DEF_STR( Coinage ) ) PORT_DIPLOCATION("SW1:1,2") /* 投幣比率 */ \
+ PORT_DIPSETTING( 0x03, DEF_STR( 1C_1C ) ) \
+ PORT_DIPSETTING( 0x02, DEF_STR( 1C_2C ) ) \
+ PORT_DIPSETTING( 0x01, DEF_STR( 1C_3C ) ) \
+ PORT_DIPSETTING( 0x00, DEF_STR( 1C_5C ) ) \
+ PORT_DIPNAME( 0x0c, 0x0c, "Key-In Rate" ) PORT_DIPLOCATION("SW1:3,4") /* 開分比率 */ \
+ PORT_DIPSETTING( 0x0c, "10" ) \
+ PORT_DIPSETTING( 0x08, "20" ) \
+ PORT_DIPSETTING( 0x04, "50" ) \
+ PORT_DIPSETTING( 0x00, "100" ) \
+ PORT_DIPNAME( 0x20, 0x20, "Credit Mode" ) PORT_DIPLOCATION("SW1:6") /* 進分方式 */ \
+ PORT_DIPSETTING( 0x20, "Coin Acceptor" ) /* 投幣 */ \
+ PORT_DIPSETTING( 0x00, "Key-In" ) /* 開分 */ \
+ PORT_DIPNAME( 0x40, 0x40, "Payout Mode" ) PORT_DIPLOCATION("SW1:7") /* 退分方式 */ \
+ PORT_DIPSETTING( 0x40, "Return Coins" ) /* 退幣 */ \
+ PORT_DIPSETTING( 0x00, "Key-Out" ) /* 洗分 */
+
+static INPUT_PORTS_START( lhzb2_common )
+ PORT_INCLUDE(igs_mahjong_matrix)
+
+ PORT_START("DSW1")
+ CREDIT_SETTINGS_COMMON
+ PORT_DIPNAME( 0x10, 0x10, "Credit Limit" ) PORT_DIPLOCATION("SW1:5") // 进分上限
+ PORT_DIPSETTING( 0x10, "1000" )
+ PORT_DIPSETTING( 0x00, "2000" )
+ PORT_DIPNAME( 0x80, 0x80, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW1:8") // 示范音乐
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) // 无
+ PORT_DIPSETTING( 0x80, DEF_STR( On ) ) // 有
+
+ PORT_START("DSW2")
+ PORT_DIPNAME( 0x03, 0x03, "Double Up Jackpot" ) PORT_DIPLOCATION("SW2:1,2") // 比倍爆机
+ PORT_DIPSETTING( 0x03, "500" )
+ PORT_DIPSETTING( 0x02, "1000" )
+ PORT_DIPSETTING( 0x01, "1500" )
+ PORT_DIPSETTING( 0x00, "2000" )
+ PORT_DIPNAME( 0x0c, 0x0c, "Minimum Bet" ) PORT_DIPLOCATION("SW2:3,4") // 最小押注
+ PORT_DIPSETTING( 0x0c, "1 (1)" )
+ PORT_DIPSETTING( 0x08, "1 (2)" )
+ PORT_DIPSETTING( 0x04, "1 (3)" )
+ PORT_DIPSETTING( 0x00, "1 (4)" )
+ PORT_DIPNAME( 0x10, 0x10, "Double Up Game" ) PORT_DIPLOCATION("SW2:5") // 比倍游戏
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) // 无
+ PORT_DIPSETTING( 0x10, DEF_STR( On ) ) // 有
+ PORT_DIPNAME( 0x20, 0x20, "Double Up Game Name" ) PORT_DIPLOCATION("SW2:6") // 比倍续玩 (changes names for double up game and Double Up/Big/Small buttons)
+ PORT_DIPSETTING( 0x20, "Continue Play" ) // 续玩 (续玩/左/右)
+ PORT_DIPSETTING( 0x00, "Double Up" ) // 比倍 (比倍/大/小)
+ PORT_DIPNAME( 0x40, 0x40, "Number Type" ) PORT_DIPLOCATION("SW2:7") // 数字型态
+ PORT_DIPSETTING( 0x40, "Numbers" ) // 数字
+ PORT_DIPSETTING( 0x00, "Blocks" ) // 方块 (pigs for credit, apples for bet, mahjong tong tiles for numbers)
+ PORT_DIPNAME( 0x80, 0x80, "Show Credits" ) PORT_DIPLOCATION("SW2:8") // 数字有无 (hides credits/bets/wins, game plays normally)
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) // 无
+ PORT_DIPSETTING( 0x80, DEF_STR( On ) ) // 有
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( lhzb2 )
+ PORT_INCLUDE( lhzb2_common )
+
+ PORT_START("COINS")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("hopper", FUNC(hopper_device::line_r)) // 哈巴
+ PORT_SERVICE_NO_TOGGLE( 0x02, IP_ACTIVE_LOW ) // 测试 (hold on start for input test)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) // 査帐
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(5) PORT_CONDITION("DSW1", 0x20, EQUALS, 0x20) // 投币
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_KEYIN ) PORT_CONDITION("DSW1", 0x20, EQUALS, 0x00) // 投币
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT ) PORT_CONDITION("DSW1", 0x40, EQUALS, 0x40) // 退币
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT ) PORT_CONDITION("DSW1", 0x40, EQUALS, 0x00) // 退币
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_NAME("Show Credits") // 清除 (hold to show credits/bets/wins when hidden)
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( lhzb2a )
+ PORT_INCLUDE( lhzb2_common )
+
+ PORT_START("COINS")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("hopper", FUNC(hopper_device::line_r)) // 哈巴
+ PORT_SERVICE_NO_TOGGLE( 0x04, IP_ACTIVE_LOW ) // 测试 (hold on start for input test)
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) // 査帐
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(5) PORT_CONDITION("DSW1", 0x20, EQUALS, 0x20) // 投币
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_GAMBLE_KEYIN ) PORT_CONDITION("DSW1", 0x20, EQUALS, 0x00) // 投币
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT ) PORT_CONDITION("DSW1", 0x40, EQUALS, 0x40) // 退币
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT ) PORT_CONDITION("DSW1", 0x40, EQUALS, 0x00) // 退币
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_NAME("Show Credits") // 清除 (hold to show credits/bets/wins when hidden)
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( lhzb )
+ PORT_INCLUDE(lhzb2)
+
+ PORT_MODIFY("DSW2")
+ PORT_DIPNAME( 0x0c, 0x0c, "Minimum Bet" ) PORT_DIPLOCATION("SW2:3,4") // 最小押注
+ PORT_DIPSETTING( 0x0c, "1" )
+ PORT_DIPSETTING( 0x08, "2" )
+ PORT_DIPSETTING( 0x04, "3" )
+ PORT_DIPSETTING( 0x00, "5" )
+ PORT_DIPUNKNOWN_DIPLOC( 0x80, 0x80, "SW2:8" )
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( mgcs )
+ // DSWs are read through a protection device (IGS029). See code at $1cf16
+
+ PORT_START("DSW1") // $3009e2
+ CREDIT_SETTINGS_COMMON
+ PORT_DIPNAME( 0x10, 0x10, "Credit Limit" ) PORT_DIPLOCATION("SW1:5") // 進分上限
+ PORT_DIPSETTING( 0x10, "500" )
+ PORT_DIPSETTING( 0x00, "1000" )
+ PORT_DIPNAME( 0x80, 0x03, "Double Up Jackpot" ) PORT_DIPLOCATION("SW1:8") // 比倍爆機
+ PORT_DIPSETTING( 0x80, "1000" )
+ PORT_DIPSETTING( 0x00, "2000" )
+
+ PORT_START("DSW2") // $3009e3
+ PORT_DIPNAME( 0x03, 0x03, "Minimum Bet" ) PORT_DIPLOCATION("SW2:1,2") // 最小押注
+ PORT_DIPSETTING( 0x03, "1" )
+ PORT_DIPSETTING( 0x02, "2" )
+ PORT_DIPSETTING( 0x01, "3" )
+ PORT_DIPSETTING( 0x00, "5" )
+ PORT_DIPNAME( 0x04, 0x04, "Double Up Game" ) PORT_DIPLOCATION("SW2:3") // 續玩遊戲
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) // 無
+ PORT_DIPSETTING( 0x04, DEF_STR( On ) ) // 有
+ PORT_DIPNAME( 0x08, 0x08, "Double Up Game Name" ) PORT_DIPLOCATION("SW2:4") // 比倍續玩 (changes names for double up game and Double Up/Big/Small buttons)
+ PORT_DIPSETTING( 0x08, "Double Up" ) // 比倍 (比倍/大/小)
+ PORT_DIPSETTING( 0x00, "Continue Play" ) // 續玩 (续玩/左/右)
+ PORT_DIPNAME( 0x10, 0x10, DEF_STR( Controls ) ) PORT_DIPLOCATION("SW2:5") // 操作方式
+ PORT_DIPSETTING( 0x10, "Mahjong" ) // 按鍵
+ PORT_DIPSETTING( 0x00, DEF_STR( Joystick ) ) // 搖桿
+ PORT_DIPNAME( 0x20, 0x20, "Number Type" ) PORT_DIPLOCATION("SW2:6") // 數字形態
+ PORT_DIPSETTING( 0x20, "Numbers" ) // 數字
+ PORT_DIPSETTING( 0x00, "Blocks" ) // 方塊 (apples for bet, mahjong tong tiles for numbers)
+ PORT_DIPNAME( 0x40, 0x40, "Hide Credits" ) PORT_DIPLOCATION("SW2:7") // 隐分功能 (hides credits/bets/wins, game plays normally)
+ PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) // 無
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) ) // 有
+ PORT_DIPUNUSED_DIPLOC( 0x80, 0x80, "SW2:8" )
+
+ // Joystick mode: the top 2 bits of COINS (port A) and JOY (port B) are read and combined with the bottom 4 bits read from port C (see code at $1c83a)
+
+ PORT_START("JOY")
+ PORT_BIT( 0xcf, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x10, EQUALS, 0x10)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_CONDITION("DSW2", 0x10, EQUALS, 0x00) // 下
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_CONDITION("DSW2", 0x10, EQUALS, 0x00) // 左
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_CONDITION("DSW2", 0x10, EQUALS, 0x00) // 右
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CONDITION("DSW2", 0x10, EQUALS, 0x00) // 摸捨
+ // Port C input is 4 bits
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START1 ) PORT_CONDITION("DSW2", 0x10, EQUALS, 0x00) // 開始
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_CONDITION("DSW2", 0x10, EQUALS, 0x00) // 上
+
+ PORT_START("COINS")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("hopper", FUNC(hopper_device::line_r)) // 哈巴
+ PORT_SERVICE_NO_TOGGLE( 0x02, IP_ACTIVE_LOW ) // 測試 (hold on start for input test)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) // 查帳
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(5) PORT_CONDITION("DSW1", 0x20, EQUALS, 0x20) // 投幣
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_KEYIN ) PORT_CONDITION("DSW1", 0x20, EQUALS, 0x00) // 投幣
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT ) PORT_CONDITION("DSW1", 0x40, EQUALS, 0x40) // 退幣
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT ) PORT_CONDITION("DSW1", 0x40, EQUALS, 0x00) // 退幣
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_NAME("Show Credits") // 清除 (hold to show credits/bets/wins when hidden)
+ PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x10, EQUALS, 0x10)
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_CONDITION("DSW2", 0x10, EQUALS, 0x00) // 押注
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_CONDITION("DSW2", 0x10, EQUALS, 0x00) // 功能
+
+ IGS_MAHJONG_MATRIX_CONDITIONAL("DSW2", 0x10, 0x10)
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( sdmg2_common )
+ PORT_START("DSW1")
+ CREDIT_SETTINGS_COMMON
+ PORT_DIPNAME( 0x10, 0x10, "Credit Limit" ) PORT_DIPLOCATION("SW1:5") // 進分上限
+ PORT_DIPSETTING( 0x10, "2000" )
+ PORT_DIPSETTING( 0x00, "Unlimited" ) // 無限制 (seems to be limited to 19,999 trying to exceed this gives "RECORD ERROR 10")
+ PORT_DIPNAME( 0x80, 0x80, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW1:8") // 示範音樂
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) // 無
+ PORT_DIPSETTING( 0x80, DEF_STR( On ) ) // 有
+
+ PORT_START("DSW2")
+ PORT_DIPNAME( 0x03, 0x03, "Double Up Jackpot" ) PORT_DIPLOCATION("SW2:1,2") // 比倍爆機
+ PORT_DIPSETTING( 0x03, "500" )
+ PORT_DIPSETTING( 0x02, "1000" )
+ PORT_DIPSETTING( 0x01, "1500" )
+ PORT_DIPSETTING( 0x00, "2000" )
+ PORT_DIPNAME( 0x0c, 0x0c, "Minimum Bet" ) PORT_DIPLOCATION("SW2:3,4") // 最小押注
+ PORT_DIPSETTING( 0x0c, "1" )
+ PORT_DIPSETTING( 0x08, "2" )
+ PORT_DIPSETTING( 0x04, "3" )
+ PORT_DIPSETTING( 0x00, "5" )
+ PORT_DIPNAME( 0x10, 0x10, "Double Up Game" ) PORT_DIPLOCATION("SW2:5") // 續玩遊戲
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) // 無
+ PORT_DIPSETTING( 0x10, DEF_STR( On ) ) // 有
+ PORT_DIPNAME( 0x20, 0x20, "Double Up Game Name" ) PORT_DIPLOCATION("SW2:6") // 比倍續玩 (changes names for double up game and Double Up/Big/Small buttons)
+ PORT_DIPSETTING( 0x20, "Continue Play" ) // 續玩 (续玩/左/右)
+ PORT_DIPSETTING( 0x00, "Double Up" ) // 比倍 (比倍/大/小)
+ PORT_DIPNAME( 0x40, 0x40, DEF_STR( Controls ) ) PORT_DIPLOCATION("SW2:7") // 操作方式
+ PORT_DIPSETTING( 0x40, "Mahjong" ) // 按鍵
+ PORT_DIPSETTING( 0x00, DEF_STR( Joystick ) ) // 搖桿
+ PORT_DIPNAME( 0x80, 0x80, "Number Type" ) PORT_DIPLOCATION("SW2:8") // 數字形態
+ PORT_DIPSETTING( 0x80, "Numbers" ) // 數字
+ PORT_DIPSETTING( 0x00, "Blocks" ) // 方塊 (apples for bet, mahjong tong tiles for numbers)
+
+ IGS_MAHJONG_MATRIX_CONDITIONAL("DSW2", 0x40, 0x40)
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( sdmg2 )
+ PORT_INCLUDE(sdmg2_common)
+
+ PORT_START("COINS")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("hopper", FUNC(hopper_device::line_r)) // 哈巴
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x40) PORT_NAME("Show Credits") // 清除 (hold to show credits/bets/wins when hidden)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x00)
+ PORT_SERVICE_NO_TOGGLE( 0x04, IP_ACTIVE_LOW ) // 測試 (hold on start for input test)
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) // 查帳
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_CONDITION("DSW1", 0x20, EQUALS, 0x20) // 投幣
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_GAMBLE_KEYIN ) PORT_CONDITION("DSW1", 0x20, EQUALS, 0x00) // 投幣
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT ) PORT_CONDITION("DSW1", 0x40, EQUALS, 0x40) // 退幣
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT ) PORT_CONDITION("DSW1", 0x40, EQUALS, 0x00) // 退幣
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE3 ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x40) // shown in test mode ('O' appears, or it might be a 0)
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x00) // 功能
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+
+ PORT_START("MATRIX")
+ PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x40) PORT_CUSTOM_MEMBER(FUNC(igs017_state::keys_ipt_r<>))
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x00) // 開始
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x00) // 上
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x00) // 下
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x00) // 左
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x00) // 右
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x00) // 摸捨
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x00) // 押注
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x00) // related to joystick BUTTON3
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( sdmg2p )
+ PORT_INCLUDE(sdmg2_common)
+
+ PORT_MODIFY("DSW1")
+ PORT_DIPNAME( 0x80, 0x80, "Hide Credits" ) PORT_DIPLOCATION("SW1:8") // 隐分功能 (hides credits/bets/wins, game plays normally)
+ PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) // 無
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) ) // 有
+
+ PORT_MODIFY("DSW2")
+ PORT_DIPNAME( 0x01, 0x01, "Game Title" ) PORT_DIPLOCATION("SW2:1") // 機種名稱
+ PORT_DIPSETTING( 0x01, "Maque Wangchao" ) // 麻雀王朝 (Máquè wángcháo)
+ PORT_DIPSETTING( 0x00, "Chaoji Da Manguan 2 - Jiaqiang Ban" ) // 超二加強 (abbreviated to Chāo èr jiāqiáng)
+ PORT_DIPNAME( 0x02, 0x02, "Double Up Jackpot" ) PORT_DIPLOCATION("SW2:2") // 比倍爆機
+ PORT_DIPSETTING( 0x02, "500" )
+ PORT_DIPSETTING( 0x00, "1000" )
+
+ PORT_START("DSW3")
+ PORT_DIPUNKNOWN_DIPLOC( 0x01, IP_ACTIVE_LOW, "SW3:1" )
+ PORT_DIPUNKNOWN_DIPLOC( 0x02, IP_ACTIVE_LOW, "SW3:2" )
+ PORT_DIPUNKNOWN_DIPLOC( 0x04, IP_ACTIVE_LOW, "SW3:3" )
+ PORT_DIPUNKNOWN_DIPLOC( 0x08, IP_ACTIVE_LOW, "SW3:4" )
+ PORT_DIPUNKNOWN_DIPLOC( 0x10, IP_ACTIVE_LOW, "SW3:5" )
+ PORT_DIPUNKNOWN_DIPLOC( 0x20, IP_ACTIVE_LOW, "SW3:6" )
+ PORT_DIPUNKNOWN_DIPLOC( 0x40, IP_ACTIVE_LOW, "SW3:7" )
+ PORT_DIPUNKNOWN_DIPLOC( 0x80, IP_ACTIVE_LOW, "SW3:8" )
+
+ PORT_START("COINS")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x40)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x00) // 功能
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT ) PORT_CONDITION("DSW1", 0x40, EQUALS, 0x40) // 退幣
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT ) PORT_CONDITION("DSW1", 0x40, EQUALS, 0x00) // 退幣
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_CONDITION("DSW1", 0x20, EQUALS, 0x20) // 投幣
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_KEYIN ) PORT_CONDITION("DSW1", 0x20, EQUALS, 0x00) // 投幣
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) // 查帳
+ PORT_SERVICE_NO_TOGGLE( 0x20, IP_ACTIVE_LOW ) // 測試 (hold on start for input test)
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+
+ PORT_START("JOY")
+ PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x40)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x00)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x00)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START1 ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x00) // 開始
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x00) // 上
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x00) // 下
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x00) // 左
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x00) // 右
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x00) // 摸捨
+
+ PORT_START("BUTTONS")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x40)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x40) PORT_NAME("Show Credits") // 清除 (hold to show credits/bets/wins when hidden)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x00) // 押注
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x40, EQUALS, 0x00)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("hopper", FUNC(hopper_device::line_r)) // 哈巴
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( mgdh )
+ PORT_START("DSW1")
+ PORT_DIPUNKNOWN_DIPLOC( 0x01, IP_ACTIVE_LOW, "SW1:1" )
+ PORT_DIPNAME( 0x06, 0x06, "Key-In Rate" ) PORT_DIPLOCATION("SW1:2,3") // 開分比率
+ PORT_DIPSETTING( 0x06, "5" )
+ PORT_DIPSETTING( 0x04, "10" )
+ PORT_DIPSETTING( 0x02, "50" )
+ PORT_DIPSETTING( 0x00, "100" )
+ PORT_DIPNAME( 0x08, 0x08, "Credit Limit" ) PORT_DIPLOCATION("SW1:4") // 進分上限
+ PORT_DIPSETTING( 0x08, "100" )
+ PORT_DIPSETTING( 0x00, "500" )
+ PORT_DIPNAME( 0x10, 0x10, "Credit Mode" ) PORT_DIPLOCATION("SW1:5") // 進分方式
+ PORT_DIPSETTING( 0x10, "Coin Acceptor" ) // 投幣
+ PORT_DIPSETTING( 0x00, "Key-In" ) // 開分
+ PORT_DIPNAME( 0x20, 0x20, "Payout Mode" ) PORT_DIPLOCATION("SW1:6") // 退分方式
+ PORT_DIPSETTING( 0x20, "Return Coins" ) // 退幣
+ PORT_DIPSETTING( 0x00, "Key-Out" ) // 洗分
+ PORT_DIPNAME( 0xc0, 0xc0, "Minimum Bet" ) PORT_DIPLOCATION("SW1:7,8") // 最小押注
+ PORT_DIPSETTING( 0xc0, "1" )
+ PORT_DIPSETTING( 0x80, "2" )
+ PORT_DIPSETTING( 0x40, "3" )
+ PORT_DIPSETTING( 0x00, "5" )
+
+ PORT_START("DSW2") // bitswapped
+ PORT_DIPNAME( 0x01, 0x01, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW2:1") // 示範音樂
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) // 無
+ PORT_DIPSETTING( 0x01, DEF_STR( On ) ) // 有
+ PORT_DIPNAME( 0x02, 0x02, DEF_STR( Controls ) ) PORT_DIPLOCATION("SW2:2") // 操作方式
+ PORT_DIPSETTING( 0x02, "Mahjong" ) // 按鍵
+ PORT_DIPSETTING( 0x00, DEF_STR( Joystick ) ) // 搖桿
+ PORT_DIPNAME( 0x04, 0x04, "Double Up Game" ) PORT_DIPLOCATION("SW2:3") // 續玩遊戲
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) // 無
+ PORT_DIPSETTING( 0x04, DEF_STR( On ) ) // 有
+ PORT_DIPNAME( 0x18, 0x18, DEF_STR( Coinage ) ) PORT_DIPLOCATION("SW2:4,5") // 投幣比率
+ PORT_DIPSETTING( 0x00, DEF_STR( 2C_1C ) )
+ PORT_DIPSETTING( 0x18, DEF_STR( 1C_1C ) )
+ PORT_DIPSETTING( 0x10, DEF_STR( 1C_2C ) )
+ PORT_DIPSETTING( 0x08, DEF_STR( 1C_3C ) )
+ PORT_DIPNAME( 0xe0, 0xe0, "Coin Out Rate" ) PORT_DIPLOCATION("SW2:6,7,8") // 退幣比率
+ PORT_DIPSETTING( 0xe0, DEF_STR( 1C_1C ) )
+ PORT_DIPSETTING( 0xc0, DEF_STR( 2C_1C ) )
+ PORT_DIPSETTING( 0xa0, DEF_STR( 5C_1C ) )
+ PORT_DIPSETTING( 0x80, DEF_STR( 6C_1C ) )
+ PORT_DIPSETTING( 0x60, DEF_STR( 7C_1C ) )
+ PORT_DIPSETTING( 0x40, DEF_STR( 8C_1C ) )
+ PORT_DIPSETTING( 0x20, DEF_STR( 9C_1C ) )
+ PORT_DIPSETTING( 0x00, "10 Coins/1 Credit" )
+
+ PORT_START("COINS")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("hopper", FUNC(hopper_device::line_r)) // 哈巴
+ PORT_SERVICE_NO_TOGGLE( 0x02, IP_ACTIVE_LOW ) // 測試 (hold on start for input test)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) // 查帳
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(5) PORT_CONDITION("DSW1", 0x10, EQUALS, 0x10) // 投幣
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_KEYIN ) PORT_CONDITION("DSW1", 0x10, EQUALS, 0x00) // 投幣
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT ) PORT_CONDITION("DSW1", 0x20, EQUALS, 0x20) // 退幣
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT ) PORT_CONDITION("DSW1", 0x20, EQUALS, 0x00) // 退幣
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_NAME("Show Credits") // 清除 (hold to show credits/bets/wins when hidden)
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+
+ PORT_START("MATRIX")
+ PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CONDITION("DSW2", 0x02, EQUALS, 0x02) PORT_CUSTOM_MEMBER(NAME((&igs017_state::keys_ipt_r<ioport_value, 2>)))
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 ) PORT_CONDITION("DSW2", 0x02, EQUALS, 0x00) // 開始
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_CONDITION("DSW2", 0x02, EQUALS, 0x00) // 上
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_CONDITION("DSW2", 0x02, EQUALS, 0x00) // 下
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_CONDITION("DSW2", 0x02, EQUALS, 0x00) // 左
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_CONDITION("DSW2", 0x02, EQUALS, 0x00) // 右
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CONDITION("DSW2", 0x02, EQUALS, 0x00) // 摸捨
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x02, EQUALS, 0x00)
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x02, EQUALS, 0x00)
+
+ PORT_START("BUTTONS")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x02, EQUALS, 0x02)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_CONDITION("DSW2", 0x02, EQUALS, 0x00) // 功能
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x02, EQUALS, 0x02)
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_CONDITION("DSW2", 0x02, EQUALS, 0x00) // 押注
+
+ IGS_MAHJONG_MATRIX_CONDITIONAL("DSW2", 0x02, 0x02)
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( slqz2 )
+ PORT_START("DSW1")
+ CREDIT_SETTINGS_COMMON
+ PORT_DIPNAME( 0x10, 0x10, "Credit Limit" ) PORT_DIPLOCATION("SW1:5") // 进分上限
+ PORT_DIPSETTING( 0x10, "1000" )
+ PORT_DIPSETTING( 0x00, "2000" )
+ PORT_DIPNAME( 0x80, 0x80, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW1:8") // 示范音乐
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) // 无
+ PORT_DIPSETTING( 0x80, DEF_STR( On ) ) // 有
+
+ PORT_START("DSW2")
+ PORT_DIPNAME( 0x03, 0x03, "Double Up Jackpot" ) PORT_DIPLOCATION("SW2:1,2") // 比倍爆机
+ PORT_DIPSETTING( 0x03, "500" )
+ PORT_DIPSETTING( 0x02, "1000" )
+ PORT_DIPSETTING( 0x01, "1500" )
+ PORT_DIPSETTING( 0x00, "2000" )
+ PORT_DIPNAME( 0x0c, 0x0c, "Minimum Bet" ) PORT_DIPLOCATION("SW2:3,4") // 最小押注
+ PORT_DIPSETTING( 0x0c, "1 (1)" )
+ PORT_DIPSETTING( 0x08, "1 (2)" )
+ PORT_DIPSETTING( 0x04, "1 (3)" )
+ PORT_DIPSETTING( 0x00, "1 (4)" )
+ PORT_DIPNAME( 0x10, 0x10, "Double Up Game" ) PORT_DIPLOCATION("SW2:5") // 比倍游戏
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) // 无
+ PORT_DIPSETTING( 0x10, DEF_STR( On ) ) // 有
+ PORT_DIPNAME( 0x20, 0x20, "Double Up Game Name" ) PORT_DIPLOCATION("SW2:6") // 比倍续玩
+ PORT_DIPSETTING( 0x20, "Continue Play" ) // 续玩
+ PORT_DIPSETTING( 0x00, "Double Up" ) // 比倍
+ PORT_DIPNAME( 0x40, 0x40, "Number Type" ) PORT_DIPLOCATION("SW2:7") // 数字型态
+ PORT_DIPSETTING( 0x40, "Numbers" ) // 数字
+ PORT_DIPSETTING( 0x00, "Blocks" ) // 方块 (pigs for credit, apples for bet, mahjong tong tiles for numbers)
+ PORT_DIPNAME( 0x80, 0x80, "Show Credits" ) PORT_DIPLOCATION("SW2:8") // 数字有无 (hides credits/bets/wins, game plays normally)
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) // 无
+ PORT_DIPSETTING( 0x80, DEF_STR( On ) ) // 有
+
+ PORT_START("COINS")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("hopper", FUNC(hopper_device::line_r)) // 哈巴
+ PORT_SERVICE_NO_TOGGLE( 0x02, IP_ACTIVE_LOW ) // 测试 (hold on start for input test)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) // 査帐
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(5) PORT_CONDITION("DSW1", 0x20, EQUALS, 0x20) // 投币
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_KEYIN ) PORT_CONDITION("DSW1", 0x20, EQUALS, 0x00) // 投币
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT ) PORT_CONDITION("DSW1", 0x40, EQUALS, 0x40) // 退币
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT ) PORT_CONDITION("DSW1", 0x40, EQUALS, 0x00) // 退币
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_NAME("Show Credits") // 清除 (hold to show credits/bets/wins when hidden)
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 ) // 押注
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON3 ) // 功能
+
+ PORT_START("PLAYER1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 ) // 开始
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) // 上
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) // 下
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) // 左
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) // 右
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // 摸/舍
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+
+ PORT_START("PLAYER2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_NAME("Show Credits") // 清除 (hold to show credits/bets/wins when hidden)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( tjsb )
+ PORT_START("DSW1")
+ CREDIT_SETTINGS_COMMON
+ PORT_DIPNAME( 0x10, 0x10, "Credit Limit" ) PORT_DIPLOCATION("SW1:5") // 進分上限
+ PORT_DIPSETTING( 0x10, "1000" )
+ PORT_DIPSETTING( 0x00, "5000" )
+ PORT_DIPNAME( 0x80, 0x80, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW1:8") // 示範音樂
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) // 無
+ PORT_DIPSETTING( 0x80, DEF_STR( On ) ) // 有
+
+ PORT_START("DSW2")
+ PORT_DIPNAME( 0x03, 0x03, "Double Up Jackpot" ) PORT_DIPLOCATION("SW2:1,2") // 比倍爆機
+ PORT_DIPSETTING( 0x03, "1000" )
+ PORT_DIPSETTING( 0x02, "2000" )
+ PORT_DIPSETTING( 0x01, "3000" )
+ PORT_DIPSETTING( 0x00, "4000" )
+ PORT_DIPNAME( 0x0c, 0x0c, "Minimum Bet" ) PORT_DIPLOCATION("SW2:3,4") // 最小押注
+ PORT_DIPSETTING( 0x0c, "1" )
+ PORT_DIPSETTING( 0x08, "3" )
+ PORT_DIPSETTING( 0x04, "5" )
+ PORT_DIPSETTING( 0x00, "10" )
+ PORT_DIPNAME( 0x10, 0x10, "Double Up Game" ) PORT_DIPLOCATION("SW2:5") // 比倍遊戲
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) // 無
+ PORT_DIPSETTING( 0x10, DEF_STR( On ) ) // 有
+ PORT_DIPNAME( 0x20, 0x20, "Number Type" ) PORT_DIPLOCATION("SW2:6") // 數字型態 (always uses pigs for credit and coins for bet)
+ PORT_DIPSETTING( 0x20, "Numbers" ) // 數字
+ PORT_DIPSETTING( 0x00, "Blocks" ) // 方塊 (dots for numbers)
+ PORT_DIPUNKNOWN_DIPLOC(0x40, 0x40, "SW2:7")
+ PORT_DIPUNKNOWN_DIPLOC(0x80, 0x80, "SW2:8")
+
+ PORT_START("DSW3") // the protection check is skipped if (DSW3 ^ 0xff) & 0x9a == 0x0a
+ PORT_DIPNAME( 0xff, 0xf5, "Double Up Game Protection Check" ) PORT_DIPLOCATION("SW3:1,2,3,4,5,6,7,8")
+ PORT_DIPSETTING( 0xf5, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0xff, DEF_STR( On ) )
+
+ PORT_START("PLAYER1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 ) // 開始
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) // 上
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) // 下
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) // 左
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) // 右
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // 摸/舍
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 ) // 押注
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+
+ PORT_START("PLAYER2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+
+ PORT_START("COINS")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) // 查帳
+ PORT_SERVICE_NO_TOGGLE( 0x02, IP_ACTIVE_LOW ) // 測試 (hold on start for input test)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_CONDITION("DSW1", 0x20, EQUALS, 0x20) // 投幣
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_GAMBLE_KEYIN ) PORT_CONDITION("DSW1", 0x20, EQUALS, 0x00) // 投幣
+
+ PORT_START("BUTTONS")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 ) // 功能
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_NAME("Show Credits") // 清除 (hold to show credits/bets/wins when hidden - seems to be no setting to hide in DIP switches or bookkeeping menu)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT ) PORT_CONDITION("DSW1", 0x40, EQUALS, 0x40) // 退幣
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT ) PORT_CONDITION("DSW1", 0x40, EQUALS, 0x00) // 退幣
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("hopper", FUNC(hopper_device::line_r)) // 哈巴
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( spkrform )
+ PORT_START("DSW1")
+ PORT_DIPNAME( 0x01, 0x00, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW1:1")
+ PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPUNKNOWN_DIPLOC( 0x02, 0x02, "SW1:2" )
+ PORT_DIPNAME( 0x01c, 0x1c, "Credits Per Coin" ) PORT_DIPLOCATION("SW1:3,4,5")
+ PORT_DIPSETTING( 0x1c, "1" )
+ PORT_DIPSETTING( 0x18, "4" )
+ PORT_DIPSETTING( 0x14, "5" )
+ PORT_DIPSETTING( 0x10, "10" )
+ PORT_DIPSETTING( 0x0c, "20" )
+ PORT_DIPSETTING( 0x08, "40" )
+ PORT_DIPSETTING( 0x04, "50" )
+ PORT_DIPSETTING( 0x00, "100" )
+ PORT_DIPNAME( 0x20, 0x20, "Hopper" ) PORT_DIPLOCATION("SW1:6")
+ PORT_DIPSETTING( 0x20, DEF_STR( No ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( Yes ) )
+ PORT_DIPUNKNOWN_DIPLOC( 0x40, 0x40, "SW1:7" )
+ PORT_DIPUNKNOWN_DIPLOC( 0x80, 0x80, "SW1:8" )
+
+ PORT_START("DSW2")
+ PORT_DIPNAME( 0x03, 0x03, "Minimum Bet" ) PORT_DIPLOCATION("SW2:1,2")
+ PORT_DIPSETTING( 0x03, "1" )
+ PORT_DIPSETTING( 0x02, "5" )
+ PORT_DIPSETTING( 0x01, "10" )
+ PORT_DIPSETTING( 0x00, "20" )
+ PORT_DIPNAME( 0x1c, 0x1c, "Credits Per Note" ) PORT_DIPLOCATION("SW2:3,4,5")
+ PORT_DIPSETTING( 0x1c, "10" )
+ PORT_DIPSETTING( 0x18, "20" )
+ PORT_DIPSETTING( 0x14, "40" )
+ PORT_DIPSETTING( 0x10, "50" )
+ PORT_DIPSETTING( 0x0c, "100" )
+ PORT_DIPSETTING( 0x08, "200" )
+ PORT_DIPSETTING( 0x04, "250" )
+ PORT_DIPSETTING( 0x00, "500" )
+ PORT_DIPUNKNOWN_DIPLOC( 0x20, 0x20, "SW2:6" )
+ PORT_DIPUNKNOWN_DIPLOC( 0x40, 0x40, "SW2:7" )
+ PORT_DIPUNKNOWN_DIPLOC( 0x80, 0x80, "SW2:8" )
+
+ PORT_START("DSW3")
+ PORT_DIPNAME( 0x03, 0x03, "?" ) PORT_DIPLOCATION("SW3:1,2")
+ PORT_DIPSETTING( 0x03, "100" )
+ PORT_DIPSETTING( 0x02, "200" )
+ PORT_DIPSETTING( 0x01, "300" )
+ PORT_DIPSETTING( 0x00, "400" )
+ PORT_DIPNAME( 0x0c, 0x0c, "Win Up Pool" ) PORT_DIPLOCATION("SW3:3,4")
+ PORT_DIPSETTING( 0x0c, "300" )
+ PORT_DIPSETTING( 0x08, "500" )
+ PORT_DIPSETTING( 0x04, "800 (1)" )
+ PORT_DIPSETTING( 0x00, "800 (2)" )
+ PORT_DIPUNKNOWN_DIPLOC( 0x10, 0x10, "SW3:5" )
+ PORT_DIPUNKNOWN_DIPLOC( 0x20, 0x20, "SW3:6" )
+ PORT_DIPUNKNOWN_DIPLOC( 0x40, 0x40, "SW3:7" )
+ PORT_DIPUNKNOWN_DIPLOC( 0x80, 0x80, "SW3:8" )
+
+ PORT_START("PLAYER1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_NAME("Hide Gambling (Switch To Formosa)")
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START2 ) PORT_NAME("Start (Formosa)")
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) // up (Formosa)
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START ) PORT_NAME("Start / Draw / Take / %p Down (Formosa)")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+
+ PORT_START("PLAYER2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_POKER_HOLD4 ) PORT_NAME("Hold 4 / Half")
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_POKER_HOLD5 ) // hold 5
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_BET ) PORT_NAME("Bet / W-Up")
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) // right (Formosa)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_POKER_HOLD1 ) PORT_NAME("Hold 1 / High / Button (Formosa)")
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_POKER_HOLD2 ) PORT_NAME("Hold 2 / Double Up")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+
+ PORT_START("COINS")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) // left (Formosa)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_POKER_HOLD3 ) PORT_NAME("Hold 3 / Low")
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_GAMBLE_KEYIN ) // key in
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT ) // key out
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+
+ PORT_START("BUTTONS")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(5) // coin 1 (impulse prevents coin error in gambling mode)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_IMPULSE(5) // coin 2 ""
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("hopper", FUNC(hopper_device::line_r)) // hopper switch
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT ) // payout
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_SERVICE3 ) PORT_NAME("Return To Gambling (From Formosa). Then Bet, Hold 1..5") // To switch back to poker from Formosa, start the sequence pressing this key (memory $f4a3 holds the sequence number)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) // book
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( tarzan )
+ PORT_START("DSW1")
+ PORT_DIPNAME( 0x01, 0x00, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW1:1") // 示范音乐
+ PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) // 无
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) ) // 有
+ PORT_DIPNAME( 0x0e, 0x0e, DEF_STR(Coinage) ) PORT_DIPLOCATION("SW1:2,3,4") // 投币比率
+ PORT_DIPSETTING( 0x0e, DEF_STR(1C_1C) )
+ PORT_DIPSETTING( 0x0c, DEF_STR(1C_2C) )
+ PORT_DIPSETTING( 0x0a, DEF_STR(1C_4C) )
+ PORT_DIPSETTING( 0x08, DEF_STR(1C_5C) )
+ PORT_DIPSETTING( 0x06, "1 Coin/10 Credits" )
+ PORT_DIPSETTING( 0x04, "1 Coin/20 Credits" )
+ PORT_DIPSETTING( 0x02, "1 Coin/50 Credits" )
+ PORT_DIPSETTING( 0x00, "1 Coin/100 Credits" )
+ PORT_DIPNAME( 0x30, 0x30, "Key-In Rate" ) PORT_DIPLOCATION("SW1:5,6") // 开分比率
+ PORT_DIPSETTING( 0x30, "100" )
+ PORT_DIPSETTING( 0x20, "200" )
+ PORT_DIPSETTING( 0x10, "500" )
+ PORT_DIPSETTING( 0x00, "1000" )
+ PORT_DIPNAME( 0xc0, 0xc0, "Key-out Rate" ) PORT_DIPLOCATION("SW1:7,8") // 洗分比率
+ PORT_DIPSETTING( 0xc0, "1" )
+ PORT_DIPSETTING( 0x80, "10" )
+ PORT_DIPSETTING( 0x40, "100" )
+ PORT_DIPSETTING( 0x00, "100 (2)" )
+
+ PORT_START("DSW2")
+ PORT_DIPNAME( 0x01, 0x01, "Credit Mode" ) PORT_DIPLOCATION("SW2:1") // 进分方式 (sets coin input function)
+ PORT_DIPSETTING( 0x01, "Coin Acceptor" ) // 投币 (uses coin rate)
+ PORT_DIPSETTING( 0x00, "Key-In" ) // 开分 (uses key-in rate)
+ PORT_DIPNAME( 0x0e, 0x0e, "Minimum Bet" ) PORT_DIPLOCATION("SW2:2,3,4") // 最小押注
+ PORT_DIPSETTING( 0x0e, "5" )
+ PORT_DIPSETTING( 0x0c, "25" )
+ PORT_DIPSETTING( 0x0a, "50" )
+ PORT_DIPSETTING( 0x08, "75" )
+ PORT_DIPSETTING( 0x06, "100" )
+ PORT_DIPSETTING( 0x04, "125" )
+ PORT_DIPSETTING( 0x02, "125 (2)" )
+ PORT_DIPSETTING( 0x00, "125 (3)" )
+ PORT_DIPNAME( 0x30, 0x30, "Bonus Bet" ) PORT_DIPLOCATION("SW2:5,6") // 赠奖押注
+ PORT_DIPSETTING( 0x30, "75" )
+ PORT_DIPSETTING( 0x20, "125" )
+ PORT_DIPSETTING( 0x10, "200" )
+ PORT_DIPSETTING( 0x00, "250" )
+ PORT_DIPNAME( 0xc0, 0xc0, "Double Up Jackpot" ) PORT_DIPLOCATION("SW2:7,8") // 续玩爆机
+ PORT_DIPSETTING( 0xc0, "50,000" )
+ PORT_DIPSETTING( 0x80, "100,000" )
+ PORT_DIPSETTING( 0x40, "150,000" )
+ PORT_DIPSETTING( 0x00, "200,000" )
+
+ PORT_START("DSW3")
+ PORT_DIPNAME( 0x01, 0x01, DEF_STR( Controls ) ) PORT_DIPLOCATION("SW3:1") // 操作界面
+ PORT_DIPSETTING( 0x01, "Mahjong" ) // 麻雀键盘
+ PORT_DIPSETTING( 0x00, DEF_STR( Joystick ) ) // 摇杆
+ PORT_DIPNAME( 0x02, 0x02, "Background Color" ) PORT_DIPLOCATION("SW3:2") // 底色模式
+ PORT_DIPSETTING( 0x02, "Black and White" ) // 黑白
+ PORT_DIPSETTING( 0x00, "Color" ) // 彩色
+ PORT_DIPNAME( 0x04, 0x04, "Hide Credits" ) PORT_DIPLOCATION("SW3:3") // 隐分功能 (hides credits/bets/wins, game plays normally)
+ PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x08, 0x08, "Number Type" ) PORT_DIPLOCATION("SW3:4") // 数字型态
+ PORT_DIPSETTING( 0x08, "Numbers" ) // 数字
+ PORT_DIPSETTING( 0x00, "Circle Tiles" ) // 筒子 (mahjong tong tiles)
+ PORT_DIPNAME( 0x10, 0x10, "Double Up Game" ) PORT_DIPLOCATION("SW3:5") // 续玩有无
+ PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) // 无
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) ) // 有
+ PORT_DIPNAME( 0x20, 0x20, "Payout Mode" ) PORT_DIPLOCATION("SW3:6") // 退分方式
+ PORT_DIPSETTING( 0x20, "Return Coins" ) // 退币 (uses hopper to pay out credits)
+ PORT_DIPSETTING( 0x00, "Key-Out" ) // 洗分 (just clears credits)
+ PORT_DIPUNUSED_DIPLOC(0x40, 0x40, "SW3:7")
+ PORT_DIPUNUSED_DIPLOC(0x80, 0x80, "SW3:8")
+
+ PORT_START("COINS")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("hopper", FUNC(hopper_device::line_r)) // 哈巴
+ PORT_SERVICE_NO_TOGGLE( 0x02, IP_ACTIVE_LOW ) // 测试 (hold on start for input test)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) // 査帐
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(5) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) // 投币
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_KEYIN ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) // 投币
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT ) PORT_CONDITION("DSW3", 0x20, EQUALS, 0x20) // 洗分
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT ) PORT_CONDITION("DSW3", 0x20, EQUALS, 0x00) // 洗分
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_NAME("Show Credits") // 清除 (hold to show credits/bets/wins when hidden)
+ PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW3", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_GAMBLE_BET ) PORT_CONDITION("DSW3", 0x01, EQUALS, 0x00) PORT_NAME("Button B / Bet / Double Up") // B
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_GAMBLE_LOW ) PORT_CONDITION("DSW3", 0x01, EQUALS, 0x00) PORT_NAME("Button C / Small / Double Up (half)") // C
+
+ PORT_START("MATRIX")
+ PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CONDITION("DSW3", 0x01, EQUALS, 0x01) PORT_CUSTOM_MEMBER(NAME((&igs017_state::keys_ipt_r<ioport_value, 3>)))
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 ) PORT_CONDITION("DSW3", 0x01, EQUALS, 0x00) PORT_NAME("Start / Stop All / Take Score") // 开始
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_SLOT_STOP1 ) PORT_CONDITION("DSW3", 0x01, EQUALS, 0x00) PORT_NAME("Up / Stop 1") // 上
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SLOT_STOP2 ) PORT_CONDITION("DSW3", 0x01, EQUALS, 0x00) PORT_NAME("Down / Stop 2") // 下
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_SLOT_STOP3 ) PORT_CONDITION("DSW3", 0x01, EQUALS, 0x00) PORT_NAME("Left / Stop 3") // 左
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_SLOT_STOP4 ) PORT_CONDITION("DSW3", 0x01, EQUALS, 0x00) PORT_NAME("Right / Stop 4") // 右
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_GAMBLE_HIGH ) PORT_CONDITION("DSW3", 0x01, EQUALS, 0x00) PORT_NAME("Button A / Big / Double Up (double) / Show Odds") // A
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW3", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW3", 0x01, EQUALS, 0x00)
+
+ IGS_MAHJONG_MATRIX_CONDITIONAL("DSW3", 0x01, 0x01)
+
+ PORT_MODIFY("KEY4") // never read and not shown in test mode
+ PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( starzan )
+ PORT_START("DSW1")
+ PORT_DIPNAME( 0x01, 0x01, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW1:1")
+ PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x02, 0x02, "System Limit" ) PORT_DIPLOCATION("SW1:2")
+ PORT_DIPSETTING( 0x02, "Unlimited" )
+ PORT_DIPSETTING( 0x00, "Limited" )
+ PORT_DIPNAME( 0x04, 0x04, "W-Up Game" ) PORT_DIPLOCATION("SW1:3")
+ PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x08, 0x00, "Back Color" ) PORT_DIPLOCATION("SW1:4")
+ PORT_DIPSETTING( 0x08, "Black" )
+ PORT_DIPSETTING( 0x00, "Color" )
+ PORT_DIPNAME( 0x10, 0x10, "Stop Status" ) PORT_DIPLOCATION("SW1:5")
+ PORT_DIPSETTING( 0x10, "Non Stop" )
+ PORT_DIPSETTING( 0x00, "Auto Stop" )
+ PORT_DIPNAME( 0x20, 0x20, "Key" ) PORT_DIPLOCATION("SW1:6")
+ PORT_DIPSETTING( 0x20, "Mode 1" )
+ PORT_DIPSETTING( 0x00, "Mode 2" ) // To Do
+ PORT_DIPNAME( 0x40, 0x40, "Credit Level" ) PORT_DIPLOCATION("SW1:7")
+ PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x80, 0x80, "Odds Table" ) PORT_DIPLOCATION("SW1:8")
+ PORT_DIPSETTING( 0x80, "Show" )
+ PORT_DIPSETTING( 0x00, "No Show" )
+
+ PORT_START("DSW2")
+ PORT_DIPNAME( 0x01, 0x01, "Normal Level" ) PORT_DIPLOCATION("SW2:1")
+ PORT_DIPSETTING( 0x01, DEF_STR( Low ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( High ) )
+ PORT_DIPUNUSED_DIPLOC(0x02, 0x02, "SW2:2") // not used from here on according to test mode, PCB does have 3 8-dip banks
+ PORT_DIPUNUSED_DIPLOC(0x04, 0x04, "SW2:3")
+ PORT_DIPUNUSED_DIPLOC(0x08, 0x08, "SW2:4")
+ PORT_DIPUNUSED_DIPLOC(0x10, 0x10, "SW2:5")
+ PORT_DIPUNUSED_DIPLOC(0x20, 0x20, "SW2:6")
+ PORT_DIPUNUSED_DIPLOC(0x40, 0x40, "SW2:7")
+ PORT_DIPUNUSED_DIPLOC(0x80, 0x80, "SW2:8")
+
+ PORT_START("DSW3")
+ PORT_DIPUNUSED_DIPLOC(0x01, 0x01, "SW3:1")
+ PORT_DIPUNUSED_DIPLOC(0x02, 0x02, "SW3:2")
+ PORT_DIPUNUSED_DIPLOC(0x04, 0x04, "SW3:3")
+ PORT_DIPUNUSED_DIPLOC(0x08, 0x08, "SW3:4")
+ PORT_DIPUNUSED_DIPLOC(0x10, 0x10, "SW3:5")
+ PORT_DIPUNUSED_DIPLOC(0x20, 0x20, "SW3:6")
+ PORT_DIPUNUSED_DIPLOC(0x40, 0x40, "SW3:7")
+ PORT_DIPUNUSED_DIPLOC(0x80, 0x80, "SW3:8")
+
+ PORT_START("PLAYER1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("hopper", FUNC(hopper_device::line_r)) // hopper switch
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) // no effects in key test
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN ) // no effects in key test
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN ) // no effects in key test
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN ) // no effects in key test
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START1 ) PORT_NAME("Start / HW-Up")
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SLOT_STOP3 ) PORT_NAME("Stop Reel 3 / Low")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SLOT_STOP_ALL ) PORT_NAME("Stop All Reels / Bet / 2W-Up")
+
+ PORT_START("PLAYER2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SLOT_STOP2 ) PORT_NAME("Stop Reel 2 / High")
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_SLOT_STOP4 ) PORT_NAME("Stop Reel 4 / W-Up")
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SLOT_STOP1 ) PORT_NAME("Stop Reel 1 / Take")
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN ) // no effects in key test
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN ) // no effects in key test
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) // no effects in key test
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) // no effects in key test
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) // no effects in key test
+
+ PORT_START("COINS")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_GAMBLE_KEYIN )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_IMPULSE(5) // 'coin C'
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(5) // 'coin A'
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT )
+ PORT_SERVICE_NO_TOGGLE( 0x20, IP_ACTIVE_LOW ) // keep pressed while booting
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) // enters book-keeping menu
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) // no effects in key test
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( tarzan202fa )
+ PORT_INCLUDE(starzan)
+
+ PORT_MODIFY("DSW1")
+ PORT_DIPUNUSED_DIPLOC(0x40, 0x40, "SW1:7") // not used from here on according to test mode, PCB does have 3 8-dip banks
+ PORT_DIPUNUSED_DIPLOC(0x80, 0x80, "SW1:8")
+
+ PORT_MODIFY("DSW2")
+ PORT_DIPUNUSED_DIPLOC(0x01, 0x01, "SW2:1")
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( tarzan103m )
+ PORT_INCLUDE(tarzan202fa)
+
+ PORT_MODIFY("DSW1")
+ PORT_DIPUNUSED_DIPLOC(0x10, 0x10, "SW1:5") // not used from here on according to test mode, PCB does have 3 8-dip banks
+ PORT_DIPUNUSED_DIPLOC(0x20, 0x20, "SW1:6")
+
+ PORT_MODIFY("PLAYER1")
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_HIGH ) PORT_NAME("Button A / Big / Double Up (double) / Show Odds")
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_GAMBLE_LOW ) PORT_NAME("Button C / Small / Double Up (half)")
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SLOT_STOP3 ) PORT_NAME("Left / Stop 3")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_GAMBLE_BET ) PORT_NAME("Button B / Bet / Double Up")
+
+ PORT_MODIFY("PLAYER2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SLOT_STOP2 ) PORT_NAME("Down / Stop 2")
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_SLOT_STOP4 ) PORT_NAME("Right / Stop 4")
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SLOT_STOP1 ) PORT_NAME("Up / Stop 1")
+INPUT_PORTS_END
+
+// Test mode is in Italian (probably machine translated given how literal it is)
+static INPUT_PORTS_START( happyskl )
+ PORT_START("DSW1")
+ PORT_DIPNAME( 0x01, 0x01, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW1:1") // 'demo audio'
+ PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x02, 0x02, "System Limit" ) PORT_DIPLOCATION("SW1:2") // 'lim. sistema'
+ PORT_DIPSETTING( 0x02, "Unlimited" )
+ PORT_DIPSETTING( 0x00, "Limited" )
+ PORT_DIPNAME( 0x04, 0x04, "W-Up Game" ) PORT_DIPLOCATION("SW1:3") // 'gioco radd.'
+ PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x08, 0x08, "Game Speed" ) PORT_DIPLOCATION("SW1:4") // 'velocitá gioco'
+ PORT_DIPSETTING( 0x08, DEF_STR( Normal ) )
+ PORT_DIPSETTING( 0x00, "Quick" )
+ PORT_DIPNAME( 0x10, 0x10, "Replay Game" ) PORT_DIPLOCATION("SW1:5") // not translated for some reason
+ PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x20, 0x20, "Show Table" ) PORT_DIPLOCATION("SW1:6") // 'vedi tabella'
+ PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x40, 0x40, "Skill" ) PORT_DIPLOCATION("SW1:7") // 'abilitá'
+ PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x80, 0x80, "Payment Type" ) PORT_DIPLOCATION("SW1:8") // 'tipo pagam.'
+ PORT_DIPSETTING( 0x80, DEF_STR( Normal ) )
+ PORT_DIPSETTING( 0x00, "Automatic" )
+
+ PORT_START("DSW2")
+ PORT_DIPNAME( 0x01, 0x01, "Auto Payment" ) PORT_DIPLOCATION("SW2:1") // 'pagam. autom.'
+ PORT_DIPSETTING( 0x01, "1" )
+ PORT_DIPSETTING( 0x00, "10" )
+ PORT_DIPNAME( 0x06, 0x06, "Enable Payment" ) PORT_DIPLOCATION("SW2:2,3") // 'abilitá pagam.', they probably meant "abilita" instead of "abilitá"
+ PORT_DIPSETTING( 0x06, "Everything" ) // 'tutto'
+ PORT_DIPSETTING( 0x04, "1/Tickets" )
+ PORT_DIPSETTING( 0x02, "10/Tickets" )
+ PORT_DIPSETTING( 0x00, "1/Tickets" ) // same as 0x04, why?
+ PORT_DIPNAME( 0x08, 0x08, "Select Balls" ) PORT_DIPLOCATION("SW2:4") // 'sel. palloni'
+ PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x10, 0x10, "Select Cubes" ) PORT_DIPLOCATION("SW2:5") // 'sel. cubi'
+ PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x20, 0x20, "Select Cans" ) PORT_DIPLOCATION("SW2:6") // 'sel. lattine'
+ PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x40, 0x40, "Select Cards" ) PORT_DIPLOCATION("SW2:7") // 'sel. carte'
+ PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x80, 0x80, "Credit Limit" ) PORT_DIPLOCATION("SW2:8") // 'lim. crediti'
+ PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+
+ PORT_START("DSW3")
+ PORT_DIPNAME( 0x01, 0x01, "Level Limit" ) PORT_DIPLOCATION("SW3:1") // 'lim. livello'
+ PORT_DIPSETTING( 0x01, DEF_STR( Low ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( High ) )
+ PORT_DIPNAME( 0x02, 0x02, "Background" ) PORT_DIPLOCATION("SW3:2") // 'sfondo'
+ PORT_DIPSETTING( 0x02, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPUNUSED_DIPLOC(0x04, 0x04, "SW3:3") // not used from here on according to test mode
+ PORT_DIPUNUSED_DIPLOC(0x08, 0x08, "SW3:4")
+ PORT_DIPUNUSED_DIPLOC(0x10, 0x10, "SW3:5")
+ PORT_DIPUNUSED_DIPLOC(0x20, 0x20, "SW3:6")
+ PORT_DIPUNUSED_DIPLOC(0x40, 0x40, "SW3:7")
+ PORT_DIPUNUSED_DIPLOC(0x80, 0x80, "SW3:8")
+
+ PORT_START("PLAYER1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("hopper", FUNC(hopper_device::line_r)) // hopper switch
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) // no effects in key test
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN ) // no effects in key test
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN ) // no effects in key test
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN ) // no effects in key test
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START1 )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_POKER_HOLD1 )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_POKER_HOLD5 )
+
+ PORT_START("PLAYER2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_POKER_HOLD2 )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_POKER_HOLD3 )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_POKER_HOLD4 )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN ) // no effects in key test
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN ) // no effects in key test
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) // no effects in key test
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) // no effects in key test
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) // no effects in key test
+
+ PORT_START("COINS")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_GAMBLE_KEYIN )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_IMPULSE(5) // 'gettone C' (shows 'ricarica in corso')
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(5) // 'gettone A'
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT )
+ PORT_SERVICE_NO_TOGGLE( 0x20, IP_ACTIVE_LOW ) // keep pressed while booting
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) // enters book-keeping menu
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) // no effects in key test
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( cpoker2 )
+ PORT_INCLUDE(happyskl)
+
+ PORT_MODIFY("PLAYER1")
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_POKER_HOLD3 )
+
+ PORT_MODIFY("PLAYER2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_POKER_HOLD1 )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_POKER_HOLD2 )
+
+ // dips definitions taken from test mode, to be verified when the game will be playable
+ PORT_MODIFY("DSW1")
+ PORT_DIPNAME( 0x01, 0x01, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW1:1")
+ PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x02, 0x02, "System Limit" ) PORT_DIPLOCATION("SW1:2")
+ PORT_DIPSETTING( 0x02, "Unlimited" )
+ PORT_DIPSETTING( 0x00, "Limited" )
+ PORT_DIPNAME( 0x04, 0x04, "W-Up Game" ) PORT_DIPLOCATION("SW1:3")
+ PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x08, 0x08, "W-Up Type" ) PORT_DIPLOCATION("SW1:4")
+ PORT_DIPSETTING( 0x08, "Big-Small" )
+ PORT_DIPSETTING( 0x00, "Red-Black" )
+ PORT_DIPNAME( 0x10, 0x10, "Game Speed" ) PORT_DIPLOCATION("SW1:5")
+ PORT_DIPSETTING( 0x10, DEF_STR( Normal ) )
+ PORT_DIPSETTING( 0x00, "Quick" )
+ PORT_DIPNAME( 0x20, 0x20, "Card Type" ) PORT_DIPLOCATION("SW1:6")
+ PORT_DIPSETTING( 0x20, "Poker" )
+ PORT_DIPSETTING( 0x00, "Symbol" )
+ PORT_DIPNAME( 0x40, 0x40, "Sexy Girl" ) PORT_DIPLOCATION("SW1:7")
+ PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x80, 0x00, "Show Title" ) PORT_DIPLOCATION("SW1:8")
+ PORT_DIPSETTING( 0x00, DEF_STR( Yes ) )
+ PORT_DIPSETTING( 0x80, DEF_STR( No ) )
+
+ PORT_MODIFY("DSW2")
+ PORT_DIPNAME( 0x01, 0x01, "Show Hold" ) PORT_DIPLOCATION("SW2:1")
+ PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x02, 0x02, "Number Type" ) PORT_DIPLOCATION("SW2:2")
+ PORT_DIPSETTING( 0x02, "Number" )
+ PORT_DIPSETTING( 0x00, "A,J,Q,K" )
+ PORT_DIPUNUSED_DIPLOC(0x04, 0x04, "SW2:3") // not used from here on according to test mode, PCB does have 3 8-dip banks
+ PORT_DIPUNUSED_DIPLOC(0x08, 0x08, "SW2:4")
+ PORT_DIPUNUSED_DIPLOC(0x10, 0x10, "SW2:5")
+ PORT_DIPUNUSED_DIPLOC(0x20, 0x20, "SW2:6")
+ PORT_DIPUNUSED_DIPLOC(0x40, 0x40, "SW2:7")
+ PORT_DIPUNUSED_DIPLOC(0x80, 0x80, "SW2:8")
+
+ PORT_MODIFY("DSW3")
+ PORT_DIPUNUSED_DIPLOC(0x01, 0x01, "SW3:1")
+ PORT_DIPUNUSED_DIPLOC(0x02, 0x02, "SW3:2")
+INPUT_PORTS_END
+
+/***************************************************************************
+ Machine Drivers
+***************************************************************************/
+
+void igs017_state::base_machine_oki(machine_config &config, const XTAL &xtal_oki)
+{
+ // i/o
+ IGS_MUX(config, m_igs_mux, 0);
+
+ I8255A(config, m_ppi);
+
+ // video
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_refresh_hz(60);
+ m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(0));
+ m_screen->set_size(512, 256);
+ m_screen->set_visarea(0, 512-1, 0, 240-1);
+ m_screen->set_screen_update("igs017_igs031", FUNC(igs017_igs031_device::screen_update));
+ m_screen->set_palette("igs017_igs031:palette");
+
+ IGS017_IGS031(config, m_igs017_igs031, 0);
+
+ // sound
+ SPEAKER(config, "mono").front_center();
+ OKIM6295(config, m_oki, xtal_oki, okim6295_device::PIN7_HIGH).add_route(ALL_OUTPUTS, "mono", 0.5);
+}
+
+
+// iqblocka, iqblockf, genius6
+
+TIMER_DEVICE_CALLBACK_MEMBER(igs017_state::iqblocka_interrupt)
+{
+ int scanline = param;
+
+ if (scanline == 240 && m_igs017_igs031->get_irq_enable())
+ m_maincpu->set_input_line(0, HOLD_LINE);
+
+ if (scanline == 0 && m_igs017_igs031->get_nmi_enable())
+ m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
+}
+
+void igs017_state::iqblocka(machine_config &config)
+{
+ base_machine_oki(config, 16_MHz_XTAL / 16);
+
+ HD64180RP(config, m_maincpu, 16_MHz_XTAL);
+ m_maincpu->set_addrmap(AS_PROGRAM, &igs017_state::iqblocka_map);
+ m_maincpu->set_addrmap(AS_IO, &igs017_state::iqblocka_io);
+ TIMER(config, "scantimer").configure_scanline(FUNC(igs017_state::iqblocka_interrupt), "screen", 0, 1);
+
+ // NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+
+ // i/o
+ m_igs_mux->set_addrmap(0, &igs017_state::iqblocka_mux_map);
+
+ m_igs017_igs031->in_pa_callback().set_ioport("DSW1");
+ m_igs017_igs031->in_pb_callback().set_ioport("DSW2");
+ m_igs017_igs031->in_pc_callback().set_ioport("DSW3");
+
+ // protection
+ IGS_BITSWAP(config, m_igs_bitswap, 0);
+ m_igs_bitswap->set_val_xor(0x15d6);
+ m_igs_bitswap->set_mf_bits(3, 5, 9, 11);
+ m_igs_bitswap->set_m3_bits<0>(~5, 8, ~10, ~15);
+ m_igs_bitswap->set_m3_bits<1>( 3, ~8, ~12, ~15);
+ m_igs_bitswap->set_m3_bits<2>( 2, ~6, ~11, ~15);
+ m_igs_bitswap->set_m3_bits<3>( 0, ~1, ~3, ~15);
+
+ IGS_INCDEC(config, m_igs_incdec, 0);
+
+ // sound
+ YM2413(config, "ymsnd", 3.579545_MHz_XTAL).add_route(ALL_OUTPUTS, "mono", 0.5);
+}
+
+void igs017_state::iqblockf(machine_config &config)
+{
+ iqblocka(config);
+
+ m_igs_mux->set_addrmap(0, &igs017_state::iqblockf_mux_map);
+
+ // tweaked protection bitswap
+ m_igs_bitswap->set_mf_bits(0, 5, 9, 13);
+}
+
+void igs017_state::genius6(machine_config &config)
+{
+ iqblockf(config);
+
+ // tweaked protection bitswap
+ m_igs_bitswap->set_mf_bits(2, 7, 9, 13);
+ m_igs_bitswap->set_m3_bits<0>(~5, 6, ~7, ~15);
+ m_igs_bitswap->set_m3_bits<1>( 1, ~6, ~9, ~15);
+ m_igs_bitswap->set_m3_bits<2>( 4, ~8, ~12, ~15);
+ m_igs_bitswap->set_m3_bits<3>( 3, ~5, ~6, ~15);
+}
+
+
+// tarzan
+
+void igs017_state::tarzan(machine_config &config)
+{
+ base_machine_oki(config, 16_MHz_XTAL / 16);
+
+ HD64180RP(config, m_maincpu, 16_MHz_XTAL);
+ m_maincpu->set_addrmap(AS_PROGRAM, &igs017_state::iqblocka_map);
+ m_maincpu->set_addrmap(AS_IO, &igs017_state::tarzan_io);
+ m_maincpu->set_addrmap(AS_OPCODES, &igs017_state::decrypted_opcodes_map);
+ TIMER(config, "scantimer").configure_scanline(FUNC(igs017_state::iqblocka_interrupt), "screen", 0, 1);
+
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+
+ // I/O
+ m_igs_mux->set_addrmap(0, &igs017_state::tarzan_mux_map);
+
+ m_igs017_igs031->in_pa_callback().set_ioport("COINS");
+ m_igs017_igs031->in_pb_callback().set_ioport("MATRIX");
+
+ HOPPER(config, m_hopper, attotime::from_msec(50));
+
+ // protection
+ IGS_STRING(config, m_igs_string, 0);
+
+ IGS_INCDEC(config, m_igs_incdec, 0);
+
+ // video
+ m_igs017_igs031->set_palette_scramble_cb(FUNC(igs017_state::tarzan_palette_bitswap));
+
+ // sound
+ YM2413(config, "ymsnd", 3.579545_MHz_XTAL).add_route(ALL_OUTPUTS, "mono", 0.5);
+}
+
+
+// starzan
+
+void igs017_state::starzan(machine_config &config)
+{
+ base_machine_oki(config, 16_MHz_XTAL / 16);
+
+ HD64180RP(config, m_maincpu, 16_MHz_XTAL);
+ m_maincpu->set_addrmap(AS_PROGRAM, &igs017_state::iqblocka_map);
+ m_maincpu->set_addrmap(AS_IO, &igs017_state::starzan_io);
+ m_maincpu->set_addrmap(AS_OPCODES, &igs017_state::decrypted_opcodes_map);
+ TIMER(config, "scantimer").configure_scanline(FUNC(igs017_state::iqblocka_interrupt), "screen", 0, 1);
+
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+
+ // i/o
+ m_igs_mux->set_addrmap(0, &igs017_state::starzan_mux_map);
+
+ m_igs017_igs031->in_pa_callback().set_ioport("COINS");
+ m_igs017_igs031->in_pb_callback().set_ioport("PLAYER1");
+ m_igs017_igs031->in_pc_callback().set(FUNC(igs017_state::dsw_r));
+
+ HOPPER(config, m_hopper, attotime::from_msec(50));
+
+ // protection
+ IGS_STRING(config, m_igs_string, 0);
+
+ IGS_INCDEC(config, m_igs_incdec, 0);
+
+ // video
+ m_igs017_igs031->set_palette_scramble_cb(FUNC(igs017_state::tarzan_palette_bitswap));
+
+ // sound
+ YM2413(config, "ymsnd", 3.579545_MHz_XTAL).add_route(ALL_OUTPUTS, "mono", 0.5);
+}
+
+
+// happyskl
+
+void igs017_state::happyskl(machine_config &config)
+{
+ base_machine_oki(config, 16_MHz_XTAL / 16);
+
+ HD64180RP(config, m_maincpu, 16_MHz_XTAL);
+ m_maincpu->set_addrmap(AS_PROGRAM, &igs017_state::happyskl_map);
+ m_maincpu->set_addrmap(AS_IO, &igs017_state::happyskl_io);
+ m_maincpu->set_addrmap(AS_OPCODES, &igs017_state::decrypted_opcodes_map);
+ TIMER(config, "scantimer").configure_scanline(FUNC(igs017_state::iqblocka_interrupt), "screen", 0, 1);
+
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+
+ // i/o
+ m_igs_mux->set_addrmap(0, &igs017_state::happyskl_mux_map);
+
+ m_igs017_igs031->in_pa_callback().set_ioport("COINS");
+ m_igs017_igs031->in_pb_callback().set_ioport("PLAYER1");
+ m_igs017_igs031->in_pc_callback().set(FUNC(igs017_state::dsw_r));
+
+ HOPPER(config, m_hopper, attotime::from_msec(50));
+
+ // video
+ m_igs017_igs031->set_palette_scramble_cb(FUNC(igs017_state::tarzan_palette_bitswap));
+}
+
+
+// cpoker2
+
+void igs017_state::cpoker2(machine_config &config)
+{
+ base_machine_oki(config, 16_MHz_XTAL / 16);
+
+ HD64180RP(config, m_maincpu, 16_MHz_XTAL);
+ m_maincpu->set_addrmap(AS_PROGRAM, &igs017_state::cpoker2_map);
+ m_maincpu->set_addrmap(AS_IO, &igs017_state::cpoker2_io);
+ TIMER(config, "scantimer").configure_scanline(FUNC(igs017_state::iqblocka_interrupt), "screen", 0, 1);
+
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+
+ // i/o
+ m_igs_mux->set_addrmap(0, &igs017_state::cpoker2_mux_map);
+
+ m_igs017_igs031->in_pa_callback().set_ioport("COINS");
+ m_igs017_igs031->in_pb_callback().set_ioport("PLAYER1");
+ m_igs017_igs031->in_pc_callback().set(FUNC(igs017_state::dsw_r));
+
+ HOPPER(config, m_hopper, attotime::from_msec(50));
+
+ // protection
+ IGS_INCDEC(config, m_igs_incdec, 0);
+
+ IGS_INC(config, m_igs_inc, 0);
+
+ // video
+ m_igs017_igs031->set_palette_scramble_cb(FUNC(igs017_state::tarzan_palette_bitswap));
+}
+
+
+// tjsb
+
+void igs017_state::tjsb(machine_config &config)
+{
+ base_machine_oki(config, 16_MHz_XTAL / 16);
+
+ HD64180RP(config, m_maincpu, 16_MHz_XTAL);
+ m_maincpu->set_addrmap(AS_PROGRAM, &igs017_state::tjsb_map);
+ m_maincpu->set_addrmap(AS_IO, &igs017_state::tjsb_io);
+ TIMER(config, "scantimer").configure_scanline(FUNC(igs017_state::iqblocka_interrupt), "screen", 0, 1);
+
+ // i/o
+ m_igs_mux->set_addrmap(0, &igs017_state::tjsb_mux_map);
+
+ m_igs017_igs031->in_pa_callback().set_ioport("DSW1");
+ m_igs017_igs031->in_pb_callback().set_ioport("DSW2");
+ m_igs017_igs031->in_pc_callback().set_ioport("DSW3");
+
+ HOPPER(config, m_hopper, attotime::from_msec(50));
+
+ // protection
+ IGS_STRING(config, m_igs_string, 0);
+
+ // video
+ m_igs017_igs031->set_palette_scramble_cb(FUNC(igs017_state::tjsb_palette_bitswap));
+
+ // sound
+ YM2413(config, "ymsnd", 3.579545_MHz_XTAL).add_route(ALL_OUTPUTS, "mono", 0.5);
+}
+
+
+// spkrform
+
+void igs017_state::spkrform(machine_config &config)
+{
+ base_machine_oki(config, 16_MHz_XTAL / 16);
+
+ HD64180RP(config, m_maincpu, 16_MHz_XTAL);
+ m_maincpu->set_addrmap(AS_PROGRAM, &igs017_state::iqblocka_map);
+ m_maincpu->set_addrmap(AS_IO, &igs017_state::spkrform_io);
+ TIMER(config, "scantimer").configure_scanline(FUNC(igs017_state::iqblocka_interrupt), "screen", 0, 1);
+
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+
+ // i/o
+ m_igs_mux->set_addrmap(0, &igs017_state::spkrform_mux_map);
+
+ m_igs017_igs031->in_pa_callback().set_ioport("DSW1");
+ m_igs017_igs031->in_pb_callback().set_ioport("DSW2");
+ m_igs017_igs031->in_pc_callback().set_ioport("DSW3");
+
+ HOPPER(config, m_hopper, attotime::from_msec(50));
+
+ // protection
+ IGS_STRING(config, m_igs_string, 0);
+
+ IGS_INCDEC(config, m_igs_incdec, 0);
+
+ // sound
+ YM2413(config, "ymsnd", 3.579545_MHz_XTAL).add_route(ALL_OUTPUTS, "mono", 0.5);
+}
+
+
+// mgcs
+
+TIMER_DEVICE_CALLBACK_MEMBER(igs017_state::mgcs_interrupt)
+{
+ int scanline = param;
+
+ if (scanline == 240 && m_igs017_igs031->get_irq_enable())
+ m_maincpu->set_input_line(1, HOLD_LINE);
+
+ if (scanline == 0 && m_igs017_igs031->get_nmi_enable())
+ m_maincpu->set_input_line(2, HOLD_LINE);
+}
+
+void igs017_state::mgcs(machine_config &config)
+{
+ base_machine_oki(config, 8_MHz_XTAL / 8);
+
+ M68000(config, m_maincpu, 22_MHz_XTAL / 2);
+ m_maincpu->set_addrmap(AS_PROGRAM, &igs017_state::mgcs_map);
+ TIMER(config, "scantimer").configure_scanline(FUNC(igs017_state::mgcs_interrupt), "screen", 0, 1);
+
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+
+ // i/o
+ m_igs_mux->set_addrmap(0, &igs017_state::mgcs_mux_map);
+
+ m_igs017_igs031->in_pa_callback().set_ioport("COINS");
+ m_igs017_igs031->in_pb_callback().set(FUNC(igs017_state::mgcs_keys_joy_r));
+ m_igs017_igs031->in_pc_callback().set_ioport("JOY");
+
+ HOPPER(config, m_hopper, attotime::from_msec(50));
+
+ // protection
+ IGS_STRING(config, m_igs_string, 0);
+
+ // video
+ m_igs017_igs031->set_palette_scramble_cb(FUNC(igs017_state::mgcs_palette_bitswap));
+}
+
+void igs017_state::mgcsa(machine_config &config)
+{
+ mgcs(config);
+
+ m_maincpu->set_addrmap(AS_PROGRAM, &igs017_state::mgcsa_map);
+}
+
+void igs017_state::mgcsb(machine_config &config)
+{
+ mgcs(config);
+
+ m_maincpu->set_addrmap(AS_PROGRAM, &igs017_state::mgcsb_map);
+
+ m_igs_mux->set_addrmap(0, &igs017_state::mgcsb_mux_map);
+}
+
+
+// lhzb2
+
+void igs017_state::lhzb2(machine_config &config)
+{
+ base_machine_oki(config, 8_MHz_XTAL / 8);
+
+ M68000(config, m_maincpu, 22_MHz_XTAL / 2);
+ m_maincpu->set_addrmap(AS_PROGRAM, &igs017_state::lhzb2_map);
+ TIMER(config, "scantimer").configure_scanline(FUNC(igs017_state::mgcs_interrupt), "screen", 0, 1);
+
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+
+ // i/o
+ m_igs_mux->set_addrmap(0, &igs017_state::lhzb2_mux_map);
+
+ m_igs017_igs031->in_pa_callback().set_ioport("COINS");
+ m_igs017_igs031->in_pb_callback().set_ioport("DSW1");
+ m_igs017_igs031->in_pc_callback().set_ioport("DSW2");
+
+ HOPPER(config, m_hopper, attotime::from_msec(50));
+
+ // protection
+ IGS_STRING(config, m_igs_string, 0);
+
+ IGS022(config, m_igs022, 0);
+
+ // video
+ m_igs017_igs031->set_palette_scramble_cb(FUNC(igs017_state::lhzb2a_palette_bitswap));
+}
+
+
+// lhzb2a
+
+MACHINE_RESET_MEMBER(igs017_state, lhzb2a)
+{
+ machine_reset();
+ lhzb2a_remap_addr_w(m_maincpu->space(AS_PROGRAM), 0xf0);
+}
+
+void igs017_state::lhzb2a(machine_config &config)
+{
+ base_machine_oki(config, 8_MHz_XTAL / 8);
+
+ M68000(config, m_maincpu, 22_MHz_XTAL / 2);
+ m_maincpu->set_addrmap(AS_PROGRAM, &igs017_state::lhzb2a_map);
+ TIMER(config, "scantimer").configure_scanline(FUNC(igs017_state::mgcs_interrupt), "screen", 0, 1);
+
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+
+ MCFG_MACHINE_RESET_OVERRIDE(igs017_state, lhzb2a)
+
+ // i/o
+ m_igs_mux->set_addrmap(0, &igs017_state::lhzb2a_mux_map);
+
+ // ppi8255 not used for i/o (just video enable)?
+
+ HOPPER(config, m_hopper, attotime::from_msec(50));
+
+ // protection
+ IGS_STRING(config, m_igs_string, 0);
+
+ IGS_BITSWAP(config, m_igs_bitswap, 0);
+ m_igs_bitswap->set_val_xor(0x289a);
+ m_igs_bitswap->set_mf_bits(4, 7, 10, 13);
+ m_igs_bitswap->set_m3_bits<0>(~3, 8, ~12, ~15);
+ m_igs_bitswap->set_m3_bits<1>(~3, ~6, ~9, ~15);
+ m_igs_bitswap->set_m3_bits<2>(~3, 4, ~5, ~15);
+ m_igs_bitswap->set_m3_bits<3>(~9, ~11, 12, ~15);
+
+ IGS_INCDEC(config, m_igs_incdec, 0);
+
+ // video
+ m_igs017_igs031->set_palette_scramble_cb(FUNC(igs017_state::lhzb2a_palette_bitswap));
+}
+
+
+// slqz2
+
+void igs017_state::slqz2(machine_config &config)
+{
+ base_machine_oki(config, 8_MHz_XTAL / 8);
+
+ M68000(config, m_maincpu, 22_MHz_XTAL / 2);
+ m_maincpu->set_addrmap(AS_PROGRAM, &igs017_state::slqz2_map);
+ TIMER(config, "scantimer").configure_scanline(FUNC(igs017_state::mgcs_interrupt), "screen", 0, 1);
+
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+
+ // i/o
+ m_igs_mux->set_addrmap(0, &igs017_state::slqz2_mux_map);
+
+ m_igs017_igs031->in_pa_callback().set_ioport("COINS");
+ m_igs017_igs031->in_pb_callback().set_ioport("DSW1");
+ m_igs017_igs031->in_pc_callback().set_ioport("DSW2");
+
+ HOPPER(config, m_hopper, attotime::from_msec(50));
+
+ // protection
+ IGS_STRING(config, m_igs_string, 0);
+
+ IGS022(config, m_igs022, 0);
+
+ // video
+ m_igs017_igs031->set_palette_scramble_cb(FUNC(igs017_state::slqz2_palette_bitswap));
+}
+
+
+// sdmg2
+
+void igs017_state::sdmg2(machine_config &config)
+{
+ base_machine_oki(config, 22_MHz_XTAL / 22);
+
+ M68000(config, m_maincpu, 22_MHz_XTAL / 2);
+ m_maincpu->set_addrmap(AS_PROGRAM, &igs017_state::sdmg2_map);
+ TIMER(config, "scantimer").configure_scanline(FUNC(igs017_state::mgcs_interrupt), "screen", 0, 1);
+
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+
+ // i/o
+ m_igs_mux->set_addrmap(0, &igs017_state::sdmg2_mux_map);
+
+ m_igs017_igs031->in_pa_callback().set_ioport("DSW1");
+ m_igs017_igs031->in_pb_callback().set_ioport("DSW2");
+ // DSW3 is read but unused (it's not populated on the PCB)
+
+ HOPPER(config, m_hopper, attotime::from_msec(50));
+
+ // protection
+ IGS_INCDEC(config, m_igs_incdec, 0);
+}
+
+
+// mgdh, mgdha
+
+TIMER_DEVICE_CALLBACK_MEMBER(igs017_state::mgdh_interrupt)
+{
+ int scanline = param;
+
+ if (scanline == 240 && m_igs017_igs031->get_irq_enable())
+ m_maincpu->set_input_line(1, HOLD_LINE);
+
+ if (scanline == 0 && m_igs017_igs031->get_nmi_enable())
+ m_maincpu->set_input_line(3, HOLD_LINE); // lev 3 instead of 2
+}
+
+void igs017_state::mgdha(machine_config &config)
+{
+ base_machine_oki(config, 22_MHz_XTAL / 22);
+
+ M68000(config, m_maincpu, 22_MHz_XTAL / 2);
+ m_maincpu->set_addrmap(AS_PROGRAM, &igs017_state::mgdh_map);
+ TIMER(config, "scantimer").configure_scanline(FUNC(igs017_state::mgdh_interrupt), "screen", 0, 1);
+
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+
+ // i/o
+ m_igs_mux->set_addrmap(0, &igs017_state::mgdha_mux_map);
+
+ m_igs017_igs031->in_pa_callback().set_ioport("DSW1");
+
+ HOPPER(config, m_hopper, attotime::from_msec(50));
+}
+
+void igs017_state::mgdh(machine_config &config)
+{
+ mgdha(config);
+
+ m_igs_mux->set_addrmap(0, &igs017_state::mgdh_mux_map);
+
+ // protection (only used for the game id check?)
+// IGS_STRING(config, m_igs_string, 0);
+}
+
+void igs017_state::sdmg2p(machine_config &config)
+{
+ base_machine_oki(config, 22_MHz_XTAL / 22);
+
+ M68000(config, m_maincpu, 22_MHz_XTAL / 2);
+ m_maincpu->set_addrmap(AS_PROGRAM, &igs017_state::sdmg2p_map);
+ TIMER(config, "scantimer").configure_scanline(FUNC(igs017_state::mgcs_interrupt), "screen", 0, 1);
+
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+
+ // i/o
+ m_igs_mux->set_addrmap(0, &igs017_state::sdmg2p_mux_map);
+
+ m_igs017_igs031->in_pa_callback().set_ioport("DSW1");
+ m_igs017_igs031->in_pb_callback().set_ioport("DSW2");
+ m_igs017_igs031->in_pc_callback().set_ioport("DSW3"); // there are 3 DIP banks on PCB but only two are shown in test mode
+
+ HOPPER(config, m_hopper, attotime::from_msec(50));
+
+ IGS_STRING(config, m_igs_string, 0);
+}
+
+void igs017_state::jking302us(machine_config &config)
+{
+ base_machine_oki(config, 22_MHz_XTAL / 22);
+
+ M68000(config, m_maincpu, 22_MHz_XTAL / 2);
+ m_maincpu->set_addrmap(AS_PROGRAM, &igs017_state::jking302us_map);
+ TIMER(config, "scantimer").configure_scanline(FUNC(igs017_state::mgdh_interrupt), "screen", 0, 1);
+
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+
+ // i/o
+ m_igs_mux->set_addrmap(0, &igs017_state::jking302us_mux_map);
+
+ HOPPER(config, m_hopper, attotime::from_msec(50));
+
+ IGS_STRING(config, m_igs_string, 0);
+}
+
+
+/***************************************************************************
+ ROMs Loading
+***************************************************************************/
+
+// These are newer versions of IQ-Block (see iqblock.cpp) with added gambling
+
+/***************************************************************************
+
+Shuzi Leyuan (V127M)
+數字樂園 (Shùzì Lèyuán)
+IGS, 1996
+
+PCB Layout
+----------
+
+IGS PCB NO-0131-4
+|---------------------------------------|
+|uPD1242H VOL U3567 3.579545MHz|
+| AR17961 |
+| HD64180RP8 |
+| 16MHz BATTERY|
+| |
+| SPEECH.U17 |
+| |
+|J 6264 |
+|A |
+|M 8255 V.U18 |
+|M |
+|A |
+| |
+| |
+| |-------| |
+| | | |
+| CG.U7 |IGS017 | |
+| | | |
+| TEXT.U8 |-------| PAL |
+| 22MHz 61256 |
+| DSW1 DSW2 DSW3 |
+|---------------------------------------|
+Notes:
+ HD64180RP8 - Hitachi HD64180 CPU. Clocks 16MHz (pins 2 & 3), 8MHz (pin 64)
+ 61256 - 32k x8 SRAM (DIP28)
+ 6264 - 8k x8 SRAM (DIP28)
+ IGS017 - Custom IGS IC (QFP208)
+ AR17961 - == Oki M6295 (QFP44). Clock 1.000MHz [16/16]. pin 7 = high
+ U3567 - == YM2413. Clock 3.579545MHz
+ VSync - 60Hz
+ HSync - 15.31kHz
+
+***************************************************************************/
+
+ROM_START( iqblocka )
+ ROM_REGION( 0x40000, "maincpu", 0 )
+ ROM_LOAD( "v.u18", 0x00000, 0x40000, CRC(2e2b7d43) SHA1(cc73f4c8f9a6e2219ee04c9910725558a80b4eb2) )
+
+ ROM_REGION( 0x100000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "cg.u7", 0x000000, 0x080000, CRC(cb48a66e) SHA1(6d597193d1333a97957d5ceec8179a24bedfd928) ) // FIXED BITS (xxxxxxxx0xxxxxxx)
+ ROM_FILL( 0x080000, 0x080000, 0xff ) // unpopulated
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0)
+ ROM_LOAD( "text.u8", 0x000000, 0x080000, CRC(48c4f4e6) SHA1(b1e1ca62cf6a99c11a5cc56705eef7e22a3b2740) )
+
+ ROM_REGION( 0x40000, "oki", 0 )
+ ROM_LOAD( "speech.u17", 0x00000, 0x40000, CRC(d9e3d39f) SHA1(bec85d1ac2dfca77453cbca0e7dd53fee8fb438b) )
+
+ ROM_REGION( 0x2dd, "pld", ROMREGION_ERASE )
+ ROM_LOAD( "cq.u24", 0x000, 0x2dd, NO_DUMP ) // PAL22CV10
+
+ ROM_REGION( 0x15, "igs_fixed_data", 0 )
+ ROM_LOAD( "igs_fixed_data.key", 0x00, 0x15, CRC(9159ecbf) SHA1(b6bdb1f327944dfc7f6f71565a24e89517607490) )
+ROM_END
+
+// English title (IQ Block) and year 1997:
+
+ROM_START( iqblockf )
+ ROM_REGION( 0x40000, "maincpu", 0 )
+ ROM_LOAD( "v113fr.u18", 0x00000, 0x40000, CRC(346c68af) SHA1(ceae4c0143c288dc9c1dd1e8a51f1e3371ffa439) )
+
+ ROM_REGION( 0x100000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "cg.u7", 0x000000, 0x080000, CRC(cb48a66e) SHA1(6d597193d1333a97957d5ceec8179a24bedfd928) ) // FIXED BITS (xxxxxxxx0xxxxxxx)
+ ROM_FILL( 0x080000, 0x080000, 0xff ) // unpopulated
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "text.u8", 0x000000, 0x080000, CRC(48c4f4e6) SHA1(b1e1ca62cf6a99c11a5cc56705eef7e22a3b2740) )
+
+ ROM_REGION( 0x40000, "oki", 0 )
+ ROM_LOAD( "sp.u17", 0x00000, 0x40000, CRC(71357845) SHA1(25f4f7aebdcc0706018f041d3696322df569b0a3) )
+
+ ROM_REGION( 0x2dd, "pld", ROMREGION_ERASE )
+ ROM_LOAD( "cq.u24", 0x000, 0x2dd, NO_DUMP ) // PAL22CV10
+
+ ROM_REGION( 0x15, "igs_fixed_data", 0 )
+ ROM_LOAD( "igs_fixed_data.key", 0x00, 0x15, CRC(9159ecbf) SHA1(b6bdb1f327944dfc7f6f71565a24e89517607490) )
+ROM_END
+
+// IQ Block V110F also exists (undumped) with IGS003e (not 8255)
+
+/***************************************************************************
+
+Genius 6 (V110F)
+IGS, 1998
+
+IGS PCB NO-0131-4
+|---------------------------------------|
+|uPD1242H VOL U3567 3.579545MHz|
+| K668 |
+| Z8018008PSC |
+| 16MHz BATTERY|
+| |
+| SPEECH.U17 |
+| |
+|J 6264 |
+|A |
+|M IGS003c V-110F.U18 |
+|M |
+|A |
+| |
+| |
+| |-------| |
+| | | |
+| CG.U7 |IGS017 | |
+| | | |
+| TEXT.U8 |-------| PAL |
+| 22MHz 61256 |
+| DSW1 DSW2 DSW3 |
+|---------------------------------------|
+
+***************************************************************************/
+
+ROM_START( genius6 )
+ ROM_REGION( 0x40000, "maincpu", 0 )
+ ROM_LOAD( "genius6_v110f.u18", 0x00000, 0x40000, CRC(2630ad44) SHA1(37002fa913ad60c59145f5a7692eef8862b9d6eb) )
+
+ ROM_REGION( 0x80000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "genius6_cg.u7", 0x000000, 0x080000, CRC(1842d021) SHA1(78bfb5108741d39bd19b603cc97623fba7b2a31e) ) // FIXED BITS (xxxxxxxx0xxxxxxx)
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "text.u8", 0x000000, 0x080000, CRC(48c4f4e6) SHA1(b1e1ca62cf6a99c11a5cc56705eef7e22a3b2740) ) // same as iqblocka
+
+ ROM_REGION( 0x40000, "oki", 0 )
+ ROM_LOAD( "speech.u17", 0x00000, 0x40000, CRC(d9e3d39f) SHA1(bec85d1ac2dfca77453cbca0e7dd53fee8fb438b) ) // same as iqblocka
+
+ ROM_REGION( 0x2dd, "pld", ROMREGION_ERASE )
+ ROM_LOAD( "cq.u24", 0x000, 0x2dd, NO_DUMP ) // PAL22CV10
+
+ ROM_REGION( 0x15, "igs_fixed_data", 0 )
+ ROM_LOAD( "igs_fixed_data.key", 0x00, 0x15, CRC(9159ecbf) SHA1(b6bdb1f327944dfc7f6f71565a24e89517607490) )
+ROM_END
+
+// strangely identifies as V133F and has 1997 copyright, while the parent is V110F but with 1998 copyright
+ROM_START( genius6a )
+ ROM_REGION( 0x40000, "maincpu", 0 )
+ ROM_LOAD( "genius6_v133.u18", 0x00000, 0x40000, CRC(b34ce8c6) SHA1(845e6c4f5b1f06229a4046cf085ce08802458bd8) )
+
+ ROM_REGION( 0x80000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "genius6_cg.u7", 0x000000, 0x080000, CRC(1842d021) SHA1(78bfb5108741d39bd19b603cc97623fba7b2a31e) ) // FIXED BITS (xxxxxxxx0xxxxxxx)
+
+ ROM_REGION( 0x40000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "text.u8", 0x000000, 0x040000, CRC(7716b601) SHA1(363cddd930fdec4821ebfaced64276f8fa943eae) ) // half sized if compared to the parent and identical to its 1st half, confirmed correct (27c2048)
+
+ ROM_REGION( 0x40000, "oki", 0 )
+ ROM_LOAD( "speech.u17", 0x00000, 0x40000, CRC(d9e3d39f) SHA1(bec85d1ac2dfca77453cbca0e7dd53fee8fb438b) ) // same as iqblocka
+
+ ROM_REGION( 0x2dd, "pld", ROMREGION_ERASE )
+ ROM_LOAD( "cq.u24", 0x000, 0x2dd, NO_DUMP ) // PAL22CV10
+
+ ROM_REGION( 0x15, "igs_fixed_data", 0 )
+ ROM_LOAD( "igs_fixed_data.key", 0x00, 0x15, CRC(9159ecbf) SHA1(b6bdb1f327944dfc7f6f71565a24e89517607490) )
+ROM_END
+
+ROM_START( genius6b ) // PCB NO-0132, identical to V133F but for the main CPU ROM
+ ROM_REGION( 0x40000, "maincpu", 0 )
+ ROM_LOAD( "genius6_v-132f.u18", 0x00000, 0x40000, CRC(231be791) SHA1(1684395dc93902893dca32952c236617ccdbc269) )
+
+ ROM_REGION( 0x80000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "genius6_cg.u7", 0x000000, 0x080000, CRC(1842d021) SHA1(78bfb5108741d39bd19b603cc97623fba7b2a31e) )
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "text.u8", 0x000000, 0x040000, CRC(7716b601) SHA1(363cddd930fdec4821ebfaced64276f8fa943eae) )
+
+ ROM_REGION( 0x40000, "oki", 0 )
+ ROM_LOAD( "speech.u17", 0x00000, 0x40000, CRC(d9e3d39f) SHA1(bec85d1ac2dfca77453cbca0e7dd53fee8fb438b) )
+
+ ROM_REGION( 0x2dd, "pld", ROMREGION_ERASE )
+ ROM_LOAD( "cq.u24", 0x000, 0x2dd, NO_DUMP ) // PAL22CV10
+
+ ROM_REGION( 0x15, "igs_fixed_data", 0 )
+ ROM_LOAD( "igs_fixed_data.key", 0x00, 0x15, CRC(9159ecbf) SHA1(b6bdb1f327944dfc7f6f71565a24e89517607490) )
+ROM_END
+
+/***************************************************************************
+
+Tian Jiang Shen Bing (V137C)
+天將神兵 (Tiān Jiāng Shén Bīng)
+IGS, 1997
+
+This PCB is almost the same as IQBlock (IGS, 1996)
+but the 8255 has been replaced with the IGS025 IC
+
+PCB Layout
+----------
+
+IGS PCB NO-0157-2
+|---------------------------------------|
+|uPD1242H VOL U3567 3.579545MHz|
+| AR17961 |
+| HD64180RP8 SPDT_SW|
+| 16MHz BATTERY|
+| |
+| S0703.U15 |
+| |
+|J |-------| 6264 |
+|A | | |
+|M |IGS025 | P0700.U16 |
+|M | | |
+|A |-------| |
+| |
+| |
+| |-------| |
+| | | PAL |
+| A0701.U3 |IGS017 | |
+| | | PAL |
+| TEXT.U6 |-------| |
+| 22MHz 61256 |
+| DSW1 DSW2 DSW3 |
+|---------------------------------------|
+Notes:
+ HD64180RP8 - Hitachi HD64180 CPU. Clocks 16MHz (pins 2 & 3), 8MHz (pin 64)
+ 61256 - 32k x8 SRAM (DIP28)
+ 6264 - 8k x8 SRAM (DIP28)
+ IGS017 - Custom IGS IC (QFP208)
+ IGS025 - Custom IGS IC (PLCC68)
+ AR17961 - == Oki M6295 (QFP44). Clock 1.000MHz [16/16]. pin 7 = high
+ U3567 - == YM2413. Clock 3.579545MHz
+ VSync - 60Hz
+ HSync - 15.30kHz
+
+***************************************************************************/
+
+ROM_START( tjsb )
+ ROM_REGION( 0x40000, "maincpu", 0 )
+ ROM_LOAD( "p0700.u16", 0x00000, 0x40000,CRC(1b2a50df) SHA1(95a272e624f727df9523667864f933118d9e633c) )
+
+ ROM_REGION( 0x400000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "a0701.u3", 0x00000, 0x400000, CRC(27502a0a) SHA1(cca79e253697f47b688ef781b1b6de9d2945f199) ) // FIXED BITS (xxxxxxxx0xxxxxxx)
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "text.u6", 0x00000, 0x80000, CRC(3be886b8) SHA1(15b3624ed076640c1828d065b01306a8656f5a9b) ) // BADADDR --xxxxxxxxxxxxxxxxx
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "s0703.u15", 0x00000, 0x80000, CRC(c6f94d29) SHA1(ec413580240711fc4977dd3c96c288501aa7ef6c) )
+
+ ROM_REGION( 0xec, "igs_string", 0 )
+ ROM_LOAD( "tjsb_string.key", 0x00, 0xec, CRC(412c83a0) SHA1(c09618aabecdde4c77d2b5695799fc89dfb325bc) )
+ROM_END
+
+/***************************************************************************
+
+Manguan Caishen (V103CS)
+满贯财神 (Mǎnguàn Cáishén)
+IGS, 1998
+
+PCB Layout
+----------
+
+IGS PCB NO-0192-1
+|---------------------------------------|
+| JAMMA uPC1242 |
+| |
+| S1502.U10 |
+| K668 VOL |
+| |
+| |
+| 22MHz |
+|1 61256 |
+|8 |-------| TEXT.U25 |
+|W PAL | | |
+|A |IGS017 | |
+|Y | | M1501.U23|
+| |-------| |
+| |-------| |
+| | | |
+| |IGS025 | P1500.U8 |
+| | | PAL 6264 |
+|1 |-------| |
+|0 |----| PAL 6264 |
+|W |IGS | PAL |
+|A |029 | 8MHz SPDT_SW|
+|Y |----| 68000 |
+|T DSW1 DSW2 BATTERY |
+|---------------------------------------|
+Notes:
+ Uses JAMMA & common 10-way/18-way Mahjong pinout
+ 68000 clock 11.000MHz [22/2]
+ K668 == Oki M6295 (QFP44). Clock 1MHz [8/8]. pin7 = High
+ VSync - 60Hz
+ HSync - 15.3kHz
+
+***************************************************************************/
+
+ROM_START( mgcs )
+ ROM_REGION( 0x80000, "maincpu", 0 )
+ ROM_LOAD16_WORD_SWAP( "p1500.u8", 0x00000, 0x80000, CRC(a8cb5905) SHA1(37be7d926a1352869632d43943763accd4dec4b7) )
+
+ ROM_REGION( 0x400000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "m1501.u23", 0x000000, 0x400000, CRC(96fce058) SHA1(6b87f47d646bad9b3061bdc8a9af65467fdbbc9f) ) // FIXED BITS (xxxxxxx0xxxxxxxx)
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "text.u25", 0x00000, 0x80000, CRC(a37f9613) SHA1(812f060ca98a34540c48a180c359c3d0f1c0b5bb) )
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "s1502.u10", 0x00000, 0x80000, CRC(a8a6ba58) SHA1(59276a8ab4a31812600816c2a43b74bd71394419) )
+
+ ROM_REGION( 0xec, "igs_string", 0 )
+ ROM_LOAD( "mgcs_string.key", 0x00, 0xec, CRC(6cdadd19) SHA1(c2b4ced5d45d0af1ddeeabd0e352fd5383995d32) )
+ROM_END
+
+/*********************************************************************************
+
+Man Guan Cai Shen, IGS 1998
+
+PCB Layout
+----------
+
+IGS PCB NO- 0208
+|-----------------------------------------|
+| JAMMA VOL TDA1020 |
+|1 F521(x25) 7805 |
+|8 S1502.U12 M6295 |
+|W 22MHz M1503.U22|
+|A LM2933 |
+|Y |
+| |
+|IGS029 |
+| 8MHz IGS031 |
+| M1501.U21|
+| |
+| 27C4096.U24|
+| 61256 |
+|1 IGS025 68000 6264 |
+|0 PAL |
+|W PAL |
+|A SW1 PAL |
+|Y SW2 SW3 T518B |
+|-----------------------------------------|
+Notes:
+ 68000 - Clock 11.000MHz [22/2]
+ M6295 - Clock 1.000MHz [22/22]
+ SW1/2 - 8-Position DIP Switch
+ SW3 - Reset / NVRAM Clear
+ 6264 - 8kBx8-bit SRAM
+ 61256 - 32kBx8-bit SRAM
+
+*********************************************************************************/
+
+ROM_START( mgcsa )
+ ROM_REGION( 0x80000, "maincpu", 0 )
+ ROM_LOAD16_WORD_SWAP( "27c4096.u24", 0x00000, 0x80000, CRC(c41b7530) SHA1(1f9f821658c50b84b2e8cce97ffea8349fdae54f) )
+
+ ROM_REGION( 0x400000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "m1501.u21", 0x000000, 0x400000, CRC(96fce058) SHA1(6b87f47d646bad9b3061bdc8a9af65467fdbbc9f) ) // FIXED BITS (xxxxxxx0xxxxxxxx)
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "m1503.u22", 0x00000, 0x80000, CRC(a37f9613) SHA1(812f060ca98a34540c48a180c359c3d0f1c0b5bb) )
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "s1502.u12", 0x00000, 0x80000, CRC(a8a6ba58) SHA1(59276a8ab4a31812600816c2a43b74bd71394419) )
+
+ ROM_REGION( 0xec, "igs_string", 0 )
+ ROM_LOAD( "mgcs_string.key", 0x00, 0xec, BAD_DUMP CRC(6cdadd19) SHA1(c2b4ced5d45d0af1ddeeabd0e352fd5383995d32) ) // TODO: seems the same as the parent, but double-check
+ROM_END
+
+// IGS PCB N0-0266. No IGS029, but a IGS026
+ROM_START( mgcsb )
+ ROM_REGION( 0x80000, "maincpu", 0 )
+ ROM_LOAD16_WORD_SWAP( "rom.u23", 0x00000, 0x80000, CRC(efc2b198) SHA1(bb004d1a7d6a623540423e1a45f93a24d9f22c88) )
+
+ ROM_REGION( 0x400000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "m1501.u21", 0x000000, 0x400000, CRC(96fce058) SHA1(6b87f47d646bad9b3061bdc8a9af65467fdbbc9f) )
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "m1503-text v100c.u12", 0x00000, 0x80000, CRC(9925423e) SHA1(c0df6f9a0886810d1f137093f5bff1b326c4a522) )
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "s1502.u16", 0x00000, 0x80000, CRC(a8a6ba58) SHA1(59276a8ab4a31812600816c2a43b74bd71394419) )
+
+ ROM_REGION( 0xec, "igs_string", ROMREGION_ERASE00 )
+ROM_END
+
+/***************************************************************************
+
+Chaoji Da Manguan II (China, V754C)
+超級大滿貫 (Chāojí Dàmǎnguàn)
+IGS, 1997
+
+PCB Layout
+----------
+
+IGS PCB NO-0147-6
+|---------------------------------------|
+| uPC1242H S0903.U15 BATTERY |
+| VOL SPDT_SW |
+| |
+| K668 6264 |
+| |
+| 6264 |
+| PAL |
+|1 8255 |
+|8 P0900.U25 |
+|W |
+|A |
+|Y |
+| 68000 |
+| |
+| M0902.U4 PAL |
+| |
+| PAL |
+|1 M0901.U5 |-------| |
+|0 | | PAL |
+|W |IGS031 | |
+|A TEXT.U6 | | |
+|Y |-------| 62256 |
+|T 22MHz DSW1 DSW2 |
+|---------------------------------------|
+Notes:
+ Uses common 10-way/18-way Mahjong pinout
+ 68000 clock 11.000MHz [22/2]
+ K668 = M6295. clock 1.000MHz [22/22]. pin7 = High
+ VSync - 60Hz
+ HSync - 15.3kHz
+
+***************************************************************************/
+
+ROM_START( sdmg2754ca )
+ ROM_REGION( 0x80000, "maincpu", 0 )
+ ROM_LOAD16_WORD_SWAP( "p0900.u25", 0x00000, 0x80000, CRC(43366f51) SHA1(48dd965dceff7de15b43c2140226a8b17a792dbc) )
+
+ ROM_REGION( 0x280000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "m0901.u5", 0x000000, 0x200000, CRC(9699db24) SHA1(50fc2f173c20b48d10595f01f1e9545f1b13a61b) ) // FIXED BITS (xxxxxxxx0xxxxxxx)
+ ROM_LOAD( "m0902.u4", 0x200000, 0x080000, CRC(3298b13b) SHA1(13b21ddeed368b7f4fea1408c8fc511244342faf) ) // FIXED BITS (xxxxxxxx0xxxxxxx)
+
+ ROM_REGION( 0x20000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "text.u6", 0x000000, 0x020000, CRC(cb34cbc0) SHA1(ceedbdda085fd1acc9a575502bdf7cf998f54f05) )
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "s0903.u15", 0x00000, 0x80000, CRC(ae5a441c) SHA1(923774ef73ab0f70e0db1738a4292dcbd70d2384) )
+ROM_END
+
+ROM_START( sdmg2754cb ) // supposedly earlier / easier, but reports same version as sdmg2754ca
+ ROM_REGION( 0x80000, "maincpu", 0 )
+ ROM_LOAD16_WORD_SWAP( "p0900.u25", 0x00000, 0x80000, CRC(1afc95d8) SHA1(924e198437359beec2abe6ee42a985f63d70b7e3) ) // SLDH
+
+ ROM_REGION( 0x280000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "m0901.u5", 0x000000, 0x200000, CRC(9699db24) SHA1(50fc2f173c20b48d10595f01f1e9545f1b13a61b) ) // FIXED BITS (xxxxxxxx0xxxxxxx)
+ ROM_LOAD( "m0902.u4", 0x200000, 0x080000, CRC(3298b13b) SHA1(13b21ddeed368b7f4fea1408c8fc511244342faf) ) // FIXED BITS (xxxxxxxx0xxxxxxx)
+
+ ROM_REGION( 0x20000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "text.u6", 0x000000, 0x020000, CRC(cb34cbc0) SHA1(ceedbdda085fd1acc9a575502bdf7cf998f54f05) )
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "s0903.u15", 0x00000, 0x80000, CRC(ae5a441c) SHA1(923774ef73ab0f70e0db1738a4292dcbd70d2384) )
+ROM_END
+
+ROM_START( sdmg2 ) // C5220P001 PCB
+ ROM_REGION( 0x80000, "maincpu", 0 )
+ ROM_LOAD16_WORD_SWAP( "rom.u16", 0x00000, 0x80000, CRC(362800e8) SHA1(00d93002272b1f3171ca84e67822eb31f760191f) )
+
+ ROM_REGION( 0x280000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "m0205.u6", 0x000000, 0x200000, BAD_DUMP CRC(9699db24) SHA1(50fc2f173c20b48d10595f01f1e9545f1b13a61b) ) // ROM didn't read correctly, taken from other sets
+ ROM_LOAD( "rom.u5", 0x200000, 0x080000, CRC(3298b13b) SHA1(13b21ddeed368b7f4fea1408c8fc511244342faf) ) // FIXED BITS (xxxxxxxx0xxxxxxx)
+
+ ROM_REGION( 0x20000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "text.u7", 0x000000, 0x020000, CRC(cb34cbc0) SHA1(ceedbdda085fd1acc9a575502bdf7cf998f54f05) )
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "s0206.u3", 0x00000, 0x80000, CRC(ae5a441c) SHA1(923774ef73ab0f70e0db1738a4292dcbd70d2384) )
+ROM_END
+
+/***************************************************************************
+
+Maque Wangchao / Chaoji Da Manguan 2 - Jiaqiang Ban
+麻雀王朝 / 超級大滿貫 2 -加強版 (Mahjong Dynasty / Super Grand Slam 2 - Enhanced Edition)
+
+IGS 2000
+Hardware info By Guru
+---------------------
+
+IGS PCB NO-0271
+|--------------------------------------|
+|PC817x19 JAMMA |
+| |-----| MA.DY_TEXT.U18|
+| | IGS | |
+| | 025 | |
+| |-----| 22MHz |
+| |-------| |
+| | IGS031| IGS_M0906.U20|
+|PC817x6 | | |
+| 22V10 | | MA.DY_V100C.U21|
+| SW1 |-------| |
+| SW2 61256|------| |
+| SW3 |68000 | 22V10 BATT|
+| | | 6264 |
+| 16V8 |------| |
+|LM7805 K668 |
+| SW4 |
+|TDA1020 VOL MA.DY_SP.U14 |
+|--------------------------------------|
+Notes:
+ 68000 - Clock 11.0MHz [22/2]
+ K668 - ==OKI M6295. Clock 1.0MHz [22/22]. Pin 7 HIGH
+ 61256 - 32kB x8-bit SRAM
+ 6262 - 8kB x8-bit SRAM (battery-backed)
+ SW1-3 - 8-position DIP Switch
+ SW4 - High Score Reset / Back-up Battery RAM Re-initialize / PCB Reset
+ PC817 - Sharp PC817 Optocoupler
+ 16V8 - Atmel ATF16V8B PLD
+ 22V10 - Atmel ATF22V10B PLD
+ TDA1020 - Audio Power Amp
+ U18/U21 - 27C4002 EPROM
+ U14 - 27C040 EPROM
+ U20 - MX23C3210 mask ROM
+
+***************************************************************************/
+
+ROM_START( sdmg2p )
+ ROM_REGION( 0x80000, "maincpu", 0 )
+ ROM_LOAD16_WORD_SWAP( "ma.dy_v100c.u21", 0x00000, 0x80000,CRC(c071270e) SHA1(8b55a80da30f4233c862bb5d8a79a76af634a296) )
+
+ ROM_REGION( 0x400000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "igs_m0906.u20", 0x000000, 0x400000, CRC(01ea0a60) SHA1(66f083084f6d9e8dc4d1d50f3c5bcf2b79025fc0) ) // FIXED BITS (xxxxxxxx0xxxxxxx)
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "ma.dy_text.u18", 0x000000, 0x080000, CRC(e46a3a52) SHA1(7b3f113170904dc474712a6a76162a8ee5dbd318) )
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "ma.dy_sp.u14", 0x00000, 0x80000, CRC(b31c6349) SHA1(9e8e5b029e1eff47581f99ecf2da3f17bee01f32) ) // 1ST AND 2ND HALF IDENTICAL
+
+ ROM_REGION( 0xec, "igs_string", 0 )
+ ROM_LOAD( "sdmg2p_string.key", 0x00, 0xec, NO_DUMP )
+ROM_END
+
+/***************************************************************************
+
+Long Hu Zhengba 2 (set 1)
+龙虎争霸 (Lóng Hǔ Zhēngbà)
+IGS, 1998
+
+PCB Layout
+----------
+
+IGS PCB NO-0206
+|---------------------------------------|
+| 6264 |-------| |
+| 6264 |----| | | |
+| |IGS | |IGS025 | |
+| |022 | | | PAL |
+| |----| |-------| |
+| PAL |
+| M1104.U11 PAL 68000 |
+|1 |
+|8 |
+|W |
+|A M1101.U6 8MHz P1100.U30 |
+|Y |
+| 6264 |
+| |
+| |-------| |
+| | | |
+| |IGS031 | 61256|
+|1 | | |
+|0 M1103.U8 |-------| |
+|W 22MHz |
+|A DSW1 DSW2 |
+|Y K668 BATTERY |
+|TDA1020 VOL S1102.U23 SPDT_SW|
+|---------------------------------------|
+Notes:
+ Uses common 10-way/18-way Mahjong pinout
+ 68000 clock 11.000MHz [22/2]
+ K668 == Oki M6295 (QFP44). Clock 1MHz [8/8]. pin7 = High
+ VSync - 60Hz
+ HSync - 15.3kHz
+
+***************************************************************************/
+
+ROM_START( lhzb2 )
+ ROM_REGION( 0x80000, "maincpu", 0 )
+ ROM_LOAD16_WORD_SWAP( "p1100.u30", 0x00000, 0x80000, CRC(68102b25) SHA1(6c1e8d204be0efda0e9b6c2f49b5c6760712475f) )
+
+ ROM_REGION( 0x10000, "igs022", 0 )
+ ROM_LOAD( "m1104.u11",0x0000, 0x10000, CRC(794d0276) SHA1(ac903d2faa3fb315438dc8da22c5337611a8790d) ) // INTERNATIONAL GAMES SYSTEM CO.,LTD
+
+ ROM_REGION( 0x400000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD16_WORD_SWAP( "m1101.u6", 0x000000, 0x400000, CRC(0114e9d1) SHA1(5b16170d3cd8b8e1662c949b7234fbdd2ca927f7) ) // FIXED BITS (0xxxxxxxxxxxxxxx)
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD16_WORD_SWAP( "m1103.u8", 0x00000, 0x80000, CRC(4d3776b4) SHA1(fa9b311b1a6ad56e136b66d090bc62ed5003b2f2) )
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "s1102.u23", 0x00000, 0x80000, CRC(51ffe245) SHA1(849011b186096add657ab20d49d260ec23363ef3) )
+
+ ROM_REGION( 0xec, "igs_string", 0 )
+ ROM_LOAD( "lhzb2_string.key", 0x00, 0xec, CRC(c964dc35) SHA1(81036e0dfa9abad123701ae8939d0d5b6f91b015) )
+ROM_END
+
+// VS221M: alt hardware, no IGS022 protection chip
+
+ROM_START( lhzb2a )
+ ROM_REGION( 0x80000, "maincpu", 0 )
+ ROM_LOAD16_WORD_SWAP( "p-4096", 0x00000, 0x80000, CRC(41293f32) SHA1(df4e993f4a458729ade13981e58f32d8116c0082) )
+
+ ROM_REGION( 0x400000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD16_WORD_SWAP( "m1101.u6", 0x000000, 0x400000, CRC(0114e9d1) SHA1(5b16170d3cd8b8e1662c949b7234fbdd2ca927f7) ) // FIXED BITS (0xxxxxxxxxxxxxxx)
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD16_WORD_SWAP( "m1103.u8", 0x00000, 0x80000, CRC(4d3776b4) SHA1(fa9b311b1a6ad56e136b66d090bc62ed5003b2f2) )
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "s1102.u23", 0x00000, 0x80000, CRC(51ffe245) SHA1(849011b186096add657ab20d49d260ec23363ef3) )
+
+ ROM_REGION( 0xec, "igs_string", 0 )
+ ROM_LOAD( "lhzb2_string.key", 0x00, 0xec, CRC(c964dc35) SHA1(81036e0dfa9abad123701ae8939d0d5b6f91b015) )
+ROM_END
+
+/*
+PCB NO-0182-2
+IGS025 sticker is D2
+Custom - IGS022, IGS017
+Osc - 8MHz near IGS022, 22MHz near IGS017
+2 banks of 8 DIP switches
+Oki M6295
+*/
+ROM_START( lhzb )
+ ROM_REGION( 0x80000, "maincpu", 0 )
+ ROM_LOAD16_WORD_SWAP( "rom.u25", 0x00000, 0x80000, CRC(46f5df48) SHA1(da35b0cfaef34179a8e2a019c472ff14d831c753) )
+
+ ROM_REGION( 0x10000, "igs022", 0 )
+ ROM_LOAD( "rom.u12",0x0000, 0x10000, CRC(794d0276) SHA1(ac903d2faa3fb315438dc8da22c5337611a8790d) )
+
+ ROM_REGION( 0x400000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD16_WORD_SWAP( "m1101.u13", 0x000000, 0x400000, CRC(0114e9d1) SHA1(5b16170d3cd8b8e1662c949b7234fbdd2ca927f7) ) // FIXED BITS (0xxxxxxxxxxxxxxx)
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD16_WORD_SWAP( "rom.u15", 0x00000, 0x80000, CRC(5d28287b) SHA1(441f7f301f9d5f1d817f907ec4cedf274a6801d4) )
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "rom.u22", 0x00000, 0x80000, CRC(51ffe245) SHA1(849011b186096add657ab20d49d260ec23363ef3) )
+
+ ROM_REGION( 0xec, "igs_string", 0 )
+ ROM_LOAD( "lhzb2_string.key", 0x00, 0xec, CRC(c964dc35) SHA1(81036e0dfa9abad123701ae8939d0d5b6f91b015) )
+ROM_END
+
+ROM_START( lhzba ) // PCB NO-0182-2, very minor code differences if compared to lhzb.
+ ROM_REGION( 0x80000, "maincpu", 0 )
+ ROM_LOAD16_WORD_SWAP( "rom.u25", 0x00000, 0x80000, CRC(2fd43fea) SHA1(6215655ae49c75cece33a359a359b0e7980a2c1c) )
+
+ ROM_REGION( 0x10000, "igs022", 0 )
+ ROM_LOAD( "rom.u12",0x0000, 0x10000, CRC(794d0276) SHA1(ac903d2faa3fb315438dc8da22c5337611a8790d) )
+
+ ROM_REGION( 0x400000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD16_WORD_SWAP( "m1101.u13", 0x000000, 0x400000, CRC(0114e9d1) SHA1(5b16170d3cd8b8e1662c949b7234fbdd2ca927f7) ) // FIXED BITS (0xxxxxxxxxxxxxxx)
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD16_WORD_SWAP( "rom.u15", 0x00000, 0x80000, CRC(5d28287b) SHA1(441f7f301f9d5f1d817f907ec4cedf274a6801d4) )
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "rom.u22", 0x00000, 0x80000, CRC(51ffe245) SHA1(849011b186096add657ab20d49d260ec23363ef3) )
+
+ ROM_REGION( 0xec, "igs_string", 0 )
+ ROM_LOAD( "lhzb2_string.key", 0x00, 0xec, CRC(c964dc35) SHA1(81036e0dfa9abad123701ae8939d0d5b6f91b015) )
+ROM_END
+
+/***************************************************************************
+
+Shuang Long Qiang Zhu 2 VS (China, VS203J)
+双龙抢珠 (Shuāng Lóng Qiǎng Zhū)
+IGS, 1998
+
+PCB Layout
+----------
+
+IGS PCB NO-0207
+|---------------------------------------|
+| K668 S1102.U20 |
+| PAL |
+| 8MHz 6264 |
+| |
+| |----| 6264 |
+| |IGS | |
+| |022 | M1103.U12 PAL |
+|J |----| PAL |
+|A |
+|M |
+|M |-------| |
+|A | | |
+| |IGS025 | 68000 |
+| | | |
+| |-------| |
+| P1100.U28 |
+| PAL |
+| M1101.U4 |-------| |
+| | | |
+| |IGS031 | 6264 |
+| TEXT.U6 | | |
+| |-------| 62256 |
+|SPDT_SW 22MHz DSW1 DSW2 BATTERY |
+|---------------------------------------|
+Notes:
+ 68000 clock 11.000MHz [22/2]
+ K668 == Oki M6295 (QFP44). Clock 1.000MHz [8/8]. pin7 = High
+ VSync - 60Hz
+ HSync - 15.3kHz
+
+***************************************************************************/
+
+ROM_START( slqz2 )
+ ROM_REGION( 0x80000, "maincpu", 0 )
+ ROM_LOAD16_WORD_SWAP( "p1100.u28", 0x00000, 0x80000, CRC(0b8e5c9e) SHA1(16572bd1163bba4da8a76b10649d2f71e50ad369) )
+
+ ROM_REGION( 0x10000, "igs022", 0 )
+ ROM_LOAD( "m1103.u12", 0x00000, 0x10000, CRC(9f3b8d65) SHA1(5ee1ad025474399c2826f21d970e76f25d0fa1fd) ) // INTERNATIONAL GAMES SYSTEM CO.,LTD
+
+ ROM_REGION( 0x400000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD16_WORD_SWAP( "m1101.u4", 0x000000, 0x400000, CRC(0114e9d1) SHA1(5b16170d3cd8b8e1662c949b7234fbdd2ca927f7) ) // FIXED BITS (0xxxxxxxxxxxxxxx)
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "text.u6", 0x00000, 0x80000, CRC(40d21adf) SHA1(18b202d6330ac89026bec2c9c8224b52540dd48d) )
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "s1102.u20", 0x00000, 0x80000, CRC(51ffe245) SHA1(849011b186096add657ab20d49d260ec23363ef3) ) // = s1102.u23 Long Hu Zhengba 2
+
+ ROM_REGION( 0xec, "igs_string", 0 )
+ ROM_LOAD( "slqz2_string.key", 0x00, 0xec, CRC(5ca22f9d) SHA1(a795415016fdcb6329623786dc992ac7b0877ddf) )
+ROM_END
+
+/*********************************************************************************
+
+An older version of Shuang Long Qiang Zhu 2 VS
+
+PCB Layout
+----------
+
+IGS PCB NO-0182-1
+|-----------------------------------------|
+| 6264 SW3|
+|1 6264 27C4096.U25 |
+|8 IGS025 |
+|W (LABEL N2) 6264 |
+|A |
+|Y 6264 |
+| |
+| 68000 |
+| IGS022 26C512.U12 |
+| 32.768kHz |
+| M1101.U13 PAL |
+| 8MHz PAL |
+|1 PAL |
+|0 27C4096.U15 PAL |
+|W IGS017 |
+|A VOL 22MHz 61256 |
+|Y 7805 |
+|UPC1242 K668 S1102.U22 SW1 SW2 |
+|-----------------------------------------|
+Notes:
+ 68000 - Clock 11.000MHz [22/2]
+ K668 - Oki M6295 clone. Clock 1.000MHz [22/22]
+ SW1/2 - 8-Position DIP Switch
+ SW3 - Reset / NVRAM Clear
+ 61256 - 32kBx8-bit SRAM
+ 6264 - 8kBx8-bit SRAM
+ IGS022 - IGS custom. 32.768kHz crystal is tied to this IC so it has a real time clock integrated into it.
+
+*********************************************************************************/
+
+
+ROM_START( slqz2a )
+ ROM_REGION( 0x80000, "maincpu", 0 )
+ ROM_LOAD16_WORD_SWAP( "27c4096.u25", 0x00000, 0x80000, NO_DUMP )// dead ROM
+
+ ROM_REGION( 0x10000, "igs022", 0 )
+ ROM_LOAD( "26c512.u12",0x0000, 0x10000, CRC(794d0276) SHA1(ac903d2faa3fb315438dc8da22c5337611a8790d) ) // INTERNATIONAL GAMES SYSTEM CO.,LTD
+
+ ROM_REGION( 0x400000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD16_WORD_SWAP( "m1101.u13", 0x000000, 0x400000, CRC(0114e9d1) SHA1(5b16170d3cd8b8e1662c949b7234fbdd2ca927f7) ) // FIXED BITS (0xxxxxxxxxxxxxxx)
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "27c4096.u15", 0x00000, 0x80000, CRC(4d3776b4) SHA1(fa9b311b1a6ad56e136b66d090bc62ed5003b2f2) )
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "s1102.u20", 0x00000, 0x80000, CRC(51ffe245) SHA1(849011b186096add657ab20d49d260ec23363ef3) )
+
+ ROM_REGION( 0xec, "igs_string", 0 )
+ ROM_LOAD( "slqz2a_string.key", 0x00, 0xec, BAD_DUMP CRC(5ca22f9d) SHA1(a795415016fdcb6329623786dc992ac7b0877ddf) ) // TODO, if / when program ROM is dumped
+ROM_END
+
+
+/***************************************************************************
+
+Manguan Daheng (V123T1)
+滿貫大亨 (Mǎnguàn Dàhēng)
+(c) 1997 IGS
+
+PCB Layout
+----------
+
+IGS PCB NO-0252
+|----------------------------------|
+| S1002.U22 6264 62256 SW |
+|TDA1020 FLASH.U19 PAL BATT|
+| LM7805 M6295 |
+| VOL |
+|ULN2004 |
+|J 68000 IGS031 |
+|A DSW2 |
+|M |
+|M |
+|A PAL PAL |
+| IGS025 |
+| |
+| M1001.U4 22MHz|
+| TEXT.U6 |
+| DSW1|
+| 18WAY 10WAY |
+|----------------------------------|
+Notes:
+ 68000 - Clock 11.000MHz [22/2]
+ M6295 - Clock 1.000MHz [22/22]. Pin 7 HIGH
+ DSW1/2 - 8-position Dip Switches
+ SW - Backup RAM Clear and Reset Switch
+ FLASH.U19 - MX29F400 4M TSOP48 mounted onto a DIP adapter and plugged into a
+ socket. Under the socket is written '27C4096'
+ M1001.U4 - 32M DIP42 Mask ROM
+ S1002.U22 - 4M DIP32 Mask ROM
+ TEXT.U6 - 27C1024 EPROM
+
+***************************************************************************/
+
+ROM_START( mgdha )
+ ROM_REGION( 0x80000, "maincpu", 0 )
+ ROM_LOAD16_WORD_SWAP( "flash.u19", 0x00000, 0x80000, CRC(ff3aed2c) SHA1(829140e6fc7e4dfc039b0e7b647ce26d59b23b3d) )
+
+ ROM_REGION( 0x400000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "m1001.u4", 0x000000, 0x400000, CRC(0cfb60d6) SHA1(e099aca730e7fd91a72915c27e569ad3d21f0d8f) ) // FIXED BITS (xxxxxxx0xxxxxxxx)
+
+ ROM_REGION( 0x20000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD16_WORD_SWAP( "text.u6", 0x00000, 0x20000, CRC(db50f8fc) SHA1(e2ce4a42f5bdc0b4b7988ad9e8d14661f17c3d51) )
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "s1002.u22", 0x00000, 0x80000, CRC(ac6b55f2) SHA1(7ff91fd1107272ad6bce071dc9ae2f374ebf5e3e) )
+ROM_END
+
+/***************************************************************************
+
+Manguan Daheng (V125T1)
+滿貫大亨 (Mǎnguàn Dàhēng)
+(c) 1997 IGS
+
+No hardware info, no sprites rom for this set.
+It has an additional game id check at the start.
+
+***************************************************************************/
+
+ROM_START( mgdh )
+ ROM_REGION( 0x80000, "maincpu", 0 )
+ ROM_LOAD16_WORD_SWAP( "igs_f4bd.125", 0x00000, 0x80000, CRC(8bb0b870) SHA1(f0313f0b8b7575f4fff1feb99d48699d50556ef5) )
+
+ ROM_REGION( 0x400000, "igs017_igs031:sprites", 0 )
+ // not in this set
+ ROM_LOAD( "m1001.u4", 0x000000, 0x400000, CRC(0cfb60d6) SHA1(e099aca730e7fd91a72915c27e569ad3d21f0d8f) ) // FIXED BITS (xxxxxxx0xxxxxxxx)
+
+ ROM_REGION( 0x20000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "igs_512e.u6", 0x00000, 0x20000, CRC(db50f8fc) SHA1(e2ce4a42f5bdc0b4b7988ad9e8d14661f17c3d51) ) // == text.u6
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "ig2_8836.u14", 0x00000, 0x80000, CRC(ac1f4da8) SHA1(789a2e0b58750292909dabca42c7e5ad72af3db5) )
+ROM_END
+
+/***************************************************************************
+
+Tarzan Chuang Tian Guan (V109C)
+泰山闯天关 (Tàishān Chuǎng Tiān Guān)
+IGS 1999
+
+PCB Layout
+----------
+
+IGS PCB NO-0248-1
+|------------------------------|
+| J A M M A |
+|1 22MHz T2105.U5 A2104.U15 |
+|8 DIP42 |
+|W |
+|A IGS031 U19 |
+|Y 24257 |
+| |
+| IGS025 PAL.U20|
+| DSW1 |
+| Z180 |
+| DSW2 16MHz |
+|1 PAL.U21|
+|0 DSW3 |
+|W BATT |
+|A VOL LM7805 RES_SW|
+|Y uPC1242 M6295 U14 |
+|------------------------------|
+Notes:
+ IGS025 - custom IGS chip labelled 'TARZAN 1'
+ IGS031 - custom IGS chip
+ VSync - 60.0060Hz
+ HSync - 15.3002kHz
+ M6295 - Clock 1.000MHz [16/16], pin 7 high
+ Z180 - Clock 16.000MHz
+ DIP42 - Empty socket
+ U19 - 28F2000 Flash ROM (DIP32)
+ U14 - 23C4000 mask ROM (DIP32)
+ U5 - 23C2048 mask ROM (DIP40)
+ U15 - 23C3210 mask ROM (DIP42)
+ 24257 - 32kx8 SRAM
+
+***************************************************************************/
+
+// IGS PCB NO-0248-1
+ROM_START( tarzanc )
+ ROM_REGION( 0x40000, "maincpu", 0 ) // V109C TARZAN C (same as tarzan set)
+ ROM_LOAD( "u19", 0x00000, 0x40000, CRC(e6c552a5) SHA1(f156de9459833474c85a1f5b35917881b390d34c) )
+
+ ROM_REGION( 0x400000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "igs_a2104_cg_v110.u15", 0x00000, 0x400000, CRC(dcbff16f) SHA1(2bf77ef4448c26124c8d8d18bb7ffe4105cfa940) ) // FIXED BITS (xxxxxxx0xxxxxxxx)
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "igs_t2105_cg_v110.u5", 0x00000, 0x80000, CRC(1d4be260) SHA1(6374c61735144b3ff54d5e490f26adac4a10b14d) ) // 27C4096 (27C2048 printed on the PCB)
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "igs_s2102_sp_v102.u14", 0x00000, 0x80000, CRC(90dda82d) SHA1(67fbc1e8d76b85e124136e2f1df09c8b6c5a8f97) )
+
+ ROM_REGION( 0x2dd * 2, "plds", ROMREGION_ERASE )
+ ROM_LOAD( "eg.u20", 0x000, 0x2dd, NO_DUMP )
+ ROM_LOAD( "eg.u21", 0x2dd, 0x2dd, NO_DUMP )
+
+ ROM_REGION( 0xec, "igs_string", 0 )
+ ROM_LOAD( "tarzan_string.key", 0x00, 0xec, CRC(595fe40c) SHA1(0b46983400d237d8bde97a72eaa99b718a03387e) )
+ROM_END
+
+// IGS PCB NO-0248
+ROM_START( tarzanb ) // V110 TARZAN C
+ ROM_REGION( 0x40000, "maincpu", 0 )
+ ROM_LOAD( "t.z._v110.u19", 0x00000, 0x40000, CRC(16026d12) SHA1(df08641b4bc1437648f0a8cd5f7a8a4786c07041) )
+
+ ROM_REGION( 0x400000, "igs017_igs031:sprites", ROMREGION_ERASE00 )
+ ROM_LOAD( "igs_a2103_cg_v100f.u15", 0x000000, 0x200000, CRC(afe56ed5) SHA1(656cee6a59f2930eec9acd11b84b416cc7354e01) )
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "t.z._text_u5.u5", 0x00000, 0x80000, CRC(1724e039) SHA1(d628499b61f98f7c9034d70b82ee25e002190ece) )
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "igs_s2102_sp_v102.u14", 0x00000, 0x80000, CRC(90dda82d) SHA1(67fbc1e8d76b85e124136e2f1df09c8b6c5a8f97) )
+
+ ROM_REGION( 0x2dd * 2, "plds", ROMREGION_ERASE )
+ ROM_LOAD( "eg.u20", 0x000, 0x2dd, NO_DUMP )
+ ROM_LOAD( "eg.u21", 0x2dd, 0x2dd, NO_DUMP )
+
+ ROM_REGION( 0xec, "igs_string", 0 )
+ ROM_LOAD( "tarzanb_string.key", 0x00, 0xec, CRC(595fe40c) SHA1(0b46983400d237d8bde97a72eaa99b718a03387e) )
+ROM_END
+
+// sets below are guesswork, assembled from partial dumps...
+
+// IGS NO-0248-1? Mislabeled?
+ROM_START( tarzan )
+ ROM_REGION( 0x40000, "maincpu", 0 ) // V109C TARZAN C (same as tarzanc set)
+ ROM_LOAD( "0228-u16.bin", 0x00000, 0x40000, CRC(e6c552a5) SHA1(f156de9459833474c85a1f5b35917881b390d34c) )
+
+ ROM_REGION( 0x80000, "igs017_igs031:sprites", ROMREGION_ERASE )
+ ROM_LOAD( "sprites.u15", 0x00000, 0x80000, NO_DUMP )
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "0228-u6.bin", 0x00000, 0x80000, CRC(55e94832) SHA1(b15409f4f1264b6d1218d5dc51c5bd1de2e40284) )
+
+ ROM_REGION( 0x40000, "oki", ROMREGION_ERASE )
+ ROM_LOAD( "sound.u14", 0x00000, 0x40000, NO_DUMP )
+
+ ROM_REGION( 0x2dd * 2, "plds", 0 )
+ ROM_LOAD( "pal1", 0x000, 0x2dd, NO_DUMP )
+ ROM_LOAD( "pal2", 0x2dd, 0x2dd, NO_DUMP )
+
+ ROM_REGION( 0xec, "igs_string", 0 )
+ ROM_LOAD( "tarzan_string.key", 0x00, 0xec, CRC(595fe40c) SHA1(0b46983400d237d8bde97a72eaa99b718a03387e) )
+ROM_END
+
+// IGS NO-0228? This allegedly has IGS029 protection
+ROM_START( tarzana )
+ ROM_REGION( 0x40000, "maincpu", 0 ) // V107 TAISAN
+ ROM_LOAD( "0228-u21.bin", 0x00000, 0x40000, CRC(80aaece4) SHA1(07cad92492c5de36c3915867ed4c6544b1a30c07) ) // 1ST AND 2ND HALF IDENTICAL
+ ROM_IGNORE( 0x40000 )
+
+ ROM_REGION( 0x80000, "igs017_igs031:sprites", ROMREGION_ERASE )
+ ROM_LOAD( "sprites.u17", 0x00000, 0x80000, NO_DUMP )
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "0228-u6.bin", 0x00000, 0x80000, CRC(55e94832) SHA1(b15409f4f1264b6d1218d5dc51c5bd1de2e40284) )
+
+ ROM_REGION( 0x40000, "oki", ROMREGION_ERASE )
+ ROM_LOAD( "sound.u16", 0x00000, 0x40000, NO_DUMP )
+
+ ROM_REGION( 0x2dd * 2, "plds", ROMREGION_ERASE )
+ ROM_LOAD( "pal1", 0x000, 0x2dd, NO_DUMP )
+ ROM_LOAD( "pal2", 0x2dd, 0x2dd, NO_DUMP )
+
+ ROM_REGION( 0xec, "igs_string", 0 )
+ ROM_LOAD( "tarzan_string.key", 0x00, 0xec, CRC(595fe40c) SHA1(0b46983400d237d8bde97a72eaa99b718a03387e) )
+ROM_END
+
+
+/***************************************************************************
+
+Super Tarzan (Italy, V100I)
+IGS PCB NO-0230-1
+
+ ----| 10/WAY CONN |--------------------------------|
+ | |---------------------| |------| |
+ _| | U23 | |
+ |_| [ U1 ][ U5 ] |--------------| |-----| | TDA | |
+ |_| | U8 IGS S2102 | | U17 | | 1020 | |
+ |_| [ U6 ] |--------------| |-----| |------| |
+ |_| |--------------| |
+ |_| | U9 SP V100I | [ U15 ] LM7805 |
+ 3 |_| |--------------| |-------------------| |
+ 6 |_| |----------| | U16 Z8018008PSC | |
+ W |_| | U4 | [ TAR97 U10-1 ] |-------------------| |
+ A |_| | IGS025 | OSC |
+ Y |_| | S_TARZAN | [ U13 ] 16.0Mhz [ TAR97 U20 ] |
+ |_| | | |
+ C |_| |----------| [ U18 ] [ U20 ] |
+ O |_| |-----------| |
+ N |_| | U12 | SW1 |
+ N |_| | IGS 031 | |
+ |_| | F00030142 | SW2 |
+ |_| | | [ U19 ] |
+ |_| |-----------| SW3 |
+ |_| |----------------| 22.00 Mhz |
+ |_| | U2 TBM27C4096 | |
+ |_| |----------------| [ R20 Ohm 5W ] Battery |
+ |_| |----------------| |----------------------| (---) Reset |
+ | | U3 C0057209 | | U11 IGST2105 CG V110 | (3.6) SW4 |
+ | |----------------| |----------------------| (---) \ |
+ |----------------------------------------------------------|
+
+ U1,U5,U6 ULN2004A SW4 1pos switch for reset
+ U2 TBM TB27C4096 Sw1-2-3 8x2 DSW
+ U4 IGS025 (protection?)
+ U8 IGS S2102 SP V102 1P1327A6 C000538
+ U11 IGS T2105 CG V110 1P1379C1 S000938
+ U12 IGS031 F00030142 (graphic array?)
+ U17 K668 = Oki M6295 (QFP44). Clock 1.000MHz [8/8]. pin7 = High
+ U16 Zilog Z8018008PSC Z180 MPU
+ U18 DN74LS14N
+ U19 SN74HC132N
+ U20 HD74LS161AP
+ U10-1,U20-1 PALCE22V10H (read protected)
+
+***************************************************************************/
+
+ROM_START( starzan )
+ ROM_REGION( 0x40000, "maincpu", 0 )
+ ROM_LOAD( "sp_tarzan_v100i.u9", 0x00000, 0x40000, CRC(64180bff) SHA1(b08dbe8a17ca33024442ebee41f111c8f98a2109) )
+
+ ROM_REGION( 0x400000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "igs_a2104_cg_v110.u3", 0x000000, 0x400000, BAD_DUMP CRC(dcbff16f) SHA1(2bf77ef4448c26124c8d8d18bb7ffe4105cfa940) ) // FIXED BITS (xxxxxxx0xxxxxxxx), not dumped for this board, but same label as the one from tarzanc, assuming same contents for now
+ ROM_LOAD( "sp_tarzan_cg.u2", 0x200000, 0x080000, CRC(884f95f5) SHA1(2e526aa966e90dc696a8b392a5a99e14f03c4bd4) ) // FIXED BITS (xxxxxxx0xxxxxxxx), overlay (handwritten label)
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "igs_t2105_cg_v110.u11", 0x00000, 0x80000, BAD_DUMP CRC(1d4be260) SHA1(6374c61735144b3ff54d5e490f26adac4a10b14d) ) // not dumped for this board, but same label as the one from tarzanc, assuming same contents for now
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "igs_s2102_sp_v102.u8", 0x00000, 0x80000, BAD_DUMP CRC(90dda82d) SHA1(67fbc1e8d76b85e124136e2f1df09c8b6c5a8f97) ) // not dumped for this board, but same label as the one from tarzanc, assuming same contents for now
+
+ ROM_REGION( 0x2dd * 2, "plds", ROMREGION_ERASE )
+ ROM_LOAD( "palce22v10h_tar97_u10-1.u10", 0x000, 0x2dd, NO_DUMP ) // read protected
+ ROM_LOAD( "palce22v10h_tar97_u20.u20", 0x2dd, 0x2dd, NO_DUMP ) // ""
+
+ ROM_REGION( 0xec, "igs_string", 0 )
+ ROM_LOAD( "starzan_string.key", 0x00, 0xec, CRC(b33f5050) SHA1(900d3c48944dbdd95d9e48d74c355e82e00ac012) )
+ROM_END
+
+ROM_START( tarzan202fa ) // IGS PCB NO-0230-1 (IGS025 stickered X7)
+ ROM_REGION( 0x40000, "maincpu", 0 )
+ ROM_LOAD( "tarzan_v102f.u9", 0x00000, 0x40000, CRC(b099baaa) SHA1(02f021852bf70dcb3ced66974a609acd45162ddc) )
+
+ ROM_REGION( 0x400000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "igs_a2104_cg_v110.u3", 0x000000, 0x400000, CRC(dcbff16f) SHA1(2bf77ef4448c26124c8d8d18bb7ffe4105cfa940) ) // FIXED BITS (xxxxxxx0xxxxxxxx)
+ // empty u2 socket
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "igs_t2105_cg_v110.u11", 0x00000, 0x80000, CRC(1d4be260) SHA1(6374c61735144b3ff54d5e490f26adac4a10b14d) )
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "igs_s2102_sp_v102.u8", 0x00000, 0x80000, CRC(90dda82d) SHA1(67fbc1e8d76b85e124136e2f1df09c8b6c5a8f97) )
+
+ ROM_REGION( 0x2dd * 2, "plds", ROMREGION_ERASE )
+ ROM_LOAD( "palce22v10h_tar97_u10-1.u10", 0x000, 0x2dd, NO_DUMP ) // read protected
+ ROM_LOAD( "palce22v10h_tar97_u20.u20", 0x2dd, 0x2dd, NO_DUMP ) // ""
+
+ ROM_REGION( 0xec, "igs_string", 0 )
+ ROM_LOAD( "tarzan202fa_string.key", 0x00, 0xec, CRC(b33f5050) SHA1(900d3c48944dbdd95d9e48d74c355e82e00ac012) )
+ROM_END
+
+// IGS PCB NO-0230-1 (IGS025 stickered Z8 and Tarzan 2)
+// has Jungle King Plus string but shows Jungle King title screen
+ROM_START( jking200pr )
+ ROM_REGION( 0x40000, "maincpu", 0 )
+ ROM_LOAD( "u9", 0x00000, 0x40000, CRC(8c40c920) SHA1(7d2c8b7b9e1eca4bf3f895e79c45e86937dc7cb4) ) // 1ST AND 2ND HALF IDENTICAL, no original label
+ ROM_IGNORE( 0x40000 )
+
+ ROM_REGION( 0x400000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "igs_a2104_cg_v110.u3", 0x000000, 0x400000, CRC(dcbff16f) SHA1(2bf77ef4448c26124c8d8d18bb7ffe4105cfa940) ) // FIXED BITS (xxxxxxx0xxxxxxxx)
+ // empty u2 socket
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "igs_t2105_cg_v110.u11", 0x00000, 0x80000, CRC(1d4be260) SHA1(6374c61735144b3ff54d5e490f26adac4a10b14d) )
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "igs_s2102_sp_v102.u8", 0x00000, 0x80000, CRC(90dda82d) SHA1(67fbc1e8d76b85e124136e2f1df09c8b6c5a8f97) )
+
+ ROM_REGION( 0x2dd * 2, "plds", ROMREGION_ERASE )
+ ROM_LOAD( "palce22v10h_tar97_u10-1.u10", 0x000, 0x2dd, NO_DUMP ) // read protected
+ ROM_LOAD( "palce22v10h_tar97_u20.u20", 0x2dd, 0x2dd, NO_DUMP ) // ""
+
+ ROM_REGION( 0xec, "igs_string", 0 )
+ ROM_LOAD( "jking200pr_string.key", 0x00, 0xec, CRC(b33f5050) SHA1(900d3c48944dbdd95d9e48d74c355e82e00ac012) )
+ROM_END
+
+// default settings password is all start button
+ROM_START( jking103a )
+ ROM_REGION( 0x40000, "maincpu", 0 )
+ ROM_LOAD( "jungleking_v103a.u9", 0x00000, 0x40000, CRC(acd23f7e) SHA1(84d487c240d6773c81c04ee12a4aafa7e34affc7) )
+
+ ROM_REGION( 0x400000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "igs_a2104_cg_v110.u3", 0x00000, 0x400000, CRC(dcbff16f) SHA1(2bf77ef4448c26124c8d8d18bb7ffe4105cfa940) ) // FIXED BITS (xxxxxxx0xxxxxxxx)
+ // empty u2
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "igs_t2105_cg_v110.u11", 0x00000, 0x80000, CRC(1d4be260) SHA1(6374c61735144b3ff54d5e490f26adac4a10b14d) )
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "igs_s2102_sp_v102.u8", 0x00000, 0x80000, CRC(90dda82d) SHA1(67fbc1e8d76b85e124136e2f1df09c8b6c5a8f97) )
+
+ ROM_REGION( 0x2dd * 2, "plds", ROMREGION_ERASE )
+ ROM_LOAD( "eg.u20", 0x000, 0x2dd, NO_DUMP )
+ ROM_LOAD( "eg.u21", 0x2dd, 0x2dd, NO_DUMP )
+
+ ROM_REGION( 0xec, "igs_string", 0 )
+ ROM_LOAD( "jking103a_string.key", 0x00, 0xec, BAD_DUMP CRC(8d288f5e) SHA1(19c184600d80838ef04be8ab29c93d91cf3161c9) ) // TODO: check this
+ROM_END
+
+// IGS PCB NO-0230-1 (IGS025 without original sticker)
+ROM_START( tarzan103m )
+ ROM_REGION( 0x40000, "maincpu", 0 )
+ ROM_LOAD( "tms27c040.u9", 0x00000, 0x40000, CRC(19e3811d) SHA1(ff6b26b7cba84f030649da92eb27892b7c8eb7df) ) // 1ST AND 2ND HALF IDENTICAL, no original label
+ ROM_IGNORE( 0x40000 )
+
+ ROM_REGION( 0x400000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "igs_a2104_cg_v110.u3", 0x00000, 0x400000, CRC(dcbff16f) SHA1(2bf77ef4448c26124c8d8d18bb7ffe4105cfa940) ) // FIXED BITS (xxxxxxx0xxxxxxxx)
+ // empty u2
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "igs_t2105_cg_v110.u11", 0x00000, 0x80000, CRC(1d4be260) SHA1(6374c61735144b3ff54d5e490f26adac4a10b14d) )
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "igs_s2102_sp_v102.u8", 0x00000, 0x80000, CRC(90dda82d) SHA1(67fbc1e8d76b85e124136e2f1df09c8b6c5a8f97) )
+
+ ROM_REGION( 0x2dd * 2, "plds", ROMREGION_ERASE )
+ ROM_LOAD( "eg.u20", 0x000, 0x2dd, NO_DUMP )
+ ROM_LOAD( "eg.u21", 0x2dd, 0x2dd, NO_DUMP )
+
+ ROM_REGION( 0xec, "igs_string", 0 )
+ ROM_LOAD( "tarzan103m_string.key", 0x00, 0xec, CRC(b33f5050) SHA1(900d3c48944dbdd95d9e48d74c355e82e00ac012) )
+ROM_END
+
+
+/***************************************************************************
+
+Happy Skill (Italy, V611IT)
+
+IGS PCB NO-0281
+
+Main CPU is a Zilog Z180 clocked @16MHz (XTAL and EXTAL pins directly tied to a 16MHz crystal)
+OKI MSM6295 (actually a rebadged one marked 'K668 0003') clocked @1MHz, pin 7 is HIGH
+A QFP208 custom ASIC marked 'IGS 031'
+A PLCC68 custom IC marked 'IGS025 A9B2201 9931' (label: '590H/S V300')
+A Ni-MH 3.6V battery as seen in other IGS hardware
+
+***************************************************************************/
+
+ROM_START( happyskl )
+ ROM_REGION( 0x40000, "maincpu", 0 )
+ ROM_LOAD( "v611.u9", 0x00000, 0x40000, CRC(1fb3da98) SHA1(60674af9f5c53298b8ef856f1986c905b9bd7b96) ) // handwritten label
+
+ ROM_REGION( 0x400000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "igs_a2701_cg_v100.u3", 0x000000, 0x400000, CRC(f3756a51) SHA1(8dd4677584f309cec4b068be9f9370a7a172a031) ) // FIXED BITS (xxxxxxx0xxxxxxxx) - 1xxxxxxxxxxxxxxxxxxxxx = 0x00
+ ROM_LOAD( "happyskill_cg.u2", 0x200000, 0x080000, CRC(297a1893) SHA1(9be9e2cdaba1615ea376f3fb7087bf990e68b3b4) ) // FIXED BITS (xxxxxxx0xxxxxxxx)
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "happyskill_text.u11", 0x00000, 0x80000, CRC(c6f51041) SHA1(81a9a03e92c1c67f299113dec9e05ba77395ea31) )
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "igs_s2702_sp_v100.u8", 0x00000, 0x80000, CRC(0ec9b1b5) SHA1(b8c7e068ddf6777a184339e6796be33e442a3df4) )
+
+ ROM_REGION( 0x2dd * 2, "plds", ROMREGION_ERASE )
+ ROM_LOAD( "atf22v10c.u10", 0x000, 0x2dd, NO_DUMP )
+ ROM_LOAD( "et_u20-c.u20", 0x2dd, 0x2dd, NO_DUMP ) // peel22cv10a
+ROM_END
+
+
+// dump confirmed from two PCBs
+ROM_START( cpoker2 )
+ ROM_REGION( 0x40000, "maincpu", 0 )
+ ROM_LOAD( "champion_2_v100a.u9", 0x00000, 0x40000, CRC(8d79eb4d) SHA1(9cad09013f83335ec78c3ff78715bc5d9a989eb7) )
+
+ ROM_REGION( 0x400000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "igs_a2701_cg_v100.u3", 0x00000, 0x400000, CRC(f3756a51) SHA1(8dd4677584f309cec4b068be9f9370a7a172a031) )
+ // U2 (overlay) not populated
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "champion_2_text.u11", 0x00000, 0x80000, CRC(34475c83) SHA1(376ff68d89c25471483b074dcf7542f42f954e67) ) // 1xxxxxxxxxxxxxxxxxx = 0x00
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "igs_s2702_sp_v100.u8", 0x00000, 0x80000, CRC(0ec9b1b5) SHA1(b8c7e068ddf6777a184339e6796be33e442a3df4) ) // same as happyskl
+
+ ROM_REGION( 0x2dd * 2, "plds", ROMREGION_ERASE )
+ ROM_LOAD( "peel22cv10h.u10", 0x000, 0x2dd, NO_DUMP ) // PALCE22V10H-25P
+ ROM_LOAD( "peel22cv10h.u20", 0x2dd, 0x2dd, NO_DUMP ) // PALCE22V10H-25P
+ROM_END
+
+
+/***************************************************************************
+
+Super Poker (V100xD03) / Formosa
+
+PCB NO-0187
+
+CPU Z8018008psc
+IGS017
+IGS025 (labels: B2 / FORMOSA)
+K668 (AD-65)
+UM3567 (YM2413)
+Audio Xtal 3.579545 MHz
+CPU Xtal 16 MHz
+3 x DSW8 (SW1-SW3)
+Push Button (SW4)
+3.6V Battery + Toggle Switch (SW5)
+
+***************************************************************************/
+
+ROM_START( spkrform )
+ ROM_REGION( 0x40000, "maincpu", 0 )
+ ROM_LOAD( "super2in1_v100xd03.u29", 0x00000, 0x40000, CRC(e8f7476c) SHA1(e20241d68d22ee01a65f5d7921fe2291077f081f) )
+
+ ROM_REGION( 0x100000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "super2in1.u26", 0x00000, 0x80000, CRC(af3b1d9d) SHA1(ce84b076939d2c9d959cd430d4f5664f32735d60) ) // FIXED BITS (xxxxxxxx0xxxxxxx)
+ ROM_LOAD( "super2in1.u25", 0x80000, 0x80000, CRC(7ebaf0a0) SHA1(c278810742cd7e1daa89a93fd7fe82495543ccbf) ) // FIXED BITS (xxxxxxxx0xxxxxxx)
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "super2in1.u24", 0x00000, 0x40000, CRC(54d68c49) SHA1(faad78779c3a5b4ecb1c733192d9477ce3324f71) )
+
+ ROM_REGION( 0x40000, "oki", 0 )
+ ROM_LOAD( "super2in1_sp.u28", 0x00000, 0x40000, CRC(33e6089d) SHA1(cd1ad01e92c18bbeab3fe3ea9152f8b0a3eb1b29) )
+
+ ROM_REGION( 0x2dd, "plds", ROMREGION_ERASE )
+ ROM_LOAD( "dn.u18", 0x000, 0x2dd, NO_DUMP )
+
+ ROM_REGION( 0xec, "igs_string", 0 )
+ ROM_LOAD( "spkrform_string.key", 0x00, 0xec, CRC(17a9021a) SHA1(41943e08f9c9be49fc3705e6f2702d504ec6d078) )
+ROM_END
+
+// MADE IN TAIWAN IGS PCB NO-0214-7 (difficult to read due to corrosion, small chance it isn't 100% correct)
+// MC68HC000FN10 with 22 MHz XTAL, IGS031, IGS025 (stickered V9 and JK V302US), IGS029 with 8 MHz XTAL, K668, 2x 8_DIP bank, 11.0592 MHz XTAL
+ROM_START( jking302us )
+ ROM_REGION( 0x80000, "maincpu", 0 )
+ ROM_LOAD16_WORD_SWAP( "jungleking.u28", 0x00000, 0x80000, CRC(d926252e) SHA1(03a3e52cba5e5986b74f57a8798a55b53d73bfd3) )
+
+ ROM_REGION( 0x200000, "igs017_igs031:sprites", 0 )
+ ROM_LOAD( "jungleking_cg_.u22", 0x000000, 0x200000, CRC(4a92fc0e) SHA1(25bdd0b240a1cc80ac737893c417cfe9561623cd) ) // FIXED BITS (xxxxxxx0xxxxxxxx)
+
+ ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
+ ROM_LOAD( "jungeking_text.u26", 0x00000, 0x80000, CRC(45d22af4) SHA1(1dca31c5049a07b234b0266590e4869685bb6e76) )
+
+ ROM_REGION( 0x80000, "oki", 0 )
+ ROM_LOAD( "igs_s2102_sp_v102.u14", 0x00000, 0x80000, CRC(90dda82d) SHA1(67fbc1e8d76b85e124136e2f1df09c8b6c5a8f97) ) // same as the earlier sets with Z180 CPU
+
+ ROM_REGION( 0x600, "plds", ROMREGION_ERASE00 ) // actually chip types unknown
+ ROM_LOAD( "dr_u6.u6", 0x000, 0x117, NO_DUMP )
+ ROM_LOAD( "dr_u7.u7", 0x000, 0x117, NO_DUMP )
+ ROM_LOAD( "dr_u18.u18", 0x000, 0x117, NO_DUMP )
+
+ ROM_REGION( 0xec, "igs_string", ROMREGION_ERASE00 )
+ //ROM_LOAD( "jking302us_string.key", 0x00, 0xec, NO_DUMP )
+ROM_END
+
+} // anonymous namespace
+
+GAME ( 1996, iqblocka, iqblock, iqblocka, iqblocka, igs017_state, init_iqblocka, ROT0, "IGS", "Shuzi Leyuan (China, V127M, gambling)", 0 ) // 數字樂園
+GAME ( 1997, iqblockf, iqblock, iqblockf, iqblockf, igs017_state, init_iqblocka, ROT0, "IGS", "IQ Block (V113FR, gambling)", 0 )
+GAME ( 1997, mgdh, 0, mgdh, mgdh, igs017_state, init_mgdh, ROT0, "IGS", "Manguan Daheng (Taiwan, V125T1)", MACHINE_IMPERFECT_COLORS | MACHINE_UNEMULATED_PROTECTION) // 滿貫大亨, wrong colors in betting screen, game id check (patched out)
+GAME ( 1997, mgdha, mgdh, mgdha, mgdh, igs017_state, init_mgdha, ROT0, "IGS", "Manguan Daheng (Taiwan, V123T1)", 0 ) // 滿貫大亨
+GAME ( 1997, sdmg2, 0, sdmg2, sdmg2, igs017_state, init_sdmg2, ROT0, "IGS", "Chaoji Da Manguan II (China, V765C)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING ) // 超級大滿貫II
+GAME ( 1997, sdmg2754ca, sdmg2, sdmg2, sdmg2, igs017_state, init_sdmg2754ca, ROT0, "IGS", "Chaoji Da Manguan II (China, V754C, set 1)", 0 ) // 超級大滿貫II
+GAME ( 1997, sdmg2754cb, sdmg2, sdmg2, sdmg2, igs017_state, init_sdmg2754cb, ROT0, "IGS", "Chaoji Da Manguan II (China, V754C, set 2)", 0 ) // 超級大滿貫II
+GAME ( 1997, tjsb, 0, tjsb, tjsb, igs017_state, init_tjsb, ROT0, "IGS", "Tian Jiang Shen Bing (China, V137C)", MACHINE_UNEMULATED_PROTECTION ) // 天將神兵, fails the bonus round protection check (if enabled via DSW), see e.g. demo mode
+GAME ( 1998, genius6, 0, genius6, genius6, igs017_state, init_iqblocka, ROT0, "IGS", "Genius 6 (V110F)", 0 ) // shows Chinese text in puzzle game
+GAME ( 1997, genius6a, genius6, genius6, genius6, igs017_state, init_iqblocka, ROT0, "IGS", "Genius 6 (V133F)", 0 ) // clone because it has older copyright year
+GAME ( 1997, genius6b, genius6, genius6, genius6, igs017_state, init_iqblocka, ROT0, "IGS", "Genius 6 (V132F)", 0 ) // "
+GAME ( 1998, mgcs, 0, mgcs, mgcs, igs017_state, init_mgcs, ROT0, "IGS", "Manguan Caishen (China, V103CS)", MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION ) // 满贯财神, finish IGS029 protection
+GAME ( 1998, mgcsa, mgcs, mgcsa, mgcs, igs017_state, init_mgcsa, ROT0, "IGS", "Manguan Caishen (China, V106CS)", MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION ) // 满贯财神, finish IGS029 protection
+GAME ( 1998, mgcsb, mgcs, mgcsb, mgcs, igs017_state, init_mgcsb, ROT0, "IGS", "Manguan Caishen (China, V110C)", MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION )
+GAME ( 1998, lhzb, 0, lhzb2, lhzb, igs017_state, init_lhzb2, ROT0, "IGS", "Long Hu Zhengba (China, VS105M, set 1)", MACHINE_UNEMULATED_PROTECTION ) // 龙虎争霸, finish IGS022 protection
+GAME ( 1998, lhzba, lhzb, lhzb2, lhzb, igs017_state, init_lhzb2, ROT0, "IGS", "Long Hu Zhengba (China, VS105M, set 2)", MACHINE_UNEMULATED_PROTECTION ) // 龙虎争霸, finish IGS022 protection
+GAME ( 1998, lhzb2, 0, lhzb2, lhzb2, igs017_state, init_lhzb2, ROT0, "IGS", "Long Hu Zhengba 2 (China, set 1)", MACHINE_UNEMULATED_PROTECTION ) // 龙虎争霸2, finish IGS022 protection
+GAME ( 1998, lhzb2a, lhzb2, lhzb2a, lhzb2a, igs017_state, init_lhzb2a, ROT0, "IGS", "Long Hu Zhengba 2 (China, VS221M)", 0 ) // 龙虎争霸2
+GAME ( 1998, slqz2, 0, slqz2, slqz2, igs017_state, init_slqz2, ROT0, "IGS", "Shuang Long Qiang Zhu 2 VS (China, VS203J)", MACHINE_UNEMULATED_PROTECTION ) // 双龙抢珠, finish IGS022 protection
+GAME ( 1998, slqz2a, slqz2, slqz2, slqz2, igs017_state, init_slqz2, ROT0, "IGS", "Shuang Long Qiang Zhu 2 VS (China, set 2)", MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION ) // 双龙抢珠, misses program ROM dump, finish IGS022 protection
+GAME ( 1999, tarzanc, 0, tarzan, tarzan, igs017_state, init_tarzanc, ROT0, "IGS", "Tarzan Chuang Tian Guan (China, V109C, set 1)", 0 ) // 泰山闯天关
+GAME ( 1999, tarzan, tarzanc, tarzan, tarzan, igs017_state, init_tarzan, ROT0, "IGS", "Tarzan Chuang Tian Guan (China, V109C, set 2)", MACHINE_NOT_WORKING ) // missing sprites and sound rom, imperfect tiles decryption
+GAME ( 1999, tarzana, tarzanc, tarzan, tarzan, igs017_state, init_tarzana, ROT0, "IGS", "Tarzan (V107)", MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION ) // missing IGS029 protection, missing sprites and sound rom
+GAME ( 1999, tarzanb, tarzanc, tarzan, tarzan, igs017_state, init_tarzanc, ROT0, "IGS", "Tarzan Chuang Tian Guan (China, V110)", 0 )
+GAME ( 2000, sdmg2p, 0, sdmg2p, sdmg2p, igs017_state, init_sdmg2p, ROT0, "IGS", "Maque Wangchao / Chaoji Da Manguan 2 - Jiaqiang Ban (China, V100C)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING ) // 麻雀王朝 / 超級大滿貫 2 -加強版 protection kicks in after starting game, hopper isn't hooked up correctly
+GAMEL( 2000?, starzan, 0, starzan, starzan, igs017_state, init_starzan, ROT0, "IGS (G.F. Gioca license)", "Super Tarzan (Italy, V100I)", 0, layout_igsslot )
+GAMEL( 2000?, jking103a, starzan, starzan, starzan, igs017_state, init_jking103a, ROT0, "IGS", "Jungle King (V103A)", 0, layout_igsslot )
+GAMEL( 1999, jking200pr, starzan, starzan, tarzan202fa, igs017_state, init_jking200pr, ROT0, "IGS", "Jungle King (V200PR)", 0, layout_igsslot )
+GAME ( 1999?, tarzan103m, tarzanc, starzan, tarzan103m, igs017_state, init_starzan, ROT0, "IGS", "Tarzan (V103M)", 0 )
+GAMEL( 1999?, tarzan202fa, tarzanc, starzan, tarzan202fa, igs017_state, init_jking103a, ROT0, "IGS", "Tarzan (V202FA)", 0, layout_igsslot )
+GAMEL( 2000?, happyskl, 0, happyskl, happyskl, igs017_state, init_happyskl, ROT0, "IGS", "Happy Skill (Italy, V611IT)", 0, layout_igspoker )
+GAMEL( 2000?, cpoker2, 0, cpoker2, cpoker2, igs017_state, init_cpoker2, ROT0, "IGS", "Champion Poker 2 (V100A)", 0, layout_igspoker )
+GAME ( 2000?, spkrform, spk306us, spkrform, spkrform, igs017_state, init_spkrform, ROT0, "IGS", "Super Poker (V100xD03) / Formosa", MACHINE_UNEMULATED_PROTECTION ) // poker game enabling forced with a patch. Parent spk306us in driver spoker.cpp
+GAME ( 2000?, jking302us, 0, jking302us, starzan, igs017_state, init_jking302us, ROT0, "IGS", "Jungle King (V302US)", MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION ) // missing IGS025 and IGS029 protection