summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/nes/mmc3_clones.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/nes/mmc3_clones.cpp')
-rw-r--r--src/devices/bus/nes/mmc3_clones.cpp2588
1 files changed, 2588 insertions, 0 deletions
diff --git a/src/devices/bus/nes/mmc3_clones.cpp b/src/devices/bus/nes/mmc3_clones.cpp
new file mode 100644
index 00000000000..4a806d0fde2
--- /dev/null
+++ b/src/devices/bus/nes/mmc3_clones.cpp
@@ -0,0 +1,2588 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli
+/***********************************************************************************************************
+
+
+ NES/Famicom cartridge emulation for MMC-3 clone PCBs
+
+
+ Here we emulate several pirate PCBs based on MMC-3 boards
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "mmc3_clones.h"
+
+
+#ifdef NES_PCB_DEBUG
+#define VERBOSE 1
+#else
+#define VERBOSE 0
+#endif
+
+#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+
+
+//-------------------------------------------------
+// constructor
+//-------------------------------------------------
+
+const device_type NES_NITRA = &device_creator<nes_nitra_device>;
+const device_type NES_KS7057 = &device_creator<nes_ks7057_device>;
+const device_type NES_SBROS11 = &device_creator<nes_sbros11_device>;
+const device_type NES_MALISB = &device_creator<nes_malisb_device>;
+const device_type NES_FAMILY4646 = &device_creator<nes_family4646_device>;
+const device_type NES_PIKAY2K = &device_creator<nes_pikay2k_device>;
+const device_type NES_8237 = &device_creator<nes_8237_device>;
+const device_type NES_SG_LIONK = &device_creator<nes_sglionk_device>;
+const device_type NES_SG_BOOG = &device_creator<nes_sgboog_device>;
+const device_type NES_KASING = &device_creator<nes_kasing_device>;
+const device_type NES_KAY = &device_creator<nes_kay_device>;
+const device_type NES_H2288 = &device_creator<nes_h2288_device>;
+const device_type NES_6035052 = &device_creator<nes_6035052_device>;
+const device_type NES_TXC_TW = &device_creator<nes_txc_tw_device>;
+const device_type NES_KOF97 = &device_creator<nes_kof97_device>;
+const device_type NES_KOF96 = &device_creator<nes_kof96_device>;
+const device_type NES_SF3 = &device_creator<nes_sf3_device>;
+const device_type NES_GOUDER = &device_creator<nes_gouder_device>;
+const device_type NES_SA9602B = &device_creator<nes_sa9602b_device>;
+const device_type NES_SACHEN_SHERO = &device_creator<nes_sachen_shero_device>;
+//const device_type NES_A9746 = &device_creator<nes_a9746_device>;
+
+const device_type NES_FK23C = &device_creator<nes_fk23c_device>;
+const device_type NES_FK23CA = &device_creator<nes_fk23ca_device>;
+const device_type NES_S24IN1SC03 = &device_creator<nes_s24in1sc03_device>;
+const device_type NES_BMC_15IN1 = &device_creator<nes_bmc_15in1_device>;
+const device_type NES_BMC_SBIG7 = &device_creator<nes_bmc_sbig7_device>;
+const device_type NES_BMC_HIK8 = &device_creator<nes_bmc_hik8_device>;
+const device_type NES_BMC_HIK4 = &device_creator<nes_bmc_hik4_device>;
+const device_type NES_BMC_MARIO7IN1 = &device_creator<nes_bmc_mario7in1_device>;
+const device_type NES_BMC_GOLD7IN1 = &device_creator<nes_bmc_gold7in1_device>;
+const device_type NES_BMC_GC6IN1 = &device_creator<nes_bmc_gc6in1_device>;
+const device_type NES_BMC_411120C = &device_creator<nes_bmc_411120c_device>;
+const device_type NES_BMC_830118C = &device_creator<nes_bmc_830118c_device>;
+const device_type NES_PJOY84 = &device_creator<nes_pjoy84_device>;
+
+
+nes_nitra_device::nes_nitra_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_NITRA, "NES Cart Nitra PCB", tag, owner, clock, "nes_nitra", __FILE__)
+{
+}
+
+nes_ks7057_device::nes_ks7057_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_KS7057, "NES Cart KS-7057 PCB", tag, owner, clock, "nes_ks7057", __FILE__)
+{
+}
+
+nes_sbros11_device::nes_sbros11_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_SBROS11, "NES Cart SMB 11 PCB", tag, owner, clock, "nes_smb11", __FILE__)
+{
+}
+
+nes_malisb_device::nes_malisb_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_MALISB, "NES Cart Mali Spash Bomb PCB", tag, owner, clock, "nes_malisb", __FILE__)
+{
+}
+
+nes_family4646_device::nes_family4646_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_FAMILY4646, "NES Cart BMC-FAMILY-4646 PCB", tag, owner, clock, "nes_family4646", __FILE__)
+{
+}
+
+nes_pikay2k_device::nes_pikay2k_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_PIKAY2K, "NES Cart PIKACHU Y2K PCB", tag, owner, clock, "nes_pikay2k", __FILE__)
+{
+}
+
+nes_8237_device::nes_8237_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_8237, "NES Cart UNL-8237 PCB", tag, owner, clock, "nes_8237", __FILE__)
+{
+}
+
+nes_sglionk_device::nes_sglionk_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_SG_LIONK, "NES Cart SuperGame Lion King PCB", tag, owner, clock, "nes_sglionk", __FILE__)
+{
+}
+
+nes_sgboog_device::nes_sgboog_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_SG_BOOG, "NES Cart SuperGame BoogerMan PCB", tag, owner, clock, "nes_sgbooger", __FILE__)
+{
+}
+
+nes_kasing_device::nes_kasing_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_KASING, "NES Cart Kasing PCB", tag, owner, clock, "nes_kasing", __FILE__)
+{
+}
+
+nes_kay_device::nes_kay_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_KAY, "NES Cart KAY PCB", tag, owner, clock, "nes_kay", __FILE__)
+{
+}
+
+nes_h2288_device::nes_h2288_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_H2288, "NES Cart H-2288 PCB", tag, owner, clock, "nes_h2288", __FILE__)
+{
+}
+
+nes_6035052_device::nes_6035052_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_6035052, "NES Cart UNL-603-5052 PCB", tag, owner, clock, "nes_6035052", __FILE__)
+{
+}
+
+nes_txc_tw_device::nes_txc_tw_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_TXC_TW, "NES Cart TXC Thunder Warrior PCB", tag, owner, clock, "nes_txc_tw", __FILE__)
+{
+}
+
+nes_kof97_device::nes_kof97_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_KOF97, "NES Cart KOF 97 PCB", tag, owner, clock, "nes_kof97", __FILE__)
+{
+}
+
+nes_kof96_device::nes_kof96_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_KOF96, "NES Cart KOF 96 PCB", tag, owner, clock, "nes_kof96", __FILE__)
+{
+}
+
+nes_sf3_device::nes_sf3_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_SF3, "NES Cart Super Fighter III PCB", tag, owner, clock, "nes_sf3", __FILE__)
+{
+}
+
+nes_gouder_device::nes_gouder_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_GOUDER, "NES Cart Gouder PCB", tag, owner, clock, "nes_gouder", __FILE__)
+{
+}
+
+nes_sa9602b_device::nes_sa9602b_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_SA9602B, "NES Cart SA-9602B PCB", tag, owner, clock, "nes_sa9602b", __FILE__)
+{
+}
+
+nes_sachen_shero_device::nes_sachen_shero_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_SACHEN_SHERO, "NES Cart Street Hero PCB", tag, owner, clock, "nes_shero", __FILE__)
+{
+}
+
+//nes_a9746_device::nes_a9746_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+// : nes_txrom_device(mconfig, NES_A9746, "NES Cart A-9746 PCB", tag, owner, clock, "nes_bmc_a9746", __FILE__)
+//{
+//}
+
+nes_fk23c_device::nes_fk23c_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
+ : nes_txrom_device(mconfig, type, name, tag, owner, clock, shortname, source)
+{
+}
+
+nes_fk23c_device::nes_fk23c_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_FK23C, "NES Cart FK23C PCB", tag, owner, clock, "nes_fk23c", __FILE__)
+{
+}
+
+nes_fk23ca_device::nes_fk23ca_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_fk23c_device(mconfig, NES_FK23CA, "NES Cart FK23CA PCB", tag, owner, clock, "nes_fk23ca", __FILE__)
+{
+}
+
+nes_s24in1sc03_device::nes_s24in1sc03_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_S24IN1SC03, "NES Cart Super 24 in 1 SC-03 PCB", tag, owner, clock, "nes_s24in1c03", __FILE__)
+{
+}
+
+nes_bmc_15in1_device::nes_bmc_15in1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_15IN1, "NES Cart BMC 15 in 1 PCB", tag, owner, clock, "nes_bmc_15in1", __FILE__)
+{
+}
+
+nes_bmc_sbig7_device::nes_bmc_sbig7_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_SBIG7, "NES Cart BMC Super BIG 7 in 1 PCB", tag, owner, clock, "nes_bmc_sbit7", __FILE__)
+{
+}
+
+nes_bmc_hik8_device::nes_bmc_hik8_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_HIK8, "NES Cart BMC Super HIK 8 in 1 PCB", tag, owner, clock, "nes_bmc_hik8", __FILE__)
+{
+}
+
+nes_bmc_hik4_device::nes_bmc_hik4_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_HIK4, "NES Cart BMC Super HIK 4 in 1 PCB", tag, owner, clock, "nes_bmc_hik4", __FILE__)
+{
+}
+
+nes_bmc_mario7in1_device::nes_bmc_mario7in1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_MARIO7IN1, "NES Cart BMC Mario 7 in 1 PCB", tag, owner, clock, "nes_bmc_mario7in1", __FILE__)
+{
+}
+
+nes_bmc_gold7in1_device::nes_bmc_gold7in1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_GOLD7IN1, "NES Cart BMC Golden 7 in 1 PCB", tag, owner, clock, "nes_bmc_gold7in1", __FILE__)
+{
+}
+
+nes_bmc_gc6in1_device::nes_bmc_gc6in1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_GC6IN1, "NES Cart BMC Golden Card 6 in 1 PCB", tag, owner, clock, "nes_bmc_gc6in1", __FILE__)
+{
+}
+
+nes_bmc_411120c_device::nes_bmc_411120c_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_411120C, "NES Cart BMC 411120C PCB", tag, owner, clock, "nes_bmc_411120c", __FILE__)
+{
+}
+
+nes_bmc_830118c_device::nes_bmc_830118c_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_BMC_830118C, "NES Cart BMC 830118C PCB", tag, owner, clock, "nes_bmc_830118c", __FILE__)
+{
+}
+
+nes_pjoy84_device::nes_pjoy84_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_PJOY84, "NES Cart Powerjoy 84 PCB", tag, owner, clock, "nes_pjoy84", __FILE__)
+{
+}
+
+
+
+void nes_family4646_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ mmc3_common_initialize(0x1f, 0xff, 0);
+}
+
+void nes_pikay2k_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_pikay2k_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ m_reg[0] = 0xff;
+ m_reg[1] = 0;
+ mmc3_common_initialize(0xff, 0xff, 0);
+}
+
+void nes_8237_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+ save_item(NAME(m_cd_enable));
+}
+
+void nes_8237_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ m_reg[0] = 0;
+ m_reg[1] = 0;
+ m_reg[2] = 0;
+ m_cd_enable = 0;
+ mmc3_common_initialize(0xff, 0xff, 0);
+}
+
+void nes_sglionk_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+ save_item(NAME(m_reg_enabled));
+}
+
+void nes_sglionk_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ m_reg = m_reg_enabled = 0;
+ mmc3_common_initialize(0xff, 0xff, 0);
+}
+
+void nes_sgboog_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+ save_item(NAME(m_mode));
+}
+
+void nes_sgboog_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ m_mode = 0x04;
+ m_reg[0] = 0x00;
+ m_reg[1] = 0xff;
+ m_reg[2] = 0;
+ mmc3_common_initialize(0x1f, 0xff, 0);
+ set_prg(m_prg_base, m_prg_mask);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+}
+
+void nes_kasing_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_kasing_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ m_reg = 0;
+ mmc3_common_initialize(0xff, 0xff, 0);
+}
+
+
+void nes_kay_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_low_reg));
+ save_item(NAME(m_reg));
+}
+
+void nes_kay_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ memset(m_reg, 0, sizeof(m_reg));
+ m_low_reg = 0;
+ mmc3_common_initialize(0xff, 0xff, 0);
+}
+
+
+void nes_h2288_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_h2288_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ m_reg[0] = 0;
+ m_reg[1] = 0;
+ mmc3_common_initialize(0xff, 0xff, 0);
+}
+
+void nes_6035052_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_prot));
+}
+
+void nes_6035052_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ mmc3_common_initialize(0xff, 0xff, 0);
+
+ m_prot = 0;
+}
+
+void nes_kof96_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_kof96_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ memset(m_reg, 0, sizeof(m_reg));
+ mmc3_common_initialize(0xff, 0xff, 0);
+}
+
+void nes_gouder_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_gouder_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ memset(m_reg, 0, sizeof(m_reg));
+ mmc3_common_initialize(0xff, 0xff, 0);
+}
+
+void nes_sa9602b_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+ save_item(NAME(m_prg_chip));
+}
+
+void nes_sa9602b_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ m_reg = 0;
+ m_prg_chip = 0;
+ mmc3_common_initialize(0x1ff, 0xff, 0); // 1.5MB of PRG-ROM, no CHR-ROM but 32K CHR-RAM
+}
+
+void nes_sachen_shero_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_sachen_shero_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ m_reg = 0;
+ mmc3_common_initialize(0xff, 0x1ff, 0);
+}
+
+void nes_fk23c_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+ save_item(NAME(m_mmc_cmd1));
+}
+
+void nes_fk23c_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ m_mmc_cmd1 = 0;
+ m_reg[0] = 4;
+ m_reg[1] = 0xff;
+ m_reg[2] = m_reg[3] = 0;
+ m_reg[4] = m_reg[5] = m_reg[6] = m_reg[7] = 0xff;
+ mmc3_common_initialize(0xff, 0xff, 0);
+ fk23c_set_prg();
+ fk23c_set_chr();
+
+}
+
+void nes_fk23ca_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ m_mmc_cmd1 = 0;
+ m_reg[0] = m_reg[1] = m_reg[2] = m_reg[3] = 0;
+ m_reg[4] = m_reg[5] = m_reg[6] = m_reg[7] = 0xff;
+ mmc3_common_initialize(0xff, 0xff, 0);
+ fk23c_set_prg();
+ fk23c_set_chr();
+}
+
+void nes_s24in1sc03_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_s24in1sc03_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ m_reg[0] = 0x24;
+ m_reg[1] = 0x9f;
+ m_reg[2] = 0;
+ mmc3_common_initialize(0xff, 0xff, 0);
+}
+
+void nes_bmc_15in1_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ mmc3_common_initialize(0x1f, 0xff, 0);
+ m_prg_base = 0x10; // this board has a diff prg_base
+ set_prg(m_prg_base, m_prg_mask);
+}
+
+void nes_bmc_sbig7_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ mmc3_common_initialize(0x0f, 0x7f, 0);
+}
+
+void nes_bmc_hik8_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+ save_item(NAME(m_count));
+}
+
+void nes_bmc_hik8_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ m_count = 0;
+ memset(m_reg, 0, sizeof(m_reg));
+ mmc3_common_initialize(0x3f, 0xff, 0);
+}
+
+void nes_bmc_hik4_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ mmc3_common_initialize(0x0f, 0x7f, 0);
+}
+
+void nes_bmc_mario7in1_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg_written));
+}
+
+void nes_bmc_mario7in1_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ m_reg_written = 0;
+ mmc3_common_initialize(0x1f, 0xff, 0);
+}
+
+void nes_bmc_gold7in1_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg_written));
+}
+
+void nes_bmc_gold7in1_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ m_reg_written = 0;
+ mmc3_common_initialize(0x1f, 0xff, 0);
+}
+
+void nes_bmc_gc6in1_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_bmc_gc6in1_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ m_reg[0] = 0x00;
+ m_reg[1] = 0xff;
+ m_reg[2] = 0x03;
+ m_reg[3] = 0;
+ mmc3_common_initialize(0xff, 0xff, 0);
+ set_prg(m_prg_base, m_prg_mask);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+}
+
+void nes_bmc_411120c_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_bmc_411120c_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ m_reg = 0;
+ mmc3_common_initialize(0x7f, 0x7f, 0);
+}
+
+void nes_bmc_830118c_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_bmc_830118c_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ m_reg = 0;
+ mmc3_common_initialize(0x7f, 0x7f, 0);
+}
+
+void nes_pjoy84_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_pjoy84_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ memset(m_reg, 0, sizeof(m_reg));
+ set_base_mask();
+ mmc3_common_initialize(m_prg_mask, m_chr_mask, 0);
+}
+
+
+
+/*-------------------------------------------------
+ mapper specific handlers
+ -------------------------------------------------*/
+
+/*-------------------------------------------------
+
+ Bootleg Board by Nitra
+
+ Games: Time Diver Avenger
+
+ This acts basically like a MMC3 with different use of write
+ address.
+
+ iNES: mapper 250
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_nitra_device::write_h)
+{
+ LOG_MMC(("nitra write_h, offset: %04x, data: %02x\n", offset, data));
+
+ txrom_write(space, (offset & 0x6000) | ((offset & 0x400) >> 10), offset & 0xff, mem_mask);
+}
+
+/*-------------------------------------------------
+
+ Board UNL-KS7057
+
+ Games: Street Fighter VI / Fight Street VI
+
+ MMC3 clone (identical, but for switched address lines)
+
+ In MESS: Supported
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_ks7057_device::write_h)
+{
+ LOG_MMC(("ks7057 write_h, offset: %04x, data: %02x\n", offset, data));
+
+ offset = (BIT(offset, 0) << 1) | BIT(offset, 1) | (offset & ~0x03);
+ txrom_write(space, offset, data, mem_mask);
+}
+
+/*-------------------------------------------------
+
+ BTL-SUPERBROS11
+
+ Games: Super Mario Bros. 11, Super Mario Bros. 17
+
+ This acts basically like a MMC3 with different use of write
+ address.
+
+ iNES: mapper 196
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_sbros11_device::write_h)
+{
+ LOG_MMC(("smb11 write_h, offset: %04x, data: %02x\n", offset, data));
+
+ txrom_write(space, (offset & 0x6000) | ((offset & 0x04) >> 2), data, mem_mask);
+}
+
+/*-------------------------------------------------
+
+ UNL-MALISB
+
+ Games: Super Mali Bros Splash Bomb
+
+ This is very similar to mapper 196, but with additional
+ data bit swap.
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+void nes_malisb_device::prg_cb(int start, int bank)
+{
+ bank = (bank & 3) | ((bank & 8) >> 1) | ((bank & 4) << 1);
+ prg8_x(start, bank);
+}
+
+void nes_malisb_device::chr_cb(int start, int bank, int source)
+{
+ bank = (bank & 0xdd) | ((bank & 0x20) >> 4) | ((bank & 2) << 4);
+ chr1_x(start, bank, source);
+}
+
+WRITE8_MEMBER(nes_malisb_device::write_h)
+{
+ LOG_MMC(("malisb write_h, offset: %04x, data: %02x\n", offset, data));
+
+ if (offset > 0x4000)
+ txrom_write(space, (offset & 0xfffe) | ((offset & 0x04) >> 2) | ((offset & 0x08) >> 3), data, mem_mask);
+ else
+ txrom_write(space, (offset & 0xfffe) | ((offset & 0x08) >> 3), data, mem_mask);
+}
+
+/*-------------------------------------------------
+
+ BMC-FAMILY-4646B
+
+ Known Boards: Unknown Multigame Bootleg Board (4646B)
+ Games: 2 in 1 - Family Kid & Aladdin 4
+
+ MMC3 clone
+
+ iNES: mapper 134
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_family4646_device::write_m)
+{
+ LOG_MMC(("family4646 write_m, offset: %04x, data: %02x\n", offset, data));
+
+ if (offset == 0x01)
+ {
+ m_prg_base = (data & 0x02) << 4;
+ m_prg_mask = 0x1f;
+ m_chr_base = (data & 0x20) << 3;
+ m_chr_mask = 0xff;
+ set_prg(m_prg_base, m_prg_mask);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
+}
+
+/*-------------------------------------------------
+
+ BTL-PIKACHUY2K
+
+ Games: Pikachu Y2k
+
+ iNES: mapper 254
+
+ In MESS:
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_pikay2k_device::write_h)
+{
+ LOG_MMC(("pikay2k write_h, offset: %04x, data: %02x\n", offset, data));
+
+ switch (offset & 0x6001)
+ {
+ case 0x2001:
+ m_reg[1] = data;
+ break;
+
+ case 0x2000:
+ m_reg[0] = 0;
+ default:
+ txrom_write(space, offset, data, mem_mask);
+ break;
+ }
+}
+
+// strange WRAM usage: it is protected at start, and gets unprotected after the first write to 0xa000
+WRITE8_MEMBER(nes_pikay2k_device::write_m)
+{
+ LOG_MMC(("pikay2k write_m, offset: %04x, data: %02x\n", offset, data));
+
+ m_prgram[offset & 0x1fff] = data;
+}
+
+READ8_MEMBER(nes_pikay2k_device::read_m)
+{
+ LOG_MMC(("pikay2k read_m, offset: %04x\n", offset));
+
+ return m_prgram[offset & 0x1fff] ^ (m_reg[0] & m_reg[1]);
+}
+
+/*-------------------------------------------------
+
+ Board UNL-8237
+
+ Games: Pocahontas 2
+
+ MMC3 clone
+
+ In MESS: Supported
+
+ -------------------------------------------------*/
+
+void nes_8237_device::prg_cb(int start, int bank)
+{
+ if (!(m_reg[0] & 0x80))
+ prg8_x(start, bank);
+}
+
+void nes_8237_device::chr_cb(int start, int bank, int source)
+{
+ bank |= ((m_reg[1] << 6) & 0x100);
+ chr1_x(start, bank, source);
+}
+
+WRITE8_MEMBER(nes_8237_device::write_l)
+{
+ LOG_MMC(("unl_8237 write_l, offset: %04x, data: %02x\n", offset, data));
+ offset += 0x100;
+
+ if (offset == 0x1000)
+ {
+ m_reg[0] = data;
+ if (m_reg[0] & 0x80)
+ {
+ if (m_reg[0] & 0x20)
+ prg32((m_reg[0] & 0x0f) >> 1);
+ else
+ {
+ prg16_89ab(m_reg[0] & 0x1f);
+ prg16_cdef(m_reg[0] & 0x1f);
+ }
+ }
+ else
+ set_prg(m_prg_base, m_prg_mask);
+ }
+
+ if (offset == 0x1001)
+ {
+ m_reg[1] = data;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
+
+ if (offset == 0x1007)
+ {
+ m_reg[2] = data & 0x07; // this selects different permutations for addresses and regs (to be implemented)
+ }
+}
+
+WRITE8_MEMBER(nes_8237_device::write_h)
+{
+ static const UINT8 conv_table[8] = {0, 2, 6, 1, 7, 3, 4, 5};
+ LOG_MMC(("unl_8237 write_h, offset: %04x, data: %02x\n", offset, data));
+
+ switch (offset & 0x7000)
+ {
+ case 0x0000:
+ case 0x1000:
+ set_nt_mirroring((data | (data >> 7)) & 0x01 ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ break;
+
+ case 0x2000:
+ case 0x3000:
+ m_cd_enable = 1;
+ data = (data & 0xc0) | conv_table[data & 0x07];
+ txrom_write(space, 0x0000, data, mem_mask);
+ break;
+
+ case 0x4000:
+ case 0x5000:
+ if (m_cd_enable)
+ {
+ m_cd_enable = 0;
+ txrom_write(space, 0x0001, data, mem_mask);
+ }
+ break;
+
+ case 0x6000:
+ break;
+
+ case 0x7000:
+ txrom_write(space, 0x6001, data, mem_mask);
+ txrom_write(space, 0x4000, data, mem_mask);
+ txrom_write(space, 0x4001, data, mem_mask);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ Bootleg Board by Super Game
+
+ Games: The Lion King
+
+ MMC3 clone.
+
+ iNES: mapper 114
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_sglionk_device::write_m)
+{
+ LOG_MMC(("sglionk write_m, offset: %04x, data: %02x\n", offset, data));
+
+ m_reg = data;
+
+ if (m_reg & 0x80)
+ {
+ prg16_89ab(data & 0x1f);
+ prg16_cdef(data & 0x1f);
+ }
+ else
+ set_prg(m_prg_base, m_prg_mask);
+
+}
+
+WRITE8_MEMBER(nes_sglionk_device::write_h)
+{
+ static const UINT8 conv_table[8] = {0, 3, 1, 5, 6, 7, 2, 4};
+ LOG_MMC(("sglionk write_h, offset: %04x, data: %02x\n", offset, data));
+
+ if (offset < 0x6000)
+ {
+ switch (offset & 0x6000)
+ {
+ case 0x0000:
+ set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ break;
+ case 0x2000:
+ m_reg_enabled = 1;
+ data = (data & 0xc0) | conv_table[data & 0x07];
+ txrom_write(space, 0x0000, data, mem_mask);
+ break;
+ case 0x4000:
+ if (m_reg_enabled && (m_reg & 0x80) == 0)
+ {
+ m_reg_enabled = 0;
+ txrom_write(space, 0x0001, data, mem_mask);
+ }
+ break;
+ }
+ }
+ else
+ {
+ switch (offset & 0x03)
+ {
+ case 0x02:
+ txrom_write(space, 0x6000, data, mem_mask);
+ break;
+ case 0x03:
+ txrom_write(space, 0x6001, data, mem_mask);
+ txrom_write(space, 0x4000, data, mem_mask);
+ txrom_write(space, 0x4001, data, mem_mask);
+ break;
+ }
+ }
+}
+
+/*-------------------------------------------------
+
+ Bootleg Board by Super Game
+
+ Games: Boogerman, Mortal Kombat III
+
+ MMC3 clone. Also, it probably needs a hack to support both
+ variants (Boogerman & MK3).
+
+ iNES: mapper 215
+
+ In MESS: Preliminary support.
+
+ -------------------------------------------------*/
+
+void nes_sgboog_device::prg_cb(int start, int bank)
+{
+ if (!(m_reg[0] & 0x80)) // if this is != 0 we should never even arrive here
+ {
+ if (m_reg[1] & 0x08)
+ bank = (bank & 0x1f) | 0x20;
+ else
+ bank = (bank & 0x0f) | (m_reg[1] & 0x10);
+
+ prg8_x(start, bank);
+ }
+}
+
+void nes_sgboog_device::chr_cb(int start, int bank, int source)
+{
+ if ((m_reg[1] & 0x04))
+ bank |= 0x100;
+ else
+ bank = (bank & 0x7f) | ((m_reg[1] & 0x10) << 3);
+
+ chr1_x(start, bank, source);
+}
+
+void nes_sgboog_device::set_prg(int prg_base, int prg_mask)
+{
+ if (m_reg[0] & 0x80)
+ {
+ prg16_89ab((m_reg[0] & 0xf0) | (m_reg[1] & 0x10));
+ prg16_cdef((m_reg[0] & 0xf0) | (m_reg[1] & 0x10));
+ }
+ else
+ {
+ // here standard MMC3 bankswitch
+ UINT8 prg_flip = (m_latch & 0x40) ? 2 : 0;
+
+ prg_cb(0, prg_base | (m_mmc_prg_bank[0 ^ prg_flip] & prg_mask));
+ prg_cb(1, prg_base | (m_mmc_prg_bank[1] & prg_mask));
+ prg_cb(2, prg_base | (m_mmc_prg_bank[2 ^ prg_flip] & prg_mask));
+ prg_cb(3, prg_base | (m_mmc_prg_bank[3] & prg_mask));
+ }
+}
+
+WRITE8_MEMBER(nes_sgboog_device::write_l)
+{
+ LOG_MMC(("sgboog write_l, offset: %04x, data: %02x\n", offset, data));
+ offset += 0x100;
+
+ if (offset == 0x1000)
+ {
+ m_reg[0] = data;
+ set_prg(m_prg_base, m_prg_mask);
+ }
+ else if (offset == 0x1001)
+ {
+ m_reg[1] = data;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
+ else if (offset == 0x1007)
+ {
+ m_latch = 0;
+ m_mode = data;
+ set_prg(m_prg_base, m_prg_mask);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
+}
+
+WRITE8_MEMBER(nes_sgboog_device::write_m)
+{
+ LOG_MMC(("sgboog write_m, offset: %04x, data: %02x\n", offset, data));
+
+ if (offset == 0x0000)
+ {
+ m_reg[0] = data;
+ set_prg(m_prg_base, m_prg_mask);
+ }
+ else if (offset == 0x0001)
+ {
+ m_reg[1] = data;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
+ else if (offset == 0x0007)
+ {
+ m_latch = 0;
+ m_mode = data;
+ set_prg(m_prg_base, m_prg_mask);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
+}
+
+WRITE8_MEMBER(nes_sgboog_device::write_h)
+{
+ static const UINT8 conv_table[8] = {0,2,5,3,6,1,7,4};
+ LOG_MMC(("sgboog write_h, offset: %04x, data: %02x\n", offset, data));
+
+ if (m_mode)
+ {
+ switch (offset & 0x6001)
+ {
+ case 0x0000:
+ break;
+
+ case 0x0001:
+ if (m_reg[2] && ((m_reg[0] & 0x80) == 0 || (m_latch & 0x07) < 6)) // if we use the prg16 banks and cmd=6,7 DON'T enter!
+ {
+ m_reg[2] = 0;
+ txrom_write(space, 0x0001, data, mem_mask);
+ }
+ break;
+
+ case 0x2000:
+ data = (data & 0xc0) | conv_table[data & 0x07];
+ m_reg[2] = 1;
+ txrom_write(space, 0x0000, data, mem_mask);
+ break;
+
+ case 0x4000:
+ set_nt_mirroring(((data >> 7) | data) & 0x01 ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ break;
+
+ case 0x4001:
+ txrom_write(space, 0x6001, data, mem_mask);
+ break;
+
+ case 0x6001:
+ txrom_write(space, 0x4000, data, mem_mask);
+ txrom_write(space, 0x4001, data, mem_mask);
+ break;
+
+ default:
+ txrom_write(space, offset, data, mem_mask);
+ break;
+ }
+ }
+ else
+ txrom_write(space, offset, data, mem_mask);
+}
+
+/*-------------------------------------------------
+
+ Bootleg Board by Kasing
+
+ Games: AV Jiu Ji Mahjong, Bao Qing Tian, Thunderbolt 2,
+ Shisen Mahjong 2
+
+ MMC3 clone
+
+ iNES: mapper 115
+
+ In MESS: Supported
+
+ -------------------------------------------------*/
+
+void nes_kasing_device::prg_cb(int start, int bank)
+{
+ if (BIT(m_reg, 7))
+ prg32(m_reg >> 1);
+ else
+ prg8_x(start, bank);
+}
+
+WRITE8_MEMBER(nes_kasing_device::write_m)
+{
+ LOG_MMC(("kasing write_m, offset: %04x, data: %02x\n", offset, data));
+
+ switch (offset & 0x01)
+ {
+ case 0x00:
+ m_reg = data;
+ set_prg(m_prg_base, m_prg_mask);
+ break;
+ case 0x01:
+ m_chr_base = (data & 0x01) ? 0x100 : 0x000;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ Bootleg Board by Kay (for Panda Prince)
+
+ Games: The Panda Prince, Sonic 3d Blast 6, SFZ2 '97, YuYu '97
+ (and its title hack MK6), UMK3, Super Lion King 2
+
+ MMC3 clone. This is basically KOF96 board + protection
+
+ iNES: mapper 121
+
+ In MESS: Most game works, with some graphical issues.
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_kay_device::write_l)
+{
+ LOG_MMC(("kay write_l, offset: %04x, data: %02x\n", offset, data));
+ offset += 0x100;
+
+ if (offset >= 0x1000)
+ {
+ switch (data & 0x03)
+ {
+ case 0x00:
+ case 0x01:
+ m_low_reg = 0x83;
+ break;
+ case 0x02:
+ m_low_reg = 0x42;
+ break;
+ case 0x03:
+ m_low_reg = 0x00;
+ break;
+ }
+ }
+}
+
+READ8_MEMBER(nes_kay_device::read_l)
+{
+ LOG_MMC(("kay read_l, offset: %04x\n", offset));
+ offset += 0x100;
+
+ if (offset >= 0x1000)
+ return m_low_reg;
+ else
+ return 0xff;
+}
+
+void nes_kay_device::update_regs()
+{
+ switch (m_reg[5] & 0x3f)
+ {
+ case 0x20:
+ case 0x29:
+ case 0x2b:
+ case 0x3f:
+ m_reg[7] = 1;
+ m_reg[1] = m_reg[6];
+ break;
+ case 0x26:
+ m_reg[7] = 0;
+ m_reg[1] = m_reg[6];
+ break;
+ case 0x2c:
+ m_reg[7] = 1;
+ if (m_reg[6])
+ m_reg[1] = m_reg[6];
+ break;
+
+ case 0x28:
+ m_reg[7] = 0;
+ m_reg[2] = m_reg[6];
+ break;
+
+ case 0x2a:
+ m_reg[7] = 0;
+ m_reg[3] = m_reg[6];
+ break;
+
+ case 0x2f:
+ break;
+
+ default:
+ m_reg[5] = 0;
+ break;
+ }
+}
+
+void nes_kay_device::prg_cb(int start, int bank)
+{
+ if (m_reg[5] & 0x3f)
+ {
+ prg8_x(start, bank & 0x3f);
+ prg8_ef(m_reg[1]);
+ prg8_cd(m_reg[2]);
+ prg8_ab(m_reg[3]);
+ }
+ else
+ prg8_x(start, bank & 0x3f);
+}
+
+void nes_kay_device::chr_cb(int start, int bank, int source)
+{
+ UINT8 chr_page = (m_latch & 0x80) >> 5;
+
+ if ((start & 0x04) == chr_page)
+ bank |= 0x100;
+
+ chr1_x(start, bank, source);
+}
+
+WRITE8_MEMBER(nes_kay_device::write_h)
+{
+ LOG_MMC(("kay write_h, offset: %04x, data: %02x\n", offset, data));
+
+ switch (offset & 0x6003)
+ {
+ case 0x0000:
+ txrom_write(space, offset, data, mem_mask);
+ set_prg(m_prg_base, m_prg_mask);
+ break;
+
+ case 0x0001:
+ m_reg[6] = (BIT(data, 0) << 5) | (BIT(data, 1) << 4) | (BIT(data, 2) << 3)
+ | (BIT(data, 3) << 2) | (BIT(data, 4) << 1) | BIT(data, 5);
+ if (!m_reg[7])
+ update_regs();
+ txrom_write(space, offset, data, mem_mask);
+ set_prg(m_prg_base, m_prg_mask);
+ break;
+
+ case 0x0003:
+ m_reg[5] = data;
+ update_regs();
+ txrom_write(space, 0x0000, data, mem_mask);
+ set_prg(m_prg_base, m_prg_mask);
+ break;
+
+ default:
+ txrom_write(space, offset, data, mem_mask);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ UNL-H2288
+
+ -------------------------------------------------*/
+
+void nes_h2288_device::prg_cb(int start, int bank)
+{
+ if (!(m_reg[0] & 0x40))
+ prg8_x(start, bank);
+}
+
+WRITE8_MEMBER(nes_h2288_device::write_l)
+{
+ LOG_MMC(("h2288 write_l, offset: %04x, data: %02x\n", offset, data));
+ offset += 0x100;
+
+ if (offset >= 0x1800)
+ {
+ m_reg[offset & 1] = data;
+ if (m_reg[0] & 0x40)
+ {
+ UINT8 helper1 = (m_reg[0] & 0x05) | ((m_reg[0] >> 2) & 0x0a);
+ UINT8 helper2 = BIT(m_reg[0], 1);
+ prg16_89ab(helper1 & ~helper2);
+ prg16_cdef(helper1 | helper2);
+ }
+ else
+ set_prg(m_prg_base, m_prg_mask);
+ }
+}
+
+READ8_MEMBER(nes_h2288_device::read_l)
+{
+ LOG_MMC(("h2288 read_l, offset: %04x\n", offset));
+ offset += 0x100;
+
+ if (offset >= 0x1000)
+ {
+ int helper = offset >> 8;
+ if (offset & 1)
+ return helper | 0x01;
+ else
+ return helper ^ 0x01;
+ }
+
+ return 0;
+}
+
+WRITE8_MEMBER(nes_h2288_device::write_h)
+{
+ static const UINT8 conv_table[8] = {0, 3, 1, 5, 6, 7, 2, 4};
+ LOG_MMC(("h2288 write_h, offset: %04x, data: %02x\n", offset, data));
+
+ switch (offset & 0x6001)
+ {
+ case 0x0000:
+ txrom_write(space, 0x0000, (data & 0xc0) | conv_table[data & 0x07], mem_mask);
+ break;
+
+ default:
+ txrom_write(space, offset, data, mem_mask);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ UNL-603-5052
+
+ MMC3 + protection access in 0x4020 - 0x7fff
+
+ in MESS: Partial support
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_6035052_device::write_ex)
+{
+ LOG_MMC(("6035052 write_ex, offset: %04x, data: %02x\n", offset, data));
+ m_prot = data & 0x03;
+ if (m_prot == 1)
+ m_prot = 2;
+}
+
+READ8_MEMBER(nes_6035052_device::read_ex)
+{
+ LOG_MMC(("6035052 read_ex, offset: %04x\n", offset));
+ return m_prot;
+}
+
+/*-------------------------------------------------
+
+ Bootleg Board 'Thunder Warrior' by TXC
+
+ Games: Master Fighter II, Master Fighter 3, Thunder Warrior
+
+ MMC3 clone
+
+ iNES: mapper 189
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_txc_tw_device::write_l)
+{
+ LOG_MMC(("txc_tw write_l, offset: %04x, data: %02x\n", offset, data));
+
+ prg32((data >> 4) | data);
+}
+
+/* writes to 0x8000-0xffff are like MMC3 but no PRG bankswitch (beacuse it is handled by low writes) */
+void nes_txc_tw_device::prg_cb(int start, int bank)
+{
+ return;
+}
+
+/*-------------------------------------------------
+
+ Board UNL-KOF97
+
+ Games: King of Fighters 97 (Rex Soft)
+
+ MMC3 clone
+
+ In MESS: Not working
+
+ -------------------------------------------------*/
+
+inline UINT8 kof97_unscramble( UINT8 data )
+{
+ return ((data >> 1) & 0x01) | ((data >> 4) & 0x02) | ((data << 2) & 0x04) | ((data >> 0) & 0xd8) | ((data << 3) & 0x20);
+}
+
+WRITE8_MEMBER(nes_kof97_device::write_h)
+{
+ LOG_MMC(("kof97 write_h, offset: %04x, data: %02x\n", offset, data));
+
+ /* Addresses 0x9000, 0xa000, 0xd000 & 0xf000 behaves differently than MMC3 */
+ if (offset == 0x1000)
+ txrom_write(space, 0x0001, kof97_unscramble(data), mem_mask);
+ else if (offset == 0x2000)
+ txrom_write(space, 0x0000, kof97_unscramble(data), mem_mask);
+ else if (offset == 0x5000)
+ txrom_write(space, 0x4001, kof97_unscramble(data), mem_mask);
+ else if (offset == 0x7000)
+ txrom_write(space, 0x6001, kof97_unscramble(data), mem_mask);
+ /* Other addresses behaves like MMC3, up to unscrambling data */
+ else
+ txrom_write(space, offset, kof97_unscramble(data), mem_mask);
+}
+
+/*-------------------------------------------------
+
+ Bootleg Board for KOF96
+
+ Games: The King of Fighters 96, Sonic 3D Blast 6, Street
+ Fighter Zero 2
+
+ MMC3 clone
+
+ iNES: mapper 187
+
+ In MESS: Preliminary Support.
+
+ -------------------------------------------------*/
+
+void nes_kof96_device::prg_cb(int start, int bank)
+{
+ if (!(m_reg[0] & 0x80))
+ prg8_x(start, bank);
+}
+
+void nes_kof96_device::chr_cb(int start, int bank, int source)
+{
+ UINT8 chr_page = (m_latch & 0x80) >> 5;
+
+ if ((start & 0x04) == chr_page)
+ bank |= 0x100;
+
+ chr1_x(start, bank, source);
+}
+
+WRITE8_MEMBER(nes_kof96_device::write_l)
+{
+ UINT8 new_bank;
+ LOG_MMC(("kof96 write_l, offset: %04x, data: %02x\n", offset, data));
+ offset += 0x100;
+
+ if (offset == 0x1000)
+ {
+ m_reg[0] = data;
+
+ if (m_reg[0] & 0x80)
+ {
+ new_bank = (m_reg[0] & 0x1f);
+
+ if (m_reg[0] & 0x20)
+ prg32(new_bank >> 2);
+ else
+ {
+ prg16_89ab(new_bank);
+ prg16_cdef(new_bank);
+ }
+ }
+ else
+ set_prg(m_prg_base, m_prg_mask);
+ }
+
+ if (offset >= 0x1000)
+ {
+ switch (data & 0x03)
+ {
+ case 0x00:
+ case 0x01:
+ m_reg[1] = 0x83;
+ break;
+ case 0x02:
+ m_reg[1] = 0x42;
+ break;
+ case 0x03:
+ m_reg[1] = 0x00;
+ break;
+ }
+
+ }
+
+ if (!m_reg[3] && offset > 0x1000)
+ {
+ m_reg[3] = 1;
+ space.write_byte(0x4017, 0x40);
+ }
+}
+
+READ8_MEMBER(nes_kof96_device::read_l)
+{
+ LOG_MMC(("kof96 read_l, offset: %04x\n", offset));
+ offset += 0x100;
+
+ if (!(offset < 0x1000))
+ return m_reg[1];
+ else
+ return 0;
+}
+
+WRITE8_MEMBER(nes_kof96_device::write_h)
+{
+ LOG_MMC(("kof96 write_h, offset: %04x, data: %02x\n", offset, data));
+
+ switch (offset & 0x6003)
+ {
+ case 0x0000:
+ m_reg[2] = 1;
+ txrom_write(space, 0x0000, data, mem_mask);
+ break;
+
+ case 0x0001:
+ if (m_reg[2])
+ txrom_write(space, 0x0001, data, mem_mask);
+ break;
+
+ case 0x0002:
+ break;
+
+ case 0x0003:
+ m_reg[2] = 0;
+
+ if (data == 0x28)
+ prg8_cd(0x17);
+ else if (data == 0x2a)
+ prg8_ab(0x0f);
+ break;
+
+ default:
+ txrom_write(space, offset, data, mem_mask);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ Bootleg Board for Super Fighter III
+
+ MMC3 clone
+
+ iNES: mapper 197
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+void nes_sf3_device::set_chr(UINT8 chr_source, int chr_base, int chr_mask)
+{
+ chr4_0(chr_base | ((m_mmc_vrom_bank[0] >> 1) & chr_mask), chr_source);
+ chr2_4(chr_base | (m_mmc_vrom_bank[1] & chr_mask), chr_source);
+ chr2_6(chr_base | (m_mmc_vrom_bank[2] & chr_mask), chr_source);
+}
+
+WRITE8_MEMBER(nes_sf3_device::write_h)
+{
+ UINT8 cmd;
+ LOG_MMC(("sf3 write_h, offset: %04x, data: %02x\n", offset, data));
+
+ switch (offset & 0x6001)
+ {
+ case 0x0001:
+ cmd = m_latch & 0x07;
+ switch (cmd)
+ {
+ case 0: case 2: case 4:
+ m_mmc_vrom_bank[cmd >> 1] = data;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ break;
+ case 6:
+ case 7:
+ m_mmc_prg_bank[cmd - 6] = data;
+ set_prg(m_prg_base, m_prg_mask);
+ break;
+ }
+ break;
+
+ default:
+ txrom_write(space, offset, data, mem_mask);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ Bootleg Board 37017 (?) by Gouder
+
+ Games: Street Fighter IV
+
+ MMC3 clone. It also requires reads from 0x5000-0x7fff.
+
+ iNES: mapper 208
+
+ In MESS: Preliminary Support.
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_gouder_device::write_l)
+{
+ static const UINT8 conv_table[256] =
+ {
+ 0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x49,0x19,0x09,0x59,0x49,0x19,0x09,
+ 0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x51,0x41,0x11,0x01,0x51,0x41,0x11,0x01,
+ 0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x49,0x19,0x09,0x59,0x49,0x19,0x09,
+ 0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x51,0x41,0x11,0x01,0x51,0x41,0x11,0x01,
+ 0x00,0x10,0x40,0x50,0x00,0x10,0x40,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x08,0x18,0x48,0x58,0x08,0x18,0x48,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x10,0x40,0x50,0x00,0x10,0x40,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x08,0x18,0x48,0x58,0x08,0x18,0x48,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x58,0x48,0x18,0x08,0x58,0x48,0x18,0x08,
+ 0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x50,0x40,0x10,0x00,0x50,0x40,0x10,0x00,
+ 0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x58,0x48,0x18,0x08,0x58,0x48,0x18,0x08,
+ 0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x50,0x40,0x10,0x00,0x50,0x40,0x10,0x00,
+ 0x01,0x11,0x41,0x51,0x01,0x11,0x41,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x09,0x19,0x49,0x59,0x09,0x19,0x49,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x11,0x41,0x51,0x01,0x11,0x41,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x09,0x19,0x49,0x59,0x09,0x19,0x49,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+ };
+
+ LOG_MMC(("gouder write_l, offset: %04x, data: %02x\n", offset, data));
+
+ if (!(offset < 0x1700))
+ m_reg[offset & 0x03] = data ^ conv_table[m_reg[4]];
+ else if (!(offset < 0xf00))
+ m_reg[4] = data;
+ else if (!(offset < 0x700))
+ prg32(((data >> 3) & 0x02) | (data & 0x01));
+}
+
+READ8_MEMBER(nes_gouder_device::read_l)
+{
+ LOG_MMC(("gouder read_l, offset: %04x\n", offset));
+
+ if (!(offset < 0x1700))
+ return m_reg[offset & 0x03];
+
+ return 0x00;
+}
+
+/* writes to 0x8000-0xffff are like MMC3 but no PRG bankswitch (beacuse it is handled by low writes) */
+void nes_gouder_device::prg_cb(int start, int bank)
+{
+ return;
+}
+
+
+/*-------------------------------------------------
+
+ UNL-SA-9602B
+
+ Sachen boards used for a chinese port of Princess Maker (?)
+
+ in MESS: Very Preliminary support, based on Cah4e3
+ code in FCEUMM
+
+ -------------------------------------------------*/
+
+void nes_sa9602b_device::prg_cb(int start, int bank)
+{
+ if (m_prg_chip == 3)
+ {
+ printf("Accessing PRG beyond end of ROM!\n");
+ m_prg_chip = 2; // assume that the higher PRG chip is mirrored twice
+ }
+ prg8_x(start, (m_prg_chip * 0x40) | (bank & 0x3f));
+
+ if (m_latch & 0x40)
+ prg8_89(0x3e);
+ else
+ prg8_cd(0x3e);
+
+ prg8_ef(0x3f);
+// printf("start %d, bank %d\n", start, bank);
+}
+
+
+WRITE8_MEMBER( nes_sa9602b_device::write_h )
+{
+ LOG_MMC(("sa9602b write_h, offset: %04x, data: %02x\n", offset, data));
+
+ switch (offset & 0x6001)
+ {
+ case 0x0000:
+ m_reg = data;
+ break;
+ case 0x0001:
+ if ((m_reg & 7) < 6)
+ m_prg_chip = (data & 0xc0) >> 6;
+ set_prg(0, m_prg_mask);
+ break;
+ }
+
+ txrom_write(space, offset, data, mem_mask);
+}
+
+/*-------------------------------------------------
+
+ UNL-SHERO
+
+ Sachen boards used for Street Heroes
+
+ in MESS: Very Preliminary support
+
+ -------------------------------------------------*/
+
+
+void nes_sachen_shero_device::chr_cb( int start, int bank, int source )
+{
+ int shift = start < 2 ? 5 :
+ start < 4 ? 6 :
+ start < 6 ? 8 : 7;
+ if (!BIT(m_reg, 6))
+ chr1_x(start, ((m_reg << shift) & 0x100) | bank, source);
+}
+
+
+WRITE8_MEMBER( nes_sachen_shero_device::write_l )
+{
+ LOG_MMC(("shero write_l, offset: %04x, data: %02x\n", offset, data));
+ offset += 0x4100;
+
+ if (offset == 0x4100)
+ {
+ m_reg = data;
+ if (BIT(m_reg, 6))
+ chr8(0, CHRRAM);
+ else
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
+}
+
+READ8_MEMBER( nes_sachen_shero_device::read_l )
+{
+ LOG_MMC(("shero read_l, offset: %04x\n", offset));
+ offset += 0x4100;
+
+ if (offset == 0x4100)
+ {
+ // DSW read!
+ }
+ return m_open_bus; // open bus
+}
+
+
+
+/*-------------------------------------------------
+
+ MULTIGAME CARTS BASED ON MMC3
+
+ -------------------------------------------------*/
+
+ /*-------------------------------------------------
+
+ Board BMC-FK23C
+
+ MMC3 clone
+
+ In MESS: partially supported (still to sort initial banking
+ for many games)
+
+ -------------------------------------------------*/
+
+#if 0
+// alt version...
+void nes_fk23c_device::prg_cb(int start, int bank)
+{
+ if (((m_reg[0] & 0x07) - 3) > 1 && (!(m_reg[3] & 0x02) || start < 2))
+ {
+ if (m_reg[0] & 0x03)
+ bank = (bank & (0x3f >> (m_reg[0] & 0x03))) | (m_reg[1] << 1);
+
+ prg8_x(start, bank);
+ }
+}
+
+void nes_fk23c_device::chr_cb(int start, int bank, int source)
+{
+ if (!(m_reg[0] & 0x40) && (!(m_reg[3] & 0x02) || (start != 1 && start != 3)))
+ chr1_x(start, ((m_reg[2] & 0x7f) << 3) | bank, source);
+}
+
+#endif
+
+void nes_fk23c_device::prg_cb(int start, int bank)
+{
+ UINT8 mask = (0x3f >> (m_reg[0] & 0x03));
+
+ if ((m_reg[0] & 0x07) < 3)
+ {
+ if (!(m_reg[0] & 0x03))
+ bank = (bank & mask) | ((m_reg[1] & (0x7f ^ mask)) << 1);
+
+ prg8_x(start, bank);
+ }
+}
+
+void nes_fk23c_device::chr_cb(int start, int bank, int source)
+{
+ if (!(m_reg[0] & 0x40) && (!(m_reg[3] & 0x02) || (start != 1 && start != 3)))
+ chr1_x(start, ((m_reg[2] & 0x7f) << 3) | bank, source);
+}
+
+void nes_fk23c_device::fk23c_set_prg()
+{
+ if ((m_reg[0] & 0x07) == 4)
+ prg32((m_reg[1] & 0x7f) >> 1);
+ else if ((m_reg[0] & 0x07) == 3)
+ {
+ prg16_89ab(m_reg[1] & 0x7f);
+ prg16_cdef(m_reg[1] & 0x7f);
+ }
+ else
+ {
+ if (m_reg[3] & 0x02)
+ {
+ prg8_cd(m_reg[4]);
+ prg8_ef(m_reg[5]);
+ }
+ else
+ set_prg(m_prg_base, m_prg_mask);
+ }
+}
+
+void nes_fk23c_device::fk23c_set_chr()
+{
+ if (m_reg[0] & 0x40)
+ chr8(m_reg[2] | m_mmc_cmd1, m_chr_source);
+ else
+ {
+ if (m_reg[3] & 0x02)
+ {
+ int base = (m_reg[2] & 0x7f) << 3;
+ chr1_x(1, base | m_reg[6], m_chr_source);
+ chr1_x(3, base | m_reg[7], m_chr_source);
+ }
+ else
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
+}
+
+WRITE8_MEMBER(nes_fk23c_device::write_l)
+{
+ LOG_MMC(("fk23c write_l, offset: %04x, data: %02x\n", offset, data));
+ offset += 0x100;
+
+ if (offset >= 0x1000)
+ {
+ if (offset & (1 << 4)) // here it should be (4 + m_mmc_dipsetting)
+ {
+ m_reg[offset & 0x03] = data;
+
+ fk23c_set_prg();
+ fk23c_set_chr();
+ }
+ }
+}
+
+WRITE8_MEMBER(nes_fk23c_device::write_h)
+{
+ LOG_MMC(("fk23c write_h, offset: %04x, data: %02x\n", offset, data));
+
+ if (m_reg[0] & 0x40)
+ {
+ if (m_reg[0] & 0x30)
+ m_mmc_cmd1 = 0;
+ else
+ {
+ m_mmc_cmd1 = data & 0x03;
+ fk23c_set_chr();
+ }
+ }
+ else
+ {
+ switch (offset & 0x6001)
+ {
+ case 0x0001:
+ if ((m_reg[3] & 0x02) && (m_latch & 0x08))
+ {
+ m_reg[4 | (m_latch & 0x03)] = data;
+ fk23c_set_prg();
+ fk23c_set_chr();
+ }
+ else
+ txrom_write(space, offset, data, mem_mask);
+ break;
+
+ case 0x2000:
+ set_nt_mirroring(data ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ break;
+
+ default:
+ txrom_write(space, offset, data, mem_mask);
+ break;
+ }
+ }
+}
+
+/*-------------------------------------------------
+
+ Board BMC-SUPER24IN1SC03
+
+ Games: Super 24-in-1
+
+ In MESS: Partially Supported
+
+ -------------------------------------------------*/
+
+void nes_s24in1sc03_device::prg_cb(int start, int bank)
+{
+ static const UINT8 masks[8] = {0x3f, 0x1f, 0x0f, 0x01, 0x03, 0x00, 0x00, 0x00};
+ int prg_base = m_reg[1] << 1;
+ int prg_mask = masks[m_reg[0] & 0x07];
+
+ bank = prg_base | (bank & prg_mask);
+ prg8_x(start, bank);
+}
+
+void nes_s24in1sc03_device::chr_cb(int start, int bank, int source)
+{
+ UINT8 chr = BIT(m_reg[0], 5) ? CHRRAM : CHRROM;
+ int chr_base = (m_reg[2] << 3) & 0xf00;
+
+ chr1_x(start, chr_base | bank, chr);
+}
+
+WRITE8_MEMBER(nes_s24in1sc03_device::write_l)
+{
+ LOG_MMC(("s24in1sc03 write_l, offset: %04x, data: %02x\n", offset, data));
+ offset += 0x100;
+
+ if (offset == 0x1ff0)
+ {
+ m_reg[0] = data;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ set_prg(m_prg_base, m_prg_mask);
+ }
+
+ if (offset == 0x1ff1)
+ {
+ m_reg[1] = data;
+ set_prg(m_prg_base, m_prg_mask);
+ }
+
+ if (offset == 0x1ff2)
+ {
+ m_reg[2] = data;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
+}
+
+/*-------------------------------------------------
+
+ BMC-15IN1
+
+ Unknown Bootleg Multigame Board
+ Games: 3 in 1, 15 in 1
+
+ iNES: mapper 205, MMC3 clone
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_bmc_15in1_device::write_m)
+{
+ LOG_MMC(("bmc_15in1 write_m, offset: %04x, data: %02x\n", offset, data));
+
+ if (offset & 0x0800)
+ {
+ m_prg_base = (data & 0x03) << 4;
+ m_prg_mask = (data & 0x02) ? 0x0f : 0x1f;
+ m_chr_base = (data & 0x03) << 7;
+ m_chr_mask = (data & 0x02) ? 0x7f : 0xff;
+ set_prg(m_prg_base, m_prg_mask);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
+}
+
+/*-------------------------------------------------
+
+ BMC-SUPERBIG-7IN1
+
+ Known Boards: Unknown Multigame Bootleg Board
+ Games: Kunio 8 in 1, Super Big 7 in 1
+
+ iNES: mapper 44
+
+ In MESS: Supported. It also uses mmc3_irq.
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_bmc_sbig7_device::write_h)
+{
+ UINT8 page;
+ LOG_MMC(("bmc_sbig7 write_h, offset: %04x, data: %02x\n", offset, data));
+
+ switch (offset & 0x6001)
+ {
+ case 0x2001: /* $a001 - Select 128K ROM/VROM base (0..5) or last 256K ROM/VRAM base (6) */
+ page = (data & 0x07);
+ if (page > 6)
+ page = 6;
+
+ m_prg_base = page << 4;
+ m_prg_mask = (page > 5) ? 0x1f : 0x0f;
+ m_chr_base = page << 7;
+ m_chr_mask = (page > 5) ? 0xff : 0x7f;
+ set_prg(m_prg_base, m_prg_mask);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ break;
+
+ default:
+ txrom_write(space, offset, data, mem_mask);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ BMC-HIK8IN1
+
+ Known Boards: Unknown Multigame Bootleg Board
+ Games: Street Fighter V, various multigame carts
+
+ iNES: mapper 45
+
+ In MESS: Supported. It also uses mmc3_irq.
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_bmc_hik8_device::write_m)
+{
+ LOG_MMC(("bmc_hik8 write_m, offset: %04x, data: %02x\n", offset, data));
+
+ /* This bit is the "register lock". Once register are locked, writes go to WRAM
+ and there is no way to unlock them (except by resetting the machine) */
+ if ((m_reg[3] & 0x40) && !m_prgram.empty())
+ m_prgram[offset] = data;
+ else
+ {
+ m_reg[m_count] = data;
+ m_count = (m_count + 1) & 0x03;
+
+ if (!m_count)
+ {
+ LOG_MMC(("bmc_hik8 write_m, command completed %02x %02x %02x %02x\n", m_reg[3],
+ m_reg[2], m_reg[1], m_reg[0]));
+
+ m_prg_base = m_reg[1];
+ m_prg_mask = 0x3f ^ (m_reg[3] & 0x3f);
+ m_chr_base = ((m_reg[2] & 0xf0) << 4) | m_reg[0];
+ if (BIT(m_reg[2], 3))
+ m_chr_mask = (1 << ((m_reg[2] & 7) + 1)) - 1;
+ else if (m_reg[2])
+ m_chr_mask = 0;
+ else
+ m_chr_mask = 0xff; // i.e. we use the vrom_bank with no masking
+
+ set_prg(m_prg_base, m_prg_mask);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
+ }
+}
+
+/*-------------------------------------------------
+
+ BMC-SUPERHIK-4IN1
+
+ Known Boards: Unknown Multigame Bootleg Board
+ Games: Super HIK 4 in 1
+
+ iNES: mapper 49
+
+ In MESS: Supported. It also uses mmc3_irq.
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_bmc_hik4_device::write_m)
+{
+ LOG_MMC(("bmc_hik4 write_m, offset: %04x, data: %02x\n", offset, data));
+
+ /* mid writes only work when WRAM is enabled. not sure if I should
+ change the condition to m_mmc_latch2==0x80 (i.e. what is the effect of
+ the read-only bit?) */
+ if (m_wram_protect & 0x80)
+ {
+ if (data & 0x01) /* if this is 0, then we have 32k PRG blocks */
+ {
+ m_prg_base = (data & 0xc0) >> 2;
+ m_prg_mask = 0x0f;
+ set_prg(m_prg_base, m_prg_mask);
+ }
+ else
+ prg32((data & 0x30) >> 4);
+
+ m_chr_base = (data & 0xc0) << 1;
+ m_chr_mask = 0x7f;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
+}
+
+/*-------------------------------------------------
+
+ BMC-MARIOPARTY-7IN1
+
+ Known Boards: Unknown Multigame Bootleg Board
+ Games: Mario 7 in 1
+
+ MMC3 clone
+
+ iNES: mapper 52
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_bmc_mario7in1_device::write_m)
+{
+ UINT8 helper1, helper2;
+ LOG_MMC(("bmc_mario7in1 write_m, offset: %04x, data: %02x\n", offset, data));
+
+ /* mid writes only work when WRAM is enabled. not sure if I should
+ change the condition to m_map52_reg_written == 0x80 (i.e. what is the effect of
+ the read-only bit?) and it only can happen once! */
+ if ((m_wram_protect & 0x80) && !m_reg_written)
+ {
+ helper1 = (data & 0x08);
+ helper2 = (data & 0x40);
+
+ m_prg_base = helper1 ? ((data & 0x07) << 4) : ((data & 0x06) << 4);
+ m_prg_mask = helper1 ? 0x0f : 0x1f;
+ m_chr_base = ((data & 0x20) << 4) | ((data & 0x04) << 6) | (helper2 ? ((data & 0x10) << 3) : 0);
+ m_chr_mask = helper2 ? 0x7f : 0xff;
+ set_prg(m_prg_base, m_prg_mask);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+
+ m_reg_written = 1;
+ }
+ else
+ m_prgram[offset] = data;
+}
+
+/*-------------------------------------------------
+
+ BMC-GOLD-7IN1
+
+ Known Boards: Unknown Multigame Bootleg Board
+ Games: Super HIK Gold 7 in 1, Golden 7 in 1 and many more
+
+ MMC3 clone, same as BMC-MARIOPARTY-7IN1 but with switched CHR
+ bank lines
+
+ iNES: mapper 52
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_bmc_gold7in1_device::write_m)
+{
+ UINT8 helper1, helper2;
+ LOG_MMC(("bmc_gold7in1 write_m, offset: %04x, data: %02x\n", offset, data));
+
+ if ((m_wram_protect & 0x80) && !m_reg_written)
+ {
+ helper1 = (data & 0x08);
+ helper2 = (data & 0x40);
+
+ m_prg_base = helper1 ? ((data & 0x07) << 4) : ((data & 0x06) << 4);
+ m_prg_mask = helper1 ? 0x0f : 0x1f;
+ m_chr_base = ((data & 0x20) << 3) | ((data & 0x04) << 7) | (helper2 ? ((data & 0x10) << 3) : 0);
+ m_chr_mask = helper2 ? 0x7f : 0xff;
+ set_prg(m_prg_base, m_prg_mask);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+
+ m_reg_written = BIT(data, 7); // mc_2hikg & mc_s3nt3 write here multiple time
+ }
+ else
+ m_prgram[offset] = data;
+}
+
+/*-------------------------------------------------
+
+ BMC-GOLDENCARD-6IN1
+
+ Known Boards: Unknown Bootleg Multigame Board
+ Games: Golden Card 6 in 1
+
+ MMC3 clone
+
+ iNES: mapper 217
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_gc6in1_device::prg_cb(int start, int bank)
+{
+ if (m_reg[1] & 0x08)
+ bank &= 0x1f;
+ else
+ {
+ bank &= 0x0f;
+ bank |= m_reg[1] & 0x10;
+ }
+
+ prg8_x(start, bank | ((m_reg[1] & 0x03) << 5));
+}
+
+void nes_bmc_gc6in1_device::chr_cb(int start, int bank, int source)
+{
+ if (!(m_reg[1] & 0x08))
+ bank = ((m_reg[1] & 0x10) << 3) | (bank & 0x7f);
+
+
+ bank |= ((m_reg[1] << 6) & 0x100);
+ chr1_x(start, ((m_reg[1] & 0x03) << 8) | bank, source);
+}
+
+WRITE8_MEMBER(nes_bmc_gc6in1_device::write_l)
+{
+ UINT8 bank;
+ LOG_MMC(("bmc_gc6in1 write_l, offset: %04x, data: %02x\n", offset, data));
+ offset += 0x100;
+
+ if (offset == 0x1000)
+ {
+ m_reg[0] = data;
+ if (data & 0x80)
+ {
+ bank = (data & 0x0f) | ((m_reg[1] & 0x03) << 4);
+ prg16_89ab(bank);
+ prg16_cdef(bank);
+ }
+ else
+ set_prg(m_prg_base, m_prg_mask);
+ }
+ else if (offset == 0x1001)
+ {
+ m_reg[1] = data;
+ set_prg(m_prg_base, m_prg_mask);
+ }
+ else if (offset == 0x1007)
+ {
+ m_reg[2] = data;
+ }
+}
+
+WRITE8_MEMBER(nes_bmc_gc6in1_device::write_h)
+{
+ UINT8 cmd;
+ static const UINT8 conv_table[8] = {0, 6, 3, 7, 5, 2, 4, 1};
+ LOG_MMC(("bmc_gc6in1 write_h, offset: %04x, data: %02x\n", offset, data));
+
+ if (!m_reg[2])
+ {
+ // in this case we act like MMC3, only with alt prg/chr handlers
+ txrom_write(space, offset, data, mem_mask);
+ }
+ else
+ {
+ switch (offset & 0x6001)
+ {
+ case 0x0000:
+ txrom_write(space, 0x4000, data, mem_mask);
+ break;
+
+ case 0x0001:
+ data = (data & 0xc0) | conv_table[data & 0x07];
+ m_reg[3] = 1;
+ txrom_write(space, 0x0000, data, mem_mask);
+ break;
+
+ case 0x2000:
+ cmd = m_latch & 0x07;
+ if (m_reg[3])
+ {
+ m_reg[3] = 0;
+ switch (cmd)
+ {
+ case 0: case 1: // these do not need to be separated: we take care of them in set_chr!
+ case 2: case 3: case 4: case 5:
+ m_mmc_vrom_bank[cmd] = data;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ break;
+ case 6:
+ case 7:
+ m_mmc_prg_bank[cmd - 6] = data;
+ set_prg(m_prg_base, m_prg_mask);
+ break;
+ }
+ }
+ break;
+
+
+ case 0x2001:
+ set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ break;
+
+ default:
+ txrom_write(space, offset, data, mem_mask);
+ break;
+ }
+ }
+}
+
+/*-------------------------------------------------
+
+ BMC-411120C
+
+
+ MMC3 clone
+
+
+ In MESS: Very Preliminary Support
+
+ -------------------------------------------------*/
+
+void nes_bmc_411120c_device::prg_cb(int start, int bank)
+{
+ if (m_reg & 8) // & 0xc when DSW change (diff menu?)
+ prg32(((m_reg >> 4) & 3) | 0x0c);
+ else
+ prg8_x(start, (bank & 0x0f) | ((m_reg & 0x03) << 4));
+}
+
+void nes_bmc_411120c_device::chr_cb(int start, int bank, int source)
+{
+ chr1_x(start, bank | ((m_reg & 3) << 7), source);
+}
+
+WRITE8_MEMBER(nes_bmc_411120c_device::write_m)
+{
+ LOG_MMC(("bmc_411120c write_m, offset: %04x, data: %02x\n", offset, data));
+
+ m_reg = data;
+ set_prg(m_prg_base, m_prg_mask);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+}
+
+/*-------------------------------------------------
+
+ BMC-830118C
+
+
+ MMC3 clone
+
+
+ In MESS: Very Preliminary Support
+
+ -------------------------------------------------*/
+
+void nes_bmc_830118c_device::prg_cb(int start, int bank)
+{
+ if ((m_reg & 0x0c) != 0x0c)
+ prg8_x(start, (bank & 0x0f) | ((m_reg & 0x0c) << 2));
+ else
+ {
+ if (start == 0)
+ {
+ prg8_89((bank & 0x0f) | ((m_reg & 0x0c) << 2));
+ prg8_ab((bank & 0x0f) | 0x20);
+ }
+ else if (start == 2)
+ {
+ prg8_cd((bank & 0x0f) | ((m_reg & 0x0c) << 2));
+ prg8_ef((bank & 0x0f) | 0x20);
+ }
+ }
+}
+
+void nes_bmc_830118c_device::chr_cb(int start, int bank, int source)
+{
+ chr1_x(start, (bank & 0x7f) | ((m_reg & 0x0c) << 5), source);
+}
+
+WRITE8_MEMBER(nes_bmc_830118c_device::write_m)
+{
+ LOG_MMC(("bmc_830118c write_m, offset: %04x, data: %02x\n", offset, data));
+
+ if (offset >= 0x800 && offset < 0x900)
+ {
+ m_reg = data;
+ set_prg(m_prg_base, m_prg_mask);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
+}
+
+/*-------------------------------------------------
+
+ BMC-POWERJOY
+
+ -------------------------------------------------*/
+
+void nes_pjoy84_device::prg_cb(int start, int bank)
+{
+ UINT8 flip = (m_latch & 0x40) ? 2 : 0;
+
+ if (!(m_reg[3] & 0x03))
+ prg8_x(start, bank);
+ else if (start == flip)
+ {
+ if ((m_reg[3] & 0x03) == 0x03)
+ prg32(bank >> 2);
+ else
+ {
+ prg16_89ab(bank >> 1);
+ prg16_cdef(bank >> 1);
+ }
+ }
+}
+
+void nes_pjoy84_device::chr_cb(int start, int bank, int source)
+{
+ if (!(m_reg[3] & 0x10))
+ chr1_x(start, bank, source);
+}
+
+inline void nes_pjoy84_device::set_base_mask()
+{
+ m_prg_base = ((m_reg[0] & (0x06 | BIT(m_reg[0], 6))) << 4) |
+ (BIT(m_reg[0], 4) << 7);
+
+ m_chr_base = ((~m_reg[0] << 0) & 0x080 & m_reg[2]) |
+ ((m_reg[0] << 4) & 0x080 & m_reg[0]) |
+ ((m_reg[0] << 3) & 0x100) |
+ ((m_reg[0] << 5) & 0x200);
+
+ m_prg_mask = BIT(m_reg[0], 6) ? 0x0f : 0x1f;
+ m_chr_mask = BIT(m_reg[0], 7) ? 0x7f : 0xff;
+}
+
+WRITE8_MEMBER(nes_pjoy84_device::write_m)
+{
+ LOG_MMC(("pjoy84 write_m, offset: %04x, data: %02x\n", offset, data));
+
+ switch (offset & 0x03)
+ {
+ case 0x00:
+ case 0x03:
+ if (m_reg[3] & 0x80)
+ return; // else we act as if offset & 3 = 1,2
+ case 0x01:
+ case 0x02:
+ m_reg[offset & 0x03] = data;
+ set_base_mask();
+ if (m_reg[3] & 0x10)
+ chr8((m_chr_base >> 3) | (m_reg[2] & 0x0f), m_chr_source);
+ else
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ set_prg(m_prg_base, m_prg_mask);
+ break;
+ }
+}
+
+#ifdef UNUSED_FUNCTION
+/*-------------------------------------------------
+
+ UNL-A9746
+
+
+ MMC3 clone
+
+
+ Preliminary emulation based on Cah4e3's code
+ No dump is available (yet) for this.
+
+ -------------------------------------------------*/
+
+void nes_a9746_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_a9746_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ m_reg[0] = 0;
+ m_reg[1] = 0;
+ m_reg[2] = 0;
+ mmc3_common_initialize(0x7f, 0xff, 0);
+}
+
+void nes_a9746_device::update_banks(UINT8 value)
+{
+ UINT8 bank = BITSWAP8(value & 0x3c,7,6,0,1,2,3,4,5);
+
+ switch (m_reg[0])
+ {
+ case 0x26: prg8_89(bank); break;
+ case 0x25: prg8_ab(bank); break;
+ case 0x24: prg8_cd(bank); break;
+ case 0x23: prg8_ef(bank); break;
+ }
+
+ switch (m_reg[1])
+ {
+ case 0x08: case 0x0a: case 0x0c: case 0x0e:
+ case 0x10: case 0x12: case 0x14: case 0x16:
+ case 0x18: case 0x1a: case 0x1c: case 0x1e:
+ m_reg[2] = (value << 4);
+ break;
+ case 0x09: chr1_0(m_reg[2] | (value >> 1), m_chr_source); break;
+ case 0x0b: chr1_1(m_reg[2] | (value >> 1) | 1, m_chr_source); break;
+ case 0x0d: chr1_2(m_reg[2] | (value >> 1), m_chr_source); break;
+ case 0x0f: chr1_3(m_reg[2] | (value >> 1) | 1, m_chr_source); break;
+ case 0x11: chr1_4(m_reg[2] | (value >> 1), m_chr_source); break;
+ case 0x15: chr1_5(m_reg[2] | (value >> 1), m_chr_source); break;
+ case 0x19: chr1_6(m_reg[2] | (value >> 1), m_chr_source); break;
+ case 0x1d: chr1_7(m_reg[2] | (value >> 1), m_chr_source); break;
+ }
+}
+
+WRITE8_MEMBER(nes_a9746_device::write_h)
+{
+ LOG_MMC(("unl_a9746 write_h, offset: %04x, data: %02x\n", offset, data));
+
+ switch (offset & 0x6003)
+ {
+ case 0x0000:
+ m_reg[1] = data;
+ m_reg[0] = 0;
+ break;
+ case 0x0001:
+ update_banks(data);
+ break;
+ case 0x0002:
+ m_reg[0] = data;
+ m_reg[1] = 0;
+ break;
+
+ case 0x0003:
+ case 0x2000:
+ case 0x2001:
+ case 0x2002:
+ case 0x2003:
+ break;
+
+ default:
+ txrom_write(space, offset, data, mem_mask);
+ break;
+ }
+}
+#endif