diff options
Diffstat (limited to 'src/devices/machine/wd_fdc.cpp')
-rw-r--r-- | src/devices/machine/wd_fdc.cpp | 409 |
1 files changed, 207 insertions, 202 deletions
diff --git a/src/devices/machine/wd_fdc.cpp b/src/devices/machine/wd_fdc.cpp index 29645a83489..4e4f03bb6e9 100644 --- a/src/devices/machine/wd_fdc.cpp +++ b/src/devices/machine/wd_fdc.cpp @@ -5,10 +5,7 @@ #include "imagedev/floppy.h" -#include "debugger.h" - -//#define LOG_GENERAL (1U << 0) //defined in logmacro.h already -#define LOG_SETUP (1U << 1) // Shows register setup +#define LOG_DATA (1U << 1) // Shows data reads and writes #define LOG_SHIFT (1U << 2) // Shows shift register contents #define LOG_COMP (1U << 3) // Shows operations on the CPU side #define LOG_COMMAND (1U << 4) // Shows command invocation @@ -30,7 +27,7 @@ #include "logmacro.h" -#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__) +#define LOGDATA(...) LOGMASKED(LOG_DATA, __VA_ARGS__) #define LOGSHIFT(...) LOGMASKED(LOG_SHIFT, __VA_ARGS__) #define LOGCOMP(...) LOGMASKED(LOG_COMP, __VA_ARGS__) #define LOGCOMMAND(...) LOGMASKED(LOG_COMMAND, __VA_ARGS__) @@ -98,6 +95,8 @@ static const char *const states[] = "SPINUP_DONE", "SETTLE_WAIT", "SETTLE_DONE", + "WRITE_PROTECT_WAIT", + "WRITE_PROTECT_DONE", "DATA_LOAD_WAIT", "DATA_LOAD_WAIT_DONE", "SEEK_MOVE", @@ -134,6 +133,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), @@ -142,12 +151,13 @@ wd_fdc_device_base::wd_fdc_device_base(const machine_config &mconfig, device_typ enp_cb(*this), sso_cb(*this), ready_cb(*this), // actually output by the drive, not by the FDC - enmf_cb(*this), + enmf_cb(*this, 0), mon_cb(*this) { force_ready = false; disable_motor_control = false; spinup_on_interrupt = false; + extended_ddam = false; hlt = true; // assume tied to VCC } @@ -163,22 +173,13 @@ void wd_fdc_device_base::set_disable_motor_control(bool _disable_motor_control) void wd_fdc_device_base::device_start() { - intrq_cb.resolve(); - drq_cb.resolve(); - hld_cb.resolve(); - enp_cb.resolve(); - sso_cb.resolve(); - ready_cb.resolve(); - enmf_cb.resolve(); - mon_cb.resolve_safe(); - - if (!has_enmf && !enmf_cb.isnull()) + if (!has_enmf && !enmf_cb.isunset()) logerror("Warning, this chip doesn't have an ENMF line.\n"); - t_gen = timer_alloc(TM_GEN); - t_cmd = timer_alloc(TM_CMD); - t_track = timer_alloc(TM_TRACK); - t_sector = timer_alloc(TM_SECTOR); + t_gen = timer_alloc(FUNC(wd_fdc_device_base::generic_tick), this); + t_cmd = timer_alloc(FUNC(wd_fdc_device_base::cmd_w_tick), this); + t_track = timer_alloc(FUNC(wd_fdc_device_base::track_w_tick), this); + t_sector = timer_alloc(FUNC(wd_fdc_device_base::sector_w_tick), this); dden = disable_mfm; enmf = false; floppy = nullptr; @@ -224,7 +225,7 @@ void wd_fdc_device_base::soft_reset() } } -WRITE_LINE_MEMBER(wd_fdc_device_base::mr_w) +void wd_fdc_device_base::mr_w(int state) { if(mr && !state) { command = 0x03; @@ -240,19 +241,16 @@ WRITE_LINE_MEMBER(wd_fdc_device_base::mr_w) mr = false; // gnd == enmf enabled, otherwise disabled (default) - if (!enmf_cb.isnull() && has_enmf) + if (!enmf_cb.isunset() && has_enmf) enmf = enmf_cb() ? false : true; intrq = false; - if (!intrq_cb.isnull()) - intrq_cb(intrq); + intrq_cb(intrq); drq = false; - if (!drq_cb.isnull()) - drq_cb(drq); + drq_cb(drq); if(head_control) { hld = false; - if(!hld_cb.isnull()) - hld_cb(hld); + hld_cb(hld); } mon_cb(1); // Clear the MON* line @@ -302,7 +300,7 @@ void wd_fdc_device_base::set_floppy(floppy_image_device *_floppy) ready_callback(floppy, next_ready); } -WRITE_LINE_MEMBER(wd_fdc_device_base::dden_w) +void wd_fdc_device_base::dden_w(int state) { if(disable_mfm) { logerror("Error, this chip does not have a dden line\n"); @@ -315,18 +313,35 @@ WRITE_LINE_MEMBER(wd_fdc_device_base::dden_w) } } -void wd_fdc_device_base::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +TIMER_CALLBACK_MEMBER(wd_fdc_device_base::generic_tick) +{ + LOGEVENT("Event fired for TM_GEN\n"); + live_sync(); + do_generic(); + general_continue(); +} + +TIMER_CALLBACK_MEMBER(wd_fdc_device_base::cmd_w_tick) { - LOGEVENT("Event fired for timer %s\n", (id==TM_GEN)? "TM_GEN" : (id==TM_CMD)? "TM_CMD" : (id==TM_TRACK)? "TM_TRACK" : "TM_SECTOR"); + LOGEVENT("Event fired for TM_CMD\n"); live_sync(); + do_cmd_w(); + general_continue(); +} - switch(id) { - case TM_GEN: do_generic(); break; - case TM_CMD: do_cmd_w(); break; - case TM_TRACK: do_track_w(); break; - case TM_SECTOR: do_sector_w(); break; - } +TIMER_CALLBACK_MEMBER(wd_fdc_device_base::track_w_tick) +{ + LOGEVENT("Event fired for TM_TRACK\n"); + live_sync(); + do_track_w(); + general_continue(); +} +TIMER_CALLBACK_MEMBER(wd_fdc_device_base::sector_w_tick) +{ + LOGEVENT("Event fired for TM_SECTOR\n"); + live_sync(); + do_sector_w(); general_continue(); } @@ -336,11 +351,12 @@ void wd_fdc_device_base::command_end() main_state = sub_state = IDLE; motor_timeout = 0; - if(!drq && (status & S_BUSY)) { - status &= ~S_BUSY; + if(status & S_BUSY) { + if (!t_cmd->enabled()) { + status &= ~S_BUSY; + } intrq = true; - if(!intrq_cb.isnull()) - intrq_cb(intrq); + intrq_cb(intrq); } } @@ -542,7 +558,6 @@ void wd_fdc_device_base::read_sector_start() main_state = READ_SECTOR; status &= ~(S_CRC|S_LOST|S_RNF|S_WP|S_DDM); - drop_drq(); update_sso(); set_hld(); sub_state = motor_control ? SPINUP : SPINUP_DONE; @@ -646,7 +661,6 @@ void wd_fdc_device_base::read_track_start() main_state = READ_TRACK; status &= ~(S_LOST|S_RNF); - drop_drq(); update_sso(); set_hld(); sub_state = motor_control ? SPINUP : SPINUP_DONE; @@ -725,7 +739,6 @@ void wd_fdc_device_base::read_id_start() main_state = READ_ID; status &= ~(S_WP|S_DDM|S_LOST|S_RNF); - drop_drq(); update_sso(); set_hld(); sub_state = motor_control ? SPINUP : SPINUP_DONE; @@ -802,7 +815,6 @@ void wd_fdc_device_base::write_track_start() main_state = WRITE_TRACK; status &= ~(S_WP|S_DDM|S_LOST|S_RNF); - drop_drq(); update_sso(); set_hld(); sub_state = motor_control ? SPINUP : SPINUP_DONE; @@ -851,8 +863,8 @@ void wd_fdc_device_base::write_track_continue() LOGSTATE("SETTLE_DONE\n"); if (floppy && floppy->wpt_r()) { LOGSTATE("WRITE_PROT\n"); - status |= S_WP; - command_end(); + sub_state = WRITE_PROTECT_WAIT; + delay_cycles(t_gen, 145); return; } set_drq(); @@ -860,6 +872,16 @@ void wd_fdc_device_base::write_track_continue() delay_cycles(t_gen, 192); return; + case WRITE_PROTECT_WAIT: + LOGSTATE("WRITE_PROTECT_WAIT\n"); + return; + + case WRITE_PROTECT_DONE: + LOGSTATE("WRITE_PROTECT_DONE\n"); + status |= S_WP; + command_end(); + return; + case DATA_LOAD_WAIT: LOGSTATE("DATA_LOAD_WAIT\n"); return; @@ -891,9 +913,9 @@ void wd_fdc_device_base::write_track_continue() if(format_last_byte_count) { char buf[32]; if(format_last_byte_count > 1) - sprintf(buf, "%dx%02x", format_last_byte_count, format_last_byte); + snprintf(buf, 32, "%dx%02x", format_last_byte_count, format_last_byte); else - sprintf(buf, "%02x", format_last_byte); + snprintf(buf, 32, "%02x", format_last_byte); format_description_string += buf; } LOGDESC("track description %s\n", format_description_string.c_str()); @@ -919,7 +941,6 @@ void wd_fdc_device_base::write_sector_start() main_state = WRITE_SECTOR; status &= ~(S_CRC|S_LOST|S_RNF|S_WP|S_DDM); - drop_drq(); update_sso(); set_hld(); sub_state = motor_control ? SPINUP : SPINUP_DONE; @@ -963,8 +984,8 @@ void wd_fdc_device_base::write_sector_continue() LOGSTATE("SETTLE_DONE\n"); if (floppy && floppy->wpt_r()) { LOGSTATE("WRITE_PROT\n"); - status |= S_WP; - command_end(); + sub_state = WRITE_PROTECT_WAIT; + delay_cycles(t_gen, 145); return; } sub_state = SCAN_ID; @@ -972,6 +993,16 @@ void wd_fdc_device_base::write_sector_continue() live_start(SEARCH_ADDRESS_MARK_HEADER); return; + case WRITE_PROTECT_WAIT: + LOGSTATE("WRITE_PROTECT_WAIT\n"); + return; + + case WRITE_PROTECT_DONE: + LOGSTATE("WRITE_PROTECT_DONE\n"); + status |= S_WP; + command_end(); + return; + case SCAN_ID: LOGSTATE("SCAN_ID\n"); if(!sector_matches()) { @@ -1037,20 +1068,19 @@ 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 // currently running command, return the status type 1 bits status_type_1 = true; + drop_drq(); } intrq_cond = command & 0x0f; if(!intrq && (command & I_IMM)) { intrq = true; - if(!intrq_cb.isnull()) - intrq_cb(intrq); + intrq_cb(intrq); } if(spinup_on_interrupt) { // see notes in FD1771 and WD1772 constructors, might be true for other FDC types as well. @@ -1121,6 +1151,10 @@ void wd_fdc_device_base::do_generic() sub_state = SETTLE_DONE; break; + case WRITE_PROTECT_WAIT: + sub_state = WRITE_PROTECT_DONE; + break; + case SEEK_WAIT_STEP_TIME: sub_state = SEEK_WAIT_STEP_TIME_DONE; break; @@ -1212,7 +1246,7 @@ void wd_fdc_device_base::do_cmd_w() void wd_fdc_device_base::cmd_w(uint8_t val) { - if (inverted_bus) val ^= 0xff; + val ^= bus_invert_value; if (!mr) { logerror("Not initiating command %02x during master reset\n", val); return; @@ -1230,8 +1264,7 @@ void wd_fdc_device_base::cmd_w(uint8_t val) // No other logic present in real chips, descriptions of "Forced interrupt" (Dx) command in datasheets are wrong. if (intrq) { intrq = false; - if(!intrq_cb.isnull()) - intrq_cb(intrq); + intrq_cb(intrq); } // No more than one write in flight, but interrupts take priority @@ -1248,6 +1281,7 @@ void wd_fdc_device_base::cmd_w(uint8_t val) else { intrq_cond = 0; + drop_drq(); // set busy, then set a timer to process the command status |= S_BUSY; delay_cycles(t_cmd, dden ? delay_command_commit*2 : delay_command_commit); @@ -1258,8 +1292,7 @@ uint8_t wd_fdc_device_base::status_r() { if(intrq && !(intrq_cond & I_IMM) && !machine().side_effects_disabled()) { intrq = false; - if(!intrq_cb.isnull()) - intrq_cb(intrq); + intrq_cb(intrq); } if(status_type_1) { @@ -1299,8 +1332,7 @@ uint8_t wd_fdc_device_base::status_r() status &= ~S_NRDY; } - uint8_t val = status; - if (inverted_bus) val ^= 0xff; + uint8_t val = status ^ bus_invert_value; LOGCOMP("Status value: %02X\n",val); @@ -1315,22 +1347,17 @@ void wd_fdc_device_base::do_track_w() void wd_fdc_device_base::track_w(uint8_t val) { - if (inverted_bus) val ^= 0xff; - // No more than one write in flight if(track_buffer != -1 || !mr) return; - track_buffer = val; + track_buffer = val ^ bus_invert_value; delay_cycles(t_track, dden ? delay_register_commit*2 : delay_register_commit); } uint8_t wd_fdc_device_base::track_r() { - uint8_t val = track; - if (inverted_bus) val ^= 0xff; - - return val; + return track ^ bus_invert_value; } void wd_fdc_device_base::do_sector_w() @@ -1343,15 +1370,13 @@ void wd_fdc_device_base::sector_w(uint8_t val) { if (!mr) return; - if (inverted_bus) val ^= 0xff; - // No more than one write in flight // C1581 accesses this register with an INC opcode, // i.e. write old value, write new value, and the new value gets ignored by this //if(sector_buffer != -1) // return; - sector_buffer = val; + sector_buffer = val ^ bus_invert_value; // set a timer to write the new value to the register, but only if we aren't in // the middle of an already occurring update @@ -1361,31 +1386,27 @@ void wd_fdc_device_base::sector_w(uint8_t val) uint8_t wd_fdc_device_base::sector_r() { - uint8_t val = sector; - if (inverted_bus) val ^= 0xff; - - return val; + return sector ^ bus_invert_value; } void wd_fdc_device_base::data_w(uint8_t val) { if (!mr) return; - if (inverted_bus) val ^= 0xff; - - data = val; + data = val ^ bus_invert_value; + LOGDATA("%s: Write %02X to data register (DRQ=%d)\n", machine().describe_context(), data, drq); drop_drq(); } uint8_t wd_fdc_device_base::data_r() { if (!machine().side_effects_disabled()) + { + LOGDATA("%s: Read %02X from data register (DRQ=%d)\n", machine().describe_context(), data, drq); drop_drq(); + } - uint8_t val = data; - if (inverted_bus) val ^= 0xff; - - return val; + return data ^ bus_invert_value; } void wd_fdc_device_base::write(offs_t reg, uint8_t val) @@ -1433,8 +1454,7 @@ void wd_fdc_device_base::spinup() void wd_fdc_device_base::ready_callback(floppy_image_device *floppy, int state) { - if(!ready_cb.isnull()) - ready_cb(state); + ready_cb(state); // why is this even possible? if (!floppy) @@ -1446,8 +1466,7 @@ void wd_fdc_device_base::ready_callback(floppy_image_device *floppy, int state) if(!intrq && (((intrq_cond & I_RDY) && !state) || ((intrq_cond & I_NRDY) && state))) { intrq = true; - if(!intrq_cb.isnull()) - intrq_cb(intrq); + intrq_cb(intrq); } } @@ -1478,8 +1497,7 @@ void wd_fdc_device_base::index_callback(floppy_image_device *floppy, int state) if(!intrq && (intrq_cond & I_IDX)) { intrq = true; - if(!intrq_cb.isnull()) - intrq_cb(intrq); + intrq_cb(intrq); } break; @@ -1498,6 +1516,8 @@ void wd_fdc_device_base::index_callback(floppy_image_device *floppy, int state) case SPINUP_DONE: case SETTLE_WAIT: case SETTLE_DONE: + case WRITE_PROTECT_WAIT: + case WRITE_PROTECT_DONE: case DATA_LOAD_WAIT: case DATA_LOAD_WAIT_DONE: case SEEK_MOVE: @@ -1539,27 +1559,27 @@ void wd_fdc_device_base::index_callback(floppy_image_device *floppy, int state) general_continue(); } -READ_LINE_MEMBER(wd_fdc_device_base::intrq_r) +int wd_fdc_device_base::intrq_r() { return intrq; } -READ_LINE_MEMBER(wd_fdc_device_base::drq_r) +int wd_fdc_device_base::drq_r() { return drq; } -READ_LINE_MEMBER(wd_fdc_device_base::hld_r) +int wd_fdc_device_base::hld_r() { return hld; } -WRITE_LINE_MEMBER(wd_fdc_device_base::hlt_w) +void wd_fdc_device_base::hlt_w(int state) { hlt = bool(state); } -READ_LINE_MEMBER(wd_fdc_device_base::enp_r) +int wd_fdc_device_base::enp_r() { return enp; } @@ -1579,7 +1599,7 @@ void wd_fdc_device_base::live_start(int state) cur_live.data_bit_context = false; cur_live.byte_counter = 0; - if (!enmf_cb.isnull() && has_enmf) + if (!enmf_cb.isunset() && has_enmf) enmf = enmf_cb() ? false : true; pll_reset(dden, enmf, cur_live.tm); @@ -1665,6 +1685,14 @@ bool wd_fdc_device_base::read_one_bit(const attotime &limit) return false; } +void wd_fdc_device_base::reset_data_sync() +{ + cur_live.data_separator_phase = false; + cur_live.bit_counter = 0; + + cur_live.data_reg = cur_live.shift_reg_data(); +} + bool wd_fdc_device_base::write_one_bit(const attotime &limit) { bool bit = cur_live.shift_reg & 0x8000; @@ -1748,28 +1776,19 @@ 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; - cur_live.data_separator_phase = false; - cur_live.bit_counter = 0; + 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; - cur_live.data_separator_phase = false; - cur_live.bit_counter = 0; + reset_data_sync(); if(main_state == READ_ID) cur_live.state = READ_ID_BLOCK_TO_DMA; else @@ -1782,15 +1801,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) @@ -1799,7 +1811,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; } @@ -1870,15 +1882,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) { @@ -1887,10 +1892,9 @@ 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; - cur_live.data_separator_phase = false; - cur_live.bit_counter = 0; + reset_data_sync(); cur_live.state = READ_DATA_BLOCK_HEADER; } } else { @@ -1899,19 +1903,24 @@ 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; - if((cur_live.data_reg & 0xfe) == 0xf8) + reset_data_sync(); + + if(extended_ddam) { + if(!(cur_live.data_reg & 1)) + status |= S_DDM; + if(!(cur_live.data_reg & 2)) + status |= S_DDM << 1; + } else if((cur_live.data_reg & 0xfe) == 0xf8) status |= S_DDM; - cur_live.data_separator_phase = false; - cur_live.bit_counter = 0; cur_live.state = READ_SECTOR_DATA; } } @@ -1922,15 +1931,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) @@ -1939,7 +1941,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; } @@ -2003,14 +2005,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_low<16>() == 0x4489 + || cur_live.shift_reg_low<16>() == 0x5224)) ) break; @@ -2027,8 +2041,7 @@ void wd_fdc_device_base::live_run(attotime limit) // MZ: TI99 "DISkASSEMBLER" copy protection requires a threshold of 8 bool output_byte = cur_live.bit_counter > 8; - cur_live.data_separator_phase = false; - cur_live.bit_counter = 0; + reset_data_sync(); if(output_byte) { live_delay(READ_TRACK_DATA_BYTE); @@ -2054,9 +2067,9 @@ void wd_fdc_device_base::live_run(attotime limit) if(format_last_byte_count) { char buf[32]; if(format_last_byte_count > 1) - sprintf(buf, "%dx%02x ", format_last_byte_count, format_last_byte); + snprintf(buf, 32, "%dx%02x ", format_last_byte_count, format_last_byte); else - sprintf(buf, "%02x ", format_last_byte); + snprintf(buf, 32, "%02x ", format_last_byte); format_description_string += buf; } format_last_byte = data; @@ -2177,7 +2190,11 @@ void wd_fdc_device_base::live_run(attotime limit) live_write_fm(0x00); else if(cur_live.byte_counter < 7) { cur_live.crc = 0xffff; - live_write_raw(command & 1 ? 0xf56a : 0xf56f); + if(extended_ddam) { + static const uint16_t dam[4] = { 0xf56f, 0xf56e, 0xf56b, 0xf56a }; + live_write_raw(dam[command & 3]); + } else + live_write_raw(command & 1 ? 0xf56a : 0xf56f); } else if(cur_live.byte_counter < sector_size + 7-1) { if(drq) { status |= S_LOST; @@ -2323,13 +2340,9 @@ 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()) - drq_cb(true); + drq_cb(true); } } @@ -2337,14 +2350,7 @@ void wd_fdc_device_base::drop_drq() { if(drq) { drq = false; - if(!drq_cb.isnull()) - drq_cb(false); - if(main_state == IDLE && (status & S_BUSY)) { - status &= ~S_BUSY; - intrq = true; - if(!intrq_cb.isnull()) - intrq_cb(intrq); - } + drq_cb(false); } } @@ -2354,8 +2360,7 @@ void wd_fdc_device_base::set_hld() hld = true; int temp = sub_state; sub_state = DUMMY; - if(!hld_cb.isnull()) - hld_cb(hld); + hld_cb(hld); sub_state = temp; } } @@ -2366,8 +2371,7 @@ void wd_fdc_device_base::drop_hld() hld = false; int temp = sub_state; sub_state = DUMMY; - if(!hld_cb.isnull()) - hld_cb(hld); + hld_cb(hld); sub_state = temp; } } @@ -2384,7 +2388,7 @@ void wd_fdc_device_base::update_sso() // If a SSO callback is defined then it is assumed that this callback // will update the floppy side if that is the connection. There are // some machines that use the SSO output for other purposes. - if(!sso_cb.isnull()) { + if(!sso_cb.isunset()) { sso_cb(side); return; } @@ -2676,7 +2680,7 @@ fd1771_device::fd1771_device(const machine_config &mconfig, const char *tag, dev delay_register_commit = 16/2; // will became x2 later due to FM delay_command_commit = 20/2; // same as above disable_mfm = true; - inverted_bus = true; + bus_invert_value = 0xff; side_control = false; side_compare = false; head_control = true; @@ -2684,6 +2688,7 @@ fd1771_device::fd1771_device(const machine_config &mconfig, const char *tag, dev motor_control = false; ready_hooked = true; spinup_on_interrupt = true; // ZX-Spectrum Beta-disk V2 require this, or ReadSector command should set HLD before RDY check + extended_ddam = true; } int fd1771_device::calc_sector_size(uint8_t size, uint8_t command) const @@ -2702,7 +2707,7 @@ fd1781_device::fd1781_device(const machine_config &mconfig, const char *tag, dev delay_register_commit = 16; delay_command_commit = 12; disable_mfm = false; - inverted_bus = true; + bus_invert_value = 0xff; side_control = false; side_compare = false; head_control = true; @@ -2729,7 +2734,7 @@ fd1791_device::fd1791_device(const machine_config &mconfig, const char *tag, dev delay_command_commit = 12; disable_mfm = false; has_enmf = false; - inverted_bus = true; + bus_invert_value = 0xff; side_control = false; side_compare = true; head_control = true; @@ -2745,7 +2750,7 @@ fd1792_device::fd1792_device(const machine_config &mconfig, const char *tag, dev delay_command_commit = 12; disable_mfm = true; has_enmf = false; - inverted_bus = true; + bus_invert_value = 0xff; side_control = false; side_compare = true; head_control = true; @@ -2761,7 +2766,7 @@ fd1793_device::fd1793_device(const machine_config &mconfig, const char *tag, dev delay_command_commit = 12; disable_mfm = false; has_enmf = false; - inverted_bus = false; + bus_invert_value = 0x00; side_control = false; side_compare = true; head_control = true; @@ -2777,7 +2782,7 @@ kr1818vg93_device::kr1818vg93_device(const machine_config &mconfig, const char * delay_command_commit = 12; disable_mfm = false; has_enmf = false; - inverted_bus = false; + bus_invert_value = 0x00; side_control = false; side_compare = true; head_control = true; @@ -2793,7 +2798,7 @@ fd1794_device::fd1794_device(const machine_config &mconfig, const char *tag, dev delay_command_commit = 12; disable_mfm = true; has_enmf = false; - inverted_bus = false; + bus_invert_value = 0x00; side_control = false; side_compare = true; head_control = true; @@ -2809,7 +2814,7 @@ fd1795_device::fd1795_device(const machine_config &mconfig, const char *tag, dev delay_command_commit = 12; disable_mfm = false; has_enmf = false; - inverted_bus = true; + bus_invert_value = 0xff; side_control = true; side_compare = false; head_control = true; @@ -2833,7 +2838,7 @@ fd1797_device::fd1797_device(const machine_config &mconfig, const char *tag, dev delay_command_commit = 12; disable_mfm = false; has_enmf = false; - inverted_bus = false; + bus_invert_value = 0x00; side_control = true; side_compare = false; head_control = true; @@ -2857,7 +2862,7 @@ mb8866_device::mb8866_device(const machine_config &mconfig, const char *tag, dev delay_command_commit = 12; disable_mfm = false; has_enmf = false; - inverted_bus = true; + bus_invert_value = 0xff; side_control = false; side_compare = true; head_control = true; @@ -2873,7 +2878,7 @@ mb8876_device::mb8876_device(const machine_config &mconfig, const char *tag, dev delay_command_commit = 12; disable_mfm = false; has_enmf = false; - inverted_bus = true; + bus_invert_value = 0xff; side_control = false; side_compare = true; head_control = true; @@ -2889,7 +2894,7 @@ mb8877_device::mb8877_device(const machine_config &mconfig, const char *tag, dev delay_command_commit = 12; disable_mfm = false; has_enmf = false; - inverted_bus = false; + bus_invert_value = 0x00; side_control = false; side_compare = true; head_control = true; @@ -2905,7 +2910,7 @@ fd1761_device::fd1761_device(const machine_config &mconfig, const char *tag, dev delay_command_commit = 12; disable_mfm = false; has_enmf = false; - inverted_bus = true; + bus_invert_value = 0xff; side_control = false; side_compare = true; head_control = true; @@ -2921,7 +2926,7 @@ fd1763_device::fd1763_device(const machine_config &mconfig, const char *tag, dev delay_command_commit = 12; disable_mfm = false; has_enmf = false; - inverted_bus = false; + bus_invert_value = 0x00; side_control = false; side_compare = true; head_control = true; @@ -2937,7 +2942,7 @@ fd1765_device::fd1765_device(const machine_config &mconfig, const char *tag, dev delay_command_commit = 12; disable_mfm = false; has_enmf = false; - inverted_bus = true; + bus_invert_value = 0xff; side_control = true; side_compare = false; head_control = true; @@ -2961,7 +2966,7 @@ fd1767_device::fd1767_device(const machine_config &mconfig, const char *tag, dev delay_command_commit = 12; disable_mfm = false; has_enmf = false; - inverted_bus = false; + bus_invert_value = 0x00; side_control = true; side_compare = false; head_control = true; @@ -2985,7 +2990,7 @@ wd2791_device::wd2791_device(const machine_config &mconfig, const char *tag, dev delay_command_commit = 12; disable_mfm = false; has_enmf = true; - inverted_bus = true; + bus_invert_value = 0xff; side_control = false; side_compare = true; head_control = true; @@ -3002,7 +3007,7 @@ wd2793_device::wd2793_device(const machine_config &mconfig, const char *tag, dev delay_command_commit = 12; disable_mfm = false; has_enmf = true; - inverted_bus = false; + bus_invert_value = 0x00; side_control = false; side_compare = true; head_control = true; @@ -3018,7 +3023,7 @@ wd2795_device::wd2795_device(const machine_config &mconfig, const char *tag, dev delay_command_commit = 12; disable_mfm = false; has_enmf = false; - inverted_bus = true; + bus_invert_value = 0xff; side_control = true; side_compare = false; head_control = true; @@ -3042,7 +3047,7 @@ wd2797_device::wd2797_device(const machine_config &mconfig, const char *tag, dev delay_command_commit = 12; disable_mfm = false; has_enmf = false; - inverted_bus = false; + bus_invert_value = 0x00; side_control = true; side_compare = false; head_control = true; @@ -3066,7 +3071,7 @@ wd1770_device::wd1770_device(const machine_config &mconfig, const char *tag, dev delay_command_commit = 36; // official 48 is too high for oric jasmin boot disable_mfm = false; has_enmf = false; - inverted_bus = false; + bus_invert_value = 0x00; side_control = false; side_compare = false; head_control = false; @@ -3084,7 +3089,7 @@ wd1772_device::wd1772_device(const machine_config &mconfig, const char *tag, dev delay_command_commit = 48; disable_mfm = false; has_enmf = false; - inverted_bus = false; + bus_invert_value = 0x00; side_control = false; side_compare = false; head_control = false; @@ -3110,7 +3115,7 @@ wd1773_device::wd1773_device(const machine_config &mconfig, const char *tag, dev delay_command_commit = 48; disable_mfm = false; has_enmf = false; - inverted_bus = false; + bus_invert_value = 0x00; side_control = false; side_compare = true; head_control = false; |