pbaction: hooked up Tecfri external pinball display on Pinball Action (working but missing some comms) (#4219)

* started looking at Tecfri external display hookup on Pinball Action (not yet correct)

* (nw)

* better (nw)

* better (nw)

* spelling (nw)
This commit is contained in:
David Haywood 2018-11-01 17:18:19 +00:00 committed by R. Belmont
parent be2ad6e737
commit 630bec618c
3 changed files with 388 additions and 19 deletions

View File

@ -59,6 +59,8 @@ This subboard controls a vertical board panel with three 7-seg displays (like on
one for player 1 (7 digits), another for player 2 (7 digits) and the third for game scores (with
three goups: two digits - one digit - two digits).
One of the Z80s on this board is the main game Z80, the other is for the Pinball cabinet
Stephh's notes (based on the game Z80 code and some tests) :
@ -99,12 +101,13 @@ Stephh's notes (based on the game Z80 code and some tests) :
#include "machine/segacrpt_device.h"
#include "screen.h"
#include "speaker.h"
#include "pbactiont.lh"
WRITE8_MEMBER(pbaction_state::pbaction_sh_command_w)
{
m_soundlatch->write(space, offset, data);
machine().scheduler().synchronize(timer_expired_delegate(FUNC(pbaction_state::sound_trigger), this));
m_soundcommand_timer->adjust(attotime::zero, 0);
}
TIMER_CALLBACK_MEMBER(pbaction_state::sound_trigger)
@ -167,7 +170,7 @@ void pbaction_state::pbaction_sound_map(address_map &map)
map(0xffff, 0xffff).w(FUNC(pbaction_state::sound_irq_ack_w));
}
void pbaction_state::pbactiont_sound_map(address_map &map)
void pbaction_state::pbaction_alt_sound_map(address_map &map)
{
map(0x0000, 0x1fff).rom();
map(0x4000, 0x47ff).ram();
@ -179,10 +182,110 @@ void pbaction_state::pbaction_sound_io_map(address_map &map)
map.global_mask(0xff);
map(0x00, 0x03).rw(m_ctc, FUNC(z80ctc_device::read), FUNC(z80ctc_device::write));
map(0x10, 0x11).w("ay1", FUNC(ay8910_device::address_data_w));
map(0x12, 0x13).nopw(); // unknown
map(0x20, 0x21).w("ay2", FUNC(ay8910_device::address_data_w));
map(0x30, 0x31).w("ay3", FUNC(ay8910_device::address_data_w));
}
WRITE8_MEMBER(pbaction_tecfri_state::pbaction_tecfri_sub8000_w)
{
m_outlatch = (data & 0x01)>>0;
}
WRITE8_MEMBER(pbaction_tecfri_state::pbaction_tecfri_sub8001_w)
{
// writes 01 , 00 to clock after writing data to 8000
if (data & 0x01)
{
m_outdata = (m_outdata << 1) | m_outlatch;
}
}
WRITE8_MEMBER(pbaction_tecfri_state::pbaction_tecfri_sub8008_w)
{
if (data != 0x00)
{
int base = 0;
switch (data)
{
case 0x01: base = 6; break;
case 0x02: base = 5; break;
case 0x04: base = 4; break;
case 0x08: base = 3; break;
case 0x10: base = 2; break;
case 0x20: base = 1; break;
case 0x40: base = 0; break;
default: break;
}
m_digits[base + 0] = (~m_outdata >> 0) & 0xff;
m_digits[base + 7] = (~m_outdata >> 8) & 0xff;
m_digits[base + 14] = (~m_outdata >> 16) & 0xff;
}
else
{
m_outdata = 0;
}
}
WRITE8_MEMBER(pbaction_tecfri_state::pbaction_tecfri_subtomain_w)
{
//m_subtomainlatch->write(space, offset, data); // where does this go if it can't go to maincpu?
}
READ8_MEMBER(pbaction_tecfri_state::pbaction_tecfri_maintosub_r)
{
return m_maintosublatch->read(space, offset);
}
READ8_MEMBER(pbaction_tecfri_state::subcpu_r)
{
return 0x00; // other values stop the flippers from working? are there different inputs from the custom cabinet in here somehow?
// return m_subtomainlatch->read(space, offset);
}
WRITE8_MEMBER(pbaction_tecfri_state::subcpu_w)
{
m_maintosublatch->write(space, offset, data);
m_subcommand_timer->adjust(attotime::zero, 0);
}
void pbaction_tecfri_state::pbaction_tecfri_sub_map(address_map &map)
{
map(0x0000, 0x03ff).rom();
map(0x4000, 0x47ff).ram();
map(0x8000, 0x8000).w(FUNC(pbaction_tecfri_state::pbaction_tecfri_sub8000_w));
map(0x8001, 0x8001).w(FUNC(pbaction_tecfri_state::pbaction_tecfri_sub8001_w));
//map(0x8002, 0x8007).nopw(); // startup only
map(0x8008, 0x8008).w(FUNC(pbaction_tecfri_state::pbaction_tecfri_sub8008_w));
map(0x8010, 0x8010).r(FUNC(pbaction_tecfri_state::pbaction_tecfri_maintosub_r));
map(0x8018, 0x8018).w(FUNC(pbaction_tecfri_state::pbaction_tecfri_subtomain_w));
}
void pbaction_tecfri_state::pbaction_tecfri_sub_io_map(address_map &map)
{
map.global_mask(0xff);
map(0x00, 0x03).rw(m_ctc2, FUNC(z80ctc_device::read), FUNC(z80ctc_device::write));
}
void pbaction_tecfri_state::pbaction_tecfri_main_io_map(address_map &map)
{
map.global_mask(0xff);
map(0x00, 0x00).rw(FUNC(pbaction_tecfri_state::subcpu_r), FUNC(pbaction_tecfri_state::subcpu_w));
}
TIMER_CALLBACK_MEMBER(pbaction_tecfri_state::sub_trigger)
{
m_ctc2->trg1(0);
m_ctc2->trg1(1);
}
static INPUT_PORTS_START( pbaction )
PORT_START("P1")
@ -263,8 +366,6 @@ static INPUT_PORTS_START( pbaction )
PORT_DIPSETTING( 0xc0, DEF_STR( Hardest ) )
INPUT_PORTS_END
static const gfx_layout charlayout1 =
{
8,8,
@ -318,6 +419,7 @@ GFXDECODE_END
void pbaction_state::machine_start()
{
m_soundcommand_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pbaction_state::sound_trigger), this));
save_item(NAME(m_nmi_mask));
save_item(NAME(m_scroll));
}
@ -390,22 +492,52 @@ MACHINE_CONFIG_START(pbaction_state::pbaction)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
MACHINE_CONFIG_END
MACHINE_CONFIG_START(pbaction_state::pbactiont)
MACHINE_CONFIG_START(pbaction_state::pbactionx)
pbaction(config);
m_audiocpu->set_addrmap(AS_PROGRAM, &pbaction_state::pbactiont_sound_map);
m_audiocpu->irqack_cb().set(FUNC(pbaction_state::sound_irq_clear));
MACHINE_CONFIG_END
MACHINE_CONFIG_START(pbaction_state::pbactionx)
pbactiont(config);
MCFG_DEVICE_REPLACE("maincpu", SEGA_315_5128, 4_MHz_XTAL)
MCFG_DEVICE_PROGRAM_MAP(pbaction_map)
MCFG_DEVICE_OPCODES_MAP(decrypted_opcodes_map)
MCFG_SEGACRPT_SET_DECRYPTED_TAG(":decrypted_opcodes")
m_audiocpu->set_addrmap(AS_PROGRAM, &pbaction_state::pbaction_alt_sound_map);
m_audiocpu->irqack_cb().set(FUNC(pbaction_state::sound_irq_clear));
MACHINE_CONFIG_END
static const z80_daisy_config daisy_chain2[] =
{
{ "ctc2" },
{ nullptr }
};
void pbaction_tecfri_state::machine_start()
{
pbaction_state::machine_start();
m_subcommand_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pbaction_tecfri_state::sub_trigger), this));
m_digits.resolve();
}
MACHINE_CONFIG_START(pbaction_tecfri_state::pbactiont)
pbaction(config);
MCFG_DEVICE_MODIFY("maincpu")
MCFG_DEVICE_IO_MAP(pbaction_tecfri_main_io_map)
Z80(config, m_subcpu, 4_MHz_XTAL);
m_subcpu->set_addrmap(AS_PROGRAM, &pbaction_tecfri_state::pbaction_tecfri_sub_map);
m_subcpu->set_addrmap(AS_IO, &pbaction_tecfri_state::pbaction_tecfri_sub_io_map);
m_subcpu->set_daisy_config(daisy_chain2);
MCFG_GENERIC_LATCH_8_ADD("maintosublatch")
//MCFG_GENERIC_LATCH_8_ADD("subtomainlatch")
Z80CTC(config, m_ctc2, 12_MHz_XTAL/4);
m_ctc2->intr_callback().set_inputline(m_subcpu, 0);
m_audiocpu->set_addrmap(AS_PROGRAM, &pbaction_state::pbaction_alt_sound_map);
m_audiocpu->irqack_cb().set(FUNC(pbaction_state::sound_irq_clear));
MACHINE_CONFIG_END
/***************************************************************************
@ -531,7 +663,7 @@ ROM_START( pbactiont )
ROM_REGION( 0x10000, "audiocpu", 0 ) /* 64k for sound board */
ROM_LOAD( "pba1.bin", 0x0000, 0x2000, CRC(8b69b933) SHA1(eb0762579d52ed9f5b1a002ffe7e517c59650e22) )
ROM_REGION( 0x10000, "cpu2", 0 ) /* 64k for the 2xZ80 subboard (not emulated) */
ROM_REGION( 0x10000, "subcpu", 0 ) /* 64k for the subboard */
ROM_LOAD( "pba17.bin", 0x0000, 0x4000, CRC(2734ae60) SHA1(4edcdfac1611c49c4f890609efbe8352b8161f8e) )
ROM_REGION( 0x06000, "fgchars", 0 )
@ -576,8 +708,8 @@ void pbaction_state::init_pbaction2()
// some of these are probably bootlegs
GAME( 1985, pbaction, 0, pbaction, pbaction, pbaction_state, empty_init, ROT90, "Tehkan", "Pinball Action (set 1)", MACHINE_SUPPORTS_SAVE )
GAME( 1985, pbaction2, pbaction, pbactionx, pbaction, pbaction_state, init_pbaction2, ROT90, "Tehkan", "Pinball Action (set 2, encrypted)", MACHINE_SUPPORTS_SAVE )
GAME( 1985, pbaction3, pbaction, pbactionx, pbaction, pbaction_state, empty_init, ROT90, "Tehkan", "Pinball Action (set 3, encrypted)", MACHINE_SUPPORTS_SAVE )
GAME( 1985, pbaction4, pbaction, pbactionx, pbaction, pbaction_state, empty_init, ROT90, "Tehkan", "Pinball Action (set 4, encrypted)", MACHINE_SUPPORTS_SAVE )
GAME( 1985, pbactiont, pbaction, pbactiont, pbaction, pbaction_state, empty_init, ROT90, "Tehkan (Tecfri license)", "Pinball Action (Tecfri license)", MACHINE_SUPPORTS_SAVE )
GAME( 1985, pbaction, 0, pbaction, pbaction, pbaction_state, empty_init, ROT90, "Tehkan", "Pinball Action (set 1)", MACHINE_SUPPORTS_SAVE ) // possible bootleg due to not being encrypted + different sound map
GAME( 1985, pbaction2, pbaction, pbactionx, pbaction, pbaction_state, init_pbaction2, ROT90, "Tehkan", "Pinball Action (set 2, encrypted)", MACHINE_SUPPORTS_SAVE ) // likely bootleg due to extra protection on top of usual
GAME( 1985, pbaction3, pbaction, pbactionx, pbaction, pbaction_state, empty_init, ROT90, "Tehkan", "Pinball Action (set 3, encrypted)", MACHINE_SUPPORTS_SAVE ) // possible bootleg due to oversized ROMs
GAME( 1985, pbaction4, pbaction, pbactionx, pbaction, pbaction_state, empty_init, ROT90, "Tehkan", "Pinball Action (set 4, encrypted)", MACHINE_SUPPORTS_SAVE ) // original?
GAMEL(1985, pbactiont, pbaction, pbactiont, pbaction, pbaction_tecfri_state, empty_init, ROT90, "Tehkan (Tecfri license)", "Pinball Action (Tecfri license)", MACHINE_SUPPORTS_SAVE, layout_pbactiont )

