hmcs40: block interrupt after conditional jump

This commit is contained in:
hap 2022-08-13 17:47:27 +02:00
parent d32a9caaf4
commit 4e2e05d2ec
5 changed files with 23 additions and 43 deletions

View File

@ -10,12 +10,6 @@ References:
- opcode decoding by Tatsuyuki Satoh, Olivier Galibert, Kevin Horton, Lord Nightmare
(verified a while later after new documentation was found)
TODO:
- How the stack works, is probably m_stack_levels+1 program counters, and
an index pointing to the current program counter. Then push/pop simply
decrements/increments the index. The way it is implemented right now
behaves the same.
*/
#include "emu.h"
@ -214,7 +208,6 @@ void hmcs40_cpu_device::device_start()
// zerofill
memset(m_stack, 0, sizeof(m_stack));
m_sp = 0;
m_op = 0;
m_prev_op = 0;
m_i = 0;
@ -244,7 +237,6 @@ void hmcs40_cpu_device::device_start()
// register for savestates
save_item(NAME(m_stack));
save_item(NAME(m_sp));
save_item(NAME(m_op));
save_item(NAME(m_prev_op));
save_item(NAME(m_i));
@ -566,8 +558,8 @@ void hmcs40_cpu_device::execute_run()
m_prev_op = m_op;
m_prev_pc = m_pc;
// check/handle interrupt, but not in the middle of a long jump
if (m_ie && (m_iri || m_irt) && (m_prev_op & 0x3e0) != 0x340)
// 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)
do_interrupt();
// fetch next opcode
@ -575,6 +567,7 @@ void hmcs40_cpu_device::execute_run()
m_op = m_program->read_word(m_pc) & 0x3ff;
m_i = bitswap<4>(m_op,0,1,2,3); // reversed bit-order for 4-bit immediate param (except for XAMR)
increment_pc();
cycle();
// handle opcode
switch (m_op)
@ -805,7 +798,5 @@ void hmcs40_cpu_device::execute_run()
default:
op_illegal(); break;
} /* big switch */
cycle();
}
}

View File

@ -147,7 +147,6 @@ protected:
u16 m_polarity; // i/o polarity (pmos vs cmos)
int m_stack_levels; // number of callstack levels
u16 m_stack[4]; // max 4
int m_sp; // internal 'stackpointer'
u16 m_op; // current opcode
u16 m_prev_op;
u8 m_i; // 4-bit immediate opcode param
@ -188,7 +187,6 @@ protected:
u8 ram_r();
void ram_w(u8 data);
void exc_stack();
void pop_stack();
void push_stack();

View File

@ -21,26 +21,18 @@ inline void hmcs40_cpu_device::ram_w(u8 data)
m_data->write_byte(address, data & 0xf);
}
void hmcs40_cpu_device::exc_stack()
{
// exchange stack/pc
u16 pc = m_stack[m_sp] & m_pcmask;
m_stack[m_sp] = m_pc;
m_pc = pc;
}
void hmcs40_cpu_device::pop_stack()
{
if (++m_sp >= m_stack_levels)
m_sp = 0;
exc_stack();
m_pc = m_stack[0] & m_pcmask;
for (int i = 0; i < m_stack_levels-1; i++)
m_stack[i] = m_stack[i+1];
}
void hmcs40_cpu_device::push_stack()
{
exc_stack();
if (--m_sp < 0)
m_sp = m_stack_levels - 1;
for (int i = m_stack_levels-1; i >= 1; i--)
m_stack[i] = m_stack[i-1];
m_stack[0] = m_pc;
}
@ -182,7 +174,7 @@ void hmcs40_cpu_device::op_xsp()
}
// Ram Register Instruction
// RAM Register Instruction
void hmcs40_cpu_device::op_lam()
{
@ -668,6 +660,8 @@ void hmcs40_cpu_device::op_lrb()
void hmcs40_cpu_device::op_p()
{
cycle();
// P p: Pattern Generation
u16 address = m_a | m_b << 4 | m_c << 8 | (m_op & 7) << 9 | (m_pc & ~0x3f);
u16 o = m_program->read_word(address & m_prgmask);
@ -686,6 +680,4 @@ void hmcs40_cpu_device::op_p()
write_r(2, o & 0xf);
write_r(3, o >> 4 & 0xf);
}
cycle();
}

View File

