docastle: remove main-sub comms hack, hook up sn ready pin

This commit is contained in:
hap 2024-11-15 22:48:02 +01:00
parent fffd5250ab
commit 2d94f582a9
6 changed files with 203 additions and 196 deletions

View File

@ -31,7 +31,6 @@ protected:
virtual void device_validity_check(validity_checker &valid) const override;
// device_execute_interface overrides
virtual u32 execute_min_cycles() const noexcept override { return 1; }
virtual u64 execute_clocks_to_cycles(u64 clocks) const noexcept override { return (clocks + 4 - 1) / 4; }
virtual u64 execute_cycles_to_clocks(u64 cycles) const noexcept override { return (cycles * 4); }

View File

@ -53,7 +53,7 @@ protected:
// device_execute_interface implementation
virtual bool cpu_is_interruptible() const override { return true; }
virtual u32 execute_min_cycles() const noexcept override { return 2; }
virtual u32 execute_min_cycles() const noexcept override { return 1; }
virtual u32 execute_max_cycles() const noexcept override { return 16; }
virtual u32 execute_default_irq_vector(int inputnum) const noexcept override { return 0xff; }
virtual bool execute_input_edge_triggered(int inputnum) const noexcept override { return inputnum == INPUT_LINE_NMI; }

View File

@ -108,25 +108,11 @@ a800 sound port 3
ac00 sound port 4
Notes:
------
- All inputs are read through the TMS1025N2LC at D8 (low 4 bits) and F8
(high 4 bits). Pins 11-16, 18 and 27-34 of both devices are linked to the
edge connector, though several of these input lines are typically unused.
- idsoccer seems to run on a modified version of this board which allows for
more sprite tiles; it also has an extra sound board for ADPCM playback.
TODO:
-----
- Third CPU. According to schematics, it's a doorway for the sprite RAM. The
main cpu actually doesn't have full access to sprite RAM. But instead, 0x9800
to 0x9fff is a latch to the 3rd cpu. CPU3 reads 0x200 bytes from maincpu, and
then passes it through (unmodified) presumedly to the sprite chip. It looks
very much like hardware protection. And it's easy to circumvent in MAME by
pretending the maincpu directly writes to sprite RAM.
- docastle schematics say that maincpu(and cpu3) interrupt comes from the 6845
CURSOR pin. The cursor is configured at scanline 0, and causes the games to
update the next video frame during active display. What is the culprit here?
For now, it's simply hooked up to vsync.
- dip switch reading bug. dorunrun and docastle are VERY timing sensitive, and
dip switch reading will fail if timing is not completely accurate.
- the dorunrun attract mode sequence is also very timing sensitive. The behaviour
@ -153,6 +139,17 @@ TODO:
differently, however it hasn't been compared with the real board so it might be
right.
TODO:
- Third CPU. According to schematics, it's a doorway for the sprite RAM. The
main cpu actually doesn't have full access to sprite RAM. But instead, 0x9800
to 0x9fff is a latch to the 3rd cpu. CPU3 reads 0x200 bytes from maincpu, and
then passes it through (unmodified) presumedly to the sprite chip. It looks
very much like hardware protection. And it's easy to circumvent in MAME by
pretending the maincpu directly writes to sprite RAM.
- docastle schematics say that maincpu(and CPU3) interrupt comes from the 6845
CURSOR pin. The cursor is configured at scanline 0, and causes the games to
update the next video frame during active display. What is the culprit here?
For now, it's simply hooked up to vsync.
- bad communication in idsoccer
- adpcm status in idsoccer
- real values for the adpcm interface in idsoccer
@ -160,14 +157,10 @@ TODO:
- idsoccer clones lock up MAME after writing junk to CRTC. Workaround:
idsoccera/idsoccert: maincpu bp 1120 -> pc=1123 -> run
asoccer: maincpu bp 1120 -> pc=1135 -> run
Or simply ROM_FILL(0x247, 1, 0x23 or 0x35 instead of 0x20) on the slave cpu (not
Or simply ROM_FILL(0x247, 1, 0x23 or 0x35 instead of 0x20) on the subcpu (not
guaranteed that a permanent ROM hack like this won't break anything).
This 0x1120 is a return address written to the stack after communicating with
the slave CPU. Maybe protection. See MT05419.
2008-08
Dip locations verified with manual for docastle, dorunrun and dowild.
the subcpu. Maybe protection. See MT05419.
***************************************************************************/
@ -175,8 +168,9 @@ Dip locations verified with manual for docastle, dorunrun and dowild.
#include "docastle.h"
#include "cpu/z80/z80.h"
#include "machine/input_merger.h"
#include "machine/watchdog.h"
#include "sound/sn76496.h"
#include "screen.h"
#include "speaker.h"
@ -188,7 +182,7 @@ void docastle_state::docastle_tint(int state)
{
int ma6 = m_crtc->get_ma() & 0x40;
if (ma6 && !m_prev_ma6) // MA6 rising edge
m_slave->set_input_line(0, HOLD_LINE);
m_subcpu->set_input_line(0, HOLD_LINE);
m_prev_ma6 = ma6;
}
}
@ -240,23 +234,23 @@ void docastle_state::docastle_map(address_map &map)
map(0x0000, 0x7fff).rom();
map(0x8000, 0x97ff).ram();
map(0x9800, 0x99ff).ram().share("spriteram");
map(0xa000, 0xa008).rw(FUNC(docastle_state::docastle_shared0_r), FUNC(docastle_state::docastle_shared1_w));
map(0xa000, 0xa000).mirror(0x07ff).rw(FUNC(docastle_state::main_from_sub_r), FUNC(docastle_state::main_to_sub_w));
map(0xa800, 0xa800).w("watchdog", FUNC(watchdog_timer_device::reset_w));
map(0xb000, 0xb3ff).mirror(0x0800).ram().w(FUNC(docastle_state::docastle_videoram_w)).share("videoram");
map(0xb400, 0xb7ff).mirror(0x0800).ram().w(FUNC(docastle_state::docastle_colorram_w)).share("colorram");
map(0xe000, 0xe000).w(FUNC(docastle_state::docastle_nmitrigger_w));
map(0xb000, 0xb3ff).mirror(0x0800).ram().w(FUNC(docastle_state::videoram_w)).share("videoram");
map(0xb400, 0xb7ff).mirror(0x0800).ram().w(FUNC(docastle_state::colorram_w)).share("colorram");
map(0xe000, 0xe000).w(FUNC(docastle_state::subcpu_nmi_w));
}
void docastle_state::docastle_map2(address_map &map)
{
map(0x0000, 0x3fff).rom();
map(0x8000, 0x87ff).ram();
map(0xa000, 0xa008).rw(FUNC(docastle_state::docastle_shared1_r), FUNC(docastle_state::docastle_shared0_w));
map(0xa000, 0xa000).mirror(0x07ff).rw(FUNC(docastle_state::sub_from_main_r), FUNC(docastle_state::sub_to_main_w));
map(0xc000, 0xc007).select(0x0080).rw(FUNC(docastle_state::inputs_flipscreen_r), FUNC(docastle_state::flipscreen_w));
map(0xe000, 0xe000).w("sn1", FUNC(sn76489a_device::write));
map(0xe400, 0xe400).w("sn2", FUNC(sn76489a_device::write));
map(0xe800, 0xe800).w("sn3", FUNC(sn76489a_device::write));
map(0xec00, 0xec00).w("sn4", FUNC(sn76489a_device::write));
map(0xe000, 0xe000).w(m_sn[0], FUNC(sn76489a_device::write));
map(0xe400, 0xe400).w(m_sn[1], FUNC(sn76489a_device::write));
map(0xe800, 0xe800).w(m_sn[2], FUNC(sn76489a_device::write));
map(0xec00, 0xec00).w(m_sn[3], FUNC(sn76489a_device::write));
}
void docastle_state::docastle_map3(address_map &map)
@ -281,23 +275,23 @@ void docastle_state::dorunrun_map(address_map &map)
map(0x2000, 0x37ff).ram();
map(0x3800, 0x39ff).ram().share("spriteram");
map(0x4000, 0x9fff).rom();
map(0xa000, 0xa008).rw(FUNC(docastle_state::docastle_shared0_r), FUNC(docastle_state::docastle_shared1_w));
map(0xa000, 0xa000).mirror(0x07ff).rw(FUNC(docastle_state::main_from_sub_r), FUNC(docastle_state::main_to_sub_w));
map(0xa800, 0xa800).w("watchdog", FUNC(watchdog_timer_device::reset_w));
map(0xb000, 0xb3ff).ram().w(FUNC(docastle_state::docastle_videoram_w)).share("videoram");
map(0xb400, 0xb7ff).ram().w(FUNC(docastle_state::docastle_colorram_w)).share("colorram");
map(0xb800, 0xb800).w(FUNC(docastle_state::docastle_nmitrigger_w));
map(0xb000, 0xb3ff).ram().w(FUNC(docastle_state::videoram_w)).share("videoram");
map(0xb400, 0xb7ff).ram().w(FUNC(docastle_state::colorram_w)).share("colorram");
map(0xb800, 0xb800).w(FUNC(docastle_state::subcpu_nmi_w));
}
void docastle_state::dorunrun_map2(address_map &map)
{
map(0x0000, 0x3fff).rom();
map(0x8000, 0x87ff).ram();
map(0xa000, 0xa000).w("sn1", FUNC(sn76489a_device::write));
map(0xa400, 0xa400).w("sn2", FUNC(sn76489a_device::write));
map(0xa800, 0xa800).w("sn3", FUNC(sn76489a_device::write));
map(0xac00, 0xac00).w("sn4", FUNC(sn76489a_device::write));
map(0xa000, 0xa000).w(m_sn[0], FUNC(sn76489a_device::write));
map(0xa400, 0xa400).w(m_sn[1], FUNC(sn76489a_device::write));
map(0xa800, 0xa800).w(m_sn[2], FUNC(sn76489a_device::write));
map(0xac00, 0xac00).w(m_sn[3], FUNC(sn76489a_device::write));
map(0xc000, 0xc007).select(0x0080).rw(FUNC(docastle_state::inputs_flipscreen_r), FUNC(docastle_state::flipscreen_w));
map(0xe000, 0xe008).rw(FUNC(docastle_state::docastle_shared1_r), FUNC(docastle_state::docastle_shared0_w));
map(0xe000, 0xe000).mirror(0x07ff).rw(FUNC(docastle_state::sub_from_main_r), FUNC(docastle_state::sub_to_main_w));
}
@ -307,12 +301,12 @@ void docastle_state::idsoccer_map(address_map &map)
map(0x4000, 0x57ff).ram();
map(0x5800, 0x59ff).ram().share("spriteram");
map(0x6000, 0x9fff).rom();
map(0xa000, 0xa008).rw(FUNC(docastle_state::docastle_shared0_r), FUNC(docastle_state::docastle_shared1_w));
map(0xa000, 0xa000).mirror(0x07ff).rw(FUNC(docastle_state::main_from_sub_r), FUNC(docastle_state::main_to_sub_w));
map(0xa800, 0xa800).w("watchdog", FUNC(watchdog_timer_device::reset_w));
map(0xb000, 0xb3ff).mirror(0x0800).ram().w(FUNC(docastle_state::docastle_videoram_w)).share("videoram");
map(0xb400, 0xb7ff).mirror(0x0800).ram().w(FUNC(docastle_state::docastle_colorram_w)).share("colorram");
map(0xb000, 0xb3ff).mirror(0x0800).ram().w(FUNC(docastle_state::videoram_w)).share("videoram");
map(0xb400, 0xb7ff).mirror(0x0800).ram().w(FUNC(docastle_state::colorram_w)).share("colorram");
map(0xc000, 0xc000).rw(FUNC(docastle_state::idsoccer_adpcm_status_r), FUNC(docastle_state::idsoccer_adpcm_w));
map(0xe000, 0xe000).w(FUNC(docastle_state::docastle_nmitrigger_w));
map(0xe000, 0xe000).w(FUNC(docastle_state::subcpu_nmi_w));
}
/* Input Ports */
@ -503,7 +497,7 @@ static INPUT_PORTS_START( idsoccer )
PORT_DIPSETTING( 0x02, DEF_STR( Medium ) )
PORT_DIPSETTING( 0x01, DEF_STR( Hard ) )
PORT_DIPSETTING( 0x00, DEF_STR( Hardest ) )
PORT_DIPNAME( 0x04, 0x04, "One Player vs. Computer" ) PORT_DIPLOCATION("SW1:!6") // Additional time extended for winning score
PORT_DIPNAME( 0x04, 0x04, "One Player vs. Computer" ) PORT_DIPLOCATION("SW1:!6") // Additional time extended for winning score
PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x08, 0x08, DEF_STR( Flip_Screen ) ) PORT_DIPLOCATION("SW1:5")
@ -544,17 +538,14 @@ GFXDECODE_END
void docastle_state::machine_reset()
{
for (int i = 0; i < 9; i++)
{
m_buffer0[i] = 0;
m_buffer1[i] = 0;
}
m_prev_ma6 = 0;
m_adpcm_pos = m_adpcm_idle = 0;
m_adpcm_data = -1;
m_adpcm_status = 0;
m_maincpu_defer_access = false;
m_subcpu_defer_access = false;
for (int i = 0; i < 2; i++)
{
m_inp[i]->write_ms(0); // pin 5 tied low
@ -571,8 +562,10 @@ void docastle_state::machine_start()
save_item(NAME(m_adpcm_data));
save_item(NAME(m_adpcm_idle));
save_item(NAME(m_adpcm_status));
save_item(NAME(m_buffer0));
save_item(NAME(m_buffer1));
save_item(NAME(m_shared_latch));
save_item(NAME(m_maincpu_defer_access));
save_item(NAME(m_subcpu_defer_access));
}
void docastle_state::docastle(machine_config &config)
@ -582,11 +575,11 @@ void docastle_state::docastle(machine_config &config)
m_maincpu->set_addrmap(AS_PROGRAM, &docastle_state::docastle_map);
m_maincpu->set_addrmap(AS_IO, &docastle_state::docastle_io_map);
Z80(config, m_slave, XTAL(4'000'000));
m_slave->set_addrmap(AS_PROGRAM, &docastle_state::docastle_map2);
Z80(config, m_subcpu, XTAL(4'000'000));
m_subcpu->set_addrmap(AS_PROGRAM, &docastle_state::docastle_map2);
Z80(config, m_cpu3, XTAL(4'000'000));
m_cpu3->set_addrmap(AS_PROGRAM, &docastle_state::docastle_map3);
Z80(config, m_spritecpu, XTAL(4'000'000));
m_spritecpu->set_addrmap(AS_PROGRAM, &docastle_state::docastle_map3);
TMS1025(config, m_inp[0]);
m_inp[0]->read_port1_callback().set_ioport("DSW2");
@ -617,7 +610,7 @@ void docastle_state::docastle(machine_config &config)
m_crtc->set_visarea_adjust(8,-8,0,0);
m_crtc->set_char_width(8);
m_crtc->out_vsync_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
m_crtc->out_vsync_callback().append_inputline(m_cpu3, INPUT_LINE_NMI);
m_crtc->out_vsync_callback().append_inputline(m_spritecpu, INPUT_LINE_NMI);
m_crtc->out_hsync_callback().set(FUNC(docastle_state::docastle_tint));
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
@ -630,10 +623,18 @@ void docastle_state::docastle(machine_config &config)
/* sound hardware */
SPEAKER(config, "mono").front_center();
SN76489A(config, "sn1", 4_MHz_XTAL).add_route(ALL_OUTPUTS, "mono", 0.25);
SN76489A(config, "sn2", 4_MHz_XTAL).add_route(ALL_OUTPUTS, "mono", 0.25);
SN76489A(config, "sn3", 4_MHz_XTAL).add_route(ALL_OUTPUTS, "mono", 0.25);
SN76489A(config, "sn4", 4_MHz_XTAL).add_route(ALL_OUTPUTS, "mono", 0.25);
SN76489A(config, m_sn[0], 4_MHz_XTAL).add_route(ALL_OUTPUTS, "mono", 0.25);
SN76489A(config, m_sn[1], 4_MHz_XTAL).add_route(ALL_OUTPUTS, "mono", 0.25);
SN76489A(config, m_sn[2], 4_MHz_XTAL).add_route(ALL_OUTPUTS, "mono", 0.25);
SN76489A(config, m_sn[3], 4_MHz_XTAL).add_route(ALL_OUTPUTS, "mono", 0.25);
input_merger_device &sn_ready(INPUT_MERGER_ANY_LOW(config, "sn_ready"));
sn_ready.output_handler().set_inputline(m_subcpu, Z80_INPUT_LINE_WAIT);
m_sn[0]->ready_cb().set("sn_ready", FUNC(input_merger_device::in_w<0>));
m_sn[1]->ready_cb().set("sn_ready", FUNC(input_merger_device::in_w<1>));
m_sn[2]->ready_cb().set("sn_ready", FUNC(input_merger_device::in_w<2>));
m_sn[3]->ready_cb().set("sn_ready", FUNC(input_merger_device::in_w<3>));
}
void docastle_state::dorunrun(machine_config &config)
@ -642,7 +643,7 @@ void docastle_state::dorunrun(machine_config &config)
/* basic machine hardware */
m_maincpu->set_addrmap(AS_PROGRAM, &docastle_state::dorunrun_map);
m_slave->set_addrmap(AS_PROGRAM, &docastle_state::dorunrun_map2);
m_subcpu->set_addrmap(AS_PROGRAM, &docastle_state::dorunrun_map2);
/* video hardware */
MCFG_VIDEO_START_OVERRIDE(docastle_state,dorunrun)
@ -677,10 +678,10 @@ ROM_START( docastle )
ROM_LOAD( "01l_a3.bin", 0x4000, 0x2000, CRC(71a70ba9) SHA1(0c9e4c402f82d61d573eb55b3e2e0c8b7c8b7028) )
ROM_LOAD( "01k_a4.bin", 0x6000, 0x2000, CRC(479a745e) SHA1(7195036727990932bc94b30405ebc2b8ea5b37a8) )
ROM_REGION( 0x10000, "slave", 0 )
ROM_REGION( 0x10000, "subcpu", 0 )
ROM_LOAD( "07n_a0.bin", 0x0000, 0x4000, CRC(f23b5cdb) SHA1(de71d9f142f8d420aa097d7e56b03a06db2f85fd) )
ROM_REGION( 0x10000, "cpu3", 0 )
ROM_REGION( 0x10000, "spritecpu", 0 )
ROM_LOAD( "01d.bin", 0x0000, 0x0200, CRC(2747ca77) SHA1(abc0ca05925974c4b852827605ee2f1caefb8524) )
ROM_REGION( 0x4000, "gfx1", 0 )
@ -703,10 +704,10 @@ ROM_START( docastle2 )
ROM_LOAD( "a3", 0x4000, 0x2000, CRC(a1f04ffb) SHA1(8cb53992cc679278a0bd33e5b728f27c585e38e1) )
ROM_LOAD( "a4", 0x6000, 0x2000, CRC(1fb14aa6) SHA1(45b50db61ca2c9ace182ddba3817257308f07c89) )
ROM_REGION( 0x10000, "slave", 0 )
ROM_REGION( 0x10000, "subcpu", 0 )
ROM_LOAD( "a10", 0x0000, 0x4000, CRC(45f7f69b) SHA1(1c614c29be4950314ab04e0b828e691fd0907eff) )
ROM_REGION( 0x10000, "cpu3", 0 )
ROM_REGION( 0x10000, "spritecpu", 0 )
ROM_LOAD( "01d.bin", 0x0000, 0x0200, CRC(2747ca77) SHA1(abc0ca05925974c4b852827605ee2f1caefb8524) )
ROM_REGION( 0x4000, "gfx1", 0 )
@ -729,10 +730,10 @@ ROM_START( docastleo )
ROM_LOAD( "c3.bin", 0x4000, 0x2000, CRC(c8c13124) SHA1(2cfc15b232744b40350c174b0d89677495c077eb) )
ROM_LOAD( "c4.bin", 0x6000, 0x2000, CRC(7ca78471) SHA1(2804f9be825973e69bc35aa703145b3ef22a5ecd) )
ROM_REGION( 0x10000, "slave", 0 )
ROM_REGION( 0x10000, "subcpu", 0 )
ROM_LOAD( "dorev10.bin", 0x0000, 0x4000, CRC(4b1925e3) SHA1(1b229dd73eede3853d23576dfe397a4d2d952991) )
ROM_REGION( 0x10000, "cpu3", 0 )
ROM_REGION( 0x10000, "spritecpu", 0 )
ROM_LOAD( "01d.bin", 0x0000, 0x0200, CRC(2747ca77) SHA1(abc0ca05925974c4b852827605ee2f1caefb8524) )
ROM_REGION( 0x4000, "gfx1", 0 )
@ -757,10 +758,10 @@ ROM_START( douni )
ROM_LOAD( "dorev3.bin", 0x4000, 0x2000, CRC(7b9e2061) SHA1(2b21af54018a2ff756d80ba0b53b71108c0ce043) )
ROM_LOAD( "dorev4.bin", 0x6000, 0x2000, CRC(e013954d) SHA1(1e05937f3b6eaef77c36b485da091ebb22e50f85) )
ROM_REGION( 0x10000, "slave", 0 )
ROM_REGION( 0x10000, "subcpu", 0 )
ROM_LOAD( "dorev10.bin", 0x0000, 0x4000, CRC(4b1925e3) SHA1(1b229dd73eede3853d23576dfe397a4d2d952991) )
ROM_REGION( 0x10000, "cpu3", 0 )
ROM_REGION( 0x10000, "spritecpu", 0 )
ROM_LOAD( "01d.bin", 0x0000, 0x0200, CRC(2747ca77) SHA1(abc0ca05925974c4b852827605ee2f1caefb8524) )
ROM_REGION( 0x4000, "gfx1", 0 )
@ -783,10 +784,10 @@ ROM_START( dorunrunc )
ROM_LOAD( "rev-0-3.l1", 0x4000, 0x2000, CRC(e9b8181a) SHA1(6b960c3503589e62b61f9a2af372b98c48412bc0) )
ROM_LOAD( "rev-0-4.k1", 0x6000, 0x2000, CRC(a63d0b89) SHA1(d2ab3b76149e6620f1eb93a051c802b208b8d6dc) )
ROM_REGION( 0x10000, "slave", 0 )
ROM_REGION( 0x10000, "subcpu", 0 )
ROM_LOAD( "rev-0-2.n7", 0x0000, 0x4000, CRC(6dac2fa3) SHA1(cd583f379f01788ce20f611f17689105d32ef97a) )
ROM_REGION( 0x10000, "cpu3", 0 )
ROM_REGION( 0x10000, "spritecpu", 0 )
ROM_LOAD( "bprom2.bin", 0x0000, 0x0200, CRC(2747ca77) SHA1(abc0ca05925974c4b852827605ee2f1caefb8524) )
ROM_REGION( 0x4000, "gfx1", 0 )
@ -809,10 +810,10 @@ ROM_START( dorunrunca )
ROM_LOAD( "runrunc_l1", 0x4000, 0x2000, CRC(223927ca) SHA1(8ae5587b4266d54ba7e8756ad07c867869ce3364) )
ROM_LOAD( "runrunc_k1", 0x6000, 0x2000, CRC(5edd6752) SHA1(c7483755e2115420ab8a17287e4adfcd9bd1b5c4) )
ROM_REGION( 0x10000, "slave", 0 )
ROM_REGION( 0x10000, "subcpu", 0 )
ROM_LOAD( "rev-0-2.n7", 0x0000, 0x4000, CRC(6dac2fa3) SHA1(cd583f379f01788ce20f611f17689105d32ef97a) )
ROM_REGION( 0x10000, "cpu3", 0 )
ROM_REGION( 0x10000, "spritecpu", 0 )
ROM_LOAD( "bprom2.bin", 0x0000, 0x0200, CRC(2747ca77) SHA1(abc0ca05925974c4b852827605ee2f1caefb8524) )
ROM_REGION( 0x4000, "gfx1", 0 )
@ -836,10 +837,10 @@ ROM_START( runrun )
ROM_LOAD( "electric_3.bin", 0x4000, 0x2000, CRC(e9b8181a) SHA1(6b960c3503589e62b61f9a2af372b98c48412bc0) )
ROM_LOAD( "electric_4.bin", 0x6000, 0x2000, CRC(a63d0b89) SHA1(d2ab3b76149e6620f1eb93a051c802b208b8d6dc) )
ROM_REGION( 0x10000, "slave", 0 )
ROM_REGION( 0x10000, "subcpu", 0 )
ROM_LOAD( "electric_10.bin", 0x0000, 0x4000, CRC(6dac2fa3) SHA1(cd583f379f01788ce20f611f17689105d32ef97a) )
ROM_REGION( 0x10000, "cpu3", 0 )
ROM_REGION( 0x10000, "spritecpu", 0 )
ROM_LOAD( "bprom2.bin", 0x0000, 0x0200, BAD_DUMP CRC(2747ca77) SHA1(abc0ca05925974c4b852827605ee2f1caefb8524) ) // not dumped for this set
ROM_REGION( 0x4000, "gfx1", 0 )
@ -862,10 +863,10 @@ ROM_START( dorunrun )
ROM_LOAD( "2764.k1", 0x6000, 0x2000, CRC(b1195d3d) SHA1(095ad2ee1f53be3203830263cb0c9efbe4710c56) )
ROM_LOAD( "2764.n1", 0x8000, 0x2000, CRC(6a8160d1) SHA1(12101c351bf800319172c459b5e7c69cb5603806) )
ROM_REGION( 0x10000, "slave", 0 )
ROM_REGION( 0x10000, "subcpu", 0 )
ROM_LOAD( "27128.p7", 0x0000, 0x4000, CRC(8b06d461) SHA1(2434478810c6301197997be76505f5fc6beba5d3) )
ROM_REGION( 0x10000, "cpu3", 0 )
ROM_REGION( 0x10000, "spritecpu", 0 )
ROM_LOAD( "bprom2.bin", 0x0000, 0x0200, CRC(2747ca77) SHA1(abc0ca05925974c4b852827605ee2f1caefb8524) )
ROM_REGION( 0x4000, "gfx1", 0 )
@ -888,10 +889,10 @@ ROM_START( dorunrun2 )
ROM_LOAD( "k1", 0x6000, 0x2000, CRC(099aaf54) SHA1(c0419db2a2349ecb97c31256811993d1dcf3dc6e) )
ROM_LOAD( "n1", 0x8000, 0x2000, CRC(4f8fcbae) SHA1(c1558664e081252141530e1932403df1fbf5f8a0) )
ROM_REGION( 0x10000, "slave", 0 )
ROM_REGION( 0x10000, "subcpu", 0 )
ROM_LOAD( "27128.p7", 0x0000, 0x4000, CRC(8b06d461) SHA1(2434478810c6301197997be76505f5fc6beba5d3) )
ROM_REGION( 0x10000, "cpu3", 0 )
ROM_REGION( 0x10000, "spritecpu", 0 )
ROM_LOAD( "bprom2.bin", 0x0000, 0x0200, CRC(2747ca77) SHA1(abc0ca05925974c4b852827605ee2f1caefb8524) )
ROM_REGION( 0x4000, "gfx1", 0 )
@ -914,10 +915,10 @@ ROM_START( spiero )
ROM_LOAD( "sp4.bin", 0x6000, 0x2000, CRC(639b4e5d) SHA1(cf252869fa0c5351f093026996c4e372f19a52a9) )
ROM_LOAD( "sp2.bin", 0x8000, 0x2000, CRC(3a29ccb0) SHA1(37d6ce598a9c3b5dbb23c19a4bd94265287f83f7) )
ROM_REGION( 0x10000, "slave", 0 )
ROM_REGION( 0x10000, "subcpu", 0 )
ROM_LOAD( "27128.p7", 0x0000, 0x4000, CRC(8b06d461) SHA1(2434478810c6301197997be76505f5fc6beba5d3) )
ROM_REGION( 0x10000, "cpu3", 0 )
ROM_REGION( 0x10000, "spritecpu", 0 )
ROM_LOAD( "bprom2.bin", 0x0000, 0x0200, CRC(2747ca77) SHA1(abc0ca05925974c4b852827605ee2f1caefb8524) )
ROM_REGION( 0x4000, "gfx1", 0 )
@ -940,10 +941,10 @@ ROM_START( dowild ) // UNIVERSAL 8339A PCB
ROM_LOAD( "w4", 0x6000, 0x2000, CRC(8aac1d30) SHA1(c746f5506a541b25a7ca6fc754fbdb94212f7178) )
ROM_LOAD( "w2", 0x8000, 0x2000, CRC(0914ab69) SHA1(048a68976d313015ff40f411d5c89d318fd9bb04) )
ROM_REGION( 0x10000, "slave", 0 )
ROM_REGION( 0x10000, "subcpu", 0 )
ROM_LOAD( "w10", 0x0000, 0x4000, CRC(d1f37fba) SHA1(827e2e3b140c4df2fd8780d7d05dc45694cf8f02) )
ROM_REGION( 0x10000, "cpu3", 0 )
ROM_REGION( 0x10000, "spritecpu", 0 )
ROM_LOAD( "8300b-2", 0x0000, 0x0200, CRC(2747ca77) SHA1(abc0ca05925974c4b852827605ee2f1caefb8524) )
ROM_REGION( 0x4000, "gfx1", 0 )
@ -966,10 +967,10 @@ ROM_START( jjack )
ROM_LOAD( "j4.bin", 0x6000, 0x2000, CRC(35bb316a) SHA1(8461503179eb7798de6f9f6677eb18ebcd22d470) )
ROM_LOAD( "j2.bin", 0x8000, 0x2000, CRC(dec52e80) SHA1(1620a070a75115d7c35f44574a8b53ce137ce21a) )
ROM_REGION( 0x10000, "slave", 0 )
ROM_REGION( 0x10000, "subcpu", 0 )
ROM_LOAD( "j0.bin", 0x0000, 0x4000, CRC(ab042f04) SHA1(06412dbdc43ebd6d376a811f240a4c9ec43ca6e7) )
ROM_REGION( 0x10000, "cpu3", 0 )
ROM_REGION( 0x10000, "spritecpu", 0 )
ROM_LOAD( "bprom2.bin", 0x0000, 0x0200, CRC(2747ca77) SHA1(abc0ca05925974c4b852827605ee2f1caefb8524) )
ROM_REGION( 0x4000, "gfx1", 0 )
@ -992,10 +993,10 @@ ROM_START( kickridr )
ROM_LOAD( "k4", 0x6000, 0x2000, CRC(a67dd2ec) SHA1(d35eefd314c7a7d9badffc8a19270380f01e263c) )
ROM_LOAD( "k2", 0x8000, 0x2000, CRC(e193fb5c) SHA1(3719c012bb1d75e79aa111093864b6e6bb46bc8c) )
ROM_REGION( 0x10000, "slave", 0 )
ROM_REGION( 0x10000, "subcpu", 0 )
ROM_LOAD( "k10", 0x0000, 0x4000, CRC(6843dbc0) SHA1(8a83f785e1fc2fa34a9955c19e27a1968a6d3f08) )
ROM_REGION( 0x10000, "cpu3", 0 )
ROM_REGION( 0x10000, "spritecpu", 0 )
ROM_LOAD( "8300b-2", 0x0000, 0x0200, CRC(2747ca77) SHA1(abc0ca05925974c4b852827605ee2f1caefb8524) )
ROM_REGION( 0x4000, "gfx1", 0 )
@ -1018,10 +1019,10 @@ ROM_START( idsoccer )
ROM_LOAD( "id03", 0x6000, 0x2000, CRC(22524661) SHA1(363528a1135d11ead03c76064042a72e0ac93533) )
ROM_LOAD( "id04", 0x8000, 0x2000, CRC(e8cd95fd) SHA1(2e272c154bd5dd2dca58d3fe12c6ba5e01a62477) )
ROM_REGION( 0x10000, "slave", 0 )
ROM_REGION( 0x10000, "subcpu", 0 )
ROM_LOAD( "id10", 0x0000, 0x4000, CRC(6c8b2037) SHA1(718d680186623d5af23ed272f04e726fbb17f078) )
ROM_REGION( 0x10000, "cpu3", 0 )
ROM_REGION( 0x10000, "spritecpu", 0 )
ROM_LOAD( "id_8p", 0x0000, 0x0200, CRC(2747ca77) SHA1(abc0ca05925974c4b852827605ee2f1caefb8524) )
ROM_REGION( 0x8000, "gfx1", 0 )
@ -1048,10 +1049,10 @@ ROM_START( idsoccera )
ROM_LOAD( "indoor.f10", 0x2000, 0x2000, CRC(54e5c6fc) SHA1(2c5a1e7bb9c8d5877eb99e8d20498986b85a8af4) )
ROM_LOAD( "indoor.h10", 0x6000, 0x2000, CRC(f0ca1ac8) SHA1(fa5724ba8ab0ff82a1ef22ddd56e57b4c2b6ab74) )
ROM_REGION( 0x10000, "slave", 0 )
ROM_REGION( 0x10000, "subcpu", 0 )
ROM_LOAD( "indoor.e2", 0x0000, 0x4000, CRC(c4bacc14) SHA1(d457a24b084726fe6b2f97a1be44e67c0a61a97b) ) // different
ROM_REGION( 0x10000, "cpu3", 0 )
ROM_REGION( 0x10000, "spritecpu", 0 )
ROM_LOAD( "indoor.p8", 0x0000, 0x0200, CRC(2747ca77) SHA1(abc0ca05925974c4b852827605ee2f1caefb8524) )
ROM_REGION( 0x8000, "gfx1", 0 )
@ -1080,10 +1081,10 @@ ROM_START( idsoccert ) // UNIVERSAL 8461-A (with TECFRI SA logo) + UNIVERSAL 846
ROM_LOAD( "2.f10", 0x2000, 0x2000, CRC(68b9764b) SHA1(73811d71aef4c43ea99a8a578b38e7836d377536) )
ROM_LOAD( "3.h10", 0x6000, 0x2000, CRC(5baabe1f) SHA1(12afaeac45ce03499614708edd171f20f3b4a73d) )
ROM_REGION( 0x10000, "slave", 0 )
ROM_REGION( 0x10000, "subcpu", 0 )
ROM_LOAD( "9.e2", 0x0000, 0x4000, CRC(c4bacc14) SHA1(d457a24b084726fe6b2f97a1be44e67c0a61a97b) )
ROM_REGION( 0x10000, "cpu3", 0 )
ROM_REGION( 0x10000, "spritecpu", 0 )
ROM_LOAD( "82s147.p8", 0x0000, 0x0200, CRC(2747ca77) SHA1(abc0ca05925974c4b852827605ee2f1caefb8524) )
ROM_REGION( 0x8000, "gfx1", 0 )
@ -1119,10 +1120,10 @@ ROM_START( asoccer )
ROM_LOAD( "as3.h10", 0x06000, 0x2000, CRC(25bbd0d8) SHA1(fa7fb4b78e5ac4200ff5f57f94794632af450ce0) )
ROM_LOAD( "as4.k10", 0x08000, 0x2000, CRC(8d8bdc08) SHA1(75da310576047102af45c3a5f7d20893ef260d40) )
ROM_REGION( 0x10000, "slave", 0 ) /* These roms are located on the 8461-A board. */
ROM_REGION( 0x10000, "subcpu", 0 ) /* These roms are located on the 8461-A board. */
ROM_LOAD( "as0.e2", 0x00000, 0x4000, CRC(05d613bf) SHA1(ab822fc532fc7f1122b5ff0385b268513e7e193e) )
ROM_REGION( 0x10000, "cpu3", 0 ) /* These roms are located on the 8461-A board. */
ROM_REGION( 0x10000, "spritecpu", 0 ) /* These roms are located on the 8461-A board. */
ROM_LOAD( "200b.p8", 0x00000, 0x0200, CRC(2747ca77) SHA1(abc0ca05925974c4b852827605ee2f1caefb8524) ) /* 82S147 PROM */
ROM_REGION( 0x8000, "gfx1", 0 ) /* These roms are located on the 8461-A board. */