View File

@ -52,6 +52,7 @@ public:
required_device<z80ctc_device> m_ctc;
optional_shared_ptr<uint8_t> m_decrypted_opcodes;
emu_timer *m_soundcommand_timer;
uint8_t m_nmi_mask;
DECLARE_WRITE8_MEMBER(pbaction_sh_command_w);
TIMER_CALLBACK_MEMBER(sound_trigger);
@ -77,11 +78,53 @@ public:
DECLARE_WRITE_LINE_MEMBER(sound_irq_clear);
void draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect );
void pbaction(machine_config &config);
void pbactiont(machine_config &config);
void pbactionx(machine_config &config);
void decrypted_opcodes_map(address_map &map);
void pbaction_map(address_map &map);
void pbaction_sound_io_map(address_map &map);
void pbaction_sound_map(address_map &map);
void pbactiont_sound_map(address_map &map);
void pbaction_alt_sound_map(address_map &map);
};
class pbaction_tecfri_state : public pbaction_state
{
public:
pbaction_tecfri_state(const machine_config &mconfig, device_type type, const char *tag)
: pbaction_state(mconfig, type, tag),
m_subcpu(*this, "subcpu"),
m_ctc2(*this, "ctc2"),
m_maintosublatch(*this, "maintosublatch"),
//m_subtomainlatch(*this, "subtomainlatch"),
m_digits(*this, "digit%u", 0U) { }
void pbactiont(machine_config &config);
protected:
virtual void machine_start() override;
private:
void pbaction_tecfri_sub_map(address_map &map);
void pbaction_tecfri_sub_io_map(address_map &map);
void pbaction_tecfri_main_io_map(address_map &map);
TIMER_CALLBACK_MEMBER(sub_trigger);
emu_timer *m_subcommand_timer;
DECLARE_READ8_MEMBER(subcpu_r);
DECLARE_WRITE8_MEMBER(subcpu_w);
DECLARE_WRITE8_MEMBER(pbaction_tecfri_sub8000_w);
DECLARE_WRITE8_MEMBER(pbaction_tecfri_sub8001_w);
DECLARE_WRITE8_MEMBER(pbaction_tecfri_sub8008_w);
DECLARE_WRITE8_MEMBER(pbaction_tecfri_subtomain_w);
DECLARE_READ8_MEMBER(pbaction_tecfri_maintosub_r);
required_device<z80_device> m_subcpu;
required_device<z80ctc_device> m_ctc2;
required_device<generic_latch_8_device> m_maintosublatch;
//required_device<generic_latch_8_device> m_subtomainlatch;
output_finder<24> m_digits;
uint8_t m_outlatch;
uint32_t m_outdata;
};

