mirror of
https://github.com/holub/mame
synced 2025-06-06 04:43:45 +03:00
hmcs40: simplify internal timer (nw)
This commit is contained in:
parent
65ad8907a4
commit
1697740cd5
@ -207,8 +207,6 @@ void hmcs40_cpu_device::device_start()
|
||||
m_datamask = (1 << m_datawidth) - 1;
|
||||
m_pcmask = (1 << m_pcwidth) - 1;
|
||||
|
||||
m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(hmcs40_cpu_device::simple_timer_cb), this));
|
||||
|
||||
// resolve callbacks
|
||||
m_read_r.resolve_all_safe(m_polarity & 0xf);
|
||||
m_write_r.resolve_all_safe();
|
||||
@ -222,6 +220,7 @@ void hmcs40_cpu_device::device_start()
|
||||
m_i = 0;
|
||||
m_eint_line = 0;
|
||||
m_halt = 0;
|
||||
m_prescaler = 0;
|
||||
m_pc = 0;
|
||||
m_prev_pc = 0;
|
||||
m_page = 0;
|
||||
@ -250,7 +249,6 @@ void hmcs40_cpu_device::device_start()
|
||||
save_item(NAME(m_i));
|
||||
save_item(NAME(m_eint_line));
|
||||
save_item(NAME(m_halt));
|
||||
save_item(NAME(m_timer_halted_remain));
|
||||
save_item(NAME(m_pc));
|
||||
save_item(NAME(m_prev_pc));
|
||||
save_item(NAME(m_page));
|
||||
@ -263,6 +261,7 @@ void hmcs40_cpu_device::device_start()
|
||||
save_item(NAME(m_s));
|
||||
save_item(NAME(m_c));
|
||||
save_item(NAME(m_tc));
|
||||
save_item(NAME(m_prescaler));
|
||||
save_item(NAME(m_cf));
|
||||
save_item(NAME(m_ie));
|
||||
save_item(NAME(m_iri));
|
||||
@ -307,9 +306,6 @@ void hmcs40_cpu_device::device_reset()
|
||||
m_iri = m_irt = 0;
|
||||
m_if[0] = m_if[1] = m_tf = 1;
|
||||
|
||||
if (!m_halt && m_timer->remaining().is_never())
|
||||
reset_prescaler();
|
||||
|
||||
// clear i/o
|
||||
m_d = m_polarity;
|
||||
for (int i = 0; i < 16; i++)
|
||||
@ -453,7 +449,6 @@ void hmcs45_cpu_device::write_r(int index, u8 data)
|
||||
|
||||
void hmcs40_cpu_device::do_interrupt()
|
||||
{
|
||||
m_icount--;
|
||||
push_stack();
|
||||
m_ie = 0;
|
||||
|
||||
@ -470,6 +465,8 @@ void hmcs40_cpu_device::do_interrupt()
|
||||
|
||||
standard_irq_callback(line);
|
||||
m_prev_pc = m_pc;
|
||||
|
||||
cycle();
|
||||
}
|
||||
|
||||
void hmcs40_cpu_device::execute_set_input(int line, int state)
|
||||
@ -479,14 +476,6 @@ void hmcs40_cpu_device::execute_set_input(int line, int state)
|
||||
// halt/unhalt mcu
|
||||
if (line == HMCS40_INPUT_LINE_HLT && state != m_halt)
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
m_timer_halted_remain = m_timer->remaining();
|
||||
m_timer->reset();
|
||||
}
|
||||
else
|
||||
m_timer->adjust(m_timer_halted_remain);
|
||||
|
||||
m_halt = state;
|
||||
return;
|
||||
}
|
||||
@ -512,20 +501,14 @@ void hmcs40_cpu_device::execute_set_input(int line, int state)
|
||||
m_int[line] = state;
|
||||
}
|
||||
|
||||
void hmcs40_cpu_device::reset_prescaler()
|
||||
void hmcs40_cpu_device::cycle()
|
||||
{
|
||||
// reset 6-bit timer prescaler
|
||||
attotime base = attotime::from_ticks(4 * 64, unscaled_clock());
|
||||
m_timer->adjust(base);
|
||||
}
|
||||
m_icount--;
|
||||
m_prescaler = (m_prescaler + 1) & 0x3f;
|
||||
|
||||
TIMER_CALLBACK_MEMBER( hmcs40_cpu_device::simple_timer_cb )
|
||||
{
|
||||
// timer prescaler overflow
|
||||
if (!m_cf)
|
||||
if (m_prescaler == 0 && !m_cf)
|
||||
increment_tc();
|
||||
|
||||
reset_prescaler();
|
||||
}
|
||||
|
||||
void hmcs40_cpu_device::increment_tc()
|
||||
@ -583,15 +566,10 @@ void hmcs40_cpu_device::execute_run()
|
||||
|
||||
// check/handle interrupt, but not in the middle of a long jump
|
||||
if (m_ie && (m_iri || m_irt) && (m_prev_op & 0x3e0) != 0x340)
|
||||
{
|
||||
do_interrupt();
|
||||
if (m_icount <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
// fetch next opcode
|
||||
debugger_instruction_hook(m_pc);
|
||||
m_icount--;
|
||||
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();
|
||||
@ -825,5 +803,7 @@ void hmcs40_cpu_device::execute_run()
|
||||
default:
|
||||
op_illegal(); break;
|
||||
} /* big switch */
|
||||
|
||||
cycle();
|
||||
}
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ protected:
|
||||
virtual u64 execute_clocks_to_cycles(u64 clocks) const noexcept override { return (clocks + 4 - 1) / 4; } // 4 cycles per machine cycle
|
||||
virtual u64 execute_cycles_to_clocks(u64 cycles) const noexcept override { return (cycles * 4); } // "
|
||||
virtual u32 execute_min_cycles() const noexcept override { return 1; }
|
||||
virtual u32 execute_max_cycles() const noexcept override { return 2; }
|
||||
virtual u32 execute_max_cycles() const noexcept override { return 2+1; } // max 2 + interrupt
|
||||
virtual u32 execute_input_lines() const noexcept override { return 2+1; } // 3rd one is internal
|
||||
virtual void execute_set_input(int line, int state) override;
|
||||
virtual void execute_run() override;
|
||||
@ -148,9 +148,8 @@ protected:
|
||||
u16 m_prev_op;
|
||||
u8 m_i; // 4-bit immediate opcode param
|
||||
int m_eint_line; // which input_line caused an interrupt
|
||||
emu_timer *m_timer;
|
||||
int m_halt; // internal HLT state
|
||||
attotime m_timer_halted_remain;
|
||||
u8 m_prescaler; // internal timer prescaler
|
||||
int m_icount;
|
||||
|
||||
u16 m_pc; // Program Counter
|
||||
@ -194,8 +193,7 @@ protected:
|
||||
virtual int read_d(int index);
|
||||
virtual void write_d(int index, int state);
|
||||
|
||||
void reset_prescaler();
|
||||
TIMER_CALLBACK_MEMBER( simple_timer_cb );
|
||||
void cycle();
|
||||
void increment_tc();
|
||||
void do_interrupt();
|
||||
|
||||
|
@ -578,14 +578,14 @@ void hmcs40_cpu_device::op_lti()
|
||||
{
|
||||
// LTI i: Load Timer/Counter from Immediate
|
||||
m_tc = m_i;
|
||||
reset_prescaler();
|
||||
m_prescaler = 0;
|
||||
}
|
||||
|
||||
void hmcs40_cpu_device::op_lta()
|
||||
{
|
||||
// LTA: Load Timer/Counter from A
|
||||
m_tc = m_a;
|
||||
reset_prescaler();
|
||||
m_prescaler = 0;
|
||||
}
|
||||
|
||||
void hmcs40_cpu_device::op_lat()
|
||||
@ -661,7 +661,6 @@ void hmcs40_cpu_device::op_lrb()
|
||||
void hmcs40_cpu_device::op_p()
|
||||
{
|
||||
// P p: Pattern Generation
|
||||
m_icount--;
|
||||
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);
|
||||
|
||||
@ -679,4 +678,6 @@ void hmcs40_cpu_device::op_p()
|
||||
write_r(2, o & 0xf);
|
||||
write_r(3, o >> 4 & 0xf);
|
||||
}
|
||||
|
||||
cycle();
|
||||
}
|
||||
|
@ -402,11 +402,7 @@ void ucom4_cpu_device::execute_run()
|
||||
{
|
||||
// handle interrupt, but not during LI($9x) or EI($31) or while skipping
|
||||
if (m_int_f && m_inte_f && (m_op & 0xf0) != 0x90 && m_op != 0x31 && !m_skip)
|
||||
{
|
||||
do_interrupt();
|
||||
if (m_icount <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
// remember previous state
|
||||
m_prev_op = m_op;
|
||||
|
@ -91,7 +91,7 @@ protected:
|
||||
virtual u64 execute_clocks_to_cycles(u64 clocks) const noexcept override { return (clocks + 4 - 1) / 4; } // 4 cycles per machine cycle
|
||||
virtual u64 execute_cycles_to_clocks(u64 cycles) const noexcept override { return (cycles * 4); } // "
|
||||
virtual u32 execute_min_cycles() const noexcept override { return 1; }
|
||||
virtual u32 execute_max_cycles() const noexcept override { return 2; }
|
||||
virtual u32 execute_max_cycles() const noexcept override { return 2+1; } // max 2 + interrupt
|
||||
virtual u32 execute_input_lines() const noexcept override { return 1; }
|
||||
virtual void execute_set_input(int line, int state) override;
|
||||
virtual void execute_run() override;
|
||||
|
@ -94,8 +94,8 @@
|
||||
- gckong random lockups (tap the jump button repeatedly): mcu stack overflow,
|
||||
works ok if stack levels is increased, 38800 B rev. has more stack levels?
|
||||
Or it could be a race condition: irq happening too late/early.
|
||||
- epacman2 booting the game in demo mode, pacman should go straight 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: 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.
|
||||
|
@ -17,6 +17,10 @@ SciSys/Novag's "Chess Champion: Pocket Chess" is assumed to be the same game,
|
||||
it has the same MCU serial (SL90387). They added battery low voltage detection
|
||||
to it (rightmost digit DP lights up).
|
||||
|
||||
TODO:
|
||||
- MCU frequency was actually measured ~3MHz, but this is much too slow when compared
|
||||
to a video recording (of Novag Pocket Chess), need to reverify
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
|
@ -7,7 +7,7 @@ SciSys Chess Partner 2000, also sold by Novag with the same name.
|
||||
It's probably the last SciSys / Novag collaboration.
|
||||
|
||||
Hardware notes:
|
||||
- 3850PK CPU at ~2.8MHz, 3853PK memory interface
|
||||
- 3850PK CPU at ~2.77MHz(averaged), 3853PK memory interface
|
||||
- 4KB ROM, 256 bytes RAM(2*2111N)
|
||||
- 4-digit 7seg panel, sensory chessboard
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user