diff options
Diffstat (limited to 'src/devices/bus/nes/bootleg.c')
-rw-r--r-- | src/devices/bus/nes/bootleg.c | 1635 |
1 files changed, 1635 insertions, 0 deletions
diff --git a/src/devices/bus/nes/bootleg.c b/src/devices/bus/nes/bootleg.c new file mode 100644 index 00000000000..23b13b51711 --- /dev/null +++ b/src/devices/bus/nes/bootleg.c @@ -0,0 +1,1635 @@ +// license:BSD-3-Clause +// copyright-holders:Fabio Priuli +/*********************************************************************************************************** + + + NES/Famicom cartridge emulation for Bootleg PCBs + + + Here we emulate the PCBs used in FDS2NES conversions which are common in the Taiwanese & HK markets + Notice that many of these have unusual PRG sizes (32KB+8KB, 32KB+24KB) partially mapped in the WRAM + area, or WRAM overlapping the usual PRG area, so that we often skip the usual bankswitching mechanisms + in favor of direct handling of the PRG accesses + + TODO: + - review all PCBs and fix the starting banks (which are often the main problem of not working games) + - investigate pcbs listed in FCEUmm but with apparently no dumps available (LE05 and LH53) + + ***********************************************************************************************************/ + + +#include "emu.h" +#include "bootleg.h" + +#include "cpu/m6502/m6502.h" +#include "video/ppu2c0x.h" // this has to be included so that IRQ functions can access PPU_BOTTOM_VISIBLE_SCANLINE + + +#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_AX5705 = &device_creator<nes_ax5705_device>; +const device_type NES_SC127 = &device_creator<nes_sc127_device>; +const device_type NES_MARIOBABY = &device_creator<nes_mbaby_device>; +const device_type NES_ASN = &device_creator<nes_asn_device>; +const device_type NES_SMB3PIRATE = &device_creator<nes_smb3p_device>; +const device_type NES_BTL_DNINJA = &device_creator<nes_btl_dn_device>; +const device_type NES_WHIRLWIND_2706 = &device_creator<nes_whirl2706_device>; +const device_type NES_SMB2J = &device_creator<nes_smb2j_device>; +const device_type NES_SMB2JA = &device_creator<nes_smb2ja_device>; +const device_type NES_SMB2JB = &device_creator<nes_smb2jb_device>; +const device_type NES_09034A = &device_creator<nes_09034a_device>; +const device_type NES_TOBIDASE = &device_creator<nes_tobidase_device>; +const device_type NES_LH32 = &device_creator<nes_lh32_device>; +const device_type NES_LH10 = &device_creator<nes_lh10_device>; +const device_type NES_LH53 = &device_creator<nes_lh53_device>; +const device_type NES_2708 = &device_creator<nes_2708_device>; +const device_type NES_AC08 = &device_creator<nes_ac08_device>; +const device_type NES_UNL_BB = &device_creator<nes_unl_bb_device>; +const device_type NES_MMALEE = &device_creator<nes_mmalee_device>; +const device_type NES_SHUIGUAN = &device_creator<nes_shuiguan_device>; + + +nes_ax5705_device::nes_ax5705_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_AX5705, "NES Cart AX5705 PCB", tag, owner, clock, "nes_ax5705", __FILE__) +{ +} + +nes_sc127_device::nes_sc127_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_SC127, "NES Cart SC-127 PCB", tag, owner, clock, "nes_sc127", __FILE__) +{ +} + +nes_mbaby_device::nes_mbaby_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_MARIOBABY, "NES Cart Mario Baby Bootleg PCB", tag, owner, clock, "nes_mbaby", __FILE__) +{ +} + +nes_asn_device::nes_asn_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_ASN, "NES Cart Ai Senshi Nicol Bootleg PCB", tag, owner, clock, "nes_asn", __FILE__) +{ +} + +nes_smb3p_device::nes_smb3p_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_SMB3PIRATE, "NES Cart Super Mario Bros. 3 Pirate PCB", tag, owner, clock, "nes_smb3p", __FILE__) +{ +} + +nes_btl_dn_device::nes_btl_dn_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_BTL_DNINJA, "NES Cart DragonNinja Pirate PCB", tag, owner, clock, "nes_btl_dn", __FILE__) +{ +} + +nes_whirl2706_device::nes_whirl2706_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_WHIRLWIND_2706, "NES Cart Whirlwind 2706 PCB", tag, owner, clock, "nes_whirl2706", __FILE__) +{ +} + +nes_smb2j_device::nes_smb2j_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_SMB2J, "NES Cart Super Mario Bros. 2 Jpn PCB", tag, owner, clock, "nes_smb2j", __FILE__) +{ +} + +nes_smb2ja_device::nes_smb2ja_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_SMB2JA, "NES Cart Super Mario Bros. 2 Jpn (Alt) PCB", tag, owner, clock, "nes_smb2ja", __FILE__) +{ +} + +nes_smb2jb_device::nes_smb2jb_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_SMB2JB, "NES Cart Super Mario Bros. 2 Jpn (Alt 2) PCB", tag, owner, clock, "nes_smb2jb", __FILE__) +{ +} + +nes_09034a_device::nes_09034a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_09034A, "NES Cart 09-034A PCB", tag, owner, clock, "nes_09034a", __FILE__) +{ +} + +nes_tobidase_device::nes_tobidase_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_TOBIDASE, "NES Cart Tobidase Daisakusen Pirate PCB", tag, owner, clock, "nes_tobidase", __FILE__) +{ +} + +nes_lh32_device::nes_lh32_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_LH32, "NES Cart LH-32 Pirate PCB", tag, owner, clock, "nes_lh32", __FILE__) +{ +} + +nes_lh10_device::nes_lh10_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_LH10, "NES Cart LH-10 Pirate PCB", tag, owner, clock, "nes_lh10", __FILE__) +{ +} + +nes_lh53_device::nes_lh53_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_LH53, "NES Cart LH-53 Pirate PCB", tag, owner, clock, "nes_lh53", __FILE__) +{ +} + +nes_2708_device::nes_2708_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_2708, "NES Cart BTL-2708 Pirate PCB", tag, owner, clock, "nes_2708", __FILE__) +{ +} + +nes_ac08_device::nes_ac08_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_AC08, "NES Cart AC08 Pirate PCB", tag, owner, clock, "nes_ac08", __FILE__) +{ +} + +nes_unl_bb_device::nes_unl_bb_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_UNL_BB, "NES Cart FDS+CHR Pirate PCB", tag, owner, clock, "nes_unl_bb", __FILE__) +{ +} + +nes_mmalee_device::nes_mmalee_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_MMALEE, "NES Cart Super Mario Bros. Malee 2 Pirate PCB", tag, owner, clock, "nes_mmalee", __FILE__) +{ +} + +nes_shuiguan_device::nes_shuiguan_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_SHUIGUAN, "NES Cart Shui Guan Pipe Pirate PCB", tag, owner, clock, "nes_shuiguan", __FILE__) +{ +} + + + + +void nes_ax5705_device::device_start() +{ + common_start(); + save_item(NAME(m_mmc_prg_bank)); + save_item(NAME(m_mmc_vrom_bank)); +} + +void nes_ax5705_device::pcb_reset() +{ + m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; + chr8(0, m_chr_source); + + m_mmc_prg_bank[0] = 0; + m_mmc_prg_bank[1] = 1; + prg8_89(m_mmc_prg_bank[0]); + prg8_ab(m_mmc_prg_bank[1]); + prg8_cd(0xfe); + prg8_ef(0xff); + + memset(m_mmc_vrom_bank, 0, sizeof(m_mmc_vrom_bank)); +} + +void nes_sc127_device::device_start() +{ + common_start(); + save_item(NAME(m_irq_enable)); + save_item(NAME(m_irq_count)); +} + +void nes_sc127_device::pcb_reset() +{ + m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; + prg32(0xff); + chr8(0, m_chr_source); + + m_irq_enable = 0; + m_irq_count = 0; +} + +void nes_mbaby_device::device_start() +{ + common_start(); + irq_timer = timer_alloc(TIMER_IRQ); + irq_timer->reset(); + timer_freq = machine().device<cpu_device>("maincpu")->cycles_to_attotime(24576); + + save_item(NAME(m_irq_enable)); + save_item(NAME(m_latch)); +} + +void nes_mbaby_device::pcb_reset() +{ + m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; + prg32((m_prg_chunks - 1) >> 1); + chr8(0, m_chr_source); + + m_irq_enable = 0; + m_latch = 0; +} + +void nes_asn_device::device_start() +{ + common_start(); + save_item(NAME(m_latch)); +} + +void nes_asn_device::pcb_reset() +{ + m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; + prg32((m_prg_chunks - 1) >> 1); + chr8(0, m_chr_source); + + m_latch = 0; +} + +void nes_smb3p_device::device_start() +{ + common_start(); + irq_timer = timer_alloc(TIMER_IRQ); + irq_timer->adjust(attotime::zero, 0, machine().device<cpu_device>("maincpu")->cycles_to_attotime(1)); + + save_item(NAME(m_irq_enable)); + save_item(NAME(m_irq_count)); +} + +void nes_smb3p_device::pcb_reset() +{ + m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; + prg8_89((m_prg_chunks << 1) - 1); + prg8_ab(0); + prg8_cd(0); + prg8_ef((m_prg_chunks << 1) - 1); + chr8(0, m_chr_source); + + m_irq_enable = 0; + m_irq_count = 0; +} + +void nes_btl_dn_device::device_start() +{ + common_start(); + save_item(NAME(m_irq_count)); +} + +void nes_btl_dn_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_count = 0; +} + +void nes_whirl2706_device::device_start() +{ + common_start(); + save_item(NAME(m_latch)); +} + +void nes_whirl2706_device::pcb_reset() +{ + m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; + prg32(0xff); + chr8(0, m_chr_source); + + m_latch = 0; +} + +void nes_smb2j_device::device_start() +{ + common_start(); + irq_timer = timer_alloc(TIMER_IRQ); + irq_timer->adjust(attotime::zero, 0, machine().device<cpu_device>("maincpu")->cycles_to_attotime(1)); + + save_item(NAME(m_irq_enable)); + save_item(NAME(m_irq_count)); +} + +void nes_smb2j_device::pcb_reset() +{ + m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; + chr8(0, m_chr_source); + prg8_89(1); + prg8_ab(0); + prg8_cd(0); + prg8_ef(9); + + m_irq_enable = 0; + m_irq_count = 0; +} + +void nes_smb2ja_device::device_start() +{ + common_start(); + irq_timer = timer_alloc(TIMER_IRQ); + irq_timer->adjust(attotime::zero, 0, machine().device<cpu_device>("maincpu")->cycles_to_attotime(1)); + + save_item(NAME(m_irq_enable)); + save_item(NAME(m_irq_count)); +} + +void nes_smb2ja_device::pcb_reset() +{ + m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; + prg8_89(0xfc); + prg8_ab(0xfd); + prg8_cd(0xfe); + prg8_ef(0xff); + chr8(0, m_chr_source); + + m_irq_enable = 0; + m_irq_count = 0; +} + +void nes_smb2jb_device::device_start() +{ + common_start(); + irq_timer = timer_alloc(TIMER_IRQ); + irq_timer->adjust(attotime::zero, 0, machine().device<cpu_device>("maincpu")->cycles_to_attotime(1)); + + save_item(NAME(m_irq_enable)); + save_item(NAME(m_irq_count)); +} + +void nes_smb2jb_device::pcb_reset() +{ + m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; + prg8_89(0x08); + prg8_ab(0x09); + prg8_cd(0); + prg8_ef(0x0b); + chr8(0, m_chr_source); + + m_irq_enable = 0; + m_irq_count = 0; +} + +void nes_09034a_device::device_start() +{ + common_start(); + save_item(NAME(m_reg)); +} + +void nes_09034a_device::pcb_reset() +{ + m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; + prg32(0); + chr8(0, m_chr_source); + m_reg = 0; +} + +void nes_tobidase_device::device_start() +{ + common_start(); + save_item(NAME(m_latch)); +} + +void nes_tobidase_device::pcb_reset() +{ + m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; + prg32(2); + chr8(0, m_chr_source); + + m_latch = 0; +} + +void nes_lh32_device::device_start() +{ + common_start(); + save_item(NAME(m_latch)); +} + +void nes_lh32_device::pcb_reset() +{ + chr8(0, CHRRAM); + + prg32((m_prg_chunks - 1) >> 1); + // 0xc000-0xdfff reads/writes WRAM + m_latch = 0xf; +} + +void nes_lh10_device::device_start() +{ + common_start(); + save_item(NAME(m_latch)); + save_item(NAME(m_reg)); +} + +void nes_lh10_device::pcb_reset() +{ + chr8(0, CHRRAM); + + prg8_89(0); + prg8_ab(0); + // 0xc000-0xdfff reads/writes WRAM + prg8_ef(0xff); + memset(m_reg, 0, sizeof(m_reg)); + m_latch = 0; +} + +void nes_lh53_device::device_start() +{ + common_start(); + irq_timer = timer_alloc(TIMER_IRQ); + irq_timer->adjust(attotime::zero, 0, machine().device<cpu_device>("maincpu")->cycles_to_attotime(1)); + + save_item(NAME(m_irq_enable)); + save_item(NAME(m_irq_count)); + save_item(NAME(m_reg)); +} + +void nes_lh53_device::pcb_reset() +{ + chr8(0, CHRRAM); + + prg8_89(0xc); + prg8_ab(0xd); // last 2K are overlayed by WRAM + prg8_cd(0xe); // first 6K are overlayed by WRAM + prg8_ef(0xf); + m_reg = 0; + m_irq_count = 0; + m_irq_enable = 0; +} + +void nes_2708_device::device_start() +{ + common_start(); + save_item(NAME(m_reg)); +} + +void nes_2708_device::pcb_reset() +{ + chr8(0, CHRRAM); + + prg32(7); + // the upper PRG banks never change, but there are 8K of WRAM overlayed to the ROM area based on reg1 + m_reg[0] = 0; + m_reg[1] = 0; +} + +void nes_ac08_device::device_start() +{ + common_start(); + save_item(NAME(m_latch)); +} + +void nes_ac08_device::pcb_reset() +{ + m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; + chr8(0, m_chr_source); + prg32(0xff); + m_latch = 0xff; +} + +void nes_unl_bb_device::device_start() +{ + common_start(); + save_item(NAME(m_reg)); +} + +void nes_unl_bb_device::pcb_reset() +{ + chr8(0, CHRROM); + prg32(0xff); + // the upper PRG banks never change, but there are 8K of WRAM overlayed to the ROM area based on reg1 + m_reg[0] = 0xff; + m_reg[1] = 0; +} + +void nes_mmalee_device::device_start() +{ + common_start(); +} + +void nes_mmalee_device::pcb_reset() +{ + chr8(0, CHRROM); + prg32(0); +} + +void nes_shuiguan_device::device_start() +{ + common_start(); + irq_timer = timer_alloc(TIMER_IRQ); + // always running and checking for IRQ every 114 cycles? or resetting every frame? + irq_timer->adjust(attotime::zero, 0, machine().device<cpu_device>("maincpu")->cycles_to_attotime(114)); + + save_item(NAME(m_irq_enable)); + save_item(NAME(m_irq_count)); + save_item(NAME(m_mmc_vrom_bank)); +} + +void nes_shuiguan_device::pcb_reset() +{ + m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; + prg32((m_prg_chunks << 1) - 1); + chr8(0, m_chr_source); + + m_irq_enable = 0; + m_irq_count = 0; + memset(m_mmc_vrom_bank, 0, sizeof(m_mmc_vrom_bank)); +} + + + +/*------------------------------------------------- + mapper specific handlers + -------------------------------------------------*/ + +/*------------------------------------------------- + + Board UNL-AX5705 + + Games: Super Mario Bros. Pocker Mali (Crayon Shin-chan pirate hack) + + In MESS: Supported + + -------------------------------------------------*/ + +void nes_ax5705_device::set_prg() +{ + prg8_89(m_mmc_prg_bank[0]); + prg8_ab(m_mmc_prg_bank[1]); +} + +WRITE8_MEMBER(nes_ax5705_device::write_h) +{ + UINT8 bank; + LOG_MMC(("ax5705 write_h, offset: %04x, data: %02x\n", offset, data)); + + switch (offset & 0x700f) + { + case 0x0000: + m_mmc_prg_bank[0] = (data & 0x05) | ((data & 0x08) >> 2) | ((data & 0x02) << 2); + set_prg(); + break; + case 0x0008: + set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); + break; + case 0x2000: + m_mmc_prg_bank[1] = (data & 0x05) | ((data & 0x08) >> 2) | ((data & 0x02) << 2); + set_prg(); + break; + /* CHR banks 0, 1, 4, 5 */ + case 0x2008: + case 0x200a: + case 0x4008: + case 0x400a: + bank = ((offset & 0x4000) ? 4 : 0) + ((offset & 0x0002) ? 1 : 0); + m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0xf0) | (data & 0x0f); + chr1_x(bank, m_mmc_vrom_bank[bank], CHRROM); + break; + case 0x2009: + case 0x200b: + case 0x4009: + case 0x400b: + bank = ((offset & 0x4000) ? 4 : 0) + ((offset & 0x0002) ? 1 : 0); + m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x04) << 3) | ((data & 0x02) << 5) | ((data & 0x09) << 4); + chr1_x(bank, m_mmc_vrom_bank[bank], CHRROM); + break; + /* CHR banks 2, 3, 6, 7 */ + case 0x4000: + case 0x4002: + case 0x6000: + case 0x6002: + bank = 2 + ((offset & 0x2000) ? 4 : 0) + ((offset & 0x0002) ? 1 : 0); + m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0xf0) | (data & 0x0f); + chr1_x(bank, m_mmc_vrom_bank[bank], CHRROM); + break; + case 0x4001: + case 0x4003: + case 0x6001: + case 0x6003: + bank = 2 + ((offset & 0x2000) ? 4 : 0) + ((offset & 0x0002) ? 1 : 0); + m_mmc_vrom_bank[bank] = (m_mmc_vrom_bank[bank] & 0x0f) | ((data & 0x04) << 3) | ((data & 0x02) << 5) | ((data & 0x09) << 4); + chr1_x(bank, m_mmc_vrom_bank[bank], CHRROM); + break; + } +} + +/*------------------------------------------------- + + SC-127 Board + + Games: Wario World II (Kirby Hack) + + iNES: mapper 35 + + In MESS: Supported + + -------------------------------------------------*/ + +void nes_sc127_device::hblank_irq(int scanline, int vblank, int blanked) +{ + if (scanline < PPU_BOTTOM_VISIBLE_SCANLINE && m_irq_enable) + { + m_irq_count--; + + if (!blanked && (m_irq_count == 0)) + { + LOG_MMC(("irq fired, scanline: %d (MAME %d, beam pos: %d)\n", scanline, + machine().first_screen()->vpos(), machine().first_screen()->hpos())); + m_maincpu->set_input_line(M6502_IRQ_LINE, HOLD_LINE); + m_irq_enable = 0; + } + } +} + +WRITE8_MEMBER(nes_sc127_device::write_h) +{ + LOG_MMC(("sc127 write_h, offset: %04x, data: %02x\n", offset, data)); + + switch (offset) + { + case 0x0000: + prg8_89(data); + break; + case 0x0001: + prg8_ab(data); + break; + case 0x0002: +// m_mmc_prg_bank[offset & 0x02] = data; + prg8_cd(data); + break; + case 0x1000: + case 0x1001: + case 0x1002: + case 0x1003: + case 0x1004: + case 0x1005: + case 0x1006: + case 0x1007: +// m_mmc_vrom_bank[offset & 0x07] = data; + chr1_x(offset & 0x07, data, CHRROM); + break; + case 0x4002: + m_irq_enable = 0; + break; + case 0x4003: + m_irq_enable = 1; + break; + case 0x4005: + m_irq_count = data; + break; + case 0x5001: + set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); + break; + } +} + +/*------------------------------------------------- + + BTL-MARIOBABY + + Games: Mario Baby, Ai Senshi Nicol + + iNES: mapper 42 + + In MESS: Supported. + + -------------------------------------------------*/ + +void nes_mbaby_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + if (id == TIMER_IRQ) + { + m_maincpu->set_input_line(M6502_IRQ_LINE, HOLD_LINE); + irq_timer->adjust(attotime::never); + } +} + +WRITE8_MEMBER(nes_mbaby_device::write_h) +{ + LOG_MMC(("Mario Baby write_h, offset: %04x, data: %02x\n", offset, data)); + + if (offset >= 0x7000) + { + switch (offset & 0x03) + { + case 0x00: + m_latch = data; + break; + case 0x01: + set_nt_mirroring(BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); + break; + case 0x02: + /* Check if IRQ is being enabled */ + if (!m_irq_enable && (data & 0x02)) + { + m_irq_enable = 1; + irq_timer->adjust(timer_freq); + } + if (!(data & 0x02)) + { + m_irq_enable = 0; + irq_timer->adjust(attotime::never); + } + break; + } + } +} + +READ8_MEMBER(nes_mbaby_device::read_m) +{ + LOG_MMC(("Mario Baby read_m, offset: %04x\n", offset)); + return m_prg[(m_latch * 0x2000) + (offset & 0x1fff)]; +} + +/*------------------------------------------------- + + BTL-AISENSHINICOL + + Games: Ai Senshi Nicol + + iNES: mapper 42 with no IRQ and no NT, but CHR switch + + In MESS: Partially Supported. + + -------------------------------------------------*/ + +WRITE8_MEMBER(nes_asn_device::write_h) +{ + LOG_MMC(("Ai Senshi Nicol write_h, offset: %04x, data: %02x\n", offset, data)); + + if (offset == 0x0000) + chr8(data, CHRROM); + + if (offset == 0x7000) + m_latch = data; +} + +READ8_MEMBER(nes_asn_device::read_m) +{ + LOG_MMC(("Ai Senshi Nicol read_m, offset: %04x\n", offset)); + return m_prg[((m_latch * 0x2000) + (offset & 0x1fff)) & (m_prg_size - 1)]; +} + + +/*------------------------------------------------- + + BTL-SMB3 + + Games: Super Mario Bros. 3 Pirate + + iNES: mapper 106 + + In MESS: Supported. + + -------------------------------------------------*/ + +void nes_smb3p_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + if (id == TIMER_IRQ) + { + if (m_irq_enable) + { + if (m_irq_count == 0xffff) + { + m_maincpu->set_input_line(M6502_IRQ_LINE, HOLD_LINE); + m_irq_enable = 0; + } + else + m_irq_count++; + } + } +} + +WRITE8_MEMBER(nes_smb3p_device::write_h) +{ + LOG_MMC(("btl_smb3_w, offset: %04x, data: %02x\n", offset, data)); + switch (offset & 0x0f) + { + case 0x00: + case 0x02: + chr1_x(offset & 0x07, data & 0xfe, CHRROM); + break; + case 0x01: + case 0x03: + chr1_x(offset & 0x07, data | 0x01, CHRROM); + break; + case 0x04: case 0x05: + case 0x06: case 0x07: + chr1_x(offset & 0x07, data, CHRROM); + break; + case 0x08: + prg8_89(data | 0x10); + break; + case 0x09: + prg8_ab(data); + break; + case 0x0a: + prg8_cd(data); + break; + case 0x0b: + prg8_ef(data | 0x10); + break; + case 0x0c: + set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); + break; + case 0x0d: + m_irq_count = 0; + m_irq_enable = 0; + break; + case 0x0e: + m_irq_count = (m_irq_count & 0xff00) | data; + break; + case 0x0f: + m_irq_count = (m_irq_count & 0x00ff) | (data << 8); + m_irq_enable = 1; + break; + } +} + +/*------------------------------------------------- + + BTL-DRAGONNINJA + + Games: Dragon Ninja (Bootleg), Super Mario Bros. 8 + + iNES: mapper 222 + + In MESS: Unsupported. + + -------------------------------------------------*/ + +/* Scanline based IRQ ? */ +void nes_btl_dn_device::hblank_irq(int scanline, int vblank, int blanked ) +{ + if (!m_irq_count || ++m_irq_count < 240) + return; + + m_irq_count = 0; + m_maincpu->set_input_line(M6502_IRQ_LINE, HOLD_LINE); +} + +WRITE8_MEMBER(nes_btl_dn_device::write_h) +{ + UINT8 bank; + LOG_MMC(("btl_dn write_h, offset: %04x, data: %02x\n", offset, data)); + + switch (offset & 0x7003) + { + case 0x0000: + prg8_89(data); + break; + case 0x1000: + set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); + break; + case 0x2000: + prg8_ab(data); + break; + case 0x3000: + case 0x3002: + case 0x4000: + case 0x4002: + case 0x5000: + case 0x5002: + case 0x6000: + case 0x6002: + bank = ((offset & 0x7000) - 0x3000) / 0x0800 + ((offset & 0x0002) >> 1); + chr1_x(bank, data, CHRROM); + break; + case 0x7000: + m_irq_count = data; + break; + } +} + +/*------------------------------------------------- + + BOOTLEG FC VERSIONS OF FDS GAMES + + -------------------------------------------------*/ + +/*------------------------------------------------- + + WHIRLWIND-2706 + + Games: Meikyuu Jiin Dababa (FDS conversion) and a few + others + + This PCB maps PRG in 0x6000-0x7fff + + iNES: mapper 108 + + In MESS: Supported. + + -------------------------------------------------*/ + +WRITE8_MEMBER(nes_whirl2706_device::write_h) +{ + LOG_MMC(("whirl2706 write_h, offset: %04x, data: %02x\n", offset, data)); + m_latch = data; +} + +READ8_MEMBER(nes_whirl2706_device::read_m) +{ + LOG_MMC(("whirl2706 read_m, offset: %04x\n", offset)); + return m_prg[(m_latch * 0x2000 + (offset & 0x1fff)) & (m_prg_size - 1)]; +} + +/*------------------------------------------------- + + Bootleg Board SMB2J + + Games: Super Mario Bros. 2 Pirate (LF36) + + iNES: mapper 43 + + In MESS: Supported. + + -------------------------------------------------*/ + +void nes_smb2j_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + if (id == TIMER_IRQ) + { + if (m_irq_enable) + { + if (m_irq_count == 0xfff) + { + m_maincpu->set_input_line(M6502_IRQ_LINE, HOLD_LINE); + m_irq_enable = 0; + m_irq_count = 0; + } + else + m_irq_count++; + } + } +} + +WRITE8_MEMBER(nes_smb2j_device::write_l) +{ + LOG_MMC(("smb2j write_l, offset: %04x, data: %02x\n", offset, data)); + offset += 0x100; + + if (offset == 0x122) // $4122 + m_irq_enable = data & 3; // maybe also m_irq_count = 0?!? +} + +WRITE8_MEMBER(nes_smb2j_device::write_h) +{ + LOG_MMC(("smb2j write_h, offset: %04x, data: %02x\n", offset, data)); + + if (offset == 0x122) // $8122 too? + m_irq_enable = data & 3; +} + +WRITE8_MEMBER(nes_smb2j_device::write_ex) +{ + LOG_MMC(("smb2j write_ex, offset: %04x, data: %02x\n", offset, data)); + + if (offset == 2) + { + int temp = 0; + + // According to hardware tests + if (data & 1) + temp = 3; + else + temp = 4 + ((data & 7) >> 1); + + prg8_cd(temp); + } +} + +READ8_MEMBER(nes_smb2j_device::read_l) +{ + LOG_MMC(("smb2j read_l, offset: %04x\n", offset)); + offset += 0x100; + + if (offset >= 0x1000) + return m_prg[0x10000 + (offset & 0x0fff)]; + + return m_open_bus; // open bus +} + +READ8_MEMBER(nes_smb2j_device::read_m) +{ + LOG_MMC(("smb2j read_m, offset: %04x\n", offset)); + return m_prg[0x4000 + offset]; +} + +/*------------------------------------------------- + + BTL-SMB2A + + Games: Super Mario Bros. 2 Pirate (Jpn version of SMB2) + + iNES: mapper 40 + + In MESS: Supported. + + -------------------------------------------------*/ + +void nes_smb2ja_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + if (id == TIMER_IRQ) + { + if (m_irq_enable) + { + if (m_irq_count == 0xfff) + { + m_maincpu->set_input_line(M6502_IRQ_LINE, HOLD_LINE); + m_irq_enable = 0; + m_irq_count = 0; + } + else + m_irq_count++; + } + } +} + +WRITE8_MEMBER(nes_smb2ja_device::write_h) +{ + LOG_MMC(("smb2ja write_h, offset: %04x, data: %02x\n", offset, data)); + + switch (offset & 0x6000) + { + case 0x0000: + m_irq_enable = 0; + m_irq_count = 0; + break; + case 0x2000: + m_irq_enable = 1; + break; + case 0x6000: + prg8_cd(data); + break; + } +} + +READ8_MEMBER(nes_smb2ja_device::read_m) +{ + LOG_MMC(("smb2ja read_m, offset: %04x\n", offset)); + return m_prg[(0xfe * 0x2000 + (offset & 0x1fff)) & (m_prg_size - 1)]; +} + +/*------------------------------------------------- + + BTL-SMB2B + + Games: Super Mario Bros. 2 Pirate (Jpn version of SMB2) + + This was marked as Alt. Levels. is it true? + + iNES: mapper 50 + + In MESS: Partially Supported. + + -------------------------------------------------*/ + +void nes_smb2jb_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + if (id == TIMER_IRQ) + { + if (m_irq_enable) + { + if (m_irq_count == 0xfff) + { + m_maincpu->set_input_line(M6502_IRQ_LINE, HOLD_LINE); + m_irq_enable = 0; + m_irq_count = 0; + } + else + m_irq_count++; + } + } +} + +WRITE8_MEMBER(nes_smb2jb_device::write_l) +{ + UINT8 prg; + LOG_MMC(("smb2jb write_l, offset: %04x, data: %02x\n", offset, data)); + offset += 0x100; + + switch (offset & 0x1e0) + { + case 0x020: + case 0x0a0: + prg = (data & 0x08) | ((data & 0x06) >> 1) | ((data & 0x01) << 2); + prg8_cd(prg); + break; + case 0x120: + case 0x1a0: + m_irq_enable = data & 0x01; + break; + } +} + +READ8_MEMBER(nes_smb2jb_device::read_m) +{ + LOG_MMC(("smb2jb read_m, offset: %04x\n", offset)); + return m_prg[((0x0f * 0x2000) + (offset & 0x1fff)) & (m_prg_size - 1)]; +} + +/* This goes to 0x4020-0x403f & 0x40a0-0x40bf */ +WRITE8_MEMBER(nes_smb2jb_device::write_ex) +{ + UINT8 prg; + LOG_MMC(("smb2jb write_ex, offset: %04x, data: %02x\n", offset, data)); + + if ((offset < 0x20) || (offset >= 0x80 && offset < 0xa0)) + { + prg = (data & 0x08) | ((data & 0x06) >> 1) | ((data & 0x01) << 2); + prg8_cd(prg); + } +} + +/*------------------------------------------------- + + (UNL-)09-034A + + Games: Zanac FDS conversion with two PRG chips and + no CHRROM and Volleyball FDS conversion with two PRG + chips and CHRROM. + Originally dumps were marked as UNL-SMB2J pcb + + iNES: + + In MESS: Partially Supported. Need to emulate IRQ + (needed by smb2 conversion?) + + -------------------------------------------------*/ + +WRITE8_MEMBER(nes_09034a_device::write_ex) +{ + LOG_MMC(("09-034a write_ex, offset: %04x, data: %02x\n", offset, data)); + + if (offset == 7) // $4027 + m_reg = data & 1; +} + +READ8_MEMBER(nes_09034a_device::read_m) +{ + LOG_MMC(("09-034a read_m, offset: %04x\n", offset)); + // in 0x6000-0x7fff is mapped the 2nd PRG chip which starts after 32K (hence the +4) + return m_prg[((m_reg + 4) * 0x2000) + offset]; +} + +/*------------------------------------------------- + + Bootleg Board used for FDS conversion + + Games: Tobidase Daisakusen (FDS conversion) + + This PCB maps PRG in 0x6000-0x7fff + + iNES: mapper 120 + + In MESS: Partially Supported. + + -------------------------------------------------*/ + +WRITE8_MEMBER(nes_tobidase_device::write_l) +{ + LOG_MMC(("tobidase write_h, offset: %04x, data: %02x\n", offset, data)); + offset += 0x4100; + + if ((offset & 0x63c0) == 0x41c0) + m_latch = data & 0x0f; +} + +READ8_MEMBER(nes_tobidase_device::read_m) +{ + LOG_MMC(("tobidase read_m, offset: %04x\n", offset)); + if (m_latch >= 0x0c) + m_latch -= 4; + return m_prg[(m_latch * 0x2000) + (offset & 0x1fff)]; +} + +/*------------------------------------------------- + + UNL-LH32 + + Games: Monty no Doki Doki Daidassou (FDS conversion) + + This PCB maps WRAM in 0xc000-0xdfff and PRG in 0x6000-0x7fff + + iNES: + + In MESS: Supported. + +-------------------------------------------------*/ + +READ8_MEMBER(nes_lh32_device::read_m) +{ + LOG_MMC(("lh32 read_m, offset: %04x\n", offset)); + return m_prg[(m_latch * 0x2000) + (offset & 0x1fff)]; +} + +READ8_MEMBER(nes_lh32_device::read_h) +{ + LOG_MMC(("lh32 read_h, offset: %04x\n", offset)); + + if (offset >= 0x4000 && offset < 0x6000) + return m_prgram[offset & 0x1fff]; + + return hi_access_rom(offset); +} + +WRITE8_MEMBER(nes_lh32_device::write_m) +{ + LOG_MMC(("lh32 write_m, offset: %04x, data: %02x\n", offset, data)); + + if (offset == 0) // 0x6000 only? + { +// printf("write %x\n", data); + m_latch = data & 0xf; + } +} + +WRITE8_MEMBER(nes_lh32_device::write_h) +{ + LOG_MMC(("lh32 write_h, offset: %04x, data: %02x\n", offset, data)); + + if (offset >= 0x4000 && offset < 0x6000) + m_prgram[offset & 0x1fff] = data; +} + +/*------------------------------------------------- + + UNL-LH10 + + Games: Fuuun Shaolin Kyo (FDS conversion) + + This PCB maps WRAM in 0xc000-0xdfff and PRG in 0x6000-0x7fff + This is very similar to KS7037 (not sure which conversion + uses that one) + + iNES: + + In MESS: Supported. + + -------------------------------------------------*/ + +void nes_lh10_device::update_prg() +{ + prg8_89(m_reg[6]); + prg8_ab(m_reg[7]); +} + +READ8_MEMBER(nes_lh10_device::read_m) +{ + LOG_MMC(("lh10 read_m, offset: %04x\n", offset)); + return m_prg[(0x0e * 0x2000) + (offset & 0x1fff)]; +} + +READ8_MEMBER(nes_lh10_device::read_h) +{ + LOG_MMC(("lh10 read_h, offset: %04x\n", offset)); + + if (offset >= 0x4000 && offset < 0x6000) + return m_prgram[offset & 0x1fff]; + + return hi_access_rom(offset); +} + +WRITE8_MEMBER(nes_lh10_device::write_h) +{ + LOG_MMC(("lh10 write_h, offset: %04x, data: %02x\n", offset, data)); + + if (offset >= 0x4000 && offset < 0x6000) + m_prgram[offset & 0x1fff] = data; + + else + { + switch (offset & 0x6001) + { + case 0x0000: + m_latch = data & 7; + break; + case 0x0001: + m_reg[m_latch] = data; + update_prg(); + break; + } + } +} + +/*------------------------------------------------- + + UNL-LH53 + + Games: Nazo no Murasamejou (FDS conversion) + + This PCB maps WRAM (w/battery) in 0xb800-0xd7ff and + PRG in 0x6000-0x7fff + + iNES: + + In MESS: Preliminar Support only. + + -------------------------------------------------*/ + +void nes_lh53_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + if (id == TIMER_IRQ) + { + if (m_irq_enable) + { + m_irq_count++; + if (m_irq_count > 7560)//value from FCEUMM... + { + m_irq_count = 0; + m_maincpu->set_input_line(M6502_IRQ_LINE, ASSERT_LINE); + } + } + } +} + +READ8_MEMBER(nes_lh53_device::read_m) +{ + LOG_MMC(("lh53 read_m, offset: %04x\n", offset)); + return m_prg[(m_reg * 0x2000) + (offset & 0x1fff)]; +} + +READ8_MEMBER(nes_lh53_device::read_h) +{ + LOG_MMC(("lh53 read_h, offset: %04x\n", offset)); + + if (offset >= 0x3800 && offset < 0x5800) + return m_battery[offset & 0x1fff]; + + return hi_access_rom(offset); +} + +WRITE8_MEMBER(nes_lh53_device::write_h) +{ + LOG_MMC(("lh53 write_h, offset: %04x, data: %02x\n", offset, data)); + + if (offset >= 0x3800 && offset < 0x5800) + m_battery[offset & 0x1fff] = data; + + else + { + switch (offset & 0x7000) + { + case 0x6000: + m_irq_enable = BIT(data, 1); + m_irq_count = 0; + if (!m_irq_enable) + m_maincpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE); + break; + case 0x7000: + m_reg = data & 0x0f; + break; + } + } +} + +/*------------------------------------------------- + + BTL-2708 + + Games: Doki Doki Panic (FDS conversion) + + iNES: mapper 103? + + This board has a very unique setup, with 8KB of WRAM + in 0x6000-0x7fff and other 8KB of WRAM in 0xb800-0xd7ff + which can be switched in 2KB chunks (we attempt to + emulate this by intercepting reads in that area before + they get to the PRG banks...) + + In MESS: Supported. + + -------------------------------------------------*/ + +READ8_MEMBER(nes_2708_device::read_m) +{ + LOG_MMC(("btl-2708 read_m, offset: %04x\n", offset)); + if (!m_reg[1]) + return m_prgram[offset]; // lower 8K of WRAM + else + return m_prg[(m_reg[0] * 0x2000) + (offset & 0x1fff)]; +} + +WRITE8_MEMBER(nes_2708_device::write_m) +{ + LOG_MMC(("btl-2708 write_m, offset: %04x, data: %02x\n", offset, data)); +// if (!m_reg[1]) + m_prgram[offset] = data; // lower 8K of WRAM +} + +READ8_MEMBER(nes_2708_device::read_h) +{ + LOG_MMC(("btl-2708 read_h, offset: %04x\n", offset)); + + if (offset >= 0x3800 && offset < 0x5800 && !m_reg[1]) + return m_prgram[0x2000 + ((offset - 0x3800) & 0x1fff)]; // higher 8K of WRAM + + return hi_access_rom(offset); +} + +WRITE8_MEMBER(nes_2708_device::write_h) +{ + LOG_MMC(("btl-2708 write_h, offset: %04x, data: %02x\n", offset, data)); + + if (offset >= 0x3800 && offset < 0x5800/* && !m_reg[1]*/) + m_prgram[0x2000 + ((offset - 0x3800) & 0x1fff)] = data; // higher 8K of WRAM + + switch (offset & 0x7000) + { + case 0x0000: + m_reg[0] = data & 0x0f; // PRG bank in 0x6000-0x7fff + break; + case 0x6000: + set_nt_mirroring(BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); + break; + case 0x7000: + m_reg[1] = BIT(data, 4); // bit4 enables the two WRAM banks + break; + } +} + +/*------------------------------------------------- + + UNL-AC08 + + Games: Green Beret (FDS conversions) + + iNES: + + This board has two PRG chips. The first (128K) is + connected to 0x6000-0x7fff and switches among the + 16x8K banks; the second (32K) is fixed in 0x8000-0xffff + + In MESS: Supported. + + -------------------------------------------------*/ + +WRITE8_MEMBER(nes_ac08_device::write_ex) +{ + LOG_MMC(("AC-08 write_ex, offset: %04x, data: %02x\n", offset, data)); + if (offset == 5) // $4025 + set_nt_mirroring(!BIT(data, 3) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ); +} + +READ8_MEMBER(nes_ac08_device::read_m) +{ + LOG_MMC(("AC-08 read_m, offset: %04x\n", offset)); + return m_prg[(m_latch * 0x2000) + (offset & 0x1fff)]; +} + +WRITE8_MEMBER(nes_ac08_device::write_h) +{ + LOG_MMC(("AC-08 write_h, offset: %04x, data: %02x\n", offset, data)); + + if (offset == 1) + m_latch = (data >> 1) & 0x0f; + else + m_latch = data & 0x0f; // apparently there also is a Castlevania FDS conversion using same board with different banking lines +} + +/*------------------------------------------------- + + UNL-BB + + Games: Bubble Bobble and other FDS conversions with CHRROM! + + iNES: + + + In MESS: Supported. + + -------------------------------------------------*/ + +READ8_MEMBER(nes_unl_bb_device::read_m) +{ + LOG_MMC(("unl-bb read_m, offset: %04x\n", offset)); + return m_prg[(((m_reg[0] & 3 & m_prg_mask) * 0x2000) + (offset & 0x1fff))]; +} + +WRITE8_MEMBER(nes_unl_bb_device::write_h) +{ + LOG_MMC(("unl-bb write_h, offset: %04x, data: %02x\n", offset, data)); + + if (!(offset & 0x1000)) + { + m_reg[0] = data; + m_reg[1] = data; + } + else + m_reg[1] = data & 1; // Pro Wrestling uses this + + chr8(m_reg[1] & 3, m_chr_source); +} + +/*------------------------------------------------- + + BTL-MARIO1-MALEE2 (aka Genius Merio Bros) + + Games: Super Mario Bros Malee 2 + + iNES: + + This PCB has two PRG chips (32K+2K) + one CHR chip (8K) + + 2KB of WRAM + The second PRG chip (2K) is connected at 0x6000-0x6800 + while WRAM is at 0x7000-0x7800 + + In MESS: Supported. + + -------------------------------------------------*/ + +READ8_MEMBER(nes_mmalee_device::read_m) +{ + LOG_MMC(("mmalee read_m, offset: %04x\n", offset)); + + if (offset < 0x0800) + return m_prg[0x8000 + offset]; + else if (!m_prgram.empty() && offset >= 0x1000 && offset < 0x1800) // WRAM only in these 2K + return m_prgram[offset & 0x7ff]; + + return ((offset + 0x6000) & 0xff00) >> 8; +} + +WRITE8_MEMBER(nes_mmalee_device::write_m) +{ + LOG_MMC(("mmalee write_m, offset: %04x, data: %02x\n", offset, data)); + + if (!m_prgram.empty() && offset >= 0x1000 && offset < 0x1800) // WRAM only in these 2K + m_prgram[offset & 0x7ff] = data; +} + +/*------------------------------------------------- + + BTL-SHUIGUANPIPE + + Games: Shui Guan Pipe (Gimmick Pirate) + + iNES: + + In MESS: Supported, but there are glitches (PPU or IRQ?) + + -------------------------------------------------*/ + +// timer always running and checking IRQ every 114 CPU cycles? +void nes_shuiguan_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + if (id == TIMER_IRQ) + { + m_irq_count++; + m_irq_count &= 0xff; + + if (m_irq_enable && !m_irq_count) + m_maincpu->set_input_line(M6502_IRQ_LINE, HOLD_LINE); + } +} + +WRITE8_MEMBER(nes_shuiguan_device::write_h) +{ + int bank; + LOG_MMC(("shuiguan write_h, offset: %04x, data: %02x\n", offset, data)); + + switch (offset & 0x7000) + { + case 0x0000: + if (offset & 0x800 && !(offset & 0x0c)) // 0x8800-0x8803 + N*0x10 + prg8_89(data); + break; + case 0x1000: + if (offset & 0x800 && !(offset & 0x0c)) // 0x9800-0x9803 + N*0x10 + { + 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; + } + } + break; + case 0x2000: + if (!(offset & 0x800) && !(offset & 0x0c)) // 0xa000-0xa003 + N*0x10 + prg8_cd(data); + if (offset & 0x800 && !(offset & 0x0c)) // 0xa800-0xa803 + N*0x10 + prg8_ab(data); + break; + case 0x3000: + case 0x4000: + case 0x5000: + case 0x6000: + bank = (((offset + 0x1000) >> 11) | (offset >> 3)) & 0x07; + if (offset & 4) + 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) << 0); + chr1_x(bank, m_mmc_vrom_bank[bank], m_chr_source); + break; + case 0x7000: + switch (offset & 0x0c) + { + case 0x00: m_irq_count = (m_irq_count & 0xf0) | ((data & 0x0f) << 0); break; + case 0x04: m_irq_count = (m_irq_count & 0x0f) | ((data & 0x0f) << 4); break; + case 0x08: m_irq_enable= data; break; + case 0x0c: break; + } + break; + } +} + +READ8_MEMBER(nes_shuiguan_device::read_m) +{ + // always first bank?? + LOG_MMC(("shuiguan read_m, offset: %04x\n", offset)); + return m_prg[offset & 0x1fff]; +} |