TD0 and IMD images of DMF media are now loaded with the correct sector interleave;

Fixed several bugs in TD0 and IMD loading;
Added FDC READ DELETED DATA, WRITE DELETED DATA, and VERIFY commands;
Mismatching data address marks are now handled correctly.
This commit is contained in:
OBattler
2016-10-05 00:47:50 +02:00
parent 8f9bbb3679
commit 64d9cdc665
7 changed files with 298 additions and 26 deletions

View File

@@ -148,6 +148,7 @@ int null_format_conditions(int drive);
void d86f_unregister(int drive);
void d86f_reset_index_hole_pos(int drive, int side);
uint8_t dmf_r[21];
uint8_t xdf_physical_sectors[2][2];
uint8_t xdf_gap3_sizes[2][2];
uint16_t xdf_trackx_spos[2][8];
@@ -168,3 +169,5 @@ xdf_sector_t xdf_img_layout[2][2][46];
xdf_sector_t xdf_disk_layout[2][2][38];
uint32_t td0_get_raw_tsize(int side_flags, int slower_rpm);
void d86f_set_track_pos(int drive, uint32_t track_pos);

View File

@@ -290,6 +290,11 @@ void d86f_register_86f(int drive)
d86f_handler[drive].check_crc = 1;
}
void d86f_set_track_pos(int drive, uint32_t track_pos)
{
d86f[drive].track_pos = track_pos;
}
/* Needed for formatting! */
int d86f_is_40_track(int drive)
{
@@ -2099,8 +2104,10 @@ void d86f_poll_find_nf(int drive, int side)
{
uint8_t mfm = 0;
uint8_t am_len = 0;
uint8_t requested_am = 0;
mfm = fdc_is_mfm();
am_len = mfm ? 4 : 1;
requested_am = fdc_is_deleted() ? 0xF8 : 0xFB;
if (d86f[drive].track_index)
{
@@ -2137,7 +2144,19 @@ void d86f_poll_find_nf(int drive, int side)
{
if ((d86f[drive].state == STATE_WRITE_FIND_SECTOR) && (d86f[drive].data_am_counter == (am_len - 1)))
{
d86f_poll_write(drive, side, 0xFB, BYTE_DATAAM);
d86f_poll_write(drive, side, fdc_is_deleted() ? 0xF8 : 0xFB, BYTE_DATAAM);
}
else if ((d86f[drive].state != STATE_WRITE_FIND_SECTOR) && (d86f[drive].data_am_counter == (am_len - 1)))
{
if (d86f[drive].track_data_byte != requested_am)
{
fdc_set_wrong_am();
if (fdc_is_sk())
{
/* Read command in skip mode, invalidate the data AM counter in order to ignore the sector. */
d86f[drive].data_am_counter = 0;
}
}
}
d86f[drive].data_am_counter++;
@@ -2162,6 +2181,7 @@ void d86f_poll_find_nf(int drive, int side)
}
break;
case BYTE_ID_CRC:
pclog("Last sector: %08X\n", d86f[drive].last_sector.dword);
d86f[drive].id_pos = d86f_get_pos(drive);
d86f[drive].track_crc.bytes[d86f[drive].id_pos ^ 1] = d86f[drive].track_data_byte;
break;
@@ -2251,6 +2271,7 @@ void d86f_poll_find_nf(int drive, int side)
Therefore, ensuring the data address mark acounter is at a correct length is all we need to do. */
if (d86f[drive].data_am_counter == am_len)
{
pclog("Changing state...\n");
d86f[drive].state++;
}
/* Data address mark counter always reset to 0. */
@@ -2508,6 +2529,8 @@ void d86f_poll_read_id(int drive, int side)
void d86f_poll_find_am_fm(int drive, int side)
{
uint16_t requested_am = fdc_is_deleted() ? 0x6AF5 : 0x6FF5;
switch (d86f[drive].track_data_word)
{
case 0x7EF5: /* ID address mark */
@@ -2527,7 +2550,21 @@ void d86f_poll_find_am_fm(int drive, int side)
d86f[drive].calc_crc.word = 0xffff;
if (d86f[drive].state == STATE_WRITE_FIND_SECTOR)
{
d86f_write_byte_direct(drive, side, 0xFB);
d86f_write_byte_direct(drive, side, fdc_is_deleted() ? 0xF8 : 0xFB);
}
else
{
if (d86f[drive].track_data_word != requested_am)
{
fdc_set_wrong_am();
if (fdc_is_sk())
{
d86f[drive].datac = 0;
d86f_poll_advancebyte(drive, side);
d86f[drive].id_was_read = 0; /* Invalidate ID was read flag to avoid false positives after read. */
return;
}
}
}
d86f_calccrc(drive, d86f[drive].track_data_byte);
d86f[drive].datac = 0;
@@ -2539,6 +2576,7 @@ void d86f_poll_find_am_fm(int drive, int side)
case STATE_READ_FIND_NEXT_SECTOR:
d86f[drive].state++;
d86f_poll_advancebyte(drive, side);
d86f[drive].id_was_read = 0; /* Invalidate ID was read flag to avoid false positives after read. */
return;
}
}
@@ -2554,6 +2592,8 @@ void d86f_poll_find_am_fm(int drive, int side)
void d86f_poll_find_am_mfm(int drive, int side)
{
uint16_t requested_am = fdc_is_deleted() ? 0x4A55 : 0x4555;
switch (d86f[drive].track_data_word)
{
case 0x8944:
@@ -2580,7 +2620,21 @@ void d86f_poll_find_am_mfm(int drive, int side)
d86f[drive].id_match = 0; /* Invalidate ID match to avoid false positives after read. */
if (d86f[drive].state == STATE_WRITE_FIND_SECTOR)
{
d86f_write_byte_direct(drive, side, 0xFB);
d86f_write_byte_direct(drive, side, fdc_is_deleted() ? 0xF8 : 0xFB);
}
else
{
if (d86f[drive].track_data_word != requested_am)
{
fdc_set_wrong_am();
if (fdc_is_sk())
{
d86f[drive].datac = 0;
d86f_poll_advancebyte(drive, side);
d86f[drive].id_was_read = 0; /* Invalidate ID was read flag to avoid false positives after read. */
return;
}
}
}
d86f_calccrc(drive, d86f[drive].track_data_byte);
d86f[drive].datac = 0;
@@ -2593,6 +2647,7 @@ void d86f_poll_find_am_mfm(int drive, int side)
// pclog("Advancing state (%04X)...\n", d86f[drive].calc_crc);
d86f[drive].state++;
d86f_poll_advancebyte(drive, side);
d86f[drive].id_was_read = 0; /* Invalidate ID was read flag to avoid false positives after read. */
return;
}
}

View File

@@ -36,6 +36,7 @@ static struct
imd_track_t tracks[256][2];
uint16_t current_side_flags[2];
uint8_t xdf_ordered_pos[256][2];
uint8_t interleave_ordered_pos[256][2];
uint8_t *current_data[2];
uint8_t track_buffer[2][25000];
} imd[2];
@@ -70,7 +71,8 @@ void imd_load(int drive, char *fn)
uint32_t track_total = 0;
uint32_t raw_tsize = 0;
uint32_t minimum_gap3 = 0;
uint32_t minimum_gap4 = 12;
// uint32_t minimum_gap4 = 12;
uint32_t minimum_gap4 = 0;
d86f_unregister(drive);
@@ -161,6 +163,7 @@ void imd_load(int drive, char *fn)
if ((track_spt == 16) && (sector_size == 2)) imd[drive].tracks[track][side].side_flags |= 0x20;
if ((track_spt == 17) && (sector_size == 2)) imd[drive].tracks[track][side].side_flags |= 0x20;
if ((track_spt == 8) && (sector_size == 3)) imd[drive].tracks[track][side].side_flags |= 0x20;
if ((imd[drive].tracks[track][side].side_flags & 7) == 1) imd[drive].tracks[track][side].side_flags |= 0x20;
imd[drive].tracks[track][side].is_present = 1;
imd[drive].tracks[track][side].file_offs = (buffer2 - buffer);
memcpy(imd[drive].tracks[track][side].params, buffer2, 5);
@@ -229,15 +232,18 @@ void imd_load(int drive, char *fn)
}
buffer2 = buffer + last_offset;
/* Leaving even GAP4: 80 : 40 */
/* Leaving only GAP1: 96 : 47 */
/* Not leaving even GAP1: 146 : 73 */
raw_tsize = td0_get_raw_tsize(imd[drive].tracks[track][side].side_flags, 0);
minimum_gap3 = 12 * track_spt;
if ((raw_tsize - track_total) < (minimum_gap3 + minimum_gap4))
if ((raw_tsize - track_total + (mfm ? 146 : 73)) < (minimum_gap3 + minimum_gap4))
{
/* If we can't fit the sectors with a reasonable minimum gap at perfect RPM, let's try 2% slower. */
raw_tsize = td0_get_raw_tsize(imd[drive].tracks[track][side].side_flags, 1);
/* Set disk flags so that rotation speed is 2% slower. */
imd[drive].disk_flags |= (3 << 5);
if ((raw_tsize - track_total) < (minimum_gap3 + minimum_gap4))
if ((raw_tsize - track_total + (mfm ? 146 : 73)) < (minimum_gap3 + minimum_gap4))
{
/* If we can't fit the sectors with a reasonable minimum gap even at 2% slower RPM, abort. */
pclog("IMD: Unable to fit the %i sectors in a track\n", track_spt);
@@ -245,7 +251,7 @@ void imd_load(int drive, char *fn)
return;
}
}
imd[drive].tracks[track][side].gap3_len = (raw_tsize - track_total - minimum_gap4) / track_spt;
imd[drive].tracks[track][side].gap3_len = (raw_tsize - track_total - minimum_gap4 + (mfm ? 146 : 73)) / track_spt;
imd[drive].track_count++;
@@ -295,7 +301,10 @@ int imd_track_is_xdf(int drive, int side, int track)
effective_sectors = xdf_sectors = high_sectors = low_sectors = 0;
memset(imd[drive].xdf_ordered_pos[side], 0, 256);
for (i = 0; i < 256; i++)
{
imd[drive].xdf_ordered_pos[i][side] = 0;
}
if (imd[drive].tracks[track][side].params[2] & 0xC0)
{
@@ -384,6 +393,52 @@ int imd_track_is_xdf(int drive, int side, int track)
}
}
int imd_track_is_interleave(int drive, int side, int track)
{
int i, effective_sectors;
uint8_t *r_map;
int track_spt;
effective_sectors = 0;
for (i = 0; i < 256; i++)
{
imd[drive].interleave_ordered_pos[i][side] = 0;
}
track_spt = imd[drive].tracks[track][side].params[3];
r_map = imd[drive].buffer + imd[drive].tracks[track][side].r_map_offs;
if (imd[drive].tracks[track][side].params[2] & 0xC0)
{
return 0;
}
if (track_spt != 21)
{
return 0;
}
if (imd[drive].tracks[track][side].params[4] != 2)
{
return 0;
}
for (i = 0; i < track_spt; i++)
{
if ((r_map[i] >= 1) && (r_map[i] <= track_spt))
{
effective_sectors++;
imd[drive].interleave_ordered_pos[r_map[i]][side] = i;
}
}
if (effective_sectors == track_spt)
{
return 1;
}
return 0;
}
void imd_sector_to_buffer(int drive, int track, int side, uint8_t *buffer, int sector, int len)
{
int i = 0;
@@ -426,6 +481,7 @@ void imd_seek(int drive, int track)
int track_gap3 = 12;
int xdf_type = 0;
int interleave_type = 0;
int is_trackx = 0;
@@ -434,6 +490,9 @@ void imd_seek(int drive, int track)
int ordered_pos = 0;
int real_sector = 0;
int actual_sector = 0;
uint8_t *c_map;
uint8_t *h_map;
uint8_t *r_map;
@@ -456,6 +515,8 @@ void imd_seek(int drive, int track)
imd[drive].current_side_flags[0] = imd[drive].tracks[track][0].side_flags;
imd[drive].current_side_flags[1] = imd[drive].tracks[track][1].side_flags;
// pclog("IMD Seek: %02X %02X (%02X)\n", imd[drive].current_side_flags[0], imd[drive].current_side_flags[1], imd[drive].disk_flags);
d86f_reset_index_hole_pos(drive, 0);
d86f_reset_index_hole_pos(drive, 1);
@@ -463,6 +524,7 @@ void imd_seek(int drive, int track)
{
track_rate = imd[drive].current_side_flags[side] & 7;
if (!track_rate && (imd[drive].current_side_flags[side] & 0x20)) track_rate = 4;
if ((imd[drive].current_side_flags[side] & 27) == 0x21) track_rate = 2;
r_map = imd[drive].buffer + imd[drive].tracks[track][side].r_map_offs;
h = imd[drive].tracks[track][side].params[2];
@@ -495,26 +557,38 @@ void imd_seek(int drive, int track)
xdf_type = imd_track_is_xdf(drive, side, track);
interleave_type = imd_track_is_interleave(drive, side, track);
current_pos = d86f_prepare_pretrack(drive, side, 0, 1);
if (!xdf_type)
{
for (sector = 0; sector < imd[drive].tracks[track][side].params[3]; sector++)
{
id[0] = (h & 0x80) ? c_map[sector] : c;
id[1] = (h & 0x40) ? h_map[sector] : (h & 1);
id[2] = r_map[sector];
id[3] = (n == 0xFF) ? n_map[sector] : n;
if (interleave_type == 0)
{
real_sector = r_map[sector];
actual_sector = sector;
}
else
{
real_sector = dmf_r[sector];
actual_sector = imd[drive].interleave_ordered_pos[real_sector][side];
}
id[0] = (h & 0x80) ? c_map[actual_sector] : c;
id[1] = (h & 0x40) ? h_map[actual_sector] : (h & 1);
id[2] = real_sector;
id[3] = (n == 0xFF) ? n_map[actual_sector] : n;
ssize = 128 << ((uint32_t) id[3]);
data = imd[drive].track_buffer[side] + track_buf_pos[side];
type = imd[drive].buffer[imd[drive].tracks[track][side].sector_data_offs[sector]];
type = imd[drive].buffer[imd[drive].tracks[track][side].sector_data_offs[actual_sector]];
type = (type >> 1) & 7;
deleted = bad_crc = 0;
if ((type == 2) || (type == 4)) deleted = 1;
if ((type == 3) || (type == 4)) bad_crc = 1;
// pclog("IMD: (%i %i) %i %i %i %i (%i %i) (GPL=%i)\n", track, side, id[0], id[1], id[2], id[3], deleted, bad_crc, track_gap3);
imd_sector_to_buffer(drive, track, side, data, sector, ssize);
imd_sector_to_buffer(drive, track, side, data, actual_sector, ssize);
current_pos = d86f_prepare_sector(drive, side, current_pos, id, data, ssize, 1, 22, track_gap3, 0, deleted, bad_crc);
track_buf_pos[side] += ssize;
}

View File

@@ -29,7 +29,7 @@ static struct
uint16_t current_sector_pos;
} img[2];
static uint8_t dmf_r[21] = { 12, 2, 13, 3, 14, 4, 15, 5, 16, 6, 17, 7, 18, 8, 19, 9, 20, 10, 21, 11, 1 };
uint8_t dmf_r[21] = { 12, 2, 13, 3, 14, 4, 15, 5, 16, 6, 17, 7, 18, 8, 19, 9, 20, 10, 21, 11, 1 };
static uint8_t xdf_spt[2] = { 6, 8 };
static uint8_t xdf_logical_sectors[2][2] = { { 38, 6 }, { 46, 8 } };
uint8_t xdf_physical_sectors[2][2] = { { 16, 3 }, { 19, 4 } };

View File

@@ -103,6 +103,7 @@ typedef struct
int current_sector_index[2];
uint8_t calculated_gap3_lengths[256][2];
uint8_t xdf_ordered_pos[256][2];
uint8_t interleave_ordered_pos[256][2];
} td0_t;
td0_t td0[2];
@@ -654,7 +655,8 @@ int td0_initialize(int drive)
uint32_t track_size = 0;
uint32_t raw_tsize = 0;
uint32_t minimum_gap3 = 0;
uint32_t minimum_gap4 = 12;
// uint32_t minimum_gap4 = 12;
uint32_t minimum_gap4 = 0;
if (!td0[drive].f)
{
@@ -861,20 +863,20 @@ int td0_initialize(int drive)
raw_tsize = td0_get_raw_tsize(td0[drive].side_flags[track][head], 0);
minimum_gap3 = 12 * track_spt;
if ((raw_tsize - track_size) < (minimum_gap3 + minimum_gap4))
if ((raw_tsize - track_size + (fm ? 73 : 146)) < (minimum_gap3 + minimum_gap4))
{
/* If we can't fit the sectors with a reasonable minimum gap at perfect RPM, let's try 2% slower. */
raw_tsize = td0_get_raw_tsize(td0[drive].side_flags[track][head], 1);
/* Set disk flags so that rotation speed is 2% slower. */
td0[drive].disk_flags |= (3 << 5);
if ((raw_tsize - track_size) < (minimum_gap3 + minimum_gap4))
if ((raw_tsize - track_size + (fm ? 73 : 146)) < (minimum_gap3 + minimum_gap4))
{
/* If we can't fit the sectors with a reasonable minimum gap even at 2% slower RPM, abort. */
pclog("TD0: Unable to fit the %i sectors in a track\n", track_spt);
return 0;
}
}
td0[drive].calculated_gap3_lengths[track][head] = (raw_tsize - track_size - minimum_gap4) / track_spt;
td0[drive].calculated_gap3_lengths[track][head] = (raw_tsize - track_size - minimum_gap4 + (fm ? 73 : 146)) / track_spt;
track_spt = imagebuf[offset];
}
@@ -1008,6 +1010,41 @@ int td0_track_is_xdf(int drive, int side, int track)
}
}
int td0_track_is_interleave(int drive, int side, int track)
{
int i, effective_sectors;
int track_spt;
effective_sectors = 0;
for (i = 0; i < 256; i++)
{
td0[drive].interleave_ordered_pos[i][side] = 0;
}
track_spt = td0[drive].track_spt[track][side];
if (track_spt != 21)
{
return 0;
}
for (i = 0; i < track_spt; i++)
{
if ((td0[drive].sects[track][side][i].track == track) && (td0[drive].sects[track][side][i].head == side) && (td0[drive].sects[track][side][i].sector >= 1) && (td0[drive].sects[track][side][i].sector <= track_spt) && (td0[drive].sects[track][side][i].size == 2))
{
effective_sectors++;
td0[drive].interleave_ordered_pos[td0[drive].sects[track][side][i].sector][side] = i;
}
}
if (effective_sectors == track_spt)
{
return 1;
}
return 0;
}
void td0_seek(int drive, int track)
{
int side;
@@ -1024,6 +1061,7 @@ void td0_seek(int drive, int track)
int track_gap3 = 12;
int xdf_type = 0;
int interleave_type = 0;
int is_trackx = 0;
@@ -1031,6 +1069,9 @@ void td0_seek(int drive, int track)
int xdf_sector = 0;
int ordered_pos = 0;
int real_sector = 0;
int actual_sector = 0;
if (!td0[drive].f)
return;
@@ -1064,19 +1105,31 @@ void td0_seek(int drive, int track)
xdf_type = td0_track_is_xdf(drive, side, track);
interleave_type = td0_track_is_interleave(drive, side, track);
current_pos = d86f_prepare_pretrack(drive, side, 0, 1);
if (!xdf_type)
{
for (sector = 0; sector < td0[drive].track_spt[track][side]; sector++)
{
id[0] = td0[drive].sects[track][side][sector].track;
id[1] = td0[drive].sects[track][side][sector].head;
id[2] = td0[drive].sects[track][side][sector].sector;
id[3] = td0[drive].sects[track][side][sector].size;
// pclog("TD0: %i %i %i %i (%i %i) (GPL=%i)\n", id[0], id[1], id[2], id[3], td0[drive].sects[track][side][sector].deleted, td0[drive].sects[track][side][sector].bad_crc, track_gap3);
ssize = 128 << ((uint32_t) td0[drive].sects[track][side][sector].size);
current_pos = d86f_prepare_sector(drive, side, current_pos, id, td0[drive].sects[track][side][sector].data, ssize, 1, track_gap2, track_gap3, 0, td0[drive].sects[track][side][sector].deleted, td0[drive].sects[track][side][sector].bad_crc);
if (interleave_type == 0)
{
real_sector = td0[drive].sects[track][side][sector].sector;
actual_sector = sector;
}
else
{
real_sector = dmf_r[sector];
actual_sector = td0[drive].interleave_ordered_pos[real_sector][side];
}
id[0] = td0[drive].sects[track][side][actual_sector].track;
id[1] = td0[drive].sects[track][side][actual_sector].head;
id[2] = real_sector;
id[3] = td0[drive].sects[track][side][actual_sector].size;
// pclog("TD0: %i %i %i %i (%i %i) (GPL=%i)\n", id[0], id[1], id[2], id[3], td0[drive].sects[track][side][actual_sector].deleted, td0[drive].sects[track][side][actual_sector].bad_crc, track_gap3);
ssize = 128 << ((uint32_t) td0[drive].sects[track][side][actual_sector].size);
current_pos = d86f_prepare_sector(drive, side, current_pos, id, td0[drive].sects[track][side][actual_sector].data, ssize, 1, track_gap2, track_gap3, 0, td0[drive].sects[track][side][actual_sector].deleted, td0[drive].sects[track][side][actual_sector].bad_crc);
}
}
else

View File

@@ -73,6 +73,11 @@ typedef struct FDC
int max_track;
int mfm;
int deleted;
int wrong_am;
int sc;
} FDC;
static FDC fdc;
@@ -103,6 +108,21 @@ void fdc_reset()
// pclog("Reset FDC\n");
}
int fdc_is_deleted()
{
return fdc.deleted & 1;
}
int fdc_is_sk()
{
return (fdc.deleted & 0x20) ? 1 : 0;
}
void fdc_set_wrong_am()
{
fdc.wrong_am = 1;
}
int fdc_get_drive()
{
return fdc.drive;
@@ -621,6 +641,8 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
break;
case 2: /*Read track*/
fdc.sc=0;
fdc.wrong_am=0;
fdc.pnum=0;
fdc.ptot=8;
fdc.stat=0x90;
@@ -638,6 +660,10 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc.stat=0x90;
break;
case 5: /*Write data*/
case 9: /*Write deleted data*/
fdc.sc=0;
fdc.wrong_am=0;
fdc.deleted = ((fdc.command&0x1F) == 9) ? 1 : 0;
// printf("Write data!\n");
fdc.pnum=0;
fdc.ptot=8;
@@ -647,6 +673,13 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
// readflash=1;
break;
case 6: /*Read data*/
case 0xC: /*Read deleted data*/
case 0x16: /*Verify*/
fdc.sc=0;
fdc.wrong_am=0;
fdc.deleted = ((fdc.command&0x1F) == 0xC) ? 1 : 0;
if ((fdc.command&0x1F) == 0x16) fdc.deleted = 2;
fdc.deleted |= (fdc.command & 0x20);
fdc.pnum=0;
fdc.ptot=8;
fdc.stat=0x90;
@@ -822,6 +855,7 @@ bad_command:
break;
case 5: /*Write data*/
case 9: /*Write deleted data*/
fdc_rate(fdc.drive);
fdc.head=fdc.params[2];
fdd_set_head(fdc.drive, (fdc.params[0] & 4) ? 1 : 0);
@@ -848,7 +882,10 @@ bad_command:
// ioc_fiq(IOC_FIQ_DISC_DATA);
break;
case 0x16: /*Verify*/
if (fdc.params[0] & 0x80) fdc.sc = fdc.params[7];
case 6: /*Read data*/
case 0xC: /*Read deleted data*/
fdc_rate(fdc.drive);
fdc.head=fdc.params[2];
fdd_set_head(fdc.drive, (fdc.params[0] & 4) ? 1 : 0);
@@ -1084,6 +1121,11 @@ void fdc_poll_readwrite_finish()
fdc.stat=0xD0;
fdc.res[4]=(fdd_get_head(fdc.drive ^ fdd_swap)?4:0)|fdc.drive;
fdc.res[5]=fdc.res[6]=0;
if (fdc.wrong_am)
{
fdc.res[6] |= 0x40;
fdc.wrong_am = 0;
}
fdc.res[7]=fdc.rw_track;
fdc.res[8]=fdc.head;
fdc.res[9]=fdc.sector;
@@ -1100,6 +1142,11 @@ void fdc_no_dma_end()
fdc.res[4]=0x40|(fdd_get_head(fdc.drive ^ fdd_swap)?4:0)|fdc.drive;
fdc.res[5]=0x80; /*NDE (No DMA End)*/
fdc.res[6]=0;
if (fdc.wrong_am)
{
fdc.res[6] |= 0x40;
fdc.wrong_am = 0;
}
fdc.res[7]=fdc.rw_track;
fdc.res[8]=fdc.head;
fdc.res[9]=fdc.sector;
@@ -1162,14 +1209,45 @@ void fdc_callback()
disctime = 0;
return;
case 5: /*Write data*/
case 9: /*Write deleted data*/
case 6: /*Read data*/
case 0xC: /*Read deleted data*/
case 0x1C: /*Verify*/
// rpclog("Read data %i\n", fdc.tc);
if ((discint == 6) || (discint == 0xC))
{
if (fdc.wrong_am && !(fdc.deleted & 0x20))
{
/* Mismatching data address mark and no skip, set TC. */
fdc.tc = 1;
}
}
if (fdc.tc)
{
fdc_poll_readwrite_finish();
return;
}
readflash = 1;
if ((discint == 0x16) && (fdc.params[0] & 0x80))
{
/* VERIFY command, EC set */
fdc.sc--;
if (!fdc.sc)
{
fdc_poll_readwrite_finish();
return;
}
/* The rest is processed normally per MT flag and EOT. */
}
else if ((discint == 0x16) && !(fdc.params[0] & 0x80))
{
/* VERIFY command, EC clear */
if ((fdc.sector == fdc.params[5]) && (fdc.head == (fdc.command & 0x80) ? 1 : 0))
{
fdc_poll_readwrite_finish();
return;
}
}
if (fdc.sector == fdc.params[5])
{
/* Reached end of track, MT bit is clear */
@@ -1410,6 +1488,12 @@ void fdc_overrun()
int fdc_data(uint8_t data)
{
if (fdc.deleted & 2)
{
/* We're in a VERIFY command, so return with 0. */
return 0;
}
if (fdc.tc)
return 0;

View File

@@ -31,6 +31,9 @@ void fdc_update_densel_force(int densel_force);
void fdc_update_drvrate(int drive, int drvrate);
void fdc_update_drv2en(int drv2en);
int fdc_is_deleted();
int fdc_is_sk();
void fdc_set_wrong_am();
int fdc_get_drive();
int fdc_get_perp();
int fdc_get_format_n();