View File

@ -13,6 +13,8 @@
#include "machine/tms1024.h"
#include "video/mc6845.h"
#include "sound/msm5205.h"
#include "sound/sn76496.h"
#include "emupal.h"
#include "tilemap.h"
@ -22,9 +24,10 @@ public:
docastle_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_slave(*this, "slave"),
m_cpu3(*this, "cpu3"),
m_subcpu(*this, "subcpu"),
m_spritecpu(*this, "spritecpu"),
m_crtc(*this, "crtc"),
m_sn(*this, "sn%u", 1U),
m_msm(*this, "msm"),
m_inp(*this, "inp%u", 1),
m_videoram(*this, "videoram"),
@ -44,15 +47,16 @@ protected:
virtual void video_start() override ATTR_COLD;
private:
/* devices */
// devices
required_device<cpu_device> m_maincpu;
required_device<cpu_device> m_slave;
required_device<cpu_device> m_cpu3;
required_device<cpu_device> m_subcpu;
required_device<cpu_device> m_spritecpu;
required_device<hd6845s_device> m_crtc;
required_device_array<sn76489a_device, 4> m_sn;
optional_device<msm5205_device> m_msm;
required_device_array<tms1025_device, 2> m_inp;
/* memory pointers */
// memory pointers
required_shared_ptr<uint8_t> m_videoram;
required_shared_ptr<uint8_t> m_colorram;
required_shared_ptr<uint8_t> m_spriteram;
@ -60,37 +64,40 @@ private:
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
/* video-related */
tilemap_t *m_do_tilemap = nullptr;
// misc
int m_prev_ma6 = 0;
int m_adpcm_pos = 0;
int m_adpcm_idle = 0;
int m_adpcm_data = 0;
int m_adpcm_status = 0;
/* misc */
int m_prev_ma6 = 0;
int m_adpcm_pos = 0;
int m_adpcm_idle = 0;
int m_adpcm_data = 0;
int m_adpcm_status = 0;
uint8_t m_buffer0[9]{};
uint8_t m_buffer1[9]{};
uint8_t m_shared_latch = 0;
bool m_maincpu_defer_access = false;
bool m_subcpu_defer_access = false;
uint8_t docastle_shared0_r(offs_t offset);
uint8_t docastle_shared1_r(offs_t offset);
void docastle_shared0_w(offs_t offset, uint8_t data);
void docastle_shared1_w(offs_t offset, uint8_t data);
void docastle_nmitrigger_w(uint8_t data);
void docastle_videoram_w(offs_t offset, uint8_t data);
void docastle_colorram_w(offs_t offset, uint8_t data);
tilemap_t *m_do_tilemap = nullptr;
uint8_t main_from_sub_r();
void main_to_sub_w(uint8_t data);
uint8_t sub_from_main_r();
void sub_to_main_w(uint8_t data);
void subcpu_nmi_w(uint8_t data);
void videoram_w(offs_t offset, uint8_t data);
void colorram_w(offs_t offset, uint8_t data);
uint8_t inputs_flipscreen_r(offs_t offset);
void flipscreen_w(offs_t offset, uint8_t data);
uint8_t idsoccer_adpcm_status_r();
void idsoccer_adpcm_w(uint8_t data);
TILE_GET_INFO_MEMBER(get_tile_info);
void docastle_palette(palette_device &palette) const;
DECLARE_VIDEO_START(dorunrun);
uint32_t screen_update_docastle(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
void video_start_common( uint32_t tile_transmask );
void draw_sprites( screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect );
void video_start_common(uint32_t tile_transmask);
void draw_sprites(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
void docastle_tint(int state);
void idsoccer_adpcm_int(int state);
void docastle_io_map(address_map &map) ATTR_COLD;
void docastle_map(address_map &map) ATTR_COLD;
void docastle_map2(address_map &map) ATTR_COLD;

View File

@ -2,8 +2,6 @@
// copyright-holders:Brad Oliver
/***************************************************************************
machine.c
Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
I/O ports)
@ -13,78 +11,80 @@
#include "cpu/z80/z80.h"
#include "docastle.h"
#define LOG 0
/*
THIS IS A GIANT HACK! It can be accurately emulated once our Z80 core supports WAIT.
Communication between the two CPUs happens through a single bidirectional latch.
Whenever CPU 0 reads or writes it, its WAIT input is asserted. It is implicitly
cleared by CPU 1, when it accesses the latch. This enforces synchronization
Whenever maincpu reads or writes it, its WAIT input is asserted. It is implicitly
cleared by subcpu, when it accesses the latch. This enforces synchronization
between the two CPUs.
This is currently impossible to reproduce accurately in MAME, because it would
require putting on hold CPU 0 while it is reading the latch, and resume its
execution only when CPU 1 has written it.
Instead, we take advantage of how the two CPUs access the latch, and treat it as
if it was a small shared buffer. The order of operations is:
1) CPU 0 triggers NMI on CPU 1
2) CPU 0 writes 9 bytes to the buffer
3) at this point we suspend execution of CPU 0, to give CPU 1 time to read the 9
bytes and write its own 9 bytes
4) resume execution of CPU 0.
It is initiated by maincpu triggering an NMI on subcpu. During this process,
timing needs to be cycle-accurate, both CPUs do LDIR opcodes in lockstep.
*/
uint8_t docastle_state::docastle_shared0_r(offs_t offset)
{
if (offset == 8 && LOG)
logerror("CPU #0 shared0r clock = %d\n", (uint32_t)m_maincpu->total_cycles());
return m_buffer0[offset];
uint8_t docastle_state::main_from_sub_r()
{
if (!machine().side_effects_disabled())
{
m_maincpu_defer_access = !m_maincpu_defer_access;
if (m_maincpu_defer_access)
{
machine().scheduler().perfect_quantum(attotime::from_usec(100));
m_maincpu->set_input_line(Z80_INPUT_LINE_WAIT, ASSERT_LINE);
// defer access to let subcpu write the latch and clear WAIT
m_maincpu->defer_access();
}
}
return m_shared_latch;
}
void docastle_state::main_to_sub_w(uint8_t data)
{
m_shared_latch = data;
machine().scheduler().perfect_quantum(attotime::from_usec(100));
m_maincpu->set_input_line(Z80_INPUT_LINE_WAIT, ASSERT_LINE);
}
uint8_t docastle_state::sub_from_main_r()
{
if (!machine().side_effects_disabled())
{
m_subcpu_defer_access = !m_subcpu_defer_access;
if (m_subcpu_defer_access)
{
// defer access to let maincpu react first
m_subcpu->defer_access();
}
else
m_maincpu->set_input_line(Z80_INPUT_LINE_WAIT, CLEAR_LINE);
}
return m_shared_latch;
}
void docastle_state::sub_to_main_w(uint8_t data)
{
m_subcpu_defer_access = !m_subcpu_defer_access;
if (m_subcpu_defer_access)
{
// defer access to let maincpu react first
m_subcpu->defer_access();
}
else
{
m_shared_latch = data;
m_maincpu->set_input_line(Z80_INPUT_LINE_WAIT, CLEAR_LINE);
}
}
uint8_t docastle_state::docastle_shared1_r(offs_t offset)
void docastle_state::subcpu_nmi_w(uint8_t data)
{
if (offset == 8 && LOG)
logerror("CPU #1 shared1r clock = %d\n", (uint32_t)m_slave->total_cycles());
return m_buffer1[offset];
}
void docastle_state::docastle_shared0_w(offs_t offset, uint8_t data)
{
if (offset == 8 && LOG)
logerror("CPU #1 shared0w %02x %02x %02x %02x %02x %02x %02x %02x %02x clock = %d\n",
m_buffer0[0], m_buffer0[1], m_buffer0[2], m_buffer0[3],
m_buffer0[4], m_buffer0[5], m_buffer0[6], m_buffer0[7],
data, (uint32_t)m_slave->total_cycles());
m_buffer0[offset] = data;
/* awake the master CPU */
if (offset == 8)
machine().scheduler().trigger(500);
}
void docastle_state::docastle_shared1_w(offs_t offset, uint8_t data)
{
m_buffer1[offset] = data;
if (offset == 8 && LOG)
logerror("CPU #0 shared1w %02x %02x %02x %02x %02x %02x %02x %02x %02x clock = %d\n",
m_buffer1[0], m_buffer1[1], m_buffer1[2], m_buffer1[3],
m_buffer1[4], m_buffer1[5], m_buffer1[6], m_buffer1[7],
data, (uint32_t)m_maincpu->total_cycles());
/* freeze execution of the master CPU until the slave has used the shared memory */
if (offset == 8)
m_maincpu->spin_until_trigger(500);
}
void docastle_state::docastle_nmitrigger_w(uint8_t data)
{
m_slave->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
m_subcpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
}

View File

@ -64,13 +64,13 @@ void docastle_state::docastle_palette(palette_device &palette) const
}
}
void docastle_state::docastle_videoram_w(offs_t offset, uint8_t data)
void docastle_state::videoram_w(offs_t offset, uint8_t data)
{
m_videoram[offset] = data;
m_do_tilemap->mark_tile_dirty(offset);
}
void docastle_state::docastle_colorram_w(offs_t offset, uint8_t data)
void docastle_state::colorram_w(offs_t offset, uint8_t data)
{
m_colorram[offset] = data;
m_do_tilemap->mark_tile_dirty(offset);
@ -107,7 +107,7 @@ TILE_GET_INFO_MEMBER(docastle_state::get_tile_info)
tileinfo.set(0, code, color, 0);
}
void docastle_state::video_start_common( uint32_t tile_transmask )
void docastle_state::video_start_common(uint32_t tile_transmask)
{
m_do_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(docastle_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
m_do_tilemap->set_scrolldy(-32, -32);
@ -124,7 +124,7 @@ VIDEO_START_MEMBER(docastle_state,dorunrun)
video_start_common(0xff00);
}
void docastle_state::draw_sprites( screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect )
void docastle_state::draw_sprites(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
screen.priority().fill(1);
@ -193,7 +193,7 @@ void docastle_state::draw_sprites( screen_device &screen, bitmap_rgb32 &bitmap,
flipy = !flipy;
}
/* first draw the sprite, visible */
// first draw the sprite, visible
m_gfxdecode->gfx(1)->prio_transmask(bitmap,cliprect,
code,
color,
@ -202,7 +202,7 @@ void docastle_state::draw_sprites( screen_device &screen, bitmap_rgb32 &bitmap,
screen.priority(),
0x00,0x80ff);
/* then draw the mask, behind the background but obscuring following sprites */
// then draw the mask, behind the background but obscuring following sprites
m_gfxdecode->gfx(1)->prio_transmask(bitmap,cliprect,
code,
color,