diff --git a/src/devices/cpu/z80/r800.h b/src/devices/cpu/z80/r800.h index 75fbe7b5ca8..69f8a922738 100644 --- a/src/devices/cpu/z80/r800.h +++ b/src/devices/cpu/z80/r800.h @@ -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); } diff --git a/src/devices/cpu/z80/z80.h b/src/devices/cpu/z80/z80.h index cffcfb21917..b97e9ff2d5f 100644 --- a/src/devices/cpu/z80/z80.h +++ b/src/devices/cpu/z80/z80.h @@ -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; } diff --git a/src/mame/universal/docastle.cpp b/src/mame/universal/docastle.cpp index cbfae56c611..2f1b6faee54 100644 --- a/src/mame/universal/docastle.cpp +++ b/src/mame/universal/docastle.cpp @@ -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. */ diff --git a/src/mame/universal/docastle.h b/src/mame/universal/docastle.h index 4b9f3ac67fd..e2a0ce43fe9 100644 --- a/src/mame/universal/docastle.h +++ b/src/mame/universal/docastle.h @@ -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 m_maincpu; - required_device m_slave; - required_device m_cpu3; + required_device m_subcpu; + required_device m_spritecpu; required_device m_crtc; + required_device_array m_sn; optional_device m_msm; required_device_array m_inp; - /* memory pointers */ + // memory pointers required_shared_ptr m_videoram; required_shared_ptr m_colorram; required_shared_ptr m_spriteram; @@ -60,37 +64,40 @@ private: required_device m_gfxdecode; required_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; diff --git a/src/mame/universal/docastle_m.cpp b/src/mame/universal/docastle_m.cpp index 789bab3f34c..238c35ac7c2 100644 --- a/src/mame/universal/docastle_m.cpp +++ b/src/mame/universal/docastle_m.cpp @@ -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); } diff --git a/src/mame/universal/docastle_v.cpp b/src/mame/universal/docastle_v.cpp index d63b1fb8df7..8dbef40911c 100644 --- a/src/mame/universal/docastle_v.cpp +++ b/src/mame/universal/docastle_v.cpp @@ -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,