diff options
Diffstat (limited to 'src/mess/machine/nes_nxrom.c')
-rw-r--r-- | src/mess/machine/nes_nxrom.c | 494 |
1 files changed, 494 insertions, 0 deletions
diff --git a/src/mess/machine/nes_nxrom.c b/src/mess/machine/nes_nxrom.c new file mode 100644 index 00000000000..55ff5f07a39 --- /dev/null +++ b/src/mess/machine/nes_nxrom.c @@ -0,0 +1,494 @@ +/*********************************************************************************************************** + + + NES/Famicom cartridge emulation for Nintendo xxROM PCBs + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + + + Here we emulate the following PCBs + + * Nintendo NROM [mapper 0] + * Nintendo AxROM [mapper 7] + * Nintendo BxROM [mapper 34] + * Nintendo CNROM [mapper 3 & 185] + * Nintendo CPROM [mapper 13] + * Nintendo GxROM/MxROM [mapper 66] + * Nintendo UxROM [mapper 2] + Crazy Climbers variant [mapper 180] + * Nintendo UN1ROM [mapper 94] + + + ***********************************************************************************************************/ + + +#include "emu.h" +#include "machine/nes_nxrom.h" + +#include "sound/samples.h" + +#ifdef NES_PCB_DEBUG +#define VERBOSE 1 +#else +#define VERBOSE 0 +#endif + +#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0) + + +//------------------------------------------------- +// constructor +//------------------------------------------------- + +const device_type NES_NROM = &device_creator<nes_nrom_device>; +const device_type NES_FCBASIC = &device_creator<nes_fcbasic_device>; +const device_type NES_AXROM = &device_creator<nes_axrom_device>; +const device_type NES_BXROM = &device_creator<nes_bxrom_device>; +const device_type NES_CNROM = &device_creator<nes_cnrom_device>; +const device_type NES_CPROM = &device_creator<nes_cprom_device>; +const device_type NES_GXROM = &device_creator<nes_gxrom_device>; +const device_type NES_UXROM = &device_creator<nes_uxrom_device>; +const device_type NES_UXROM_CC = &device_creator<nes_uxrom_cc_device>; +const device_type NES_UN1ROM = &device_creator<nes_un1rom_device>; + + +nes_nrom_device::nes_nrom_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source), + device_nes_cart_interface( mconfig, *this ) +{ +} + +nes_nrom_device::nes_nrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, NES_NROM, "NES Cart NROM PCB", tag, owner, clock, "nes_nrom", __FILE__), + device_nes_cart_interface( mconfig, *this ) +{ +} + +nes_fcbasic_device::nes_fcbasic_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_FCBASIC, "NES Cart Famicom BASIC PCB", tag, owner, clock, "nes_fcbasic", __FILE__) +{ +} + +nes_axrom_device::nes_axrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_AXROM, "NES Cart AxROM PCB", tag, owner, clock, "nes_axrom", __FILE__) +{ +} + +nes_bxrom_device::nes_bxrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_BXROM, "NES Cart BxROM PCB", tag, owner, clock, "nes_bxrom", __FILE__) +{ +} + +nes_cnrom_device::nes_cnrom_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) + : nes_nrom_device(mconfig, type, name, tag, owner, clock, shortname, source) +{ +} + +nes_cnrom_device::nes_cnrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_CNROM, "NES Cart CNROM PCB", tag, owner, clock, "nes_cnrom", __FILE__) +{ +} + +nes_cprom_device::nes_cprom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_CPROM, "NES Cart CPROM PCB", tag, owner, clock, "nes_cprom", __FILE__) +{ +} + +nes_gxrom_device::nes_gxrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_GXROM, "NES Cart GxROM PCB", tag, owner, clock, "nes_gxrom", __FILE__) +{ +} + +nes_uxrom_device::nes_uxrom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_UXROM, "NES Cart UxROM PCB", tag, owner, clock, "nes_uxrom", __FILE__) +{ +} + +nes_uxrom_cc_device::nes_uxrom_cc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_UXROM_CC, "NES Cart UNROM M5 PCB (Crazy Climber)", tag, owner, clock, "nes_uxrom_cc", __FILE__) +{ +} + +nes_un1rom_device::nes_un1rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_UN1ROM, "NES Cart UN1ROM PCB", tag, owner, clock, "nes_un1rom", __FILE__) +{ +} + + +void nes_nrom_device::common_start() +{ + // PRG + save_item(NAME(m_prg_bank)); + + // CHR + save_item(NAME(m_chr_source)); + save_item(NAME(m_chr_src)); + save_item(NAME(m_chr_orig)); + + // NT + save_item(NAME(m_mirroring)); + save_item(NAME(m_nt_src)); + save_item(NAME(m_nt_orig)); + save_item(NAME(m_nt_writable)); +} + +void nes_nrom_device::pcb_reset() +{ + m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; + prg32(0); + chr8(0, m_chr_source); +} + +void nes_axrom_device::device_start() +{ + common_start(); +} + +void nes_axrom_device::pcb_reset() +{ + m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; + prg32(0); + chr8(0, m_chr_source); + + set_nt_mirroring(PPU_MIRROR_LOW); +} + +void nes_bxrom_device::device_start() +{ + common_start(); +} + +void nes_bxrom_device::pcb_reset() +{ + m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; + prg32(0); + chr8(0, m_chr_source); +} + +void nes_cnrom_device::device_start() +{ + common_start(); + save_item(NAME(m_chr_open_bus)); +} + +void nes_cnrom_device::pcb_reset() +{ + m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; + prg32(0); + chr8(0, m_chr_source); + + m_chr_open_bus = 0; +} + +void nes_cprom_device::device_start() +{ + common_start(); +} + +void nes_cprom_device::pcb_reset() +{ + m_chr_source = CHRRAM; + prg32(0); + chr4_0(0, m_chr_source); + chr4_4(0, m_chr_source); +} + +void nes_gxrom_device::device_start() +{ + common_start(); +} + +void nes_gxrom_device::pcb_reset() +{ + m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; + prg32(0); + chr8(0, m_chr_source); +} + +void nes_uxrom_device::device_start() +{ + common_start(); +} + +void nes_uxrom_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); +} + +void nes_uxrom_cc_device::device_start() +{ + common_start(); +} + +void nes_uxrom_cc_device::pcb_reset() +{ + m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; + prg32(0); + chr8(0, m_chr_source); +} + +void nes_un1rom_device::device_start() +{ + common_start(); +} + +void nes_un1rom_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); +} + + +/*------------------------------------------------- + mapper specific handlers + -------------------------------------------------*/ + +/*------------------------------------------------- + + NROM board emulation + + Games: Mario Bros., Super Mario Bros., Tennis and most of + the first generation games + + iNES: mapper 0 + + In MESS: Supported, no need of specific handlers or IRQ + + -------------------------------------------------*/ + + +/*------------------------------------------------- + + AxROM board emulation + + Games: Arch Rivals, Battletoads, Cabal, Commando, Solstice + + writes to 0x8000-0xffff change PRG banks + sets mirroring + + AMROM has bus conflict + AOROM has generally bus conflict too, but some later pcbs + added some discrete component to disable ROM and avoid + conflicts. No AOROM games is known to glitch due to lack of + bus conflict, so it seems safe to emulate AOROM + without bus conflict. + + iNES: mapper 7 + + In MESS: Supported + + -------------------------------------------------*/ + +WRITE8_MEMBER(nes_axrom_device::write_h) +{ + LOG_MMC(("axrom write_h, offset: %04x, data: %02x\n", offset, data)); + + // this pcb is subject to bus conflict + data = account_bus_conflict(offset, data); + + set_nt_mirroring(BIT(data, 4) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW); + prg32(data); +} + +/*------------------------------------------------- + + BxROM board emulation + + writes to 0x8000-0xffff change PRG banks + + iNES: mapper 34 + + -------------------------------------------------*/ + +WRITE8_MEMBER(nes_bxrom_device::write_h) +{ + /* This portion of the mapper is nearly identical to Mapper 7, except no one-screen mirroring */ + /* Deadly Towers is really a BxROM game - the demo screens look wrong using mapper 7. */ + LOG_MMC(("bxrom write_h, offset: %04x, data: %02x\n", offset, data)); + + // this pcb is subject to bus conflict, but the same is not true for some pirate variants + data = account_bus_conflict(offset, data); + + prg32(data); +} + +/*------------------------------------------------- + + CNROM board emulation + + Games: B-Wings, Mighty Bomb Jack, Seicross, Spy vs. Spy, + Adventure Island, Flipull, Friday 13th, GeGeGe no + Kitarou, Ghostbusters, Gradius, Hokuto no Ken, Milon's + Secret Castle + + writes to 0x8000-0xffff change CHR 8K banks + + missing BC? + + iNES: mappers 3 & 185 (the latter for games using Pins as + protection) + + Notice that BANDAI_PT554 board (Aerobics Studio) uses very + similar hardware but with an additional sound chip which + gets writes to 0x6000 (currently unemulated in MESS) + + In MESS: Supported + + -------------------------------------------------*/ + +WRITE8_MEMBER(nes_cnrom_device::write_h) +{ + LOG_MMC(("cxrom write_h, offset: %04x, data: %02x\n", offset, data)); + + // this pcb is subject to bus conflict, but the same is not true for some pirate variants + data = account_bus_conflict(offset, data); + + if (m_ce_mask) + { + chr8(data & ~m_ce_mask, CHRROM); + + if ((data & m_ce_mask) == m_ce_state) + m_chr_open_bus = 0; + else + m_chr_open_bus = 1; + } + else + chr8(data, CHRROM); +} + +READ8_MEMBER(nes_cnrom_device::chr_r) +{ + int bank = offset >> 10; + + // a few CNROM boards contained copy protection schemes through + // suitably configured diodes, so that subsequent CHR reads can + // give actual VROM content or open bus values. + // For most boards, chr_open_bus remains always zero. + if (m_chr_open_bus) + return 0xff; + + return m_chr_access[bank][offset & 0x3ff]; +} + + +/*------------------------------------------------- + + CPROM board emulation + + Games: Videomation + + writes to 0x8000-0xffff change CHR 4K lower banks + + iNES: mapper 13 + + In MESS: Supported + + -------------------------------------------------*/ + +WRITE8_MEMBER(nes_cprom_device::write_h) +{ + LOG_MMC(("cprom write_h, offset: %04x, data: %02x\n", offset, data)); + + // this pcb is subject to bus conflict + data = account_bus_conflict(offset, data); + + chr4_4(data, CHRRAM); +} + + +/*------------------------------------------------- + + GxROM/MxROM board emulation + + writes to 0x8000-0xffff change PRG and CHR banks + + iNES: mapper 66 + + -------------------------------------------------*/ + +WRITE8_MEMBER(nes_gxrom_device::write_h) +{ + LOG_MMC(("gxrom write_h, offset %04x, data: %02x\n", offset, data)); + + // this pcb is subject to bus conflict + data = account_bus_conflict(offset, data); + + prg32((data & 0xf0) >> 4); + chr8(data & 0x0f, CHRROM); +} + +/*------------------------------------------------- + + UxROM board emulation + + Games: Castlevania, Dragon Quest II, Duck Tales, MegaMan, + Metal Gear + + writes to 0x8000-0xffff change PRG 16K lower banks + + iNES: mapper 2 + + In MESS: Supported. + + -------------------------------------------------*/ + +WRITE8_MEMBER(nes_uxrom_device::write_h) +{ + LOG_MMC(("uxrom write_h, offset: %04x, data: %02x\n", offset, data)); + + // this pcb is subject to bus conflict + data = account_bus_conflict(offset, data); + + prg16_89ab(data); +} + +/*------------------------------------------------- + + Nihon Bussan UNROM M5 + + Games: Crazy Climber Jpn + + Very simple mapper: prg16_89ab is always set to bank 0, + while prg16_cdef is set by writes to 0x8000-0xffff. The game + uses a custom controller. + + iNES: mapper 180 + + In MESS: Supported. + + -------------------------------------------------*/ + +WRITE8_MEMBER(nes_uxrom_cc_device::write_h) +{ + LOG_MMC(("uxrom_cc write_h, offset: %04x, data: %02x\n", offset, data)); + + prg16_cdef(data); +} + +/*------------------------------------------------- + + UN1ROM board emulation + + Games: Senjou no Okami + + writes to 0x8000-0xffff change PRG 16K lower banks + + iNES: mapper 94 + + In MESS: Supported. + + -------------------------------------------------*/ + +WRITE8_MEMBER(nes_un1rom_device::write_h) +{ + LOG_MMC(("un1rom write_h, offset: %04x, data: %02x\n", offset, data)); + + // this pcb is subject to bus conflict + data = account_bus_conflict(offset, data); + + prg16_89ab(data >> 2); +} |