diff --git a/src/mame/nintendo/vsnes.cpp b/src/mame/nintendo/vsnes.cpp index 416ade4c867..26bba906bd1 100644 --- a/src/mame/nintendo/vsnes.cpp +++ b/src/mame/nintendo/vsnes.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Pierpaolo Prazzoli +// copyright-holders:Pierpaolo Prazzoli, Brad Oliver, Fabio Priuli /*************************************************************************** Nintendo VS UniSystem and DualSystem - (c) 1984 Nintendo of America @@ -96,7 +96,7 @@ Needed roms: - Wild Gunman (1984, light gun game) TO DO: - - Merge mapper implementations in machine/vsnes.c with playch10 and MESS NES + - Merge mapper implementations with playch10, NES, etc - Check others bits in coin counter - Check other values in bnglngby irq - Top Gun: cpu #0 (PC=00008016): unmapped memory byte read from 00007FFF ??? @@ -139,21 +139,219 @@ Changes: ***************************************************************************/ #include "emu.h" -#include "vsnes.h" +#include "bus/nes_ctrl/zapper_sensor.h" #include "cpu/m6502/n2a03.h" #include "cpu/z80/z80.h" +#include "machine/nvram.h" +#include "sound/sn76496.h" +#include "video/ppu2c0x.h" + #include "screen.h" #include "speaker.h" #include "layout/generic.h" -/******************************************************************************/ +namespace { + +class vs_base_state : public driver_device +{ +protected: + vs_base_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_subcpu(*this, "sub") + , m_ppu1(*this, "ppu1") + , m_ppu2(*this, "ppu2") + , m_sensor(*this, "sensor") + , m_nvram(*this, "nvram") + , m_gfx1_rom(*this, "gfx1") + , m_prg_banks(*this, "prg%u", 0U) + , m_prg_view(*this, "prg_view") + , m_chr_banks(*this, "chr%u", 0U) + , m_chr_view(*this, "chr_view") + , m_in(*this, "IN%u", 0U) + , m_coins(*this, "COINS%u", 1U) + , m_dsw(*this, "DSW%u", 0U) + , m_gunx(*this, "GUNX") + , m_guny(*this, "GUNY") + { + } + + virtual void machine_reset() override; + + template void sprite_dma_w(address_space &space, u8 data); + template void vsnes_coin_counter_w(offs_t offset, u8 data); + template u8 vsnes_coin_counter_r(offs_t offset); + template void vsnes_in0_w(u8 data); + template u8 vsnes_in0_r(); + template u8 vsnes_in1_r(); + + void vsnes_cpu1_map(address_map &map); + void vsnes_cpu2_map(address_map &map); + void vsnes_ppu1_map(address_map &map); + void vsnes_ppu2_map(address_map &map); + + void init_prg_banking(); + void prg32(int bank); + void prg16(int slot, int bank); + void prg8(int slot, int bank); + + enum { MAIN = 0, SUB = 1 }; + + required_device m_maincpu; + optional_device m_subcpu; + required_device m_ppu1; + optional_device m_ppu2; + + optional_device m_sensor; + optional_device m_nvram; + + optional_memory_region m_gfx1_rom; + + memory_bank_array_creator<4> m_prg_banks; + memory_view m_prg_view; + int m_prg_chunks = 0; + + memory_bank_array_creator<8> m_chr_banks; + memory_view m_chr_view; + int m_chr_chunks = 0; + + bool m_has_gun = false; + +private: + optional_ioport_array<4> m_in; + optional_ioport_array<2> m_coins; + optional_ioport_array<2> m_dsw; + optional_ioport m_gunx; + optional_ioport m_guny; + + int m_coin = 0; + int m_input_latch[4]{}; + int m_input_strobe[2]{}; +}; + +class vs_uni_state : public vs_base_state +{ +public: + vs_uni_state(const machine_config &mconfig, device_type type, const char *tag) + : vs_base_state(mconfig, type, tag) + { + } + + void vsnes(machine_config &config); + void jajamaru(machine_config &config); + void mightybj(machine_config &config); + void topgun(machine_config &config); + void vsgshoe(machine_config &config); + + void init_vskonami(); + void init_vsvram(); + void init_bnglngby(); + void init_drmario(); + void init_vs108(); + void init_vsfdf(); + void init_tkoboxng(); + void init_vsgun(); + void init_supxevs(); + void init_vsgshoe(); + void init_vsnormal(); + void init_platoon(); + void init_rbibb(); + +protected: + virtual void machine_start() override; + +private: + void vsnormal_vrom_banking(u8 data); + void vskonami_rom_banking(offs_t offset, u8 data); + void vsgshoe_gun_in0_w(u8 data); + void drmario_rom_banking(offs_t offset, u8 data); + void vsvram_rom_banking(u8 data); + void vs108_rom_banking(offs_t offset, u8 data); + u8 rbibb_prot_r(offs_t offset); + u8 supxevs_prot_1_r(); + u8 supxevs_prot_2_r(); + u8 supxevs_prot_3_r(); + u8 supxevs_prot_4_r(); + u8 tkoboxng_prot_r(offs_t offset); + void sunsoft3_rom_banking(offs_t offset, u8 data); + void set_bnglngby_irq_w(u8 data); + u8 set_bnglngby_irq_r(); + + void v_set_videorom_bank(int start, int count, int vrom_start_bank); + + int m_mmc1_shiftreg = 0; + int m_mmc1_shiftcount = 0; + int m_mmc1_prg16k = 0; + int m_mmc1_switchlow = 0; + int m_mmc1_chr4k = 0; + int m_108_reg = 0; + int m_prot_index = 0; + int m_ret = 0; +}; + +class vs_dual_state : public vs_base_state +{ +public: + vs_dual_state(const machine_config &mconfig, device_type type, const char *tag) + : vs_base_state(mconfig, type, tag) + { + } + + void vsdual(machine_config &config); + void vsdual_pi(machine_config &config); + void init_vsdual(); + +protected: + virtual void machine_start() override; + +private: + template void vsdual_vrom_banking(u8 data); +}; + +class vs_smbbl_state : public vs_base_state +{ +public: + vs_smbbl_state(const machine_config &mconfig, device_type type, const char *tag) + : vs_base_state(mconfig, type, tag) + , m_sn1(*this, "sn1") + , m_sn2(*this, "sn2") + { + } + + void vs_smbbl(machine_config &config); + void init_smbbl(); + +protected: + virtual void machine_start() override; + +private: + void bootleg_sound_write(offs_t offset, u8 data); + u8 vsnes_bootleg_z80_data_r(); + u8 vsnes_bootleg_z80_address_r(offs_t offset); + void vsnes_bootleg_scanline(int scanline, bool vblank, bool blanked); + u8 vsnes_bootleg_ppudata(); + void vsnes_bootleg_z80_map(address_map &map); + void vsnes_cpu1_bootleg_map(address_map &map); + void vsnes_ppu_bootleg_map(address_map &map); + void vssmbbl_sn_w(offs_t offset, u8 data); + + required_device m_sn1; + required_device m_sn2; + + u8 m_bootleg_sound_offset = 0; + u8 m_bootleg_sound_data = 0; + int m_bootleg_latched_scanline = 0; +}; + + +//****************************************************************************** template -void vsnes_state::sprite_dma_w(address_space &space, u8 data) +void vs_base_state::sprite_dma_w(address_space &space, u8 data) { if (Side == MAIN) m_ppu1->spriteram_dma(space, data & 0x07); @@ -162,7 +360,7 @@ void vsnes_state::sprite_dma_w(address_space &space, u8 data) } template -void vsnes_state::vsnes_coin_counter_w(offs_t offset, u8 data) +void vs_base_state::vsnes_coin_counter_w(offs_t offset, u8 data) { machine().bookkeeping().coin_counter_w(Side, data & 0x01); m_coin = data; @@ -173,7 +371,7 @@ void vsnes_state::vsnes_coin_counter_w(offs_t offset, u8 data) } template -u8 vsnes_state::vsnes_coin_counter_r(offs_t offset) +u8 vs_base_state::vsnes_coin_counter_r(offs_t offset) { // reads effectively write MSB of address (via open bus) to coin counter machine().bookkeeping().coin_counter_w(Side, BIT(offset, 8)); @@ -183,7 +381,7 @@ u8 vsnes_state::vsnes_coin_counter_r(offs_t offset) } template -void vsnes_state::vsnes_in0_w(u8 data) +void vs_base_state::vsnes_in0_w(u8 data) { // Toggling bit 0 high then low resets both controllers if (m_input_strobe[Side] & ~data & 1) @@ -202,7 +400,7 @@ void vsnes_state::vsnes_in0_w(u8 data) } template -u8 vsnes_state::vsnes_in0_r() +u8 vs_base_state::vsnes_in0_r() { int p1 = 2 * Side; @@ -223,7 +421,7 @@ u8 vsnes_state::vsnes_in0_r() } template -u8 vsnes_state::vsnes_in1_r() +u8 vs_base_state::vsnes_in1_r() { int p2 = 2 * Side + 1; @@ -238,17 +436,567 @@ u8 vsnes_state::vsnes_in1_r() return ret; } -/******************************************************************************/ +/************************************* + * + * Init machine + * + *************************************/ + +void vs_base_state::machine_reset() +{ + m_input_latch[0] = m_input_latch[1] = 0; + m_input_latch[2] = m_input_latch[3] = 0; + m_input_strobe[0] = m_input_strobe[1] = 0; +} + +/************************************* + * + * Machine start functions + * + *************************************/ + +void vs_base_state::init_prg_banking() +{ + u8 *base = memregion("prg")->base(); + m_prg_chunks = memregion("prg")->bytes() / 0x2000; + + for (int i = 0; i < 4; i++) + { + m_prg_banks[i]->configure_entries(0, m_prg_chunks, base, 0x2000); + m_prg_banks[i]->set_entry(m_prg_chunks - 4 + i); + } + + m_prg_view.select(0); +} + +// safe banking helpers (only work when PRG size is a power of 2, i.e. not Gumshoe) + +void vs_base_state::prg32(int bank) +{ + bank = (bank << 2) & (m_prg_chunks - 1); + + for (int i = 0; i < 4; i++) + m_prg_banks[i]->set_entry(bank + i); +} + +void vs_base_state::prg16(int slot, int bank) +{ + bank = (bank << 1) & (m_prg_chunks - 1); + slot = (slot & 1) << 1; + + for (int i = 0; i < 2; i++) + m_prg_banks[slot + i]->set_entry(bank + i); +} + +void vs_base_state::prg8(int slot, int bank) +{ + m_prg_banks[slot & 0x03]->set_entry(bank & (m_prg_chunks - 1)); +} + +void vs_uni_state::v_set_videorom_bank(int start, int count, int vrom_start_bank) +{ + assert(start + count <= 8); + + vrom_start_bank &= m_chr_chunks - 1; + assert(vrom_start_bank + count <= m_chr_chunks); + + // count determines the size of the area mapped + for (int i = 0; i < count; i++) + m_chr_banks[i + start]->set_entry(vrom_start_bank + i); +} + +void vs_uni_state::machine_start() +{ + // establish chr banks + // DRIVER_INIT is called first - means we can handle this different for VRAM games! + if (m_gfx1_rom != nullptr) + { + u8 *base = m_gfx1_rom->base(); + m_chr_chunks = m_gfx1_rom->bytes() / 0x400; + + for (int i = 0; i < 8; i++) + { + m_ppu1->space(AS_PROGRAM).install_read_bank(0x0400 * i, 0x0400 * i + 0x03ff, m_chr_banks[i]); + m_chr_banks[i]->configure_entries(0, m_chr_chunks, base, 0x400); + } + v_set_videorom_bank(0, 8, 0); + } + else + m_chr_view.select(0); +} + +void vs_dual_state::machine_start() +{ + for (int i = 0; i < 2; i++) + { + const char *region = i ? "gfx2" : "gfx1"; + u8 *base = memregion(region)->base(); + int entries = memregion(region)->bytes() / 0x2000; + m_chr_banks[i]->configure_entries(0, entries, base, 0x2000); + m_chr_banks[i]->set_entry(0); + } +} + +void vs_smbbl_state::machine_start() +{ + u8 *base = m_gfx1_rom->base(); + int entries = m_gfx1_rom->bytes() / 0x2000; + m_chr_banks[0]->configure_entries(0, entries, base, 0x2000); + m_chr_banks[0]->set_entry(0); +} + +/********************************************************************************** + * + * Game and Board-specific initialization + * + **********************************************************************************/ + +//********************************************************************************** +// Most games: VROM Banking in controller 0 write + +void vs_uni_state::vsnormal_vrom_banking(u8 data) +{ + // switch vrom + v_set_videorom_bank(0, 8, (data & 4) ? 8 : 0); + + // bit 1 ( data & 2 ) enables writes to extra ram, we ignore it + + // move along + vsnes_in0_w
(data); +} + +void vs_uni_state::init_vsnormal() +{ + // vrom switching is enabled with bit 2 of $4016 + m_maincpu->space(AS_PROGRAM).install_write_handler(0x4016, 0x4016, write8smo_delegate(*this, FUNC(vs_uni_state::vsnormal_vrom_banking))); +} + +//********************************************************************************** +// Gun games: VROM Banking in controller 0 write + +void vs_uni_state::init_vsgun() +{ + init_vsnormal(); + m_has_gun = true; +} + +//********************************************************************************** +// Konami VRC1 games: ROM banking at $8000-$ffff + +void vs_uni_state::vskonami_rom_banking(offs_t offset, u8 data) +{ + int reg = BIT(offset, 12, 3); + + switch (reg) + { + case 0: // prg bank 0 + case 2: // prg bank 1 + case 4: // prg bank 2 + prg8(reg >> 1, data); + break; + + case 6: // vrom bank 0 + v_set_videorom_bank(0, 4, data * 4); + break; + + case 7: // vrom bank 1 + v_set_videorom_bank(4, 4, data * 4); + break; + } +} + +void vs_uni_state::init_vskonami() +{ + // point program banks to last 32K + init_prg_banking(); + + // banking is done with writes to the $8000-$ffff area + m_maincpu->space(AS_PROGRAM).install_write_handler(0x8000, 0xffff, write8sm_delegate(*this, FUNC(vs_uni_state::vskonami_rom_banking))); +} + +//********************************************************************************** +// Vs. Gumshoe + +void vs_uni_state::vsgshoe_gun_in0_w(u8 data) +{ + // Gumshoe uniquely has a bankable 16K EPROM in addition to the normal unbanked 8K slots + m_prg_banks[0]->set_entry(BIT(data, 2)); + + // otherwise do normal CHR banking and IO write + vsnormal_vrom_banking(data); +} + +void vs_uni_state::init_vsgshoe() +{ + // point program banks to last 32K + init_prg_banking(); + + // vrom switching is enabled with bit 2 of $4016 + m_maincpu->space(AS_PROGRAM).install_write_handler(0x4016, 0x4016, write8smo_delegate(*this, FUNC(vs_uni_state::vsgshoe_gun_in0_w))); + + m_has_gun = true; +} + +//********************************************************************************** +// MMC1 (Dr Mario): ROM banking at $8000-$ffff + +void vs_uni_state::drmario_rom_banking(offs_t offset, u8 data) +{ + // reset mapper + if (data & 0x80) + { + m_mmc1_shiftcount = 0; + m_mmc1_prg16k = 1; + m_mmc1_switchlow = 1; + m_mmc1_chr4k = 0; + + return; + } + + // update shift register + m_mmc1_shiftreg = (m_mmc1_shiftreg >> 1) | (data & 1) << 4; + m_mmc1_shiftcount = (m_mmc1_shiftcount + 1) % 5; + + // are we done shifting? + if (!m_mmc1_shiftcount) + { + // apply data to registers + switch (BIT(offset, 13, 2)) + { + case 0: // mirroring and options + m_mmc1_chr4k = m_mmc1_shiftreg & 0x10; + m_mmc1_prg16k = m_mmc1_shiftreg & 0x08; + m_mmc1_switchlow = m_mmc1_shiftreg & 0x04; + // 0x03: mirroring bits unused on VS + break; + + case 1: // video rom banking - bank 0 - 4k or 8k + if (m_mmc1_chr4k) + v_set_videorom_bank(0, 4, m_mmc1_shiftreg * 4); + else + v_set_videorom_bank(0, 8, (m_mmc1_shiftreg & ~1) * 4); + break; + + case 2: // video rom banking - bank 1 - 4k only + if (m_mmc1_chr4k) + v_set_videorom_bank(4, 4, m_mmc1_shiftreg * 4); + break; + + case 3: // program banking + if (m_mmc1_prg16k) + prg16(!m_mmc1_switchlow, m_mmc1_shiftreg); + else + prg32(m_mmc1_shiftreg >> 1); + break; + } + } +} + +void vs_uni_state::init_drmario() +{ + // point program banks to last 32K + init_prg_banking(); + + // MMC1 mapper at $8000-$ffff + m_maincpu->space(AS_PROGRAM).install_write_handler(0x8000, 0xffff, write8sm_delegate(*this, FUNC(vs_uni_state::drmario_rom_banking))); + + m_mmc1_shiftreg = 0; + m_mmc1_shiftcount = 0; +} + +//********************************************************************************** +// (UNROM) Games with VRAM instead of graphics ROMs: ROM banking at $8000-$ffff + +void vs_uni_state::vsvram_rom_banking(u8 data) +{ + prg16(0, data); +} + +void vs_uni_state::init_vsvram() +{ + // point program banks to last 32K + init_prg_banking(); + + // banking is done with writes to the $8000-$ffff area + m_maincpu->space(AS_PROGRAM).install_write_handler(0x8000, 0xffff, write8smo_delegate(*this, FUNC(vs_uni_state::vsvram_rom_banking))); +} + +//********************************************************************************** +// (Namco) 108 (MMC3 predecessor) games + +void vs_uni_state::vs108_rom_banking(offs_t offset, u8 data) +{ + switch (offset & 0x6001) + { + case 0x0000: // $8000 + m_108_reg = data & 0x07; + break; + + case 0x0001: // $8001 + switch (m_108_reg) + { + case 0: case 1: + v_set_videorom_bank(m_108_reg * 2, 2, data); + break; + case 2: case 3: case 4: case 5: + v_set_videorom_bank(m_108_reg + 2, 1, data); + break; + case 6: case 7: + prg8(m_108_reg - 6, data); + break; + } + break; + + default: + logerror("vs108_rom_banking uncaught: %04x value: %02x\n", offset + 0x8000, data); + break; + } +} + +// Common init for (Namco) 108 games + +void vs_uni_state::init_vs108() +{ + // point program banks to last 32K + init_prg_banking(); + + m_108_reg = 0; + + // 108 chip at $8000-$9fff + m_maincpu->space(AS_PROGRAM).install_write_handler(0x8000, 0xffff, write8sm_delegate(*this, FUNC(vs_uni_state::vs108_rom_banking))); +} + +// Vs. RBI Baseball +// rbibb uses a protection chip labeled '127' +// Tests indicate that '127' uses a LFSR with taps: 23, 18, 0 +// It is still unknown how bits are then shuffled for readback at 0x5601/0x5e01 +u8 vs_uni_state::rbibb_prot_r(offs_t offset) +{ + static constexpr u8 prot_data[32] = { + 0xff, 0xfd, 0xf5, 0xf4, 0xb4, 0xb4, 0xa6, 0x2e, + 0x2f, 0x6f, 0x6f, 0x7d, 0xd5, 0xd4, 0x94, 0x94, + 0x86, 0x2e, 0x2f, 0x6f, 0x6b, 0x79, 0xd1, 0xd0, + 0x92, 0x92, 0x8d, 0x65, 0x64, 0x34, 0xb0, 0xa2 + }; + + if (offset == 0) + { + m_prot_index = 0; + return 0; + } + + return prot_data[m_prot_index++ & 0x1f]; +} + +void vs_uni_state::init_rbibb() +{ + init_vs108(); + + // RBI Baseball protection, address fully decoded except A11 + m_maincpu->space(AS_PROGRAM).install_read_handler(0x5600, 0x5601, read8sm_delegate(*this, FUNC(vs_uni_state::rbibb_prot_r))); + m_maincpu->space(AS_PROGRAM).install_read_handler(0x5e00, 0x5e01, read8sm_delegate(*this, FUNC(vs_uni_state::rbibb_prot_r))); +} + +// Vs. Super Xevious + +u8 vs_uni_state::supxevs_prot_1_r() +{ + m_prot_index ^= 1; + return 0x05; +} + +u8 vs_uni_state::supxevs_prot_2_r() +{ + return m_prot_index ? 0x01 : 0x00; +} + +u8 vs_uni_state::supxevs_prot_3_r() +{ + return m_prot_index ? 0x89 : 0xd1; +} + +u8 vs_uni_state::supxevs_prot_4_r() +{ + return m_prot_index ? 0x37 : 0x3e; +} + +void vs_uni_state::init_supxevs() +{ + init_vs108(); + + // Vs. Super Xevious Protection + m_maincpu->space(AS_PROGRAM).install_read_handler(0x54ff, 0x54ff, read8smo_delegate(*this, FUNC(vs_uni_state::supxevs_prot_1_r))); + m_maincpu->space(AS_PROGRAM).install_read_handler(0x5678, 0x5678, read8smo_delegate(*this, FUNC(vs_uni_state::supxevs_prot_2_r))); + m_maincpu->space(AS_PROGRAM).install_read_handler(0x578f, 0x578f, read8smo_delegate(*this, FUNC(vs_uni_state::supxevs_prot_3_r))); + m_maincpu->space(AS_PROGRAM).install_read_handler(0x5567, 0x5567, read8smo_delegate(*this, FUNC(vs_uni_state::supxevs_prot_4_r))); + + m_prot_index = 0; +} + +// Vs. TKO Boxing +// tkoboxng uses a protection chip labeled '128' +u8 vs_uni_state::tkoboxng_prot_r(offs_t offset) +{ + static constexpr u8 prot_data[32] = { + 0xff, 0xbf, 0xb7, 0x97, 0x97, 0x17, 0x57, 0x4f, + 0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90, 0x94, 0x14, + 0x56, 0x4e, 0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90, + 0xd4, 0x5c, 0x3e, 0x26, 0x87, 0x83, 0x13, 0x00 + }; + + if (offset == 0) + { + m_prot_index = 0; + return 0; + } + + return prot_data[m_prot_index++ & 0x1f]; +} + +void vs_uni_state::init_tkoboxng() +{ + init_vs108(); + + // security device at $5e00-$5e01 + m_maincpu->space(AS_PROGRAM).install_read_handler(0x5e00, 0x5e01, read8sm_delegate(*this, FUNC(vs_uni_state::tkoboxng_prot_r))); +} + +// Vs. Freedom Force + +void vs_uni_state::init_vsfdf() +{ + init_vs108(); + m_has_gun = true; +} + +//********************************************************************************** +// Sunsoft-3 (Platoon) rom banking + +void vs_uni_state::sunsoft3_rom_banking(offs_t offset, u8 data) +{ + switch (offset & 0x7800) + { + case 0x0800: + case 0x1800: + case 0x2800: + case 0x3800: + v_set_videorom_bank((offset >> 11) & 0x06, 2, data * 2); + break; + + case 0x7800: + prg16(0, data); + break; + } + +} + +void vs_uni_state::init_platoon() +{ + // point program banks to last 32K + init_prg_banking(); + + m_maincpu->space(AS_PROGRAM).install_write_handler(0x8000, 0xffff, write8sm_delegate(*this, FUNC(vs_uni_state::sunsoft3_rom_banking))); +} + +//********************************************************************************** +// Vs. Raid on Bungeling Bay (Japan) + +// FIXME: this is a bad hack! The unused 8K ROM in the driver supposedly runs on the main CPU (protection?) +// and does some sort of handshake (with IRQs) with the game running on the sub CPU. +void vs_uni_state::set_bnglngby_irq_w(u8 data) +{ + m_ret = data; + m_maincpu->set_input_line(0, (data & 2) ? ASSERT_LINE : CLEAR_LINE); + // other values ??? + // 0, 4, 84 +} + +u8 vs_uni_state::set_bnglngby_irq_r() +{ + return m_ret; +} + +void vs_uni_state::init_bnglngby() +{ + m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x0231, 0x0231, read8smo_delegate(*this, FUNC(vs_uni_state::set_bnglngby_irq_r)), write8smo_delegate(*this, FUNC(vs_uni_state::set_bnglngby_irq_w))); + + m_ret = 0; + + // normal banking + init_vsnormal(); +} + +//********************************************************************************** +// VS Dualsystem + +template +void vs_dual_state::vsdual_vrom_banking(u8 data) +{ + // switch vrom + m_chr_banks[Side]->set_entry(BIT(data, 2)); + + // bit 1 ( data & 2 ) triggers irq on the other cpu + auto cpu = (Side == SUB) ? m_maincpu : m_subcpu; + cpu->set_input_line(0, (data & 2) ? CLEAR_LINE : ASSERT_LINE); + + // move along + vsnes_in0_w(data); +} + +void vs_dual_state::init_vsdual() +{ + // vrom switching is enabled with bit 2 of $4016 + m_maincpu->space(AS_PROGRAM).install_write_handler(0x4016, 0x4016, write8smo_delegate(*this, FUNC(vs_dual_state::vsdual_vrom_banking
))); + m_subcpu->space(AS_PROGRAM).install_write_handler(0x4016, 0x4016, write8smo_delegate(*this, FUNC(vs_dual_state::vsdual_vrom_banking))); +} + +//********************************************************************************** +// Vs. Super Mario Bros (Bootleg) + +void vs_smbbl_state::vsnes_bootleg_scanline(int scanline, bool vblank, bool blanked) +{ + // Z80 IRQ is controlled by two factors: + // - bit 6 of current (next) scanline number + // - bit 6 of latched scanline number from Z80 reading $4000 + if (!(m_bootleg_latched_scanline & 0x40)) + { + m_subcpu->set_input_line(INPUT_LINE_IRQ0, ((scanline + 1) & 0x40) ? ASSERT_LINE : CLEAR_LINE); + } +} + +u8 vs_smbbl_state::vsnes_bootleg_ppudata() +{ + // CPU always reads higher CHR ROM banks from $2007, PPU always reads lower ones + m_chr_banks[0]->set_entry(1); + u8 data = m_ppu1->read(0x2007); + m_chr_banks[0]->set_entry(0); + + return data; +} + +void vs_smbbl_state::init_smbbl() +{ + m_bootleg_sound_offset = 0; + m_bootleg_sound_data = 0; + m_bootleg_latched_scanline = 0; + + m_ppu1->set_scanline_callback(*this, FUNC(vs_smbbl_state::vsnes_bootleg_scanline)); + + m_maincpu->space(AS_PROGRAM).install_read_handler(0x2007, 0x2007, read8smo_delegate(*this, FUNC(vs_smbbl_state::vsnes_bootleg_ppudata))); +} -void vsnes_state::vsnes_cpu1_map(address_map &map) +//****************************************************************************** + + +void vs_base_state::vsnes_cpu1_map(address_map &map) { map(0x0000, 0x07ff).mirror(0x1800).ram(); map(0x2000, 0x3fff).rw(m_ppu1, FUNC(ppu2c0x_device::read), FUNC(ppu2c0x_device::write)); - map(0x4014, 0x4014).w(FUNC(vsnes_state::sprite_dma_w
)); - map(0x4016, 0x4016).rw(FUNC(vsnes_state::vsnes_in0_r
), FUNC(vsnes_state::vsnes_in0_w
)); - map(0x4017, 0x4017).r(FUNC(vsnes_state::vsnes_in1_r
)); // IN1 - input port 2 / PSG second control register - map(0x4020, 0x5fff).rw(FUNC(vsnes_state::vsnes_coin_counter_r
), FUNC(vsnes_state::vsnes_coin_counter_w
)); + map(0x4014, 0x4014).w(FUNC(vs_base_state::sprite_dma_w
)); + map(0x4016, 0x4016).rw(FUNC(vs_base_state::vsnes_in0_r
), FUNC(vs_base_state::vsnes_in0_w
)); + map(0x4017, 0x4017).r(FUNC(vs_base_state::vsnes_in1_r
)); // IN1 - input port 2 / PSG second control register + map(0x4020, 0x5fff).rw(FUNC(vs_base_state::vsnes_coin_counter_r
), FUNC(vs_base_state::vsnes_coin_counter_w
)); map(0x6000, 0x67ff).mirror(0x1800).ram().share("nvram"); // Games that don't bank PRG map(0x8000, 0xffff).rom().region("prg", 0); @@ -260,19 +1008,19 @@ void vsnes_state::vsnes_cpu1_map(address_map &map) m_prg_view[0](0xe000, 0xffff).bankr(m_prg_banks[3]); } -void vsnes_state::vsnes_cpu2_map(address_map &map) +void vs_base_state::vsnes_cpu2_map(address_map &map) { map(0x0000, 0x07ff).mirror(0x1800).ram(); map(0x2000, 0x3fff).rw(m_ppu2, FUNC(ppu2c0x_device::read), FUNC(ppu2c0x_device::write)); - map(0x4014, 0x4014).w(FUNC(vsnes_state::sprite_dma_w)); - map(0x4016, 0x4016).rw(FUNC(vsnes_state::vsnes_in0_r), FUNC(vsnes_state::vsnes_in0_w)); - map(0x4017, 0x4017).r(FUNC(vsnes_state::vsnes_in1_r)); // IN1 - input port 2 / PSG second control register - map(0x4020, 0x5fff).rw(FUNC(vsnes_state::vsnes_coin_counter_r), FUNC(vsnes_state::vsnes_coin_counter_w)); + map(0x4014, 0x4014).w(FUNC(vs_base_state::sprite_dma_w)); + map(0x4016, 0x4016).rw(FUNC(vs_base_state::vsnes_in0_r), FUNC(vs_base_state::vsnes_in0_w)); + map(0x4017, 0x4017).r(FUNC(vs_base_state::vsnes_in1_r)); // IN1 - input port 2 / PSG second control register + map(0x4020, 0x5fff).rw(FUNC(vs_base_state::vsnes_coin_counter_r), FUNC(vs_base_state::vsnes_coin_counter_w)); map(0x6000, 0x67ff).mirror(0x1800).ram().share("nvram"); map(0x8000, 0xffff).rom(); } -void vsnes_state::vsnes_ppu1_map(address_map &map) +void vs_base_state::vsnes_ppu1_map(address_map &map) { map(0x0000, 0x1fff).bankr(m_chr_banks[0]); map(0x0000, 0x1fff).view(m_chr_view); @@ -281,7 +1029,7 @@ void vsnes_state::vsnes_ppu1_map(address_map &map) map(0x3f00, 0x3fff).rw(m_ppu1, FUNC(ppu2c0x_device::palette_read), FUNC(ppu2c0x_device::palette_write)); } -void vsnes_state::vsnes_ppu2_map(address_map &map) +void vs_base_state::vsnes_ppu2_map(address_map &map) { map(0x0000, 0x1fff).bankr(m_chr_banks[1]); map(0x2000, 0x2fff).mirror(0x1000).ram(); @@ -290,7 +1038,7 @@ void vsnes_state::vsnes_ppu2_map(address_map &map) -uint8_t vsnes_state::vsnes_bootleg_z80_address_r(offs_t offset) +u8 vs_smbbl_state::vsnes_bootleg_z80_address_r(offs_t offset) { // NMI routine uses the value read here as the low part of an offset from 0x2000 to store a value read at 0x4000 // before reading 0x6000 and returning @@ -303,7 +1051,7 @@ uint8_t vsnes_state::vsnes_bootleg_z80_address_r(offs_t offset) return 0xf0 | m_bootleg_sound_offset; } -void vsnes_state::bootleg_sound_write(offs_t offset, uint8_t data) +void vs_smbbl_state::bootleg_sound_write(offs_t offset, u8 data) { m_bootleg_sound_offset = offset & 0xf; m_bootleg_sound_data = data; @@ -311,7 +1059,7 @@ void vsnes_state::bootleg_sound_write(offs_t offset, uint8_t data) m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); } -uint8_t vsnes_state::vsnes_bootleg_z80_data_r() +u8 vs_smbbl_state::vsnes_bootleg_z80_data_r() { //printf("Z80 read data %02x\n", m_bootleg_sound_data); m_bootleg_latched_scanline = m_ppu1->get_current_scanline(); @@ -321,7 +1069,7 @@ uint8_t vsnes_state::vsnes_bootleg_z80_data_r() } // A0 = SN #1 enable, A1 = SN #2 enable, A2 = SN write enables (both) on edge -void vsnes_state::vssmbbl_sn_w(offs_t offset, uint8_t data) +void vs_smbbl_state::vssmbbl_sn_w(offs_t offset, u8 data) { // printf("sn_w: ofs %x\n", offset & 7); if (!(offset & 4)) @@ -340,14 +1088,14 @@ void vsnes_state::vssmbbl_sn_w(offs_t offset, uint8_t data) // the bootleg still makes writes to the PSG addresses, it seems the Z80 should interpret them to play the sounds -void vsnes_state::vsnes_cpu1_bootleg_map(address_map &map) +void vs_smbbl_state::vsnes_cpu1_bootleg_map(address_map &map) { map(0x0000, 0x07ff).mirror(0x0800).ram(); map(0x2000, 0x3fff).rw(m_ppu1, FUNC(ppu2c0x_device::read), FUNC(ppu2c0x_device::write)); - map(0x4000, 0x400f).w(FUNC(vsnes_state::bootleg_sound_write)); - map(0x4016, 0x4016).rw(FUNC(vsnes_state::vsnes_in0_r
), FUNC(vsnes_state::vsnes_in0_w
)); - map(0x4017, 0x4017).r(FUNC(vsnes_state::vsnes_in1_r
)); // IN1 - input port 2 / PSG second control register - map(0x4020, 0x4020).w(FUNC(vsnes_state::vsnes_coin_counter_w
)); + map(0x4000, 0x400f).w(FUNC(vs_smbbl_state::bootleg_sound_write)); + map(0x4016, 0x4016).rw(FUNC(vs_smbbl_state::vsnes_in0_r
), FUNC(vs_smbbl_state::vsnes_in0_w
)); + map(0x4017, 0x4017).r(FUNC(vs_smbbl_state::vsnes_in1_r
)); // IN1 - input port 2 / PSG second control register + map(0x4020, 0x4020).w(FUNC(vs_smbbl_state::vsnes_coin_counter_w
)); map(0x6000, 0x67ff).mirror(0x0800).ram(); map(0x8000, 0xffff).rom(); } @@ -365,23 +1113,23 @@ void vsnes_state::vsnes_cpu1_bootleg_map(address_map &map) // x11x xxxx xxxx xxxx = 6502 address (6000) (read) // x11x xxxx xxxx xW21 = SN76489s (6000) (write) -void vsnes_state::vsnes_bootleg_z80_map(address_map &map) +void vs_smbbl_state::vsnes_bootleg_z80_map(address_map &map) { map(0x0000, 0x1fff).rom().region("sub", 0); map(0x2000, 0x27ff).ram(); - map(0x4000, 0x5fff).r(FUNC(vsnes_state::vsnes_bootleg_z80_data_r)); // read in IRQ & NMI - map(0x6000, 0x7fff).rw(FUNC(vsnes_state::vsnes_bootleg_z80_address_r), FUNC(vsnes_state::vssmbbl_sn_w)); + map(0x4000, 0x5fff).r(FUNC(vs_smbbl_state::vsnes_bootleg_z80_data_r)); // read in IRQ & NMI + map(0x6000, 0x7fff).rw(FUNC(vs_smbbl_state::vsnes_bootleg_z80_address_r), FUNC(vs_smbbl_state::vssmbbl_sn_w)); } -void vsnes_state::vsnes_ppu_bootleg_map(address_map &map) +void vs_smbbl_state::vsnes_ppu_bootleg_map(address_map &map) { map(0x0000, 0x1fff).bankr(m_chr_banks[0]); map(0x2000, 0x27ff).mirror(0x1800).ram(); map(0x3f00, 0x3fff).rw(m_ppu1, FUNC(ppu2c0x_device::palette_read), FUNC(ppu2c0x_device::palette_write)); } -/******************************************************************************/ +//****************************************************************************** static INPUT_PORTS_START( vsnes ) @@ -1800,35 +2548,34 @@ static INPUT_PORTS_START( supxevs ) PORT_DIPSETTING( 0xc0, "RP2C04-0004" ) INPUT_PORTS_END -void vsnes_state::vsnes(machine_config &config) -{ - /* basic machine hardware */ - n2a03_device &maincpu(N2A03(config, m_maincpu, NTSC_APU_CLOCK)); - maincpu.set_addrmap(AS_PROGRAM, &vsnes_state::vsnes_cpu1_map); - MCFG_MACHINE_START_OVERRIDE(vsnes_state,vsnes) +void vs_uni_state::vsnes(machine_config &config) +{ + // basic machine hardware + n2a03_device &maincpu(N2A03(config, m_maincpu, NTSC_APU_CLOCK)); + maincpu.set_addrmap(AS_PROGRAM, &vs_uni_state::vsnes_cpu1_map); NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); - /* video hardware */ + // video hardware screen_device &screen1(SCREEN(config, "screen1", SCREEN_TYPE_RASTER)); screen1.set_raw(N2A03_NTSC_XTAL / 4, 341, 0, VISIBLE_SCREEN_WIDTH, ppu2c0x_device::NTSC_SCANLINES_PER_FRAME, 0, VISIBLE_SCREEN_HEIGHT); screen1.set_screen_update("ppu1", FUNC(ppu2c0x_device::screen_update)); PPU_2C04(config, m_ppu1); - m_ppu1->set_addrmap(0, &vsnes_state::vsnes_ppu1_map); + m_ppu1->set_addrmap(0, &vs_uni_state::vsnes_ppu1_map); m_ppu1->set_screen("screen1"); m_ppu1->set_cpu_tag(m_maincpu); m_ppu1->int_callback().set_inputline(m_maincpu, INPUT_LINE_NMI); NES_ZAPPER_SENSOR(config, m_sensor, 0).set_screen_tag("screen1"); - /* sound hardware */ + // sound hardware SPEAKER(config, "mono").front_center(); maincpu.add_route(ALL_OUTPUTS, "mono", 0.50); } -void vsnes_state::jajamaru(machine_config &config) +void vs_uni_state::jajamaru(machine_config &config) { vsnes(config); @@ -1838,7 +2585,7 @@ void vsnes_state::jajamaru(machine_config &config) m_ppu1->int_callback().set_inputline(m_maincpu, INPUT_LINE_NMI); } -void vsnes_state::mightybj(machine_config &config) +void vs_uni_state::mightybj(machine_config &config) { vsnes(config); @@ -1848,7 +2595,7 @@ void vsnes_state::mightybj(machine_config &config) m_ppu1->int_callback().set_inputline(m_maincpu, INPUT_LINE_NMI); } -void vsnes_state::vsgshoe(machine_config &config) +void vs_uni_state::vsgshoe(machine_config &config) { vsnes(config); @@ -1858,27 +2605,25 @@ void vsnes_state::vsgshoe(machine_config &config) m_ppu1->int_callback().set_inputline(m_maincpu, INPUT_LINE_NMI); } -void vsnes_state::topgun(machine_config &config) +void vs_uni_state::topgun(machine_config &config) { vsnes(config); PPU_2C05_04(config.replace(), m_ppu1); - m_ppu1->set_addrmap(0, &vsnes_state::vsnes_ppu1_map); + m_ppu1->set_addrmap(0, &vs_uni_state::vsnes_ppu1_map); m_ppu1->set_screen("screen1"); m_ppu1->set_cpu_tag(m_maincpu); m_ppu1->int_callback().set_inputline(m_maincpu, INPUT_LINE_NMI); } -void vsnes_state::vsdual(machine_config &config) +void vs_dual_state::vsdual(machine_config &config) { - /* basic machine hardware */ + // basic machine hardware n2a03_device &maincpu(N2A03(config, m_maincpu, NTSC_APU_CLOCK)); - maincpu.set_addrmap(AS_PROGRAM, &vsnes_state::vsnes_cpu1_map); + maincpu.set_addrmap(AS_PROGRAM, &vs_dual_state::vsnes_cpu1_map); n2a03_device &subcpu(N2A03(config, m_subcpu, NTSC_APU_CLOCK)); - subcpu.set_addrmap(AS_PROGRAM, &vsnes_state::vsnes_cpu2_map); - - MCFG_MACHINE_START_OVERRIDE(vsnes_state,vsdual) + subcpu.set_addrmap(AS_PROGRAM, &vs_dual_state::vsnes_cpu2_map); config.set_default_layout(layout_dualhsxs); @@ -1893,24 +2638,25 @@ void vsnes_state::vsdual(machine_config &config) screen2.set_screen_update("ppu2", FUNC(ppu2c0x_device::screen_update)); PPU_2C04(config, m_ppu1); - m_ppu1->set_addrmap(0, &vsnes_state::vsnes_ppu1_map); + m_ppu1->set_addrmap(0, &vs_dual_state::vsnes_ppu1_map); m_ppu1->set_screen("screen1"); m_ppu1->set_cpu_tag(m_maincpu); m_ppu1->int_callback().set_inputline(m_maincpu, INPUT_LINE_NMI); PPU_2C04(config, m_ppu2); - m_ppu2->set_addrmap(0, &vsnes_state::vsnes_ppu2_map); + m_ppu2->set_addrmap(0, &vs_dual_state::vsnes_ppu2_map); m_ppu2->set_screen("screen2"); m_ppu2->set_cpu_tag(m_subcpu); m_ppu2->int_callback().set_inputline(m_subcpu, INPUT_LINE_NMI); - /* sound hardware */ - SPEAKER(config, "mono").front_center(); - maincpu.add_route(ALL_OUTPUTS, "mono", 0.50); - subcpu.add_route(ALL_OUTPUTS, "mono", 0.50); + // sound hardware + SPEAKER(config, "lspeaker").front_left(); + SPEAKER(config, "rspeaker").front_right(); + maincpu.add_route(ALL_OUTPUTS, "lspeaker", 0.50); + subcpu.add_route(ALL_OUTPUTS, "rspeaker", 0.50); } -void vsnes_state::vsdual_pi(machine_config &config) +void vs_dual_state::vsdual_pi(machine_config &config) { vsdual(config); config.set_perfect_quantum(m_maincpu); @@ -1919,18 +2665,16 @@ void vsnes_state::vsdual_pi(machine_config &config) // as the board would always be running in 'perfect interleave' the fact the Mahjong game doesn't work like this needs investigating. } -void vsnes_state::vsnes_bootleg(machine_config &config) +void vs_smbbl_state::vs_smbbl(machine_config &config) { - /* basic machine hardware */ + // basic machine hardware M6502(config, m_maincpu, XTAL(16'000'000)/8); - m_maincpu->set_addrmap(AS_PROGRAM, &vsnes_state::vsnes_cpu1_bootleg_map); - - MCFG_MACHINE_START_OVERRIDE(vsnes_state,bootleg) + m_maincpu->set_addrmap(AS_PROGRAM, &vs_smbbl_state::vsnes_cpu1_bootleg_map); Z80(config, m_subcpu, XTAL(16'000'000)/8); // Z8400APS-Z80CPU - m_subcpu->set_addrmap(AS_PROGRAM, &vsnes_state::vsnes_bootleg_z80_map); + m_subcpu->set_addrmap(AS_PROGRAM, &vs_smbbl_state::vsnes_bootleg_z80_map); - /* video hardware */ + // video hardware screen_device &screen1(SCREEN(config, "screen1", SCREEN_TYPE_RASTER)); screen1.set_refresh_hz(56.69); screen1.set_size(32*8, 280); @@ -1938,19 +2682,19 @@ void vsnes_state::vsnes_bootleg(machine_config &config) screen1.set_screen_update("ppu1", FUNC(ppu2c0x_device::screen_update)); PPU_2C04C(config, m_ppu1); - m_ppu1->set_addrmap(0, &vsnes_state::vsnes_ppu_bootleg_map); + m_ppu1->set_addrmap(0, &vs_smbbl_state::vsnes_ppu_bootleg_map); m_ppu1->set_cpu_tag(m_maincpu); m_ppu1->set_screen("screen1"); m_ppu1->int_callback().set_inputline(m_maincpu, INPUT_LINE_NMI); - /* sound hardware */ + // sound hardware SPEAKER(config, "mono").front_center(); SN76489(config, "sn1", XTAL(16'000'000)/8).add_route(ALL_OUTPUTS, "mono", 0.50); // one runs at 2 MHz, other runs at 4 MHz SN76489(config, "sn2", XTAL(16'000'000)/4).add_route(ALL_OUTPUTS, "mono", 0.50); } -/******************************************************************************/ +//****************************************************************************** /* Palettes were obtained for each RGB PPU type by running a test program that fills the screen with a single color and analyzing the RGB output. @@ -2907,70 +3651,72 @@ ROM_START( iceclmrd ) ROM_COPY( "ppu1:palette", 0x00, 0x00, 0xc0 ) ROM_END -/******************************************************************************/ +} // anonymous namespace + +//****************************************************************************** /* Sets by region: World (C) Nintendo US (C) Nintendo of America Japan (C) Nintendo Co., Ltd. */ -// YEAR NAME PARENT MACHINE INPUT STATE INIT MONITOR -GAME( 1985, btlecity, 0, vsnes, btlecity, vsnes_state, init_vsnormal, ROT0, "Namco", "Vs. Battle City", 0 ) -GAME( 1985, starlstr, 0, vsnes, starlstr, vsnes_state, init_vsnormal, ROT0, "Namco", "Vs. Star Luster", 0 ) -GAME( 1987, cstlevna, 0, vsnes, cstlevna, vsnes_state, init_vsvram, ROT0, "Konami", "Vs. Castlevania", 0 ) -GAME( 1984, cluclu, 0, vsnes, cluclu, vsnes_state, init_vsnormal, ROT0, "Nintendo", "Vs. Clu Clu Land", 0 ) -GAME( 1990, drmario, 0, vsnes, drmario, vsnes_state, init_drmario, ROT0, "Nintendo", "Vs. Dr. Mario", 0 ) -GAME( 1984, excitebk, 0, vsnes, excitebk, vsnes_state, init_vsnormal, ROT0, "Nintendo", "Vs. Excitebike (set EB4-3 E)", 0 ) -GAME( 1984, excitebko,excitebk, vsnes, excitebk, vsnes_state, init_vsnormal, ROT0, "Nintendo", "Vs. Excitebike (set EB4-3 ?)", 0 ) // older -GAME( 1984, excitebkj,excitebk, vsnes, excitebk, vsnes_state, init_vsnormal, ROT0, "Nintendo", "Vs. Excitebike (set EB4-4 A)", 0 ) // likely Japan -GAME( 1986, goonies, 0, vsnes, goonies, vsnes_state, init_vskonami, ROT0, "Konami", "Vs. The Goonies (set E)", 0 ) -GAME( 1984, iceclimb, 0, vsnes, iceclmbj, vsnes_state, init_vsnormal, ROT0, "Nintendo", "Vs. Ice Climber (set IC4-4 B-1)", 0 ) -GAME( 1984, iceclimba,iceclimb, vsnes, iceclimb, vsnes_state, init_vsnormal, ROT0, "Nintendo", "Vs. Ice Climber (set IC4-4 ?)", 0 ) -GAME( 1985, nvs_machrider, 0, vsnes, machridr, vsnes_state, init_vsnormal, ROT0, "Nintendo", "Vs. Mach Rider (Endurance Course Version)", MACHINE_IMPERFECT_GRAPHICS ) -GAME( 1985, nvs_machridera,nvs_machrider,vsnes, machridj, vsnes_state, init_vsnormal, ROT0, "Nintendo", "Vs. Mach Rider (Fighting Course Version, set MR4-1 A)", MACHINE_IMPERFECT_GRAPHICS ) -GAME( 1986, rbibb, 0, vsnes, rbibb, vsnes_state, init_rbibb, ROT0, "Namco", "Vs. Atari R.B.I. Baseball (set 1)", 0 ) -GAME( 1986, rbibba, rbibb, vsnes, rbibb, vsnes_state, init_rbibb, ROT0, "Namco", "Vs. Atari R.B.I. Baseball (set 2)", 0 ) -GAME( 1986, suprmrio, 0, vsnes, suprmrio, vsnes_state, init_vsnormal, ROT0, "Nintendo", "Vs. Super Mario Bros. (set SM4-4 E)", 0 ) -GAME( 1986, suprmrioa,suprmrio, vsnes, suprmrio, vsnes_state, init_vsnormal, ROT0, "Nintendo", "Vs. Super Mario Bros. (set ?, harder)", 0 ) -GAME( 1986, suprmriobl,suprmrio, vsnes_bootleg, suprmrio, vsnes_state, init_bootleg, ROT0, "bootleg", "Vs. Super Mario Bros. (bootleg with Z80, set 1)", 0 ) // timer starts at 200(!) -GAME( 1986, suprmriobl2,suprmrio,vsnes_bootleg, suprmrio, vsnes_state, init_bootleg, ROT0, "bootleg", "Vs. Super Mario Bros. (bootleg with Z80, set 2)", 0 ) // timer starts at 300 -GAME( 1988, skatekds, suprmrio, vsnes, suprmrio, vsnes_state, init_vsnormal, ROT0, "hack (Two-Bit Score)", "Vs. Skate Kids. (Graphic hack of Super Mario Bros.)", 0 ) -GAME( 1985, vsskykid, 0, vsnes, vsskykid, vsnes_state, init_vs108, ROT0, "Namco", "Vs. Super SkyKid", 0 ) -GAME( 1987, tkoboxng, 0, vsnes, tkoboxng, vsnes_state, init_tkoboxng, ROT0, "Namco / Data East USA", "Vs. T.K.O. Boxing", 0 ) -GAME( 1984, smgolf, 0, vsnes, golf4s, vsnes_state, init_vsnormal, ROT0, "Nintendo", "Vs. Stroke & Match Golf (Men Version, set GF4-2 F)", 0 ) -GAME( 1984, smgolfb, smgolf, vsnes, golf, vsnes_state, init_vsnormal, ROT0, "Nintendo", "Vs. Stroke & Match Golf (Men Version, set GF4-2 ?)", 0 ) -GAME( 1984, smgolfj, smgolf, vsnes, golf, vsnes_state, init_vsnormal, ROT0, "Nintendo Co., Ltd.", "Vs. Stroke & Match Golf (Men Version) (Japan, set GF3 B)", 0 ) -GAME( 1984, ladygolfe,smgolf, vsnes, golf, vsnes_state, init_vsnormal, ROT0, "Nintendo", "Vs. Stroke & Match Golf (Ladies Version, set LG4 E)", 0 ) -GAME( 1984, ladygolf, smgolf, vsnes, golf, vsnes_state, init_vsnormal, ROT0, "Nintendo", "Vs. Stroke & Match Golf (Ladies Version, set LG4 ?)", 0 ) -GAME( 1984, vspinbal, 0, vsnes, vspinbal, vsnes_state, init_vsnormal, ROT0, "Nintendo", "Vs. Pinball (US, set PN4 E-1)", 0 ) -GAME( 1984, vspinbalj,vspinbal, vsnes, vspinblj, vsnes_state, init_vsnormal, ROT0, "Nintendo Co., Ltd.", "Vs. Pinball (Japan, set PN3 B)", 0 ) -GAME( 1986, vsslalom, 0, vsnes, vsslalom, vsnes_state, init_vsnormal, ROT0, "Rare Coin-It Inc.", "Vs. Slalom", MACHINE_IMPERFECT_GRAPHICS ) -GAME( 1985, vssoccer, 0, vsnes, vssoccer, vsnes_state, init_vsnormal, ROT0, "Nintendo", "Vs. Soccer (set SC4-2 A)", 0 ) -GAME( 1985, vssoccera,vssoccer, vsnes, vssoccer, vsnes_state, init_bnglngby, ROT0, "Nintendo", "Vs. Soccer (set SC4-3 ?)", 0 ) -GAME( 1986, vsgradus, 0, vsnes, vsgradus, vsnes_state, init_vskonami, ROT0, "Konami", "Vs. Gradius (US, set GR E)", 0 ) -GAME( 1987, nvs_platoon, 0, vsnes, platoon, vsnes_state, init_platoon, ROT0, "Ocean Software Limited", "Vs. Platoon", 0 ) -GAME( 1987, vstetris, 0, vsnes, vstetris, vsnes_state, init_vsnormal, ROT0, "Academysoft-Elorg", "Vs. Tetris" , 0 ) -GAME( 1986, nvs_mightybj, 0, mightybj, mightybj, vsnes_state, init_vsnormal, ROT0, "Tecmo", "Vs. Mighty Bomb Jack (Japan)", 0 ) -GAME( 1985, jajamaru, 0, jajamaru, jajamaru, vsnes_state, init_vsnormal, ROT0, "Jaleco", "Vs. Ninja Jajamaru Kun (Japan)", 0 ) -GAME( 1987, topgun, 0, topgun, topgun, vsnes_state, init_vsvram, ROT0, "Konami", "Vs. Top Gun", 0) -GAME( 1985, bnglngby, 0, vsnes, bnglngby, vsnes_state, init_bnglngby, ROT0, "Nintendo / Broderbund Software Inc.", "Vs. Raid on Bungeling Bay (RD4-2 B)", 0 ) -GAME( 1986, supxevs, 0, vsnes, supxevs, vsnes_state, init_supxevs, ROT0, "Namco", "Vs. Super Xevious", 0 ) +// YEAR NAME PARENT MACHINE INPUT STATE INIT MONITOR +GAME( 1985, btlecity, 0, vsnes, btlecity, vs_uni_state, init_vsnormal, ROT0, "Namco", "Vs. Battle City", 0 ) +GAME( 1985, starlstr, 0, vsnes, starlstr, vs_uni_state, init_vsnormal, ROT0, "Namco", "Vs. Star Luster", 0 ) +GAME( 1987, cstlevna, 0, vsnes, cstlevna, vs_uni_state, init_vsvram, ROT0, "Konami", "Vs. Castlevania", 0 ) +GAME( 1984, cluclu, 0, vsnes, cluclu, vs_uni_state, init_vsnormal, ROT0, "Nintendo", "Vs. Clu Clu Land", 0 ) +GAME( 1990, drmario, 0, vsnes, drmario, vs_uni_state, init_drmario, ROT0, "Nintendo", "Vs. Dr. Mario", 0 ) +GAME( 1984, excitebk, 0, vsnes, excitebk, vs_uni_state, init_vsnormal, ROT0, "Nintendo", "Vs. Excitebike (set EB4-3 E)", 0 ) +GAME( 1984, excitebko, excitebk, vsnes, excitebk, vs_uni_state, init_vsnormal, ROT0, "Nintendo", "Vs. Excitebike (set EB4-3 ?)", 0 ) // older +GAME( 1984, excitebkj, excitebk, vsnes, excitebk, vs_uni_state, init_vsnormal, ROT0, "Nintendo", "Vs. Excitebike (set EB4-4 A)", 0 ) // likely Japan +GAME( 1986, goonies, 0, vsnes, goonies, vs_uni_state, init_vskonami, ROT0, "Konami", "Vs. The Goonies (set E)", 0 ) +GAME( 1984, iceclimb, 0, vsnes, iceclmbj, vs_uni_state, init_vsnormal, ROT0, "Nintendo", "Vs. Ice Climber (set IC4-4 B-1)", 0 ) +GAME( 1984, iceclimba, iceclimb, vsnes, iceclimb, vs_uni_state, init_vsnormal, ROT0, "Nintendo", "Vs. Ice Climber (set IC4-4 ?)", 0 ) +GAME( 1985, nvs_machrider, 0, vsnes, machridr, vs_uni_state, init_vsnormal, ROT0, "Nintendo", "Vs. Mach Rider (Endurance Course Version)", MACHINE_IMPERFECT_GRAPHICS ) +GAME( 1985, nvs_machridera, nvs_machrider, vsnes, machridj, vs_uni_state, init_vsnormal, ROT0, "Nintendo", "Vs. Mach Rider (Fighting Course Version, set MR4-1 A)", MACHINE_IMPERFECT_GRAPHICS ) +GAME( 1986, rbibb, 0, vsnes, rbibb, vs_uni_state, init_rbibb, ROT0, "Namco", "Vs. Atari R.B.I. Baseball (set 1)", 0 ) +GAME( 1986, rbibba, rbibb, vsnes, rbibb, vs_uni_state, init_rbibb, ROT0, "Namco", "Vs. Atari R.B.I. Baseball (set 2)", 0 ) +GAME( 1986, suprmrio, 0, vsnes, suprmrio, vs_uni_state, init_vsnormal, ROT0, "Nintendo", "Vs. Super Mario Bros. (set SM4-4 E)", 0 ) +GAME( 1986, suprmrioa, suprmrio, vsnes, suprmrio, vs_uni_state, init_vsnormal, ROT0, "Nintendo", "Vs. Super Mario Bros. (set ?, harder)", 0 ) +GAME( 1986, suprmriobl, suprmrio, vs_smbbl, suprmrio, vs_smbbl_state, init_smbbl, ROT0, "bootleg", "Vs. Super Mario Bros. (bootleg with Z80, set 1)", 0 ) // timer starts at 200(!) +GAME( 1986, suprmriobl2, suprmrio, vs_smbbl, suprmrio, vs_smbbl_state, init_smbbl, ROT0, "bootleg", "Vs. Super Mario Bros. (bootleg with Z80, set 2)", 0 ) // timer starts at 300 +GAME( 1988, skatekds, suprmrio, vsnes, suprmrio, vs_uni_state, init_vsnormal, ROT0, "hack (Two-Bit Score)", "Vs. Skate Kids. (Graphic hack of Super Mario Bros.)", 0 ) +GAME( 1985, vsskykid, 0, vsnes, vsskykid, vs_uni_state, init_vs108, ROT0, "Namco", "Vs. Super SkyKid", 0 ) +GAME( 1987, tkoboxng, 0, vsnes, tkoboxng, vs_uni_state, init_tkoboxng, ROT0, "Namco / Data East USA", "Vs. T.K.O. Boxing", 0 ) +GAME( 1984, smgolf, 0, vsnes, golf4s, vs_uni_state, init_vsnormal, ROT0, "Nintendo", "Vs. Stroke & Match Golf (Men Version, set GF4-2 F)", 0 ) +GAME( 1984, smgolfb, smgolf, vsnes, golf, vs_uni_state, init_vsnormal, ROT0, "Nintendo", "Vs. Stroke & Match Golf (Men Version, set GF4-2 ?)", 0 ) +GAME( 1984, smgolfj, smgolf, vsnes, golf, vs_uni_state, init_vsnormal, ROT0, "Nintendo Co., Ltd.", "Vs. Stroke & Match Golf (Men Version) (Japan, set GF3 B)", 0 ) +GAME( 1984, ladygolfe, smgolf, vsnes, golf, vs_uni_state, init_vsnormal, ROT0, "Nintendo", "Vs. Stroke & Match Golf (Ladies Version, set LG4 E)", 0 ) +GAME( 1984, ladygolf, smgolf, vsnes, golf, vs_uni_state, init_vsnormal, ROT0, "Nintendo", "Vs. Stroke & Match Golf (Ladies Version, set LG4 ?)", 0 ) +GAME( 1984, vspinbal, 0, vsnes, vspinbal, vs_uni_state, init_vsnormal, ROT0, "Nintendo", "Vs. Pinball (US, set PN4 E-1)", 0 ) +GAME( 1984, vspinbalj, vspinbal, vsnes, vspinblj, vs_uni_state, init_vsnormal, ROT0, "Nintendo Co., Ltd.", "Vs. Pinball (Japan, set PN3 B)", 0 ) +GAME( 1986, vsslalom, 0, vsnes, vsslalom, vs_uni_state, init_vsnormal, ROT0, "Rare Coin-It Inc.", "Vs. Slalom", MACHINE_IMPERFECT_GRAPHICS ) +GAME( 1985, vssoccer, 0, vsnes, vssoccer, vs_uni_state, init_vsnormal, ROT0, "Nintendo", "Vs. Soccer (set SC4-2 A)", 0 ) +GAME( 1985, vssoccera, vssoccer, vsnes, vssoccer, vs_uni_state, init_bnglngby, ROT0, "Nintendo", "Vs. Soccer (set SC4-3 ?)", 0 ) +GAME( 1986, vsgradus, 0, vsnes, vsgradus, vs_uni_state, init_vskonami, ROT0, "Konami", "Vs. Gradius (US, set GR E)", 0 ) +GAME( 1987, nvs_platoon, 0, vsnes, platoon, vs_uni_state, init_platoon, ROT0, "Ocean Software Limited", "Vs. Platoon", 0 ) +GAME( 1987, vstetris, 0, vsnes, vstetris, vs_uni_state, init_vsnormal, ROT0, "Academysoft-Elorg", "Vs. Tetris" , 0 ) +GAME( 1986, nvs_mightybj, 0, mightybj, mightybj, vs_uni_state, init_vsnormal, ROT0, "Tecmo", "Vs. Mighty Bomb Jack (Japan)", 0 ) +GAME( 1985, jajamaru, 0, jajamaru, jajamaru, vs_uni_state, init_vsnormal, ROT0, "Jaleco", "Vs. Ninja Jajamaru Kun (Japan)", 0 ) +GAME( 1987, topgun, 0, topgun, topgun, vs_uni_state, init_vsvram, ROT0, "Konami", "Vs. Top Gun", 0 ) +GAME( 1985, bnglngby, 0, vsnes, bnglngby, vs_uni_state, init_bnglngby, ROT0, "Nintendo / Broderbund Software Inc.", "Vs. Raid on Bungeling Bay (RD4-2 B)", 0 ) +GAME( 1986, supxevs, 0, vsnes, supxevs, vs_uni_state, init_supxevs, ROT0, "Namco", "Vs. Super Xevious", 0 ) // Light Gun games -GAME( 1985, duckhunt, 0, vsnes, duckhunt, vsnes_state, init_vsgun, ROT0, "Nintendo", "Vs. Duck Hunt (set DH3 E)", 0 ) -GAME( 1985, hogalley, 0, vsnes, hogalley, vsnes_state, init_vsgun, ROT0, "Nintendo", "Vs. Hogan's Alley (set HA4-1 E-1)", 0 ) -GAME( 1986, vsgshoe, 0, vsgshoe, vsgshoe, vsnes_state, init_vsgshoe, ROT0, "Nintendo", "Vs. Gumshoe (set GM5)", 0 ) -GAME( 1988, vsfdf, 0, vsnes, vsfdf, vsnes_state, init_vsfdf, ROT0, "Sunsoft", "Vs. Freedom Force", 0 ) +GAME( 1985, duckhunt, 0, vsnes, duckhunt, vs_uni_state, init_vsgun, ROT0, "Nintendo", "Vs. Duck Hunt (set DH3 E)", 0 ) +GAME( 1985, hogalley, 0, vsnes, hogalley, vs_uni_state, init_vsgun, ROT0, "Nintendo", "Vs. Hogan's Alley (set HA4-1 E-1)", 0 ) +GAME( 1986, vsgshoe, 0, vsgshoe, vsgshoe, vs_uni_state, init_vsgshoe, ROT0, "Nintendo", "Vs. Gumshoe (set GM5)", 0 ) +GAME( 1988, vsfdf, 0, vsnes, vsfdf, vs_uni_state, init_vsfdf, ROT0, "Sunsoft", "Vs. Freedom Force", 0 ) // Dual games -GAME( 1984, vstennis, 0, vsdual_pi, vstennis, vsnes_state, init_vsdual, ROT0, "Nintendo Co., Ltd.", "Vs. Tennis (Japan/USA, set TE A-3)" , 0 ) -GAME( 1984, vstennisa,vstennis, vsdual_pi, vstennis, vsnes_state, init_vsdual, ROT0, "Nintendo Co., Ltd.", "Vs. Tennis (Japan/USA, set 2)", 0 ) -GAME( 1984, vstennisb,vstennis, vsdual_pi, vstennis, vsnes_state, init_vsdual, ROT0, "Nintendo Co., Ltd.", "Vs. Tennis (Japan/USA, set 3)", MACHINE_IMPERFECT_GRAPHICS ) -GAME( 1984, wrecking, 0, vsdual_pi, wrecking, vsnes_state, init_vsdual, ROT0, "Nintendo", "Vs. Wrecking Crew", 0 ) -GAME( 1984, balonfgt, 0, vsdual_pi, balonfgt, vsnes_state, init_vsdual, ROT0, "Nintendo", "Vs. Balloon Fight (set BF4 A-3)", 0 ) -GAME( 1984, vsmahjng, 0, vsdual, vsmahjng, vsnes_state, init_vsdual, ROT0, "Nintendo Co., Ltd.", "Vs. Mahjong (Japan)", 0 ) -GAME( 1984, vsbball, 0, vsdual_pi, vsbball, vsnes_state, init_vsdual, ROT0, "Nintendo of America", "Vs. Baseball (US, set BA E-1)", 0 ) -GAME( 1984, vsbballj, vsbball, vsdual_pi, vsbballj, vsnes_state, init_vsdual, ROT0, "Nintendo Co., Ltd.", "Vs. Baseball (Japan, set BA A-3)", 0 ) -GAME( 1984, vsbballja,vsbball, vsdual_pi, vsbballj, vsnes_state, init_vsdual, ROT0, "Nintendo Co., Ltd.", "Vs. Baseball (Japan, set BA A-2)", 0 ) -GAME( 1984, vsbballjb,vsbball, vsdual_pi, vsbballj, vsnes_state, init_vsdual, ROT0, "Nintendo Co., Ltd.", "Vs. Baseball (Japan, set BA A-1)", 0 ) -GAME( 1984, iceclmrd, 0, vsdual_pi, iceclmrj, vsnes_state, init_vsdual, ROT0, "Nintendo", "Vs. Ice Climber Dual (set IC4-4 A-1)", 0 ) +GAME( 1984, vstennis, 0, vsdual_pi, vstennis, vs_dual_state, init_vsdual, ROT0, "Nintendo Co., Ltd.", "Vs. Tennis (Japan/USA, set TE A-3)" , 0 ) +GAME( 1984, vstennisa, vstennis, vsdual_pi, vstennis, vs_dual_state, init_vsdual, ROT0, "Nintendo Co., Ltd.", "Vs. Tennis (Japan/USA, set 2)", 0 ) +GAME( 1984, vstennisb, vstennis, vsdual_pi, vstennis, vs_dual_state, init_vsdual, ROT0, "Nintendo Co., Ltd.", "Vs. Tennis (Japan/USA, set 3)", MACHINE_IMPERFECT_GRAPHICS ) +GAME( 1984, wrecking, 0, vsdual_pi, wrecking, vs_dual_state, init_vsdual, ROT0, "Nintendo", "Vs. Wrecking Crew", 0 ) +GAME( 1984, balonfgt, 0, vsdual_pi, balonfgt, vs_dual_state, init_vsdual, ROT0, "Nintendo", "Vs. Balloon Fight (set BF4 A-3)", 0 ) +GAME( 1984, vsmahjng, 0, vsdual, vsmahjng, vs_dual_state, init_vsdual, ROT0, "Nintendo Co., Ltd.", "Vs. Mahjong (Japan)", 0 ) +GAME( 1984, vsbball, 0, vsdual_pi, vsbball, vs_dual_state, init_vsdual, ROT0, "Nintendo of America", "Vs. Baseball (US, set BA E-1)", 0 ) +GAME( 1984, vsbballj, vsbball, vsdual_pi, vsbballj, vs_dual_state, init_vsdual, ROT0, "Nintendo Co., Ltd.", "Vs. Baseball (Japan, set BA A-3)", 0 ) +GAME( 1984, vsbballja, vsbball, vsdual_pi, vsbballj, vs_dual_state, init_vsdual, ROT0, "Nintendo Co., Ltd.", "Vs. Baseball (Japan, set BA A-2)", 0 ) +GAME( 1984, vsbballjb, vsbball, vsdual_pi, vsbballj, vs_dual_state, init_vsdual, ROT0, "Nintendo Co., Ltd.", "Vs. Baseball (Japan, set BA A-1)", 0 ) +GAME( 1984, iceclmrd, 0, vsdual_pi, iceclmrj, vs_dual_state, init_vsdual, ROT0, "Nintendo", "Vs. Ice Climber Dual (set IC4-4 A-1)", 0 ) diff --git a/src/mame/nintendo/vsnes.h b/src/mame/nintendo/vsnes.h deleted file mode 100644 index 63658957130..00000000000 --- a/src/mame/nintendo/vsnes.h +++ /dev/null @@ -1,157 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Pierpaolo Prazzoli - -#include "bus/nes_ctrl/zapper_sensor.h" -#include "machine/nvram.h" -#include "sound/sn76496.h" -#include "video/ppu2c0x.h" - -class vsnes_state : public driver_device -{ -public: - vsnes_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag) - , m_maincpu(*this, "maincpu") - , m_subcpu(*this, "sub") - , m_ppu1(*this, "ppu1") - , m_ppu2(*this, "ppu2") - , m_sn1(*this, "sn1") - , m_sn2(*this, "sn2") - , m_sensor(*this, "sensor") - , m_nvram(*this, "nvram") - , m_gfx1_rom(*this, "gfx1") - , m_in(*this, "IN%u", 0U) - , m_coins(*this, "COINS%u", 1U) - , m_dsw(*this, "DSW%u", 0U) - , m_gunx(*this, "GUNX") - , m_guny(*this, "GUNY") - , m_prg_banks(*this, "prg%u", 0U) - , m_prg_view(*this, "prg_view") - , m_chr_banks(*this, "chr%u", 0U) - , m_chr_view(*this, "chr_view") - { - } - - void vsdual(machine_config &config); - void vsgshoe(machine_config &config); - void vsnes(machine_config &config); - void vsdual_pi(machine_config &config); - void topgun(machine_config &config); - void mightybj(machine_config &config); - void vsnes_bootleg(machine_config &config); - void jajamaru(machine_config &config); - - void init_vskonami(); - void init_vsvram(); - void init_bnglngby(); - void init_drmario(); - void init_vs108(); - void init_vsfdf(); - void init_tkoboxng(); - void init_vsgun(); - void init_supxevs(); - void init_vsgshoe(); - void init_vsnormal(); - void init_platoon(); - void init_rbibb(); - void init_vsdual(); - void init_bootleg(); - -protected: - virtual void machine_reset() override; - -private: - enum { MAIN = 0, SUB = 1 }; - - required_device m_maincpu; - optional_device m_subcpu; - required_device m_ppu1; - optional_device m_ppu2; - optional_device m_sn1; - optional_device m_sn2; - - optional_device m_sensor; - optional_device m_nvram; - - optional_memory_region m_gfx1_rom; - - optional_ioport_array<4> m_in; - optional_ioport_array<2> m_coins; - optional_ioport_array<2> m_dsw; - optional_ioport m_gunx; - optional_ioport m_guny; - - template void sprite_dma_w(address_space &space, u8 data); - template void vsnes_coin_counter_w(offs_t offset, u8 data); - template u8 vsnes_coin_counter_r(offs_t offset); - template void vsnes_in0_w(u8 data); - template u8 vsnes_in0_r(); - template u8 vsnes_in1_r(); - void vsnormal_vrom_banking(uint8_t data); - void vskonami_rom_banking(offs_t offset, uint8_t data); - void vsgshoe_gun_in0_w(uint8_t data); - void drmario_rom_banking(offs_t offset, uint8_t data); - void vsvram_rom_banking(uint8_t data); - void vs108_rom_banking(offs_t offset, uint8_t data); - u8 rbibb_prot_r(offs_t offset); - u8 supxevs_prot_1_r(); - u8 supxevs_prot_2_r(); - u8 supxevs_prot_3_r(); - u8 supxevs_prot_4_r(); - u8 tkoboxng_prot_r(offs_t offset); - void sunsoft3_rom_banking(offs_t offset, uint8_t data); - void set_bnglngby_irq_w(uint8_t data); - uint8_t set_bnglngby_irq_r(); - void vsdual_vrom_banking_main(uint8_t data); - void vsdual_vrom_banking_sub(uint8_t data); - void vssmbbl_sn_w(offs_t offset, uint8_t data); - - DECLARE_MACHINE_START(vsnes); - DECLARE_MACHINE_START(vsdual); - DECLARE_MACHINE_START(bootleg); - void v_set_videorom_bank(int start, int count, int vrom_start_bank); - - void bootleg_sound_write(offs_t offset, uint8_t data); - uint8_t vsnes_bootleg_z80_data_r(); - uint8_t vsnes_bootleg_z80_address_r(offs_t offset); - void vsnes_bootleg_scanline(int scanline, bool vblank, bool blanked); - uint8_t vsnes_bootleg_ppudata(); - - void vsnes_bootleg_z80_map(address_map &map); - void vsnes_cpu1_bootleg_map(address_map &map); - void vsnes_ppu_bootleg_map(address_map &map); - void vsnes_cpu1_map(address_map &map); - void vsnes_cpu2_map(address_map &map); - void vsnes_ppu1_map(address_map &map); - void vsnes_ppu2_map(address_map &map); - - void init_prg_banking(); - void prg32(int bank); - void prg16(int slot, int bank); - void prg8(int slot, int bank); - - memory_bank_array_creator<4> m_prg_banks; - memory_view m_prg_view; - int m_prg_chunks = 0; - - memory_bank_array_creator<8> m_chr_banks; - memory_view m_chr_view; - int m_chr_chunks = 0; - - bool m_has_gun = false; - int m_coin = 0; - int m_input_latch[4]{}; - int m_input_strobe[2]{}; - int m_mmc1_shiftreg = 0; - int m_mmc1_shiftcount = 0; - int m_mmc1_prg16k = 0; - int m_mmc1_switchlow = 0; - int m_mmc1_chr4k = 0; - int m_108_reg = 0; - int m_prot_index = 0; - int m_ret = 0; - - u8 m_bootleg_sound_offset = 0U; - u8 m_bootleg_sound_data = 0U; - int m_bootleg_latched_scanline = 0; -}; diff --git a/src/mame/nintendo/vsnes_m.cpp b/src/mame/nintendo/vsnes_m.cpp deleted file mode 100644 index 774516fe959..00000000000 --- a/src/mame/nintendo/vsnes_m.cpp +++ /dev/null @@ -1,582 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Brad Oliver, Fabio Priuli -/*************************************************************************** - -Nintendo VS UniSystem and DualSystem - (c) 1984 Nintendo of America - - Portions of this code are heavily based on - Brad Oliver's MESS implementation of the NES. - -***************************************************************************/ - -#include "emu.h" -#include "screen.h" -#include "video/ppu2c0x.h" -#include "vsnes.h" - - -/* PPU notes */ -/* nametable is, per Lord Nightmare, always 4K per PPU */ -/* The vsnes system has relatively few banking options for CHR */ -/* Each driver will use ROM or RAM for CHR, never both, and RAM is never banked */ -/* This leads to the memory system being an optimal place to perform banking */ - - -/************************************* - * - * Init machine - * - *************************************/ - -void vsnes_state::machine_reset() -{ - m_input_latch[0] = m_input_latch[1] = 0; - m_input_latch[2] = m_input_latch[3] = 0; - m_input_strobe[0] = m_input_strobe[1] = 0; -} - -/************************************* - * - * Machine start functions - * - *************************************/ - -void vsnes_state::init_prg_banking() -{ - u8 *base = memregion("prg")->base(); - m_prg_chunks = memregion("prg")->bytes() / 0x2000; - - for (int i = 0; i < 4; i++) - { - m_prg_banks[i]->configure_entries(0, m_prg_chunks, base, 0x2000); - m_prg_banks[i]->set_entry(m_prg_chunks - 4 + i); - } - - m_prg_view.select(0); -} - -// safe banking helpers (only work when PRG size is a power of 2, i.e. not Gumshoe) - -void vsnes_state::prg32(int bank) -{ - bank = (bank << 2) & (m_prg_chunks - 1); - - for (int i = 0; i < 4; i++) - m_prg_banks[i]->set_entry(bank + i); -} - -void vsnes_state::prg16(int slot, int bank) -{ - bank = (bank << 1) & (m_prg_chunks - 1); - slot = (slot & 1) << 1; - - for (int i = 0; i < 2; i++) - m_prg_banks[slot + i]->set_entry(bank + i); -} - -void vsnes_state::prg8(int slot, int bank) -{ - m_prg_banks[slot & 0x03]->set_entry(bank & (m_prg_chunks - 1)); -} - -void vsnes_state::v_set_videorom_bank(int start, int count, int vrom_start_bank) -{ - assert(start + count <= 8); - - vrom_start_bank &= m_chr_chunks - 1; - assert(vrom_start_bank + count <= m_chr_chunks); - - // count determines the size of the area mapped - for (int i = 0; i < count; i++) - m_chr_banks[i + start]->set_entry(vrom_start_bank + i); -} - -MACHINE_START_MEMBER(vsnes_state, vsnes) -{ - // establish chr banks - // DRIVER_INIT is called first - means we can handle this different for VRAM games! - if (m_gfx1_rom != nullptr) - { - u8 *base = m_gfx1_rom->base(); - m_chr_chunks = m_gfx1_rom->bytes() / 0x400; - - for (int i = 0; i < 8; i++) - { - m_ppu1->space(AS_PROGRAM).install_read_bank(0x0400 * i, 0x0400 * i + 0x03ff, m_chr_banks[i]); - m_chr_banks[i]->configure_entries(0, m_chr_chunks, base, 0x400); - } - v_set_videorom_bank(0, 8, 0); - } - else - m_chr_view.select(0); -} - -MACHINE_START_MEMBER(vsnes_state, vsdual) -{ - for (int i = 0; i < 2; i++) - { - const char *region = i ? "gfx2" : "gfx1"; - u8 *base = memregion(region)->base(); - int entries = memregion(region)->bytes() / 0x2000; - m_chr_banks[i]->configure_entries(0, entries, base, 0x2000); - m_chr_banks[i]->set_entry(0); - } -} - -MACHINE_START_MEMBER(vsnes_state, bootleg) -{ - u8 *base = m_gfx1_rom->base(); - int entries = m_gfx1_rom->bytes() / 0x2000; - m_chr_banks[0]->configure_entries(0, entries, base, 0x2000); - m_chr_banks[0]->set_entry(0); -} - -/********************************************************************************** - * - * Game and Board-specific initialization - * - **********************************************************************************/ - -//********************************************************************************** -// Most games: VROM Banking in controller 0 write - -void vsnes_state::vsnormal_vrom_banking(u8 data) -{ - // switch vrom - v_set_videorom_bank(0, 8, (data & 4) ? 8 : 0); - - // bit 1 ( data & 2 ) enables writes to extra ram, we ignore it - - // move along - vsnes_in0_w
(data); -} - -void vsnes_state::init_vsnormal() -{ - // vrom switching is enabled with bit 2 of $4016 - m_maincpu->space(AS_PROGRAM).install_write_handler(0x4016, 0x4016, write8smo_delegate(*this, FUNC(vsnes_state::vsnormal_vrom_banking))); -} - -//********************************************************************************** -// Gun games: VROM Banking in controller 0 write - -void vsnes_state::init_vsgun() -{ - init_vsnormal(); - m_has_gun = true; -} - -//********************************************************************************** -// Konami VRC1 games: ROM banking at $8000-$ffff - -void vsnes_state::vskonami_rom_banking(offs_t offset, u8 data) -{ - int reg = BIT(offset, 12, 3); - - switch (reg) - { - case 0: // prg bank 0 - case 2: // prg bank 1 - case 4: // prg bank 2 - prg8(reg >> 1, data); - break; - - case 6: // vrom bank 0 - v_set_videorom_bank(0, 4, data * 4); - break; - - case 7: // vrom bank 1 - v_set_videorom_bank(4, 4, data * 4); - break; - } -} - -void vsnes_state::init_vskonami() -{ - // point program banks to last 32K - init_prg_banking(); - - // banking is done with writes to the $8000-$ffff area - m_maincpu->space(AS_PROGRAM).install_write_handler(0x8000, 0xffff, write8sm_delegate(*this, FUNC(vsnes_state::vskonami_rom_banking))); -} - -//********************************************************************************** -// Vs. Gumshoe - -void vsnes_state::vsgshoe_gun_in0_w(u8 data) -{ - // Gumshoe uniquely has a bankable 16K EPROM in addition to the normal unbanked 8K slots - m_prg_banks[0]->set_entry(BIT(data, 2)); - - // otherwise do normal CHR banking and IO write - vsnormal_vrom_banking(data); -} - -void vsnes_state::init_vsgshoe() -{ - // point program banks to last 32K - init_prg_banking(); - - // vrom switching is enabled with bit 2 of $4016 - m_maincpu->space(AS_PROGRAM).install_write_handler(0x4016, 0x4016, write8smo_delegate(*this, FUNC(vsnes_state::vsgshoe_gun_in0_w))); - - m_has_gun = true; -} - -//********************************************************************************** -// MMC1 (Dr Mario): ROM banking at $8000-$ffff - -void vsnes_state::drmario_rom_banking(offs_t offset, u8 data) -{ - // reset mapper - if (data & 0x80) - { - m_mmc1_shiftcount = 0; - m_mmc1_prg16k = 1; - m_mmc1_switchlow = 1; - m_mmc1_chr4k = 0; - - return; - } - - // update shift register - m_mmc1_shiftreg = (m_mmc1_shiftreg >> 1) | (data & 1) << 4; - m_mmc1_shiftcount = (m_mmc1_shiftcount + 1) % 5; - - // are we done shifting? - if (!m_mmc1_shiftcount) - { - // apply data to registers - switch (BIT(offset, 13, 2)) - { - case 0: // mirroring and options - m_mmc1_chr4k = m_mmc1_shiftreg & 0x10; - m_mmc1_prg16k = m_mmc1_shiftreg & 0x08; - m_mmc1_switchlow = m_mmc1_shiftreg & 0x04; - // 0x03: mirroring bits unused on VS - break; - - case 1: // video rom banking - bank 0 - 4k or 8k - if (m_mmc1_chr4k) - v_set_videorom_bank(0, 4, m_mmc1_shiftreg * 4); - else - v_set_videorom_bank(0, 8, (m_mmc1_shiftreg & ~1) * 4); - break; - - case 2: // video rom banking - bank 1 - 4k only - if (m_mmc1_chr4k) - v_set_videorom_bank(4, 4, m_mmc1_shiftreg * 4); - break; - - case 3: // program banking - if (m_mmc1_prg16k) - prg16(!m_mmc1_switchlow, m_mmc1_shiftreg); - else - prg32(m_mmc1_shiftreg >> 1); - break; - } - } -} - -void vsnes_state::init_drmario() -{ - // point program banks to last 32K - init_prg_banking(); - - // MMC1 mapper at $8000-$ffff - m_maincpu->space(AS_PROGRAM).install_write_handler(0x8000, 0xffff, write8sm_delegate(*this, FUNC(vsnes_state::drmario_rom_banking))); - - m_mmc1_shiftreg = 0; - m_mmc1_shiftcount = 0; -} - -//********************************************************************************** -// (UNROM) Games with VRAM instead of graphics ROMs: ROM banking at $8000-$ffff - -void vsnes_state::vsvram_rom_banking(u8 data) -{ - prg16(0, data); -} - -void vsnes_state::init_vsvram() -{ - // point program banks to last 32K - init_prg_banking(); - - // banking is done with writes to the $8000-$ffff area - m_maincpu->space(AS_PROGRAM).install_write_handler(0x8000, 0xffff, write8smo_delegate(*this, FUNC(vsnes_state::vsvram_rom_banking))); -} - -//********************************************************************************** -// (Namco) 108 (MMC3 predecessor) games - -void vsnes_state::vs108_rom_banking(offs_t offset, u8 data) -{ - switch (offset & 0x6001) - { - case 0x0000: // $8000 - m_108_reg = data & 0x07; - break; - - case 0x0001: // $8001 - switch (m_108_reg) - { - case 0: case 1: - v_set_videorom_bank(m_108_reg * 2, 2, data); - break; - case 2: case 3: case 4: case 5: - v_set_videorom_bank(m_108_reg + 2, 1, data); - break; - case 6: case 7: - prg8(m_108_reg - 6, data); - break; - } - break; - - default: - logerror("vs108_rom_banking uncaught: %04x value: %02x\n", offset + 0x8000, data); - break; - } -} - -// Common init for (Namco) 108 games - -void vsnes_state::init_vs108() -{ - // point program banks to last 32K - init_prg_banking(); - - m_108_reg = 0; - - // 108 chip at $8000-$9fff - m_maincpu->space(AS_PROGRAM).install_write_handler(0x8000, 0xffff, write8sm_delegate(*this, FUNC(vsnes_state::vs108_rom_banking))); -} - -// Vs. RBI Baseball -// rbibb uses a protection chip labeled '127' -// Tests indicate that '127' uses a LFSR with taps: 23, 18, 0 -// It is still unknown how bits are then shuffled for readback at 0x5601/0x5e01 -u8 vsnes_state::rbibb_prot_r(offs_t offset) -{ - static constexpr u8 prot_data[32] = { - 0xff, 0xfd, 0xf5, 0xf4, 0xb4, 0xb4, 0xa6, 0x2e, - 0x2f, 0x6f, 0x6f, 0x7d, 0xd5, 0xd4, 0x94, 0x94, - 0x86, 0x2e, 0x2f, 0x6f, 0x6b, 0x79, 0xd1, 0xd0, - 0x92, 0x92, 0x8d, 0x65, 0x64, 0x34, 0xb0, 0xa2 - }; - - if (offset == 0) - { - m_prot_index = 0; - return 0; - } - - return prot_data[m_prot_index++]; -} - -void vsnes_state::init_rbibb() -{ - init_vs108(); - - // RBI Baseball protection, address fully decoded except A11 - m_maincpu->space(AS_PROGRAM).install_read_handler(0x5600, 0x5601, read8sm_delegate(*this, FUNC(vsnes_state::rbibb_prot_r))); - m_maincpu->space(AS_PROGRAM).install_read_handler(0x5e00, 0x5e01, read8sm_delegate(*this, FUNC(vsnes_state::rbibb_prot_r))); -} - -// Vs. Super Xevious - -u8 vsnes_state::supxevs_prot_1_r() -{ - m_prot_index ^= 1; - return 0x05; -} - -u8 vsnes_state::supxevs_prot_2_r() -{ - return m_prot_index ? 0x01 : 0x00; -} - -u8 vsnes_state::supxevs_prot_3_r() -{ - return m_prot_index ? 0x89 : 0xd1; -} - -u8 vsnes_state::supxevs_prot_4_r() -{ - return m_prot_index ? 0x37 : 0x3e; -} - -void vsnes_state::init_supxevs() -{ - init_vs108(); - - // Vs. Super Xevious Protection - m_maincpu->space(AS_PROGRAM).install_read_handler(0x54ff, 0x54ff, read8smo_delegate(*this, FUNC(vsnes_state::supxevs_prot_1_r))); - m_maincpu->space(AS_PROGRAM).install_read_handler(0x5678, 0x5678, read8smo_delegate(*this, FUNC(vsnes_state::supxevs_prot_2_r))); - m_maincpu->space(AS_PROGRAM).install_read_handler(0x578f, 0x578f, read8smo_delegate(*this, FUNC(vsnes_state::supxevs_prot_3_r))); - m_maincpu->space(AS_PROGRAM).install_read_handler(0x5567, 0x5567, read8smo_delegate(*this, FUNC(vsnes_state::supxevs_prot_4_r))); - - m_prot_index = 0; -} - -// Vs. TKO Boxing -// tkoboxng uses a protection chip labeled '128' -u8 vsnes_state::tkoboxng_prot_r(offs_t offset) -{ - static constexpr u8 prot_data[32] = { - 0xff, 0xbf, 0xb7, 0x97, 0x97, 0x17, 0x57, 0x4f, - 0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90, 0x94, 0x14, - 0x56, 0x4e, 0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90, - 0xd4, 0x5c, 0x3e, 0x26, 0x87, 0x83, 0x13, 0x00 - }; - - if (offset == 0) - { - m_prot_index = 0; - return 0; - } - - return prot_data[m_prot_index++]; -} - -void vsnes_state::init_tkoboxng() -{ - init_vs108(); - - // security device at $5e00-$5e01 - m_maincpu->space(AS_PROGRAM).install_read_handler(0x5e00, 0x5e01, read8sm_delegate(*this, FUNC(vsnes_state::tkoboxng_prot_r))); -} - -// Vs. Freedom Force - -void vsnes_state::init_vsfdf() -{ - init_vs108(); - m_has_gun = true; -} - -//********************************************************************************** -// Sunsoft-3 (Platoon) rom banking - -void vsnes_state::sunsoft3_rom_banking(offs_t offset, u8 data) -{ - switch (offset & 0x7800) - { - case 0x0800: - case 0x1800: - case 0x2800: - case 0x3800: - v_set_videorom_bank((offset >> 11) & 0x06, 2, data * 2); - break; - - case 0x7800: - prg16(0, data); - break; - } - -} - -void vsnes_state::init_platoon() -{ - // point program banks to last 32K - init_prg_banking(); - - m_maincpu->space(AS_PROGRAM).install_write_handler(0x8000, 0xffff, write8sm_delegate(*this, FUNC(vsnes_state::sunsoft3_rom_banking))); -} - -//********************************************************************************** -// Vs. Raid on Bungeling Bay (Japan) - -// FIXME: this is a bad hack! The unused 8K ROM in the driver supposedly runs on the main CPU (protection?) -// and does some sort of handshake (with IRQs) with the game running on the sub CPU. -void vsnes_state::set_bnglngby_irq_w(uint8_t data) -{ - m_ret = data; - m_maincpu->set_input_line(0, (data & 2) ? ASSERT_LINE : CLEAR_LINE); - /* other values ??? */ - /* 0, 4, 84 */ -} - -uint8_t vsnes_state::set_bnglngby_irq_r() -{ - return m_ret; -} - -void vsnes_state::init_bnglngby() -{ - m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x0231, 0x0231, read8smo_delegate(*this, FUNC(vsnes_state::set_bnglngby_irq_r)), write8smo_delegate(*this, FUNC(vsnes_state::set_bnglngby_irq_w))); - - m_ret = 0; - - /* normal banking */ - init_vsnormal(); -} - -//********************************************************************************** -// VS Dualsystem - -void vsnes_state::vsdual_vrom_banking_main(u8 data) -{ - // switch vrom - m_chr_banks[0]->set_entry(BIT(data, 2)); - - // bit 1 ( data & 2 ) triggers irq on the other cpu - m_subcpu->set_input_line(0, (data & 2) ? CLEAR_LINE : ASSERT_LINE); - - // move along - vsnes_in0_w
(data); -} - -void vsnes_state::vsdual_vrom_banking_sub(u8 data) -{ - // switch vrom - m_chr_banks[1]->set_entry(BIT(data, 2)); - - // bit 1 ( data & 2 ) triggers irq on the other cpu - m_maincpu->set_input_line(0, (data & 2) ? CLEAR_LINE : ASSERT_LINE); - - // move along - vsnes_in0_w(data); -} - -void vsnes_state::init_vsdual() -{ - // vrom switching is enabled with bit 2 of $4016 - m_maincpu->space(AS_PROGRAM).install_write_handler(0x4016, 0x4016, write8smo_delegate(*this, FUNC(vsnes_state::vsdual_vrom_banking_main))); - m_subcpu->space(AS_PROGRAM).install_write_handler(0x4016, 0x4016, write8smo_delegate(*this, FUNC(vsnes_state::vsdual_vrom_banking_sub))); -} - -//********************************************************************************** -// Vs. Super Mario Bros (Bootleg) - -void vsnes_state::vsnes_bootleg_scanline(int scanline, bool vblank, bool blanked) -{ - // Z80 IRQ is controlled by two factors: - // - bit 6 of current (next) scanline number - // - bit 6 of latched scanline number from Z80 reading $4000 - if (!(m_bootleg_latched_scanline & 0x40)) - { - m_subcpu->set_input_line(INPUT_LINE_IRQ0, ((scanline + 1) & 0x40) ? ASSERT_LINE : CLEAR_LINE); - } -} - -u8 vsnes_state::vsnes_bootleg_ppudata() -{ - // CPU always reads higher CHR ROM banks from $2007, PPU always reads lower ones - m_chr_banks[0]->set_entry(1); - u8 data = m_ppu1->read(0x2007); - m_chr_banks[0]->set_entry(0); - - return data; -} - -void vsnes_state::init_bootleg() -{ - m_bootleg_sound_offset = 0; - m_bootleg_sound_data = 0; - m_bootleg_latched_scanline = 0; - - m_ppu1->set_scanline_callback(*this, FUNC(vsnes_state::vsnes_bootleg_scanline)); - - m_maincpu->space(AS_PROGRAM).install_read_handler(0x2007, 0x2007, read8smo_delegate(*this, FUNC(vsnes_state::vsnes_bootleg_ppudata))); -}