diff options
author | 2022-08-11 08:06:13 -0800 | |
---|---|---|
committer | 2022-08-12 02:06:13 +1000 | |
commit | 40137c52eb45875fef5d7d118827d95ca3838e8a (patch) | |
tree | fd4744bb16e6d832ce3c8d3768ae558d921cbdf2 /src | |
parent | dec2c8e8b7fca1246664f302e65274efeae836ee (diff) |
nintendo/vsnes.cpp: A few minor changes. (#10205)
* Added watchdog timer (currently only active on DualSystem games).
* Set perfect quantum for vsmahjng, just like all the other DualSystem games.
* Switched vssoccera from bnglngby's init, which installs a fake IRQ hack, to standard init.
* Switched suprmriobl to empty_init and gave it more consistent function naming.
Diffstat (limited to 'src')
-rw-r--r-- | src/mame/nintendo/vsnes.cpp | 125 |
1 files changed, 62 insertions, 63 deletions
diff --git a/src/mame/nintendo/vsnes.cpp b/src/mame/nintendo/vsnes.cpp index 26bba906bd1..7380b99aca1 100644 --- a/src/mame/nintendo/vsnes.cpp +++ b/src/mame/nintendo/vsnes.cpp @@ -144,6 +144,7 @@ Changes: #include "cpu/m6502/n2a03.h" #include "cpu/z80/z80.h" #include "machine/nvram.h" +#include "machine/watchdog.h" #include "sound/sn76496.h" #include "video/ppu2c0x.h" @@ -166,6 +167,7 @@ protected: , m_ppu2(*this, "ppu2") , m_sensor(*this, "sensor") , m_nvram(*this, "nvram") + , m_watchdog(*this, "watchdog") , m_gfx1_rom(*this, "gfx1") , m_prg_banks(*this, "prg%u", 0U) , m_prg_view(*this, "prg_view") @@ -207,6 +209,7 @@ protected: optional_device<nes_zapper_sensor_device> m_sensor; optional_device<nvram_device> m_nvram; + optional_device<watchdog_timer_device> m_watchdog; optional_memory_region m_gfx1_rom; @@ -301,7 +304,6 @@ public: } void vsdual(machine_config &config); - void vsdual_pi(machine_config &config); void init_vsdual(); protected: @@ -322,21 +324,21 @@ public: } 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); + void smbbl_6502_sn_w(offs_t offset, u8 data); + void smbbl_z80_sn_w(offs_t offset, u8 data); + u8 smbbl_z80_data_r(); + u8 smbbl_z80_address_r(offs_t offset); + void smbbl_scanline_cb(int scanline, bool vblank, bool blanked); + u8 smbbl_ppu_data_r(); + + void smbbl_6502_map(address_map &map); + void smbbl_z80_map(address_map &map); + void smbbl_ppu_map(address_map &map); required_device<sn76489_device> m_sn1; required_device<sn76489_device> m_sn2; @@ -416,6 +418,7 @@ u8 vs_base_state::vsnes_in0_r() ret |= m_coins[Side]->read(); // merge coins, etc ret |= (m_dsw[Side]->read() & 3) << 3; // merge 2 dipswitches + ret |= Side << 7; // CPU indicator bit return ret; } @@ -423,6 +426,11 @@ u8 vs_base_state::vsnes_in0_r() template <u8 Side> u8 vs_base_state::vsnes_in1_r() { + // Only the SUB side CPU can kick the watchdog, which it must do by periodically reading $4017. + // This is one reason UniSystem games too must be installed on the SUB side. + if (m_watchdog && Side == SUB) + m_watchdog->watchdog_reset(); + int p2 = 2 * Side + 1; if (m_input_strobe[Side] & 1) @@ -539,6 +547,8 @@ void vs_dual_state::machine_start() void vs_smbbl_state::machine_start() { + m_ppu1->set_scanline_callback(*this, FUNC(vs_smbbl_state::smbbl_scanline_cb)); + u8 *base = m_gfx1_rom->base(); int entries = m_gfx1_rom->bytes() / 0x2000; m_chr_banks[0]->configure_entries(0, entries, base, 0x2000); @@ -927,7 +937,7 @@ void vs_uni_state::init_bnglngby() } //********************************************************************************** -// VS Dualsystem +// VS DualSystem template <u8 Side> void vs_dual_state::vsdual_vrom_banking(u8 data) @@ -953,18 +963,18 @@ void vs_dual_state::init_vsdual() //********************************************************************************** // Vs. Super Mario Bros (Bootleg) -void vs_smbbl_state::vsnes_bootleg_scanline(int scanline, bool vblank, bool blanked) +void vs_smbbl_state::smbbl_scanline_cb(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)) + if (!BIT(m_bootleg_latched_scanline, 6)) { - m_subcpu->set_input_line(INPUT_LINE_IRQ0, ((scanline + 1) & 0x40) ? ASSERT_LINE : CLEAR_LINE); + m_subcpu->set_input_line(INPUT_LINE_IRQ0, BIT(scanline + 1, 6) ? ASSERT_LINE : CLEAR_LINE); } } -u8 vs_smbbl_state::vsnes_bootleg_ppudata() +u8 vs_smbbl_state::smbbl_ppu_data_r() { // CPU always reads higher CHR ROM banks from $2007, PPU always reads lower ones m_chr_banks[0]->set_entry(1); @@ -974,17 +984,6 @@ u8 vs_smbbl_state::vsnes_bootleg_ppudata() 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))); -} - //****************************************************************************** @@ -1038,7 +1037,7 @@ void vs_base_state::vsnes_ppu2_map(address_map &map) -u8 vs_smbbl_state::vsnes_bootleg_z80_address_r(offs_t offset) +u8 vs_smbbl_state::smbbl_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 @@ -1051,7 +1050,7 @@ u8 vs_smbbl_state::vsnes_bootleg_z80_address_r(offs_t offset) return 0xf0 | m_bootleg_sound_offset; } -void vs_smbbl_state::bootleg_sound_write(offs_t offset, u8 data) +void vs_smbbl_state::smbbl_6502_sn_w(offs_t offset, u8 data) { m_bootleg_sound_offset = offset & 0xf; m_bootleg_sound_data = data; @@ -1059,7 +1058,7 @@ void vs_smbbl_state::bootleg_sound_write(offs_t offset, u8 data) m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); } -u8 vs_smbbl_state::vsnes_bootleg_z80_data_r() +u8 vs_smbbl_state::smbbl_z80_data_r() { //printf("Z80 read data %02x\n", m_bootleg_sound_data); m_bootleg_latched_scanline = m_ppu1->get_current_scanline(); @@ -1069,7 +1068,7 @@ u8 vs_smbbl_state::vsnes_bootleg_z80_data_r() } // A0 = SN #1 enable, A1 = SN #2 enable, A2 = SN write enables (both) on edge -void vs_smbbl_state::vssmbbl_sn_w(offs_t offset, u8 data) +void vs_smbbl_state::smbbl_z80_sn_w(offs_t offset, u8 data) { // printf("sn_w: ofs %x\n", offset & 7); if (!(offset & 4)) @@ -1088,11 +1087,12 @@ void vs_smbbl_state::vssmbbl_sn_w(offs_t offset, u8 data) // the bootleg still makes writes to the PSG addresses, it seems the Z80 should interpret them to play the sounds -void vs_smbbl_state::vsnes_cpu1_bootleg_map(address_map &map) +void vs_smbbl_state::smbbl_6502_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(vs_smbbl_state::bootleg_sound_write)); + map(0x2007, 0x2007).r(FUNC(vs_smbbl_state::smbbl_ppu_data_r)); + map(0x4000, 0x400f).w(FUNC(vs_smbbl_state::smbbl_6502_sn_w)); map(0x4016, 0x4016).rw(FUNC(vs_smbbl_state::vsnes_in0_r<MAIN>), FUNC(vs_smbbl_state::vsnes_in0_w<MAIN>)); map(0x4017, 0x4017).r(FUNC(vs_smbbl_state::vsnes_in1_r<MAIN>)); // IN1 - input port 2 / PSG second control register map(0x4020, 0x4020).w(FUNC(vs_smbbl_state::vsnes_coin_counter_w<MAIN>)); @@ -1113,16 +1113,15 @@ void vs_smbbl_state::vsnes_cpu1_bootleg_map(address_map &map) // x11x xxxx xxxx xxxx = 6502 address (6000) (read) // x11x xxxx xxxx xW21 = SN76489s (6000) (write) -void vs_smbbl_state::vsnes_bootleg_z80_map(address_map &map) +void vs_smbbl_state::smbbl_z80_map(address_map &map) { map(0x0000, 0x1fff).rom().region("sub", 0); - map(0x2000, 0x27ff).ram(); - - 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)); + map(0x2000, 0x27ff).mirror(0x1800).ram(); + map(0x4000, 0x5fff).r(FUNC(vs_smbbl_state::smbbl_z80_data_r)); // read in IRQ & NMI + map(0x6000, 0x7fff).rw(FUNC(vs_smbbl_state::smbbl_z80_address_r), FUNC(vs_smbbl_state::smbbl_z80_sn_w)); } -void vs_smbbl_state::vsnes_ppu_bootleg_map(address_map &map) +void vs_smbbl_state::smbbl_ppu_map(address_map &map) { map(0x0000, 0x1fff).bankr(m_chr_banks[0]); map(0x2000, 0x27ff).mirror(0x1800).ram(); @@ -2573,6 +2572,9 @@ void vs_uni_state::vsnes(machine_config &config) // sound hardware SPEAKER(config, "mono").front_center(); maincpu.add_route(ALL_OUTPUTS, "mono", 0.50); + + // watchdog resets system between 1.23s and 1.33s in hardware tests, exact timing unknown + WATCHDOG_TIMER(config, m_watchdog); // .set_time(attotime::from_msec(1300)); // FIXME: this won't work yet since the UniSystem emulation uses the wrong side of the PCB } void vs_uni_state::jajamaru(machine_config &config) @@ -2625,6 +2627,9 @@ void vs_dual_state::vsdual(machine_config &config) n2a03_device &subcpu(N2A03(config, m_subcpu, NTSC_APU_CLOCK)); subcpu.set_addrmap(AS_PROGRAM, &vs_dual_state::vsnes_cpu2_map); + // need high level of interleave to keep screens in sync in Balloon Fight. + config.set_perfect_quantum(m_maincpu); + config.set_default_layout(layout_dualhsxs); NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); @@ -2654,25 +2659,19 @@ void vs_dual_state::vsdual(machine_config &config) SPEAKER(config, "rspeaker").front_right(); maincpu.add_route(ALL_OUTPUTS, "lspeaker", 0.50); subcpu.add_route(ALL_OUTPUTS, "rspeaker", 0.50); -} -void vs_dual_state::vsdual_pi(machine_config &config) -{ - vsdual(config); - config.set_perfect_quantum(m_maincpu); - // need high level of interleave to keep screens in sync in Balloon Fight. - // however vsmahjng doesn't like perfect interleave? you end up needing to reset it to boot? maybe something in a bad default state? watchdog? - // as the board would always be running in 'perfect interleave' the fact the Mahjong game doesn't work like this needs investigating. + // watchdog resets system between 1.23s and 1.33s in hardware tests, exact timing unknown + WATCHDOG_TIMER(config, m_watchdog).set_time(attotime::from_msec(1300)); } void vs_smbbl_state::vs_smbbl(machine_config &config) { // basic machine hardware M6502(config, m_maincpu, XTAL(16'000'000)/8); - m_maincpu->set_addrmap(AS_PROGRAM, &vs_smbbl_state::vsnes_cpu1_bootleg_map); + m_maincpu->set_addrmap(AS_PROGRAM, &vs_smbbl_state::smbbl_6502_map); Z80(config, m_subcpu, XTAL(16'000'000)/8); // Z8400APS-Z80CPU - m_subcpu->set_addrmap(AS_PROGRAM, &vs_smbbl_state::vsnes_bootleg_z80_map); + m_subcpu->set_addrmap(AS_PROGRAM, &vs_smbbl_state::smbbl_z80_map); // video hardware screen_device &screen1(SCREEN(config, "screen1", SCREEN_TYPE_RASTER)); @@ -2682,7 +2681,7 @@ void vs_smbbl_state::vs_smbbl(machine_config &config) screen1.set_screen_update("ppu1", FUNC(ppu2c0x_device::screen_update)); PPU_2C04C(config, m_ppu1); - m_ppu1->set_addrmap(0, &vs_smbbl_state::vsnes_ppu_bootleg_map); + m_ppu1->set_addrmap(0, &vs_smbbl_state::smbbl_ppu_map); m_ppu1->set_cpu_tag(m_maincpu); m_ppu1->set_screen("screen1"); m_ppu1->int_callback().set_inputline(m_maincpu, INPUT_LINE_NMI); @@ -3678,8 +3677,8 @@ GAME( 1986, rbibb, 0, vsnes, rbibb, vs_uni_state 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( 1986, suprmriobl, suprmrio, vs_smbbl, suprmrio, vs_smbbl_state, empty_init, 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, empty_init, 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 ) @@ -3692,7 +3691,7 @@ GAME( 1984, vspinbal, 0, vsnes, vspinbal, vs_uni_state 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( 1985, vssoccera, vssoccer, vsnes, vssoccer, vs_uni_state, init_vsnormal, 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 ) @@ -3709,14 +3708,14 @@ GAME( 1986, vsgshoe, 0, vsgshoe, vsgshoe, vs_uni_state 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, 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, vstennis, 0, vsdual, vstennis, vs_dual_state, init_vsdual, ROT0, "Nintendo Co., Ltd.", "Vs. Tennis (Japan/USA, set TE A-3)" , 0 ) +GAME( 1984, vstennisa, vstennis, vsdual, vstennis, vs_dual_state, init_vsdual, ROT0, "Nintendo Co., Ltd.", "Vs. Tennis (Japan/USA, set 2)", 0 ) +GAME( 1984, vstennisb, vstennis, vsdual, vstennis, vs_dual_state, init_vsdual, ROT0, "Nintendo Co., Ltd.", "Vs. Tennis (Japan/USA, set 3)", MACHINE_IMPERFECT_GRAPHICS ) +GAME( 1984, wrecking, 0, vsdual, wrecking, vs_dual_state, init_vsdual, ROT0, "Nintendo", "Vs. Wrecking Crew", 0 ) +GAME( 1984, balonfgt, 0, vsdual, 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 ) +GAME( 1984, vsbball, 0, vsdual, vsbball, vs_dual_state, init_vsdual, ROT0, "Nintendo of America", "Vs. Baseball (US, set BA E-1)", 0 ) +GAME( 1984, vsbballj, vsbball, vsdual, vsbballj, vs_dual_state, init_vsdual, ROT0, "Nintendo Co., Ltd.", "Vs. Baseball (Japan, set BA A-3)", 0 ) +GAME( 1984, vsbballja, vsbball, vsdual, vsbballj, vs_dual_state, init_vsdual, ROT0, "Nintendo Co., Ltd.", "Vs. Baseball (Japan, set BA A-2)", 0 ) +GAME( 1984, vsbballjb, vsbball, vsdual, vsbballj, vs_dual_state, init_vsdual, ROT0, "Nintendo Co., Ltd.", "Vs. Baseball (Japan, set BA A-1)", 0 ) +GAME( 1984, iceclmrd, 0, vsdual, iceclmrj, vs_dual_state, init_vsdual, ROT0, "Nintendo", "Vs. Ice Climber Dual (set IC4-4 A-1)", 0 ) |