diff --git a/src/devices/cpu/sm510/sm510.cpp b/src/devices/cpu/sm510/sm510.cpp index ab1b4cb0ebb..69a099f1cb4 100644 --- a/src/devices/cpu/sm510/sm510.cpp +++ b/src/devices/cpu/sm510/sm510.cpp @@ -68,6 +68,37 @@ void sm510_base_device::device_start() m_write_segbs.resolve_safe(); m_write_segc.resolve_safe(); + // zerofill + memset(m_stack, 0, sizeof(m_stack)); + m_pc = 0; + m_prev_pc = 0; + m_op = 0; + m_prev_op = 0; + m_param = 0; + m_acc = 0; + m_bl = 0; + m_bm = 0; + m_sbm = false; + m_c = 0; + m_skip = false; + m_w = 0; + m_r = 0; + m_r_out = 0; + m_div = 0; + m_1s = false; + m_k_active = false; + m_l = 0; + m_x = 0; + m_y = 0; + m_bp = false; + m_bc = false; + m_halt = false; + m_melody_rd = 0; + m_melody_step_count = 0; + m_melody_duty_count = 0; + m_melody_duty_index = 0; + m_melody_address = 0; + // register for savestates save_item(NAME(m_stack)); save_item(NAME(m_pc)); @@ -78,10 +109,12 @@ void sm510_base_device::device_start() save_item(NAME(m_acc)); save_item(NAME(m_bl)); save_item(NAME(m_bm)); + save_item(NAME(m_sbm)); save_item(NAME(m_c)); save_item(NAME(m_skip)); save_item(NAME(m_w)); save_item(NAME(m_r)); + save_item(NAME(m_r_out)); save_item(NAME(m_div)); save_item(NAME(m_1s)); save_item(NAME(m_k_active)); @@ -138,7 +171,7 @@ void sm510_base_device::device_reset() m_bc = false; m_y = 0; - m_r = 0; + m_r = m_r_out = 0; m_write_r(0, 0, 0xff); m_melody_rd &= ~1; } @@ -190,82 +223,6 @@ void sm510_base_device::init_lcd_driver() -//------------------------------------------------- -// melody controller -//------------------------------------------------- - -void sm510_base_device::clock_melody() -{ - if (!m_melody_rom) - return; - - // tone cycle table (SM511/SM512 datasheet fig.5) - // cmd 0 = cmd, 1 = stop, > 13 = illegal(unknown) - static const u8 lut_tone_cycles[4*16] = - { - 0, 0, 7, 8, 8, 9, 9, 10,11,11,12,13,14,14, 7*2, 8*2, - 0, 0, 8, 8, 9, 9, 10,11,11,12,13,13,14,15, 8*2, 8*2, - 0, 0, 8, 8, 9, 9, 10,10,11,12,12,13,14,15, 8*2, 8*2, - 0, 0, 8, 9, 9, 10,10,11,11,12,13,14,14,15, 8*2, 9*2 - }; - - u8 cmd = m_melody_rom[m_melody_address] & 0x3f; - u8 out = 0; - - // clock duty cycle if tone is active - if ((cmd & 0xf) > 1) - { - out = m_melody_duty_index & m_melody_rd & 1; - m_melody_duty_count++; - int index = m_melody_duty_index << 4 | (cmd & 0xf); - int shift = ~cmd >> 4 & 1; // OCT - - if (m_melody_duty_count >= (lut_tone_cycles[index] << shift)) - { - m_melody_duty_count = 0; - m_melody_duty_index = (m_melody_duty_index + 1) & 3; - } - } - else if ((cmd & 0xf) == 1) - { - // rest tell signal - m_melody_rd |= 2; - } - - // clock time base on F8(d7) - if ((m_div & 0x7f) == 0) - { - u8 mask = (cmd & 0x20) ? 0x1f : 0x0f; - m_melody_step_count = (m_melody_step_count + 1) & mask; - - if (m_melody_step_count == 0) - m_melody_address++; - } - - // output to R pin - if (out != m_r) - { - m_write_r(0, out, 0xff); - m_r = out; - } -} - -void sm510_base_device::init_melody() -{ - if (!m_melody_rom) - return; - - // verify melody rom - for (int i = 0; i < 0x100; i++) - { - u8 data = m_melody_rom[i]; - if (data & 0xc0 || (data & 0x0f) > 13) - logerror("%s unknown melody ROM data $%02X at $%02X\n", tag(), data, i); - } -} - - - //------------------------------------------------- // interrupt/divider //------------------------------------------------- diff --git a/src/devices/cpu/sm510/sm510.h b/src/devices/cpu/sm510/sm510.h index 68f8f780fa9..b0dd41e408f 100644 --- a/src/devices/cpu/sm510/sm510.h +++ b/src/devices/cpu/sm510/sm510.h @@ -174,7 +174,7 @@ protected: u8 m_c; bool m_skip; u8 m_w; - u8 m_r; + u8 m_r, m_r_out; bool m_k_active; bool m_halt; @@ -199,8 +199,8 @@ protected: u8 m_melody_duty_index; u8 m_melody_address; - void clock_melody(); - void init_melody(); + virtual void clock_melody() { } + virtual void init_melody() { } // interrupt/divider emu_timer *m_div_timer; @@ -311,6 +311,8 @@ protected: virtual void get_opcode_param() override; virtual void update_w_latch() override { m_write_s(0, m_w, 0xff); } // W is connected directly to S + + virtual void clock_melody() override; }; @@ -324,6 +326,9 @@ protected: virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const u8 *oprom, const u8 *opram, u32 options) override; virtual void execute_one() override; virtual void get_opcode_param() override; + + virtual void clock_melody() override; + virtual void init_melody() override; }; class sm512_device : public sm511_device diff --git a/src/devices/cpu/sm510/sm510core.cpp b/src/devices/cpu/sm510/sm510core.cpp index a531fc37e69..c739fa83ffe 100644 --- a/src/devices/cpu/sm510/sm510core.cpp +++ b/src/devices/cpu/sm510/sm510core.cpp @@ -45,6 +45,27 @@ offs_t sm510_device::disasm_disassemble(std::ostream &stream, offs_t pc, const u +//------------------------------------------------- +// buzzer controller +//------------------------------------------------- + +void sm510_device::clock_melody() +{ + // buzzer from divider, R2 inverse phase + u8 out = m_div >> 2 & 1; + out |= (out << 1 ^ 2); + out &= m_r; + + // output to R pin + if (out != m_r_out) + { + m_write_r(0, out, 0xff); + m_r_out = out; + } +} + + + //------------------------------------------------- // execute //------------------------------------------------- diff --git a/src/devices/cpu/sm510/sm510op.cpp b/src/devices/cpu/sm510/sm510op.cpp index f0a32851708..8b248c2cf90 100644 --- a/src/devices/cpu/sm510/sm510op.cpp +++ b/src/devices/cpu/sm510/sm510op.cpp @@ -263,11 +263,7 @@ void sm510_base_device::op_atfc() void sm510_base_device::op_atr() { // ATR: output ACC to R - if (m_r != (m_acc & 3)) - { - m_r = m_acc & 3; - m_write_r(0, m_r, 0xff); - } + m_r = m_acc; } diff --git a/src/devices/cpu/sm510/sm511core.cpp b/src/devices/cpu/sm510/sm511core.cpp index 1c40e781764..54f9db77e84 100644 --- a/src/devices/cpu/sm510/sm511core.cpp +++ b/src/devices/cpu/sm510/sm511core.cpp @@ -58,6 +58,82 @@ sm512_device::sm512_device(const machine_config &mconfig, const char *tag, devic +//------------------------------------------------- +// melody controller +//------------------------------------------------- + +void sm511_device::clock_melody() +{ + if (!m_melody_rom) + return; + + // tone cycle table (SM511/SM512 datasheet fig.5) + // cmd 0 = cmd, 1 = stop, > 13 = illegal(unknown) + static const u8 lut_tone_cycles[4*16] = + { + 0, 0, 7, 8, 8, 9, 9, 10,11,11,12,13,14,14, 7*2, 8*2, + 0, 0, 8, 8, 9, 9, 10,11,11,12,13,13,14,15, 8*2, 8*2, + 0, 0, 8, 8, 9, 9, 10,10,11,12,12,13,14,15, 8*2, 8*2, + 0, 0, 8, 9, 9, 10,10,11,11,12,13,14,14,15, 8*2, 9*2 + }; + + u8 cmd = m_melody_rom[m_melody_address] & 0x3f; + u8 out = 0; + + // clock duty cycle if tone is active + if ((cmd & 0xf) > 1) + { + out = m_melody_duty_index & m_melody_rd & 1; + m_melody_duty_count++; + int index = m_melody_duty_index << 4 | (cmd & 0xf); + int shift = ~cmd >> 4 & 1; // OCT + + if (m_melody_duty_count >= (lut_tone_cycles[index] << shift)) + { + m_melody_duty_count = 0; + m_melody_duty_index = (m_melody_duty_index + 1) & 3; + } + } + else if ((cmd & 0xf) == 1) + { + // rest tell signal + m_melody_rd |= 2; + } + + // clock time base on F8(d7) + if ((m_div & 0x7f) == 0) + { + u8 mask = (cmd & 0x20) ? 0x1f : 0x0f; + m_melody_step_count = (m_melody_step_count + 1) & mask; + + if (m_melody_step_count == 0) + m_melody_address++; + } + + // output to R pin + if (out != m_r_out) + { + m_write_r(0, out, 0xff); + m_r_out = out; + } +} + +void sm511_device::init_melody() +{ + if (!m_melody_rom) + return; + + // verify melody rom + for (int i = 0; i < 0x100; i++) + { + u8 data = m_melody_rom[i]; + if (data & 0xc0 || (data & 0x0f) > 13) + logerror("%s unknown melody ROM data $%02X at $%02X\n", tag(), data, i); + } +} + + + //------------------------------------------------- // execute //-------------------------------------------------