diff options
Diffstat (limited to 'src/devices/bus/nes/mmc3_clones.cpp')
-rw-r--r-- | src/devices/bus/nes/mmc3_clones.cpp | 2588 |
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 |