diff --git a/hash/nes.xml b/hash/nes.xml index ab4b629b36e..259d105f25f 100644 --- a/hash/nes.xml +++ b/hash/nes.xml @@ -52630,24 +52630,6 @@ preliminary proto for the PAL version, still running on NTSC systems) or the gfx - - M82 Game Selectable Working Product Display (Euro) - 19?? - <unknown> - - - - - - - - - - - - - - Pro Action Replay (Euro, v1.0) 19?? diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 80c8b7f547e..fa95403625a 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -33405,15 +33405,21 @@ drpcjr // Bung Doctor PC Jr famicom // Nintendo Family Computer (a.k.a. Famicom) famicomo // Nintendo Family Computer (original with RP2A03) famitvc1 // Sharp My Computer Terebi C1 -famitwin // Sharp Famicom Twin System +famitwin // Sharp Twin Famicom fctitler // Sharp Famicom Titler AN-510 fds // Nintendo Family Computer (a.k.a. Famicom) + Disk System add-on gchinatv // Golden China TV Game Centre (Chinese famiclone) -m82 // Nintendo M82 Display Unit -m82p // Nintendo M82 Display Unit PAL nes // Nintendo Entertainment System nespal // Nintendo Entertainment System PAL +@source:nintendo/nes_m8.cpp +nesm8 // Nintendo M8 Game Selectable Working Product Display +nesm8a +nesm8b + +@source:nintendo/nes_m82.cpp +m82 // Nintendo M82 Game Selectable Working Product Display + @source:nintendo/nes_arcade_bl.cpp smb3bl diff --git a/src/mame/nintendo/nes.cpp b/src/mame/nintendo/nes.cpp index c8baea8f901..4af7963d192 100644 --- a/src/mame/nintendo/nes.cpp +++ b/src/mame/nintendo/nes.cpp @@ -129,6 +129,7 @@ void nes_state::famicomo(machine_config &config) n2a03_device &maincpu(N2A03(config.replace(), m_maincpu, NTSC_APU_CLOCK)); maincpu.set_addrmap(AS_PROGRAM, &nes_state::nes_map); + // sound hardware maincpu.add_route(ALL_OUTPUTS, "mono", 0.90); } @@ -261,7 +262,7 @@ MACHINE_RESET_MEMBER( nes_state, famitvc1 ) void nes_state::famitvc1(machine_config &config) { - famicom(config); + famicomo(config); // has an RP2A03 like the original Famicom MCFG_MACHINE_RESET_OVERRIDE( nes_state, famitvc1 ) @@ -282,7 +283,7 @@ MACHINE_START_MEMBER( nes_state, famitwin ) { setup_disk(m_disk); - // replace the famicom disk ROM with the famicom twin one (until we modernize the floppy drive) + // replace the famicom disk ROM with the twin famicom one (until we modernize the floppy drive) m_maincpu->space(AS_PROGRAM).install_rom(0xe000, 0xffff, memregion("maincpu")->base() + 0xe000); } } @@ -368,19 +369,6 @@ ROM_START( fctitler ) ROM_LOAD( "rp2c0x.pal", 0x00, 0xc0, CRC(48de65dc) SHA1(d10acafc8da9ff479c270ec01180cca61efe62f5) ) ROM_END -ROM_START( m82 ) - ROM_REGION( 0x14000, "maincpu", 0 ) // Main RAM + program banks - // Banks to be mapped at 0xe000? More investigations needed... - ROM_LOAD( "m82_v1_0.bin", 0x10000, 0x4000, CRC(7d56840a) SHA1(cbd2d14fa073273ba58367758f40d67fd8a9106d) ) -ROM_END - -ROM_START( m82p ) - // same as m82 - ROM_REGION( 0x14000, "maincpu", 0 ) // Main RAM + program banks - // Banks to be mapped at 0xe000? More investigations needed... - ROM_LOAD( "m82_v1_0.bin", 0x10000, 0x4000, CRC(7d56840a) SHA1(cbd2d14fa073273ba58367758f40d67fd8a9106d) ) -ROM_END - // see http://www.disgruntleddesigner.com/chrisc/drpcjr/index.html // and http://www.disgruntleddesigner.com/chrisc/drpcjr/DrPCJrMemMap.txt ROM_START( drpcjr ) @@ -427,17 +415,13 @@ ROM_END // Nintendo Entertainment System hardware CONS( 1985, nes, 0, 0, nes, nes, nes_state, empty_init, "Nintendo", "Nintendo Entertainment System / Famicom (NTSC)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE ) CONS( 1987, nespal, nes, 0, nespal, nes, nes_state, empty_init, "Nintendo", "Nintendo Entertainment System (PAL)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE ) -// M82 Display Unit -// supports up to twelve cartridge slots -CONS( 198?, m82, nes, 0, nes, nes, nes_state, empty_init, "Nintendo", "M82 Display Unit (NTSC)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE ) -CONS( 198?, m82p, nes, 0, nespal, nes, nes_state, empty_init, "Nintendo", "M82 Display Unit (PAL)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE ) // Famicom hardware CONS( 1983, famicom, 0, nes, famicom, famicom, nes_state, init_famicom, "Nintendo", "Famicom", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE ) CONS( 1983, famicomo, famicom, 0, famicomo, famicom, nes_state, init_famicom, "Nintendo", "Famicom (earlier, with RP2A03)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE ) CONS( 1983, famitvc1, famicom, 0, famitvc1, famicom, nes_state, init_famicom, "Sharp", "My Computer Terebi C1", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE ) CONS( 1986, fds, famicom, 0, fds, famicom, nes_state, init_famicom, "Nintendo", "Famicom (w/ Disk System add-on)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE ) -CONS( 1986, famitwin, famicom, 0, famitwin, famicom, nes_state, init_famicom, "Sharp", "Famicom Twin", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE ) +CONS( 1986, famitwin, famicom, 0, famitwin, famicom, nes_state, init_famicom, "Sharp", "Twin Famicom", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE ) CONS( 1989, fctitler, famicom, 0, fctitler, famicom, nes_state, init_famicom, "Sharp", "Famicom Titler", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE ) // Clone hardware diff --git a/src/mame/nintendo/nes_m8.cpp b/src/mame/nintendo/nes_m8.cpp new file mode 100644 index 00000000000..166c239cd24 --- /dev/null +++ b/src/mame/nintendo/nes_m8.cpp @@ -0,0 +1,848 @@ +// license:BSD-3-Clause +// copyright-holders:kmg + +/*************************************************************************** + + Nintendo NES M8 Game Selectable Working Product Display + + This was the first store display unit put out by Nintendo of America. + + Internally it contains a near-stock NES main PCB and a NES M8 board. + The NES M8 board connects to the NES via the standard cartridge slot + (by way of a 72-pin cart adapter as the M8 board's edge connector is + 60-pin Famicom-style), and multiplexes 16 pairs of PRG and CHR EPROMs. + The near-stock NES is missing its CIC chip, and an additional wire + runs from the M8 board to the host reset line of the CIC (that is the + M8 board can directly reset the 2A03). + + The M8 board is also connected to the NES M8 LED board. This board + houses the Game Select switch and 16 LEDs, one of which lights up near + the title of the currently active game. The M8 board also has another + connector that goes to a Play Time Limit nob on the back of the unit. + + Three standard NES controller connectors are hidden away in the case, + and things are rewired so that 2 and 3 share the same lines. The M8 + unit was shipped with two joypads on 1 and 2, and a zapper on 3. + + TODO: + - Determine how timer and game select button actually operate. Does the + timer cycle the games like the game select button? Is the timer reset + after game select button is pressed? What happens if the timer nob is + adjusted while the machine is running? Timer chip is an MC1455PI. + +***************************************************************************/ + +#include "emu.h" + +#include "bus/nes_ctrl/ctrl.h" +#include "cpu/m6502/n2a03.h" +#include "video/ppu2c0x.h" + +#include "screen.h" +#include "speaker.h" + + +namespace { + +class m8_state : public driver_device +{ +public: + m8_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_ppu(*this, "ppu") + , m_screen(*this, "screen") + , m_ctrl(*this, "ctrl%u", 1U) + , m_dsw(*this, "DSW%u", 0U) + , m_s1(*this, "S1") + , m_nt_page(*this, "nt_page%u", 0U) + , m_prg(*this, "prg%u", 0U) + , m_chr(*this, "chr%u", 0U) + , m_prg_bank(*this, "prg_bank") + , m_chr_bank(*this, "chr_bank") + { + } + + void nes_m8(machine_config &config); + DECLARE_INPUT_CHANGED_MEMBER(m8_dsw_changed); + DECLARE_INPUT_CHANGED_MEMBER(m8_game_select); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + +private: + required_device m_maincpu; + required_device m_ppu; + required_device m_screen; + optional_device_array m_ctrl; + + required_ioport_array<4> m_dsw; + required_ioport m_s1; + + required_memory_bank_array<4> m_nt_page; + std::unique_ptr m_nt_ram; + + required_memory_region_array<16> m_prg; + required_memory_region_array<16> m_chr; + required_memory_bank m_prg_bank; + required_memory_bank m_chr_bank; + + u8 m_curr_game = 0; + u16 m_time_limit = 0; + emu_timer* m_play_timer = nullptr; + + TIMER_CALLBACK_MEMBER(m8_play_timer_cb); + u8 m8_in0_r(); + u8 m8_in1_r(); + void m8_in0_w(u8 data); + void m8_set_mirroring(); + void m8_romswitch(); + void m8_reset(); + void m8_map(address_map &map); + void m8_ppu_map(address_map &map); +}; + + +INPUT_CHANGED_MEMBER(m8_state::m8_dsw_changed) +{ + m8_set_mirroring(); +} + +INPUT_CHANGED_MEMBER(m8_state::m8_game_select) +{ + if (newval) + m8_reset(); +} + +u8 m8_state::m8_in0_r() +{ + u8 ret = 0x40; + + ret |= m_ctrl[0]->read_bit0(); + ret |= m_ctrl[0]->read_bit34(); + + return ret; +} + +u8 m8_state::m8_in1_r() +{ + u8 ret = 0x40; + + // both 2nd and 3rd controllers are tied to $4017 + ret |= m_ctrl[1]->read_bit0(); + ret |= m_ctrl[1]->read_bit34(); + ret |= m_ctrl[2]->read_bit0(); + ret |= m_ctrl[2]->read_bit34(); + + return ret; +} + +void m8_state::m8_in0_w(u8 data) +{ + for (auto &ctrl : m_ctrl) + ctrl->write(data); +} + + +/**************************************************************************/ + +void m8_state::m8_set_mirroring() +{ + // set nametable mirroring directly from DSW + int dip = m_curr_game / 4; + int sw = m_curr_game & 3; + int bit = BIT(m_dsw[dip]->read(), sw); + for (int i = 0; i < 4; i++) + m_nt_page[i]->set_entry(BIT(i, bit)); +} + +void m8_state::m8_romswitch() +{ + m_prg_bank->set_entry(m_curr_game); + m_chr_bank->set_entry(m_curr_game); + m8_set_mirroring(); +} + +void m8_state::m8_reset() +{ + m_play_timer->adjust(attotime::from_seconds(m_time_limit)); + m_curr_game = (m_curr_game + 1) & 0x0f; + m8_romswitch(); + m_maincpu->reset(); +} + +TIMER_CALLBACK_MEMBER(m8_state::m8_play_timer_cb) +{ + m8_reset(); +} + +/*************************************************************************** + + Memory map + +***************************************************************************/ + +void m8_state::m8_map(address_map &map) +{ + map(0x0000, 0x07ff).mirror(0x1800).ram(); + map(0x2000, 0x3fff).rw(m_ppu, FUNC(ppu2c0x_device::read), FUNC(ppu2c0x_device::write)); + map(0x4014, 0x4014).lw8(NAME([this] (address_space &space, u8 data) { m_ppu->spriteram_dma(space, data); })); + map(0x4016, 0x4016).rw(FUNC(m8_state::m8_in0_r), FUNC(m8_state::m8_in0_w)); // IN0 - input port 1 + map(0x4017, 0x4017).r(FUNC(m8_state::m8_in1_r)); // IN1 - input port 2 / PSG second control register + + map(0x8000, 0xffff).bankr(m_prg_bank); +} + +void m8_state::m8_ppu_map(address_map &map) +{ + map(0x0000, 0x1fff).bankr(m_chr_bank); + map(0x2000, 0x23ff).mirror(0x1000).bankrw(m_nt_page[0]); + map(0x2400, 0x27ff).mirror(0x1000).bankrw(m_nt_page[1]); + map(0x2800, 0x2bff).mirror(0x1000).bankrw(m_nt_page[2]); + map(0x2c00, 0x2fff).mirror(0x1000).bankrw(m_nt_page[3]); + map(0x3f00, 0x3fff).rw(m_ppu, FUNC(ppu2c0x_device::palette_read), FUNC(ppu2c0x_device::palette_write)); +} + + + +static INPUT_PORTS_START( m8_base ) + PORT_START("P3") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Game Select") PORT_CODE( KEYCODE_0 ) PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_game_select, 0) + + PORT_START("S1") + PORT_CONFNAME( 0x0f, 0x08, "Play Time Limit" ) + PORT_CONFSETTING( 0x01, "20 sec." ) + PORT_CONFSETTING( 0x02, "3 min." ) + PORT_CONFSETTING( 0x04, "6 min." ) + PORT_CONFSETTING( 0x08, "25 min." ) +INPUT_PORTS_END + +static INPUT_PORTS_START( nes_m8 ) + PORT_INCLUDE( m8_base ) + + PORT_START("DSW0") + PORT_DIPNAME( 0x01, 0x00, "Splash Screen Mirroring" ) PORT_DIPLOCATION("DS1:1") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x01, "V" ) + PORT_DIPNAME( 0x02, 0x00, "Duck Hunt Mirroring" ) PORT_DIPLOCATION("DS1:2") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x02, "V" ) + PORT_DIPNAME( 0x04, 0x00, "Hogan's Alley Mirroring" ) PORT_DIPLOCATION("DS1:3") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x04, "V" ) + PORT_DIPNAME( 0x08, 0x00, "Wild Gunman Mirroring" ) PORT_DIPLOCATION("DS1:4") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x08, "V" ) + + PORT_START("DSW1") + PORT_DIPNAME( 0x01, 0x01, "Balloon Fight Mirroring" ) PORT_DIPLOCATION("DS2:1") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x01, "V" ) + PORT_DIPNAME( 0x02, 0x02, "Ice Climber Mirroring" ) PORT_DIPLOCATION("DS2:2") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x02, "V" ) + PORT_DIPNAME( 0x04, 0x00, "Kung Fu Mirroring" ) PORT_DIPLOCATION("DS2:3") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x04, "V" ) + PORT_DIPNAME( 0x08, 0x08, "Pinball Mirroring" ) PORT_DIPLOCATION("DS2:4") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x08, "V" ) + + PORT_START("DSW2") + PORT_DIPNAME( 0x01, 0x00, "Super Mario Bros. Mirroring" ) PORT_DIPLOCATION("DS3:1") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x01, "V" ) + PORT_DIPNAME( 0x02, 0x02, "Baseball Mirroring" ) PORT_DIPLOCATION("DS3:2") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x02, "V" ) + PORT_DIPNAME( 0x04, 0x04, "Golf Mirroring" ) PORT_DIPLOCATION("DS3:3") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x04, "V" ) + PORT_DIPNAME( 0x08, 0x08, "Tennis Mirroring" ) PORT_DIPLOCATION("DS3:4") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x08, "V" ) + + PORT_START("DSW3") + PORT_DIPNAME( 0x01, 0x00, "Excitebike Mirroring" ) PORT_DIPLOCATION("DS4:1") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x01, "V" ) + PORT_DIPNAME( 0x02, 0x00, "Mach Rider Mirroring" ) PORT_DIPLOCATION("DS4:2") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x02, "V" ) + PORT_DIPNAME( 0x04, 0x04, "Wrecking Crew Mirroring" ) PORT_DIPLOCATION("DS4:3") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x04, "V" ) + PORT_DIPNAME( 0x08, 0x08, "Popeye Mirroring" ) PORT_DIPLOCATION("DS4:4") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x08, "V" ) +INPUT_PORTS_END + +static INPUT_PORTS_START( nes_m8a ) + PORT_INCLUDE( m8_base ) + + PORT_START("DSW0") + PORT_DIPNAME( 0x01, 0x00, "Tennis Mirroring" ) PORT_DIPLOCATION("DS1:1") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x01, "V" ) + PORT_DIPNAME( 0x02, 0x02, "Baseball Mirroring" ) PORT_DIPLOCATION("DS1:2") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x02, "V" ) + PORT_DIPNAME( 0x04, 0x00, "Soccer Mirroring" ) PORT_DIPLOCATION("DS1:3") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x04, "V" ) + PORT_DIPNAME( 0x08, 0x08, "Golf Mirroring" ) PORT_DIPLOCATION("DS1:4") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x08, "V" ) + + PORT_START("DSW1") + PORT_DIPNAME( 0x01, 0x00, "Donkey Kong Jr. Math Mirroring" ) PORT_DIPLOCATION("DS2:1") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x01, "V" ) + PORT_DIPNAME( 0x02, 0x00, "Wild Gunman Mirroring" ) PORT_DIPLOCATION("DS2:2") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x02, "V" ) + PORT_DIPNAME( 0x04, 0x00, "Hogan's Alley Mirroring" ) PORT_DIPLOCATION("DS2:3") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x04, "V" ) + PORT_DIPNAME( 0x08, 0x00, "Duck Hunt Mirroring" ) PORT_DIPLOCATION("DS2:4") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x08, "V" ) + + PORT_START("DSW2") + PORT_DIPNAME( 0x01, 0x01, "Wrecking Crew Mirroring" ) PORT_DIPLOCATION("DS3:1") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x01, "V" ) + PORT_DIPNAME( 0x02, 0x00, "Excitebike Mirroring" ) PORT_DIPLOCATION("DS3:2") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x02, "V" ) + PORT_DIPNAME( 0x04, 0x00, "Kung Fu Mirroring" ) PORT_DIPLOCATION("DS3:3") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x04, "V" ) + PORT_DIPNAME( 0x08, 0x00, "Super Mario Bros. Mirroring" ) PORT_DIPLOCATION("DS3:4") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x08, "V" ) + + PORT_START("DSW3") + PORT_DIPNAME( 0x01, 0x01, "Ice Climber Mirroring" ) PORT_DIPLOCATION("DS4:1") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x01, "V" ) + PORT_DIPNAME( 0x02, 0x02, "Pinball Mirroring" ) PORT_DIPLOCATION("DS4:2") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x02, "V" ) + PORT_DIPNAME( 0x04, 0x04, "Clu Clu Land Mirroring" ) PORT_DIPLOCATION("DS4:3") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x04, "V" ) + PORT_DIPNAME( 0x08, 0x00, "Splash Screen Mirroring" ) PORT_DIPLOCATION("DS1:1") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x08, "V" ) +INPUT_PORTS_END + +static INPUT_PORTS_START( nes_m8b ) + PORT_INCLUDE( m8_base ) + + PORT_START("DSW0") + PORT_DIPNAME( 0x01, 0x00, "Tennis Mirroring" ) PORT_DIPLOCATION("DS1:1") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x01, "V" ) + PORT_DIPNAME( 0x02, 0x02, "Baseball Mirroring" ) PORT_DIPLOCATION("DS1:2") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x02, "V" ) + PORT_DIPNAME( 0x04, 0x00, "Soccer Mirroring" ) PORT_DIPLOCATION("DS1:3") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x04, "V" ) + PORT_DIPNAME( 0x08, 0x08, "10-Yard Fight Mirroring" ) PORT_DIPLOCATION("DS1:4") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x08, "V" ) + + PORT_START("DSW1") + PORT_DIPNAME( 0x01, 0x01, "Golf Mirroring" ) PORT_DIPLOCATION("DS2:1") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x01, "V" ) + PORT_DIPNAME( 0x02, 0x00, "Wild Gunman Mirroring" ) PORT_DIPLOCATION("DS2:2") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x02, "V" ) + PORT_DIPNAME( 0x04, 0x00, "Hogan's Alley Mirroring" ) PORT_DIPLOCATION("DS2:3") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x04, "V" ) + PORT_DIPNAME( 0x08, 0x00, "Duck Hunt Mirroring" ) PORT_DIPLOCATION("DS2:4") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x08, "V" ) + + PORT_START("DSW2") + PORT_DIPNAME( 0x01, 0x01, "Wrecking Crew Mirroring" ) PORT_DIPLOCATION("DS3:1") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x01, "V" ) + PORT_DIPNAME( 0x02, 0x00, "Excitebike Mirroring" ) PORT_DIPLOCATION("DS3:2") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x02, "V" ) + PORT_DIPNAME( 0x04, 0x00, "Kung Fu Mirroring" ) PORT_DIPLOCATION("DS3:3") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x04, "V" ) + PORT_DIPNAME( 0x08, 0x00, "Super Mario Bros. Mirroring" ) PORT_DIPLOCATION("DS3:4") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x08, "V" ) + + PORT_START("DSW3") + PORT_DIPNAME( 0x01, 0x01, "Ice Climber Mirroring" ) PORT_DIPLOCATION("DS4:1") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x01, "V" ) + PORT_DIPNAME( 0x02, 0x02, "Pinball Mirroring" ) PORT_DIPLOCATION("DS4:2") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x02, "V" ) + PORT_DIPNAME( 0x04, 0x04, "Clu Clu Land Mirroring" ) PORT_DIPLOCATION("DS4:3") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x04, "V" ) + PORT_DIPNAME( 0x08, 0x08, "Stack Up Mirroring" ) PORT_DIPLOCATION("DS4:4") PORT_CHANGED_MEMBER(DEVICE_SELF, m8_state, m8_dsw_changed, 0) + PORT_DIPSETTING( 0x00, "H" ) + PORT_DIPSETTING( 0x08, "V" ) +INPUT_PORTS_END + + + +void m8_state::machine_start() +{ + m_nt_ram = std::make_unique(0x800); + + for (auto &page : m_nt_page) + page->configure_entries(0, 2, m_nt_ram.get(), 0x400); + + for (int i = 0; i < 16; i++) + { + m_prg_bank->configure_entry(i, m_prg[i]->base()); + m_chr_bank->configure_entry(i, m_chr[i]->base()); + } + + m_play_timer = timer_alloc(FUNC(m8_state::m8_play_timer_cb), this); + + save_item(NAME(m_curr_game)); + save_item(NAME(m_time_limit)); + save_pointer(NAME(m_nt_ram), 0x800); +} + +void m8_state::machine_reset() +{ + switch (m_s1->read()) + { + case 1: m_time_limit = 20; break; + case 2: m_time_limit = 3 * 60; break; + case 4: m_time_limit = 6 * 60; break; + case 8: m_time_limit = 25 * 60; break; + } + + m_curr_game = 0xf; + m8_reset(); +} + + +void m8_state::nes_m8(machine_config &config) +{ + // basic machine hardware + N2A03G(config, m_maincpu, NTSC_APU_CLOCK); // actual model is RP2A03E + m_maincpu->set_addrmap(AS_PROGRAM, &m8_state::m8_map); + + // video hardware + SCREEN(config, m_screen, SCREEN_TYPE_RASTER); + m_screen->set_raw(N2A03_NTSC_XTAL / 4, 341, 0, VISIBLE_SCREEN_WIDTH, ppu2c0x_device::NTSC_SCANLINES_PER_FRAME, 0, VISIBLE_SCREEN_HEIGHT); + m_screen->set_screen_update(m_ppu, FUNC(ppu2c0x_device::screen_update)); + + PPU_2C02(config, m_ppu); + m_ppu->set_addrmap(0, &m8_state::m8_ppu_map); + m_ppu->set_cpu_tag(m_maincpu); + m_ppu->int_callback().set_inputline(m_maincpu, INPUT_LINE_NMI); + + // sound hardware + SPEAKER(config, "mono").front_center(); + m_maincpu->add_route(ALL_OUTPUTS, "mono", 0.50); + + NES_CONTROL_PORT(config, m_ctrl[0], famibox_control_port12_devices, "joypad").set_screen_tag(m_screen); + NES_CONTROL_PORT(config, m_ctrl[1], famibox_control_port12_devices, "joypad").set_screen_tag(m_screen); + NES_CONTROL_PORT(config, m_ctrl[2], famibox_control_port12_devices, "zapper").set_screen_tag(m_screen); +} + + + +ROM_START( nesm8 ) + // M8 splash screen and instructions + ROM_REGION( 0x8000, "prg0", 0 ) + ROM_LOAD( "m8-prg-2 h.u1", 0x0000, 0x4000, CRC(15a0d398) SHA1(3601ee85d568271a1ebaae058191b092a8dcbcdc) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr0", 0 ) + ROM_LOAD( "m8-chr h.u29", 0x0000, 0x2000, CRC(7a7ad128) SHA1(a22be640cf04a6fdd9ec3b291b33d10ecbee0ef8) ) + + // Duck Hunt + ROM_REGION( 0x8000, "prg1", 0 ) + ROM_LOAD( "dh-prg h.u2", 0x0000, 0x4000, CRC(90ca616d) SHA1(b742576317cd6a04caac25252d5593844c9a0bb6) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr1", 0 ) + ROM_LOAD( "dh-chr h.u30", 0x0000, 0x2000, CRC(4e049e03) SHA1(ffad32a3bab2fb3826bc554b1b9838e837513576) ) + + // Hogan's Alley + ROM_REGION( 0x8000, "prg2", 0 ) + ROM_LOAD( "ha-prg h.u3", 0x0000, 0x4000, CRC(8963ae6e) SHA1(bca489ed0fb58e1e99f36c427bc0d7d805b6c61a) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr2", 0 ) + ROM_LOAD( "ha-chr h.u31", 0x0000, 0x2000, CRC(5df42fc4) SHA1(4fcf23151d9f11c1ef1b1007dd8058f5d5fe9ab8) ) + + // Wild Gunman + ROM_REGION( 0x8000, "prg3", 0 ) + ROM_LOAD( "wg-prg h.u4", 0x0000, 0x4000, CRC(389960db) SHA1(6b38f2c86ef27f653a2bdb9c682ac0bc981c7db6) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr3", 0 ) + ROM_LOAD( "wg-chr h.u32", 0x0000, 0x2000, CRC(a5e04856) SHA1(9194d89a34f687742216889cbb3e717a9ae81c92) ) + + // Balloon Fight + ROM_REGION( 0x8000, "prg4", 0 ) + ROM_LOAD( "bf-prg v.u5", 0x0000, 0x4000, CRC(bd2e9025) SHA1(6742fa2ea498e5b73dc2024ad3888a64e6b894e4) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr4", 0 ) + ROM_LOAD( "bf-chr v.u33", 0x0000, 0x2000, CRC(c642a1df) SHA1(e73cd3d4c0bad8e6f7a1aa6a580f3817a83756a9) ) + + // Ice Climber + ROM_REGION( 0x8000, "prg5", 0 ) + ROM_LOAD( "ic-prg v.u6", 0x0000, 0x4000, CRC(d548307f) SHA1(e323ebaa2c0be5b9a31a21743ddfe7f3d1580672) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr5", 0 ) + ROM_LOAD( "ic-chr v.u34", 0x0000, 0x2000, CRC(0d58a8b1) SHA1(7ae5f457bb5996a5373c9cf46db3d296e27ec56a) ) + + // Kung Fu + ROM_REGION( 0x8000, "prg6", 0 ) + ROM_LOAD( "sx-prg h.u7", 0x0000, 0x8000, CRC(0516375e) SHA1(55dc3550c6133f8624eb6cf3d2f145e4313c2ff6) ) + + ROM_REGION( 0x2000, "chr6", 0 ) + ROM_LOAD( "sx-chr h.u35", 0x0000, 0x2000, CRC(430b49a4) SHA1(7e618dbff521c3d5ee0f3d8bb01d2e770395a6bc) ) + + // Pinball + ROM_REGION( 0x8000, "prg7", 0 ) + ROM_LOAD( "pn-prg v.u8", 0x0000, 0x4000, CRC(91d33e3c) SHA1(607c5954e5c577ac78db3234987f8fe62f86f068) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr7", 0 ) + ROM_LOAD( "pn-chr v.u36", 0x0000, 0x2000, CRC(f2a53b3d) SHA1(0d2a521fd984c76cbf9b3cbd47e68c6ce4c6eeae) ) + + // Super Mario Bros. + ROM_REGION( 0x8000, "prg8", 0 ) + ROM_LOAD( "sm-prg h.u15", 0x0000, 0x8000, CRC(5cf548d3) SHA1(fefa1097449a3a11ebf8c6199e905996c5dc8fbd) ) + + ROM_REGION( 0x2000, "chr8", 0 ) + ROM_LOAD( "sm-chr h.u40", 0x0000, 0x2000, CRC(867b51ad) SHA1(394badaf0b0bdd0ea279a1bca89a9d9ddc00b1b5) ) + + // Baseball + ROM_REGION( 0x8000, "prg9", 0 ) + ROM_LOAD( "ba-prg v.u16", 0x0000, 0x4000, CRC(39d1fa03) SHA1(28d84cfefa81bbfd3d26e0f70f1b9f53383e54ad) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr9", 0 ) + ROM_LOAD( "ba-chr v.u41", 0x0000, 0x2000, CRC(cde71b82) SHA1(296ccef8a1fd9209f414ce0c788ab0dc95058242) ) + + // Golf + ROM_REGION( 0x8000, "prg10", 0 ) + ROM_LOAD( "gf-prg v.u17", 0x0000, 0x4000, CRC(f9622bfa) SHA1(b4e341a91f614bb19c67cc0205b2443591567aea) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr10", 0 ) + ROM_LOAD( "gf-chr v.u42", 0x0000, 0x2000, CRC(ff6fc790) SHA1(40177839b61f375f2ad03b203328683264845b5b) ) + + // Tennis + ROM_REGION( 0x8000, "prg11", 0 ) + ROM_LOAD( "te-prg h.u18", 0x0000, 0x4000, CRC(8b2e3e81) SHA1(e54274c0b0d651458c5459d41872b1f99904d0fb) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr11", 0 ) + ROM_LOAD( "te-chr h.u43", 0x0000, 0x2000, CRC(3a34c45b) SHA1(2cc26a01c38ead50503dccb3ee929ba7a2b6772c) ) + + // Excitebike + ROM_REGION( 0x8000, "prg12", 0 ) + ROM_LOAD( "eb-prg h.u19", 0x0000, 0x4000, CRC(3a94fa0b) SHA1(6239e91ccefdc017d233cbae388c6568a17ed04b) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr12", 0 ) + ROM_LOAD( "eb-chr h.u44", 0x0000, 0x2000, CRC(e5f72401) SHA1(a8bf028e1a62677e48e88cf421bb2a8051eb800c) ) + + // Mach Rider + ROM_REGION( 0x8000, "prg13", 0 ) + ROM_LOAD( "mr-prg h.u20", 0x0000, 0x8000, CRC(af2bbcbc) SHA1(79b0886c35137b1f31f86e935574c1816a823851) ) + + ROM_REGION( 0x2000, "chr13", 0 ) + ROM_LOAD( "mr-chr h.u45", 0x0000, 0x2000, CRC(33a2b41a) SHA1(671f37bce742e63250296e62c143f8a82f860b04) ) + + // Wrecking Crew + ROM_REGION( 0x8000, "prg14", 0 ) + ROM_LOAD( "wr-prg v.u21", 0x0000, 0x8000, CRC(4328b273) SHA1(764d68f05f4a6e43fb26d7e654e237d2b0258fe4) ) + + ROM_REGION( 0x2000, "chr14", 0 ) + ROM_LOAD( "wr-chr v.u46", 0x0000, 0x2000, CRC(23f0b9fd) SHA1(c7f2d4f5f555490847654b8458687f94fba3bd12) ) + + // Popeye + ROM_REGION( 0x8000, "prg15", 0 ) + ROM_LOAD( "pp-prg v.u22", 0x0000, 0x4000, CRC(0fa63a45) SHA1(50c594a6d8dcbeee2d83bca8c54c42cf57093aba) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr15", 0 ) + ROM_LOAD( "pp-chr v.u47", 0x0000, 0x2000, CRC(a5fd8d98) SHA1(09d229404babb6c89b417ac541bab80fb06d2ba9) ) +ROM_END + +// ROMs, labels, and locations all need confirmed +ROM_START( nesm8a ) + // Tennis + ROM_REGION( 0x8000, "prg0", 0 ) + ROM_LOAD( "te-prg h.u1", 0x0000, 0x4000, CRC(8b2e3e81) SHA1(e54274c0b0d651458c5459d41872b1f99904d0fb) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr0", 0 ) + ROM_LOAD( "te-chr h.u29", 0x0000, 0x2000, CRC(3a34c45b) SHA1(2cc26a01c38ead50503dccb3ee929ba7a2b6772c) ) + + // Baseball + ROM_REGION( 0x8000, "prg1", 0 ) + ROM_LOAD( "ba-prg v.u2", 0x0000, 0x4000, CRC(39d1fa03) SHA1(28d84cfefa81bbfd3d26e0f70f1b9f53383e54ad) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr1", 0 ) + ROM_LOAD( "ba-chr v.u30", 0x0000, 0x2000, CRC(cde71b82) SHA1(296ccef8a1fd9209f414ce0c788ab0dc95058242) ) + + // Soccer + ROM_REGION( 0x8000, "prg2", 0 ) + ROM_LOAD( "sc-prg h.u3", 0x0000, 0x8000, CRC(32e37dcb) SHA1(9d881111634c88218a58e4404848f595824f1c0c) ) + + ROM_REGION( 0x2000, "chr2", 0 ) + ROM_LOAD( "sc-chr h.u31", 0x0000, 0x2000, CRC(307b19ab) SHA1(b35ef4c2cf071db77cec1b4529b43a20cfcce172) ) + + // Golf + ROM_REGION( 0x8000, "prg3", 0 ) + ROM_LOAD( "gf-prg v.u4", 0x0000, 0x4000, CRC(f9622bfa) SHA1(b4e341a91f614bb19c67cc0205b2443591567aea) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr3", 0 ) + ROM_LOAD( "gf-chr v.u32", 0x0000, 0x2000, CRC(ff6fc790) SHA1(40177839b61f375f2ad03b203328683264845b5b) ) + + // Donkey Kong Jr. Math + ROM_REGION( 0x8000, "prg4", 0 ) + ROM_LOAD( "ca-prg h.u5", 0x0000, 0x4000, CRC(66f11648) SHA1(4e243d05d60ee578a720f6fadd6c3ebde305605b) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr4", 0 ) + ROM_LOAD( "ca-chr h.u33", 0x0000, 0x2000, CRC(73329878) SHA1(4c0c87f38af851bd605ccd980fb87ef49dfe98c8) ) + + // Wild Gunman + ROM_REGION( 0x8000, "prg5", 0 ) + ROM_LOAD( "wg-prg h.u6", 0x0000, 0x4000, CRC(389960db) SHA1(6b38f2c86ef27f653a2bdb9c682ac0bc981c7db6) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr5", 0 ) + ROM_LOAD( "wg-chr h.u34", 0x0000, 0x2000, CRC(a5e04856) SHA1(9194d89a34f687742216889cbb3e717a9ae81c92) ) + + // Hogan's Alley + ROM_REGION( 0x8000, "prg6", 0 ) + ROM_LOAD( "ha-prg h.u7", 0x0000, 0x4000, CRC(8963ae6e) SHA1(bca489ed0fb58e1e99f36c427bc0d7d805b6c61a) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr6", 0 ) + ROM_LOAD( "ha-chr h.u35", 0x0000, 0x2000, CRC(5df42fc4) SHA1(4fcf23151d9f11c1ef1b1007dd8058f5d5fe9ab8) ) + + // Duck Hunt + ROM_REGION( 0x8000, "prg7", 0 ) + ROM_LOAD( "dh-prg h.u8", 0x0000, 0x4000, CRC(90ca616d) SHA1(b742576317cd6a04caac25252d5593844c9a0bb6) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr7", 0 ) + ROM_LOAD( "dh-chr h.u36", 0x0000, 0x2000, CRC(4e049e03) SHA1(ffad32a3bab2fb3826bc554b1b9838e837513576) ) + + // Wrecking Crew + ROM_REGION( 0x8000, "prg8", 0 ) + ROM_LOAD( "wr-prg v.u15", 0x0000, 0x8000, CRC(4328b273) SHA1(764d68f05f4a6e43fb26d7e654e237d2b0258fe4) ) + + ROM_REGION( 0x2000, "chr8", 0 ) + ROM_LOAD( "wr-chr v.u40", 0x0000, 0x2000, CRC(23f0b9fd) SHA1(c7f2d4f5f555490847654b8458687f94fba3bd12) ) + + // Excitebike + ROM_REGION( 0x8000, "prg9", 0 ) + ROM_LOAD( "eb-prg h.u16", 0x0000, 0x4000, CRC(3a94fa0b) SHA1(6239e91ccefdc017d233cbae388c6568a17ed04b) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr9", 0 ) + ROM_LOAD( "eb-chr h.u41", 0x0000, 0x2000, CRC(e5f72401) SHA1(a8bf028e1a62677e48e88cf421bb2a8051eb800c) ) + + // Kung Fu + ROM_REGION( 0x8000, "prg10", 0 ) + ROM_LOAD( "sx-prg h.u17", 0x0000, 0x8000, CRC(0516375e) SHA1(55dc3550c6133f8624eb6cf3d2f145e4313c2ff6) ) + + ROM_REGION( 0x2000, "chr10", 0 ) + ROM_LOAD( "sx-chr h.u42", 0x0000, 0x2000, CRC(430b49a4) SHA1(7e618dbff521c3d5ee0f3d8bb01d2e770395a6bc) ) + + // Super Mario Bros. + ROM_REGION( 0x8000, "prg11", 0 ) + ROM_LOAD( "sm-prg h.u18", 0x0000, 0x8000, CRC(5cf548d3) SHA1(fefa1097449a3a11ebf8c6199e905996c5dc8fbd) ) + + ROM_REGION( 0x2000, "chr11", 0 ) + ROM_LOAD( "sm-chr h.u43", 0x0000, 0x2000, CRC(867b51ad) SHA1(394badaf0b0bdd0ea279a1bca89a9d9ddc00b1b5) ) + + // Ice Climber + ROM_REGION( 0x8000, "prg12", 0 ) + ROM_LOAD( "ic-prg v.u19", 0x0000, 0x4000, CRC(d548307f) SHA1(e323ebaa2c0be5b9a31a21743ddfe7f3d1580672) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr12", 0 ) + ROM_LOAD( "ic-chr v.u44", 0x0000, 0x2000, CRC(0d58a8b1) SHA1(7ae5f457bb5996a5373c9cf46db3d296e27ec56a) ) + + // Pinball + ROM_REGION( 0x8000, "prg13", 0 ) + ROM_LOAD( "pn-prg v.u20", 0x0000, 0x4000, CRC(91d33e3c) SHA1(607c5954e5c577ac78db3234987f8fe62f86f068) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr13", 0 ) + ROM_LOAD( "pn-chr v.u45", 0x0000, 0x2000, CRC(f2a53b3d) SHA1(0d2a521fd984c76cbf9b3cbd47e68c6ce4c6eeae) ) + + // Clu Clu Land + ROM_REGION( 0x8000, "prg14", 0 ) + ROM_LOAD( "cl-prg v.u21", 0x0000, 0x4000, CRC(23a60a62) SHA1(36003de2a208bf132f1ecbf7af7efd9095ef85c8) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr14", 0 ) + ROM_LOAD( "cl-chr v.u46", 0x0000, 0x2000, CRC(a63b8b98) SHA1(8ddf97dcc8e28f2218c4a4c8b3d9d527fa0525fb) ) + + // M8 splash screen and instructions + ROM_REGION( 0x8000, "prg15", 0 ) + ROM_LOAD( "m8-prg h.u22", 0x0000, 0x4000, CRC(15a0d398) SHA1(3601ee85d568271a1ebaae058191b092a8dcbcdc) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr15", 0 ) + ROM_LOAD( "m8-chr h.u47", 0x0000, 0x2000, CRC(7a7ad128) SHA1(a22be640cf04a6fdd9ec3b291b33d10ecbee0ef8) ) +ROM_END + +// ROMs, labels, and locations all need confirmed +ROM_START( nesm8b ) + // Tennis + ROM_REGION( 0x8000, "prg0", 0 ) + ROM_LOAD( "te-prg h.u1", 0x0000, 0x4000, CRC(8b2e3e81) SHA1(e54274c0b0d651458c5459d41872b1f99904d0fb) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr0", 0 ) + ROM_LOAD( "te-chr h.u29", 0x0000, 0x2000, CRC(3a34c45b) SHA1(2cc26a01c38ead50503dccb3ee929ba7a2b6772c) ) + + // Baseball + ROM_REGION( 0x8000, "prg1", 0 ) + ROM_LOAD( "ba-prg v.u2", 0x0000, 0x4000, CRC(39d1fa03) SHA1(28d84cfefa81bbfd3d26e0f70f1b9f53383e54ad) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr1", 0 ) + ROM_LOAD( "ba-chr v.u30", 0x0000, 0x2000, CRC(cde71b82) SHA1(296ccef8a1fd9209f414ce0c788ab0dc95058242) ) + + // Soccer + ROM_REGION( 0x8000, "prg2", 0 ) + ROM_LOAD( "sc-prg h.u3", 0x0000, 0x8000, CRC(32e37dcb) SHA1(9d881111634c88218a58e4404848f595824f1c0c) ) + + ROM_REGION( 0x2000, "chr2", 0 ) + ROM_LOAD( "sc-chr h.u31", 0x0000, 0x2000, CRC(307b19ab) SHA1(b35ef4c2cf071db77cec1b4529b43a20cfcce172) ) + + // 10-Yard Fight + ROM_REGION( 0x8000, "prg3", 0 ) + ROM_LOAD( "ty-prg v.u4", 0x0000, 0x8000, CRC(df58fc5a) SHA1(7cc69b39ece2168574599d45ab8452edd4f5a3a1) ) + + ROM_REGION( 0x2000, "chr3", 0 ) + ROM_LOAD( "ty-chr v.u32", 0x0000, 0x2000, CRC(2b8336ee) SHA1(6b40a3b7ad6214abf9c35bcbf89d9c1da06f47a0) ) + + // Golf + ROM_REGION( 0x8000, "prg4", 0 ) + ROM_LOAD( "gf-prg v.u5", 0x0000, 0x4000, CRC(f9622bfa) SHA1(b4e341a91f614bb19c67cc0205b2443591567aea) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr4", 0 ) + ROM_LOAD( "gf-chr v.u33", 0x0000, 0x2000, CRC(ff6fc790) SHA1(40177839b61f375f2ad03b203328683264845b5b) ) + + // Wild Gunman + ROM_REGION( 0x8000, "prg5", 0 ) + ROM_LOAD( "wg-prg h.u6", 0x0000, 0x4000, CRC(389960db) SHA1(6b38f2c86ef27f653a2bdb9c682ac0bc981c7db6) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr5", 0 ) + ROM_LOAD( "wg-chr h.u34", 0x0000, 0x2000, CRC(a5e04856) SHA1(9194d89a34f687742216889cbb3e717a9ae81c92) ) + + // Hogan's Alley + ROM_REGION( 0x8000, "prg6", 0 ) + ROM_LOAD( "ha-prg h.u7", 0x0000, 0x4000, CRC(8963ae6e) SHA1(bca489ed0fb58e1e99f36c427bc0d7d805b6c61a) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr6", 0 ) + ROM_LOAD( "ha-chr h.u35", 0x0000, 0x2000, CRC(5df42fc4) SHA1(4fcf23151d9f11c1ef1b1007dd8058f5d5fe9ab8) ) + + // Duck Hunt + ROM_REGION( 0x8000, "prg7", 0 ) + ROM_LOAD( "dh-prg h.u8", 0x0000, 0x4000, CRC(90ca616d) SHA1(b742576317cd6a04caac25252d5593844c9a0bb6) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr7", 0 ) + ROM_LOAD( "dh-chr h.u36", 0x0000, 0x2000, CRC(4e049e03) SHA1(ffad32a3bab2fb3826bc554b1b9838e837513576) ) + + // Wrecking Crew + ROM_REGION( 0x8000, "prg8", 0 ) + ROM_LOAD( "wr-prg v.u15", 0x0000, 0x8000, CRC(4328b273) SHA1(764d68f05f4a6e43fb26d7e654e237d2b0258fe4) ) + + ROM_REGION( 0x2000, "chr8", 0 ) + ROM_LOAD( "wr-chr v.u40", 0x0000, 0x2000, CRC(23f0b9fd) SHA1(c7f2d4f5f555490847654b8458687f94fba3bd12) ) + + // Excitebike + ROM_REGION( 0x8000, "prg9", 0 ) + ROM_LOAD( "eb-prg h.u16", 0x0000, 0x4000, CRC(3a94fa0b) SHA1(6239e91ccefdc017d233cbae388c6568a17ed04b) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr9", 0 ) + ROM_LOAD( "eb-chr h.u41", 0x0000, 0x2000, CRC(e5f72401) SHA1(a8bf028e1a62677e48e88cf421bb2a8051eb800c) ) + + // Kung Fu + ROM_REGION( 0x8000, "prg10", 0 ) + ROM_LOAD( "sx-prg h.u17", 0x0000, 0x8000, CRC(0516375e) SHA1(55dc3550c6133f8624eb6cf3d2f145e4313c2ff6) ) + + ROM_REGION( 0x2000, "chr10", 0 ) + ROM_LOAD( "sx-chr h.u42", 0x0000, 0x2000, CRC(430b49a4) SHA1(7e618dbff521c3d5ee0f3d8bb01d2e770395a6bc) ) + + // Super Mario Bros. + ROM_REGION( 0x8000, "prg11", 0 ) + ROM_LOAD( "sm-prg h.u18", 0x0000, 0x8000, CRC(5cf548d3) SHA1(fefa1097449a3a11ebf8c6199e905996c5dc8fbd) ) + + ROM_REGION( 0x2000, "chr11", 0 ) + ROM_LOAD( "sm-chr h.u43", 0x0000, 0x2000, CRC(867b51ad) SHA1(394badaf0b0bdd0ea279a1bca89a9d9ddc00b1b5) ) + + // Ice Climber + ROM_REGION( 0x8000, "prg12", 0 ) + ROM_LOAD( "ic-prg v.u19", 0x0000, 0x4000, CRC(d548307f) SHA1(e323ebaa2c0be5b9a31a21743ddfe7f3d1580672) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr12", 0 ) + ROM_LOAD( "ic-chr v.u44", 0x0000, 0x2000, CRC(0d58a8b1) SHA1(7ae5f457bb5996a5373c9cf46db3d296e27ec56a) ) + + // Pinball + ROM_REGION( 0x8000, "prg13", 0 ) + ROM_LOAD( "pn-prg v.u20", 0x0000, 0x4000, CRC(91d33e3c) SHA1(607c5954e5c577ac78db3234987f8fe62f86f068) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr13", 0 ) + ROM_LOAD( "pn-chr v.u45", 0x0000, 0x2000, CRC(f2a53b3d) SHA1(0d2a521fd984c76cbf9b3cbd47e68c6ce4c6eeae) ) + + // Clu Clu Land + ROM_REGION( 0x8000, "prg14", 0 ) + ROM_LOAD( "cl-prg v.u21", 0x0000, 0x4000, CRC(23a60a62) SHA1(36003de2a208bf132f1ecbf7af7efd9095ef85c8) ) + ROM_RELOAD( 0x4000, 0x4000 ) + + ROM_REGION( 0x2000, "chr14", 0 ) + ROM_LOAD( "cl-chr v.u46", 0x0000, 0x2000, CRC(a63b8b98) SHA1(8ddf97dcc8e28f2218c4a4c8b3d9d527fa0525fb) ) + + // Stack Up + ROM_REGION( 0x8000, "prg15", 0 ) + ROM_LOAD( "bl-prg v.u22", 0x0000, 0x8000, CRC(4ee735c1) SHA1(36b6b30f451c3b4a48464bee9a144c873ae04cc7) ) + + ROM_REGION( 0x2000, "chr15", 0 ) + ROM_LOAD( "bl-chr v.u47", 0x0000, 0x2000, CRC(41f4b527) SHA1(49f8dabda7e8585e6961049c46ed913518cd959e) ) +ROM_END + +} // anonymous namespace + + +GAME( 1986, nesm8, 0, nes_m8, nes_m8, m8_state, empty_init, ROT0, "Nintendo", "M8 Game Selectable Working Product Display (US, set 3)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE ) +GAME( 1986, nesm8a, nesm8, nes_m8, nes_m8a, m8_state, empty_init, ROT0, "Nintendo", "M8 Game Selectable Working Product Display (US, set 2)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE ) +GAME( 1986, nesm8b, nesm8, nes_m8, nes_m8b, m8_state, empty_init, ROT0, "Nintendo", "M8 Game Selectable Working Product Display (US, set 1)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/nintendo/nes_m82.cpp b/src/mame/nintendo/nes_m82.cpp new file mode 100644 index 00000000000..7346a4b587f --- /dev/null +++ b/src/mame/nintendo/nes_m82.cpp @@ -0,0 +1,235 @@ +// license:BSD-3-Clause +// copyright-holders:kmg + +/*************************************************************************** + + Nintendo NES M82 Game Selectable Working Product Display + + Emulation is incomplete. It loads the builtin splash screen ROM but lacks + 12 cartridge slots, timer, game select button, etc. Listen to the nice + little tune in the meantime. It's not the same as M8 and FamicomBox. + + TODO: + - Carts + - Timer + - Game Select + - PAL version (same internal ROM?) + +***************************************************************************/ + +#include "emu.h" + +#include "bus/nes_ctrl/ctrl.h" +#include "cpu/m6502/n2a03.h" +#include "video/ppu2c0x.h" + +#include "screen.h" +#include "speaker.h" + + +namespace { + +class m82_state : public driver_device +{ +public: + m82_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_ppu(*this, "ppu") + , m_screen(*this, "screen") + , m_ctrl(*this, "ctrl%u", 1U) + , m_cn12(*this, "CN12") + , m_nt_page(*this, "nt_page%u", 0U) + { + } + + void nes_m82(machine_config &config); + DECLARE_INPUT_CHANGED_MEMBER(m82_game_select); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + +private: + required_device m_maincpu; + required_device m_ppu; + required_device m_screen; + optional_device_array m_ctrl; + + required_ioport m_cn12; + + required_memory_bank_array<4> m_nt_page; + std::unique_ptr m_nt_ram; + + u8 m_curr_slot = 0; + u16 m_time_limit = 0; + emu_timer* m_play_timer = nullptr; + + TIMER_CALLBACK_MEMBER(m82_play_timer_cb); + u8 m82_in0_r(); + u8 m82_in1_r(); + void m82_in0_w(u8 data); + void m82_map(address_map &map); + void m82_ppu_map(address_map &map); +}; + + +INPUT_CHANGED_MEMBER(m82_state::m82_game_select) +{ + if (newval) + { + } +} + +// TODO: Connectors 1/2 are P1 and 3/4/5 are P2? Space between them on board implies this. +u8 m82_state::m82_in0_r() +{ + u8 ret = 0x40; + + ret |= m_ctrl[0]->read_bit0(); + ret |= m_ctrl[0]->read_bit34(); + ret |= m_ctrl[1]->read_bit0(); + ret |= m_ctrl[1]->read_bit34(); + + return ret; +} + +u8 m82_state::m82_in1_r() +{ + u8 ret = 0x40; + + ret |= m_ctrl[2]->read_bit0(); + ret |= m_ctrl[2]->read_bit34(); + ret |= m_ctrl[3]->read_bit0(); + ret |= m_ctrl[3]->read_bit34(); + ret |= m_ctrl[4]->read_bit0(); + ret |= m_ctrl[4]->read_bit34(); + + return ret; +} + +void m82_state::m82_in0_w(u8 data) +{ + for (auto &ctrl : m_ctrl) + ctrl->write(data); +} + + +/**************************************************************************/ + +TIMER_CALLBACK_MEMBER(m82_state::m82_play_timer_cb) +{ +} + +/*************************************************************************** + + Memory map + +***************************************************************************/ + +void m82_state::m82_map(address_map &map) +{ + map(0x0000, 0x07ff).mirror(0x1800).ram(); + map(0x2000, 0x3fff).rw(m_ppu, FUNC(ppu2c0x_device::read), FUNC(ppu2c0x_device::write)); + map(0x4014, 0x4014).lw8(NAME([this] (address_space &space, u8 data) { m_ppu->spriteram_dma(space, data); })); + map(0x4016, 0x4016).rw(FUNC(m82_state::m82_in0_r), FUNC(m82_state::m82_in0_w)); // IN0 - input port 1 + map(0x4017, 0x4017).r(FUNC(m82_state::m82_in1_r)); // IN1 - input port 2 / PSG second control register + + map(0x8000, 0xffff).rom(); // TODO: cart PRG muxed here +} + +void m82_state::m82_ppu_map(address_map &map) +{ + map(0x0000, 0x1fff).rom(); // TODO: cart CHR muxed here + map(0x2000, 0x23ff).mirror(0x1000).bankrw(m_nt_page[0]); + map(0x2400, 0x27ff).mirror(0x1000).bankrw(m_nt_page[1]); + map(0x2800, 0x2bff).mirror(0x1000).bankrw(m_nt_page[2]); + map(0x2c00, 0x2fff).mirror(0x1000).bankrw(m_nt_page[3]); + map(0x3f00, 0x3fff).rw(m_ppu, FUNC(ppu2c0x_device::palette_read), FUNC(ppu2c0x_device::palette_write)); +} + + + +static INPUT_PORTS_START( nes_m82 ) + PORT_START("CN13") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Game Select") PORT_CODE( KEYCODE_0 ) PORT_CHANGED_MEMBER(DEVICE_SELF, m82_state, m82_game_select, 0) + + PORT_START("CN12") + PORT_CONFNAME( 0x0f, 0x08, "Play Time Limit" ) + PORT_CONFSETTING( 0x01, "30 sec." ) + PORT_CONFSETTING( 0x02, "3 min." ) + PORT_CONFSETTING( 0x04, "6 min." ) + PORT_CONFSETTING( 0x08, "128 min." ) +INPUT_PORTS_END + + + +void m82_state::machine_start() +{ + m_nt_ram = std::make_unique(0x800); + + for (auto &page : m_nt_page) + page->configure_entries(0, 2, m_nt_ram.get(), 0x400); + + // vertical mirroring. TODO: replace this with proper code + m_nt_page[1]->set_entry(1); + m_nt_page[3]->set_entry(1); + + m_play_timer = timer_alloc(FUNC(m82_state::m82_play_timer_cb), this); +} + +void m82_state::machine_reset() +{ + switch (m_cn12->read()) + { + case 1: m_time_limit = 30; break; + case 2: m_time_limit = 3 * 60; break; + case 4: m_time_limit = 6 * 60; break; + case 8: m_time_limit = 128 * 60; break; + } + + m_curr_slot = 0; +} + + +void m82_state::nes_m82(machine_config &config) +{ + // basic machine hardware + N2A03G(config, m_maincpu, NTSC_APU_CLOCK); + m_maincpu->set_addrmap(AS_PROGRAM, &m82_state::m82_map); + + // video hardware + SCREEN(config, m_screen, SCREEN_TYPE_RASTER); + m_screen->set_raw(N2A03_NTSC_XTAL / 4, 341, 0, VISIBLE_SCREEN_WIDTH, ppu2c0x_device::NTSC_SCANLINES_PER_FRAME, 0, VISIBLE_SCREEN_HEIGHT); + m_screen->set_screen_update(m_ppu, FUNC(ppu2c0x_device::screen_update)); + + PPU_2C02(config, m_ppu); + m_ppu->set_addrmap(0, &m82_state::m82_ppu_map); + m_ppu->set_cpu_tag(m_maincpu); + m_ppu->int_callback().set_inputline(m_maincpu, INPUT_LINE_NMI); + + // sound hardware + SPEAKER(config, "mono").front_center(); + m_maincpu->add_route(ALL_OUTPUTS, "mono", 0.50); + + NES_CONTROL_PORT(config, m_ctrl[0], famibox_control_port12_devices, "joypad").set_screen_tag(m_screen); + NES_CONTROL_PORT(config, m_ctrl[1], famibox_control_port12_devices, nullptr).set_screen_tag(m_screen); + NES_CONTROL_PORT(config, m_ctrl[2], famibox_control_port12_devices, "joypad").set_screen_tag(m_screen); + NES_CONTROL_PORT(config, m_ctrl[3], famibox_control_port12_devices, nullptr).set_screen_tag(m_screen); + NES_CONTROL_PORT(config, m_ctrl[4], famibox_control_port12_devices, "zapper").set_screen_tag(m_screen); +} + + + +ROM_START( m82 ) + ROM_REGION( 0x10000, "maincpu", 0 ) + ROM_LOAD( "m82-prg v.1.0.ic31", 0xc000, 0x4000, CRC(7d56840a) SHA1(cbd2d14fa073273ba58367758f40d67fd8a9106d) ) + + ROM_REGION( 0x2000, "ppu", 0 ) + ROM_LOAD( "m82-chr v.1.0.ic26", 0x0000, 0x2000, CRC(8e19c2b1) SHA1(1d9a34a8eadf1a6c4806d0da96f1ab690389cbd7) ) +ROM_END + +} // anonymous namespace + + +GAME( 1986, m82, 0, nes_m82, nes_m82, m82_state, empty_init, ROT0, "Nintendo", "M82 Game Selectable Working Product Display", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING )