summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/megadriv_sunplus_hybrid.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/drivers/megadriv_sunplus_hybrid.cpp')
-rw-r--r--src/mame/drivers/megadriv_sunplus_hybrid.cpp177
1 files changed, 177 insertions, 0 deletions
diff --git a/src/mame/drivers/megadriv_sunplus_hybrid.cpp b/src/mame/drivers/megadriv_sunplus_hybrid.cpp
new file mode 100644
index 00000000000..af27f279d46
--- /dev/null
+++ b/src/mame/drivers/megadriv_sunplus_hybrid.cpp
@@ -0,0 +1,177 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+/*
+ This is an enhanced 'Mega Drive / Genesis on a Chip' combined with a SunPlus SPG2xx system for the 'Bonus Games' menu
+
+ It can take MegaDrive cartridges
+
+ The MD side of things doesn't work as it needs enhanced chipset emulation?
+
+ TODO:
+ hook up the SunPlus side again (see spg2xx_zone.cpp for hookup)
+
+*/
+
+#include "emu.h"
+#include "includes/megadriv.h"
+
+class megadriv_sunplus_state : public md_base_state
+{
+public:
+ megadriv_sunplus_state(const machine_config &mconfig, device_type type, const char *tag)
+ // Mega Drive part
+ : md_base_state(mconfig, type, tag),
+ m_md_is_running(true),
+ m_bank(0),
+ m_rom(*this, "maincpu")
+ {}
+
+ // Mega Drive part
+ uint16_t read(offs_t offset);
+ void megadriv_sunplus_pal(machine_config &config);
+ void megadriv_sunplus_map(address_map &map);
+
+ void init_reactmd();
+
+protected:
+ virtual void machine_start() override;
+ virtual void machine_reset() override;
+
+private:
+ bool m_md_is_running;
+
+ // Mega Drive part
+ int m_bank;
+ required_region_ptr<uint16_t> m_rom;
+ uint32_t screen_update_hybrid(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+ DECLARE_WRITE_LINE_MEMBER(screen_vblank_hybrid);
+
+};
+
+
+// todo, use actual MD map, easier once maps are part of base class.
+void megadriv_sunplus_state::megadriv_sunplus_map(address_map &map)
+{
+ map(0x000000, 0x3fffff).r(FUNC(megadriv_sunplus_state::read)); /* Cartridge Program Rom */
+ map(0xa00000, 0xa01fff).rw(FUNC(megadriv_sunplus_state::megadriv_68k_read_z80_ram), FUNC(megadriv_sunplus_state::megadriv_68k_write_z80_ram));
+ map(0xa02000, 0xa03fff).w(FUNC(megadriv_sunplus_state::megadriv_68k_write_z80_ram));
+ map(0xa04000, 0xa04003).rw(FUNC(megadriv_sunplus_state::megadriv_68k_YM2612_read), FUNC(megadriv_sunplus_state::megadriv_68k_YM2612_write));
+ map(0xa06000, 0xa06001).w(FUNC(megadriv_sunplus_state::megadriv_68k_z80_bank_write));
+ map(0xa10000, 0xa1001f).rw(FUNC(megadriv_sunplus_state::megadriv_68k_io_read), FUNC(megadriv_sunplus_state::megadriv_68k_io_write));
+ map(0xa11100, 0xa11101).rw(FUNC(megadriv_sunplus_state::megadriv_68k_check_z80_bus), FUNC(megadriv_sunplus_state::megadriv_68k_req_z80_bus));
+ map(0xa11200, 0xa11201).w(FUNC(megadriv_sunplus_state::megadriv_68k_req_z80_reset));
+ map(0xc00000, 0xc0001f).rw(m_vdp, FUNC(sega315_5313_device::vdp_r), FUNC(sega315_5313_device::vdp_w));
+ map(0xe00000, 0xe0ffff).ram().mirror(0x1f0000).share("megadrive_ram");
+}
+
+uint16_t megadriv_sunplus_state::read(offs_t offset)
+{
+ return m_rom[(((m_bank * 0x10000) + (offset << 1)) & (0x400000 - 1))/2];
+}
+
+
+// controller is wired directly into unit, no controller slots
+static INPUT_PORTS_START( megadriv_sunplus )
+ PORT_INCLUDE( md_common )
+
+ PORT_MODIFY("PAD1")
+#if 0
+ PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)
+ PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1)
+ PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
+ PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START1 )
+#else
+ PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED )
+#endif
+
+ PORT_MODIFY("PAD2")
+#if 0
+ PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
+ PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2)
+ PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
+ PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START2 )
+##else
+ PORT_BIT( 0x00ff, IP_ACTIVE_LOW, IPT_UNUSED )
+#endif
+INPUT_PORTS_END
+
+
+void megadriv_sunplus_state::machine_start()
+{
+ logerror("megadriv_sunplus_state::machine_start\n");
+ md_base_state::machine_start();
+
+ m_vdp->stop_timers();
+ save_item(NAME(m_bank));
+}
+
+void megadriv_sunplus_state::machine_reset()
+{
+ logerror("megadriv_sunplus_state::machine_reset\n");
+ md_base_state::machine_reset();
+}
+
+uint32_t megadriv_sunplus_state::screen_update_hybrid(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ if (m_md_is_running)
+ {
+ /* Copies a bitmap */
+ return screen_update_megadriv(screen, bitmap, cliprect);
+ }
+
+ return 0;
+}
+
+WRITE_LINE_MEMBER(megadriv_sunplus_state::screen_vblank_hybrid)
+{
+ if (m_md_is_running)
+ {
+ /* Used to Sync the timing */
+ md_base_state::screen_vblank_megadriv(state);
+ }
+}
+
+
+void megadriv_sunplus_state::megadriv_sunplus_pal(machine_config &config)
+{
+ md_pal(config);
+ m_maincpu->set_addrmap(AS_PROGRAM, &megadriv_sunplus_state::megadriv_sunplus_map);
+
+ m_screen->set_screen_update(FUNC(megadriv_sunplus_state::screen_update_hybrid));
+ m_screen->screen_vblank().set(FUNC(megadriv_sunplus_state::screen_vblank_hybrid));
+}
+
+
+void megadriv_sunplus_state::init_reactmd()
+{
+ uint16_t *ROM = (uint16_t*)memregion("sunplus")->base();
+ int size = memregion("sunplus")->bytes();
+
+ for (int i = 0; i < size/2; i++)
+ {
+ ROM[i] = bitswap<16>(ROM[i], 15, 13, 14, 12, 7, 6, 5, 4,
+ 11, 10, 9, 8, 3, 1, 2, 0);
+
+ ROM[i] = ROM[i] ^ 0xa5a5;
+ }
+
+ init_megadrie();
+}
+
+
+ROM_START( reactmd )
+ ROM_REGION( 0x2000000, "maincpu", ROMREGION_ERASE00 ) // this contains the MD games and main boot menu
+ ROM_LOAD16_WORD_SWAP( "reactormd.bin", 0x0000, 0x2000000, CRC(fe9664a4) SHA1(d475b524f576c9d1d90aed20c7467cc652396baf) )
+
+ ROM_REGION( 0x4000000, "sunplus", ROMREGION_ERASE00 ) // this contains the SunPlus games
+ ROM_LOAD16_WORD_SWAP( "reactor_md_sunplus-full.bin", 0x0000, 0x4000000, CRC(843aa58c) SHA1(07cdc6d4aa0057939c145ece01a9aca73c7f1f2b) )
+ ROM_IGNORE(0x4000000) // the 2nd half of the ROM can't be accessed by the PCB (address line tied low) (contains garbage? data)
+ROM_END
+
+
+// Two systems in one unit - Genesis on a Chip and SunPlus, only the SunPlus part is currently emulated. Genesis on a chip is a very poor implementation with many issues on real hardware.
+// This should actually boot to a menu on the MD size, with the SunPlus only being enabled if selected from that menu. MD side menu runs in some enhanced / custom MD mode though.
+// Badminton hangs, as it does in the 49-in-1 above
+CONS( 2009, reactmd, 0, 0, megadriv_sunplus_pal, megadriv_sunplus, megadriv_sunplus_state, init_reactmd, "AtGames / Sega / Waixing", "Reactor MD (PAL)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_GRAPHICS )
+