diff options
author | 2022-08-14 03:06:00 +0200 | |
---|---|---|
committer | 2022-08-14 03:06:11 +0200 | |
commit | e43684772fbb00e8d536feb64e9f114543475957 (patch) | |
tree | 493fc301d2de78472cf4eac408a47b92a2188f9f | |
parent | bb1b50429419b70f8912e81f07d4778824aa3a4d (diff) |
eturtles: add game speed control
-rw-r--r-- | src/devices/cpu/hmcs40/hmcs40.cpp | 13 | ||||
-rw-r--r-- | src/devices/cpu/hmcs40/hmcs40.h | 1 | ||||
-rw-r--r-- | src/devices/cpu/hmcs40/hmcs40op.cpp | 4 | ||||
-rw-r--r-- | src/mame/handheld/hh_hmcs40.cpp | 47 | ||||
-rw-r--r-- | src/mame/layout/microvision.lay | 2 |
5 files changed, 51 insertions, 16 deletions
diff --git a/src/devices/cpu/hmcs40/hmcs40.cpp b/src/devices/cpu/hmcs40/hmcs40.cpp index 5a2f8ff393d..841e37e1558 100644 --- a/src/devices/cpu/hmcs40/hmcs40.cpp +++ b/src/devices/cpu/hmcs40/hmcs40.cpp @@ -10,6 +10,11 @@ References: - opcode decoding by Tatsuyuki Satoh, Olivier Galibert, Kevin Horton, Lord Nightmare (verified a while later after new documentation was found) +TODO: +- Which opcodes block interrupt on next cycle? LPU is obvious, and Gakken Crazy Kong + (VFD tabletop game) locks up if CAL doesn't do it. Maybe BR? But that's a + dangerous assumption since tight infinite loops wouldn't work right anymore. + */ #include "emu.h" @@ -232,6 +237,7 @@ void hmcs40_cpu_device::device_start() memset(m_if, 0, sizeof(m_if)); m_tf = 0; memset(m_int, 0, sizeof(m_int)); + m_block_int = false; memset(m_r, 0, sizeof(m_r)); m_d = 0; @@ -262,7 +268,7 @@ void hmcs40_cpu_device::device_start() save_item(NAME(m_if)); save_item(NAME(m_tf)); save_item(NAME(m_int)); - + save_item(NAME(m_block_int)); save_item(NAME(m_r)); save_item(NAME(m_d)); @@ -558,9 +564,10 @@ void hmcs40_cpu_device::execute_run() m_prev_op = m_op; m_prev_pc = m_pc; - // check/handle interrupt, but not after LPU/BR/CAL - if (m_ie && (m_iri || m_irt) && (m_prev_op & 0x3e0) != 0x340 && (m_prev_op & 0x1c0) != 0x1c0) + // check/handle interrupt + if (m_ie && (m_iri || m_irt) && !m_block_int) do_interrupt(); + m_block_int = false; // fetch next opcode debugger_instruction_hook(m_pc); diff --git a/src/devices/cpu/hmcs40/hmcs40.h b/src/devices/cpu/hmcs40/hmcs40.h index 904bb91ab13..0738eab209a 100644 --- a/src/devices/cpu/hmcs40/hmcs40.h +++ b/src/devices/cpu/hmcs40/hmcs40.h @@ -153,6 +153,7 @@ protected: int m_eint_line; // which input_line caused an interrupt int m_halt; // internal HLT state u8 m_prescaler; // internal timer prescaler + bool m_block_int; // block interrupt on next cycle u16 m_pc; // Program Counter u16 m_prev_pc; diff --git a/src/devices/cpu/hmcs40/hmcs40op.cpp b/src/devices/cpu/hmcs40/hmcs40op.cpp index 8d07ef571dd..3469ce495ba 100644 --- a/src/devices/cpu/hmcs40/hmcs40op.cpp +++ b/src/devices/cpu/hmcs40/hmcs40op.cpp @@ -452,6 +452,7 @@ void hmcs40_cpu_device::op_cal() // CAL a: Subroutine Jump on Status 1 if (m_s) { + m_block_int = true; push_stack(); m_pc = m_op & 0x3f; // short calls default to page 0 } @@ -463,7 +464,10 @@ void hmcs40_cpu_device::op_lpu() { // LPU u: Load Program Counter Upper on Status 1 if (m_s) + { + m_block_int = true; m_page = m_op & 0x1f; + } else m_op |= 0x400; // indicate unhandled LPU } diff --git a/src/mame/handheld/hh_hmcs40.cpp b/src/mame/handheld/hh_hmcs40.cpp index 0d99bc0fee7..95e7ad53d66 100644 --- a/src/mame/handheld/hh_hmcs40.cpp +++ b/src/mame/handheld/hh_hmcs40.cpp @@ -107,8 +107,9 @@ ROM source notes when dumped from another model, but confident it's the same: TODO: - cgalaxn discrete sound (alien attacking sound effect) -- epacman2 booting the game in demo mode, pacman should take the shortest route to - the upper-left power pill: mcu cycle/interrupt timing related +- epacman2 booting the game in demo mode, pacman should take the shortest route + to the upper-left power pill, followed by going to the top-right power pill: + mcu cycle/interrupt timing related - kevtris's HMCS40 ROM dumps are incomplete, missing MCU factory test code from the 2nd half of the ROM, none of the games access it though and it's impossible to execute unless the chip is in testmode. @@ -3296,12 +3297,15 @@ public: void eturtles(machine_config &config); DECLARE_INPUT_CHANGED_MEMBER(input_changed) { update_int(); } + DECLARE_INPUT_CHANGED_MEMBER(game_speed) { set_clock(); } protected: virtual void machine_start() override; + virtual void machine_reset() override; required_device<cop411_cpu_device> m_audiocpu; + void set_clock(); void update_int(); virtual void update_display(); void plate_w(offs_t offset, u8 data); @@ -3321,8 +3325,20 @@ void eturtles_state::machine_start() save_item(NAME(m_cop_irq)); } +void eturtles_state::machine_reset() +{ + hh_hmcs40_state::machine_reset(); + set_clock(); +} + // handlers: maincpu side +void eturtles_state::set_clock() +{ + // maincpu clock is controlled by game speed knob, range is around 150kHz + m_maincpu->set_unscaled_clock(m_inputs[6]->read() * 1500 + 325000); +} + void eturtles_state::update_display() { // D10 also goes to the same plate as R13 @@ -3422,12 +3438,15 @@ static INPUT_PORTS_START( eturtles ) PORT_CONFSETTING( 0x02, "0 (Demo)" ) PORT_CONFSETTING( 0x00, "1" ) PORT_CONFSETTING( 0x01, "2" ) + + PORT_START("IN.6") + PORT_ADJUSTER(50, "Game Speed") PORT_CHANGED_MEMBER(DEVICE_SELF, eturtles_state, game_speed, 0) INPUT_PORTS_END void eturtles_state::eturtles(machine_config &config) { // basic machine hardware - HD38820(config, m_maincpu, 400000); // approximation + HD38820(config, m_maincpu, 400000); // see set_clock m_maincpu->write_r<0>().set(FUNC(eturtles_state::plate_w)); m_maincpu->write_r<1>().set(FUNC(eturtles_state::plate_w)); m_maincpu->write_r<2>().set(FUNC(eturtles_state::plate_w)); @@ -3469,8 +3488,8 @@ ROM_START( eturtles ) ROM_REGION( 0x0200, "audiocpu", 0 ) ROM_LOAD( "cop411l-ked_n", 0x0000, 0x0200, CRC(503d26e9) SHA1(a53d24d62195bfbceff2e4a43199846e0950aef6) ) - ROM_REGION( 1027614, "screen", 0) - ROM_LOAD( "eturtles.svg", 0, 1027614, CRC(0f77eeab) SHA1(903d5e22bd83e63725ebe914914682370e978a71) ) + ROM_REGION( 1027549, "screen", 0) + ROM_LOAD( "eturtles.svg", 0, 1027549, CRC(34c16de6) SHA1(039be17b2df4beecab637cebbe48c3e3b3c2797e) ) ROM_END @@ -3531,23 +3550,25 @@ void estargte_state::cop_vol_w(u8 data) // config static INPUT_PORTS_START( estargte ) - PORT_START("IN.0") // D1 INT0/1 + PORT_INCLUDE( eturtles ) + + PORT_MODIFY("IN.0") // D1 INT0/1 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_CHANGED_MEMBER(DEVICE_SELF, eturtles_state, input_changed, 0) PORT_NAME("Inviso") PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_CHANGED_MEMBER(DEVICE_SELF, eturtles_state, input_changed, 0) PORT_NAME("Smart Bomb") - PORT_START("IN.1") // D2 INT0/1 + PORT_MODIFY("IN.1") // D2 INT0/1 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_CHANGED_MEMBER(DEVICE_SELF, eturtles_state, input_changed, 0) PORT_NAME("Fire") PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, eturtles_state, input_changed, 0) PORT_NAME("Change Direction") - PORT_START("IN.2") // D3 INT0/1 + PORT_MODIFY("IN.2") // D3 INT0/1 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_CHANGED_MEMBER(DEVICE_SELF, eturtles_state, input_changed, 0) PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_CHANGED_MEMBER(DEVICE_SELF, eturtles_state, input_changed, 0) - PORT_START("IN.3") // D4 INT0/1 + PORT_MODIFY("IN.3") // D4 INT0/1 PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_CHANGED_MEMBER(DEVICE_SELF, eturtles_state, input_changed, 0) PORT_NAME("Thrust") PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED ) - PORT_START("IN.4") // D5 INT0/1 + PORT_MODIFY("IN.4") // D5 INT0/1 PORT_CONFNAME( 0x11, 0x00, DEF_STR( Players ) ) PORT_CHANGED_MEMBER(DEVICE_SELF, eturtles_state, input_changed, 0) PORT_CONFSETTING( 0x10, "0 (Demo)" ) // yes, same value as 1-player, hold the Inviso button at boot to enter demo mode PORT_CONFSETTING( 0x00, "1" ) @@ -3556,14 +3577,14 @@ static INPUT_PORTS_START( estargte ) PORT_CONFSETTING( 0x00, "1" ) PORT_CONFSETTING( 0x02, "2" ) - PORT_START("IN.5") // D6 INT0/1 + PORT_MODIFY("IN.5") // D6 INT0/1 PORT_BIT( 0x03, IP_ACTIVE_HIGH, IPT_UNUSED ) INPUT_PORTS_END void estargte_state::estargte(machine_config &config) { // basic machine hardware - HD38820(config, m_maincpu, 400000); // approximation + HD38820(config, m_maincpu, 400000); // see set_clock m_maincpu->write_r<0>().set(FUNC(estargte_state::plate_w)); m_maincpu->write_r<1>().set(FUNC(estargte_state::plate_w)); m_maincpu->write_r<2>().set(FUNC(estargte_state::plate_w)); @@ -4015,6 +4036,8 @@ ROM_END * Hitachi HD38820L53 MCU (SDIP) * cyan/red/green VFD + Entex Defender is possibly the same game, but with a cyan/red VFD. + ***************************************************************************/ class gdefender_state : public hh_hmcs40_state diff --git a/src/mame/layout/microvision.lay b/src/mame/layout/microvision.lay index f9e00cb0310..fa72aa8e6f1 100644 --- a/src/mame/layout/microvision.lay +++ b/src/mame/layout/microvision.lay @@ -10,7 +10,7 @@ license:CC0 <element name="lcdm"><rect><color red="0.59" green="0.60" blue="0.44" /></rect></element> <element name="lcda"><rect><color red="0.17" green="0.15" blue="0.27" /></rect></element> <!-- blue tint --> - <element name="nothing" defstate="0"><text string=" "/></element> + <element name="nothing" defstate="0"><rect><color alpha="0" /></rect></element> <element name="text_p1"><text string="PADDLE:" align="2"><color red="0.1" green="0.1" blue="0.1" /></text></element> <element name="text_p2" defstate="0"> <simplecounter maxstate="999" digits="3" align="1"> |