diff --git a/src/emu/cpu/sm510/sm510.c b/src/emu/cpu/sm510/sm510.c index 2968335b68a..2da7d34d19f 100644 --- a/src/emu/cpu/sm510/sm510.c +++ b/src/emu/cpu/sm510/sm510.c @@ -36,8 +36,13 @@ void sm510_base_device::device_start() m_prgmask = (1 << m_prgwidth) - 1; m_datamask = (1 << m_datawidth) - 1; + m_div_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sm510_base_device::div_timer_cb), this)); + reset_divider(); + // resolve callbacks m_read_k.resolve_safe(0); + m_read_ba.resolve_safe(1); + m_read_b.resolve_safe(1); m_write_s.resolve_safe(); // zerofill @@ -53,9 +58,11 @@ void sm510_base_device::device_start() m_c = 0; m_skip = false; m_w = 0; - m_div = 0; - m_bdc = false; - m_cend = false; +// m_div = 0; + m_1s = false; + m_bp = false; + m_bc = false; + m_halt = false; // register for savestates save_item(NAME(m_stack)); @@ -71,8 +78,10 @@ void sm510_base_device::device_start() save_item(NAME(m_skip)); save_item(NAME(m_w)); save_item(NAME(m_div)); - save_item(NAME(m_bdc)); - save_item(NAME(m_cend)); + save_item(NAME(m_1s)); + save_item(NAME(m_bp)); + save_item(NAME(m_bc)); + save_item(NAME(m_halt)); // register state for debugger state_add(SM510_PC, "PC", m_pc).formatstr("%04X"); @@ -97,11 +106,66 @@ void sm510_base_device::device_start() void sm510_base_device::device_reset() { m_skip = false; - m_bdc = false; - m_cend = false; + m_halt = false; m_op = m_prev_op = 0; do_branch(3, 7, 0); m_prev_pc = m_pc; + + // lcd is on (Bp on, BC off) + m_bp = true; + m_bc = false; + + // y=0(bs), r=0 +} + + + +//------------------------------------------------- +// interrupt/timer +//------------------------------------------------- + +void sm510_base_device::wake_me_up() +{ + // in halt mode, wake up after 1S signal or K input + if (m_halt) + { + m_halt = false; + do_branch(1, 0, 0); + + standard_irq_callback(0); + + // note: official doc warns that Bl/Bm and the stack are undefined + // after waking up, but we leave it unchanged + } +} + +void sm510_base_device::execute_set_input(int line, int state) +{ + if (line != 0) + return; +} + +TIMER_CALLBACK_MEMBER(sm510_base_device::div_timer_cb) +{ + // no need to increment it by 1 everytime, since only the + // highest bits are accessible + m_div = (m_div + 0x800) & 0x7fff; + + // 1S signal on overflow(falling edge of f1) + if (m_div == 0) + { + m_1s = true; + wake_me_up(); + } + + // schedule next timeout + m_div_timer->adjust(attotime::from_ticks(0x800, unscaled_clock())); +} + +void sm510_base_device::reset_divider() +{ + m_div = 0; + m_div_timer->adjust(attotime::from_ticks(0x800, unscaled_clock())); } @@ -120,6 +184,13 @@ void sm510_base_device::increment_pc() void sm510_base_device::execute_run() { + // nothing to do if in halt mode + if (m_halt) + { + m_icount = 0; + return; + } + while (m_icount > 0) { // remember previous state diff --git a/src/emu/cpu/sm510/sm510.h b/src/emu/cpu/sm510/sm510.h index 7af7f1a7542..e8d345d2389 100644 --- a/src/emu/cpu/sm510/sm510.h +++ b/src/emu/cpu/sm510/sm510.h @@ -14,10 +14,18 @@ // I/O ports setup -// 4-bit K input port +// 4-bit K input port (pull-down) #define MCFG_SM510_READ_K_CB(_devcb) \ sm510_base_device::set_read_k_callback(*device, DEVCB_##_devcb); +// 1-bit BA input pin (pull-up) +#define MCFG_SM510_READ_BA_CB(_devcb) \ + sm510_base_device::set_read_ba_callback(*device, DEVCB_##_devcb); + +// 1-bit B(beta) input pin (pull-up) +#define MCFG_SM510_READ_B_CB(_devcb) \ + sm510_base_device::set_read_b_callback(*device, DEVCB_##_devcb); + // 8-bit S strobe output port #define MCFG_SM510_WRITE_S_CB(_devcb) \ sm510_base_device::set_write_s_callback(*device, DEVCB_##_devcb); @@ -43,11 +51,15 @@ public: , m_datawidth(datawidth) , m_stack_levels(stack_levels) , m_read_k(*this) + , m_read_ba(*this) + , m_read_b(*this) , m_write_s(*this) { } // static configuration helpers template static devcb_base &set_read_k_callback(device_t &device, _Object object) { return downcast(device).m_read_k.set_callback(object); } + template static devcb_base &set_read_ba_callback(device_t &device, _Object object) { return downcast(device).m_read_ba.set_callback(object); } + template static devcb_base &set_read_b_callback(device_t &device, _Object object) { return downcast(device).m_read_b.set_callback(object); } template static devcb_base &set_write_s_callback(device_t &device, _Object object) { return downcast(device).m_write_s.set_callback(object); } protected: @@ -61,7 +73,7 @@ protected: virtual UINT32 execute_min_cycles() const { return 1; } virtual UINT32 execute_max_cycles() const { return 2; } virtual UINT32 execute_input_lines() const { return 1; } - //virtual void execute_set_input(int line, int state); + virtual void execute_set_input(int line, int state); virtual void execute_run(); virtual void execute_one() { } // -> child class @@ -89,6 +101,7 @@ protected: int m_stack_levels; UINT16 m_stack[2]; int m_icount; + emu_timer *m_div_timer; UINT8 m_acc; UINT8 m_bl; @@ -97,15 +110,22 @@ protected: bool m_skip; UINT8 m_w; UINT16 m_div; - bool m_bdc; - bool m_cend; + bool m_1s; + bool m_bp; + bool m_bc; + bool m_halt; // i/o handlers - devcb_read16 m_read_k; + devcb_read8 m_read_k; + devcb_read_line m_read_ba; + devcb_read_line m_read_b; devcb_write8 m_write_s; // misc internal helpers void increment_pc(); + TIMER_CALLBACK_MEMBER(div_timer_cb); + void wake_me_up(); + virtual void reset_divider(); virtual void get_opcode_param() { } // -> child class UINT8 ram_r(); diff --git a/src/emu/cpu/sm510/sm510op.c b/src/emu/cpu/sm510/sm510op.c index 0e3238e1739..b1391a7da8f 100644 --- a/src/emu/cpu/sm510/sm510op.c +++ b/src/emu/cpu/sm510/sm510op.c @@ -161,7 +161,7 @@ void sm510_base_device::op_exc() void sm510_base_device::op_bdc() { // BDC: enable LCD bleeder current with C - m_bdc = (m_c != 0); + m_bc = (m_c != 0); } void sm510_base_device::op_exci() @@ -217,8 +217,8 @@ void sm510_base_device::op_kta() void sm510_base_device::op_atbp() { - // ATBP: output ACC to BP - op_illegal(); + // ATBP: output ACC to BP(internal LCD backplate signal) + m_bp = ((m_acc & 1) != 0); } void sm510_base_device::op_atl() @@ -296,8 +296,8 @@ void sm510_base_device::op_sc() void sm510_base_device::op_tb() { - // TB: x - op_illegal(); + // TB: skip next if B(beta) pin is set + m_skip = (m_read_b() != 0); } void sm510_base_device::op_tc() @@ -326,32 +326,33 @@ void sm510_base_device::op_ta0() void sm510_base_device::op_tabl() { - // TABL: skip next of ACC equals BL + // TABL: skip next if ACC equals BL m_skip = (m_acc == m_bl); } void sm510_base_device::op_tis() { - // TIS: x - op_illegal(); + // TIS: skip next if 1S(gamma flag) is clear, reset it after + m_skip = !m_1s; + m_1s = false; } void sm510_base_device::op_tal() { - // TAL: x - op_illegal(); + // TAL: skip next if BA pin is set + m_skip = (m_read_ba() != 0); } void sm510_base_device::op_tf1() { - // TF1: x - op_illegal(); + // TF1: skip next if divider F1(d14) is set + m_skip = ((m_div & 0x4000) != 0); } void sm510_base_device::op_tf4() { - // TF4: x - op_illegal(); + // TF4: skip next if divider F4(d11) is set + m_skip = ((m_div & 0x0800) != 0); } @@ -379,14 +380,14 @@ void sm510_base_device::op_skip() void sm510_base_device::op_cend() { - // CEND: stop clock - m_cend = true; + // CEND: stop clock (halt the cpu and go into low-power mode) + m_halt = true; } void sm510_base_device::op_idiv() { // IDIV: reset divider - m_div = 0; + reset_divider(); } void sm510_base_device::op_illegal()