diff options
author | 2021-07-25 03:59:23 +0200 | |
---|---|---|
committer | 2021-07-25 11:59:23 +1000 | |
commit | 4098f3007d7cd5746df46f52f86564d9d5b61a7d (patch) | |
tree | 7690ff2bc68ad8b0f424086e6791e0148f227b46 | |
parent | bc8a1315ca241df013710df14b00d46782c9e220 (diff) |
vsmjtria.cpp: Allow comms to actually work so that game can be coined up properly from either side. (#8245)
* Added NMI acknowledge, fixed coin input polarity, fixed gal B display, fixed flip screen behaviour.
* Added NVRAM clear using SW2.
Machines promoted to working
-------------------------
VS Mahjong Triangle [Angelo Salese, Vas Crabb]
-rw-r--r-- | src/mame/drivers/rmhaihai.cpp | 1 | ||||
-rw-r--r-- | src/mame/drivers/vsmjtria.cpp | 222 |
2 files changed, 145 insertions, 78 deletions
diff --git a/src/mame/drivers/rmhaihai.cpp b/src/mame/drivers/rmhaihai.cpp index 071bed5a799..4928f92d61a 100644 --- a/src/mame/drivers/rmhaihai.cpp +++ b/src/mame/drivers/rmhaihai.cpp @@ -21,6 +21,7 @@ TODO: protection (in rmhaisei the failure is more explicit, in rmhaijin it's deviously delayed to a later part of the game). In themj the checks are patched out, maybe it's a bootleg? + ETA: it uses IOX, which is shared with speedatk.cpp and srmp2.cpp as well. - some unknown reads and writes. diff --git a/src/mame/drivers/vsmjtria.cpp b/src/mame/drivers/vsmjtria.cpp index 43be66fdd7e..ecb9659eed8 100644 --- a/src/mame/drivers/vsmjtria.cpp +++ b/src/mame/drivers/vsmjtria.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders: +// copyright-holders:Vas Crabb, Angelo Salese /* VS Mahjong Triangle (c) 1986 Dyna @@ -10,13 +10,28 @@ Unmarked board with everything doubled up, to provide a versus experience with a CPU: 2x Z80 RAM: 6x M5M5117P Sound: 2x AY-3-8910 -I/O: 2x 8255, 4x 8-dip banks, 1x single dip +I/O: 2x 8255, 4x 8-dip banks, 1x single dip switch (at position 11m) OSC: 20MHz +Notes: +- Loosely based off rmhaihai.cpp. + Changes needed for merging both implementations seems too trivial to warrant a + driver merge, basically just the video HW, the CRTC (448x224 clocked at 20 MHz?) + and a few I/O bits looks very similar, the odd screen size is also a thing in srmp2.cpp + and probably other Seta HWs. +- CPU seems a bit too slow when deciding about what tile to discard, + it also takes a bit too much to sync when a player takes a tile from the pond in + a VS play. It's most likely btanb unless a gameplay video proves otherwise; +- Position 11m on PCB has a single slider switch. + It is not read by the CPUs at all, but instead zaps the nearby NVRAM contents if active. + TODO: -- coins don't work (set to free play to test for now) -- VS. feature communications aren't implemented -- the hardware is based on the one in rmhaihai.cpp. Derive, merge or neither? +- Upper byte of I/O access seems to be some extra comms state machine + (i.e. it more or less mimic the commands that CPUs send between each other). + Maybe just a debug port that is read thru external HW? +- Pinpoint how HW reads the three lead-filled marked as SW1 (position 1b). + It's located next to the key matrix, maybe just ext debugging? + */ #include "emu.h" @@ -36,13 +51,16 @@ namespace { class vsmjtria_state : public driver_device { public: - vsmjtria_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - m_cpu(*this, "cpu%u", 0U), - m_gfxdecode(*this, "gfxdecode%u", 0U), - m_colorram(*this, "colorram%u", 0U), - m_videoram(*this, "videoram%u", 0U), - m_key{ { *this, "P1_KEY%u", 0U }, { *this, "P2_KEY%u", 0U } } + vsmjtria_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_cpu(*this, "cpu%u", 0U) + , m_gfxdecode(*this, "gfxdecode%u", 0U) + , m_colorram(*this, "colorram%u", 0U) + , m_videoram(*this, "videoram%u", 0U) + , m_key{ { *this, "P1_KEY%u", 0U }, { *this, "P2_KEY%u", 0U } } + , m_nvram(*this, "nvram%u", 0U) + , m_nvram_data(*this, "nvram%u", 0U) + , m_sw2(*this, "SW2") { } void vsmjtria(machine_config &config); @@ -51,6 +69,7 @@ public: protected: virtual void machine_start() override; + virtual void machine_reset() override; virtual void video_start() override; private: @@ -59,11 +78,15 @@ private: required_shared_ptr_array<uint8_t, 2> m_colorram; required_shared_ptr_array<uint8_t, 2> m_videoram; required_ioport_array<5> m_key[2]; + required_device_array<nvram_device, 2> m_nvram; + required_shared_ptr_array<u8, 2> m_nvram_data; + required_ioport m_sw2; tilemap_t *m_bg_tilemap[2]; uint8_t m_keyboard_cmd[2]; - template <uint8_t Which> void nmi_w(uint8_t data); + template <uint8_t Which> void nmi_set_w(uint8_t data); + template <uint8_t Which> void nmi_ack_w(uint8_t data); template <uint8_t Which> void ctrl_w(uint8_t data); template <uint8_t Which> uint8_t keyboard_r(); template <uint8_t Which> void keyboard_w(uint8_t data); @@ -79,108 +102,119 @@ private: void sub_io_map(address_map &map); }; +/* + * Video section + */ -void vsmjtria_state::machine_start() +void vsmjtria_state::video_start() { - m_keyboard_cmd[0] = m_keyboard_cmd[1] = 0; - - save_item(NAME(m_keyboard_cmd)); + m_bg_tilemap[0] = &machine().tilemap().create(*m_gfxdecode[0], tilemap_get_info_delegate(*this, FUNC(vsmjtria_state::get_bg_tile_info<0>)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32); + m_bg_tilemap[1] = &machine().tilemap().create(*m_gfxdecode[1], tilemap_get_info_delegate(*this, FUNC(vsmjtria_state::get_bg_tile_info<1>)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32); } template <uint8_t Which> -void vsmjtria_state::nmi_w(uint8_t data) +void vsmjtria_state::videoram_w(offs_t offset, uint8_t data) { - m_cpu[Which]->pulse_input_line(INPUT_LINE_NMI, m_cpu[Which]->minimum_quantum_time()); + m_videoram[Which][offset] = data; + m_bg_tilemap[Which]->mark_tile_dirty(offset); } template <uint8_t Which> -void vsmjtria_state::ctrl_w(uint8_t data) +void vsmjtria_state::colorram_w(offs_t offset, uint8_t data) { - flip_screen_set(data & 0x01); - - // (data & 0x02) is switched on and off in service mode - - machine().bookkeeping().coin_lockout_w(0, ~data & 0x04); - machine().bookkeeping().coin_counter_w(0, data & 0x08); + m_colorram[Which][offset] = data; + m_bg_tilemap[Which]->mark_tile_dirty(offset); } template <uint8_t Which> -uint8_t vsmjtria_state::keyboard_r() +TILE_GET_INFO_MEMBER(vsmjtria_state::get_bg_tile_info) { - uint8_t data = 0x00; - - if (BIT(m_keyboard_cmd[Which], 0)) data |= m_key[Which][0]->read(); - if (BIT(m_keyboard_cmd[Which], 1)) data |= m_key[Which][1]->read(); - if (BIT(m_keyboard_cmd[Which], 2)) data |= m_key[Which][2]->read(); - if (BIT(m_keyboard_cmd[Which], 3)) data |= m_key[Which][3]->read(); - if (BIT(m_keyboard_cmd[Which], 4)) data |= m_key[Which][4]->read(); + int attr = m_colorram[Which][tile_index]; + int code = m_videoram[Which][tile_index] + ((attr & 0x07) << 8) + ((attr & 0x80) << 4); + int color = (attr >> 3); - return data; + tileinfo.set(0, code, color, 0); } template <uint8_t Which> -void vsmjtria_state::keyboard_w(uint8_t data) +uint32_t vsmjtria_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { - m_keyboard_cmd[Which] = data; + m_bg_tilemap[Which]->draw(screen, bitmap, cliprect, 0, 0); + return 0; } +/* + * I/O + */ -void vsmjtria_state::video_start() +template <uint8_t Which> +void vsmjtria_state::nmi_set_w(uint8_t data) { - m_bg_tilemap[0] = &machine().tilemap().create(*m_gfxdecode[0], tilemap_get_info_delegate(*this, FUNC(vsmjtria_state::get_bg_tile_info<0>)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32); - m_bg_tilemap[1] = &machine().tilemap().create(*m_gfxdecode[1], tilemap_get_info_delegate(*this, FUNC(vsmjtria_state::get_bg_tile_info<1>)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32); + m_cpu[Which]->set_input_line(INPUT_LINE_NMI, ASSERT_LINE); } template <uint8_t Which> -void vsmjtria_state::videoram_w(offs_t offset, uint8_t data) +void vsmjtria_state::nmi_ack_w(uint8_t data) { - m_videoram[Which][offset] = data; - m_bg_tilemap[Which]->mark_tile_dirty(offset); + m_cpu[Which]->set_input_line(INPUT_LINE_NMI, CLEAR_LINE); } +// TODO: flip screen and coin counter are actually never triggered, are they really connected for this HW? +// (ctrl_w fn comes from rmhaihai.cpp assumption of being identical, it's most likely not present here) template <uint8_t Which> -void vsmjtria_state::colorram_w(offs_t offset, uint8_t data) +void vsmjtria_state::ctrl_w(uint8_t data) { - m_colorram[Which][offset] = data; - m_bg_tilemap[Which]->mark_tile_dirty(offset); +// flip_screen_set(data & 0x01); + m_bg_tilemap[Which]->set_flip((data & 1) ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0); + + // (data & 0x02) is switched on and off in service mode + + machine().bookkeeping().coin_lockout_w(Which, ~data & 0x04); + machine().bookkeeping().coin_counter_w(Which, data & 0x08); } template <uint8_t Which> -TILE_GET_INFO_MEMBER(vsmjtria_state::get_bg_tile_info) +uint8_t vsmjtria_state::keyboard_r() { - int attr = m_colorram[Which][tile_index]; - int code = m_videoram[Which][tile_index] + ((attr & 0x07) << 8) + ((attr & 0x80) << 4); - int color = (attr >> 3); + uint8_t data = 0x00; - tileinfo.set(0, code, color, 0); + for (int key_n = 0; key_n < 5; key_n ++ ) + { + if (BIT(m_keyboard_cmd[Which], key_n)) + data |= m_key[Which][key_n]->read(); + } + + return data; } template <uint8_t Which> -uint32_t vsmjtria_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +void vsmjtria_state::keyboard_w(uint8_t data) { - m_bg_tilemap[Which]->draw(screen, bitmap, cliprect, 0, 0); - return 0; + // bits 6-5 are always set when accessed, unknown purpose + // 0x60 (at boot only, not read back), then 0x61 -> 0x62 -> 0x64 -> 0x68 -> 0x70 and back to 0x61 + m_keyboard_cmd[Which] = data; } - void vsmjtria_state::main_prg_map(address_map &map) { map(0x0000, 0x9fff).rom(); map(0xa000, 0xa7ff).ram().share("nvram0"); map(0xa800, 0xafff).ram().w(FUNC(vsmjtria_state::colorram_w<0>)).share(m_colorram[0]); map(0xb000, 0xb7ff).ram().w(FUNC(vsmjtria_state::videoram_w<0>)).share(m_videoram[0]); - map(0xc000, 0xdfff).rom(); + map(0xc000, 0xdfff).rom().region("cpu0", 0xa000); map(0xe000, 0xffff).rom(); } void vsmjtria_state::main_io_map(address_map &map) { - map(0x8000, 0x8003).rw("ppi0", FUNC(i8255_device::read), FUNC(i8255_device::write)); - map(0x8020, 0x8020).r("ay0", FUNC(ay8910_device::data_r)); - map(0x8020, 0x8021).w("ay0", FUNC(ay8910_device::address_data_w)); - map(0x8060, 0x8060).w(FUNC(vsmjtria_state::ctrl_w<0>)); - map(0x80c0, 0x80c0).w(FUNC(vsmjtria_state::nmi_w<1>)); - map(0x80e0, 0x80e0).r("latch1", FUNC(generic_latch_8_device::read)).w("latch0", FUNC(generic_latch_8_device::write)); + map.global_mask(0xff); + map(0x00, 0x03).rw("ppi0", FUNC(i8255_device::read), FUNC(i8255_device::write)); + map(0x20, 0x20).r("ay0", FUNC(ay8910_device::data_r)); + map(0x20, 0x21).w("ay0", FUNC(ay8910_device::address_data_w)); + map(0x60, 0x60).w(FUNC(vsmjtria_state::ctrl_w<0>)); + map(0xa0, 0xa0).w(FUNC(vsmjtria_state::nmi_ack_w<0>)); + map(0xc0, 0xc0).w(FUNC(vsmjtria_state::nmi_set_w<1>)); + map(0xe0, 0xe0).r("latch1", FUNC(generic_latch_8_device::read)).w("latch0", FUNC(generic_latch_8_device::write)); } void vsmjtria_state::sub_prg_map(address_map &map) @@ -189,31 +223,35 @@ void vsmjtria_state::sub_prg_map(address_map &map) map(0xa000, 0xa7ff).ram().share("nvram1"); map(0xa800, 0xafff).ram().w(FUNC(vsmjtria_state::colorram_w<1>)).share(m_colorram[1]); map(0xb000, 0xb7ff).ram().w(FUNC(vsmjtria_state::videoram_w<1>)).share(m_videoram[1]); - map(0xc000, 0xdfff).rom(); + map(0xc000, 0xdfff).rom().region("cpu1", 0xa000); map(0xe000, 0xffff).rom(); } void vsmjtria_state::sub_io_map(address_map &map) { - map(0x8000, 0x8003).rw("ppi1", FUNC(i8255_device::read), FUNC(i8255_device::write)); - map(0x8020, 0x8020).r("ay1", FUNC(ay8910_device::data_r)); - map(0x8020, 0x8021).w("ay1", FUNC(ay8910_device::address_data_w)); - map(0x8060, 0x8060).w(FUNC(vsmjtria_state::ctrl_w<1>)); - map(0x80c0, 0x80c0).w(FUNC(vsmjtria_state::nmi_w<0>)); - map(0x80e0, 0x80e0).r("latch0", FUNC(generic_latch_8_device::read)).w("latch1", FUNC(generic_latch_8_device::write)); + map.global_mask(0xff); + map(0x00, 0x03).rw("ppi1", FUNC(i8255_device::read), FUNC(i8255_device::write)); + map(0x20, 0x20).r("ay1", FUNC(ay8910_device::data_r)); + map(0x20, 0x21).w("ay1", FUNC(ay8910_device::address_data_w)); + map(0x60, 0x60).w(FUNC(vsmjtria_state::ctrl_w<1>)); + map(0xa0, 0xa0).w(FUNC(vsmjtria_state::nmi_ack_w<1>)); + map(0xc0, 0xc0).w(FUNC(vsmjtria_state::nmi_set_w<0>)); + map(0xe0, 0xe0).r("latch0", FUNC(generic_latch_8_device::read)).w("latch1", FUNC(generic_latch_8_device::write)); } static INPUT_PORTS_START( vsmjtria ) + // TODO: deduplicate all inputs here + // either use a C-style macro or device-ify PORT_START("P1_COIN") - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_IMPULSE(1) - PORT_BIT( 0x1e, IP_ACTIVE_HIGH, IPT_UNUSED ) // stored at A38F along with bit 0 - seems to be vestigial, bit 2 tested at 02D1, but result discarded - PORT_BIT( 0xe0, IP_ACTIVE_HIGH, IPT_UNUSED ) // masked out after being read + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) + PORT_BIT( 0x1e, IP_ACTIVE_LOW, IPT_UNKNOWN ) // stored at A38F along with bit 0 - seems to be vestigial, bit 2 tested at 02D1, but result discarded + PORT_BIT( 0xe0, IP_ACTIVE_LOW, IPT_UNUSED ) // masked out after being read PORT_START("P2_COIN") - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN2 ) PORT_IMPULSE(1) - PORT_BIT( 0x1e, IP_ACTIVE_HIGH, IPT_UNUSED ) // stored at A38F along with bit 0 - seems to be vestigial, bit 2 tested at 02D1, but result discarded - PORT_BIT( 0xe0, IP_ACTIVE_HIGH, IPT_UNUSED ) // masked out after being read + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN2 ) + PORT_BIT( 0x1e, IP_ACTIVE_LOW, IPT_UNKNOWN ) // stored at A38F along with bit 0 - seems to be vestigial, bit 2 tested at 02D1, but result discarded + PORT_BIT( 0xe0, IP_ACTIVE_LOW, IPT_UNUSED ) // masked out after being read PORT_START("P1_KEY0") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_START1 ) PORT_NAME("P1 Single Start") @@ -416,6 +454,13 @@ static INPUT_PORTS_START( vsmjtria ) PORT_DIPNAME( 0x80, 0x80, "Unknown 4-7" ) PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + + // single slider switch, not read by CPU + // grounds NVRAM contents, simulated in machine_reset fn + PORT_START("SW2") + PORT_DIPNAME( 0x01, 0x00, "Clear NVRAM at boot" ) + PORT_DIPSETTING( 0x00, DEF_STR( No ) ) + PORT_DIPSETTING( 0x01, DEF_STR( Yes ) ) INPUT_PORTS_END @@ -438,10 +483,31 @@ static GFXDECODE_START( gfx_vsmjtria_sub ) GFXDECODE_ENTRY( "subgfx", 0, charlayout, 0, 32 ) GFXDECODE_END +void vsmjtria_state::machine_start() +{ + m_keyboard_cmd[0] = m_keyboard_cmd[1] = 0; + + save_item(NAME(m_keyboard_cmd)); +} + +void vsmjtria_state::machine_reset() +{ + if (m_sw2->read() & 1) + { + // Note: there's no direct setter in nvram_device that directly flushes contents for this case scenario + for (auto &nvram : m_nvram_data) + std::fill_n(&nvram[0], nvram.length(), 0); + + logerror("machine_reset: flush NVRAM contents\n"); + } +} + void vsmjtria_state::vsmjtria(machine_config &config) { config.set_perfect_quantum("cpu0"); // crude way to make comms work - does it have FIFOs rather than latches? + // Both CPUs are LH0080A -> Z80A, nominally 4 MHz + // Clock also controls sound tempo, which at /4 sounds too fast already. Z80(config, m_cpu[0], 20_MHz_XTAL / 5); // divider guessed m_cpu[0]->set_addrmap(AS_PROGRAM, &vsmjtria_state::main_prg_map); m_cpu[0]->set_addrmap(AS_IO, &vsmjtria_state::main_io_map); @@ -452,8 +518,8 @@ void vsmjtria_state::vsmjtria(machine_config &config) m_cpu[1]->set_addrmap(AS_IO, &vsmjtria_state::sub_io_map); m_cpu[1]->set_vblank_int("rscreen", FUNC(vsmjtria_state::irq0_line_hold)); - NVRAM(config, "nvram0", nvram_device::DEFAULT_ALL_0); - NVRAM(config, "nvram1", nvram_device::DEFAULT_ALL_0); + NVRAM(config, m_nvram[0], nvram_device::DEFAULT_ALL_0); + NVRAM(config, m_nvram[1], nvram_device::DEFAULT_ALL_0); GENERIC_LATCH_8(config, "latch0"); GENERIC_LATCH_8(config, "latch1"); @@ -574,4 +640,4 @@ void vsmjtria_state::init_vsmjtria() } // Anonymous namespace -GAME( 1986, vsmjtria, 0, vsmjtria, vsmjtria, vsmjtria_state, init_vsmjtria, ROT0, "Dyna", "VS Mahjong Triangle", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE ) // puts Home Data in RAM? coins and CPU comms not working +GAME( 1986, vsmjtria, 0, vsmjtria, vsmjtria, vsmjtria_state, init_vsmjtria, ROT0, "Dyna", "VS Mahjong Triangle", MACHINE_SUPPORTS_SAVE ) // puts Home Data in RAM? |