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_unregister(int drive);
void d86f_reset_index_hole_pos(int drive, int side); 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_physical_sectors[2][2];
uint8_t xdf_gap3_sizes[2][2]; uint8_t xdf_gap3_sizes[2][2];
uint16_t xdf_trackx_spos[2][8]; 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]; xdf_sector_t xdf_disk_layout[2][2][38];
uint32_t td0_get_raw_tsize(int side_flags, int slower_rpm); 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; 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! */ /* Needed for formatting! */
int d86f_is_40_track(int drive) 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 mfm = 0;
uint8_t am_len = 0; uint8_t am_len = 0;
uint8_t requested_am = 0;
mfm = fdc_is_mfm(); mfm = fdc_is_mfm();
am_len = mfm ? 4 : 1; am_len = mfm ? 4 : 1;
requested_am = fdc_is_deleted() ? 0xF8 : 0xFB;
if (d86f[drive].track_index) 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))) 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++; d86f[drive].data_am_counter++;
@@ -2162,6 +2181,7 @@ void d86f_poll_find_nf(int drive, int side)
} }
break; break;
case BYTE_ID_CRC: case BYTE_ID_CRC:
pclog("Last sector: %08X\n", d86f[drive].last_sector.dword);
d86f[drive].id_pos = d86f_get_pos(drive); d86f[drive].id_pos = d86f_get_pos(drive);
d86f[drive].track_crc.bytes[d86f[drive].id_pos ^ 1] = d86f[drive].track_data_byte; d86f[drive].track_crc.bytes[d86f[drive].id_pos ^ 1] = d86f[drive].track_data_byte;
break; 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. */ 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) if (d86f[drive].data_am_counter == am_len)
{ {
pclog("Changing state...\n");
d86f[drive].state++; d86f[drive].state++;
} }
/* Data address mark counter always reset to 0. */ /* 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) 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) switch (d86f[drive].track_data_word)
{ {
case 0x7EF5: /* ID address mark */ 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; d86f[drive].calc_crc.word = 0xffff;
if (d86f[drive].state == STATE_WRITE_FIND_SECTOR) 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_calccrc(drive, d86f[drive].track_data_byte);
d86f[drive].datac = 0; d86f[drive].datac = 0;
@@ -2539,6 +2576,7 @@ void d86f_poll_find_am_fm(int drive, int side)
case STATE_READ_FIND_NEXT_SECTOR: case STATE_READ_FIND_NEXT_SECTOR:
d86f[drive].state++; d86f[drive].state++;
d86f_poll_advancebyte(drive, side); d86f_poll_advancebyte(drive, side);
d86f[drive].id_was_read = 0; /* Invalidate ID was read flag to avoid false positives after read. */
return; 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) 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) switch (d86f[drive].track_data_word)
{ {
case 0x8944: 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. */ d86f[drive].id_match = 0; /* Invalidate ID match to avoid false positives after read. */
if (d86f[drive].state == STATE_WRITE_FIND_SECTOR) 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_calccrc(drive, d86f[drive].track_data_byte);
d86f[drive].datac = 0; 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); // pclog("Advancing state (%04X)...\n", d86f[drive].calc_crc);
d86f[drive].state++; d86f[drive].state++;
d86f_poll_advancebyte(drive, side); d86f_poll_advancebyte(drive, side);
d86f[drive].id_was_read = 0; /* Invalidate ID was read flag to avoid false positives after read. */
return; return;
} }
} }

View File

