sm510: fix ATR opcode (nw)

This commit is contained in:
hap 2017-04-30 10:42:47 +02:00
parent 6b53e7ddf0
commit 33170b8521
5 changed files with 140 additions and 85 deletions

View File

@ -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
//-------------------------------------------------

View File

@ -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

View File

@ -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
//-------------------------------------------------

View File

@ -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;
}

View File

@ -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
//-------------------------------------------------