mirror of
https://github.com/holub/mame
synced 2025-05-11 16:48:52 +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_segbs.resolve_safe();
|
||||||
m_write_segc.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
|
// register for savestates
|
||||||
save_item(NAME(m_stack));
|
save_item(NAME(m_stack));
|
||||||
save_item(NAME(m_pc));
|
save_item(NAME(m_pc));
|
||||||
@ -78,10 +109,12 @@ void sm510_base_device::device_start()
|
|||||||
save_item(NAME(m_acc));
|
save_item(NAME(m_acc));
|
||||||
save_item(NAME(m_bl));
|
save_item(NAME(m_bl));
|
||||||
save_item(NAME(m_bm));
|
save_item(NAME(m_bm));
|
||||||
|
save_item(NAME(m_sbm));
|
||||||
save_item(NAME(m_c));
|
save_item(NAME(m_c));
|
||||||
save_item(NAME(m_skip));
|
save_item(NAME(m_skip));
|
||||||
save_item(NAME(m_w));
|
save_item(NAME(m_w));
|
||||||
save_item(NAME(m_r));
|
save_item(NAME(m_r));
|
||||||
|
save_item(NAME(m_r_out));
|
||||||
save_item(NAME(m_div));
|
save_item(NAME(m_div));
|
||||||
save_item(NAME(m_1s));
|
save_item(NAME(m_1s));
|
||||||
save_item(NAME(m_k_active));
|
save_item(NAME(m_k_active));
|
||||||
@ -138,7 +171,7 @@ void sm510_base_device::device_reset()
|
|||||||
m_bc = false;
|
m_bc = false;
|
||||||
m_y = 0;
|
m_y = 0;
|
||||||
|
|
||||||
m_r = 0;
|
m_r = m_r_out = 0;
|
||||||
m_write_r(0, 0, 0xff);
|
m_write_r(0, 0, 0xff);
|
||||||
m_melody_rd &= ~1;
|
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
|
// interrupt/divider
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
@ -174,7 +174,7 @@ protected:
|
|||||||
u8 m_c;
|
u8 m_c;
|
||||||
bool m_skip;
|
bool m_skip;
|
||||||
u8 m_w;
|
u8 m_w;
|
||||||
u8 m_r;
|
u8 m_r, m_r_out;
|
||||||
bool m_k_active;
|
bool m_k_active;
|
||||||
bool m_halt;
|
bool m_halt;
|
||||||
|
|
||||||
@ -199,8 +199,8 @@ protected:
|
|||||||
u8 m_melody_duty_index;
|
u8 m_melody_duty_index;
|
||||||
u8 m_melody_address;
|
u8 m_melody_address;
|
||||||
|
|
||||||
void clock_melody();
|
virtual void clock_melody() { }
|
||||||
void init_melody();
|
virtual void init_melody() { }
|
||||||
|
|
||||||
// interrupt/divider
|
// interrupt/divider
|
||||||
emu_timer *m_div_timer;
|
emu_timer *m_div_timer;
|
||||||
@ -311,6 +311,8 @@ protected:
|
|||||||
virtual void get_opcode_param() override;
|
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 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 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 execute_one() override;
|
||||||
virtual void get_opcode_param() override;
|
virtual void get_opcode_param() override;
|
||||||
|
|
||||||
|
virtual void clock_melody() override;
|
||||||
|
virtual void init_melody() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class sm512_device : public sm511_device
|
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
|
// execute
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
@ -263,11 +263,7 @@ void sm510_base_device::op_atfc()
|
|||||||
void sm510_base_device::op_atr()
|
void sm510_base_device::op_atr()
|
||||||
{
|
{
|
||||||
// ATR: output ACC to R
|
// ATR: output ACC to R
|
||||||
if (m_r != (m_acc & 3))
|
m_r = m_acc;
|
||||||
{
|
|
||||||
m_r = m_acc & 3;
|
|
||||||
m_write_r(0, m_r, 0xff);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
// execute
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user