summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/nes/bootleg.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/nes/bootleg.cpp')
-rw-r--r--src/devices/bus/nes/bootleg.cpp1695
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
}