summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/wd_fdc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/wd_fdc.cpp')
-rw-r--r--src/devices/machine/wd_fdc.cpp409
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;