@@ -36,6 +36,7 @@ static struct
imd_track_t tracks[256][2]; imd_track_t tracks[256][2];
uint16_t current_side_flags[2]; uint16_t current_side_flags[2];
uint8_t xdf_ordered_pos[256][2]; uint8_t xdf_ordered_pos[256][2];
uint8_t interleave_ordered_pos[256][2];
uint8_t *current_data[2]; uint8_t *current_data[2];
uint8_t track_buffer[2][25000]; uint8_t track_buffer[2][25000];
} imd[2]; } imd[2];
@@ -70,7 +71,8 @@ void imd_load(int drive, char *fn)
uint32_t track_total = 0; uint32_t track_total = 0;
uint32_t raw_tsize = 0; uint32_t raw_tsize = 0;
uint32_t minimum_gap3 = 0; uint32_t minimum_gap3 = 0;
uint32_t minimum_gap4 = 12; // uint32_t minimum_gap4 = 12;
uint32_t minimum_gap4 = 0;
d86f_unregister(drive); 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 == 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 == 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 ((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].is_present = 1;
imd[drive].tracks[track][side].file_offs = (buffer2 - buffer); imd[drive].tracks[track][side].file_offs = (buffer2 - buffer);
memcpy(imd[drive].tracks[track][side].params, buffer2, 5); memcpy(imd[drive].tracks[track][side].params, buffer2, 5);
@@ -229,15 +232,18 @@ void imd_load(int drive, char *fn)
} }
buffer2 = buffer + last_offset; 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); raw_tsize = td0_get_raw_tsize(imd[drive].tracks[track][side].side_flags, 0);
minimum_gap3 = 12 * track_spt; 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. */ /* 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); raw_tsize = td0_get_raw_tsize(imd[drive].tracks[track][side].side_flags, 1);
/* Set disk flags so that rotation speed is 2% slower. */ /* Set disk flags so that rotation speed is 2% slower. */
imd[drive].disk_flags |= (3 << 5); 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. */ /* 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); 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; 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++; 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; 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) 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) void imd_sector_to_buffer(int drive, int track, int side, uint8_t *buffer, int sector, int len)
{ {
int i = 0; int i = 0;
@@ -426,6 +481,7 @@ void imd_seek(int drive, int track)
int track_gap3 = 12; int track_gap3 = 12;
int xdf_type = 0; int xdf_type = 0;
int interleave_type = 0;
int is_trackx = 0; int is_trackx = 0;
@@ -434,6 +490,9 @@ void imd_seek(int drive, int track)
int ordered_pos = 0; int ordered_pos = 0;
int real_sector = 0;
int actual_sector = 0;
uint8_t *c_map; uint8_t *c_map;
uint8_t *h_map; uint8_t *h_map;
uint8_t *r_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[0] = imd[drive].tracks[track][0].side_flags;
imd[drive].current_side_flags[1] = imd[drive].tracks[track][1].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, 0);
d86f_reset_index_hole_pos(drive, 1); 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; track_rate = imd[drive].current_side_flags[side] & 7;
if (!track_rate && (imd[drive].current_side_flags[side] & 0x20)) track_rate = 4; 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; r_map = imd[drive].buffer + imd[drive].tracks[track][side].r_map_offs;
h = imd[drive].tracks[track][side].params[2]; 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); 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); current_pos = d86f_prepare_pretrack(drive, side, 0, 1);
if (!xdf_type) if (!xdf_type)
{ {
for (sector = 0; sector < imd[drive].tracks[track][side].params[3]; sector++) for (sector = 0; sector < imd[drive].tracks[track][side].params[3]; sector++)
{ {
id[0] = (h & 0x80) ? c_map[sector] : c; if (interleave_type == 0)
id[1] = (h & 0x40) ? h_map[sector] : (h & 1); {
id[2] = r_map[sector]; real_sector = r_map[sector];
id[3] = (n == 0xFF) ? n_map[sector] : n; 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]); ssize = 128 << ((uint32_t) id[3]);
data = imd[drive].track_buffer[side] + track_buf_pos[side]; 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; type = (type >> 1) & 7;
deleted = bad_crc = 0; deleted = bad_crc = 0;
if ((type == 2) || (type == 4)) deleted = 1; if ((type == 2) || (type == 4)) deleted = 1;
if ((type == 3) || (type == 4)) bad_crc = 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); // 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); 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; track_buf_pos[side] += ssize;
} }

View File

@@ -29,7 +29,7 @@ static struct
uint16_t current_sector_pos; uint16_t current_sector_pos;
} img[2]; } 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_spt[2] = { 6, 8 };
static uint8_t xdf_logical_sectors[2][2] = { { 38, 6 }, { 46, 8 } }; static uint8_t xdf_logical_sectors[2][2] = { { 38, 6 }, { 46, 8 } };
uint8_t xdf_physical_sectors[2][2] = { { 16, 3 }, { 19, 4 } }; uint8_t xdf_physical_sectors[2][2] = { { 16, 3 }, { 19, 4 } };

View File

@@ -103,6 +103,7 @@ typedef struct
int current_sector_index[2]; int current_sector_index[2];
uint8_t calculated_gap3_lengths[256][2]; uint8_t calculated_gap3_lengths[256][2];
uint8_t xdf_ordered_pos[256][2]; uint8_t xdf_ordered_pos[256][2];
uint8_t interleave_ordered_pos[256][2];
} td0_t; } td0_t;
td0_t td0[2]; td0_t td0[2];
@@ -654,7 +655,8 @@ int td0_initialize(int drive)
uint32_t track_size = 0; uint32_t track_size = 0;
uint32_t raw_tsize = 0; uint32_t raw_tsize = 0;
uint32_t minimum_gap3 = 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) 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); raw_tsize = td0_get_raw_tsize(td0[drive].side_flags[track][head], 0);
minimum_gap3 = 12 * track_spt; 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. */ /* 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); raw_tsize = td0_get_raw_tsize(td0[drive].side_flags[track][head], 1);
/* Set disk flags so that rotation speed is 2% slower. */ /* Set disk flags so that rotation speed is 2% slower. */
td0[drive].disk_flags |= (3 << 5); 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. */ /* 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); pclog("TD0: Unable to fit the %i sectors in a track\n", track_spt);
return 0; 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]; 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) void td0_seek(int drive, int track)
{ {
int side; int side;
@@ -1024,6 +1061,7 @@ void td0_seek(int drive, int track)
int track_gap3 = 12; int track_gap3 = 12;
int xdf_type = 0; int xdf_type = 0;
int interleave_type = 0;
int is_trackx = 0; int is_trackx = 0;
@@ -1032,6 +1070,9 @@ void td0_seek(int drive, int track)
int ordered_pos = 0; int ordered_pos = 0;
int real_sector = 0;
int actual_sector = 0;
if (!td0[drive].f) if (!td0[drive].f)
return; return;
@@ -1064,19 +1105,31 @@ void td0_seek(int drive, int track)
xdf_type = td0_track_is_xdf(drive, side, 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); current_pos = d86f_prepare_pretrack(drive, side, 0, 1);
if (!xdf_type) if (!xdf_type)
{ {
for (sector = 0; sector < td0[drive].track_spt[track][side]; sector++) for (sector = 0; sector < td0[drive].track_spt[track][side]; sector++)
{ {
id[0] = td0[drive].sects[track][side][sector].track; if (interleave_type == 0)
id[1] = td0[drive].sects[track][side][sector].head; {
id[2] = td0[drive].sects[track][side][sector].sector; real_sector = td0[drive].sects[track][side][sector].sector;
id[3] = td0[drive].sects[track][side][sector].size; actual_sector = sector;
// 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); else
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); {
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 else

View File

@@ -73,6 +73,11 @@ typedef struct FDC
int max_track; int max_track;
int mfm; int mfm;
int deleted;
int wrong_am;
int sc;
} FDC; } FDC;
static FDC fdc; static FDC fdc;
@@ -103,6 +108,21 @@ void fdc_reset()
// pclog("Reset FDC\n"); // 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() int fdc_get_drive()
{ {
return fdc.drive; return fdc.drive;
@@ -621,6 +641,8 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
break; break;
case 2: /*Read track*/ case 2: /*Read track*/
fdc.sc=0;
fdc.wrong_am=0;
fdc.pnum=0; fdc.pnum=0;
fdc.ptot=8; fdc.ptot=8;
fdc.stat=0x90; fdc.stat=0x90;
@@ -638,6 +660,10 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
fdc.stat=0x90; fdc.stat=0x90;
break; break;
case 5: /*Write data*/ 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"); // printf("Write data!\n");
fdc.pnum=0; fdc.pnum=0;
fdc.ptot=8; fdc.ptot=8;
@@ -647,6 +673,13 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
// readflash=1; // readflash=1;
break; break;
case 6: /*Read data*/ 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.pnum=0;
fdc.ptot=8; fdc.ptot=8;
fdc.stat=0x90; fdc.stat=0x90;
@@ -822,6 +855,7 @@ bad_command:
break; break;
case 5: /*Write data*/ case 5: /*Write data*/
case 9: /*Write deleted data*/
fdc_rate(fdc.drive); fdc_rate(fdc.drive);
fdc.head=fdc.params[2]; fdc.head=fdc.params[2];
fdd_set_head(fdc.drive, (fdc.params[0] & 4) ? 1 : 0); fdd_set_head(fdc.drive, (fdc.params[0] & 4) ? 1 : 0);
@@ -848,7 +882,10 @@ bad_command:
// ioc_fiq(IOC_FIQ_DISC_DATA); // ioc_fiq(IOC_FIQ_DISC_DATA);
break; break;
case 0x16: /*Verify*/
if (fdc.params[0] & 0x80) fdc.sc = fdc.params[7];
case 6: /*Read data*/ case 6: /*Read data*/
case 0xC: /*Read deleted data*/
fdc_rate(fdc.drive); fdc_rate(fdc.drive);
fdc.head=fdc.params[2]; fdc.head=fdc.params[2];
fdd_set_head(fdc.drive, (fdc.params[0] & 4) ? 1 : 0); fdd_set_head(fdc.drive, (fdc.params[0] & 4) ? 1 : 0);
@@ -1084,6 +1121,11 @@ void fdc_poll_readwrite_finish()
fdc.stat=0xD0; fdc.stat=0xD0;
fdc.res[4]=(fdd_get_head(fdc.drive ^ fdd_swap)?4:0)|fdc.drive; fdc.res[4]=(fdd_get_head(fdc.drive ^ fdd_swap)?4:0)|fdc.drive;
fdc.res[5]=fdc.res[6]=0; 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[7]=fdc.rw_track;
fdc.res[8]=fdc.head; fdc.res[8]=fdc.head;
fdc.res[9]=fdc.sector; 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[4]=0x40|(fdd_get_head(fdc.drive ^ fdd_swap)?4:0)|fdc.drive;
fdc.res[5]=0x80; /*NDE (No DMA End)*/ fdc.res[5]=0x80; /*NDE (No DMA End)*/
fdc.res[6]=0; fdc.res[6]=0;
if (fdc.wrong_am)
{
fdc.res[6] |= 0x40;
fdc.wrong_am = 0;
}
fdc.res[7]=fdc.rw_track; fdc.res[7]=fdc.rw_track;
fdc.res[8]=fdc.head; fdc.res[8]=fdc.head;
fdc.res[9]=fdc.sector; fdc.res[9]=fdc.sector;
@@ -1162,14 +1209,45 @@ void fdc_callback()
disctime = 0; disctime = 0;
return; return;
case 5: /*Write data*/ case 5: /*Write data*/
case 9: /*Write deleted data*/
case 6: /*Read data*/ case 6: /*Read data*/
case 0xC: /*Read deleted data*/
case 0x1C: /*Verify*/
// rpclog("Read data %i\n", fdc.tc); // 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) if (fdc.tc)
{ {
fdc_poll_readwrite_finish(); fdc_poll_readwrite_finish();
return; return;
} }
readflash = 1; 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]) if (fdc.sector == fdc.params[5])
{ {
/* Reached end of track, MT bit is clear */ /* Reached end of track, MT bit is clear */
@@ -1410,6 +1488,12 @@ void fdc_overrun()
int fdc_data(uint8_t data) 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) if (fdc.tc)
return 0; 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_drvrate(int drive, int drvrate);
void fdc_update_drv2en(int drv2en); 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_drive();
int fdc_get_perp(); int fdc_get_perp();
int fdc_get_format_n(); int fdc_get_format_n();