diff options
author | 2022-03-13 11:05:12 +0100 | |
---|---|---|
committer | 2022-03-13 11:05:26 +0100 | |
commit | db6c9c1d9aff7b8605f61fd07be5c3779406d54a (patch) | |
tree | ba0fdf99ede29b8117bd929c881b2d900e59a2ff /src/devices/cpu | |
parent | 1ad39cb5dd52e87c4b00b17456a1dcdbb89e74d7 (diff) |
New working machines
--------------------
Star Fox (Nelsonic)
New machines marked as NOT_WORKING
----------------------------------
Super Mario Bros. 3 (Nelsonic)
Super Mario World (Nelsonic)
Diffstat (limited to 'src/devices/cpu')
-rw-r--r-- | src/devices/cpu/sm510/sm500.cpp | 8 | ||||
-rw-r--r-- | src/devices/cpu/sm510/sm500.h | 22 | ||||
-rw-r--r-- | src/devices/cpu/sm510/sm500op.cpp | 13 | ||||
-rw-r--r-- | src/devices/cpu/sm510/sm510.cpp | 2 | ||||
-rw-r--r-- | src/devices/cpu/sm510/sm510.h | 62 | ||||
-rw-r--r-- | src/devices/cpu/sm510/sm510base.cpp | 53 | ||||
-rw-r--r-- | src/devices/cpu/sm510/sm510base.h | 18 | ||||
-rw-r--r-- | src/devices/cpu/sm510/sm510op.cpp | 21 | ||||
-rw-r--r-- | src/devices/cpu/sm510/sm511.cpp | 6 | ||||
-rw-r--r-- | src/devices/cpu/sm510/sm511.h | 1 | ||||
-rw-r--r-- | src/devices/cpu/sm510/sm530.cpp | 125 | ||||
-rw-r--r-- | src/devices/cpu/sm510/sm530.h | 90 | ||||
-rw-r--r-- | src/devices/cpu/sm510/sm530op.cpp | 80 | ||||
-rw-r--r-- | src/devices/cpu/sm510/sm590.cpp | 4 | ||||
-rw-r--r-- | src/devices/cpu/sm510/sm590.h | 9 | ||||
-rw-r--r-- | src/devices/cpu/sm510/sm590op.cpp | 4 | ||||
-rw-r--r-- | src/devices/cpu/sm510/sm5a.cpp | 16 | ||||
-rw-r--r-- | src/devices/cpu/sm510/sm5a.h | 26 |
18 files changed, 392 insertions, 168 deletions
diff --git a/src/devices/cpu/sm510/sm500.cpp b/src/devices/cpu/sm510/sm500.cpp index e9772a1780c..347f17423dd 100644 --- a/src/devices/cpu/sm510/sm500.cpp +++ b/src/devices/cpu/sm510/sm500.cpp @@ -65,7 +65,6 @@ void sm500_device::device_start() // init/zerofill memset(m_ox, 0, sizeof(m_ox)); memset(m_o, 0, sizeof(m_o)); - m_cn = 0; m_mx = 0; m_cb = 0; m_s = 0; @@ -74,7 +73,6 @@ void sm500_device::device_start() // register for savestates save_item(NAME(m_ox)); save_item(NAME(m_o)); - save_item(NAME(m_cn)); save_item(NAME(m_mx)); save_item(NAME(m_cb)); save_item(NAME(m_s)); @@ -95,7 +93,7 @@ void sm500_device::device_reset() // SM500 specific push_stack(); op_idiv(); - m_1s = true; + m_gamma = 1; m_cb = 0; m_rsub = false; m_r = 0xf; @@ -109,14 +107,14 @@ void sm500_device::device_reset() void sm500_device::lcd_update() { - // 2 columns + // 2 rows for (int h = 0; h < 2; h++) { for (int o = 0; o < m_o_pins; o++) { // 4 segments per group u8 seg = h ? m_ox[o] : m_o[o]; - m_write_segs(o << 1 | h, m_bp ? seg : 0, 0xffff); + m_write_segs(o << 1 | h, (m_bp & 1) ? seg : 0); } } } diff --git a/src/devices/cpu/sm510/sm500.h b/src/devices/cpu/sm510/sm500.h index c0d097df61e..90be21ca184 100644 --- a/src/devices/cpu/sm510/sm500.h +++ b/src/devices/cpu/sm510/sm500.h @@ -23,20 +23,31 @@ ________________________________________________ | | O23 37 | | 24 OS2 + | | O13 38 | | 23 OS3 + | | O44 39 | | 22 OS4 + | | O34 40 | | 21 H1 + | | O24 41 | | 20 H2 -O14 42 | SM500 | 19 Vm + | | +O14 42 | | 19 Vm + | SM500 | O45 43 | | 18 OSCin + | | O35 44 | | 17 OSCout + | | O25 45 | | 16 Vdd + | | O15 46 | | 15 K4 + | | O46 47 | | 14 K3 -O36 48 | * | 13 K2 + | | +O36 48 | * | 13 K2 |________________________________________________/ - 1 2 3 4 5 6 7 8 9 10 11 12 + 1 2 3 4 5 6 7 8 9 10 11 12 O26 O16 R4 R3 R2 R1 GND _T bt al ACL K1 note: bt = beta symbol, al = alpha symbol */ @@ -67,7 +78,6 @@ protected: int m_o_pins; // number of 4-bit O pins u8 m_ox[9]; // W' latch, max 9 u8 m_o[9]; // W latch - u8 m_cn; u8 m_mx; u8 m_cb; @@ -76,11 +86,12 @@ protected: void shift_w(); u8 get_digit(); + + // opcode handlers void set_su(u8 su) { m_stack[0] = (m_stack[0] & ~0x3c0) | (su << 6 & 0x3c0); } u8 get_su() { return m_stack[0] >> 6 & 0xf; } virtual int get_trs_field() { return 0; } - // opcode handlers virtual void op_lb() override; virtual void op_incb() override; virtual void op_sbm() override; @@ -92,7 +103,6 @@ protected: virtual void op_tr(); virtual void op_trs(); - virtual void op_atbp() override; virtual void op_ptw() override; virtual void op_tw(); virtual void op_pdtw(); diff --git a/src/devices/cpu/sm510/sm500op.cpp b/src/devices/cpu/sm510/sm500op.cpp index 9fb66a8a4cc..39af8e6020b 100644 --- a/src/devices/cpu/sm510/sm500op.cpp +++ b/src/devices/cpu/sm510/sm500op.cpp @@ -25,7 +25,9 @@ u8 sm500_device::get_digit() 0xb, 0x9, 0x7, 0xf, 0xd, 0xe, 0xe, 0xb, 0xf, 0xf, 0x4, 0x0, 0xd, 0xe, 0x4, 0x0 }; - return lut_digits[m_cn << 4 | m_acc] | (~m_cn & m_mx); + // row select is from BP d3 (aka CN flag) + u8 sel = BIT(m_bp, 3); + return lut_digits[sel << 4 | m_acc] | (~sel & m_mx); } @@ -110,13 +112,6 @@ void sm500_device::op_trs() // Data transfer instructions -void sm500_device::op_atbp() -{ - // ATBP: same as SM510, and set CN with ACC3 - sm510_base_device::op_atbp(); - m_cn = m_acc >> 3 & 1; -} - void sm500_device::op_ptw() { // PTW: partial transfer W' to W @@ -206,5 +201,5 @@ void sm500_device::op_smf() void sm500_device::op_comcn() { // COMCN: complement CN flag - m_cn ^= 1; + m_bp ^= 8; } diff --git a/src/devices/cpu/sm510/sm510.cpp b/src/devices/cpu/sm510/sm510.cpp index 35c141dcde8..fa35d53e0ec 100644 --- a/src/devices/cpu/sm510/sm510.cpp +++ b/src/devices/cpu/sm510/sm510.cpp @@ -156,7 +156,7 @@ void sm510_device::execute_one() } // big switch // BM high bit is only valid for 1 step - m_sbm = (m_op == 0x02); + m_bmask = (m_op == 0x02) ? 0x40 : 0; } bool sm510_device::op_argument() diff --git a/src/devices/cpu/sm510/sm510.h b/src/devices/cpu/sm510/sm510.h index c85bd374eb4..af1e18d2861 100644 --- a/src/devices/cpu/sm510/sm510.h +++ b/src/devices/cpu/sm510/sm510.h @@ -18,30 +18,44 @@ /* - b2 a3 b3 a4 b4 a5 b5 GNDa6 b6 a7 b7 a8 b8 a9 - 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 - ______________________________________________ - | | -a2 46 | | 30 b9 -b1 47 | | 29 a10 -a1 48 | | 28 b10 -H4 49 | | 27 a11 -H3 50 | | 26 b11 -H2 51 | | 25 a12 -H1 52 | | 24 b12 -S1 53 | SM510 | 23 a13 -S2 54 | | 22 b13 -S3 55 | | 21 a14 -S4 56 | | 20 b14 -S5 57 | | 19 a15 -S6 58 | | 18 b15 -S7 59 | | 17 a16 -S8 60 | * | 16 b16 - |______________________________________________/ - - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - T K1 K2 K3 K4 ACL | GND |OSCin| bt R1 R2 bs note: bt = beta symbol - BA OSCout Vdd + b2 a3 b3 a4 b4 a5 b5 GND a6 b6 a7 b7 a8 b8 a9 + 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 + ____________________________________________________________ + | | +a2 46 | | 30 b9 + | | +b1 47 | | 29 a10 + | | +a1 48 | | 28 b10 + | | +H4 49 | | 27 a11 + | | +H3 50 | | 26 b11 + | | +H2 51 | | 25 a12 + | | +H1 52 | | 24 b12 + | SM510 | +S1 53 | SM511 | 23 a13 + | | +S2 54 | | 22 b13 + | | +S3 55 | | 21 a14 + | | +S4 56 | | 20 b14 + | | +S5 57 | | 19 a15 + | | +S6 58 | | 18 b15 + | | +S7 59 | | 17 a16 + | | +S8 60 | * | 16 b16 + |____________________________________________________________/ + + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + T K1 K2 K3 K4 ACL BA GND OSC OSC Vdd bt R1 R2 bs note: bt = beta symbol + out in */ class sm510_device : public sm510_base_device diff --git a/src/devices/cpu/sm510/sm510base.cpp b/src/devices/cpu/sm510/sm510base.cpp index c260c07667b..ec169a00e40 100644 --- a/src/devices/cpu/sm510/sm510base.cpp +++ b/src/devices/cpu/sm510/sm510base.cpp @@ -55,16 +55,14 @@ void sm510_base_device::device_start() m_acc = 0; m_bl = 0; m_bm = 0; - m_sbl = false; - m_sbm = false; + m_bmask = 0; m_c = 0; m_skip = false; m_w = 0; m_r = 0; m_r_out = 0; m_div = 0; - m_1s = false; - m_1s_rise = false; + m_gamma = 0; m_ext_wakeup = false; m_l = 0; m_x = 0; @@ -89,16 +87,14 @@ 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_sbl)); - save_item(NAME(m_sbm)); + save_item(NAME(m_bmask)); 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_1s_rise)); + save_item(NAME(m_gamma)); save_item(NAME(m_ext_wakeup)); save_item(NAME(m_l)); save_item(NAME(m_x)); @@ -152,8 +148,7 @@ void sm510_base_device::device_reset() // ACL m_skip = false; m_halt = false; - m_sbl = false; - m_sbm = false; + m_bmask = 0; m_op = m_prev_op = 0; reset_vector(); m_prev_pc = m_pc; @@ -175,7 +170,7 @@ void sm510_base_device::device_reset() inline u16 sm510_base_device::get_lcd_row(int column, u8* ram) { // output 0 if lcd blackpate/bleeder is off, or in case row doesn't exist - if (ram == nullptr || m_bc || !m_bp) + if (ram == nullptr || m_bc || !(m_bp & 1)) return 0; u16 rowdata = 0; @@ -191,14 +186,14 @@ void sm510_base_device::lcd_update() for (int h = 0; h < 4; h++) { // 16 segments per row from upper part of RAM - m_write_segs(h | SM510_PORT_SEGA, get_lcd_row(h, m_lcd_ram_a), 0xffff); - m_write_segs(h | SM510_PORT_SEGB, get_lcd_row(h, m_lcd_ram_b), 0xffff); - m_write_segs(h | SM510_PORT_SEGC, get_lcd_row(h, m_lcd_ram_c), 0xffff); + m_write_segs(h | SM510_PORT_SEGA, get_lcd_row(h, m_lcd_ram_a)); + m_write_segs(h | SM510_PORT_SEGB, get_lcd_row(h, m_lcd_ram_b)); + m_write_segs(h | SM510_PORT_SEGC, get_lcd_row(h, m_lcd_ram_c)); // bs output from L/X and Y regs u8 blink = (m_div & 0x4000) ? m_y : 0; u8 bs = ((m_l & ~blink) >> h & 1) | ((m_x*2) >> h & 2); - m_write_segs(h | SM510_PORT_SEGBS, (m_bc || !m_bp) ? 0 : bs, 0xffff); + m_write_segs(h | SM510_PORT_SEGBS, (m_bc || !(m_bp & 1)) ? 0 : bs); } } @@ -224,12 +219,9 @@ TIMER_CALLBACK_MEMBER(sm510_base_device::div_timer_cb) { m_div = (m_div + 1) & 0x7fff; - // 1S signal on overflow(falling edge of F1) + // 1S(gamma) signal on overflow(falling edge of F1) if (m_div == 0) - { - m_1s_rise = !m_1s; - m_1s = true; - } + m_gamma |= 1; clock_melody(); } @@ -237,7 +229,8 @@ TIMER_CALLBACK_MEMBER(sm510_base_device::div_timer_cb) void sm510_base_device::init_divider() { m_div_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sm510_base_device::div_timer_cb), this)); - m_div_timer->adjust(attotime::from_ticks(1, unscaled_clock()), 0, attotime::from_ticks(1, unscaled_clock())); + attotime period = attotime::from_ticks(1, unscaled_clock()); + m_div_timer->adjust(period, 0, period); } @@ -279,24 +272,19 @@ void sm510_base_device::increment_pc() void sm510_base_device::execute_run() { - bool prev_1s = m_1s_rise; - while (m_icount > 0) { - // in halt mode, wake up after 1S signal or K input - bool wakeup = m_ext_wakeup || m_1s_rise; - m_1s_rise = false; - + // in halt mode, wake up after gamma signal or K input if (m_halt) { - if (!wakeup) + if (m_ext_wakeup || m_gamma) + do_interrupt(); + else { // got nothing to do m_icount = 0; return; } - else - do_interrupt(); } m_icount--; @@ -327,10 +315,5 @@ void sm510_base_device::execute_run() } else execute_one(); - - // if CEND triggered at the same time as 1S signal, make sure it still wakes up - if (m_halt) - m_1s_rise = prev_1s; - prev_1s = false; } } diff --git a/src/devices/cpu/sm510/sm510base.h b/src/devices/cpu/sm510/sm510base.h index 4cfdaa2c715..f699c035b26 100644 --- a/src/devices/cpu/sm510/sm510base.h +++ b/src/devices/cpu/sm510/sm510base.h @@ -61,7 +61,7 @@ public: void set_r_mask_option(int bit) { m_r_mask_option = bit; } static constexpr int RMASK_DIRECT = -1; - // 4-bit K input port (pull-down) + // 4/8-bit K input port (pull-down) auto read_k() { return m_read_k.bind(); } // 1-bit BA(aka alpha) input pin (pull-up) @@ -70,15 +70,16 @@ public: // 1-bit B(beta) input pin (pull-up) auto read_b() { return m_read_b.bind(); } - // 8-bit S strobe output port + // 4/8-bit S strobe output port auto write_s() { return m_write_s.bind(); } // 1/2/4-bit R (buzzer/melody) output port + // may also be called F(frequency?) or SO(sound out) auto write_r() { return m_write_r.bind(); } - // LCD segment outputs, SM51X: H1-4 as offset(low), a/b/c 1-16 as data d0-d15, + // LCD segment outputs, SM51x: H1-4 as offset(low), a/b/c 1-16 as data d0-d15, // bs output is same as above, but only up to 2 bits used. - // SM500/SM5A: H1/2 as a0, O group as a1-a4, O data as d0-d3 + // SM500/SM5A/SM530: H1/2 as a0, O group as a1-a4, O data as d0-d3 auto write_segs() { return m_write_segs.bind(); } protected: @@ -124,8 +125,7 @@ protected: u8 m_acc; u8 m_bl; u8 m_bm; - bool m_sbm; - bool m_sbl; + u8 m_bmask; u8 m_c; bool m_skip; u8 m_w; @@ -165,11 +165,10 @@ protected: // divider emu_timer *m_div_timer; u16 m_div; - bool m_1s; - bool m_1s_rise; + u8 m_gamma; virtual void init_divider(); - TIMER_CALLBACK_MEMBER(div_timer_cb); + virtual TIMER_CALLBACK_MEMBER(div_timer_cb); // other i/o handlers devcb_read8 m_read_k; @@ -193,7 +192,6 @@ protected: // opcode handlers virtual void op_lb(); virtual void op_lbl(); - virtual void op_sbl(); virtual void op_sbm(); virtual void op_exbla(); virtual void op_incb(); diff --git a/src/devices/cpu/sm510/sm510op.cpp b/src/devices/cpu/sm510/sm510op.cpp index 672209861aa..9c7aa24c85c 100644 --- a/src/devices/cpu/sm510/sm510op.cpp +++ b/src/devices/cpu/sm510/sm510op.cpp @@ -11,17 +11,13 @@ u8 sm510_base_device::ram_r() { - int blh = (m_sbl) ? 8 : 0; // from SBL (optional) - int bmh = (m_sbm) ? (1 << (m_datawidth-1)) : 0; // from SBM - u8 address = (bmh | blh | m_bm << 4 | m_bl) & m_datamask; + u8 address = (m_bmask | m_bm << 4 | m_bl) & m_datamask; return m_data->read_byte(address) & 0xf; } void sm510_base_device::ram_w(u8 data) { - int blh = (m_sbl) ? 8 : 0; // from SBL (optional) - int bmh = (m_sbm) ? (1 << (m_datawidth-1)) : 0; // from SBM - u8 address = (bmh | blh | m_bm << 4 | m_bl) & m_datamask; + u8 address = (m_bmask | m_bm << 4 | m_bl) & m_datamask; m_data->write_byte(address, data & 0xf); } @@ -70,11 +66,6 @@ void sm510_base_device::op_lbl() m_bm = (m_param & m_datamask) >> 4; } -void sm510_base_device::op_sbl() -{ - // SBL: set BL high bit for next opcode - handled in execute_one() -} - void sm510_base_device::op_sbm() { // SBM: set BM high bit for next opcode - handled in execute_one() @@ -229,8 +220,8 @@ void sm510_base_device::op_kta() void sm510_base_device::op_atbp() { - // ATBP: output ACC to BP(internal LCD backplate signal) - m_bp = m_acc & 1; + // ATBP: output ACC to BP LCD flag(s) + m_bp = m_acc; } void sm510_base_device::op_atx() @@ -352,8 +343,8 @@ void sm510_base_device::op_tabl() void sm510_base_device::op_tis() { // TIS: skip next if 1S(gamma flag) is clear, reset it after - m_skip = !m_1s; - m_1s = false; + m_skip = !m_gamma; + m_gamma = 0; } void sm510_base_device::op_tal() diff --git a/src/devices/cpu/sm510/sm511.cpp b/src/devices/cpu/sm510/sm511.cpp index b80427c5f8c..9ac8e36699e 100644 --- a/src/devices/cpu/sm510/sm511.cpp +++ b/src/devices/cpu/sm510/sm511.cpp @@ -123,8 +123,8 @@ void sm511_device::clock_melody() m_melody_rd |= 2; } - // clock time base on F8(d7) - if ((m_div & 0x7f) == 0) + // clock time base on divider F7/F8 + if ((m_div & melody_step_mask()) == 0) { u8 mask = (cmd & 0x20) ? 0x1f : 0x0f; m_melody_step_count = (m_melody_step_count + 1) & mask; @@ -251,7 +251,7 @@ void sm511_device::execute_one() } // big switch // BM high bit is only valid for 1 step - m_sbm = (m_op == 0x02); + m_bmask = (m_op == 0x02) ? 0x40 : 0; } bool sm511_device::op_argument() diff --git a/src/devices/cpu/sm510/sm511.h b/src/devices/cpu/sm510/sm511.h index 54066d1d405..463ede6be04 100644 --- a/src/devices/cpu/sm510/sm511.h +++ b/src/devices/cpu/sm510/sm511.h @@ -44,6 +44,7 @@ protected: virtual void clock_melody() override; virtual void init_melody() override; + virtual u16 melody_step_mask() { return 0x7f; } }; class sm512_device : public sm511_device diff --git a/src/devices/cpu/sm510/sm530.cpp b/src/devices/cpu/sm510/sm530.cpp index 3b73ee036f2..ddc2e24a368 100644 --- a/src/devices/cpu/sm510/sm530.cpp +++ b/src/devices/cpu/sm510/sm530.cpp @@ -5,7 +5,12 @@ Sharp SM530 MCU core implementation TODO: - - almost everything + - is unused RAM unmapped? or mirrored? + - add BP3,BP4, they connect the 1s or 1/100s counter to some of the LCD segs + - what do BP1,BP2 do? datasheet block diagram shows BP is 4 bit, but it doesn't + explain anywhere what they're for + - add SM531: not just smaller ROM/RAM, melody controller supposedly supports + envelopes (melody ROM is 128x7 instead of 256x6) */ @@ -16,8 +21,7 @@ // MCU types -DEFINE_DEVICE_TYPE(SM530, sm530_device, "sm530", "Sharp SM530") // x -DEFINE_DEVICE_TYPE(SM531, sm531_device, "sm531", "Sharp SM531") // x +DEFINE_DEVICE_TYPE(SM530, sm530_device, "sm530", "Sharp SM530") // 2Kx8 ROM, 88x4 RAM(24x4 for LCD), melody controller // internal memory maps @@ -47,11 +51,8 @@ sm530_device::sm530_device(const machine_config &mconfig, const char *tag, devic { } sm530_device::sm530_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int stack_levels, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data) : - sm511_device(mconfig, type, tag, owner, clock, stack_levels, prgwidth, program, datawidth, data) -{ } - -sm531_device::sm531_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - sm530_device(mconfig, SM531, tag, owner, clock, 1, 11, address_map_constructor(FUNC(sm531_device::program_2k), this), 7, address_map_constructor(FUNC(sm531_device::data_64_24x4), this)) + sm511_device(mconfig, type, tag, owner, clock, stack_levels, prgwidth, program, datawidth, data), + m_write_f(*this) { } @@ -63,6 +64,21 @@ void sm530_device::device_start() { // common init sm511_device::device_start(); + + // resolve callbacks + m_write_f.resolve_safe(); + + // zerofill + m_subdiv = 0; + m_count_1s = 0; + m_count_10ms = 0; + m_ds = false; + + // register for savestates + save_item(NAME(m_subdiv)); + save_item(NAME(m_count_1s)); + save_item(NAME(m_count_10ms)); + save_item(NAME(m_ds)); } @@ -74,6 +90,74 @@ void sm530_device::device_reset() { // common reset sm511_device::device_reset(); + + // assume LCD is on + m_bp = 0; + m_ds = true; +} + + +//------------------------------------------------- +// lcd driver +//------------------------------------------------- + +void sm530_device::lcd_update() +{ + // 2 rows + for (int h = 0; h < 2; h++) + { + for (int o = 0; o < m_lcd_ram_a.bytes(); o++) + { + // 4 segments per group + u8 seg = h ? m_lcd_ram_b[o] : m_lcd_ram_a[o]; + m_write_segs(o << 1 | h, m_ds ? seg : 0); + } + } +} + + +//------------------------------------------------- +// divider +//------------------------------------------------- + +TIMER_CALLBACK_MEMBER(sm530_device::div_timer_cb) +{ + m_div = (m_div + 1) & 0x7fff; + + if (m_div == 0) + { + // gamma signal on 1s + m_gamma |= 2; + + // increment seconds counter + m_count_1s = (m_count_1s + 1) % 10; + + // gamma signal on 10s + if (m_count_1s == 0) + m_gamma |= 1; + } + + // gamma signal on 0.5s + if ((m_div & 0x3fff) == 0) + m_gamma |= 4; + + // secondary timer for 1/100s intervals + if ((m_div & 0xff) < 250) + { + m_subdiv = (m_subdiv + 1) % 32000; + + if ((m_subdiv % 320) == 0) + { + // increment 1/100s counter + m_count_10ms = (m_count_10ms + 1) % 10; + + // gamma signal on 0.1s + if (m_count_10ms == 0) + m_gamma |= 8; + } + } + + clock_melody(); } @@ -105,19 +189,19 @@ void sm530_device::execute_one() case 0x44: op_sm(); break; case 0x48: op_tmi(); break; // TM case 0x60: case 0x64: op_tl(); break; - //case 0x6c: op_tg(); break; + case 0x6c: op_tg(); break; default: switch (m_op) { case 0x4c: op_incb(); break; case 0x4d: op_decb(); break; - //case 0x4e: op_rds(); break; - //case 0x4f: op_sds(); break; + case 0x4e: op_rds(); break; + case 0x4f: op_sds(); break; case 0x50: op_kta(); break; - //case 0x51: op_keta(); break; - //case 0x52: op_dta(); break; + case 0x51: op_keta(); break; + case 0x52: op_dta(); break; case 0x53: op_coma(); break; case 0x54: op_add(); break; case 0x55: op_add11(); break; // ADDC @@ -127,8 +211,8 @@ void sm530_device::execute_one() case 0x59: op_tam(); break; case 0x5a: op_exbla(); break; // EXBL case 0x5b: op_tc(); break; - //case 0x5c: op_ats(); break; - //case 0x5d: op_atf(); break; + case 0x5c: op_ats(); break; + case 0x5d: op_atf(); break; case 0x5e: op_atbp(); break; case 0x68: op_rtn0(); break; // RTN @@ -136,10 +220,10 @@ void sm530_device::execute_one() case 0x6a: op_atpl(); break; case 0x6b: op_lbl(); break; - //case 0x70: op_idiv(); break; - //case 0x71: op_inis(); break; + case 0x70: op_idiv(); break; + case 0x71: op_inis(); break; case 0x72: op_sbm(); break; // SABM - case 0x73: op_sbl(); break; // SABL + case 0x73: op_sabl(); break; case 0x74: op_cend(); break; case 0x75: op_tmel(); break; case 0x76: op_rme(); break; @@ -156,9 +240,8 @@ void sm530_device::execute_one() } // big switch - // SABL/SABM is only valid for 1 step - m_sbl = (m_op == 0x73); - m_sbm = (m_op == 0x72); + // SABM/SABL is only valid for 1 step + m_bmask = (m_op == 0x72) ? 0x40 : ((m_op == 0x73) ? 0x08 : 0); } bool sm530_device::op_argument() diff --git a/src/devices/cpu/sm510/sm530.h b/src/devices/cpu/sm510/sm530.h index 66136b89904..a9ea769d679 100644 --- a/src/devices/cpu/sm510/sm530.h +++ b/src/devices/cpu/sm510/sm530.h @@ -13,12 +13,67 @@ #include "sm511.h" +// pinout reference + +/* + OSC OSC + O21 O31 O41 O11 H1 K3 out in ACL BA GND Vm Vdd DDC Vcc K4 O10 O20 O30 O40 O1B + 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 + ____________________________________________________________________________________ + | | +O12 61 | | 39 O2B + | | +O42 62 | | 38 O3B + | | +O32 63 | | 37 O4B + | | +O22 64 | | 36 O1A + | | +O13 65 | | 35 O2A + | | +O43 66 | | 34 O3A + | | +O33 67 | | 33 O4A + | | +O23 68 | | 32 O19 + | | +O14 69 | | 31 O29 + | | +O44 70 | | 30 O39 + | SM530 | +O34 71 | | 29 O49 + | | +O24 72 | | 28 O18 + | | +O15 73 | | 27 O28 + | | +O45 74 | | 26 O38 + | | +O35 75 | | 25 O48 + | | +O25 76 | | 24 O17 + | | +O16 77 | | 23 O27 + | | +O46 78 | | 22 O37 + | | +O36 79 | | 21 O47 + | / +O26 80 | * / + |__________________________________________________________________________________/ + + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + H2 K2 KE1 KE2 KE3 KE3 S1 S2 S3 S4 GND SO NC NC F1 F2 F3 F4 TEST K1 +*/ class sm530_device : public sm511_device { public: sm530_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 32768); + // 4-bit F output port + auto write_f() { return m_write_f.bind(); } + protected: sm530_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int stack_levels, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data); @@ -39,26 +94,45 @@ protected: virtual void reset_vector() override { do_branch(0xf, 0); } virtual void wakeup_vector() override { do_branch(0, 0); } + devcb_write8 m_write_f; + + // lcd driver + virtual void lcd_update() override; + bool m_ds; + + // divider + virtual TIMER_CALLBACK_MEMBER(div_timer_cb) override; + u16 m_subdiv; + u8 m_count_1s; + u8 m_count_10ms; + + virtual u16 melody_step_mask() override { return 0xff; } + // opcode handlers - virtual void op_lb() override; virtual void op_incb() override; + virtual void op_lb() override; + virtual void op_sabl(); virtual void op_tl() override; virtual void op_trs(); + virtual void op_dta() override; + virtual void op_adx() override; - virtual void op_atbp() override; -}; + virtual void op_tg(); -class sm531_device : public sm530_device -{ -public: - sm531_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 32768); + virtual void op_keta(); + virtual void op_ats(); + virtual void op_atf(); + virtual void op_sds(); + virtual void op_rds(); + + virtual void op_idiv() override; + virtual void op_inis(); }; DECLARE_DEVICE_TYPE(SM530, sm530_device) -DECLARE_DEVICE_TYPE(SM531, sm531_device) #endif // MAME_CPU_SM510_SM530_H diff --git a/src/devices/cpu/sm510/sm530op.cpp b/src/devices/cpu/sm510/sm530op.cpp index 6beaa8905f4..a8a55d89d7b 100644 --- a/src/devices/cpu/sm510/sm530op.cpp +++ b/src/devices/cpu/sm510/sm530op.cpp @@ -20,6 +20,13 @@ void sm530_device::do_branch(u8 pu, u8 pl) // RAM address instructions +void sm530_device::op_incb() +{ + // INCB: increment BL, but overflow on 3rd bit! + sm511_device::op_incb(); + m_skip = ((m_bl & 7) == 0); +} + void sm530_device::op_lb() { // LB x: load BM/BL with 4-bit immediate value (partial) @@ -27,11 +34,9 @@ void sm530_device::op_lb() m_bm = m_op >> 2 & 3; } -void sm530_device::op_incb() +void sm530_device::op_sabl() { - // INCB: increment BL, but overflow on 3rd bit! - sm510_base_device::op_incb(); - m_skip = (m_bl == 8); + // SABL: set BL high bit for next opcode - handled in execute_one() } @@ -49,7 +54,16 @@ void sm530_device::op_trs() m_icount--; push_stack(); u8 jump = m_program->read_byte((14 << 6) | (m_op & 0x3f)); - do_branch(jump >> 5 & 7, jump & 0x1f); + do_branch(bitswap<3>(jump, 5,7,6), jump & 0x1f); +} + + +// Data transfer instructions + +void sm530_device::op_dta() +{ + // DTA: transfer 1/100s counter to ACC + m_acc = m_count_10ms; } @@ -64,10 +78,60 @@ void sm530_device::op_adx() } +// Test instructions + +void sm530_device::op_tg() +{ + // TG x: skip next if gamma flag is set, reset it after + m_skip = bool(m_gamma & bitmask(m_op)); + m_gamma &= ~bitmask(m_op); +} + + // I/O instructions -void sm530_device::op_atbp() +void sm530_device::op_keta() +{ + // KETA: input KE to ACC + m_acc = m_read_k() >> 4 & 0xf; +} + +void sm530_device::op_ats() +{ + // ATS: output ACC to S + m_write_s(m_acc); +} + +void sm530_device::op_atf() +{ + // ATS: output ACC to F + m_write_f(m_acc); +} + +void sm530_device::op_sds() +{ + // SDS: set display enable + m_ds = true; +} + +void sm530_device::op_rds() +{ + // RDS: reset display enable + m_ds = false; +} + + +// Special instructions + +void sm530_device::op_idiv() +{ + // IDIV: reset divider and 1s counter + m_div = m_subdiv = 0; + m_count_1s = 0; +} + +void sm530_device::op_inis() { - // ATBP: output ACC to BP - m_bp = m_acc; + // INIS: reset 1/100s counter + m_count_10ms = 0; } diff --git a/src/devices/cpu/sm510/sm590.cpp b/src/devices/cpu/sm510/sm590.cpp index d45fbbe7a82..790e8578a54 100644 --- a/src/devices/cpu/sm510/sm590.cpp +++ b/src/devices/cpu/sm510/sm590.cpp @@ -7,8 +7,6 @@ TODO: - finish SM590/SM595 emulation (NES/SNES CIC) - http://bitsavers.informatik.uni-stuttgart.de/pdf/sharp/_dataBooks/1990_Sharp_Microcomputers_Data_Book.pdf - pdf page 35/doc page 26 thru pdf page 44/doc page 35 */ #include "emu.h" @@ -67,11 +65,9 @@ void sm590_device::device_reset() // ACL m_skip = false; m_halt = false; - m_sbm = false; // needed? m_op = m_prev_op = 0; reset_vector(); m_prev_pc = m_pc; - m_clk_div = 4; // 4 clock oscillations per cycle on SM59x, see datasheet page 30/pdf page 39 m_rports[0] = m_rports[1] = m_rports[2] = m_rports[3] = 0; //m_write_r(0); // TODO: are the four ports zeroed on reset? diff --git a/src/devices/cpu/sm510/sm590.h b/src/devices/cpu/sm510/sm590.h index 5a0023642c8..93fedc460c1 100644 --- a/src/devices/cpu/sm510/sm590.h +++ b/src/devices/cpu/sm510/sm590.h @@ -98,10 +98,13 @@ protected: void data_16x2x4(address_map &map); virtual void device_reset() override; + virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; - virtual void init_divider() override { } - virtual void init_lcd_driver() override { } - virtual void init_melody() override { } + 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 void init_divider() override { } // no divider timer + virtual void init_lcd_driver() override { } // no lcd driver virtual void increment_pc() override; virtual void execute_one() override; virtual bool op_argument() override; diff --git a/src/devices/cpu/sm510/sm590op.cpp b/src/devices/cpu/sm510/sm590op.cpp index ff0b902c697..7a2c3f09ade 100644 --- a/src/devices/cpu/sm510/sm590op.cpp +++ b/src/devices/cpu/sm510/sm590op.cpp @@ -139,14 +139,14 @@ void sm590_device::op_lbmx() void sm590_device::op_tl() { // TL xyz: long jump (same as sm510 TL except m_op and m_param masks) - do_branch((m_op & 2)>>1, (((m_op & 1)<<1)|((m_param&0x80)?1:0)), m_param & 0x7f); + do_branch(BIT(m_op, 1), (m_op << 1 & 2) | BIT(m_param, 7), m_param & 0x7f); } void sm590_device::op_tml() // aka TLS { // TLS xyz: long call (same as sm510 TML except m_param mask) push_stack(); - do_branch((m_op & 2)>>1, (((m_op & 1)<<1)|((m_param&0x80)?1:0)), m_param & 0x7f); + do_branch(BIT(m_op, 1), (m_op << 1 & 2) | BIT(m_param, 7), m_param & 0x7f); } void sm590_device::op_t() diff --git a/src/devices/cpu/sm510/sm5a.cpp b/src/devices/cpu/sm510/sm5a.cpp index a6dbf24edab..298cefe9b2f 100644 --- a/src/devices/cpu/sm510/sm5a.cpp +++ b/src/devices/cpu/sm510/sm5a.cpp @@ -30,16 +30,12 @@ void sm5a_device::program_1_8k(address_map &map) void sm5a_device::data_5x13x4(address_map &map) { - map(0x00, 0x0b).ram(); - map(0x0c, 0x0c).ram().mirror(0x03); - map(0x10, 0x1b).ram(); - map(0x1c, 0x1c).ram().mirror(0x03); - map(0x20, 0x2b).ram(); - map(0x2c, 0x2c).ram().mirror(0x03); - map(0x30, 0x3b).ram(); - map(0x3c, 0x3c).ram().mirror(0x03); - map(0x40, 0x4b).ram().mirror(0x30); - map(0x4c, 0x4c).ram().mirror(0x33); + map(0x00, 0x7f).rw(FUNC(sm5a_device::mirror_r), FUNC(sm5a_device::mirror_w)); // d,e,f -> c + map(0x00, 0x0c).ram(); + map(0x10, 0x1c).ram(); + map(0x20, 0x2c).ram(); + map(0x30, 0x3c).ram(); + map(0x40, 0x4c).ram().mirror(0x30); } diff --git a/src/devices/cpu/sm510/sm5a.h b/src/devices/cpu/sm510/sm5a.h index de7128078d6..a44c687dfd9 100644 --- a/src/devices/cpu/sm510/sm5a.h +++ b/src/devices/cpu/sm510/sm5a.h @@ -23,23 +23,37 @@ ____________________________________________________________ | | OS1 46 | | 30 H1 + | | O41 47 | | 29 H2 + | | O31 48 | | 28 Vm + | | O21 49 | | 27 Vdd + | | O11 50 | | 26 _R2 + | | O42 51 | | 25 _R3 -O32 52 | SM5A | 24 _R4 -O22 53 | SM5L | 23 OSCin + | | +O32 52 | | 24 _R4 + | SM5A | +O22 53 | SM5L | 23 OSCin + | | O12 54 | | 22 OSCout + | | O43 55 | | 21 _T2 + | | O33 56 | | 20 _T1 + | | O23 57 | | 19 O18 + | | O13 58 | | 18 O28 + | | O44 59 | | 17 O38 -O34 60 | * | 16 O48 + | | +O34 60 | * | 16 O48 |____________________________________________________________/ - 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 O24 O14 O45 O35 O25 O15 O46 GND O36 O26 O16 O47 O37 O27 O17 */ @@ -56,6 +70,10 @@ protected: virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; virtual void execute_one() override; + + u8 mirror_r(offs_t offset) { return m_data->read_byte(offset & 0x7c); } + void mirror_w(offs_t offset, u8 data) { m_data->write_byte(offset & 0x7c, data); } + virtual int get_trs_field() override { return 1; } }; |