mirror of
https://github.com/holub/mame
synced 2025-04-24 09:20:02 +03:00
iwm: Better state management, better write flush, better underrun handling
This commit is contained in:
parent
c823e1668f
commit
2835f1c165
@ -56,6 +56,7 @@ void iwm_device::device_start()
|
||||
save_item(NAME(m_rsh));
|
||||
save_item(NAME(m_wsh));
|
||||
save_item(NAME(m_rw_bit_count));
|
||||
save_item(NAME(m_devsel));
|
||||
}
|
||||
|
||||
void iwm_device::device_reset()
|
||||
@ -77,6 +78,7 @@ void iwm_device::device_reset()
|
||||
m_flux_write_start = 0;
|
||||
m_flux_write_count = 0;
|
||||
m_rw_bit_count = 0;
|
||||
m_devsel = 0;
|
||||
m_devsel_cb(0);
|
||||
}
|
||||
|
||||
@ -85,9 +87,12 @@ void iwm_device::device_timer(emu_timer &, device_timer_id, int, void *)
|
||||
if(m_active == MODE_DELAY) {
|
||||
flush_write();
|
||||
m_active = MODE_IDLE;
|
||||
m_rw = MODE_IDLE;
|
||||
m_rw_state = S_IDLE;
|
||||
if(m_floppy)
|
||||
m_floppy->mon_w(true);
|
||||
m_devsel_cb(0);
|
||||
m_devsel = 0;
|
||||
m_status &= ~0x20;
|
||||
m_whd &= ~0x40;
|
||||
}
|
||||
@ -99,6 +104,7 @@ void iwm_device::set_floppy(floppy_image_device *floppy)
|
||||
return;
|
||||
|
||||
sync();
|
||||
flush_write();
|
||||
|
||||
logerror("floppy %s\n", floppy ? floppy->tag() : "-");
|
||||
|
||||
@ -128,7 +134,8 @@ void iwm_device::write(offs_t offset, u8 data)
|
||||
void iwm_device::flush_write()
|
||||
{
|
||||
if(m_floppy && m_flux_write_start && m_last_sync > m_flux_write_start) {
|
||||
if(m_flux_write_count && m_flux_write[m_flux_write_count-1] == m_last_sync)
|
||||
bool last_on_edge = m_flux_write_count && m_flux_write[m_flux_write_count-1] == m_last_sync;
|
||||
if(last_on_edge)
|
||||
m_flux_write_count--;
|
||||
attotime start = cycles_to_time(m_flux_write_start);
|
||||
attotime end = cycles_to_time(m_last_sync);
|
||||
@ -137,16 +144,18 @@ void iwm_device::flush_write()
|
||||
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_start = m_last_sync;
|
||||
}
|
||||
m_flux_write_count = 0;
|
||||
m_flux_write_count = 0;
|
||||
if(last_on_edge)
|
||||
m_flux_write[m_flux_write_count++] = m_last_sync;
|
||||
} else
|
||||
m_flux_write_count = 0;
|
||||
|
||||
}
|
||||
|
||||
u8 iwm_device::control(int offset, u8 data)
|
||||
{
|
||||
sync();
|
||||
|
||||
// logerror("control trigger %x, %02x\n", offset, data);
|
||||
u8 changed = m_control | (m_phases & 0xf);
|
||||
if(offset < 8) {
|
||||
if(offset & 1)
|
||||
m_phases |= 1 << (offset >> 1);
|
||||
@ -160,22 +169,48 @@ u8 iwm_device::control(int offset, u8 data)
|
||||
m_control &= ~(1 << (offset >> 1));
|
||||
}
|
||||
|
||||
changed ^= m_control | (m_phases & 0xf);
|
||||
|
||||
if(changed & 0x30)
|
||||
m_devsel_cb(m_control & 0x10 ? m_control & 0x20 ? 2 : 1 : 0);
|
||||
|
||||
if(changed & 0x10) {
|
||||
if(m_control & 0x10) {
|
||||
if(m_control & 0x10) {
|
||||
if(m_active != MODE_ACTIVE) {
|
||||
m_active = MODE_ACTIVE;
|
||||
m_status |= 0x20;
|
||||
if(m_floppy)
|
||||
m_floppy->mon_w(false);
|
||||
}
|
||||
|
||||
if((m_control & 0x80) == 0x00) {
|
||||
if(m_rw != MODE_READ) {
|
||||
if(m_rw == MODE_WRITE) {
|
||||
flush_write();
|
||||
m_flux_write_start = 0;
|
||||
}
|
||||
m_rw = MODE_READ;
|
||||
m_rw_state = S_IDLE;
|
||||
m_next_state_change = 0;
|
||||
m_sync_update = 0;
|
||||
m_async_update = 0;
|
||||
m_data = 0x00;
|
||||
}
|
||||
|
||||
} else {
|
||||
if(m_rw != MODE_WRITE) {
|
||||
m_rw = MODE_WRITE;
|
||||
m_rw_state = S_IDLE;
|
||||
m_whd |= 0x40;
|
||||
m_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_active == MODE_ACTIVE) {
|
||||
flush_write();
|
||||
if(m_mode & 0x04) {
|
||||
flush_write();
|
||||
m_flux_write_start = 0;
|
||||
m_active = MODE_IDLE;
|
||||
m_rw = MODE_IDLE;
|
||||
m_rw_state = S_IDLE;
|
||||
m_status &= ~0x20;
|
||||
m_whd &= ~0x40;
|
||||
if(m_floppy)
|
||||
@ -188,37 +223,10 @@ u8 iwm_device::control(int offset, u8 data)
|
||||
}
|
||||
}
|
||||
|
||||
if(changed & 0xd0) {
|
||||
if((m_control & 0xc0) == 0x00 && m_active) {
|
||||
if(m_rw == MODE_WRITE) {
|
||||
flush_write();
|
||||
m_flux_write_start = 0;
|
||||
}
|
||||
m_rw = MODE_READ;
|
||||
m_rw_state = S_IDLE;
|
||||
m_next_state_change = 0;
|
||||
m_sync_update = 0;
|
||||
m_async_update = 0;
|
||||
m_data = 0x00;
|
||||
|
||||
} else if((m_control & 0xc0) == 0xc0 && m_active && m_rw != MODE_WRITE) {
|
||||
m_rw = MODE_WRITE;
|
||||
m_rw_state = S_IDLE;
|
||||
m_whd |= 0x40;
|
||||
m_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_rw == MODE_WRITE) {
|
||||
if(!(m_control & 0x80)) {
|
||||
flush_write();
|
||||
m_flux_write_start = 0;
|
||||
m_rw = MODE_IDLE;
|
||||
}
|
||||
} else
|
||||
m_rw = MODE_IDLE;
|
||||
u8 devsel = m_active != MODE_IDLE ? m_control & 0x20 ? 2 : 1 : 0;
|
||||
if(devsel != m_devsel) {
|
||||
m_devsel = devsel;
|
||||
m_devsel_cb(devsel);
|
||||
}
|
||||
|
||||
if(0) {
|
||||
@ -253,7 +261,7 @@ u8 iwm_device::control(int offset, u8 data)
|
||||
m_whd, m_data);
|
||||
}
|
||||
|
||||
if(m_active && !(m_control & 0xc0) && !is_sync() && (m_data & 0x80))
|
||||
if(m_active && !(m_control & 0x80) && !is_sync() && (m_data & 0x80))
|
||||
m_async_update = m_last_sync + 14;
|
||||
|
||||
switch(m_control & 0xc0) {
|
||||
@ -337,8 +345,6 @@ u64 iwm_device::write_sync_half_window_size() const
|
||||
return m_mode & 0x08 ? 2 : 4;
|
||||
}
|
||||
|
||||
static u64 ssx1 = 0, ssx2 = 0;
|
||||
|
||||
void iwm_device::sync()
|
||||
{
|
||||
if(!m_active)
|
||||
@ -358,12 +364,6 @@ void iwm_device::sync()
|
||||
next_flux_change = flux.is_never() ? u64(-1) : time_to_cycles(flux);
|
||||
if(next_flux_change <= m_last_sync)
|
||||
next_flux_change = m_last_sync+1;
|
||||
if(!ssx1)
|
||||
ssx1 = ssx2 = next_flux_change;
|
||||
if(ssx2 != next_flux_change) {
|
||||
ssx1 = ssx2;
|
||||
ssx2 = next_flux_change;
|
||||
}
|
||||
}
|
||||
if(next_sync < m_next_state_change) {
|
||||
m_last_sync = next_sync;
|
||||
@ -429,7 +429,7 @@ void iwm_device::sync()
|
||||
|
||||
case MODE_WRITE: {
|
||||
while(next_sync > m_last_sync) {
|
||||
if(next_sync < m_next_state_change) {
|
||||
if(next_sync < m_next_state_change || !(m_whd & 0x40)) {
|
||||
m_last_sync = next_sync;
|
||||
break;
|
||||
}
|
||||
@ -454,8 +454,10 @@ void iwm_device::sync()
|
||||
|
||||
case SW_WINDOW_LOAD:
|
||||
if(m_whd & 0x80) {
|
||||
logerror("underrun\n");
|
||||
flush_write();
|
||||
m_flux_write_start = 0;
|
||||
m_whd &= ~0x40;
|
||||
m_rw_state = S_IDLE;
|
||||
m_last_sync = next_sync;
|
||||
} else {
|
||||
m_wsh = m_data;
|
||||
|
@ -67,6 +67,7 @@ private:
|
||||
int m_active, m_rw, m_rw_state;
|
||||
u8 m_data, m_whd, m_mode, m_status, m_control, m_rw_bit_count;
|
||||
u8 m_rsh, m_wsh;
|
||||
u8 m_devsel;
|
||||
|
||||
u8 control(int offset, u8 data);
|
||||
u64 time_to_cycles(const attotime &tm) const;
|
||||
|
Loading…
Reference in New Issue
Block a user