machine/wd_fdc.cpp: Don’t clear DRQ on LDB/INTR, and fix spurious READ TRACk/ADDR FM mark syncs. (#11041) [Peter Phillips, Tim Lindner]

Fixes SuperUtility 3 (MT08511) and Marble Maze on TRS-80 Color Computer.
This commit is contained in:
tim lindner 2023-03-30 10:22:58 -07:00 committed by GitHub
parent ce4015da60
commit 6ea69b0ed9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 50 additions and 61 deletions

View File

@ -136,6 +136,16 @@ static const char *const states[] =
"WRITE_SECTOR_PRE_BYTE"
};
template <unsigned B> inline uint32_t wd_fdc_device_base::live_info::shift_reg_low() const
{
return shift_reg & make_bitmask<uint32_t>(B);
}
inline uint8_t wd_fdc_device_base::live_info::shift_reg_data() const
{
return bitswap<8>(shift_reg, 14, 12, 10, 8, 6, 4, 2, 0);
}
wd_fdc_device_base::wd_fdc_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, type, tag, owner, clock),
intrq_cb(*this),
@ -1079,7 +1089,6 @@ void wd_fdc_device_base::interrupt_start()
main_state = sub_state = cur_live.state = IDLE;
cur_live.tm = attotime::never;
status &= ~S_BUSY;
drop_drq();
motor_timeout = 0;
} else {
// when a force interrupt command is issued and there is no
@ -1718,7 +1727,7 @@ void wd_fdc_device_base::reset_data_sync()
cur_live.data_separator_phase = false;
cur_live.bit_counter = 0;
cur_live.data_reg = bitswap<8>(cur_live.shift_reg, 14, 12, 10, 8, 6, 4, 2, 0);
cur_live.data_reg = cur_live.shift_reg_data();
}
bool wd_fdc_device_base::write_one_bit(const attotime &limit)
@ -1804,24 +1813,17 @@ void wd_fdc_device_base::live_run(attotime limit)
if(read_one_bit(limit))
return;
LOGSHIFT("%s: shift = %04x data=%02x c=%d\n", cur_live.tm.to_string(), cur_live.shift_reg,
(cur_live.shift_reg & 0x4000 ? 0x80 : 0x00) |
(cur_live.shift_reg & 0x1000 ? 0x40 : 0x00) |
(cur_live.shift_reg & 0x0400 ? 0x20 : 0x00) |
(cur_live.shift_reg & 0x0100 ? 0x10 : 0x00) |
(cur_live.shift_reg & 0x0040 ? 0x08 : 0x00) |
(cur_live.shift_reg & 0x0010 ? 0x04 : 0x00) |
(cur_live.shift_reg & 0x0004 ? 0x02 : 0x00) |
(cur_live.shift_reg & 0x0001 ? 0x01 : 0x00),
LOGSHIFT("%s: shift = %08x data=%02x c=%d\n", cur_live.tm.to_string(), cur_live.shift_reg,
cur_live.shift_reg_data(),
cur_live.bit_counter);
if(!dden && cur_live.shift_reg == 0x4489) {
if(!dden && cur_live.shift_reg_low<16>() == 0x4489) {
cur_live.crc = 0x443b;
reset_data_sync();
cur_live.state = READ_HEADER_BLOCK_HEADER;
}
if(dden && cur_live.shift_reg == 0xf57e) {
if(dden && cur_live.shift_reg_low<23>() == 0x2af57e) {
cur_live.crc = 0xef21;
reset_data_sync();
if(main_state == READ_ID)
@ -1836,15 +1838,8 @@ void wd_fdc_device_base::live_run(attotime limit)
if(read_one_bit(limit))
return;
LOGSHIFT("%s: shift = %04x data=%02x counter=%d\n", cur_live.tm.to_string(), cur_live.shift_reg,
(cur_live.shift_reg & 0x4000 ? 0x80 : 0x00) |
(cur_live.shift_reg & 0x1000 ? 0x40 : 0x00) |
(cur_live.shift_reg & 0x0400 ? 0x20 : 0x00) |
(cur_live.shift_reg & 0x0100 ? 0x10 : 0x00) |
(cur_live.shift_reg & 0x0040 ? 0x08 : 0x00) |
(cur_live.shift_reg & 0x0010 ? 0x04 : 0x00) |
(cur_live.shift_reg & 0x0004 ? 0x02 : 0x00) |
(cur_live.shift_reg & 0x0001 ? 0x01 : 0x00),
LOGSHIFT("%s: shift = %08x data=%02x counter=%d\n", cur_live.tm.to_string(), cur_live.shift_reg,
cur_live.shift_reg_data(),
cur_live.bit_counter);
if(cur_live.bit_counter & 15)
@ -1853,7 +1848,7 @@ void wd_fdc_device_base::live_run(attotime limit)
int slot = cur_live.bit_counter >> 4;
if(slot < 3) {
if(cur_live.shift_reg != 0x4489)
if(cur_live.shift_reg_low<16>() != 0x4489)
cur_live.state = SEARCH_ADDRESS_MARK_HEADER;
break;
}
@ -1924,15 +1919,8 @@ void wd_fdc_device_base::live_run(attotime limit)
if(read_one_bit(limit))
return;
LOGSHIFT("%s: shift = %04x data=%02x c=%d.%x\n", cur_live.tm.to_string(), cur_live.shift_reg,
(cur_live.shift_reg & 0x4000 ? 0x80 : 0x00) |
(cur_live.shift_reg & 0x1000 ? 0x40 : 0x00) |
(cur_live.shift_reg & 0x0400 ? 0x20 : 0x00) |
(cur_live.shift_reg & 0x0100 ? 0x10 : 0x00) |
(cur_live.shift_reg & 0x0040 ? 0x08 : 0x00) |
(cur_live.shift_reg & 0x0010 ? 0x04 : 0x00) |
(cur_live.shift_reg & 0x0004 ? 0x02 : 0x00) |
(cur_live.shift_reg & 0x0001 ? 0x01 : 0x00),
LOGSHIFT("%s: shift = %08x data=%02x c=%d.%x\n", cur_live.tm.to_string(), cur_live.shift_reg,
cur_live.shift_reg_data(),
cur_live.bit_counter >> 4, cur_live.bit_counter & 15);
if(!dden) {
@ -1941,7 +1929,7 @@ void wd_fdc_device_base::live_run(attotime limit)
return;
}
if(cur_live.bit_counter >= 28*16 && cur_live.shift_reg == 0x4489) {
if(cur_live.bit_counter >= 28*16 && cur_live.shift_reg_low<16>() == 0x4489) {
cur_live.crc = 0x443b;
reset_data_sync();
cur_live.state = READ_DATA_BLOCK_HEADER;
@ -1952,12 +1940,12 @@ void wd_fdc_device_base::live_run(attotime limit)
return;
}
if(cur_live.bit_counter >= 11*16 && (cur_live.shift_reg == 0xf56a || cur_live.shift_reg == 0xf56b ||
cur_live.shift_reg == 0xf56e || cur_live.shift_reg == 0xf56f)) {
if(cur_live.bit_counter >= 11*16 && (cur_live.shift_reg_low<16>() == 0xf56a || cur_live.shift_reg_low<16>() == 0xf56b ||
cur_live.shift_reg_low<16>() == 0xf56e || cur_live.shift_reg_low<16>() == 0xf56f)) {
cur_live.crc =
cur_live.shift_reg == 0xf56a ? 0x8fe7 :
cur_live.shift_reg == 0xf56b ? 0x9fc6 :
cur_live.shift_reg == 0xf56e ? 0xafa5 :
cur_live.shift_reg_low<16>() == 0xf56a ? 0x8fe7 :
cur_live.shift_reg_low<16>() == 0xf56b ? 0x9fc6 :
cur_live.shift_reg_low<16>() == 0xf56e ? 0xafa5 :
0xbf84;
reset_data_sync();
@ -1980,15 +1968,8 @@ void wd_fdc_device_base::live_run(attotime limit)
if(read_one_bit(limit))
return;
LOGSHIFT("%s: shift = %04x data=%02x counter=%d\n", cur_live.tm.to_string(), cur_live.shift_reg,
(cur_live.shift_reg & 0x4000 ? 0x80 : 0x00) |
(cur_live.shift_reg & 0x1000 ? 0x40 : 0x00) |
(cur_live.shift_reg & 0x0400 ? 0x20 : 0x00) |
(cur_live.shift_reg & 0x0100 ? 0x10 : 0x00) |
(cur_live.shift_reg & 0x0040 ? 0x08 : 0x00) |
(cur_live.shift_reg & 0x0010 ? 0x04 : 0x00) |
(cur_live.shift_reg & 0x0004 ? 0x02 : 0x00) |
(cur_live.shift_reg & 0x0001 ? 0x01 : 0x00),
LOGSHIFT("%s: shift = %08x data=%02x counter=%d\n", cur_live.tm.to_string(), cur_live.shift_reg,
cur_live.shift_reg_data(),
cur_live.bit_counter);
if(cur_live.bit_counter & 15)
@ -1997,7 +1978,7 @@ void wd_fdc_device_base::live_run(attotime limit)
int slot = cur_live.bit_counter >> 4;
if(slot < 3) {
if(cur_live.shift_reg != 0x4489) {
if(cur_live.shift_reg_low<16>() != 0x4489) {
live_delay(SEARCH_ADDRESS_MARK_DATA_FAILED);
return;
}
@ -2061,17 +2042,26 @@ void wd_fdc_device_base::live_run(attotime limit)
if(read_one_bit(limit))
return;
if(dden) {
//FM Prefix match
if(cur_live.shift_reg_low<17>() == 0xabd5) { // 17-bit match
cur_live.data_separator_phase = false;
cur_live.bit_counter = 5*2; // prefix is 5 of 8 bits
cur_live.data_reg = 0xff;
break;
} else if(cur_live.bit_counter == 16) {
cur_live.data_separator_phase = false;
cur_live.bit_counter = 0;
live_delay(READ_TRACK_DATA_BYTE);
return;
}
break;
}
// !dden
if(cur_live.bit_counter != 16
// MFM resyncs
&& !(!dden && (cur_live.shift_reg == 0x4489
|| cur_live.shift_reg == 0x5224))
// FM resyncs
&& !(dden && (cur_live.shift_reg == 0xf57e // FM IDAM
|| cur_live.shift_reg == 0xf56f // FM DAM
|| cur_live.shift_reg == 0xf56a // FM DDAM
|| cur_live.shift_reg == 0xf56b // FM DDAM
|| cur_live.shift_reg == 0xf56e // FM DDAM
|| cur_live.shift_reg == 0xf56f)) // FM DDAM
&& !((cur_live.shift_reg_low<16>() == 0x4489
|| cur_live.shift_reg_low<16>() == 0x5224))
)
break;
@ -2387,9 +2377,6 @@ void wd_fdc_device_base::set_drq()
{
if(drq) {
status |= S_LOST;
drq = false;
if(!drq_cb.isnull())
drq_cb(false);
} else if(!(status & S_LOST)) {
drq = true;
if(!drq_cb.isnull())

View File

@ -254,12 +254,14 @@ private:
attotime tm;
int state, next_state;
uint16_t shift_reg;
uint32_t shift_reg;
uint16_t crc;
int bit_counter, byte_counter, previous_type;
bool data_separator_phase, data_bit_context;
uint8_t data_reg;
uint8_t idbuf[6];
template <unsigned B> uint32_t shift_reg_low() const;
uint8_t shift_reg_data() const;
};
enum {