View File

@ -0,0 +1,194 @@
<?xml version="1.0"?>
<mamelayout version="2">
<!-- Mini Flipper cabinet, used by Tecfri versions of Pinball Action -->
<!-- based on Speed Ball layout, which used a similar cabinet -->
<!-- define elements -->
<element name="static_black">
<rect>
<color red="0.0" green="0.0" blue="0.0" />
</rect>
</element>
<element name="static_red">
<rect>
<color red="0.6" green="0.2" blue="0.2" />
</rect>
</element>
<element name="digit" defstate="0">
<led7seg>
<color red="1.0" green="0.3" blue="0.0" />
</led7seg>
</element>
<element name="text_p1">
<text string="1 PLAYER">
<color red="1.0" green="1.0" blue="1.0" />
</text>
</element>
<element name="text_p2">
<text string="2 PLAYER">
<color red="1.0" green="1.0" blue="1.0" />
</text>
</element>
<element name="text_credit">
<text string="CREDIT">
<color red="1.0" green="1.0" blue="1.0" />
</text>
</element>
<element name="text_ball">
<text string="BALL">
<color red="1.0" green="1.0" blue="1.0" />
</text>
</element>
<element name="text_bonus">
<text string="BONUS">
<color red="1.0" green="1.0" blue="1.0" />
</text>
</element>
<view name="Simple LEDs">
<bounds left="0" right="300" top="-35" bottom="400" />
<screen index="0">
<bounds left="0" top="0" right="300" bottom="400" />
</screen>
<!-- player 1 score -->
<bezel element="static_red">
<bounds left="4" top="-23" right="86" bottom="-5" />
</bezel>
<bezel element="static_black">
<bounds left="5" top="-22" right="85" bottom="-6" />
</bezel>
<bezel element="text_p1">
<bounds left="4" top="-34" right="86" bottom="-25" />
</bezel>
<bezel name="digit0" element="digit">
<bounds left="10" top="-20" right="20" bottom="-8" />
</bezel>
<bezel name="digit1" element="digit">
<bounds left="20" top="-20" right="30" bottom="-8" />
</bezel>
<bezel name="digit2" element="digit">
<bounds left="30" top="-20" right="40" bottom="-8" />
</bezel>
<bezel name="digit3" element="digit">
<bounds left="40" top="-20" right="50" bottom="-8" />
</bezel>
<bezel name="digit4" element="digit">
<bounds left="50" top="-20" right="60" bottom="-8" />
</bezel>
<bezel name="digit5" element="digit">
<bounds left="60" top="-20" right="70" bottom="-8" />
</bezel>
<bezel name="digit6" element="digit">
<bounds left="70" top="-20" right="80" bottom="-8" />
</bezel>
<!-- credit -->
<bezel element="static_red">
<bounds left="104" top="-23" right="136" bottom="-5" />
</bezel>
<bezel element="static_black">
<bounds left="105" top="-22" right="135" bottom="-6" />
</bezel>
<bezel element="text_credit">
<bounds left="104" top="-34" right="136" bottom="-25" />
</bezel>
<bezel name="digit15" element="digit">
<bounds left="110" top="-20" right="120" bottom="-8" />
</bezel>
<bezel name="digit16" element="digit">
<bounds left="120" top="-20" right="130" bottom="-8" />
</bezel>
<!-- ball -->
<!-- note: digit14 (before credit) and digit17 (before ball) are left unused -->
<bezel element="static_red">
<bounds left="139" top="-23" right="161" bottom="-5" />
</bezel>
<bezel element="static_black">
<bounds left="140" top="-22" right="160" bottom="-6" />
</bezel>
<bezel element="text_ball">
<bounds left="139" top="-34" right="161" bottom="-25" />
</bezel>
<bezel name="digit18" element="digit">
<bounds left="145" top="-20" right="155" bottom="-8" />
</bezel>
<!-- bonus -->
<bezel element="static_red">
<bounds left="164" top="-23" right="196" bottom="-5" />
</bezel>
<bezel element="static_black">
<bounds left="165" top="-22" right="195" bottom="-6" />
</bezel>
<bezel element="text_bonus">
<bounds left="164" top="-34" right="196" bottom="-25" />
</bezel>
<bezel name="digit19" element="digit">
<bounds left="170" top="-20" right="180" bottom="-8" />
</bezel>
<bezel name="digit20" element="digit">
<bounds left="180" top="-20" right="190" bottom="-8" />
</bezel>
<!-- player 2 score -->
<bezel element="static_red">
<bounds left="214" top="-23" right="296" bottom="-5" />
</bezel>
<bezel element="static_black">
<bounds left="215" top="-22" right="295" bottom="-6" />
</bezel>
<bezel element="text_p2">
<bounds left="214" top="-34" right="296" bottom="-25" />
</bezel>
<bezel name="digit7" element="digit">
<bounds left="220" top="-20" right="230" bottom="-8" />
</bezel>
<bezel name="digit8" element="digit">
<bounds left="230" top="-20" right="240" bottom="-8" />
</bezel>
<bezel name="digit9" element="digit">
<bounds left="240" top="-20" right="250" bottom="-8" />
</bezel>
<bezel name="digit10" element="digit">
<bounds left="250" top="-20" right="260" bottom="-8" />
</bezel>
<bezel name="digit11" element="digit">
<bounds left="260" top="-20" right="270" bottom="-8" />
</bezel>
<bezel name="digit12" element="digit">
<bounds left="270" top="-20" right="280" bottom="-8" />
</bezel>
<bezel name="digit13" element="digit">
<bounds left="280" top="-20" right="290" bottom="-8" />
</bezel>
</view>
</mamelayout>