summaryrefslogtreecommitdiffstats
path: root/src/mame/drivers/popper.cpp
diff options
context:
space:
mode:
authorGravatarGravatar Dirk Best <mail@dirk-best.de>2017-03-03 03:32:34 +0100
committerGravatarGravatar Dirk Best <mail@dirk-best.de>2017-03-03 03:33:28 +0100
commit89a1848c6897c66ff810eea7bf6283062970a535 (patch)
treefec1394a5a569c2a06192409214818738a12ec29 /src/mame/drivers/popper.cpp
parent08443793c6501da12f66df82969575f40814f535 (diff)
popper: Get some meat back onto the bones
* Decode color PROMs [Joe Magiera, couriersud] * Full memory map for main and audio CPU derived from schematics * Add both dip switches * Hook up interrupt generation logic * Decode character and sprite layout and draw character tilemap * Raw screen parameters (to be verified)
Diffstat (limited to 'src/mame/drivers/popper.cpp')
-rw-r--r--src/mame/drivers/popper.cpp466
1 files changed, 429 insertions, 37 deletions
diff --git a/src/mame/drivers/popper.cpp b/src/mame/drivers/popper.cpp
index d0fa2557645..82856fe068f 100644
--- a/src/mame/drivers/popper.cpp
+++ b/src/mame/drivers/popper.cpp
@@ -1,71 +1,463 @@
-// license:BSD-3-Clause
-// copyright-holders:David Haywood
-
-// **** SKELETON DRIVER **** original removed due to unresolved licensing.
-
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
/***************************************************************************
Popper
- Omori Electric CAD (OEC) 1983
-
-
- PPR-12
+ © 1983 Omori Electric Co. (OEC)
+ PCB connector pinout
- 18.432MHz 6148 6148
- 6148 4148
- 2128
- 2128
- 2128
- 2128
- p3 p6
- z80A p2 p5
- p0 p1 p4
- z80A
- 8910
- 8910 SW2 SW1 p.m4 p.m3
+ GND 1 2 GND
+ GND 3 4 GND
+ 5V 5 6 5V
+ 5V 7 8 5V
+ Speaker 9 10 Speaker
+ 12V 11 12 12V
+ 1-P Push 13 14 1-P Right
+ 2-P Push 15 16 2-P Right
+ 1-P Start 17 18 1-P Left
+ 2-P Start 19 20 2-P Left
+ Coin A 21 22 1-P Down
+ Coin B 23 24 2-P Down
+ Service 25 26 1-P Up
+ 27 28 2-P Up
+ 29 30
+ 31 32
+ Synic 33 34 Red
+ Green 35 36 Blue
+ 5V 37 38 5V
+ 5V 39 40 5V
+ GND 41 42 GND
+ TODO:
+ - According to the schematics the audio CPU ROM should be 0x2000
+ - Verify dip switch defaults
+ - Verify screen raw parameters
+ - Finish driver
***************************************************************************/
#include "emu.h"
+#include "cpu/z80/z80.h"
+#include "sound/ay8910.h"
+#include "video/resnet.h"
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
class popper_state : public driver_device
{
public:
popper_state(const machine_config &mconfig, device_type type, const char *tag)
- : driver_device(mconfig, type, tag)
+ : driver_device(mconfig, type, tag),
+ m_maincpu(*this, "maincpu"),
+ m_audiocpu(*this, "audiocpu"),
+ m_screen(*this, "screen"),
+ m_gfxdecode(*this, "gfxdecode"),
+ m_ay{ {*this, "ay1"}, {*this, "ay2"} },
+ m_ram(*this, "ram"),
+ m_scanline_timer(nullptr),
+ m_tilemap(nullptr),
+ m_nmi_enable(0), m_vram_page(0)
{ }
+
+ DECLARE_PALETTE_INIT(popper);
+ uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+ TILE_GET_INFO_MEMBER(tile_info);
+
+ DECLARE_WRITE8_MEMBER(nmi_control_w);
+ DECLARE_WRITE8_MEMBER(crt_direction_w);
+ DECLARE_WRITE8_MEMBER(back_color_select_w);
+ DECLARE_WRITE8_MEMBER(vram_page_select_w);
+ DECLARE_WRITE8_MEMBER(intcycle_w);
+ DECLARE_READ8_MEMBER(audiocpu_nmi_r);
+ DECLARE_READ8_MEMBER(audiocpu_reset_r);
+ template <unsigned N> DECLARE_WRITE8_MEMBER(ay_w);
+ DECLARE_READ8_MEMBER(watchdog_clear_r);
+ DECLARE_READ8_MEMBER(inputs_r);
+
+protected:
+ virtual void machine_start() override;
+ virtual void machine_reset() override;
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+
+private:
+ required_device<z80_device> m_maincpu;
+ required_device<z80_device> m_audiocpu;
+ required_device<screen_device> m_screen;
+ required_device<gfxdecode_device> m_gfxdecode;
+ required_device<ay8910_device> m_ay[2];
+ required_shared_ptr<uint8_t> m_ram;
+
+ emu_timer *m_scanline_timer;
+ tilemap_t *m_tilemap;
+
+ int m_nmi_enable;
+ int m_vram_page;
};
+//**************************************************************************
+// ADDRESS MAPS
+//**************************************************************************
+
+static ADDRESS_MAP_START( main_map, AS_PROGRAM, 8, popper_state )
+ AM_RANGE(0x0000, 0x7fff) AM_ROM
+ AM_RANGE(0x8000, 0xbfff) AM_NOP
+ AM_RANGE(0xc000, 0xdfff) AM_RAM AM_SHARE("ram")
+ AM_RANGE(0xe000, 0xe003) AM_MIRROR(0x1ffc) AM_READ(inputs_r)
+ AM_RANGE(0xe000, 0xe000) AM_MIRROR(0x1ff8) AM_WRITE(nmi_control_w)
+ AM_RANGE(0xe001, 0xe001) AM_MIRROR(0x1ff8) AM_WRITE(crt_direction_w)
+ AM_RANGE(0xe002, 0xe002) AM_MIRROR(0x1ff8) AM_WRITE(back_color_select_w)
+ AM_RANGE(0xe003, 0xe003) AM_MIRROR(0x1ff8) AM_WRITE(vram_page_select_w)
+ AM_RANGE(0xe004, 0xe007) AM_MIRROR(0x1ff8) AM_WRITE(intcycle_w)
+ AM_RANGE(0xe400, 0xe400) AM_MIRROR(0x03ff) AM_READ(audiocpu_nmi_r)
+ AM_RANGE(0xe800, 0xf7ff) AM_NOP
+ AM_RANGE(0xf800, 0xf800) AM_MIRROR(0x03ff) AM_READ(audiocpu_reset_r)
+ AM_RANGE(0xfc00, 0xfc00) AM_MIRROR(0x03ff) AM_READ(watchdog_clear_r)
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( audio_map, AS_PROGRAM, 8, popper_state )
+ AM_RANGE(0x0000, 0x1fff) AM_ROM
+ AM_RANGE(0x2000, 0x7fff) AM_NOP
+ AM_RANGE(0x8000, 0x8003) AM_MIRROR(0x1ffc) AM_WRITE(ay_w<0>)
+ AM_RANGE(0xa000, 0xa003) AM_MIRROR(0x1ffc) AM_WRITE(ay_w<1>)
+ AM_RANGE(0xc000, 0xdfff) AM_RAM AM_SHARE("ram")
+ AM_RANGE(0xe000, 0xffff) AM_NOP
+ADDRESS_MAP_END
+
+
+//**************************************************************************
+// INPUT PORT DEFINITIONS
+//**************************************************************************
+
static INPUT_PORTS_START( popper )
+ PORT_START("dipsw1")
+ PORT_DIPNAME(0x03, 0x00, DEF_STR( Coin_A )) PORT_DIPLOCATION("DIPSW1:1,2")
+ PORT_DIPSETTING( 0x00, DEF_STR( 1C_1C ))
+ PORT_DIPSETTING( 0x01, DEF_STR( 2C_1C ))
+ PORT_DIPSETTING( 0x02, DEF_STR( 3C_1C ))
+ PORT_DIPSETTING( 0x03, DEF_STR( 1C_2C ))
+ PORT_DIPNAME(0x0c, 0x00, DEF_STR( Coin_B )) PORT_DIPLOCATION("DIPSW1:3,4")
+ PORT_DIPSETTING( 0x00, DEF_STR( 1C_3C ))
+ PORT_DIPSETTING( 0x01, DEF_STR( 1C_4C ))
+ PORT_DIPSETTING( 0x02, DEF_STR( 1C_5C ))
+ PORT_DIPSETTING( 0x03, DEF_STR( 1C_6C ))
+ PORT_DIPNAME(0x30, 0x00, DEF_STR( Lives )) PORT_DIPLOCATION("DIPSW1:5,6")
+ PORT_DIPSETTING( 0x00, "2")
+ PORT_DIPSETTING( 0x10, "3")
+ PORT_DIPSETTING( 0x20, "4")
+ PORT_DIPSETTING( 0x30, "5")
+ PORT_DIPNAME(0xc0, 0x00, DEF_STR( Bonus_Life )) PORT_DIPLOCATION("DIPSW1:7,8")
+ PORT_DIPSETTING( 0x00, "20,000 Points")
+ PORT_DIPSETTING( 0x40, "30,000 Points")
+ PORT_DIPSETTING( 0x80, "40,000 Points")
+ PORT_DIPSETTING( 0xc0, "50,000 Points")
+
+ PORT_START("dipsw2")
+ PORT_DIPNAME(0x01, 0x00, DEF_STR( Demo_Sounds )) PORT_DIPLOCATION("DIPSW2:1")
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ))
+ PORT_DIPSETTING( 0x01, DEF_STR( On ))
+ PORT_DIPUNUSED_DIPLOC(0x02, IP_ACTIVE_LOW, "DIPSW2:2")
+ PORT_DIPNAME(0x04, 0x00, DEF_STR( Free_Play )) PORT_DIPLOCATION("DIPSW2:3")
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ))
+ PORT_DIPSETTING( 0x04, DEF_STR( On ))
+ PORT_DIPNAME(0x08, 0x00, "Invulnerability") PORT_DIPLOCATION("DIPSW2:4")
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ))
+ PORT_DIPSETTING( 0x08, DEF_STR( On ))
+ PORT_DIPNAME(0x10, 0x00, DEF_STR( Flip_Screen )) PORT_DIPLOCATION("DIPSW2:5")
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ))
+ PORT_DIPSETTING( 0x10, DEF_STR( On ))
+ PORT_DIPNAME(0x20, 0x00, DEF_STR( Cabinet )) PORT_DIPLOCATION("DIPSW2:6")
+ PORT_DIPSETTING( 0x00, DEF_STR( Cocktail ))
+ PORT_DIPSETTING( 0x20, DEF_STR( Upright ))
+ PORT_DIPNAME(0x40, 0x00, "Game Repeating") PORT_DIPLOCATION("DIPSW2:7")
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ))
+ PORT_DIPSETTING( 0x40, DEF_STR( On ))
+ PORT_DIPNAME(0x80, 0x00, DEF_STR( Pause )) PORT_DIPLOCATION("DIPSW2:8")
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ))
+ PORT_DIPSETTING( 0x80, DEF_STR( On ))
INPUT_PORTS_END
+
+//**************************************************************************
+// INPUT PORT HANDLING
+//**************************************************************************
+
+READ8_MEMBER( popper_state::inputs_r )
+{
+// logerror("inputs_r: %d\n", offset);
+ return 0;
+}
+
+
+//**************************************************************************
+// PALETTE
+//**************************************************************************
+
+static const res_net_decode_info popper_decode_info =
+{
+ 1,
+ 0,
+ 63,
+ // R G B
+ { 0, 0, 0, }, // offsets
+ { 0, 3, 6, }, // shifts
+ { 0x07, 0x07, 0x03, } // masks
+};
+
+static const res_net_info popper_net_info =
+{
+ RES_NET_VCC_5V | RES_NET_VBIAS_5V | RES_NET_VIN_TTL_OUT,
+ {
+ { RES_NET_AMP_NONE, 0, 0, 3, { 1000, 470, 220 } },
+ { RES_NET_AMP_NONE, 0, 0, 3, { 1000, 470, 220 } },
+ { RES_NET_AMP_NONE, 0, 0, 2, { 470, 220, 0 } }
+ }
+};
+
+PALETTE_INIT_MEMBER( popper_state, popper )
+{
+ const uint8_t *prom = memregion("colors")->base();
+ std::vector<rgb_t> rgb;
+
+ compute_res_net_all(rgb, prom, popper_decode_info, popper_net_info);
+
+ palette.set_pen_colors(0, rgb);
+ palette.palette()->normalize_range(0, 63);
+}
+
+
+//**************************************************************************
+// VIDEO EMULATION
+//**************************************************************************
+
+void popper_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ int y = m_screen->vpos();
+
+ // the maincpu gets an nmi when we enter vblank (when enabled)
+ m_maincpu->set_input_line(INPUT_LINE_NMI, (m_nmi_enable && y == 240) ? ASSERT_LINE : CLEAR_LINE);
+
+ // the audiocpu gets an interrupt each 16 lines
+ m_audiocpu->set_input_line(INPUT_LINE_IRQ0, y & 16 ? ASSERT_LINE : CLEAR_LINE);
+
+ m_scanline_timer->adjust(machine().first_screen()->time_until_pos(y + 1, 0));
+}
+
+WRITE8_MEMBER( popper_state::crt_direction_w )
+{
+// logerror("crt_direction_w: %02x\n", data);
+}
+
+WRITE8_MEMBER( popper_state::back_color_select_w )
+{
+ logerror("back_color_select_w: %02x\n", data);
+}
+
+WRITE8_MEMBER( popper_state::vram_page_select_w )
+{
+ logerror("vram_page_select_w: %02x\n", data);
+ m_vram_page = data & 1;
+}
+
+uint32_t popper_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ bitmap.fill(0, cliprect);
+
+ // always draw all tiles
+ m_tilemap->mark_all_dirty();
+
+ // draw the character layer
+ m_tilemap->draw(screen, bitmap, cliprect, 0, 0);
+
+ return 0;
+}
+
+
+//**************************************************************************
+// DRAWGFX LAYOUTS
+//**************************************************************************
+
+static const gfx_layout charlayout =
+{
+ 8,8,
+ RGN_FRAC(2,2),
+ 2,
+ { 0, 4 },
+ { STEP4(8,1), STEP4(0,1) },
+ { STEP8(0,16) },
+ 16*8
+};
+
+static const gfx_layout spritelayout =
+{
+ 16,16,
+ RGN_FRAC(1,2),
+ 2,
+ { RGN_FRAC(0,2), RGN_FRAC(1,2) },
+ { STEP8(8,1), STEP8(0,1) },
+ { STEP16(0,16) },
+ 16*2*8
+};
+
+static GFXDECODE_START( popper )
+ GFXDECODE_ENTRY("tiles", 0, charlayout, 0, 16)
+ GFXDECODE_ENTRY("sprites", 0, spritelayout, 0, 16)
+GFXDECODE_END
+
+TILE_GET_INFO_MEMBER( popper_state::tile_info )
+{
+ int code = (m_vram_page << 8) | m_ram[0x100 + tile_index];
+ int attr = m_ram[0x900 + tile_index];
+ int color = attr >> 4;
+
+ SET_TILE_INFO_MEMBER(0, code, color, 0);
+}
+
+
+//**************************************************************************
+// AUDIO
+//**************************************************************************
+
+READ8_MEMBER( popper_state::audiocpu_nmi_r )
+{
+ m_audiocpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE);
+ m_audiocpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
+
+ return 0;
+}
+
+READ8_MEMBER( popper_state::audiocpu_reset_r )
+{
+ m_audiocpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
+ m_audiocpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
+
+ return 0;
+}
+
+template <unsigned N> WRITE8_MEMBER( popper_state::ay_w )
+{
+ if (offset == 0)
+ m_ay[N]->reset();
+
+ m_ay[N]->address_data_w(space, offset, data);
+}
+
+template WRITE8_MEMBER( popper_state::ay_w<0> );
+template WRITE8_MEMBER( popper_state::ay_w<1> );
+
+
+//**************************************************************************
+// MACHINE EMULATION
+//**************************************************************************
+
+WRITE8_MEMBER( popper_state::nmi_control_w )
+{
+// logerror("nmi_control_w: %02x\n", data);
+ m_nmi_enable = data & 1;
+}
+
+WRITE8_MEMBER( popper_state::intcycle_w )
+{
+ logerror("intcycle_w: %d = %02x\n", offset, data);
+}
+
+READ8_MEMBER( popper_state::watchdog_clear_r )
+{
+ logerror("watchdog_clear_r\n");
+ return 0;
+}
+
+void popper_state::machine_start()
+{
+ // create tilemap
+ m_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(popper_state::tile_info), this), TILEMAP_SCAN_COLS, 8, 8, 48, 32);
+ m_tilemap->set_transparent_pen(3);
+
+ // allocate and start scanline timer
+ m_scanline_timer = timer_alloc(0);
+ m_scanline_timer->adjust(machine().first_screen()->time_until_pos(0, 0));
+
+ // register for save states
+ save_item(NAME(m_nmi_enable));
+ save_item(NAME(m_vram_page));
+}
+
+void popper_state::machine_reset()
+{
+ m_nmi_enable = 0;
+ m_vram_page = 0;
+}
+
+
+//**************************************************************************
+// MACHINE DEFINTIONS
+//**************************************************************************
+
static MACHINE_CONFIG_START( popper, popper_state )
+ MCFG_CPU_ADD("maincpu", Z80, XTAL_18_432MHz/3/2)
+ MCFG_CPU_PROGRAM_MAP(main_map)
+
+ MCFG_CPU_ADD("audiocpu", Z80, XTAL_18_432MHz/3/2)
+ MCFG_CPU_PROGRAM_MAP(audio_map)
+
+ MCFG_QUANTUM_PERFECT_CPU("maincpu")
+
+ // video hardware
+ MCFG_SCREEN_ADD("screen", RASTER)
+ MCFG_SCREEN_RAW_PARAMS(XTAL_18_432MHz/3, 384, 48, 328, 264, 16, 240)
+ MCFG_SCREEN_UPDATE_DRIVER(popper_state, screen_update)
+ MCFG_SCREEN_PALETTE("palette")
+
+ MCFG_GFXDECODE_ADD("gfxdecode", "palette", popper)
+
+ MCFG_PALETTE_ADD("palette", 64)
+ MCFG_PALETTE_INIT_OWNER(popper_state, popper)
+
+ // audio hardware
+ MCFG_SPEAKER_STANDARD_MONO("mono")
+
+ MCFG_SOUND_ADD("ay1", AY8910, XTAL_18_432MHz/3/2/2)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
+
+ MCFG_SOUND_ADD("ay2", AY8910, XTAL_18_432MHz/3/2/2)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
MACHINE_CONFIG_END
+
+//**************************************************************************
+// ROM DEFINITIONS
+//**************************************************************************
+
ROM_START( popper )
- ROM_REGION( 0x10000, "maincpu", 0 )
- ROM_LOAD( "p1", 0x0000, 0x2000, CRC(56881b70) SHA1(d3ade7a54a6cb8a0babf0d667a6b27f492a739dc) )
- ROM_LOAD( "p2", 0x2000, 0x2000, CRC(a054d9d2) SHA1(fcd86e7247b40cf07ea595a64c104b99b0e93ced) )
- ROM_LOAD( "p3", 0x4000, 0x2000, CRC(6201928a) SHA1(53b571b9f2c0568f10cd974641863c2e00777b46) )
+ ROM_REGION(0x8000, "maincpu", 0)
+ ROM_LOAD("p1", 0x0000, 0x2000, CRC(56881b70) SHA1(d3ade7a54a6cb8a0babf0d667a6b27f492a739dc))
+ ROM_LOAD("p2", 0x2000, 0x2000, CRC(a054d9d2) SHA1(fcd86e7247b40cf07ea595a64c104b99b0e93ced))
+ ROM_LOAD("p3", 0x4000, 0x2000, CRC(6201928a) SHA1(53b571b9f2c0568f10cd974641863c2e00777b46))
- ROM_REGION( 0x10000, "audiocpu", 0 )
- ROM_LOAD( "p0", 0x0000, 0x1000, CRC(ef5f7c5b) SHA1(c63a3d9ef2868ad7eaacddec810d62d2e124dc15) )
+ ROM_REGION(0x2000, "audiocpu", 0)
+ ROM_LOAD("p0", 0x0000, 0x1000, CRC(ef5f7c5b) SHA1(c63a3d9ef2868ad7eaacddec810d62d2e124dc15))
- ROM_REGION( 0x2000, "gfx1", 0 )
- ROM_LOAD( "p4", 0x0000, 0x2000, CRC(86203349) SHA1(cce2dd3fa786c2fb3ca80e7b93adf94db3b46b01) )
+ ROM_REGION(0x2000, "tiles", 0)
+ ROM_LOAD("p4", 0x0000, 0x2000, CRC(86203349) SHA1(cce2dd3fa786c2fb3ca80e7b93adf94db3b46b01))
- ROM_REGION( 0x4000, "gfx2", 0 )
- ROM_LOAD( "p5", 0x0000, 0x2000, CRC(a21ac194) SHA1(2c0e3df8981a12d383b1c4619a0b95a7c2d176a7) )
- ROM_LOAD( "p6", 0x2000, 0x2000, CRC(d99fa790) SHA1(201271ee4fb812236a38cb5f9070ac29e8186097) )
+ ROM_REGION(0x4000, "sprites", 0)
+ ROM_LOAD("p5", 0x0000, 0x2000, CRC(a21ac194) SHA1(2c0e3df8981a12d383b1c4619a0b95a7c2d176a7))
+ ROM_LOAD("p6", 0x2000, 0x2000, CRC(d99fa790) SHA1(201271ee4fb812236a38cb5f9070ac29e8186097))
- ROM_REGION( 0x0040, "proms", 0 )
- ROM_LOAD( "p.m3", 0x0000, 0x0020, CRC(713217aa) SHA1(6083c3432bf94c9e983fcc79171529f519c86105) )
- ROM_LOAD( "p.m4", 0x0020, 0x0020, CRC(384de5c1) SHA1(892c89a01c11671c5708113b4e4c27b84be37ea6) )
+ ROM_REGION(0x40, "colors", 0)
+ ROM_LOAD("p.m3", 0x00, 0x20, CRC(713217aa) SHA1(6083c3432bf94c9e983fcc79171529f519c86105))
+ ROM_LOAD("p.m4", 0x20, 0x20, CRC(384de5c1) SHA1(892c89a01c11671c5708113b4e4c27b84be37ea6))
ROM_END
-GAME( 1983, popper, 0, popper, popper, driver_device, 0, ROT90, "Omori Electric Co., Ltd.", "Popper", MACHINE_IS_SKELETON )
+
+//**************************************************************************
+// SYSTEM DRIVERS
+//**************************************************************************
+
+// YEAR NAME PARENT MACHINE INPUT CLASS INIT ROTATION COMPANY FULLNAME FLAGS
+GAME( 1983, popper, 0, popper, popper, driver_device, 0, ROT90, "Omori", "Popper", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE )