summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/segahang.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/drivers/segahang.cpp')
-rw-r--r--src/mame/drivers/segahang.cpp119
1 files changed, 64 insertions, 55 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;
@@ -306,29 +339,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));
}
@@ -2229,18 +2244,12 @@ 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;
}
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 )