summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/nes/vrc_clones.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/nes/vrc_clones.cpp')
-rw-r--r--src/devices/bus/nes/vrc_clones.cpp861
1 files changed, 861 insertions, 0 deletions
diff --git a/src/devices/bus/nes/vrc_clones.cpp b/src/devices/bus/nes/vrc_clones.cpp
new file mode 100644
index 00000000000..ba358cb164f
--- /dev/null
+++ b/src/devices/bus/nes/vrc_clones.cpp
@@ -0,0 +1,861 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+/***********************************************************************************************************
+
+
+ NES/Famicom cartridge emulation for Konami VRC clone PCBs
+
+
+ Here we emulate several pirate PCBs based on VRC2/4 boards
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "vrc_clones.h"
+
+#define LOG_HIFREQ (1U << 1)
+
+#ifdef NES_PCB_DEBUG
+#define VERBOSE (LOG_GENERAL)
+#else
+#define VERBOSE (0)
+#endif
+#include "logmacro.h"
+
+
+//-------------------------------------------------
+// constructor
+//-------------------------------------------------
+
+DEFINE_DEVICE_TYPE(NES_2YUDB, nes_2yudb_device, "nes_2yudb", "NES Cart Yu Yu Hakusho - Dragon Ball Z 2 in 1 PCB")
+DEFINE_DEVICE_TYPE(NES_900218, nes_900218_device, "nes_900218", "NES Cart 900218 PCB")
+DEFINE_DEVICE_TYPE(NES_AX40G, nes_ax40g_device, "nes_ax40g", "NES Cart UNL-AX-40G PCB")
+DEFINE_DEVICE_TYPE(NES_AX5705, nes_ax5705_device, "nes_ax5705", "NES Cart AX5705 PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_830506C, nes_bmc_830506c_device, "nes_bmc_830506c", "NES Cart BMC 830506C PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_831128C, nes_bmc_831128c_device, "nes_bmc_831128c", "NES Cart BMC 831128C PCB")
+DEFINE_DEVICE_TYPE(NES_BMC_KL06, nes_bmc_kl06_device, "nes_bmc_kl06", "NES Cart BMC KL-06 PCB")
+DEFINE_DEVICE_TYPE(NES_CITYFIGHT, nes_cityfight_device, "nes_cityfight", "NES Cart City Fighter PCB")
+DEFINE_DEVICE_TYPE(NES_SHUIGUAN, nes_shuiguan_device, "nes_shuiguan", "NES Cart Shui Guan Pipe Pirate PCB")
+DEFINE_DEVICE_TYPE(NES_T230, nes_t230_device, "nes_t230", "NES Cart T-230 PCB")
+DEFINE_DEVICE_TYPE(NES_TF1201, nes_tf1201_device, "nes_tf1201", "NES Cart UNL-TF1201 PCB")
+DEFINE_DEVICE_TYPE(NES_TH21311, nes_th21311_device, "nes_th21311", "NES Cart UNL-TH2131-1 PCB")
+DEFINE_DEVICE_TYPE(NES_WAIXING_SGZ, nes_waixing_sgz_device, "nes_waixing_sgz", "NES Cart Waixing San Guo Zhi PCB")
+DEFINE_DEVICE_TYPE(NES_HENGG_SHJY3, nes_hengg_shjy3_device, "nes_hengg_shjy3", "NES Cart Henggedianzi Shen Hua Jian Yun III PCB")
+
+
+nes_2yudb_device::nes_2yudb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc4_device(mconfig, NES_2YUDB, tag, owner, clock), m_outer(0)
+{
+}
+
+nes_900218_device::nes_900218_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc2_device(mconfig, NES_900218, tag, owner, clock), m_irq_count(0), m_irq_enable(0), irq_timer(nullptr)
+{
+}
+
+nes_ax40g_device::nes_ax40g_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc2_device(mconfig, NES_AX40G, tag, owner, clock)
+{
+}
+
+nes_ax5705_device::nes_ax5705_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc4_device(mconfig, NES_AX5705, tag, owner, clock)
+{
+}
+
+nes_bmc_830506c_device::nes_bmc_830506c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc4_device(mconfig, NES_BMC_830506C, tag, owner, clock), m_outer(0)
+{
+}
+
+nes_bmc_831128c_device::nes_bmc_831128c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc4_device(mconfig, NES_BMC_831128C, tag, owner, clock), m_reg(0)
+{
+}
+
+nes_bmc_kl06_device::nes_bmc_kl06_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc4_device(mconfig, NES_BMC_KL06, tag, owner, clock), m_reg(0)
+{
+}
+
+nes_cityfight_device::nes_cityfight_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc4_device(mconfig, NES_CITYFIGHT, tag, owner, clock)
+{
+}
+
+nes_shuiguan_device::nes_shuiguan_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc4_device(mconfig, NES_SHUIGUAN, tag, owner, clock)
+{
+}
+
+nes_t230_device::nes_t230_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc4_device(mconfig, NES_T230, tag, owner, clock)
+{
+}
+
+nes_tf1201_device::nes_tf1201_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc4_device(mconfig, NES_TF1201, tag, owner, clock)
+{
+}
+
+nes_th21311_device::nes_th21311_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_konami_vrc2_device(mconfig, NES_TH21311, tag, owner, clock), m_irq_count(0), m_irq_enable(0), irq_timer(nullptr)
+{
+}
+
+nes_waixing_sgz_device::nes_waixing_sgz_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 chr_match)
+ : nes_konami_vrc4_device(mconfig, type, tag, owner, clock), m_chr_match(chr_match)
+{
+}
+
+nes_waixing_sgz_device::nes_waixing_sgz_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_waixing_sgz_device(mconfig, NES_WAIXING_SGZ, tag, owner, clock, 0x06)
+{
+}
+
+nes_hengg_shjy3_device::nes_hengg_shjy3_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_waixing_sgz_device(mconfig, NES_HENGG_SHJY3, tag, owner, clock, 0x04)
+{
+}
+
+
+
+void nes_2yudb_device::device_start()
+{
+ nes_konami_vrc4_device::device_start();
+ save_item(NAME(m_outer));
+
+ // VRC4 pins 3 and 4
+ m_vrc_ls_prg_a = 3; // A3
+ m_vrc_ls_prg_b = 2; // A2
+}
+
+void nes_2yudb_device::pcb_reset()
+{
+ m_outer = 0;
+ nes_konami_vrc4_device::pcb_reset();
+}
+
+void nes_900218_device::device_start()
+{
+ nes_konami_vrc2_device::device_start();
+ irq_timer = timer_alloc(FUNC(nes_900218_device::irq_timer_tick), this);
+ irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
+
+ save_item(NAME(m_irq_enable));
+ save_item(NAME(m_irq_count));
+
+ // VRC2 pins 3 and 4
+ m_vrc_ls_prg_a = 1; // A1
+ m_vrc_ls_prg_b = 0; // A0
+}
+
+void nes_900218_device::pcb_reset()
+{
+ nes_konami_vrc2_device::pcb_reset();
+ m_irq_enable = 0;
+ m_irq_count = 0;
+}
+
+void nes_ax40g_device::device_start()
+{
+ nes_konami_vrc2_device::device_start();
+
+ // VRC2 pins 3 and 4
+ m_vrc_ls_prg_a = 1; // A1
+ m_vrc_ls_prg_b = 0; // A0
+}
+
+void nes_ax5705_device::device_start()
+{
+ nes_konami_vrc4_device::device_start();
+
+ // VRC4 pins 3 and 4
+ m_vrc_ls_prg_a = 1; // A1
+ m_vrc_ls_prg_b = 0; // A0
+}
+
+void nes_bmc_830506c_device::device_start()
+{
+ nes_konami_vrc4_device::device_start();
+ save_item(NAME(m_outer));
+
+ // VRC4 pins 3 and 4
+ m_vrc_ls_prg_a = 1; // A1
+ m_vrc_ls_prg_b = 0; // A0
+}
+
+void nes_bmc_830506c_device::pcb_reset()
+{
+ m_outer = 0;
+ nes_konami_vrc4_device::pcb_reset();
+}
+
+void nes_bmc_831128c_device::device_start()
+{
+ nes_konami_vrc4_device::device_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_bmc_831128c_device::pcb_reset()
+{
+ nes_konami_vrc4_device::pcb_reset();
+
+ m_reg = 0;
+ prg32((m_prg_chunks >> 1) - 1);
+}
+
+void nes_bmc_kl06_device::device_start()
+{
+ nes_konami_vrc4_device::device_start();
+ save_item(NAME(m_reg));
+
+ // VRC4 pins 3 and 4
+ m_vrc_ls_prg_a = 3; // A1
+ m_vrc_ls_prg_b = 2; // A0
+}
+
+void nes_bmc_kl06_device::pcb_reset()
+{
+ m_reg = 0;
+ nes_konami_vrc4_device::pcb_reset();
+}
+
+void nes_cityfight_device::device_start()
+{
+ nes_konami_vrc4_device::device_start();
+
+ // VRC4 pins 3 and 4
+ m_vrc_ls_prg_a = 3; // A3
+ m_vrc_ls_prg_b = 2; // A2
+}
+
+void nes_shuiguan_device::device_start()
+{
+ nes_konami_vrc4_device::device_start();
+ save_item(NAME(m_reg));
+
+ // VRC4 pins 3 and 4
+ m_vrc_ls_prg_a = 3; // A3
+ m_vrc_ls_prg_b = 2; // A2
+}
+
+void nes_shuiguan_device::pcb_reset()
+{
+ nes_konami_vrc4_device::pcb_reset();
+ m_reg = 0;
+}
+
+void nes_t230_device::device_start()
+{
+ nes_konami_vrc4_device::device_start();
+
+ // VRC4 pins 3 and 4
+ m_vrc_ls_prg_a = 3; // A3
+ m_vrc_ls_prg_b = 2; // A2
+}
+
+void nes_tf1201_device::device_start()
+{
+ nes_konami_vrc4_device::device_start();
+
+ // VRC4 pins 3 and 4
+ m_vrc_ls_prg_a = 0; // A0
+ m_vrc_ls_prg_b = 1; // A1
+}
+
+void nes_th21311_device::device_start()
+{
+ nes_konami_vrc2_device::device_start();
+ irq_timer = timer_alloc(FUNC(nes_th21311_device::irq_timer_tick), this);
+ irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
+
+ save_item(NAME(m_irq_enable));
+ save_item(NAME(m_irq_count));
+ save_item(NAME(m_irq_latch));
+
+ // VRC2 pins 3 and 4
+ m_vrc_ls_prg_a = 1; // A1
+ m_vrc_ls_prg_b = 0; // A0
+}
+
+void nes_th21311_device::pcb_reset()
+{
+ nes_konami_vrc2_device::pcb_reset();
+ m_irq_enable = 0;
+ m_irq_count = 0;
+ m_irq_latch = 0;
+}
+
+void nes_waixing_sgz_device::device_start()
+{
+ nes_konami_vrc4_device::device_start();
+ save_item(NAME(m_chr_mask));
+ save_item(NAME(m_chr_match));
+
+ m_chr_mask = 0xfe;
+
+ // VRC4 pins 3 and 4
+ m_vrc_ls_prg_a = 3; // A3
+ m_vrc_ls_prg_b = 2; // A2
+}
+
+
+
+/*-------------------------------------------------
+ mapper specific handlers
+ -------------------------------------------------*/
+
+/*-------------------------------------------------
+
+ Board BTL-900218
+
+ Games: Lord of King (Astyanax pirate)
+
+ This board has a VRC2 clone that has been altered to
+ add a simple IRQ counter fixed to 1024 CPU cycles.
+
+ NES 2.0: mapper 524
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+TIMER_CALLBACK_MEMBER(nes_900218_device::irq_timer_tick)
+{
+ if (m_irq_enable)
+ {
+ m_irq_count++;
+ set_irq_line(BIT(m_irq_count, 10) ? ASSERT_LINE : CLEAR_LINE);
+ }
+}
+
+void nes_900218_device::write_h(offs_t offset, u8 data)
+{
+ LOG("900218 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ if ((offset & 0x7000) == 0x7000)
+ {
+ switch (offset & 0xc)
+ {
+ case 0x8:
+ m_irq_enable = 1;
+ break;
+ case 0xc:
+ m_irq_enable = 0;
+ m_irq_count = 0;
+ set_irq_line(CLEAR_LINE);
+ break;
+ }
+ }
+ else
+ nes_konami_vrc2_device::write_h(offset, data);
+}
+
+/*-------------------------------------------------
+
+ Board UNL-AX-40G
+
+ Games: Fudou Myouou Den pirate
+
+ VRC2 clone that supports extra single screen mirroring
+ modes seen in the original Taito X1-005 board.
+
+ NES 2.0: mapper 527
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_ax40g_device::write_h(offs_t offset, u8 data)
+{
+ LOG("ax40g write_h, offset: %04x, data: %02x\n", offset, data);
+
+ nes_konami_vrc2_device::write_h(offset, data);
+
+ if ((offset & 0x7001) == 0x3001)
+ {
+ set_nt_page(offset & 0x02, CIRAM, BIT(data, 3), 1);
+ set_nt_page((offset & 0x02) + 1, CIRAM, BIT(data, 3), 1);
+ }
+}
+
+/*-------------------------------------------------
+
+ Board UNL-AX5705
+
+ Games: Super Mario Bros. Pocker Mali (Crayon Shin-chan pirate hack)
+
+ VRC4 clone with a few PRG/CHR address lines swapped.
+
+ NES 2.0: mapper 530
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_ax5705_device::write_h(offs_t offset, u8 data)
+{
+ LOG("ax5705 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ offset = (offset & ~0x1000) | BIT(offset, 3) << 12;
+ switch (offset & 0x7001)
+ {
+ case 0x0000: case 0x0001: case 0x2000: case 0x2001:
+ data = bitswap<4>(data, 1, 2, 3, 0);
+ break;
+ case 0x3001: case 0x4001: case 0x5001: case 0x6001:
+ data = bitswap<3>(data, 1, 2, 0);
+ break;
+ }
+ nes_konami_vrc4_device::write_h(offset, data);
+}
+
+/*-------------------------------------------------
+
+ UNL-CITYFIGHT
+
+ Games: City Fighter IV
+
+ VRC4 clone with simple 32K PRG banking (it's a minimal
+ hack of Master Fighter II banking). More interestingly
+ it adds a 4-bit PCM audio register, not emulated yet.
+
+ NES 2.0: mapper 266
+
+ In MAME: Partially supported.
+
+ -------------------------------------------------*/
+
+void nes_cityfight_device::write_h(offs_t offset, u8 data)
+{
+ LOG("unl_cityfight write_h, offset: %04x, data: %02x\n", offset, data);
+
+ offset = (offset & ~0x6000) | bitswap<2>(offset, 13, 14) << 13;
+ switch (offset & 0x7800)
+ {
+ case 0x0000:
+ case 0x0800:
+ break; // PRG banking at $8000 ignored
+ case 0x1000:
+ prg32(BIT(data, 2, 2));
+ if (!(offset & 3)) // $9000 is also VRC4 mirroring
+ nes_konami_vrc4_device::write_h(offset, data);
+ break;
+ case 0x1800:
+ LOG("Extended Audio write, data %x!", data & 0x0f); // pcmwrite(0x4011, (V & 0xf) << 3); (etabeta's original comment, FCEUX code)
+ break;
+ default:
+ nes_konami_vrc4_device::write_h(offset, data);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ BTL-SHUIGUANPIPE
+
+ Games: Shui Guan Pipe (Gimmick Pirate)
+
+ VRC4 clone that differs in its PRG banking only.
+
+ iNES: mapper 183
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+u8 nes_shuiguan_device::read_m(offs_t offset)
+{
+ LOGMASKED(LOG_HIFREQ, "shuiguan read_m, offset: %04x\n", offset);
+ return m_prg[(m_reg * 0x2000 + offset) & (m_prg_size - 1)];
+}
+
+void nes_shuiguan_device::write_m(offs_t offset, u8 data)
+{
+ LOG("shuiguan write_m, offset: %04x, data: %02x\n", offset, data);
+ if ((offset & 0x1800) == 0x800)
+ m_reg = offset & 0x1f;
+}
+
+void nes_shuiguan_device::write_h(offs_t offset, u8 data)
+{
+ LOG("shuiguan write_h, offset: %04x, data: %02x\n", offset, data);
+
+ switch (offset & 0x7800)
+ {
+ case 0x0000:
+ case 0x1000:
+ break; // writes to $8000 and $9000 ignored
+ case 0x0800:
+ prg8_89(data);
+ break;
+ case 0x2000:
+ prg8_cd(data);
+ break;
+ case 0x2800:
+ prg8_ab(data);
+ break;
+ default:
+ nes_konami_vrc4_device::write_h(offset, data);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ Board UNL-T-230
+
+ Games: Dragon Ball Z IV (Unl)
+
+ VRC4 clone that uses CHRRAM instead of CHRROM and
+ has nonstandard PRG banking.
+
+ NES 2.0: mapper 529
+
+ In MAME: Supported.
+
+ TODO: This cart and its appearance on the 2yudb set
+ have IRQ timing issues that cause a bouncing status
+ bar in fights. Other emulators also have issues
+ on the split line so perhaps some noise is expected?
+
+ -------------------------------------------------*/
+
+void nes_t230_device::write_h(offs_t offset, u8 data)
+{
+ LOG("t230 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ switch (offset & 0x7000)
+ {
+ case 0x0000:
+ break; // PRG banking at $8000 ignored
+ case 0x2000:
+ prg16_89ab(data);
+ break;
+ default:
+ nes_konami_vrc4_device::write_h(offset, data);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ UNL-TF1201
+
+ Games: Leathal Weapon (Leathal Enforcers clone)
+
+ VRC4 clone where the only known difference is in the
+ IRQ behavior. This clone does not copy the IRQ reload
+ bit to the enable bit on writes to IRQ acknowledge.
+
+ NES 2.0: mapper 298
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_tf1201_device::irq_ack_w()
+{
+ set_irq_line(CLEAR_LINE);
+}
+
+/*-------------------------------------------------
+
+ Board UNL-TH2131-1
+
+ Games: Batman pirate (Dynacon)
+
+ VRC2 clone with an added IRQ timer. A selectable 4-bit
+ latch controls the duration as it is decremented
+ relative to another internal 12-bit counter.
+
+ NES 2.0: mapper 308
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+TIMER_CALLBACK_MEMBER(nes_th21311_device::irq_timer_tick)
+{
+ if (m_irq_enable)
+ {
+ m_irq_count = (m_irq_count + 1) & 0xfff; // 12-bit counter
+ if (m_irq_count == 0x800)
+ m_irq_latch--;
+ if (!m_irq_latch && m_irq_count < 0x800)
+ set_irq_line(ASSERT_LINE);
+ }
+}
+
+void nes_th21311_device::write_h(offs_t offset, u8 data)
+{
+ LOG("th21311 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ if ((offset & 0x7000) == 0x7000)
+ {
+ switch (offset & 3)
+ {
+ case 0:
+ m_irq_enable = 0;
+ m_irq_count = 0;
+ set_irq_line(CLEAR_LINE);
+ break;
+ case 1:
+ m_irq_enable = 1;
+ break;
+ case 3:
+ m_irq_latch = data >> 4;
+ break;
+ }
+ }
+ else
+ nes_konami_vrc2_device::write_h(offset, data);
+}
+
+/*-------------------------------------------------
+
+ Waixing San Guo Zhi Board, Henggedianzi UNL-SHJY3
+
+ Games: San Guo Zhi (mapper 252), several Chinese
+ hacks of Dragon Ball games (mapper 253)
+
+ VRC4 clones that substitute 2K of CHRRAM in place for
+ two of the standard 1K CHRROM pages. Unusually this is
+ done by a GAL looking at certain address bits of the
+ PPU's address space, as the PPU writes pattern tables.
+
+ iNES: mapper 252 and mapper 253
+
+ In MAME: Supported.
+
+ TODO: Why does Sanguozhi flicker every second or two?
+
+ -------------------------------------------------*/
+
+void nes_waixing_sgz_device::write_h(offs_t offset, u8 data)
+{
+ LOG("waixing_sgz write_h, offset: %04x, data: %02x\n", offset, data);
+
+ nes_konami_vrc4_device::write_h(offset, data);
+
+ for (int bank = 0; bank < 8; bank++)
+ if ((m_mmc_vrom_bank[bank] & m_chr_mask) == m_chr_match)
+ chr1_x(bank, m_mmc_vrom_bank[bank] & 1, CHRRAM);
+}
+
+void nes_waixing_sgz_device::chr_w(offs_t offset, u8 data)
+{
+ device_nes_cart_interface::chr_w(offset, data);
+
+ switch (m_mmc_vrom_bank[BIT(offset, 10, 3)])
+ {
+ case 0x88:
+ m_chr_mask = 0xfc;
+ m_chr_match = 0x4c;
+ break;
+ case 0xc2:
+ m_chr_mask = 0xfe;
+ m_chr_match = 0x7c;
+ break;
+ case 0xc8:
+ m_chr_mask = 0xfe;
+ m_chr_match = 0x04;
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ MULTIGAME CARTS BASED ON VRC
+
+ -------------------------------------------------*/
+
+/*-------------------------------------------------
+
+ Board BTL-2YUDB
+
+ Games: 2 in 1 Datach Yu Yu Hakusho + Dragon Ball Z
+
+ VRC4 clone that uses CHRRAM instead of the usual
+ CHRROM and has a bit for selecting the outer PRG bank.
+
+ NES 2.0: mapper 520
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_2yudb_device::write_h(offs_t offset, u8 data)
+{
+ LOG("2yudb write_h, offset: %04x, data: %02x\n", offset, data);
+
+ nes_konami_vrc4_device::write_h(offset, data);
+
+ if (offset >= 0x3000 && offset < 0x7000 && !BIT(offset, m_vrc_ls_prg_b))
+ {
+ u8 bank = ((offset >> 12) - 3) * 2 + BIT(offset, m_vrc_ls_prg_a);
+ m_outer = (m_mmc_vrom_bank[bank] & 0x08) << 2;
+ set_prg();
+ }
+}
+
+/*-------------------------------------------------
+
+ Board BMC-830506C
+
+ Games: 1995 Super HiK 4 in 1 (JY-005)
+
+ VRC4 clone with banking for multicart menu.
+
+ NES 2.0: mapper 362
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_bmc_830506c_device::irq_ack_w()
+{
+ set_irq_line(CLEAR_LINE);
+}
+
+void nes_bmc_830506c_device::write_h(offs_t offset, u8 data)
+{
+ LOG("bmc_830506c write_h, offset: %04x, data: %02x\n", offset, data);
+
+ nes_konami_vrc4_device::write_h(offset, data);
+
+ if (offset >= 0x3000 && offset < 0x7000 && BIT(offset, m_vrc_ls_prg_b))
+ {
+ u8 bank = ((offset >> 12) - 3) * 2 + BIT(offset, m_vrc_ls_prg_a);
+ m_outer = (m_mmc_vrom_bank[bank] & 0x180) >> 3;
+ set_prg();
+ }
+}
+
+/*-------------------------------------------------
+
+ Board BMC-831128C
+
+ Games: 1995 New Series Super 2 in 1
+
+ Weird clone that seems to be part Konami VRC4 (IRQ),
+ and part Sunsoft FME-7 (banking/mirroring).
+
+ NES 2.0: mapper 528
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+
+u8 nes_bmc_831128c_device::read_m(offs_t offset)
+{
+ u8 data = 0;
+ if (m_reg == 1)
+ data = device_nes_cart_interface::read_m(offset);
+ else
+ data = m_prg[(m_reg * 0x2000 + offset) & (m_prg_size - 1)];
+ LOGMASKED(LOG_HIFREQ, "bmc_831128c read_m, offset: %04x, data: %02x\n", offset, data);
+ return data;
+}
+
+void nes_bmc_831128c_device::write_m(offs_t offset, u8 data)
+{
+ LOGMASKED(LOG_HIFREQ, "bmc_831128c write_m, offset: %04x, data: %02x\n", offset, data);
+
+ if (m_reg == 1)
+ device_nes_cart_interface::write_m(offset, data);
+}
+
+void nes_bmc_831128c_device::write_h(offs_t offset, u8 data)
+{
+ LOG("bmc_831128c write_h, offset: %04x, data: %02x\n", offset, data);
+
+ u8 page = offset >> 12;
+ if (page != 2 && page != 4) // ignore writes except $Axxx and $Cxxx
+ return;
+
+ int outer = BIT(offset, 14) << 4;
+ prg16_cdef(outer ? m_prg_chunks - 1 : 7);
+
+ u8 reg = offset & 0x0f;
+ switch (reg)
+ {
+ case 0x0: case 0x1: case 0x2: case 0x3:
+ case 0x4: case 0x5: case 0x6: case 0x7:
+ chr1_x(reg, (outer << 4) | data, m_chr_source);
+ break;
+ case 0x8:
+ m_reg = data;
+ break;
+ case 0x9:
+ case 0xa:
+ prg8_x(reg - 9, outer + (data & (outer | 0x0f)));
+ break;
+ // case 0xb: do nothing
+ case 0xc:
+ set_mirror(data);
+ break;
+ case 0xd:
+ irq_ctrl_w(data);
+ break;
+ case 0xe:
+ irq_ack_w();
+ break;
+ case 0xf:
+ m_irq_count_latch = data;
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ Board BMC-KL-06
+
+ Games: 1993 New 860 in 1 Over-Valued Golden Version Games
+
+ VRC4 clone with banking for multicart menu.
+
+ NES 2.0: mapper 447
+
+ In MAME: Supported.
+
+ TODO: There must be jumper settings since this is
+ showing up as a 1650 in 1.
+
+ -------------------------------------------------*/
+
+void nes_bmc_kl06_device::set_prg()
+{
+ u8 outer = (m_reg & 0x03) << 4;
+
+ if (BIT(m_reg, 2))
+ {
+ u8 bank_lo = outer | m_mmc_prg_bank[0];
+ u8 bank_hi = outer | m_mmc_prg_bank[1];
+ u8 mode = ~m_reg & 0x02;
+ prg8_89(bank_lo & ~mode);
+ prg8_ab(bank_hi & ~mode);
+ prg8_cd(bank_lo | mode);
+ prg8_ef(bank_hi | mode);
+ }
+ else
+ nes_konami_vrc4_device::set_prg(outer, 0x0f);
+}
+
+void nes_bmc_kl06_device::write_m(offs_t offset, u8 data)
+{
+ LOG("bmc_kl06 write_m, offset: %04x, data: %02x\n", offset, data);
+
+ // 2K RAM for Crisis Force overlays control register
+ nes_konami_vrc4_device::write_m(offset, data);
+
+ if (!(m_reg & 1)) // lock bit
+ {
+ m_reg = offset;
+ set_prg();
+ set_chr();
+ }
+}