swim1: import iwm fixes

This commit is contained in:
Olivier Galibert 2021-02-15 09:21:48 +01:00
parent 2835f1c165
commit 13017e5de1
3 changed files with 81 additions and 62 deletions

View File

@ -503,5 +503,5 @@ void iwm_device::sync()
}
break;
}
}
}
}

View File

@ -66,6 +66,7 @@ void swim1_device::device_start()
save_item(NAME(m_iwm_wsh));
save_item(NAME(m_iwm_rw_bit_count));
save_item(NAME(m_iwm_to_ism_counter));
save_item(NAME(m_iwm_devsel));
}
void swim1_device::device_reset()
@ -94,6 +95,7 @@ void swim1_device::device_reset()
m_iwm_rsh = 0x00;
m_iwm_rw_bit_count = 0;
m_iwm_to_ism_counter = 0;
m_iwm_devsel = 0;
m_devsel_cb(0);
m_sel35_cb(true);
@ -106,6 +108,9 @@ void swim1_device::set_floppy(floppy_image_device *floppy)
return;
sync();
flush_write();
logerror("floppy %s\n", floppy ? floppy->tag() : "-");
m_floppy = floppy;
update_phases();
@ -357,9 +362,13 @@ void swim1_device::ism_write(offs_t offset, u8 data)
void swim1_device::device_timer(emu_timer &, device_timer_id, int, void *)
{
if(m_iwm_active == MODE_DELAY) {
flush_write();
m_iwm_active = MODE_IDLE;
m_iwm_status &= ~0x20;
m_devsel_cb(0);
m_iwm_rw = MODE_IDLE;
m_iwm_rw_state = S_IDLE;
if(!(m_ism_mode & 0x40))
m_devsel_cb(0);
m_iwm_devsel = 0;
m_iwm_status &= ~0x20;
m_iwm_whd &= ~0x40;
}
@ -367,24 +376,26 @@ void swim1_device::device_timer(emu_timer &, device_timer_id, int, void *)
void swim1_device::flush_write(u64 when)
{
if(!m_flux_write_start)
return;
if(!when)
when = m_last_sync;
if(m_floppy && when > m_flux_write_start) {
if(m_flux_write_count && m_flux_write[m_flux_write_count-1] == when)
if(m_floppy && m_flux_write_start && when > m_flux_write_start) {
bool last_on_edge = m_flux_write_count && m_flux_write[m_flux_write_count-1] == when;
if(last_on_edge)
m_flux_write_count--;
attotime start = cycles_to_time(m_flux_write_start);
attotime end = cycles_to_time(when);
std::vector<attotime> fluxes(m_flux_write_count);
for(u32 i=0; i != m_flux_write_count; i++)
fluxes[i] = cycles_to_time(m_flux_write[i]);
m_floppy->write_flux(start, end, m_flux_write_count, m_flux_write_count ? &fluxes[0] : nullptr);
}
m_flux_write_count = 0;
m_flux_write_start = when;
m_flux_write_start = m_last_sync;
m_flux_write_count = 0;
if(last_on_edge)
m_flux_write[m_flux_write_count++] = when;
} else
m_flux_write_count = 0;
}
u8 swim1_device::iwm_control(int offset, u8 data)
@ -393,9 +404,6 @@ u8 swim1_device::iwm_control(int offset, u8 data)
u8 prev_iwm_to_ism_counter = m_iwm_to_ism_counter;
if(0)
logerror("iwm control trigger %x, %02x\n", offset, data);
u8 changed = m_iwm_control | (m_phases & 0xf);
if(offset < 8) {
if(offset & 1)
m_phases |= 1 << (offset >> 1);
@ -409,19 +417,52 @@ u8 swim1_device::iwm_control(int offset, u8 data)
m_iwm_control &= ~(1 << (offset >> 1));
}
changed ^= m_iwm_control | (m_phases & 0xf);
if(changed & 0x30)
m_devsel_cb(m_iwm_control & 0x10 ? m_iwm_control & 0x20 ? 2 : 1 : 0);
if(changed & 0x10) {
if(m_iwm_control & 0x10) {
if(m_iwm_control & 0x10) {
if(m_iwm_active != MODE_ACTIVE) {
m_iwm_active = MODE_ACTIVE;
m_iwm_status |= 0x20;
if(m_floppy)
m_floppy->mon_w(false);
}
if((m_iwm_control & 0x80) == 0x00) {
if(m_iwm_rw != MODE_READ) {
if(m_iwm_rw == MODE_WRITE) {
flush_write();
m_flux_write_start = 0;
}
m_iwm_rw = MODE_READ;
m_iwm_rw_state = S_IDLE;
m_iwm_next_state_change = 0;
m_iwm_sync_update = 0;
m_iwm_async_update = 0;
m_iwm_data = 0x00;
}
} else {
if(m_iwm_rw != MODE_WRITE) {
m_iwm_rw = MODE_WRITE;
m_iwm_rw_state = S_IDLE;
m_iwm_whd |= 0x40;
m_iwm_next_state_change = 0;
m_flux_write_start = m_last_sync;
m_flux_write_count = 0;
if(m_floppy)
m_floppy->set_write_splice(cycles_to_time(m_flux_write_start));
}
}
} else {
if(m_iwm_active == MODE_ACTIVE) {
flush_write();
if(m_iwm_mode & 0x04) {
m_flux_write_start = 0;
m_iwm_active = MODE_IDLE;
m_iwm_rw = MODE_IDLE;
m_iwm_rw_state = S_IDLE;
m_iwm_status &= ~0x20;
m_iwm_whd &= ~0x40;
if(m_floppy)
m_floppy->mon_w(true);
} else {
m_devsel_cb(m_iwm_control & 0x20 ? 2 : 1);
m_iwm_active = MODE_DELAY;
@ -430,39 +471,13 @@ u8 swim1_device::iwm_control(int offset, u8 data)
}
}
if(changed & 0xd0) {
if((m_iwm_control & 0xc0) == 0x00 && m_iwm_active) {
if(m_iwm_rw == MODE_WRITE)
flush_write();
m_iwm_rw = MODE_READ;
m_iwm_rw_state = S_IDLE;
m_iwm_status &= ~0x20;
m_iwm_whd &= ~0x40;
m_iwm_next_state_change = 0;
m_iwm_sync_update = 0;
m_iwm_async_update = 0;
m_iwm_data = 0x00;
} else if((m_iwm_control & 0xc0) == 0xc0 && m_iwm_active && m_iwm_rw != MODE_WRITE) {
m_iwm_rw = MODE_WRITE;
m_iwm_rw_state = S_IDLE;
m_iwm_whd |= 0x40;
m_iwm_next_state_change = 0;
m_flux_write_start = m_last_sync;
m_flux_write_count = 0;
if(m_floppy)
m_floppy->set_write_splice(cycles_to_time(m_flux_write_start));
} else if(m_iwm_rw == MODE_WRITE) {
if(!(m_iwm_control & 0x80)) {
flush_write();
m_iwm_rw = MODE_IDLE;
}
} else
m_iwm_rw = MODE_IDLE;
u8 devsel = m_iwm_active != MODE_IDLE ? m_iwm_control & 0x20 ? 2 : 1 : 0;
if(devsel != m_iwm_devsel) {
m_iwm_devsel = devsel;
m_devsel_cb(devsel);
}
if(changed && 0) {
if(0) {
u8 s = m_iwm_control & 0xc0;
const char *slot = "?";
if(s == 0x00 && !m_iwm_active)
@ -478,7 +493,8 @@ u8 swim1_device::iwm_control(int offset, u8 data)
if(s == 0xc0 && m_iwm_active)
slot = "write load / write data";
logerror("control %c%c %c%c %c%c%c%c (%s) [%s, %s]\n",
logerror("%s control %c%c %c%c %c%c%c%c (%s) [%s, %s] whd=%02x data=%02x\n",
machine().time().to_string(),
m_iwm_control & 0x80 ? '1' : '0',
m_iwm_control & 0x40 ? '1' : '0',
m_iwm_control & 0x20 ? 'b' : 'a',
@ -489,10 +505,11 @@ u8 swim1_device::iwm_control(int offset, u8 data)
m_phases & 0x01 ? '#' : '.',
slot,
m_iwm_active == MODE_IDLE ? "idle" : m_iwm_active == MODE_DELAY ? "delay" : "active",
m_iwm_rw == MODE_IDLE ? "idle" : m_iwm_rw == MODE_READ ? "read" : "write");
m_iwm_rw == MODE_IDLE ? "idle" : m_iwm_rw == MODE_READ ? "read" : "write",
m_iwm_whd, m_iwm_data);
}
if(m_iwm_active && !(m_iwm_control & 0xc0) && !iwm_is_sync() && (m_iwm_data & 0x80))
if(m_iwm_active && !(m_iwm_control & 0x80) && !iwm_is_sync() && (m_iwm_data & 0x80))
m_iwm_async_update = m_last_sync + 14;
if(offset == 0xf) {
@ -520,7 +537,7 @@ u8 swim1_device::iwm_control(int offset, u8 data)
switch(m_iwm_control & 0xc0) {
case 0x00: return m_iwm_active ? m_iwm_data : 0xff;
case 0x40: return (m_iwm_status & 0x7f) | (m_floppy && m_floppy->wpt_r() ? 0x80 : 0);
case 0x40: return (m_iwm_status & 0x7f) | ((m_floppy && m_floppy->wpt_r()) ? 0x80 : 0x00);
case 0x80: return m_iwm_whd;
case 0xc0: if(offset & 1) { if(m_iwm_active) iwm_data_w(data); else iwm_mode_w(data); } return 0xff;
}
@ -695,6 +712,7 @@ void swim1_device::iwm_sync()
} else if(m_iwm_rsh >= 0x80) {
m_iwm_data = m_iwm_rsh;
m_iwm_async_update = 0;
m_iwm_rsh = 0;
}
break;
@ -707,9 +725,8 @@ void swim1_device::iwm_sync()
m_iwm_sync_update = 0;
}
if(m_iwm_async_update && m_iwm_async_update <= m_last_sync) {
if(!iwm_is_sync()) {
if(!iwm_is_sync())
m_iwm_data = 0;
}
m_iwm_async_update = 0;
}
break;
@ -717,7 +734,7 @@ void swim1_device::iwm_sync()
case MODE_WRITE: {
while(next_sync > m_last_sync) {
if(next_sync < m_iwm_next_state_change) {
if(next_sync < m_iwm_next_state_change || !(m_iwm_whd & 0x40)) {
m_last_sync = next_sync;
break;
}
@ -739,9 +756,10 @@ void swim1_device::iwm_sync()
case SW_WINDOW_LOAD:
if(m_iwm_whd & 0x80) {
logerror("Underrun\n");
logerror("underrun\n");
flush_write();
m_flux_write_start = 0;
m_iwm_whd &= ~0x40;
m_iwm_rw_state = S_IDLE;
m_last_sync = next_sync;
} else {
m_iwm_wsh = m_iwm_data;
@ -781,7 +799,7 @@ void swim1_device::iwm_sync()
}
break;
}
}
}
}
void swim1_device::ism_sync()

View File

@ -108,6 +108,7 @@ private:
u8 m_iwm_data, m_iwm_whd, m_iwm_mode, m_iwm_status, m_iwm_control, m_iwm_rw_bit_count;
u8 m_iwm_rsh, m_iwm_wsh;
u8 m_iwm_to_ism_counter;
u8 m_iwm_devsel;
u64 time_to_cycles(const attotime &tm) const;
attotime cycles_to_time(u64 cycles) const;