summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/nes/waixing.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/nes/waixing.c')
-rw-r--r--src/devices/bus/nes/waixing.c1244
1 files changed, 1244 insertions, 0 deletions
diff --git a/src/devices/bus/nes/waixing.c b/src/devices/bus/nes/waixing.c
new file mode 100644
index 00000000000..8a223a8e295
--- /dev/null
+++ b/src/devices/bus/nes/waixing.c
@@ -0,0 +1,1244 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli
+/***********************************************************************************************************
+
+
+ NES/Famicom cartridge emulation for Waixing PCBs
+
+ Here we emulate the various PCBs used by Waixing for its games
+
+ TODO:
+ - investigate the PPU issues causing some games not to have sprites (e.g. some games using mappers 15, 164,
+ 242, 249)
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "waixing.h"
+
+#include "cpu/m6502/m6502.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_WAIXING_A = &device_creator<nes_waixing_a_device>;
+const device_type NES_WAIXING_A1 = &device_creator<nes_waixing_a1_device>;
+const device_type NES_WAIXING_B = &device_creator<nes_waixing_b_device>;
+const device_type NES_WAIXING_C = &device_creator<nes_waixing_c_device>;
+const device_type NES_WAIXING_D = &device_creator<nes_waixing_d_device>;
+const device_type NES_WAIXING_E = &device_creator<nes_waixing_e_device>;
+const device_type NES_WAIXING_F = &device_creator<nes_waixing_f_device>;
+const device_type NES_WAIXING_G = &device_creator<nes_waixing_g_device>;
+const device_type NES_WAIXING_H = &device_creator<nes_waixing_h_device>;
+const device_type NES_WAIXING_H1 = &device_creator<nes_waixing_h1_device>;
+const device_type NES_WAIXING_I = &device_creator<nes_waixing_i_device>;
+const device_type NES_WAIXING_J = &device_creator<nes_waixing_j_device>;
+const device_type NES_WAIXING_SH2 = &device_creator<nes_waixing_sh2_device>;
+const device_type NES_WAIXING_SEC = &device_creator<nes_waixing_sec_device>;
+const device_type NES_WAIXING_SGZ = &device_creator<nes_waixing_sgz_device>;
+const device_type NES_WAIXING_SGZLZ = &device_creator<nes_waixing_sgzlz_device>;
+const device_type NES_WAIXING_FFV = &device_creator<nes_waixing_ffv_device>;
+const device_type NES_WAIXING_WXZS = &device_creator<nes_waixing_wxzs_device>;
+const device_type NES_WAIXING_DQ8 = &device_creator<nes_waixing_dq8_device>;
+const device_type NES_WAIXING_WXZS2 = &device_creator<nes_waixing_wxzs2_device>;
+const device_type NES_WAIXING_FS304 = &device_creator<nes_waixing_fs304_device>;
+
+
+nes_waixing_a_device::nes_waixing_a_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_waixing_a_device::nes_waixing_a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_WAIXING_A, "NES Cart Waixing Type A PCB", tag, owner, clock, "nes_waixing_a", __FILE__)
+{
+}
+
+nes_waixing_a1_device::nes_waixing_a1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_waixing_a_device(mconfig, NES_WAIXING_A1, "NES Cart Waixing Type A (Alt) PCB", tag, owner, clock, "nes_waixing_a1", __FILE__)
+{
+}
+
+nes_waixing_b_device::nes_waixing_b_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_waixing_a_device(mconfig, NES_WAIXING_B, "NES Cart Waixing Type B PCB", tag, owner, clock, "nes_waixing_b", __FILE__)
+{
+}
+
+nes_waixing_c_device::nes_waixing_c_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_waixing_a_device(mconfig, NES_WAIXING_C, "NES Cart Waixing Type C PCB", tag, owner, clock, "nes_waixing_c", __FILE__)
+{
+}
+
+nes_waixing_d_device::nes_waixing_d_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_waixing_a_device(mconfig, NES_WAIXING_D, "NES Cart Waixing Type D PCB", tag, owner, clock, "nes_waixing_d", __FILE__)
+{
+}
+
+nes_waixing_e_device::nes_waixing_e_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_waixing_a_device(mconfig, NES_WAIXING_E, "NES Cart Waixing Type E PCB", tag, owner, clock, "nes_waixing_e", __FILE__)
+{
+}
+
+nes_waixing_f_device::nes_waixing_f_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_waixing_a_device(mconfig, NES_WAIXING_F, "NES Cart Waixing Type F PCB", tag, owner, clock, "nes_waixing_f", __FILE__)
+{
+}
+
+nes_waixing_g_device::nes_waixing_g_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_waixing_a_device(mconfig, NES_WAIXING_G, "NES Cart Waixing Type G PCB", tag, owner, clock, "nes_waixing_g", __FILE__)
+{
+}
+
+nes_waixing_h_device::nes_waixing_h_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_waixing_h_device::nes_waixing_h_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_WAIXING_H, "NES Cart Waixing Type H PCB", tag, owner, clock, "nes_waixing_h", __FILE__)
+{
+}
+
+nes_waixing_h1_device::nes_waixing_h1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_waixing_h_device(mconfig, NES_WAIXING_H1, "NES Cart Waixing Type H (Alt) PCB", tag, owner, clock, "nes_waixing_h1", __FILE__)
+{
+}
+
+nes_waixing_i_device::nes_waixing_i_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_waixing_a_device(mconfig, NES_WAIXING_I, "NES Cart Waixing Type I PCB", tag, owner, clock, "nes_waixing_i", __FILE__)
+{
+}
+
+nes_waixing_j_device::nes_waixing_j_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_waixing_a_device(mconfig, NES_WAIXING_J, "NES Cart Waixing Type J PCB", tag, owner, clock, "nes_waixing_j", __FILE__)
+{
+}
+
+nes_waixing_sh2_device::nes_waixing_sh2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_WAIXING_SH2, "NES Cart Waixing SH2 PCB", tag, owner, clock, "nes_waixing_sh2", __FILE__)
+{
+}
+
+nes_waixing_sec_device::nes_waixing_sec_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_txrom_device(mconfig, NES_WAIXING_SEC, "NES Cart Waixing Security Chip PCB", tag, owner, clock, "nes_waixing_sec", __FILE__)
+{
+}
+
+nes_waixing_sgz_device::nes_waixing_sgz_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_nrom_device(mconfig, NES_WAIXING_SGZ, "NES Cart Waixing San Guo Zhi PCB", tag, owner, clock, "nes_waixing_sgz", __FILE__)
+{
+}
+
+nes_waixing_sgzlz_device::nes_waixing_sgzlz_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_nrom_device(mconfig, NES_WAIXING_SGZLZ, "NES Cart Waixing San Guo Zhong Lie Zhuan PCB", tag, owner, clock, "nes_waixing_sgzlz", __FILE__)
+{
+}
+
+nes_waixing_ffv_device::nes_waixing_ffv_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_nrom_device(mconfig, NES_WAIXING_FFV, "NES Cart Waixing Final Fantasy V PCB", tag, owner, clock, "nes_waixing_ffv", __FILE__)
+{
+}
+
+nes_waixing_wxzs_device::nes_waixing_wxzs_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_nrom_device(mconfig, NES_WAIXING_WXZS, "NES Cart Waixing Wai Xing Zhan Shi PCB", tag, owner, clock, "nes_waixing_wxzs", __FILE__)
+{
+}
+
+nes_waixing_dq8_device::nes_waixing_dq8_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_nrom_device(mconfig, NES_WAIXING_DQ8, "NES Cart Waixing Dragon Quest VIII PCB", tag, owner, clock, "nes_waixing_dq8", __FILE__)
+{
+}
+
+nes_waixing_wxzs2_device::nes_waixing_wxzs2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_nrom_device(mconfig, NES_WAIXING_WXZS2, "NES Cart Waixing Wai Xing Zhan Shi 2 PCB", tag, owner, clock, "nes_waixing_wxzs2", __FILE__)
+{
+}
+
+nes_waixing_fs304_device::nes_waixing_fs304_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_nrom_device(mconfig, NES_WAIXING_FS304, "NES Cart Waixing FS-304 PCB", tag, owner, clock, "nes_waixing_fs304", __FILE__)
+{
+}
+
+
+void nes_waixing_a_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(mapper_ram));
+}
+
+void nes_waixing_a_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ mmc3_common_initialize(0xff, 0xff, 0);
+
+ memset(mapper_ram, 0, sizeof(mapper_ram));
+}
+
+void nes_waixing_f_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ mmc3_common_initialize(0xff, 0xff, 0);
+
+ memset(mapper_ram, 0, sizeof(mapper_ram));
+ m_mmc_prg_bank[0] = 0x00;
+ m_mmc_prg_bank[1] = 0x01;
+ m_mmc_prg_bank[2] = 0x4e;
+ m_mmc_prg_bank[3] = 0x4f;
+ set_prg(m_prg_base, m_prg_mask);
+}
+
+void nes_waixing_g_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ mmc3_common_initialize(0xff, 0xff, 0);
+
+ memset(mapper_ram, 0, sizeof(mapper_ram));
+ m_mmc_prg_bank[0] = 0x00;
+ m_mmc_prg_bank[1] = 0x01;
+ m_mmc_prg_bank[2] = 0x3e;
+ m_mmc_prg_bank[3] = 0x3f;
+ m_mmc_vrom_bank[0] = 0x00;
+ m_mmc_vrom_bank[1] = 0x02;
+ m_mmc_vrom_bank[2] = 0x04;
+ m_mmc_vrom_bank[3] = 0x05;
+ m_mmc_vrom_bank[4] = 0x06;
+ m_mmc_vrom_bank[5] = 0x07;
+ m_mmc_vrom_bank[6] = 0x01;
+ m_mmc_vrom_bank[7] = 0x03;
+ set_prg(m_prg_base, m_prg_mask);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+}
+
+void nes_waixing_j_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_waixing_j_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ m_reg[0] = 0x01;
+ m_reg[1] = 0x02;
+ m_reg[2] = 0x7e;
+ m_reg[3] = 0x7f;
+ mmc3_common_initialize(0xff, 0xff, 0);
+ set_prg(m_prg_base, m_prg_mask);
+}
+
+void nes_waixing_sh2_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_waixing_sh2_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ m_reg[0] = m_reg[1] = 0;
+ mmc3_common_initialize(0xff, 0xff, 0);
+}
+
+void nes_waixing_sec_device::device_start()
+{
+ mmc3_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_waixing_sec_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+
+ m_reg = 0;
+ mmc3_common_initialize(0xff, 0xff, 0);
+}
+
+void nes_waixing_sgz_device::device_start()
+{
+ common_start();
+ save_item(NAME(m_irq_enable));
+ save_item(NAME(m_irq_enable_latch));
+ save_item(NAME(m_irq_count));
+ save_item(NAME(m_irq_count_latch));
+ save_item(NAME(m_mmc_vrom_bank));
+}
+
+void nes_waixing_sgz_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ prg16_89ab(0);
+ prg16_cdef(m_prg_chunks - 1);
+ chr8(0, m_chr_source);
+
+ m_irq_enable = 0;
+ m_irq_enable_latch = 0;
+ m_irq_count = 0;
+ m_irq_count_latch = 0;
+
+ memset(m_mmc_vrom_bank, 0, sizeof(m_mmc_vrom_bank));
+}
+
+void nes_waixing_sgzlz_device::device_start()
+{
+ common_start();
+ save_item(NAME(m_latch));
+}
+
+void nes_waixing_sgzlz_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ prg32(0);
+ chr8(0, m_chr_source);
+
+ m_latch = 0;
+}
+
+void nes_waixing_ffv_device::device_start()
+{
+ common_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_waixing_ffv_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ prg16_89ab(0);
+ prg16_cdef(0x1f);
+ chr8(0, m_chr_source);
+
+ m_reg[0] = m_reg[1] = 0;
+}
+
+void nes_waixing_wxzs_device::device_start()
+{
+ common_start();
+}
+
+void nes_waixing_wxzs_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ prg32(0);
+ chr8(0, m_chr_source);
+}
+
+void nes_waixing_dq8_device::device_start()
+{
+ common_start();
+}
+
+void nes_waixing_dq8_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ prg32(0);
+ chr8(0, m_chr_source);
+}
+
+void nes_waixing_wxzs2_device::device_start()
+{
+ common_start();
+}
+
+void nes_waixing_wxzs2_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ prg32(0);
+ chr8(0, m_chr_source);
+ set_nt_mirroring(PPU_MIRROR_VERT);
+}
+
+void nes_waixing_fs304_device::device_start()
+{
+ common_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_waixing_fs304_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ prg32(0);
+ chr8(0, m_chr_source);
+
+ memset(m_reg, 0x00, sizeof(m_reg));
+}
+
+
+
+
+
+/*-------------------------------------------------
+ mapper specific handlers
+ -------------------------------------------------*/
+
+/*-------------------------------------------------
+
+ Waixing Board Type A
+
+ Games: Columbus - Ougon no Yoake (C), Ji Jia Zhan Shi,
+ Jia A Fung Yun, Wei Luo Chuan Qi
+
+ This mapper is quite similar to MMC3, but with two differences:
+ mirroring is not the same, and when VROM banks 8,9 are accessed
+ they point to CHRRAM and not CHRROM.
+
+ iNES: mapper 74
+
+ In MESS: Supported
+
+ -------------------------------------------------*/
+
+/* MIRROR_LOW and MIRROR_HIGH are swapped! */
+void nes_waixing_a_device::set_mirror(UINT8 nt)
+{
+ switch (nt)
+ {
+ case 0:
+ case 1:
+ set_nt_mirroring(nt ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ break;
+ case 2:
+ set_nt_mirroring(PPU_MIRROR_LOW);
+ break;
+ case 3:
+ set_nt_mirroring(PPU_MIRROR_HIGH);
+ break;
+ default:
+ LOG_MMC(("Mapper set NT to invalid value %02x", nt));
+ break;
+ }
+}
+
+/* Luo Ke Ren X only works with this */
+void nes_waixing_a_device::chr_cb(int start, int bank, int source)
+{
+ int chr_src = (bank <= 9) ? CHRRAM : CHRROM;
+ chr1_x(start, bank, chr_src);
+}
+
+/* Ji Jia Zhan Shi only works with this */
+void nes_waixing_a1_device::chr_cb(int start, int bank, int source)
+{
+ int chr_src = ((bank == 8) || (bank == 9)) ? CHRRAM : CHRROM;
+ chr1_x(start, bank, chr_src);
+}
+
+WRITE8_MEMBER(nes_waixing_a_device::waixing_write)
+{
+ LOG_MMC(("waixing_write, offset: %04x, data: %02x\n", offset, data));
+
+ switch (offset & 0x6001)
+ {
+ case 0x2000:
+ set_mirror(data); //maybe data & 0x03?
+ break;
+
+ case 0x2001:
+ break;
+
+ default:
+ txrom_write(space, offset, data, mem_mask);
+ break;
+ }
+}
+
+READ8_MEMBER(nes_waixing_a_device::read_l)
+{
+ LOG_MMC(("waixing read_l, offset: %04x\n", offset));
+ offset += 0x100;
+ if (offset >= 0x1000 && offset < 0x1400)
+ return mapper_ram[offset & 0x3ff];
+ else
+ return 0xff;
+}
+
+WRITE8_MEMBER(nes_waixing_a_device::write_l)
+{
+ LOG_MMC(("waixing write_l, offset: %04x, data: %02x\n", offset, data));
+ offset += 0x100;
+ if (offset >= 0x1000 && offset < 0x1400)
+ mapper_ram[offset & 0x3ff] = data;
+}
+
+
+/*-------------------------------------------------
+
+ Waixing Board Type B
+
+ Games: Sugoro Quest (C)
+
+ MMC3 clone. This is a minor modification of Mapper 74,
+ in the sense that it is the same board except for the
+ CHRRAM pages.
+
+ iNES: mapper 191
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+void nes_waixing_b_device::chr_cb(int start, int bank, int source)
+{
+ int chr_src = BIT(bank, 7) ? CHRRAM : CHRROM;
+ chr1_x(start, bank, chr_src);
+}
+
+/*-------------------------------------------------
+
+ Waixing Board Type C
+
+ Games: Ying Lie Qun Xia Zhuan, Young Chivalry
+
+ MMC3 clone. This is a minor modification of Mapper 74,
+ in the sense that it is the same board except for the
+ CHRRAM pages.
+
+ iNES: mapper 192
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+void nes_waixing_c_device::chr_cb(int start, int bank, int source)
+{
+ int chr_src = ((bank == 0x08) || (bank == 0x09) || (bank == 0x0a) || (bank == 0x0b)) ? CHRRAM : CHRROM;
+ chr1_x(start, bank, chr_src);
+}
+
+/*-------------------------------------------------
+
+ Waixing Board Type D
+
+ Games: Super Robot Taisen (C)
+
+ MMC3 clone. This is a minor modification of Mapper 74,
+ in the sense that it is the same board except for the
+ CHRRAM pages.
+
+ iNES: mapper 194
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+void nes_waixing_d_device::chr_cb(int start, int bank, int source)
+{
+ int chr_src = (bank < 0x02) ? CHRRAM : CHRROM;
+ chr1_x(start, bank, chr_src);
+}
+
+/*-------------------------------------------------
+
+ Waixing Board Type E
+
+ Games: Captain Tsubasa Vol. II (C), Chaos World, God
+ Slayer (C), Zu Qiu Xiao Jiang
+
+ MMC3 clone. This is a minor modification of Mapper 74,
+ in the sense that it is the same board except for the
+ CHRRAM pages.
+
+ iNES: mapper 195
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+void nes_waixing_e_device::chr_cb(int start, int bank, int source)
+{
+ int chr_src = (bank < 0x04) ? CHRRAM : CHRROM;
+ chr1_x(start, bank, chr_src);
+}
+
+
+/*-------------------------------------------------
+
+ Waixing Board Type F
+
+ Games: Tenchi wo Kurau II (C)
+
+ MMC3 clone.
+
+ iNES: mapper 198
+
+ In MESS: Preliminary support.
+
+ -------------------------------------------------*/
+
+void nes_waixing_f_device::chr_cb(int start, int bank, int source)
+{
+ chr1_x(start, bank, CHRRAM);
+}
+
+void nes_waixing_f_device::prg_cb(int start, int bank)
+{
+// if (bank > 0x3f)
+// bank = 0x40 | (bank & 0xf);
+ prg8_x(start, bank);
+}
+
+void nes_waixing_f_device::set_prg( int prg_base, int prg_mask )
+{
+ UINT8 prg_flip = (m_latch & 0x40) ? 2 : 0;
+
+ prg_cb(0, m_mmc_prg_bank[0 ^ prg_flip]);
+ prg_cb(1, m_mmc_prg_bank[1]);
+ prg_cb(2, m_mmc_prg_bank[2 ^ prg_flip]);
+ prg_cb(3, m_mmc_prg_bank[3]);
+}
+
+WRITE8_MEMBER(nes_waixing_f_device::write_h)
+{
+ UINT8 cmd;
+ LOG_MMC(("waixing_f write_h, offset: %04x, data: %02x\n", offset, data));
+
+ switch (offset & 0x6001)
+ {
+ case 0x0001:
+ cmd = m_latch & 0x07;
+ 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:
+ case 8:
+ case 9:
+ m_mmc_prg_bank[cmd - 6] = data;
+ //printf("prg bank %d value %x\n", cmd - 6, data);
+ set_prg(m_prg_base, m_prg_mask);
+ break;
+ }
+ break;
+
+ case 0x2001:
+ break;
+
+ default:
+ waixing_write(space, offset, data, mem_mask);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ Waixing Board Type G
+
+ Games: San Guo Zhi 2, Dragon Ball Z Gaiden (C), Dragon
+ Ball Z II (C)
+
+ MMC3 clone, capable of switching all 4 PRG banks
+
+ iNES: mapper 199
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+void nes_waixing_g_device::chr_cb(int start, int bank, int source)
+{
+ int chr_src = (bank < 0x08) ? CHRRAM : CHRROM;
+ chr1_x(start, bank, chr_src);
+}
+
+void nes_waixing_g_device::set_chr(UINT8 chr, int chr_base, int chr_mask)
+{
+ UINT8 chr_page = (m_latch & 0x80) >> 5;
+
+ chr_cb(chr_page ^ 0, chr_base | (m_mmc_vrom_bank[0] & chr_mask), chr);
+ chr_cb(chr_page ^ 1, chr_base | (m_mmc_vrom_bank[6] & chr_mask), chr);
+ chr_cb(chr_page ^ 2, chr_base | (m_mmc_vrom_bank[1] & chr_mask), chr);
+ chr_cb(chr_page ^ 3, chr_base | (m_mmc_vrom_bank[7] & chr_mask), chr);
+ chr_cb(chr_page ^ 4, chr_base | (m_mmc_vrom_bank[2] & chr_mask), chr);
+ chr_cb(chr_page ^ 5, chr_base | (m_mmc_vrom_bank[3] & chr_mask), chr);
+ chr_cb(chr_page ^ 6, chr_base | (m_mmc_vrom_bank[4] & chr_mask), chr);
+ chr_cb(chr_page ^ 7, chr_base | (m_mmc_vrom_bank[5] & chr_mask), chr);
+}
+
+WRITE8_MEMBER(nes_waixing_g_device::write_h)
+{
+ UINT8 cmd;
+ LOG_MMC(("waixing_g write_h, offset: %04x, data: %02x\n", offset, data));
+
+ switch (offset & 0x6001)
+ {
+ case 0x0001:
+ cmd = m_latch & 0x0f;
+ switch (cmd)
+ {
+ case 0: case 1:
+ 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:
+ case 8:
+ case 9:
+ m_mmc_prg_bank[cmd - 6] = data;
+ set_prg(m_prg_base, m_prg_mask);
+ break;
+ case 0x0a: case 0x0b:
+ m_mmc_vrom_bank[cmd - 4] = data;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ break;
+ }
+ break;
+
+ default:
+ waixing_write(space, offset, data, mem_mask);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ Waixing Board Type H
+
+ Games: Ying Xiong Yuan Yi Jing Chuan Qi, Yong Zhe Dou E
+ Long - Dragon Quest VII
+
+ MMC3 clone. More info to come.
+
+ Notice that Chinese Zelda translation stops working if
+ WRAM protect bit is ignored (i.e. if writes to 0x2001
+ are skipped)! OTOH, Chinese Monster Maker 1/2 translations
+ and Zheng Ba ShiJi stop working if WRAM protect is
+ accounted. So we split the board into two subtypes
+
+ iNES: mapper 245
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+void nes_waixing_h_device::chr_cb(int start, int bank, int source)
+{
+ if (source == CHRROM)
+ chr1_x(start, bank, source);
+}
+
+WRITE8_MEMBER(nes_waixing_h_device::write_h)
+{
+ UINT8 cmd;
+ LOG_MMC(("waixing_h write_h, offset: %04x, data: %02x\n", offset, data));
+
+ switch (offset & 0x6001)
+ {
+ case 0x0001:
+ cmd = m_latch & 0x07;
+ switch (cmd)
+ {
+ case 0: // in this case we set prg_base in addition to m_mmc_vrom_bank!
+ m_prg_base = (data << 5) & 0x40;
+ m_prg_mask = 0x3f;
+ set_prg(m_prg_base, m_prg_mask);
+ case 1:
+ 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;
+ case 0x0a: case 0x0b: // CHR switches in 1K banks only, and bank1 & bank3 are controlled by these
+ m_mmc_vrom_bank[cmd - 4] = data;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ break;
+ }
+ break;
+
+ case 0x2001:
+ break;
+
+ default:
+ txrom_write(space, offset, data, mem_mask);
+ break;
+ }
+}
+
+WRITE8_MEMBER(nes_waixing_h1_device::write_h)
+{
+ UINT8 cmd;
+ LOG_MMC(("waixing_h1 write_h, offset: %04x, data: %02x\n", offset, data));
+
+ switch (offset & 0x6001)
+ {
+ case 0x0001:
+ cmd = m_latch & 0x07;
+ switch (cmd)
+ {
+ case 0: // in this case we set prg_base in addition to m_mmc_vrom_bank!
+ m_prg_base = (data << 5) & 0x40;
+ m_prg_mask = 0x3f;
+ set_prg(m_prg_base, m_prg_mask);
+ case 1:
+ 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;
+ case 0x0a: case 0x0b: // CHR switches in 1K banks only, and bank1 & bank3 are controlled by these
+ m_mmc_vrom_bank[cmd - 4] = data;
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ break;
+ }
+ break;
+
+ default:
+ txrom_write(space, offset, data, mem_mask);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ Waixing Board Type J
+
+ Games: Final Fantasy III (C)
+
+ MMC3 clone.
+
+ In MESS: Preliminary support.
+
+ -------------------------------------------------*/
+
+void nes_waixing_j_device::set_prg( int prg_base, int prg_mask )
+{
+ UINT8 prg_flip = (m_latch & 0x40) ? 2 : 0;
+
+ prg_cb(0, m_reg[0 ^ prg_flip]);
+ prg_cb(1, m_reg[1]);
+ prg_cb(2, m_reg[2 ^ prg_flip]);
+ prg_cb(3, m_reg[3]);
+}
+
+WRITE8_MEMBER(nes_waixing_j_device::write_h)
+{
+ UINT8 cmd;
+ LOG_MMC(("waixing_f write_h, offset: %04x, data: %02x\n", offset, data));
+
+ switch (offset & 0x6001)
+ {
+ case 0x0001:
+ cmd = m_latch & 0x07;
+ 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:
+ case 8:
+ case 9:
+ m_reg[cmd - 6] = data;
+ set_prg(m_prg_base, m_prg_mask);
+ break;
+ }
+ break;
+
+// case 0x2001:
+// break;
+
+ default:
+ waixing_write(space, offset, data, mem_mask);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ Waixing SH2 Board
+
+ Games: Fire Emblem (C) and Fire Emblem Gaiden (C)
+
+ MMC3 clone with different access to CHR
+
+ iNES: mapper 165
+
+ In MESS: Partially Supported.
+
+ -------------------------------------------------*/
+
+void nes_waixing_sh2_device::chr_cb(int start, int bank, int source)
+{
+ chr4_0(m_reg[0], m_reg[0] ? CHRRAM : CHRROM);
+ chr4_4(m_reg[1], m_reg[1] ? CHRRAM : CHRROM);
+}
+
+READ8_MEMBER(nes_waixing_sh2_device::chr_r)
+{
+ int bank = offset >> 10;
+ UINT8 val = m_chr_access[bank][offset & 0x3ff]; // this would be usual return value
+ int chr_helper;
+
+ switch (offset & 0xff8)
+ {
+ case 0xfd0: chr_helper = (bank & 0x4) | 0x0; break;
+ case 0xfe8: chr_helper = (bank & 0x4) | 0x2; break;
+ default: return val;
+ }
+
+ m_reg[offset >> 12] = chr_helper;
+ if (offset & 0x1000)
+ chr4_4(m_reg[1], m_reg[1] ? CHRRAM : CHRROM);
+ else
+ chr4_0(m_reg[0], m_reg[0] ? CHRRAM : CHRROM);
+
+ return val;
+}
+
+/*-------------------------------------------------
+
+ Waixing Board with Security Chip
+
+ Games: Duo Bao Xiao Ying Hao - Guang Ming yu An Hei Chuan Shuo,
+ Myth Struggle, San Shi Liu Ji, Shui Hu Zhuan
+
+ MMC3 clone
+
+ iNES: mapper 249
+
+ In MESS: Partially Supported.
+
+ -------------------------------------------------*/
+
+void nes_waixing_sec_device::prg_cb(int start, int bank)
+{
+ if (m_reg)
+ bank = BITSWAP8(bank & 0x1f,7,6,5,2,1,3,4,0);
+
+ prg8_x(start, bank);
+}
+
+void nes_waixing_sec_device::chr_cb(int start, int bank, int source)
+{
+ if (m_reg)
+ bank = BITSWAP8(bank, 5,4,2,6,7,3,1,0);
+
+ chr1_x(start, bank, source);
+}
+
+WRITE8_MEMBER(nes_waixing_sec_device::write_l)
+{
+ LOG_MMC(("waixing_sec write_l, offset: %04x, data: %02x\n", offset, data));
+ offset += 0x100;
+
+ if (offset == 0x1000)
+ {
+ m_reg = data & 0x02;
+ set_prg(m_prg_base, m_prg_mask);
+ set_chr(m_chr_source, m_chr_base, m_chr_mask);
+ }
+}
+
+/*-------------------------------------------------
+
+ Waixing San Guo Zhi Board
+
+ Games: San Guo Zhi
+
+ This board uses Konami IRQ
+
+ iNES: mapper 252
+
+ In MESS: Unsupported.
+
+ -------------------------------------------------*/
+
+// same as Konami IRQ
+void nes_waixing_sgz_device::hblank_irq(int scanline, int vblank, int blanked)
+{
+ /* Increment & check the IRQ scanline counter */
+ if (m_irq_enable && (++m_irq_count == 0x100))
+ {
+ m_irq_count = m_irq_count_latch;
+ m_irq_enable = m_irq_enable_latch;
+ m_maincpu->set_input_line(M6502_IRQ_LINE, HOLD_LINE);
+ }
+}
+
+WRITE8_MEMBER(nes_waixing_sgz_device::write_h)
+{
+ UINT8 helper, bank;
+ LOG_MMC(("waixing_sgz write_h, offset: %04x, data: %02x\n", offset, data));
+
+ switch (offset & 0x7000)
+ {
+ case 0x0000:
+ prg8_89(data);
+ break;
+ case 0x2000:
+ prg8_ab(data);
+ break;
+ case 0x3000:
+ case 0x4000:
+ case 0x5000:
+ case 0x6000:
+ bank = ((offset & 0x7000) - 0x3000) / 0x0800 + ((offset & 0x0008) >> 3);
+ helper = offset & 0x04;
+ if (helper)
+ m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x0f) << 4);
+ else
+ m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0xf0) | (data & 0x0f);
+ chr1_x(bank, m_mmc_vrom_bank[bank], CHRROM);
+ break;
+ case 0x7000:
+ switch (offset & 0x0c)
+ {
+ case 0x00:
+ m_irq_count_latch = (m_irq_count_latch & 0xf0) | (data & 0x0f);
+ break;
+ case 0x04:
+ m_irq_count_latch = (m_irq_count_latch & 0x0f) | ((data & 0x0f) << 4);
+ break;
+ case 0x08:
+ m_irq_enable = data & 0x02;
+ m_irq_count_latch = data & 0x01;
+ if (data & 0x02)
+ m_irq_count = m_irq_count_latch;
+ break;
+ case 0x0c:
+ m_irq_enable = m_irq_enable_latch;
+ break;
+ }
+ break;
+ }
+}
+
+
+/*-------------------------------------------------
+
+ Waixing San Guo Zhong Lie Zhuan Board
+
+ Games: Fan Kong Jing Ying, San Guo Zhong Lie Zhuan, Xing
+ Ji Zheng Ba
+
+ iNES: mapper 178
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_waixing_sgzlz_device::write_l)
+{
+ LOG_MMC(("waixing_sgzlz write_l, offset: %04x, data: %02x\n", offset, data));
+
+ switch (offset)
+ {
+ case 0x700:
+ set_nt_mirroring(data ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ break;
+ case 0x701:
+ m_latch = (m_latch & 0x0c) | ((data >> 1) & 0x03);
+ prg32(m_latch);
+ break;
+ case 0x702:
+ m_latch = (m_latch & 0x03) | ((data << 2) & 0x0c);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ Waixing Final Fantasy V Board
+
+ Games: Darkseed, Digital Dragon, Final Fantasy V, Pocket
+ Monster Red
+
+ iNES: mapper 164
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_waixing_ffv_device::write_l)
+{
+ UINT8 helper;
+ LOG_MMC(("waixing_ffv write_l, offset: %04x, data: %02x\n", offset, data));
+ offset += 0x100; /* the checks work better on addresses */
+
+ if ((offset & 0x1200) == 0x1000)
+ {
+ m_reg[BIT(offset, 8)] = data;
+ helper = BIT(m_reg[1], 0) << 5;
+ switch (m_reg[0] & 0x70)
+ {
+ case 0x00:
+ case 0x20:
+ case 0x40:
+ case 0x60:
+ prg16_89ab(helper | ((m_reg[0] >> 1) & 0x10) | (m_reg[0] & 0x0f));
+ prg16_cdef(helper & 0x1f);
+ break;
+ case 0x50:
+ prg32((helper >> 1) | (m_reg[0] & 0x0f));
+ break;
+ case 0x70:
+ prg16_89ab(helper | ((m_reg[0] << 1) & 0x10) | (m_reg[0] & 0x0f));
+ prg16_cdef(helper & 0x1f);
+ break;
+ }
+ }
+}
+
+/*-------------------------------------------------
+
+ Waixing Zhan Shi Board
+
+ Games: Wai Xing Zhan Shi
+
+ Simple mapper: writes to 0x8000-0xffff sets prg32 banks to
+ (offset>>3)&f. written data&3 sets the mirroring (with
+ switched high/low compared to the standard one).
+
+ A crc check is required to support Dragon Quest VIII (which
+ uses a slightly different board)
+
+ iNES: mapper 242
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_waixing_wxzs_device::write_h)
+{
+ LOG_MMC(("waixing_zs write_h, offset: %04x, data: %02x\n", offset, data));
+
+ prg32(offset >> 3);
+
+ switch (data & 0x03)
+ {
+ case 0: set_nt_mirroring(PPU_MIRROR_VERT); break;
+ case 1: set_nt_mirroring(PPU_MIRROR_HORZ); break;
+ case 2: set_nt_mirroring(PPU_MIRROR_LOW); break;
+ case 3: set_nt_mirroring(PPU_MIRROR_HIGH); break;
+ }
+}
+
+/*-------------------------------------------------
+
+ Waixing Dragon Quest VIII Board
+
+ Games: Dragon Quest VIII
+
+ Simple mapper: writes to 0x8000-0xffff sets prg32 banks to
+ (offset>>3)&f.
+
+ iNES: mapper 242
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_waixing_dq8_device::write_h)
+{
+ LOG_MMC(("waixing_dq8 write_h, offset: %04x, data: %02x\n", offset, data));
+
+ prg32(offset >> 3);
+}
+
+
+/*-------------------------------------------------
+
+ Waixing WXZS2 / PS2 board
+
+ Games: Wai Xing Zhan Shi 2 (aka Phantasy Star 2),
+ Bao Xiao Tien Guo, Bio Hazard, Pokemon Gold, Subor (R)
+
+ iNES: mapper 15
+
+ In MESS: Supported
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_waixing_wxzs2_device::write_h)
+{
+ UINT8 flip = (data & 0x80) >> 7;
+ UINT8 helper = (data & 0x7f) << 1;
+
+ LOG_MMC(("waixing_wxzs2 write_h, offset: %04x, data: %02x\n", offset, data));
+
+ set_nt_mirroring(BIT(data, 6) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+
+ switch (offset & 0x0fff)
+ {
+ case 0x000:
+ prg8_89((helper + 0) ^ flip);
+ prg8_ab((helper + 1) ^ flip);
+ prg8_cd((helper + 2) ^ flip);
+ prg8_ef((helper + 3) ^ flip);
+ break;
+ case 0x001:
+ helper |= flip;
+ prg8_89(helper);
+ prg8_ab(helper + 1);
+ prg8_cd(helper + 1);
+ prg8_ef(helper + 1);
+ break;
+ case 0x002:
+ helper |= flip;
+ prg8_89(helper);
+ prg8_ab(helper);
+ prg8_cd(helper);
+ prg8_ef(helper);
+ break;
+ case 0x003:
+ helper |= flip;
+ prg8_89(helper);
+ prg8_ab(helper + 1);
+ prg8_cd(helper);
+ prg8_ef(helper + 1);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ Board UNL-FS304
+
+ Games: A Link to the Past by Waixing
+
+ iNES: mapper 162? (only found in UNIF format)
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_waixing_fs304_device::write_l)
+{
+ LOG_MMC(("fs304 write_l, offset: %04x, data: %02x\n", offset, data));
+ int bank;
+ offset += 0x100;
+
+ if (offset >= 0x1000)
+ {
+ m_reg[(offset >> 8) & 3] = data;
+ bank = ((m_reg[2] & 0x0f) << 4) | BIT(m_reg[1], 1) | (m_reg[0] & 0x0e);
+ prg32(bank);
+ chr8(0, CHRRAM);
+ }
+}