From 566a741f4fda9be53504eb9bc965bd9f1649ae2d Mon Sep 17 00:00:00 2001 From: Dirk Best Date: Sun, 19 Sep 2021 17:45:33 +0200 Subject: sharrier: Hook up MCU, remove simulation (#8552) - The MCU for the sharrier1 set is handcrafted and marked BAD_DUMP - There is a slight issue with the initial synchronisation, so there is a hack to ignore the problematic write --- src/mame/drivers/segahang.cpp | 119 +++++++++++++++++++++++------------------- src/mame/includes/segahang.h | 15 ++---- 2 files changed, 69 insertions(+), 65 deletions(-) diff --git a/src/mame/drivers/segahang.cpp b/src/mame/drivers/segahang.cpp index d3cbc2ea8c3..177790b7e98 100644 --- a/src/mame/drivers/segahang.cpp +++ b/src/mame/drivers/segahang.cpp @@ -27,6 +27,10 @@ #include "speaker.h" +#define LOG_MCU (1 << 1) +//#define VERBOSE (LOG_MCU) +#include "logmacro.h" + //************************************************************************** @@ -242,19 +246,50 @@ uint8_t segahang_state::sound_data_r() //************************************************************************** -// I8751-RELATED VBLANK INTERRUPT HANDLERS +// I8751 PROTECTION MCU //************************************************************************** -//------------------------------------------------- -// i8751_main_cpu_vblank - if we have a fake -// handler, we hook this to execute it -//------------------------------------------------- +uint8_t segahang_state::i8751_r(offs_t offset) +{ + offs_t addr = (m_i8751_addr << 16) | (offset ^ 1); + uint8 data = m_maincpu->space(AS_PROGRAM).read_byte(addr); + + LOGMASKED(LOG_MCU, "i8751_r: %06x = %02x\n", addr, data); + + return data; +} + +void segahang_state::i8751_w(offs_t offset, uint8_t data) +{ + offs_t addr = (m_i8751_addr << 16) | (offset ^ 1); -INTERRUPT_GEN_MEMBER( segahang_state::i8751_main_cpu_vblank ) + // hack, either the cpu is too fast or the mcu too slow or there + // is some kind of synchronization missing. either way, the mcu + // clears this value after the cpu sets it. + if (addr == 0x40385) + return; + + m_maincpu->space(AS_PROGRAM).write_byte(addr, data); + + LOGMASKED(LOG_MCU, "i8751_w: %06x = %02x\n", addr, data); +} + +void segahang_state::i8751_p1_w(uint8_t data) { - // if we have a fake 8751 handler, call it on VBLANK - if (!m_i8751_vblank_hook.isnull()) - m_i8751_vblank_hook(); + // 7------- halt? (not used by the mcu code) + // -6------ a20 + // --5----- a18 + // ---4---- a17 + // ----3--- a16 + // -----210 68k ipl + + m_i8751_addr = (BIT(data, 6) << 4) | ((data & 0x38) >> 3); + int irq = ~data & 0x07; + + LOGMASKED(LOG_MCU, "i8751_p1_w: %d %02x %d\n", BIT(data, 7), m_i8751_addr, irq); + + if (irq) + m_maincpu->set_input_line(irq, HOLD_LINE); } @@ -272,7 +307,7 @@ void segahang_state::machine_reset() // reset misc components m_segaic16vid->tilemap_reset(*m_screen); - // queue up a timer to either boost interleave or disable the MCU + // queue up a timer to boost interleave synchronize(TID_INIT_I8751); // reset global state @@ -288,11 +323,9 @@ void segahang_state::device_timer(emu_timer &timer, device_timer_id id, int para { switch (id) { - // if we have a fake i8751 handler, disable the actual 8751, otherwise crank the interleave + // crank the interleave case TID_INIT_I8751: - if (!m_i8751_vblank_hook.isnull()) - m_mcu->suspend(SUSPEND_REASON_DISABLE, 1); - else if (m_mcu != nullptr) + if (m_mcu != nullptr) machine().scheduler().boost_interleave(attotime::zero, attotime::from_msec(10)); break; @@ -305,29 +338,6 @@ void segahang_state::device_timer(emu_timer &timer, device_timer_id id, int para -//************************************************************************** -// I8751 SIMULATIONS -//************************************************************************** - -//------------------------------------------------- -// sharrier_i8751_sim - simulate the I8751 -// from Space Harrier -//------------------------------------------------- - -void segahang_state::sharrier_i8751_sim() -{ - // signal a VBLANK to the main CPU - m_maincpu->set_input_line(4, HOLD_LINE); - - // disable timer-based protection - m_workram[0x090/2] = 1; - - // read I/O ports - m_workram[0x492/2] = (m_adc_ports[0]->read() << 8) | m_adc_ports[1]->read(); -} - - - //************************************************************************** // MAIN CPU ADDRESS MAPS //************************************************************************** @@ -370,6 +380,8 @@ void segahang_state::sharrier_map(address_map &map) map(0x140010, 0x140017).mirror(0xffc8).r(FUNC(segahang_state::sharrier_inputs_r)).umask16(0x00ff); map(0x140020, 0x140027).mirror(0xffc8).rw(m_i8255_2, FUNC(i8255_device::read), FUNC(i8255_device::write)).umask16(0x00ff); map(0x140031, 0x140031).mirror(0xffce).rw(m_adc, FUNC(adc0804_device::read), FUNC(adc0804_device::write)); + map(0x150000, 0x150001).mirror(0xfffe).nopw(); // mcu writes 0x1c here in its vblank irq + map(0x170000, 0x170001).mirror(0xfffe).nopr(); // mcu reads here (by accident?) map(0xc68000, 0xc68fff).ram().share("segaic16road:roadram"); } @@ -447,6 +459,7 @@ void segahang_state::sound_portmap_2203x2(address_map &map) void segahang_state::mcu_io_map(address_map &map) { + map(0x0000, 0xffff).rw(FUNC(segahang_state::i8751_r), FUNC(segahang_state::i8751_w)); } @@ -902,10 +915,11 @@ void segahang_state::sharrier(machine_config &config) sharrier_base(config); sound_board_2203(config); - m_maincpu->set_vblank_int("screen", FUNC(segahang_state::i8751_main_cpu_vblank)); + m_maincpu->remove_vblank_int(); I8751(config, m_mcu, 8000000); m_mcu->set_addrmap(AS_IO, &segahang_state::mcu_io_map); + m_mcu->port_out_cb<1>().set(FUNC(segahang_state::i8751_p1_w)); m_screen->screen_vblank().set_inputline("mcu", INPUT_LINE_IRQ0); } @@ -1595,8 +1609,8 @@ ROM_START( sharrier1 ) ROM_LOAD( "epr-7231.ic5", 0x00000, 0x8000, CRC(871c6b14) SHA1(6d04ddc32fdf1db409cb519890821bd10fc9e58b) ) ROM_LOAD( "epr-7232.ic6", 0x08000, 0x8000, CRC(4b59340c) SHA1(a01ba8580b65dd17bfd92560265e502d95d3ff16) ) - ROM_REGION( 0x10000, "mcu", 0 ) // Internal i8751 MCU code - ROM_LOAD( "315-5163.ic32", 0x00000, 0x1000, NO_DUMP ) + ROM_REGION( 0x10000, "mcu", 0 ) // handcrafted from decapped rev a mcu + ROM_LOAD( "315-5163.ic32", 0x00000, 0x1000, BAD_DUMP CRC(52b0c81a) SHA1(11a910949e61bb1376d15f538557b9ff210c8dc7) ) ROM_REGION( 0x2000, "sprites:zoom", 0 ) // zoom table ROM_LOAD( "epr-6844.ic123", 0x0000, 0x2000, CRC(e3ec7bd6) SHA1(feec0fe664e16fac0fde61cf64b401b9b0575323) ) @@ -2218,6 +2232,7 @@ void segahang_state::init_generic() // save states save_item(NAME(m_adc_select)); save_item(NAME(m_shadow)); + save_item(NAME(m_i8751_addr)); } @@ -2226,13 +2241,6 @@ void segahang_state::init_generic() //------------------------------------------------- void segahang_state::init_sharrier() -{ - init_generic(); - m_sharrier_video = true; - m_i8751_vblank_hook = i8751_sim_delegate(&segahang_state::sharrier_i8751_sim, this); -} - -void segahang_state::init_enduror() { init_generic(); m_sharrier_video = true; @@ -2240,7 +2248,8 @@ void segahang_state::init_enduror() void segahang_state::init_endurobl() { - init_enduror(); + init_sharrier(); + // assemble decrypted half of ROM and register it uint16_t *rom = reinterpret_cast(memregion("maincpu")->base()); memcpy(&m_decrypted_opcodes[0x00000/2], rom + 0x30000/2, 0x10000); @@ -2249,7 +2258,7 @@ void segahang_state::init_endurobl() void segahang_state::init_endurob2() { - init_enduror(); + init_sharrier(); // assemble decrypted half of ROM and register it uint16_t *rom = reinterpret_cast(memregion("maincpu")->base()); @@ -2276,12 +2285,12 @@ GAME( 1987, shangonrb2, shangon, shangupb, shangupb, segahang_state, init_gene GAME( 1985, sharrier, 0, sharrier, sharrier, segahang_state, init_sharrier, ROT0, "Sega", "Space Harrier (Rev A, 8751 315-5163A)", 0 ) GAME( 1985, sharrier1, sharrier, sharrier, sharrier, segahang_state, init_sharrier, ROT0, "Sega", "Space Harrier (8751 315-5163)", 0 ) -GAME( 1986, enduror, 0, enduror, enduror, segahang_state, init_enduror, ROT0, "Sega", "Enduro Racer (Rev A, YM2151, FD1089B 317-0013A)", 0 ) -GAME( 1986, endurora, enduror, enduror, enduror, segahang_state, init_enduror, ROT0, "Sega", "Enduro Racer (Rev A, YM2151, mask ROM sprites, FD1089B 317-0013A)", 0 ) -GAME( 1986, endurorb, enduror, enduror, enduror, segahang_state, init_enduror, ROT0, "Sega", "Enduro Racer (YM2151, FD1089B 317-0013A)", 0 ) -GAME( 1986, enduror1, enduror, enduror1, enduror, segahang_state, init_enduror, ROT0, "Sega", "Enduro Racer (YM2203, FD1089B 317-0013A)", 0 ) +GAME( 1986, enduror, 0, enduror, enduror, segahang_state, init_sharrier, ROT0, "Sega", "Enduro Racer (Rev A, YM2151, FD1089B 317-0013A)", 0 ) +GAME( 1986, endurora, enduror, enduror, enduror, segahang_state, init_sharrier, ROT0, "Sega", "Enduro Racer (Rev A, YM2151, mask ROM sprites, FD1089B 317-0013A)", 0 ) +GAME( 1986, endurorb, enduror, enduror, enduror, segahang_state, init_sharrier, ROT0, "Sega", "Enduro Racer (YM2151, FD1089B 317-0013A)", 0 ) +GAME( 1986, enduror1, enduror, enduror1, enduror, segahang_state, init_sharrier, ROT0, "Sega", "Enduro Racer (YM2203, FD1089B 317-0013A)", 0 ) GAME( 1986, endurobl, enduror, endurobl, enduror, segahang_state, init_endurobl, ROT0, "bootleg", "Enduro Racer (bootleg set 1)", 0 ) GAME( 1986, endurob2, enduror, endurob2, enduror, segahang_state, init_endurob2, ROT0, "bootleg", "Enduro Racer (bootleg set 2)", MACHINE_NOT_WORKING ) -GAME( 1986, endurord, enduror, endurord, enduror, segahang_state, init_enduror, ROT0, "bootleg", "Enduro Racer (bootleg of Rev A, YM2151, FD1089B 317-0013A set)", 0 ) -GAME( 1986, enduror1d, enduror, enduror1d, enduror, segahang_state, init_enduror, ROT0, "bootleg", "Enduro Racer (bootleg of YM2203, FD1089B 317-0013A set)", 0 ) +GAME( 1986, endurord, enduror, endurord, enduror, segahang_state, init_sharrier, ROT0, "bootleg", "Enduro Racer (bootleg of Rev A, YM2151, FD1089B 317-0013A set)", 0 ) +GAME( 1986, enduror1d, enduror, enduror1d, enduror, segahang_state, init_sharrier, ROT0, "bootleg", "Enduro Racer (bootleg of YM2203, FD1089B 317-0013A set)", 0 ) diff --git a/src/mame/includes/segahang.h b/src/mame/includes/segahang.h index 88841e5eea6..7456b330193 100644 --- a/src/mame/includes/segahang.h +++ b/src/mame/includes/segahang.h @@ -68,7 +68,6 @@ public: // game-specific driver init void init_generic(); void init_sharrier(); - void init_enduror(); void init_endurobl(); void init_endurob2(); @@ -90,8 +89,11 @@ private: // Z80 sound CPU read/write handlers uint8_t sound_data_r(); - // I8751-related VBLANK interrupt handlers - INTERRUPT_GEN_MEMBER( i8751_main_cpu_vblank ); + // I8751 + uint8_t i8751_r(offs_t offset); + void i8751_w(offs_t offset, uint8_t data); + void i8751_p1_w(uint8_t data); + uint8_t m_i8751_addr; // video updates uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); @@ -108,9 +110,6 @@ private: void sound_portmap_2203x2(address_map &map); void sub_map(address_map &map); - // internal types - typedef delegate i8751_sim_delegate; - // timer IDs enum { @@ -124,9 +123,6 @@ private: virtual void machine_reset() override; virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; - // I8751 simulations - void sharrier_i8751_sim(); - // devices required_device m_maincpu; required_device m_subcpu; @@ -146,7 +142,6 @@ private: // configuration bool m_sharrier_video; - i8751_sim_delegate m_i8751_vblank_hook; // internal state uint8_t m_adc_select; -- cgit v1.2.3