mirror of
https://github.com/holub/mame
synced 2025-05-07 23:02:33 +03:00
sm510: fix ATR opcode (nw)
This commit is contained in:
parent
6b53e7ddf0
commit
33170b8521
@ -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
|
||||
//-------------------------------------------------
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
//-------------------------------------------------
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
//-------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user