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
This commit is contained in:
Dirk Best 2021-09-19 17:45:33 +02:00 committed by GitHub
parent 4e972dc95b
commit 566a741f4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 70 additions and 66 deletions

View File

@ -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
//-------------------------------------------------
INTERRUPT_GEN_MEMBER( segahang_state::i8751_main_cpu_vblank )
uint8_t segahang_state::i8751_r(offs_t offset)
{
// if we have a fake 8751 handler, call it on VBLANK
if (!m_i8751_vblank_hook.isnull())
m_i8751_vblank_hook();
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);
// 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)
{
// 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<uint16_t *>(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<uint16_t *>(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 )

View File

@ -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<void ()> 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<m68000_device> m_maincpu;
required_device<m68000_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;