diff options
Diffstat (limited to 'src/devices/bus/nes/bootleg.cpp')
-rw-r--r-- | src/devices/bus/nes/bootleg.cpp | 1695 |
1 files changed, 1063 insertions, 632 deletions
diff --git a/src/devices/bus/nes/bootleg.cpp b/src/devices/bus/nes/bootleg.cpp index d585a8df9de..4ce050033d5 100644 --- a/src/devices/bus/nes/bootleg.cpp +++ b/src/devices/bus/nes/bootleg.cpp @@ -13,7 +13,9 @@ 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) + - SMB2 bootlegs all seem to have timing issues. This is apparent on worlds A-D as the bottom of the + world letter scrolls. Hardware footage of the mapper 50 version shows the letter bottoms flickering + (though it could be a video/compression artifact). ***********************************************************************************************************/ @@ -22,57 +24,61 @@ #include "bootleg.h" #include "video/ppu2c0x.h" // this has to be included so that IRQ functions can access ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE -#include "screen.h" +#define LOG_HIFREQ (1U << 1) #ifdef NES_PCB_DEBUG -#define VERBOSE 1 +#define VERBOSE (LOG_GENERAL) #else -#define VERBOSE 0 +#define VERBOSE (0) #endif - -#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0) +#include "logmacro.h" //------------------------------------------------- // constructor //------------------------------------------------- -DEFINE_DEVICE_TYPE(NES_AX5705, nes_ax5705_device, "nes_ax5705", "NES Cart AX5705 PCB") DEFINE_DEVICE_TYPE(NES_SC127, nes_sc127_device, "nes_sc127", "NES Cart SC-127 PCB") DEFINE_DEVICE_TYPE(NES_MARIOBABY, nes_mbaby_device, "nes_mbaby", "NES Cart Mario Baby Bootleg PCB") DEFINE_DEVICE_TYPE(NES_ASN, nes_asn_device, "nes_asn", "NES Cart Ai Senshi Nicol Bootleg PCB") DEFINE_DEVICE_TYPE(NES_SMB3PIRATE, nes_smb3p_device, "nes_smb3p", "NES Cart Super Mario Bros. 3 Pirate PCB") +DEFINE_DEVICE_TYPE(NES_BTL_CONTRAJ, nes_btl_cj_device, "nes_btl_cj", "NES Cart Contra Japan Pirate PCB") DEFINE_DEVICE_TYPE(NES_BTL_DNINJA, nes_btl_dn_device, "nes_btl_dn", "NES Cart DragonNinja Pirate PCB") -DEFINE_DEVICE_TYPE(NES_WHIRLWIND_2706, nes_whirl2706_device, "nes_whirl2706", "NES Cart Whilwind 2706 PCB") DEFINE_DEVICE_TYPE(NES_SMB2J, nes_smb2j_device, "nes_smb2j", "NES Cart Super Mario Bros. 2 Jpn PCB") DEFINE_DEVICE_TYPE(NES_SMB2JA, nes_smb2ja_device, "nes_smb2ja", "NES Cart Super Mario Bros. 2 Jpn (Alt) PCB") DEFINE_DEVICE_TYPE(NES_SMB2JB, nes_smb2jb_device, "nes_smb2jb", "NES Cart Super Mario Bros. 2 Jpn (Alt 2) PCB") +DEFINE_DEVICE_TYPE(NES_N32_4IN1, nes_n32_4in1_device, "nes_n32_4in1", "NES Cart N-32 4 in 1 PCB") +DEFINE_DEVICE_TYPE(NES_0353, nes_0353_device, "nes_0353", "NES Cart 0353 PCB") DEFINE_DEVICE_TYPE(NES_09034A, nes_09034a_device, "nes_09034a", "NES Cart 09-034A PCB") +DEFINE_DEVICE_TYPE(NES_L001, nes_l001_device, "nes_l001", "NES Cart L-001 PCB") +DEFINE_DEVICE_TYPE(NES_BATMANFS, nes_batmanfs_device, "nes_batmanfs", "NES Cart Batman Pirate PCB") +DEFINE_DEVICE_TYPE(NES_PALTHENA, nes_palthena_device, "nes_palthena", "NES Cart Palthena no Kagami Pirate PCB") DEFINE_DEVICE_TYPE(NES_TOBIDASE, nes_tobidase_device, "nes_tobidase", "NES Cart Tobidase Daisakusen Pirate PCB") -DEFINE_DEVICE_TYPE(NES_LH32, nes_lh32_device, "nes_lh32", "NES Cart LH-32 Pirate PCB") -DEFINE_DEVICE_TYPE(NES_LH10, nes_lh10_device, "nes_lh10", "NES Cart LH-10 Pirate PCB") -DEFINE_DEVICE_TYPE(NES_LH53, nes_lh53_device, "nes_lh53", "NES Cart LH-53 Pirate PCB") +DEFINE_DEVICE_TYPE(NES_DH08, nes_dh08_device, "nes_dh08", "NES Cart DH-08 Pirate PCB") +DEFINE_DEVICE_TYPE(NES_LE05, nes_le05_device, "nes_le05", "NES Cart LE05 Pirate PCB") +DEFINE_DEVICE_TYPE(NES_LG25, nes_lg25_device, "nes_lg25", "NES Cart LG25 Pirate PCB") +DEFINE_DEVICE_TYPE(NES_LH10, nes_lh10_device, "nes_lh10", "NES Cart LH10 Pirate PCB") +DEFINE_DEVICE_TYPE(NES_LH28_LH54, nes_lh28_lh54_device, "nes_lh28_lh54", "NES Cart LH28/LH54 Pirate PCBs") +DEFINE_DEVICE_TYPE(NES_LH31, nes_lh31_device, "nes_lh31", "NES Cart LH31 Pirate PCB") +DEFINE_DEVICE_TYPE(NES_LH32, nes_lh32_device, "nes_lh32", "NES Cart LH32 Pirate PCB") +DEFINE_DEVICE_TYPE(NES_LH42, nes_lh42_device, "nes_lh42", "NES Cart LH42 Pirate PCB") +DEFINE_DEVICE_TYPE(NES_LH51, nes_lh51_device, "nes_lh51", "NES Cart LH51 Pirate PCB") +DEFINE_DEVICE_TYPE(NES_LH53, nes_lh53_device, "nes_lh53", "NES Cart LH53 Pirate PCB") DEFINE_DEVICE_TYPE(NES_2708, nes_2708_device, "nes_2708", "NES Cart BTL-2708 Pirate PCB") DEFINE_DEVICE_TYPE(NES_AC08, nes_ac08_device, "nes_ac08", "NES Cart AC08 Pirate PCB") -DEFINE_DEVICE_TYPE(NES_UNL_BB, nes_unl_bb_device, "nes_unl_bb", "NES Cart FDS+CHR Pirate PCB") DEFINE_DEVICE_TYPE(NES_MMALEE, nes_mmalee_device, "nes_mmalee", "NES Cart Super Mario Bros. Malee 2 Pirate PCB") -DEFINE_DEVICE_TYPE(NES_SHUIGUAN, nes_shuiguan_device, "nes_shuiguan", "NES Cart Shui Guan Pipe Pirate PCB") DEFINE_DEVICE_TYPE(NES_RT01, nes_rt01_device, "nes_rt01", "NES Cart RT-01 PCB") +DEFINE_DEVICE_TYPE(NES_YUNG08, nes_yung08_device, "nes_yung08", "NES Cart Super Mario Bros. 2 YUNG-08 PCB") -nes_ax5705_device::nes_ax5705_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : nes_nrom_device(mconfig, NES_AX5705, tag, owner, clock) -{ -} - nes_sc127_device::nes_sc127_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : nes_nrom_device(mconfig, NES_SC127, tag, owner, clock), m_irq_count(0), m_irq_enable(0) { } -nes_mbaby_device::nes_mbaby_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : nes_nrom_device(mconfig, NES_MARIOBABY, tag, owner, clock), m_latch(0), m_irq_enable(0), irq_timer(nullptr) +nes_mbaby_device::nes_mbaby_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : nes_nrom_device(mconfig, NES_MARIOBABY, tag, owner, clock), m_irq_count(0), m_irq_enable(0), m_latch(0), irq_timer(nullptr) { } @@ -81,38 +87,68 @@ nes_asn_device::nes_asn_device(const machine_config &mconfig, const char *tag, d { } -nes_smb3p_device::nes_smb3p_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) +nes_smb3p_device::nes_smb3p_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : nes_nrom_device(mconfig, NES_SMB3PIRATE, tag, owner, clock), m_irq_count(0), m_irq_enable(0), irq_timer(nullptr) { } -nes_btl_dn_device::nes_btl_dn_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : nes_nrom_device(mconfig, NES_BTL_DNINJA, tag, owner, clock), m_irq_count(0) +nes_btl_cj_device::nes_btl_cj_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : nes_nrom_device(mconfig, NES_BTL_CONTRAJ, tag, owner, clock) { } -nes_whirl2706_device::nes_whirl2706_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : nes_nrom_device(mconfig, NES_WHIRLWIND_2706, tag, owner, clock), m_latch(0) +nes_btl_dn_device::nes_btl_dn_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : nes_nrom_device(mconfig, NES_BTL_DNINJA, tag, owner, clock), m_irq_count(0) { } -nes_smb2j_device::nes_smb2j_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) +nes_smb2j_device::nes_smb2j_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : nes_nrom_device(mconfig, NES_SMB2J, tag, owner, clock), m_irq_count(0), m_irq_enable(0), irq_timer(nullptr) { } -nes_smb2ja_device::nes_smb2ja_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) +nes_smb2ja_device::nes_smb2ja_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : nes_nrom_device(mconfig, NES_SMB2JA, tag, owner, clock), m_irq_count(0), m_irq_enable(0), irq_timer(nullptr) { } -nes_smb2jb_device::nes_smb2jb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : nes_nrom_device(mconfig, NES_SMB2JB, tag, owner, clock), m_irq_count(0), m_irq_enable(0), irq_timer(nullptr) +nes_smb2jb_device::nes_smb2jb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 bank67) + : nes_nrom_device(mconfig, type, tag, owner, clock), m_irq_count(0), m_irq_enable(0), m_reg(0), m_bank67(bank67), irq_timer(nullptr) +{ +} + +nes_smb2jb_device::nes_smb2jb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : nes_smb2jb_device(mconfig, NES_SMB2JB, tag, owner, clock, 0x0f) +{ +} + +nes_n32_4in1_device::nes_n32_4in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : nes_smb2jb_device(mconfig, NES_N32_4IN1, tag, owner, clock, 0x07) +{ +} + +nes_0353_device::nes_0353_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : nes_nrom_device(mconfig, NES_0353, tag, owner, clock), m_reg(0) +{ +} + +nes_09034a_device::nes_09034a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : nes_nrom_device(mconfig, NES_09034A, tag, owner, clock), m_irq_count(0), m_irq_enable(0), m_reg(0), irq_timer(nullptr) +{ +} + +nes_l001_device::nes_l001_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : nes_nrom_device(mconfig, NES_L001, tag, owner, clock), m_irq_count(0), irq_timer(nullptr) +{ +} + +nes_batmanfs_device::nes_batmanfs_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : nes_nrom_device(mconfig, NES_BATMANFS, tag, owner, clock), m_irq_count(0), m_irq_enable(0), irq_timer(nullptr) { } -nes_09034a_device::nes_09034a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : nes_nrom_device(mconfig, NES_09034A, tag, owner, clock), m_reg(0) +nes_palthena_device::nes_palthena_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : nes_nrom_device(mconfig, NES_PALTHENA, tag, owner, clock), m_reg(0) { } @@ -121,16 +157,56 @@ nes_tobidase_device::nes_tobidase_device(const machine_config &mconfig, const ch { } +nes_whirlwind_device::nes_whirlwind_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) + : nes_nrom_device(mconfig, type, tag, owner, clock), m_reg(0) +{ +} + +nes_dh08_device::nes_dh08_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : nes_whirlwind_device(mconfig, NES_DH08, tag, owner, clock) +{ +} + +nes_le05_device::nes_le05_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : nes_whirlwind_device(mconfig, NES_LE05, tag, owner, clock) +{ +} + +nes_lh28_lh54_device::nes_lh28_lh54_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : nes_whirlwind_device(mconfig, NES_LH28_LH54, tag, owner, clock) +{ +} + +nes_lh31_device::nes_lh31_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : nes_whirlwind_device(mconfig, NES_LH31, tag, owner, clock) +{ +} + nes_lh32_device::nes_lh32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : nes_nrom_device(mconfig, NES_LH32, tag, owner, clock), m_latch(0) { } -nes_lh10_device::nes_lh10_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) +nes_lh42_device::nes_lh42_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : nes_nrom_device(mconfig, NES_LH42, tag, owner, clock), m_latch(0) +{ +} + +nes_lg25_device::nes_lg25_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : nes_nrom_device(mconfig, NES_LG25, tag, owner, clock), m_latch(0) +{ +} + +nes_lh10_device::nes_lh10_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : nes_nrom_device(mconfig, NES_LH10, tag, owner, clock), m_latch(0) { } +nes_lh51_device::nes_lh51_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : nes_nrom_device(mconfig, NES_LH51, tag, owner, clock) +{ +} + nes_lh53_device::nes_lh53_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : nes_nrom_device(mconfig, NES_LH53, tag, owner, clock), m_irq_count(0), m_irq_enable(0), m_reg(0), irq_timer(nullptr) { @@ -146,50 +222,23 @@ nes_ac08_device::nes_ac08_device(const machine_config &mconfig, const char *tag, { } -nes_unl_bb_device::nes_unl_bb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : nes_nrom_device(mconfig, NES_UNL_BB, tag, owner, clock) -{ -} - nes_mmalee_device::nes_mmalee_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : nes_nrom_device(mconfig, NES_MMALEE, tag, owner, clock) { } -nes_shuiguan_device::nes_shuiguan_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : nes_nrom_device(mconfig, NES_SHUIGUAN, tag, owner, clock), m_irq_count(0), m_irq_enable(0), irq_timer(nullptr) -{ -} - nes_rt01_device::nes_rt01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : nes_nrom_device(mconfig, NES_RT01, tag, owner, clock) { } - - - -void nes_ax5705_device::device_start() +nes_yung08_device::nes_yung08_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : nes_nrom_device(mconfig, NES_YUNG08, tag, owner, clock), m_irq_count(0), m_irq_latch(0), irq_timer(nullptr) { - 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() { @@ -200,7 +249,6 @@ void nes_sc127_device::device_start() void nes_sc127_device::pcb_reset() { - m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; prg32(0xff); chr8(0, m_chr_source); @@ -211,21 +259,20 @@ void nes_sc127_device::pcb_reset() void nes_mbaby_device::device_start() { common_start(); - irq_timer = timer_alloc(TIMER_IRQ); - irq_timer->reset(); - timer_freq = clocks_to_attotime(24576); + irq_timer = timer_alloc(FUNC(nes_mbaby_device::irq_timer_tick), this); + irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1)); save_item(NAME(m_irq_enable)); + save_item(NAME(m_irq_count)); save_item(NAME(m_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_irq_count = 0; m_latch = 0; } @@ -237,7 +284,6 @@ void nes_asn_device::device_start() 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); @@ -247,61 +293,70 @@ void nes_asn_device::pcb_reset() void nes_smb3p_device::device_start() { common_start(); - irq_timer = timer_alloc(TIMER_IRQ); + irq_timer = timer_alloc(FUNC(nes_smb3p_device::irq_timer_tick), this); irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1)); save_item(NAME(m_irq_enable)); save_item(NAME(m_irq_count)); } -void nes_smb3p_device::pcb_reset() +void nes_smb3p_device::pcb_start(running_machine &machine, u8 *ciram_ptr, bool cart_mounted) { - 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); + device_nes_cart_interface::pcb_start(machine, ciram_ptr, cart_mounted); + // registers reliably boot up with all 1s according to hardware tests + for (int i = 0; i < 4; i++) + prg8_x(i, 0x1f); +} - m_irq_enable = 0; - m_irq_count = 0; +void nes_smb3p_device::pcb_reset() +{ + // registers not cleared or initialized at reset } -void nes_btl_dn_device::device_start() +void nes_batmanfs_device::device_start() { common_start(); + irq_timer = timer_alloc(FUNC(nes_batmanfs_device::irq_timer_tick), this); + irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1)); + + save_item(NAME(m_irq_enable)); save_item(NAME(m_irq_count)); } -void nes_btl_dn_device::pcb_reset() +void nes_batmanfs_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); + prg32((m_prg_chunks >> 1) - 1); // Last 8K bank is fixed, the rest are swappable + chr8(0, CHRROM); + m_irq_enable = 0; m_irq_count = 0; } -void nes_whirl2706_device::device_start() +void nes_btl_cj_device::pcb_reset() +{ + prg32((m_prg_chunks >> 1) - 1); // Last 8K bank is fixed, the rest are swappable + chr8(0, CHRROM); +} + +void nes_btl_dn_device::device_start() { common_start(); - save_item(NAME(m_latch)); + save_item(NAME(m_irq_count)); } -void nes_whirl2706_device::pcb_reset() +void nes_btl_dn_device::pcb_reset() { - m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; - prg32(0xff); + prg16_89ab(0); + prg16_cdef(m_prg_chunks - 1); chr8(0, m_chr_source); - m_latch = 0; + m_irq_count = 0; } void nes_smb2j_device::device_start() { common_start(); - irq_timer = timer_alloc(TIMER_IRQ); + irq_timer = timer_alloc(FUNC(nes_smb2j_device::irq_timer_tick), this); irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1)); save_item(NAME(m_irq_enable)); @@ -310,12 +365,11 @@ void nes_smb2j_device::device_start() 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_cd(4); // switchable bank prg8_ef(9); + chr8(0, CHRROM); m_irq_enable = 0; m_irq_count = 0; @@ -324,7 +378,7 @@ void nes_smb2j_device::pcb_reset() void nes_smb2ja_device::device_start() { common_start(); - irq_timer = timer_alloc(TIMER_IRQ); + irq_timer = timer_alloc(FUNC(nes_smb2ja_device::irq_timer_tick), this); irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1)); save_item(NAME(m_irq_enable)); @@ -333,12 +387,11 @@ void nes_smb2ja_device::device_start() 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); + prg8_89(4); + prg8_ab(5); + prg8_cd(0); // switchable bank + prg8_ef(7); + chr8(0, CHRROM); m_irq_enable = 0; m_irq_count = 0; @@ -347,37 +400,98 @@ void nes_smb2ja_device::pcb_reset() void nes_smb2jb_device::device_start() { common_start(); - irq_timer = timer_alloc(TIMER_IRQ); + irq_timer = timer_alloc(FUNC(nes_smb2jb_device::irq_timer_tick), this); irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1)); save_item(NAME(m_irq_enable)); save_item(NAME(m_irq_count)); + save_item(NAME(m_reg)); } void nes_smb2jb_device::pcb_reset() { - m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; prg8_89(0x08); prg8_ab(0x09); - prg8_cd(0); + prg8_cd(0); // switchable bank prg8_ef(0x0b); - chr8(0, m_chr_source); m_irq_enable = 0; m_irq_count = 0; + m_reg = 0; +} + +void nes_n32_4in1_device::pcb_reset() +{ + // Powers up in menu, but soft reset does not touch banks (so each game returns to its own title). Is this correct? + + m_irq_enable = 0; + m_irq_count = 0; + m_reg = 0; +} + +void nes_0353_device::device_start() +{ + common_start(); + save_item(NAME(m_reg)); +} + +void nes_0353_device::pcb_reset() +{ + prg32((m_prg_chunks >> 1) - 1); // fixed 32K bank + + m_reg = 0; } void nes_09034a_device::device_start() { common_start(); + irq_timer = timer_alloc(FUNC(nes_09034a_device::irq_timer_tick), this); + irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1)); + + save_item(NAME(m_irq_enable)); + save_item(NAME(m_irq_count)); save_item(NAME(m_reg)); } void nes_09034a_device::pcb_reset() { - m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; prg32(0); chr8(0, m_chr_source); + + m_irq_enable = 0; + m_irq_count = 0; + m_reg = 0; +} + +void nes_l001_device::device_start() +{ + common_start(); + irq_timer = timer_alloc(FUNC(nes_l001_device::irq_timer_tick), this); + irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1)); + + save_item(NAME(m_irq_count)); +} + +void nes_l001_device::pcb_reset() +{ + prg32((m_prg_chunks >> 1) - 1); + chr8(0, CHRROM); + + m_irq_count = 0; +} + +void nes_palthena_device::device_start() +{ + common_start(); + save_item(NAME(m_reg)); +} + +void nes_palthena_device::pcb_reset() +{ + prg8_89(0x0c); + // 0xa000-0xbfff switchable bank + prg16_cdef(m_prg_chunks - 1); + m_reg = 0; } @@ -389,13 +503,25 @@ void nes_tobidase_device::device_start() 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_whirlwind_device::device_start() +{ + common_start(); + save_item(NAME(m_reg)); +} + +void nes_whirlwind_device::pcb_reset() +{ + prg32((m_prg_chunks >> 1) - 1); // upper PRG: banks are always fixed + chr8(0, m_chr_source); + + m_reg = (m_prg_chunks << 1) - 1; // lower PRG: ProWres needs this fixed, others modify it +} + void nes_lh32_device::device_start() { common_start(); @@ -404,36 +530,64 @@ void nes_lh32_device::device_start() 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_lh42_device::device_start() +{ + common_start(); + save_item(NAME(m_latch)); +} + +void nes_lh42_device::pcb_reset() +{ + prg16_89ab(0); + prg16_cdef(m_prg_chunks - 1); // Last 16K is fixed + + m_latch = 0; +} + +void nes_lg25_device::device_start() +{ + common_start(); + save_item(NAME(m_latch)); +} + +void nes_lg25_device::pcb_reset() +{ + prg16_89ab(0); + prg16_cdef(m_prg_chunks - 1); // Last 16K is fixed + + m_latch = 0; +} + 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)); + prg8_ef((m_prg_chunks << 1) - 1); + m_latch = 0; } +void nes_lh51_device::pcb_reset() +{ + prg32((m_prg_chunks >> 1) - 1); // first 8K is switchable, the rest fixed +} + void nes_lh53_device::device_start() { common_start(); - irq_timer = timer_alloc(TIMER_IRQ); + irq_timer = timer_alloc(FUNC(nes_lh53_device::irq_timer_tick), this); irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1)); save_item(NAME(m_irq_enable)); @@ -443,11 +597,9 @@ void nes_lh53_device::device_start() 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_ab(0xd); // last 2K are overlaid by WRAM + prg8_cd(0xe); // first 6K are overlaid by WRAM prg8_ef(0xf); m_reg = 0; m_irq_count = 0; @@ -462,10 +614,8 @@ void nes_2708_device::device_start() 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 + // the upper PRG banks never change, but there are 8K of WRAM overlaid to the ROM area based on reg1 m_reg[0] = 0; m_reg[1] = 0; } @@ -478,75 +628,40 @@ void nes_ac08_device::device_start() 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() +void nes_rt01_device::pcb_reset() { - chr8(0, CHRROM); - prg32(0); + chr2_0(0, CHRROM); + chr2_2(0, CHRROM); + chr2_4(0, CHRROM); + chr2_6(0, CHRROM); + prg16_89ab(0); + prg16_cdef(0); } -void nes_shuiguan_device::device_start() +void nes_yung08_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, clocks_to_attotime(114)); + irq_timer = timer_alloc(FUNC(nes_yung08_device::irq_timer_tick), this); + irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1)); - save_item(NAME(m_irq_enable)); save_item(NAME(m_irq_count)); - save_item(NAME(m_mmc_vrom_bank)); + save_item(NAME(m_irq_latch)); } -void nes_shuiguan_device::pcb_reset() +void nes_yung08_device::pcb_reset() { - m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; - prg32((m_prg_chunks << 1) - 1); - chr8(0, m_chr_source); + prg8_89(1); + prg8_ab(0); + prg8_cd(0); // switchable bank + prg8_ef(8); + chr8(0, CHRROM); - m_irq_enable = 0; m_irq_count = 0; - memset(m_mmc_vrom_bank, 0, sizeof(m_mmc_vrom_bank)); -} - - -void nes_rt01_device::device_start() -{ - common_start(); -} - -void nes_rt01_device::pcb_reset() -{ - chr2_0(0, CHRROM); - chr2_2(0, CHRROM); - chr2_4(0, CHRROM); - chr2_6(0, CHRROM); - prg16_89ab(0); - prg16_cdef(0); + m_irq_latch = 0; } @@ -556,88 +671,17 @@ void nes_rt01_device::pcb_reset() /*------------------------------------------------- - 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]); -} - -void nes_ax5705_device::write_h(offs_t offset, uint8_t data) -{ - uint8_t 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 + In MAME: Supported. -------------------------------------------------*/ -void nes_sc127_device::hblank_irq(int scanline, int vblank, int blanked) +void nes_sc127_device::hblank_irq(int scanline, bool vblank, bool blanked) { if (scanline < ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE && m_irq_enable) { @@ -645,8 +689,8 @@ void nes_sc127_device::hblank_irq(int scanline, int vblank, int blanked) if (!blanked && (m_irq_count == 0)) { - LOG_MMC(("irq fired, scanline: %d\n", scanline)); - hold_irq_line(); + LOG("irq fired, scanline: %d\n", scanline); + set_irq_line(ASSERT_LINE); m_irq_enable = 0; } } @@ -654,7 +698,7 @@ void nes_sc127_device::hblank_irq(int scanline, int vblank, int blanked) void nes_sc127_device::write_h(offs_t offset, uint8_t data) { - LOG_MMC(("sc127 write_h, offset: %04x, data: %02x\n", offset, data)); + LOG("sc127 write_h, offset: %04x, data: %02x\n", offset, data); switch (offset) { @@ -681,6 +725,7 @@ void nes_sc127_device::write_h(offs_t offset, uint8_t data) break; case 0x4002: m_irq_enable = 0; + set_irq_line(CLEAR_LINE); break; case 0x4003: m_irq_enable = 1; @@ -702,22 +747,24 @@ void nes_sc127_device::write_h(offs_t offset, uint8_t data) iNES: mapper 42 - In MESS: Supported. + In MAME: Supported. -------------------------------------------------*/ -void nes_mbaby_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +TIMER_CALLBACK_MEMBER(nes_mbaby_device::irq_timer_tick) { - if (id == TIMER_IRQ) + if (m_irq_enable) { - hold_irq_line(); - irq_timer->adjust(attotime::never); + m_irq_count = (m_irq_count + 1) & 0x7fff; // unverified 15-bit counter based on FCEUX + + if (m_irq_count >= 0x6000) + set_irq_line(ASSERT_LINE); } } -void nes_mbaby_device::write_h(offs_t offset, uint8_t data) +void nes_mbaby_device::write_h(offs_t offset, u8 data) { - LOG_MMC(("Mario Baby write_h, offset: %04x, data: %02x\n", offset, data)); + LOG("Mario Baby write_h, offset: %04x, data: %02x\n", offset, data); if (offset >= 0x7000) { @@ -730,25 +777,20 @@ void nes_mbaby_device::write_h(offs_t offset, uint8_t data) 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 = BIT(data, 1); + if (!m_irq_enable) { - m_irq_enable = 0; - irq_timer->adjust(attotime::never); + m_irq_count = 0; + set_irq_line(CLEAR_LINE); } break; } } } -uint8_t nes_mbaby_device::read_m(offs_t offset) +u8 nes_mbaby_device::read_m(offs_t offset) { - LOG_MMC(("Mario Baby read_m, offset: %04x\n", offset)); + LOG("Mario Baby read_m, offset: %04x\n", offset); return m_prg[(m_latch * 0x2000) + (offset & 0x1fff)]; } @@ -760,13 +802,13 @@ uint8_t nes_mbaby_device::read_m(offs_t offset) iNES: mapper 42 with no IRQ and no NT, but CHR switch - In MESS: Partially Supported. + In MAME: Partially supported. -------------------------------------------------*/ void nes_asn_device::write_h(offs_t offset, uint8_t data) { - LOG_MMC(("Ai Senshi Nicol write_h, offset: %04x, data: %02x\n", offset, data)); + LOG("Ai Senshi Nicol write_h, offset: %04x, data: %02x\n", offset, data); if (offset == 0x0000) chr8(data, CHRROM); @@ -777,11 +819,10 @@ void nes_asn_device::write_h(offs_t offset, uint8_t data) uint8_t nes_asn_device::read_m(offs_t offset) { - LOG_MMC(("Ai Senshi Nicol read_m, offset: %04x\n", offset)); + LOG("Ai Senshi Nicol read_m, offset: %04x\n", offset); return m_prg[((m_latch * 0x2000) + (offset & 0x1fff)) & (m_prg_size - 1)]; } - /*------------------------------------------------- BTL-SMB3 @@ -790,62 +831,46 @@ uint8_t nes_asn_device::read_m(offs_t offset) iNES: mapper 106 - In MESS: Supported. + In MAME: Supported. -------------------------------------------------*/ -void nes_smb3p_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +TIMER_CALLBACK_MEMBER(nes_smb3p_device::irq_timer_tick) { - if (id == TIMER_IRQ) - { - if (m_irq_enable) - { - if (m_irq_count == 0xffff) - { - hold_irq_line(); - m_irq_enable = 0; - } - else - m_irq_count++; - } - } + // counter does not stop when interrupts are disabled + if (m_irq_count != 0xffff) + m_irq_count++; + if (m_irq_enable && m_irq_count == 0xffff) + set_irq_line(ASSERT_LINE); } -void nes_smb3p_device::write_h(offs_t offset, uint8_t data) +void nes_smb3p_device::write_h(offs_t offset, u8 data) { - LOG_MMC(("btl_smb3_w, offset: %04x, data: %02x\n", offset, data)); + LOG("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); + case 0x00: case 0x01: case 0x02: case 0x03: + chr1_x(offset & 0x07, (data & 0x7e) | BIT(offset, 0), CHRROM); break; - case 0x04: case 0x05: - case 0x06: case 0x07: - chr1_x(offset & 0x07, data, CHRROM); + case 0x04: case 0x05: case 0x06: case 0x07: + chr1_x(offset & 0x07, data & 0x7f, CHRROM); break; case 0x08: - prg8_89(data | 0x10); + case 0x0b: + prg8_x(offset & 0x03, (data | 0x10) & 0x1f); break; case 0x09: - prg8_ab(data); - break; case 0x0a: - prg8_cd(data); - break; - case 0x0b: - prg8_ef(data | 0x10); + prg8_x(offset & 0x03, data & 0x1f); break; case 0x0c: - set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); + set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); break; case 0x0d: m_irq_count = 0; m_irq_enable = 0; + set_irq_line(CLEAR_LINE); break; case 0x0e: m_irq_count = (m_irq_count & 0xff00) | data; @@ -859,30 +884,72 @@ void nes_smb3p_device::write_h(offs_t offset, uint8_t data) /*------------------------------------------------- + BTL-CONTRAJ + + Games: Contra (J) pirate + + NES 2.0: mapper 326 + + This PCB has swappable 8K banks at 0x8000-0x9fff, + 0xa000-0xbfff, and 0xc000-0xdfff and associated + registers in those ranges. Selectable 1K banks for + both CHRROM and CIRAM are also in registers across + upper memory, 0x8000-0xffff, with mask 0x8010. + + In MAME: Supported. + + TODO: Find out why this crashes in the intro story. + Bootleggers missed the bug? Bad dump? This differs + only in a couple hundred bytes from contraj, so there + aren't that many places for the problem to hide. + + -------------------------------------------------*/ + +void nes_btl_cj_device::write_h(offs_t offset, u8 data) +{ + LOG("btl_cj write_h, offset: %04x, data: %02x\n", offset, data); + + if (BIT(offset, 4)) + { + if (BIT(offset, 3)) + set_nt_page(offset & 0x03, CIRAM, data & 1, 1); + else + chr1_x(offset & 0x07, data, CHRROM); + } + else + { + offset = BIT(offset, 13, 2); + if (offset != 3) + prg8_x(offset, data & 0x0f); + } +} + +/*------------------------------------------------- + BTL-DRAGONNINJA Games: Dragon Ninja (Bootleg), Super Mario Bros. 8 iNES: mapper 222 - In MESS: Unsupported. + In MAME: Unsupported. -------------------------------------------------*/ /* Scanline based IRQ ? */ -void nes_btl_dn_device::hblank_irq(int scanline, int vblank, int blanked ) +void nes_btl_dn_device::hblank_irq(int scanline, bool vblank, bool blanked) { if (!m_irq_count || ++m_irq_count < 240) return; m_irq_count = 0; - hold_irq_line(); + set_irq_line(ASSERT_LINE); } void nes_btl_dn_device::write_h(offs_t offset, uint8_t data) { uint8_t bank; - LOG_MMC(("btl_dn write_h, offset: %04x, data: %02x\n", offset, data)); + LOG("btl_dn write_h, offset: %04x, data: %02x\n", offset, data); switch (offset & 0x7003) { @@ -903,11 +970,12 @@ void nes_btl_dn_device::write_h(offs_t offset, uint8_t data) case 0x5002: case 0x6000: case 0x6002: - bank = ((offset & 0x7000) - 0x3000) / 0x0800 + ((offset & 0x0002) >> 1); + bank = 2 * (BIT(offset, 12, 3) - 3) + BIT(offset, 1); chr1_x(bank, data, CHRROM); break; case 0x7000: m_irq_count = data; + set_irq_line(CLEAR_LINE); break; } } @@ -920,152 +988,174 @@ void nes_btl_dn_device::write_h(offs_t offset, uint8_t data) /*------------------------------------------------- - WHIRLWIND-2706 + Boards DH-08, LE05, LH28, LH31, LH54 (same as LH28) - Games: Meikyuu Jiin Dababa (FDS conversion) and a few - others + Games: Bubble Bobble alt 1, ProWres, Meikyuu Jiin Dababa, + Bubble Bobble alt 2, Falsion - This PCB maps PRG in 0x6000-0x7fff + Similar PCB variants for FDS conversions by Whirlwind Manu. They + map PRG in 0x6000-0x7fff. They vary slightly in the use/nonuse + of CHR RAM, switchable banks, and valid register locations. - iNES: mapper 108 + iNES: mapper 108, 4 submappers - In MESS: Supported. + In MAME: Supported. -------------------------------------------------*/ -void nes_whirl2706_device::write_h(offs_t offset, uint8_t data) +u8 nes_whirlwind_device::read_m(offs_t offset) { - LOG_MMC(("whirl2706 write_h, offset: %04x, data: %02x\n", offset, data)); - m_latch = data; + LOG("whirlwind read_m, offset: %04x\n", offset); + return m_prg[((m_reg & m_prg_mask) * 0x2000) + offset]; } -uint8_t nes_whirl2706_device::read_m(offs_t offset) +void nes_dh08_device::write_h(offs_t offset, u8 data) // submapper 1 { - LOG_MMC(("whirl2706 read_m, offset: %04x\n", offset)); - return m_prg[(m_latch * 0x2000 + (offset & 0x1fff)) & (m_prg_size - 1)]; + LOG("dh08 write_h, offset: %04x, data: %02x\n", offset, data); + if (offset >= 0x7000) + m_reg = data; +} + +void nes_le05_device::write_h(offs_t offset, u8 data) // submapper 4 +{ + LOG("le05 write_h, offset: %04x, data: %02x\n", offset, data); + chr8(data & 1, m_chr_source); +} + +void nes_lh28_lh54_device::write_h(offs_t offset, u8 data) // submapper 3 +{ + LOG("lh28_lh54 write_h, offset: %04x, data: %02x\n", offset, data); + m_reg = data; +} + +void nes_lh31_device::write_h(offs_t offset, u8 data) // submapper 2 +{ + LOG("lh31 write_h, offset: %04x, data: %02x\n", offset, data); + if (offset >= 0x6000) + { + m_reg = data; + chr8(data, m_chr_source); + } } /*------------------------------------------------- Bootleg Board SMB2J - Games: Super Mario Bros. 2 Pirate (LF36) + Games: Super Mario Bros. 2 Pirates (TONY-I, YS-612) iNES: mapper 43 - In MESS: Supported. + In MAME: Supported. -------------------------------------------------*/ -void nes_smb2j_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +TIMER_CALLBACK_MEMBER(nes_smb2j_device::irq_timer_tick) { - if (id == TIMER_IRQ) + if (m_irq_enable) { - if (m_irq_enable) - { - if (m_irq_count == 0xfff) - { - hold_irq_line(); - m_irq_enable = 0; - m_irq_count = 0; - } - else - m_irq_count++; - } + m_irq_count = (m_irq_count + 1) & 0xfff; + if (!m_irq_count) + set_irq_line(ASSERT_LINE); } } -void nes_smb2j_device::write_l(offs_t offset, uint8_t data) +void nes_smb2j_device::update_irq(u8 data) { - 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?!? + m_irq_enable = BIT(data, 0); + if (!m_irq_enable) + { + set_irq_line(CLEAR_LINE); + m_irq_count = 0; + } } -void nes_smb2j_device::write_h(offs_t offset, uint8_t data) +void nes_smb2j_device::write_45(offs_t offset, u8 data) { - LOG_MMC(("smb2j write_h, offset: %04x, data: %02x\n", offset, data)); + static const u8 bank[8] = {4, 3, 4, 4, 4, 7, 5, 6}; - if (offset == 0x122) // $8122 too? - m_irq_enable = data & 3; + switch (offset & 0x71ff) + { + case 0x4022: + prg8_cd(bank[data & 0x07]); + break; + case 0x4122: + nes_smb2j_device::update_irq(data); + break; + } } -void nes_smb2j_device::write_ex(offs_t offset, uint8_t data) +void nes_smb2j_device::write_ex(offs_t offset, u8 data) { - LOG_MMC(("smb2j write_ex, offset: %04x, data: %02x\n", offset, data)); + LOG("smb2j write_ex, offset: %04x, data: %02x\n", offset, data); + nes_smb2j_device::write_45(offset + 0x4020, data); +} - if (offset == 2) - { - int temp; +void nes_smb2j_device::write_l(offs_t offset, u8 data) +{ + LOG("smb2j write_l, offset: %04x, data: %02x\n", offset, data); + nes_smb2j_device::write_45(offset + 0x4100, data); +} - // According to hardware tests - if (data & 1) - temp = 3; - else - temp = 4 + ((data & 7) >> 1); +void nes_smb2j_device::write_h(offs_t offset, u8 data) +{ + LOG("smb2j write_h, offset: %04x, data: %02x\n", offset, data); - prg8_cd(temp); - } + if (offset == 0x122) // $8122 is also IRQ for YS-612, mask unknown + nes_smb2j_device::update_irq(data); } -uint8_t nes_smb2j_device::read_l(offs_t offset) +u8 nes_smb2j_device::read_l(offs_t offset) { - LOG_MMC(("smb2j read_l, offset: %04x\n", offset)); + LOG("smb2j read_l, offset: %04x\n", offset); offset += 0x100; if (offset >= 0x1000) return m_prg[0x10000 + (offset & 0x0fff)]; - return get_open_bus(); // open bus + return get_open_bus(); } -uint8_t nes_smb2j_device::read_m(offs_t offset) +u8 nes_smb2j_device::read_m(offs_t offset) { - LOG_MMC(("smb2j read_m, offset: %04x\n", offset)); + LOG("smb2j read_m, offset: %04x\n", offset); return m_prg[0x4000 + offset]; } /*------------------------------------------------- - BTL-SMB2A + BTL-SMB2JA - Games: Super Mario Bros. 2 Pirate (Jpn version of SMB2) + Games: Super Mario Bros. 2 Pirates (LF36, Hey Sung, 1990 SMB4) iNES: mapper 40 - In MESS: Supported. + In MAME: Supported. -------------------------------------------------*/ -void nes_smb2ja_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +TIMER_CALLBACK_MEMBER(nes_smb2ja_device::irq_timer_tick) { - if (id == TIMER_IRQ) + if (m_irq_enable) { - if (m_irq_enable) - { - if (m_irq_count == 0xfff) - { - hold_irq_line(); - m_irq_enable = 0; - m_irq_count = 0; - } - else - m_irq_count++; - } + m_irq_count = (m_irq_count + 1) & 0x1fff; // 13-bit counter + if (BIT(m_irq_count, 12)) + set_irq_line(ASSERT_LINE); + else if (!m_irq_count) + set_irq_line(CLEAR_LINE); // CD4020 acknowledges on overflow } } -void nes_smb2ja_device::write_h(offs_t offset, uint8_t data) +void nes_smb2ja_device::write_h(offs_t offset, u8 data) { - LOG_MMC(("smb2ja write_h, offset: %04x, data: %02x\n", offset, data)); + LOG("smb2ja write_h, offset: %04x, data: %02x\n", offset, data); switch (offset & 0x6000) { case 0x0000: m_irq_enable = 0; m_irq_count = 0; + set_irq_line(CLEAR_LINE); break; case 0x2000: m_irq_enable = 1; @@ -1076,112 +1166,407 @@ void nes_smb2ja_device::write_h(offs_t offset, uint8_t data) } } -uint8_t nes_smb2ja_device::read_m(offs_t offset) +u8 nes_smb2ja_device::read_m(offs_t offset) { - LOG_MMC(("smb2ja read_m, offset: %04x\n", offset)); - return m_prg[(0xfe * 0x2000 + (offset & 0x1fff)) & (m_prg_size - 1)]; + LOG("smb2ja read_m, offset: %04x\n", offset); + return m_prg[0x06 * 0x2000 + offset]; // fixed 8K bank } /*------------------------------------------------- - BTL-SMB2B + BTL-SMB2JB (PCB 761214) - Games: Super Mario Bros. 2 Pirate (Jpn version of SMB2) + Games: Super Mario Bros. 2 Pirate (N-32) This was marked as Alt. Levels. is it true? iNES: mapper 50 - In MESS: Partially Supported. + In MAME: Supported. -------------------------------------------------*/ -void nes_smb2jb_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +TIMER_CALLBACK_MEMBER(nes_smb2jb_device::irq_timer_tick) { - if (id == TIMER_IRQ) + if (m_irq_enable) { - if (m_irq_enable) - { - if (m_irq_count == 0xfff) + if (BIT(++m_irq_count, 12)) + set_irq_line(ASSERT_LINE); + } +} + +void nes_smb2jb_device::write_45(offs_t offset, u8 data) +{ + switch (offset & 0x4120) + { + case 0x4020: + m_reg = bitswap<4>(data, 3, 0, 2, 1); + prg8_cd(m_reg); + break; + case 0x4120: + m_irq_enable = BIT(data, 0); + if (!m_irq_enable) { - hold_irq_line(); - m_irq_enable = 0; + set_irq_line(CLEAR_LINE); m_irq_count = 0; } + break; + } +} + +void nes_smb2jb_device::write_ex(offs_t offset, u8 data) +{ + LOG("smb2jb write_ex, offset: %04x, data: %02x\n", offset, data); + write_45(offset + 0x4020, data); +} + +void nes_smb2jb_device::write_l(offs_t offset, u8 data) +{ + LOG("smb2jb write_l, offset: %04x, data: %02x\n", offset, data); + write_45(offset + 0x4100, data); +} + +u8 nes_smb2jb_device::read_m(offs_t offset) +{ + LOG("smb2jb read_m, offset: %04x\n", offset); + return m_prg[(m_bank67 * 0x2000 + offset) & (m_prg_size - 1)]; +} + +/*------------------------------------------------- + + BMC-N32-4IN1 + + Unknown Bootleg Multigame Board + Games: 4 in 1 + + This multicart contains the mapper 50 version of SMB2. + There are changes to bank locations compared to that + game, but otherwise we rely on the existing SMB2JB + emulation (unless other differences are discovered?) + + NES 2.0: mapper 416 + + In MAME: Supported. + + -------------------------------------------------*/ + +void nes_n32_4in1_device::write_h(offs_t offset, u8 data) +{ + LOG("n32_4in1 write_h, offset: %04x, data: %02x\n", offset, data); + + if (offset < 0x2000) + { + if (BIT(data, 3)) // NROM games + { + u8 bank = bitswap<3>(data, 3, 7, 5); + u8 mode = BIT(data, 7); + if (data & 0xc0) + { + prg16_89ab(bank & ~mode); + prg16_cdef(bank | mode); + } else - m_irq_count++; + for (int i = 0; i < 4; i++) + prg8_x(i, bank << 1); } + else // SMB2 only + { + prg8_89(0); + prg8_ab(1); + prg8_cd(m_reg); + prg8_ef(3); + } + + chr8(BIT(data, 1, 2), CHRROM); + set_nt_mirroring(BIT(data, 2) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); } } -void nes_smb2jb_device::write_l(offs_t offset, uint8_t data) +/*------------------------------------------------- + + (BTL-)0353 + + Games: Lucky Rabbit (Roger Rabbit conversion) + + NES 2.0: mapper 415 + + In MAME: Supported. + + -------------------------------------------------*/ + +u8 nes_0353_device::read_m(offs_t offset) +{ + LOGMASKED(LOG_HIFREQ, "0353 read_m, offset: %04x\n", offset); + return m_prg[m_reg * 0x2000 + offset]; +} + +void nes_0353_device::write_h(offs_t offset, u8 data) { - uint8_t prg; - LOG_MMC(("smb2jb write_l, offset: %04x, data: %02x\n", offset, data)); - offset += 0x100; + LOG("0353 write_h, offset: %04x, data: %02x\n", offset, data); + + set_nt_mirroring(BIT(data, 4) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); + m_reg = data & 0x0f; +} + +/*------------------------------------------------- + + (UNL-)09-034A + + Games: Zanac FDS conversion with two PRG chips and + no CHRROM, and SMB2 and Volleyball FDS conversions + with two PRG chips and CHRROM. Originally dumps + were marked as UNL-SMB2J PCB. + + Only SMB2 uses the IRQ and it has been documented as + being broken on real hardware. Most notably the status + bar scrolls with the rest of the screen and the game + completely crashes between the "our princess" scene of + world 4-4 and the beginning of world 5-1. How the IRQ + functions is to be confirmed but it likely uses a 12-bit + counter just like the other SMB2 bootlegs. That is how + we presently emulate it here. + + NES 2.0: mapper 304 + + In MAME: Supported. + + -------------------------------------------------*/ - switch (offset & 0x1e0) +TIMER_CALLBACK_MEMBER(nes_09034a_device::irq_timer_tick) +{ + if (m_irq_enable) { - case 0x020: - case 0x0a0: - prg = (data & 0x08) | ((data & 0x06) >> 1) | ((data & 0x01) << 2); - prg8_cd(prg); + m_irq_count = (m_irq_count + 1) & 0x0fff; + if (!m_irq_count) + set_irq_line(ASSERT_LINE); + } +} + +void nes_09034a_device::write_ex(offs_t offset, u8 data) +{ + LOG("09-034a write_ex, offset: %04x, data: %02x\n", offset, data); + + offset += 0x20; + switch (offset) + { + case 0x0027: + m_reg = data & 1; break; - case 0x120: - case 0x1a0: - m_irq_enable = data & 0x01; + case 0x0068: + m_irq_enable = BIT(data, 0); + if (!m_irq_enable) + { + m_irq_count = 0; + set_irq_line(CLEAR_LINE); + } break; } } -uint8_t nes_smb2jb_device::read_m(offs_t offset) +u8 nes_09034a_device::read_ex(offs_t offset) +{ + LOG("09-034a read_ex, offset: %04x, data: %02x\n", offset); + + offset += 0x20; + // SMB2 does not boot with the default open bus reads in this range + if (offset >= 0x42 && offset <= 0x55) + return 0xff; + else + return get_open_bus(); +} + +u8 nes_09034a_device::read_m(offs_t offset) +{ + LOG("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) & (m_prg_size - 1)]; +} + +/*------------------------------------------------- + + Board L-001 + + Games: Sangokushi III (Sangokushi II bootleg) + + This board has swappable 8K PRG banks at 0x8000, 0xa000, + and 0xc000, while 0xe000 is fixed to the final bank. + CHRROM and CIRAM are also swappable in 1K banks. + The board has a 16-bit IRQ counter with the enable bit + acting as the MSB. The enhanced audio of the original + Namco 163 board is not retained. + + NES 2.0: mapper 330 + + In MAME: Supported. + + -------------------------------------------------*/ + +TIMER_CALLBACK_MEMBER(nes_l001_device::irq_timer_tick) { - LOG_MMC(("smb2jb read_m, offset: %04x\n", offset)); - return m_prg[((0x0f * 0x2000) + (offset & 0x1fff)) & (m_prg_size - 1)]; + if (BIT(m_irq_count, 15)) + { + if (++m_irq_count == 0) + set_irq_line(ASSERT_LINE); + } } -/* This goes to 0x4020-0x403f & 0x40a0-0x40bf */ -void nes_smb2jb_device::write_ex(offs_t offset, uint8_t data) +void nes_l001_device::write_h(offs_t offset, u8 data) { - uint8_t prg; - LOG_MMC(("smb2jb write_ex, offset: %04x, data: %02x\n", offset, data)); + LOG("l-001 write_h, offset: %04x, data: %02x\n", offset, data); - if ((offset < 0x20) || (offset >= 0x80 && offset < 0xa0)) + switch (offset & 0x6400) { - prg = (data & 0x08) | ((data & 0x06) >> 1) | ((data & 0x01) << 2); - prg8_cd(prg); + case 0x0000: + case 0x2000: + chr1_x(BIT(offset, 11, 3), data, CHRROM); + break; + case 0x0400: + m_irq_count = (m_irq_count & 0xff00) | data; + break; + case 0x2400: + m_irq_count = (m_irq_count & 0x00ff) | data << 8; + set_irq_line(CLEAR_LINE); + break; + case 0x4000: + set_nt_page(BIT(offset, 11, 2), CIRAM, data & 1, 1); + break; + case 0x6000: + if (offset < 0x7800) + prg8_x(BIT(offset, 11, 2), data & 0x1f); + break; } } /*------------------------------------------------- - (UNL-)09-034A + BTL-BATMANFS - 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 + Games: Batman "Fine Studio" pirate - iNES: + NES 2.0: mapper 417 - In MESS: Partially Supported. Need to emulate IRQ - (needed by smb2 conversion?) + In MAME: Supported. -------------------------------------------------*/ -void nes_09034a_device::write_ex(offs_t offset, uint8_t data) +TIMER_CALLBACK_MEMBER(nes_batmanfs_device::irq_timer_tick) { - LOG_MMC(("09-034a write_ex, offset: %04x, data: %02x\n", offset, data)); + // 10-bit counter does not stop when interrupts are disabled + m_irq_count = (m_irq_count + 1) & 0x3ff; + if (m_irq_enable && !m_irq_count) + set_irq_line(ASSERT_LINE); +} - if (offset == 7) // $4027 - m_reg = data & 1; +void nes_batmanfs_device::write_h(offs_t offset, u8 data) +{ + LOG("batmanfs write_h, offset: %04x, data: %02x\n", offset, data); + switch (offset & 0x70) + { + case 0x00: + if ((offset & 0x03) != 0x03) + prg8_x(offset & 0x03, data & 0x0f); + break; + case 0x10: + case 0x20: + chr1_x((offset & 0x03) + 4 * BIT(offset, 5), data, CHRROM); + break; + case 0x30: + m_irq_enable = 1; + m_irq_count = 0; + break; + case 0x40: + m_irq_enable = 0; + set_irq_line(CLEAR_LINE); + break; + case 0x50: + set_nt_page(offset & 0x03, CIRAM, data & 1, 1); + break; + } } -uint8_t nes_09034a_device::read_m(offs_t offset) +/*------------------------------------------------- + + BTL-PALTHENA + + Games: Palthena no Kagami (FDS conversion) + + This board has fixed 8K PRG banks at 0x6000, 0x8000, + 0xc000, and 0xe000. The PRG bank at 0xa000 is switchable + by writing to the register in the same 0xa000-0xbfff + range. What makes the board interesting is the overlaid + 8K of RAM with only 6K addressable: + + 8K WRAM: Addr: + 0x0000-0x11ff 0xc000-0xd1ff + 0x1200-0x12ff 0x8200-0x82ff + 0x1300-0x17ff N/A + 0x1800-0x18ff 0x6000-0x60ff + 0x1900-0x19ff N/A + 0x1a00-0x1aff 0x6200-0x62ff + 0x1b00-0x1bff N/A + 0x1c00-0x1dff 0x6400-0x65ff + 0x1e00-0x1eff N/A + 0x1f00-0x1fff 0xdf00-0xdfff + + NES 2.0: mapper 539 + + In MAME: Supported. + +-------------------------------------------------*/ + +u8 nes_palthena_device::read_m(offs_t offset) { - 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]; + LOGMASKED(LOG_HIFREQ, "palthena read_m, offset: %04x\n", offset); + switch (offset & 0x1f00) + { + case 0x0000: + case 0x0200: + case 0x0400: + case 0x0500: + return m_prgram[offset | 0x1800]; + default: + return m_prg[0x0d * 0x2000 + offset]; // fixed PRG bank + } +} + +void nes_palthena_device::write_m(offs_t offset, u8 data) +{ + LOG("palthena write_m, offset: %04x, data: %02x\n", offset, data); + switch (offset & 0x1f00) + { + case 0x0000: + case 0x0200: + case 0x0400: + case 0x0500: + m_prgram[offset | 0x1800] = data; + break; + } +} + +u8 nes_palthena_device::read_h(offs_t offset) +{ + LOGMASKED(LOG_HIFREQ, "palthena read_h, offset: %04x\n", offset); + u8 page = offset >> 8; + if ((page >= 0x40 && page < 0x52) || page == 0x5f) + return m_prgram[offset & 0x1fff]; + else if (page == 0x02) + return m_prgram[offset | 0x1000]; + + return hi_access_rom(offset); +} + +void nes_palthena_device::write_h(offs_t offset, u8 data) +{ + LOG("palthena write_h, offset: %04x, data: %02x\n", offset, data); + u8 page = offset >> 8; + if ((page >= 0x40 && page < 0x52) || page == 0x5f) + m_prgram[offset & 0x1fff] = data; + else if (page == 0x02) + m_prgram[offset | 0x1000] = data; + else if (page >= 0x20 && page < 0x40) + prg8_ab(data & 0x0f); + else if (offset == 0x7fff) + set_nt_mirroring(BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); } /*------------------------------------------------- @@ -1194,13 +1579,13 @@ uint8_t nes_09034a_device::read_m(offs_t offset) iNES: mapper 120 - In MESS: Partially Supported. + In MAME: Partially supported. -------------------------------------------------*/ void nes_tobidase_device::write_l(offs_t offset, uint8_t data) { - LOG_MMC(("tobidase write_h, offset: %04x, data: %02x\n", offset, data)); + LOG("tobidase write_l, offset: %04x, data: %02x\n", offset, data); offset += 0x4100; if ((offset & 0x63c0) == 0x41c0) @@ -1209,7 +1594,7 @@ void nes_tobidase_device::write_l(offs_t offset, uint8_t data) uint8_t nes_tobidase_device::read_m(offs_t offset) { - LOG_MMC(("tobidase read_m, offset: %04x\n", offset)); + LOG("tobidase read_m, offset: %04x\n", offset); if (m_latch >= 0x0c) m_latch -= 4; return m_prg[(m_latch * 0x2000) + (offset & 0x1fff)]; @@ -1223,21 +1608,21 @@ uint8_t nes_tobidase_device::read_m(offs_t offset) This PCB maps WRAM in 0xc000-0xdfff and PRG in 0x6000-0x7fff - iNES: + iNES: mapper 125 - In MESS: Supported. + In MAME: Supported. -------------------------------------------------*/ uint8_t nes_lh32_device::read_m(offs_t offset) { - LOG_MMC(("lh32 read_m, offset: %04x\n", offset)); + LOG("lh32 read_m, offset: %04x\n", offset); return m_prg[(m_latch * 0x2000) + (offset & 0x1fff)]; } uint8_t nes_lh32_device::read_h(offs_t offset) { -// LOG_MMC(("lh32 read_h, offset: %04x\n", offset)); + LOGMASKED(LOG_HIFREQ, "lh32 read_h, offset: %04x\n", offset); if (offset >= 0x4000 && offset < 0x6000) return m_prgram[offset & 0x1fff]; @@ -1247,18 +1632,17 @@ uint8_t nes_lh32_device::read_h(offs_t offset) void nes_lh32_device::write_m(offs_t offset, uint8_t data) { - LOG_MMC(("lh32 write_m, offset: %04x, data: %02x\n", offset, data)); + LOG("lh32 write_m, offset: %04x, data: %02x\n", offset, data); if (offset == 0) // 0x6000 only? { -// printf("write %x\n", data); m_latch = data & 0xf; } } void nes_lh32_device::write_h(offs_t offset, uint8_t data) { - LOG_MMC(("lh32 write_h, offset: %04x, data: %02x\n", offset, data)); + LOG("lh32 write_h, offset: %04x, data: %02x\n", offset, data); if (offset >= 0x4000 && offset < 0x6000) m_prgram[offset & 0x1fff] = data; @@ -1266,6 +1650,81 @@ void nes_lh32_device::write_h(offs_t offset, uint8_t data) /*------------------------------------------------- + UNL-LH42 + + Games: Highway Star (Whirlwind Manu bootleg) + + NES 2.0: mapper 418 + + In MAME: Supported. + + -------------------------------------------------*/ + +void nes_lh42_device::write_h(offs_t offset, u8 data) +{ + LOG("lh42 write_h, offset: %04x, data: %02x\n", offset, data); + + switch (offset & 0x6001) + { + case 0x0000: + m_latch = data & 0x07; + break; + case 0x0001: + switch (m_latch) + { + case 5: + set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); + break; + case 6: + case 7: + prg8_x(m_latch & 1, data & 0x0f); + break; + } + break; + } +} + +/*------------------------------------------------- + + UNL-LG25 + + Games: Moero TwinBee Cinnamon Hakase o Sukue! (FDS conversion) + + In addition to the two swappable 8K PRG banks at + 0x8000 and 0xa000, this board has 8K WRAM at 0x6000. + + NES 2.0: mapper 557 + + In MAME: Supported. + + -------------------------------------------------*/ + +void nes_lg25_device::write_h(offs_t offset, u8 data) +{ + LOG("lg25 write_h, offset: %04x, data: %02x\n", offset, data); + + switch (offset & 0x6001) + { + case 0x0000: + m_latch = data & 0x07; + break; + case 0x0001: + switch (m_latch) + { + case 5: + set_nt_mirroring(BIT(data, 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); + break; + case 6: + case 7: + prg8_x(m_latch & 1, data & 0x0f); + break; + } + break; + } +} + +/*------------------------------------------------- + UNL-LH10 Games: Fuuun Shaolin Kyo (FDS conversion) @@ -1273,27 +1732,21 @@ void nes_lh32_device::write_h(offs_t offset, uint8_t data) This PCB maps WRAM in 0xc000-0xdfff and PRG in 0x6000-0x7fff This is very similar to KS7037 (see kaiser.cpp) - iNES: + NES 2.0: mapper 522 - In MESS: Supported. + In MAME: Supported. -------------------------------------------------*/ -void nes_lh10_device::update_prg() -{ - prg8_89(m_reg[6]); - prg8_ab(m_reg[7]); -} - -uint8_t nes_lh10_device::read_m(offs_t offset) +u8 nes_lh10_device::read_m(offs_t offset) { - LOG_MMC(("lh10 read_m, offset: %04x\n", offset)); - return m_prg[(0x0e * 0x2000) + (offset & 0x1fff)]; + LOG("lh10 read_m, offset: %04x\n", offset); + return m_prg[(0x0e * 0x2000 + offset) & (m_prg_size - 1)]; } -uint8_t nes_lh10_device::read_h(offs_t offset) +u8 nes_lh10_device::read_h(offs_t offset) { -// LOG_MMC(("lh10 read_h, offset: %04x\n", offset)); + LOGMASKED(LOG_HIFREQ, "lh10 read_h, offset: %04x\n", offset); if (offset >= 0x4000 && offset < 0x6000) return m_prgram[offset & 0x1fff]; @@ -1301,25 +1754,60 @@ uint8_t nes_lh10_device::read_h(offs_t offset) return hi_access_rom(offset); } -void nes_lh10_device::write_h(offs_t offset, uint8_t data) +void nes_lh10_device::write_h(offs_t offset, u8 data) { - LOG_MMC(("lh10 write_h, offset: %04x, data: %02x\n", offset, data)); + LOG("lh10 write_h, offset: %04x, data: %02x\n", offset, data); - if (offset >= 0x4000 && offset < 0x6000) - m_prgram[offset & 0x1fff] = data; + switch (offset & 0x6001) + { + case 0x0000: + m_latch = data & 7; + break; + case 0x0001: + switch (m_latch) + { + case 6: + case 7: + prg8_x(m_latch & 1, data & 0x0f); + break; + } + break; + case 0x4000: + case 0x4001: + m_prgram[offset & 0x1fff] = data; + break; + } +} - else +/*------------------------------------------------- + + UNL-LH51 + + Games: Ai Senshi Nicol (Whirlwind Manu FDS conversion) + + A simple board with swappable 8K PRG at 0x8000-0x9fff, + fixed PRG above that, and 8K WRAM at 0x6000-0x7fff. + The game's sound code is broken and does not work on + real hardware. + + NES 2.0: mapper 309 + + In MAME: Supported. + + -------------------------------------------------*/ + +void nes_lh51_device::write_h(offs_t offset, u8 data) +{ + LOG("lh51 write_h, offset: %04x, data: %02x\n", offset, data); + + switch (offset & 0x6000) { - switch (offset & 0x6001) - { - case 0x0000: - m_latch = data & 7; - break; - case 0x0001: - m_reg[m_latch] = data; - update_prg(); - break; - } + case 0x0000: + prg8_89(data & 0x0f); + break; + case 0x6000: + set_nt_mirroring(BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT); + break; } } @@ -1329,54 +1817,49 @@ void nes_lh10_device::write_h(offs_t offset, uint8_t data) Games: Nazo no Murasamejou (FDS conversion) - This PCB maps WRAM (w/battery) in 0xb800-0xd7ff and - PRG in 0x6000-0x7fff + This PCB maps WRAM in 0xb800-0xd7ff and PRG in 0x6000-0x7fff - iNES: + NES 2.0: mapper 535 - In MESS: Preliminar Support only. + In MAME: Preliminary support only. -------------------------------------------------*/ -void nes_lh53_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +TIMER_CALLBACK_MEMBER(nes_lh53_device::irq_timer_tick) { - if (id == TIMER_IRQ) + if (m_irq_enable) { - if (m_irq_enable) + m_irq_count++; + if (m_irq_count > 7560)//value from FCEUMM... { - m_irq_count++; - if (m_irq_count > 7560)//value from FCEUMM... - { - m_irq_count = 0; - set_irq_line(ASSERT_LINE); - } + m_irq_count = 0; + set_irq_line(ASSERT_LINE); } } } uint8_t nes_lh53_device::read_m(offs_t offset) { - LOG_MMC(("lh53 read_m, offset: %04x\n", offset)); - return m_prg[(m_reg * 0x2000) + (offset & 0x1fff)]; + LOG("lh53 read_m, offset: %04x\n", offset); + return m_prg[m_reg * 0x2000 + offset]; } uint8_t nes_lh53_device::read_h(offs_t offset) { -// LOG_MMC(("lh53 read_h, offset: %04x\n", offset)); + LOGMASKED(LOG_HIFREQ, "lh53 read_h, offset: %04x\n", offset); if (offset >= 0x3800 && offset < 0x5800) - return m_battery[offset & 0x1fff]; + return m_prgram[offset - 0x3800]; return hi_access_rom(offset); } void nes_lh53_device::write_h(offs_t offset, uint8_t data) { - LOG_MMC(("lh53 write_h, offset: %04x, data: %02x\n", offset, data)); + LOG("lh53 write_h, offset: %04x, data: %02x\n", offset, data); if (offset >= 0x3800 && offset < 0x5800) - m_battery[offset & 0x1fff] = data; - + m_prgram[offset - 0x3800] = data; else { switch (offset & 0x7000) @@ -1400,21 +1883,21 @@ void nes_lh53_device::write_h(offs_t offset, uint8_t data) 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. + iNES: mapper 103 + + In MAME: Supported. -------------------------------------------------*/ uint8_t nes_2708_device::read_m(offs_t offset) { - LOG_MMC(("btl-2708 read_m, offset: %04x\n", offset)); + LOG("btl-2708 read_m, offset: %04x\n", offset); if (!m_reg[1]) return m_prgram[offset]; // lower 8K of WRAM else @@ -1423,14 +1906,14 @@ uint8_t nes_2708_device::read_m(offs_t offset) void nes_2708_device::write_m(offs_t offset, uint8_t data) { - LOG_MMC(("btl-2708 write_m, offset: %04x, data: %02x\n", offset, data)); + LOG("btl-2708 write_m, offset: %04x, data: %02x\n", offset, data); // if (!m_reg[1]) m_prgram[offset] = data; // lower 8K of WRAM } uint8_t nes_2708_device::read_h(offs_t offset) { -// LOG_MMC(("btl-2708 read_h, offset: %04x\n", offset)); + LOGMASKED(LOG_HIFREQ, "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 @@ -1440,7 +1923,7 @@ uint8_t nes_2708_device::read_h(offs_t offset) void nes_2708_device::write_h(offs_t offset, uint8_t data) { - LOG_MMC(("btl-2708 write_h, offset: %04x, data: %02x\n", offset, data)); + LOG("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 @@ -1465,93 +1948,59 @@ void nes_2708_device::write_h(offs_t offset, uint8_t data) 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. + iNES: ??? + + In MAME: Supported. -------------------------------------------------*/ void nes_ac08_device::write_ex(offs_t offset, uint8_t data) { - LOG_MMC(("AC-08 write_ex, offset: %04x, data: %02x\n", offset, data)); + LOG("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); } uint8_t nes_ac08_device::read_m(offs_t offset) { - LOG_MMC(("AC-08 read_m, offset: %04x\n", offset)); + LOG("AC-08 read_m, offset: %04x\n", offset); return m_prg[(m_latch * 0x2000) + (offset & 0x1fff)]; } void nes_ac08_device::write_h(offs_t offset, uint8_t data) { - LOG_MMC(("AC-08 write_h, offset: %04x, data: %02x\n", offset, data)); + LOG("AC-08 write_h, offset: %04x, data: %02x\n", offset, data); if (offset == 1) - m_latch = (data >> 1) & 0x0f; + m_latch = BIT(data, 1, 4); 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. - - -------------------------------------------------*/ - -uint8_t nes_unl_bb_device::read_m(offs_t offset) -{ - LOG_MMC(("unl-bb read_m, offset: %04x\n", offset)); - return m_prg[(((m_reg[0] & 3 & m_prg_mask) * 0x2000) + (offset & 0x1fff))]; -} - -void nes_unl_bb_device::write_h(offs_t offset, uint8_t data) -{ - 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. + iNES: mapper 55 + + In MAME: Supported. -------------------------------------------------*/ uint8_t nes_mmalee_device::read_m(offs_t offset) { - LOG_MMC(("mmalee read_m, offset: %04x\n", offset)); + LOG("mmalee read_m, offset: %04x\n", offset); if (offset < 0x0800) return m_prg[0x8000 + offset]; @@ -1563,7 +2012,7 @@ uint8_t nes_mmalee_device::read_m(offs_t offset) void nes_mmalee_device::write_m(offs_t offset, uint8_t data) { - LOG_MMC(("mmalee write_m, offset: %04x, data: %02x\n", offset, data)); + LOG("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; @@ -1571,113 +2020,95 @@ void nes_mmalee_device::write_m(offs_t offset, uint8_t data) /*------------------------------------------------- - BTL-SHUIGUANPIPE + RT-01 + + Games: Russian test cart + + The PRG EPROM has copy protected areas with + "weak bits", which is tested at some points (info + from Cah4e3). + + NES 2.0: mapper 328 + + In MAME: Partially supported? + + -------------------------------------------------*/ + +uint8_t nes_rt01_device::read_h(offs_t offset) +{ + LOGMASKED(LOG_HIFREQ, "rt01 read_h, offset: %04x\n", offset); + + if ((offset >= 0x4e80) && (offset < 0x4f00)) + return 0xf2 | (machine().rand() & 0x0d); + if ((offset >= 0x7e80) && (offset < 0x7f00)) + return 0xf2 | (machine().rand() & 0x0d); + + return hi_access_rom(offset); +} + +/*------------------------------------------------- + + YUNG-08 - Games: Shui Guan Pipe (Gimmick Pirate) + Games: Super Mario Bros. 2 Pirate (YUNG-08) - iNES: + NES 2.0: mapper 368 - In MESS: Supported, but there are glitches (PPU or IRQ?) + In MAME: Supported. -------------------------------------------------*/ -// 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) +TIMER_CALLBACK_MEMBER(nes_yung08_device::irq_timer_tick) { - if (id == TIMER_IRQ) + if (BIT(m_irq_latch, 0)) { - m_irq_count++; - m_irq_count &= 0xff; - - if (m_irq_enable && !m_irq_count) - hold_irq_line(); + m_irq_count = (m_irq_count + 1) & 0x0fff; + if (!m_irq_count) + set_irq_line(ASSERT_LINE); } } -void nes_shuiguan_device::write_h(offs_t offset, uint8_t data) +void nes_yung08_device::write_45(offs_t offset, u8 data) { - int bank; - LOG_MMC(("shuiguan write_h, offset: %04x, data: %02x\n", offset, data)); - - switch (offset & 0x7000) + switch (offset & 0x51ff) { - 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); + case 0x4022: + prg8_cd(data & 1 ? 3 : 4 + BIT(data, 1, 2)); break; - case 0x7000: - switch (offset & 0x0c) + case 0x4122: + m_irq_latch = data & 0x35; + if (!BIT(m_irq_latch, 0)) { - 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; + set_irq_line(CLEAR_LINE); + m_irq_count = 0; } break; } } -uint8_t nes_shuiguan_device::read_m(offs_t offset) +void nes_yung08_device::write_ex(offs_t offset, u8 data) { - // always first bank?? - LOG_MMC(("shuiguan read_m, offset: %04x\n", offset)); - return m_prg[offset & 0x1fff]; + LOG("yung08 write_ex, offset: %04x, data: %02x\n", offset, data); + write_45(offset + 0x4020, data); } - -/*------------------------------------------------- - - RT-01 - - Games: Russian test cart - - The PRG EPROM has copy protected areas with - "weak bits", which is tested at some points (info - from Cah4e3). - - iNES: - - In MESS: - - -------------------------------------------------*/ - -uint8_t nes_rt01_device::read_h(offs_t offset) +void nes_yung08_device::write_l(offs_t offset, u8 data) { -// LOG_MMC(("rt01 read_h, offset: %04x\n", offset)); + LOG("yung08 write_l, offset: %04x, data: %02x\n", offset, data); + write_45(offset + 0x4100, data); +} - if ((offset >= 0x4e80) && (offset < 0x4f00)) - return 0xf2 | (machine().rand() & 0x0d); - if ((offset >= 0x7e80) && (offset < 0x7f00)) - return 0xf2 | (machine().rand() & 0x0d); +u8 nes_yung08_device::read_l(offs_t offset) +{ + LOG("yung08 read_l, offset: %04x\n", offset); + offset += 0x100; + if ((offset & 0x11ff) == 0x0122) // 0x4122 + return m_irq_latch | 0x8a; + return get_open_bus(); +} - return hi_access_rom(offset); +u8 nes_yung08_device::read_m(offs_t offset) +{ + LOG("yung08 read_m, offset: %04x\n", offset); + return m_prg[0x02 * 0x2000 + offset]; // fixed to bank #2 } |