@ -107,9 +107,6 @@ ROM source notes when dumped from another model, but confident it's the same:
TODO:
- cgalaxn discrete sound (alien attacking sound effect)
- gckong glitchy jump on 1st level (rarely happens), caused by MCU stack overflow.
It can be tested by jumping up repeatedly at the start position under the ladder,
if the glitch happens there, you can jump onto the 2nd floor.
- epacman2 booting the game in demo mode, pacman should take the shortest route to
the upper-left power pill: mcu cycle/interrupt timing related
- kevtris's HMCS40 ROM dumps are incomplete, missing MCU factory test code from
@ -1420,7 +1417,7 @@ ROM_START( bbtime )
ROM_CONTINUE( 0x1e80, 0x0100 )
ROM_REGION( 461598, "screen", 0)
ROM_LOAD( "bbtime.svg", 0, 461598, BAD_DUMP CRC(1fb7b0b8) SHA1(bf938aa1c3c5032daba064a51d5b234bb9e512f5) )
ROM_LOAD( "bbtime.svg", 0, 461598, BAD_DUMP CRC(297f30de) SHA1(a5f38cd9c5d5ba9392c5d57ac85ecc2782b6ae7a) )
ROM_END
@ -2730,7 +2727,7 @@ u8 cpacman_state::input_r()
static INPUT_PORTS_START( cpacman )
PORT_START("IN.0") // D13 port R0x
PORT_CONFNAME( 0x01, 0x01, DEF_STR( Difficulty ) )
PORT_CONFNAME( 0x01, 0x00, DEF_STR( Difficulty ) )
PORT_CONFSETTING( 0x00, "1" )
PORT_CONFSETTING( 0x01, "2" )
PORT_BIT( 0x0e, IP_ACTIVE_HIGH, IPT_UNUSED )
@ -3108,7 +3105,7 @@ static INPUT_PORTS_START( epacman2 )
PORT_START("IN.3") // D4 port R0x
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_CONFNAME( 0x02, 0x02, DEF_STR( Difficulty ) )
PORT_CONFNAME( 0x02, 0x00, DEF_STR( Difficulty ) )
PORT_CONFSETTING( 0x00, "1" )
PORT_CONFSETTING( 0x02, "2" )
PORT_CONFNAME( 0x0c, 0x04, DEF_STR( Players ) )
@ -3282,7 +3279,7 @@ ROM_END
Entex Turtles (manufactured in Japan)
* PCB label: 560359
* Hitachi QFP HD38820A43 MCU
* Hitachi QFP HD38820A43 MCU, speed adjustable by knob
* COP411L sub MCU for sound, label COP411L-KED/N
* cyan/red/green VFD NEC FIP15BM32T
@ -3484,11 +3481,13 @@ ROM_END
Entex Stargate (manufactured in Japan)
* PCB label: 5603521/31
* Hitachi QFP HD38820A42 MCU
* Hitachi QFP HD38820A42 MCU, speed adjustable by knob
* COP411L sub MCU for sound, label ~/B8236 COP411L-KEC/N, volume control
* cyan/red/green VFD NEC FIP15AM32T (EL628-003) no. 2-421
* color overlay: bottom row: red
BTANB: when changing direction, player bullets remain and become obstacles
***************************************************************************/
class estargte_state : public eturtles_state
@ -3549,11 +3548,11 @@ static INPUT_PORTS_START( estargte )
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_START("IN.4") // D5 INT0/1
PORT_CONFNAME( 0x01, 0x00, DEF_STR( Players ) ) PORT_CHANGED_MEMBER(DEVICE_SELF, eturtles_state, input_changed, 0)
PORT_CONFSETTING( 0x00, "0 (Demo)" ) // yes, same value as 1-player, hold the Inviso button at boot to enter demo mode
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" )
PORT_CONFSETTING( 0x01, "2" )
PORT_CONFNAME( 0x02, 0x02, DEF_STR( Difficulty ) ) PORT_CHANGED_MEMBER(DEVICE_SELF, eturtles_state, input_changed, 0)
PORT_CONFNAME( 0x02, 0x00, DEF_STR( Difficulty ) ) PORT_CHANGED_MEMBER(DEVICE_SELF, eturtles_state, input_changed, 0)
PORT_CONFSETTING( 0x00, "1" )
PORT_CONFSETTING( 0x02, "2" )

View File

@ -1050,7 +1050,7 @@ ROM_START( bcclimbr )
ROM_LOAD( "d553c-170", 0x0000, 0x0800, CRC(fc2eabdb) SHA1(0f5cc854be7fdf105d9bd2114659d40c65f9d782) )
ROM_REGION( 219983, "screen", 0)
ROM_LOAD( "bcclimbr.svg", 0, 219983, CRC(02994933) SHA1(e1b650a70c6010cb78c84088e1bde2413682823b) )
ROM_LOAD( "bcclimbr.svg", 0, 219983, CRC(92c83961) SHA1(208b4c63c6aecd90acb15d9767fa1cf3aed835fb) )
ROM_END