vsnes.cpp: Various fixes and cleanups. (#9265)

- Fixed size and mirroring of RAM. Correctly share shared RAM only. Shared RAM is also now properly NVRAM (Wrecking Crew saves high scores, etc).
- Removed spurious "extra RAM" installed in a couple spots.
- Added coin read/write address mirroring.
- Renamed "mapper 68" to Sunsoft-3, the chip on Platoon's board. Fixed its write masking.
- Implemented proper strobe behavior for joystick read/writes.
- Removed now unnecessary lightgun-specific read function and unused variables.
This commit is contained in:
0kmg 2022-02-04 17:44:45 -09:00 committed by GitHub
parent da9bf2ddb0
commit fff6c5e9fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 128 deletions

View File

@ -198,24 +198,25 @@ void vsnes_state::vsnes_coin_counter_1_w(uint8_t data)
void vsnes_state::vsnes_cpu1_map(address_map &map)
{
map(0x0000, 0x07ff).mirror(0x1800).ram().share("work_ram");
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_0_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, 0x4020).rw(FUNC(vsnes_state::vsnes_coin_counter_r), FUNC(vsnes_state::vsnes_coin_counter_w));
map(0x6000, 0x7fff).ram();
map(0x4020, 0x4020).mirror(0x1fdf).rw(FUNC(vsnes_state::vsnes_coin_counter_r), FUNC(vsnes_state::vsnes_coin_counter_w));
map(0x6000, 0x67ff).mirror(0x1800).ram().share("nvram");
map(0x8000, 0xffff).rom();
}
void vsnes_state::vsnes_cpu2_map(address_map &map)
{
map(0x0000, 0x07ff).mirror(0x1800).ram().share("work_ram_1");
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_1_w));
map(0x4016, 0x4016).rw(FUNC(vsnes_state::vsnes_in0_1_r), FUNC(vsnes_state::vsnes_in0_1_w));
map(0x4017, 0x4017).r(FUNC(vsnes_state::vsnes_in1_1_r)); /* IN1 - input port 2 / PSG second control register */
map(0x4020, 0x4020).w(FUNC(vsnes_state::vsnes_coin_counter_1_w));
map(0x4020, 0x4020).mirror(0x1fdf).w(FUNC(vsnes_state::vsnes_coin_counter_1_w));
map(0x6000, 0x67ff).mirror(0x1800).ram().share("nvram");
map(0x8000, 0xffff).rom();
}
@ -273,13 +274,13 @@ 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)
{
map(0x0000, 0x07ff).mirror(0x1800).ram().share("work_ram");
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(0x6000, 0x7fff).ram();
map(0x6000, 0x67ff).mirror(0x0800).ram();
map(0x8000, 0xffff).rom();
}
@ -299,7 +300,7 @@ void vsnes_state::vsnes_cpu1_bootleg_map(address_map &map)
void vsnes_state::vsnes_bootleg_z80_map(address_map &map)
{
map(0x0000, 0x1fff).rom().region("sub", 0);
map(0x2000, 0x23ff).ram();
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));
@ -470,7 +471,7 @@ static INPUT_PORTS_START( vsnes_zapper )
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // low 6 bits always read 0b010000
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNUSED ) /* sprite hit */
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON1 ) /* gun trigger */
@ -1733,6 +1734,8 @@ void vsnes_state::vsnes(machine_config &config)
MCFG_MACHINE_RESET_OVERRIDE(vsnes_state,vsnes)
MCFG_MACHINE_START_OVERRIDE(vsnes_state,vsnes)
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
/* 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);
@ -1797,11 +1800,13 @@ void vsnes_state::vsdual(machine_config &config)
n2a03_device &subcpu(N2A03(config, m_subcpu, NTSC_APU_CLOCK));
subcpu.set_addrmap(AS_PROGRAM, &vsnes_state::vsnes_cpu2_map);
MCFG_MACHINE_RESET_OVERRIDE(vsnes_state,vsdual)
MCFG_MACHINE_RESET_OVERRIDE(vsnes_state,vsnes)
MCFG_MACHINE_START_OVERRIDE(vsnes_state,vsdual)
config.set_default_layout(layout_dualhsxs);
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
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));

View File

@ -1,6 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:Pierpaolo Prazzoli
#include "machine/nvram.h"
#include "sound/sn76496.h"
#include "video/ppu2c0x.h"
@ -15,8 +16,7 @@ public:
, m_ppu2(*this, "ppu2")
, m_sn1(*this, "sn1")
, m_sn2(*this, "sn2")
, m_work_ram(*this, "work_ram")
, m_work_ram_1(*this, "work_ram_1")
, m_nvram(*this, "nvram")
, m_gfx1_rom(*this, "gfx1")
, m_chr_banks(*this, "chr%u", 0U)
, m_bank_vrom(*this, "vrom%u", 0U)
@ -56,8 +56,7 @@ private:
optional_device<sn76489_device> m_sn1;
optional_device<sn76489_device> m_sn2;
required_shared_ptr<uint8_t> m_work_ram;
optional_shared_ptr<uint8_t> m_work_ram_1;
optional_device<nvram_device> m_nvram;
optional_memory_region m_gfx1_rom;
memory_bank_array_creator<8> m_chr_banks;
@ -73,7 +72,6 @@ private:
void vsnes_in0_1_w(uint8_t data);
uint8_t vsnes_in0_1_r();
uint8_t vsnes_in1_1_r();
uint8_t gun_in0_r();
void vsnormal_vrom_banking(uint8_t data);
void gun_in0_w(uint8_t data);
void vskonami_rom_banking(offs_t offset, uint8_t data);
@ -87,7 +85,7 @@ private:
uint8_t supxevs_read_prot_3_r();
uint8_t supxevs_read_prot_4_r();
uint8_t tko_security_r(offs_t offset);
void mapper68_rom_banking(offs_t offset, uint8_t data);
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);
@ -97,7 +95,6 @@ private:
DECLARE_MACHINE_START(vsnes);
DECLARE_MACHINE_RESET(vsnes);
DECLARE_MACHINE_START(vsdual);
DECLARE_MACHINE_RESET(vsdual);
DECLARE_MACHINE_START(bootleg);
void v_set_videorom_bank( int start, int count, int vrom_start_bank );
@ -115,16 +112,13 @@ private:
int m_coin;
int m_do_vrom_bank;
int m_input_latch[4];
int m_sound_fix;
uint8_t m_last_bank;
int m_input_strobe[2];
std::unique_ptr<uint8_t[]> m_vram;
std::unique_ptr<uint8_t[]> m_extraram;
uint8_t* m_vrom[2];
std::unique_ptr<uint8_t[]> m_nt_ram[2];
memory_bank_array_creator<8> m_bank_vrom;
uint32_t m_vrom_size[2];
int m_vrom_banks;
int m_zapstore;
int m_old_bank;
int m_drmario_shiftreg;
int m_drmario_shiftcount;

View File

@ -33,98 +33,81 @@ Nintendo VS UniSystem and DualSystem - (c) 1984 Nintendo of America
void vsnes_state::vsnes_in0_w(uint8_t data)
{
/* Toggling bit 0 high then low resets both controllers */
if (data & 1)
if (m_input_strobe[0] & ~data & 1)
{
/* load up the latches */
m_input_latch[0] = ioport("IN0")->read();
m_input_latch[1] = ioport("IN1")->read();
}
}
uint8_t vsnes_state::gun_in0_r()
{
int ret = (m_input_latch[0]) & 1;
/* shift */
m_input_latch[0] >>= 1;
ret |= ioport("COINS")->read(); /* merge coins, etc */
ret |= (ioport("DSW0")->read() & 3) << 3; /* merge 2 dipswitches */
/* The gun games expect a 1 returned on every 5th read after sound_fix is reset*/
/* Info Supplied by Ben Parnell <xodnizel@home.com> of FCE Ultra fame */
if (m_sound_fix == 4)
{
ret = 1;
}
m_sound_fix++;
return ret;
m_input_strobe[0] = data;
}
uint8_t vsnes_state::vsnes_in0_r()
{
int ret = (m_input_latch[0]) & 1;
if (m_input_strobe[0] & 1)
m_input_latch[0] = ioport("IN0")->read();
/* shift */
int ret = m_input_latch[0] & 1;
m_input_latch[0] >>= 1;
ret |= ioport("COINS")->read(); /* merge coins, etc */
ret |= (ioport("DSW0")->read() & 3) << 3; /* merge 2 dipswitches */
return ret;
}
uint8_t vsnes_state::vsnes_in1_r()
{
int ret = (m_input_latch[1]) & 1;
if (m_input_strobe[0] & 1)
m_input_latch[1] = ioport("IN1")->read();
int ret = m_input_latch[1] & 1;
m_input_latch[1] >>= 1;
ret |= ioport("DSW0")->read() & ~3; /* merge the rest of the dipswitches */
/* shift */
m_input_latch[1] >>= 1;
return ret;
}
void vsnes_state::vsnes_in0_1_w(uint8_t data)
{
/* Toggling bit 0 high then low resets both controllers */
if (data & 1)
if (m_input_strobe[1] & ~data & 1)
{
/* load up the latches */
m_input_latch[2] = ioport("IN2")->read();
m_input_latch[3] = ioport("IN3")->read();
}
m_input_strobe[1] = data;
}
uint8_t vsnes_state::vsnes_in0_1_r()
{
int ret = (m_input_latch[2]) & 1;
if (m_input_strobe[1] & 1)
m_input_latch[2] = ioport("IN2")->read();
/* shift */
int ret = m_input_latch[2] & 1;
m_input_latch[2] >>= 1;
ret |= ioport("COINS2")->read(); /* merge coins, etc */
ret |= (ioport("DSW1")->read() & 3) << 3; /* merge 2 dipswitches */
return ret;
}
uint8_t vsnes_state::vsnes_in1_1_r()
{
int ret = (m_input_latch[3]) & 1;
if (m_input_strobe[1] & 1)
m_input_latch[3] = ioport("IN3")->read();
int ret = m_input_latch[3] & 1;
m_input_latch[3] >>= 1;
ret |= ioport("DSW1")->read() & ~3; /* merge the rest of the dipswitches */
/* shift */
m_input_latch[3] >>= 1;
return ret;
}
/*************************************
@ -135,24 +118,9 @@ uint8_t vsnes_state::vsnes_in1_1_r()
MACHINE_RESET_MEMBER(vsnes_state,vsnes)
{
m_last_bank = 0xff;
m_sound_fix = 0;
m_input_latch[0] = m_input_latch[1] = 0;
m_input_latch[2] = m_input_latch[3] = 0;
}
/*************************************
*
* Init machine
*
*************************************/
MACHINE_RESET_MEMBER(vsnes_state,vsdual)
{
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;
}
/*************************************
@ -163,8 +131,6 @@ MACHINE_RESET_MEMBER(vsnes_state,vsdual)
void vsnes_state::v_set_videorom_bank(int start, int count, int vrom_start_bank)
{
int i;
assert(start + count <= 8);
vrom_start_bank &= (m_vrom_banks - 1);
@ -172,7 +138,7 @@ void vsnes_state::v_set_videorom_bank(int start, int count, int vrom_start_bank)
/* bank_size_in_kb is used to determine how large the "bank" parameter is */
/* count determines the size of the area mapped */
for (i = 0; i < count; i++)
for (int i = 0; i < count; i++)
{
m_chr_banks[i + start]->set_entry(vrom_start_bank + i);
}
@ -181,7 +147,6 @@ void vsnes_state::v_set_videorom_bank(int start, int count, int vrom_start_bank)
MACHINE_START_MEMBER(vsnes_state,vsnes)
{
address_space &ppu1_space = m_ppu1->space(AS_PROGRAM);
int i;
/* establish nametable ram */
m_nt_ram[0] = std::make_unique<uint8_t[]>(0x1000);
@ -207,7 +172,7 @@ MACHINE_START_MEMBER(vsnes_state,vsnes)
/* DRIVER_INIT is called first - means we can handle this different for VRAM games! */
if (m_vrom[0] != nullptr)
{
for (i = 0; i < 8; i++)
for (int i = 0; i < 8; i++)
{
ppu1_space.install_read_bank(0x0400 * i, 0x0400 * i + 0x03ff, m_chr_banks[i]);
m_chr_banks[i]->configure_entries(0, m_vrom_banks, m_vrom[0], 0x400);
@ -305,7 +270,7 @@ void vsnes_state::gun_in0_w(uint8_t data)
}
/* here we do things a little different */
if (data & 1)
if (m_input_strobe[0] & ~data & 1)
{
/* load up the latches */
m_input_latch[0] = ioport("IN0")->read();
@ -361,19 +326,13 @@ void vsnes_state::gun_in0_w(uint8_t data)
m_input_latch[1] = ioport("IN1")->read();
}
if ((m_zapstore & 1) && (!(data & 1)))
/* reset sound_fix to keep sound from hanging */
{
m_sound_fix = 0;
}
m_zapstore = data;
m_input_strobe[0] = data;
}
void vsnes_state::init_vsgun()
{
/* VROM switching is enabled with bit 2 of $4016 */
m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x4016, 0x4016, read8smo_delegate(*this, FUNC(vsnes_state::gun_in0_r)), write8smo_delegate(*this, FUNC(vsnes_state::gun_in0_w)));
m_maincpu->space(AS_PROGRAM).install_write_handler(0x4016, 0x4016, write8smo_delegate(*this, FUNC(vsnes_state::gun_in0_w)));
m_do_vrom_bank = 1;
}
@ -441,7 +400,7 @@ void vsnes_state::init_vsgshoe()
memcpy (&prg[0x08000], &prg[0x12000], 0x2000);
/* vrom switching is enabled with bit 2 of $4016 */
m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x4016, 0x4016, read8smo_delegate(*this, FUNC(vsnes_state::gun_in0_r)), write8smo_delegate(*this, FUNC(vsnes_state::vsgshoe_gun_in0_w)));
m_maincpu->space(AS_PROGRAM).install_write_handler(0x4016, 0x4016, write8smo_delegate(*this, FUNC(vsnes_state::vsgshoe_gun_in0_w)));
m_do_vrom_bank = 1;
}
@ -629,11 +588,6 @@ void vsnes_state::init_vs108()
// 108 chip at $8000-$9fff
m_maincpu->space(AS_PROGRAM).install_write_handler(0x8000, 0xffff, write8sm_delegate(*this, FUNC(vsnes_state::vs108_rom_banking)));
// extra ram at $6000-$7fff
m_extraram = std::make_unique<uint8_t[]>(0x2000);
save_pointer(NAME(m_extraram.get()), 0x2000);
m_maincpu->space(AS_PROGRAM).install_ram(0x6000, 0x7fff, m_extraram.get());
}
/* Vs. RBI Baseball */
@ -760,7 +714,7 @@ void vsnes_state::init_vsfdf()
{
init_vs108();
m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x4016, 0x4016, read8smo_delegate(*this, FUNC(vsnes_state::gun_in0_r)), write8smo_delegate(*this, FUNC(vsnes_state::gun_in0_w)));
m_maincpu->space(AS_PROGRAM).install_write_handler(0x4016, 0x4016, write8smo_delegate(*this, FUNC(vsnes_state::gun_in0_w)));
m_do_vrom_bank = 0;
}
@ -768,28 +722,18 @@ void vsnes_state::init_vsfdf()
/**********************************************************************************/
/* Platoon rom banking */
void vsnes_state::mapper68_rom_banking(offs_t offset, uint8_t data)
void vsnes_state::sunsoft3_rom_banking(offs_t offset, uint8_t data)
{
switch (offset & 0x7000)
switch (offset & 0x7800)
{
case 0x0000:
v_set_videorom_bank(0, 2, data * 2);
break;
case 0x1000:
v_set_videorom_bank(2, 2, data * 2);
break;
case 0x2000:
v_set_videorom_bank(4, 2, data * 2);
break;
case 0x3000: /* ok? */
v_set_videorom_bank(6, 2, data * 2);
case 0x0800:
case 0x1800:
case 0x2800:
case 0x3800:
v_set_videorom_bank((offset >> 11) & 0x06, 2, data * 2);
break;
case 0x7000:
case 0x7800:
{
uint8_t *prg = memregion("maincpu")->base();
memcpy(&prg[0x08000], &prg[0x10000 + data * 0x4000], 0x4000);
@ -802,14 +746,14 @@ void vsnes_state::mapper68_rom_banking(offs_t offset, uint8_t data)
void vsnes_state::init_platoon()
{
/* when starting a mapper 68 game the first 16K ROM bank in the cart is loaded into $8000
/* when starting a mapper 67 game the first 16K ROM bank in the cart is loaded into $8000
the LAST 16K ROM bank is loaded into $C000. The last 16K of ROM cannot be swapped. */
uint8_t *prg = memregion("maincpu")->base();
memcpy(&prg[0x08000], &prg[0x10000], 0x4000);
memcpy(&prg[0x0c000], &prg[0x2c000], 0x4000);
m_maincpu->space(AS_PROGRAM).install_write_handler(0x8000, 0xffff, write8sm_delegate(*this, FUNC(vsnes_state::mapper68_rom_banking)));
m_maincpu->space(AS_PROGRAM).install_write_handler(0x8000, 0xffff, write8sm_delegate(*this, FUNC(vsnes_state::sunsoft3_rom_banking)));
}
/**********************************************************************************/
@ -832,11 +776,6 @@ 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)));
/* extra ram */
m_extraram = std::make_unique<uint8_t[]>(0x2000);
save_pointer(NAME(m_extraram.get()), 0x2000);
m_maincpu->space(AS_PROGRAM).install_ram(0x6000, 0x7fff, m_extraram.get());
m_ret = 0;
/* normal banking */
@ -872,15 +811,9 @@ void vsnes_state::vsdual_vrom_banking_sub(uint8_t data)
void vsnes_state::init_vsdual()
{
uint8_t *prg = memregion("maincpu")->base();
/* 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)));
/* shared ram at $6000 */
m_maincpu->space(AS_PROGRAM).install_ram(0x6000, 0x7fff, &prg[0x6000]);
m_subcpu->space(AS_PROGRAM).install_ram(0x6000, 0x7fff, &prg[0x6000]);
}
/**********************************************************************************/