Added support for version 1.10 of the .86F format;

Floppy drive head now set to 0 on drive eject/load;
FDC result phase now returns head from HDSEL.
This commit is contained in:
OBattler
2016-09-05 21:58:28 +02:00
parent 0b1c2c3a6a
commit 23325e16a1
3 changed files with 174 additions and 53 deletions

View File

@@ -106,6 +106,7 @@ void disc_load(int drive, char *fn)
loaders[c].load(drive, fn); loaders[c].load(drive, fn);
drive_empty[drive] = 0; drive_empty[drive] = 0;
strcpy(discfns[drive], fn); strcpy(discfns[drive], fn);
fdd_set_head(drive ^ fdd_swap, 0);
fdd_seek(drive ^ fdd_swap, 0); fdd_seek(drive ^ fdd_swap, 0);
disc_changed[drive] = 1; disc_changed[drive] = 1;
return; return;
@@ -114,6 +115,7 @@ void disc_load(int drive, char *fn)
} }
pclog("Couldn't load %s %s\n",fn,p); pclog("Couldn't load %s %s\n",fn,p);
drive_empty[drive] = 1; drive_empty[drive] = 1;
fdd_set_head(drive ^ fdd_swap, 0);
discfns[drive][0] = 0; discfns[drive][0] = 0;
} }
@@ -122,6 +124,7 @@ void disc_close(int drive)
// pclog("disc_close %i\n", drive); // pclog("disc_close %i\n", drive);
if (loaders[driveloaders[drive]].close) loaders[driveloaders[drive]].close(drive); if (loaders[driveloaders[drive]].close) loaders[driveloaders[drive]].close(drive);
drive_empty[drive] = 1; drive_empty[drive] = 1;
fdd_set_head(drive ^ fdd_swap, 0);
discfns[drive][0] = 0; discfns[drive][0] = 0;
drives[drive].hole = NULL; drives[drive].hole = NULL;
drives[drive].poll = NULL; drives[drive].poll = NULL;

View File

@@ -63,8 +63,8 @@ static struct
{ {
FILE *f; FILE *f;
uint8_t disk_flags; uint8_t disk_flags;
uint8_t track_data[2][25000]; uint8_t track_data[2][50000];
uint8_t track_layout[2][25000]; uint8_t track_layout[2][50000];
uint8_t track_flags; uint8_t track_flags;
uint8_t track_in_file; uint8_t track_in_file;
uint32_t track_offset[256]; uint32_t track_offset[256];
@@ -140,6 +140,63 @@ void d86f_init()
d86f_setupcrc(0x1021, 0xcdb4); d86f_setupcrc(0x1021, 0xcdb4);
} }
int d86f_get_sides(int drive)
{
return (d86f[drive].disk_flags & 8) ? 2 : 1;
}
int d86f_get_side_size(int drive)
{
int pos = 25002;
switch (d86f_hole(drive))
{
case 0:
pos = 15001;
break;
case 1:
pos = 25001;
break;
case 2:
pos = 100001;
break;
}
}
int d86f_get_array_size(int drive)
{
int pos = 25002;
switch (d86f_hole(drive))
{
case 0:
pos = 7500;
break;
case 1:
pos = 12500;
break;
case 2:
pos = 50000;
break;
}
}
int d86f_valid_bit_rate(int drive)
{
int rate = fdc_get_bit_rate();
switch (d86f_hole(drive))
{
case 0: /* DD */
if ((rate < 1) || (rate > 2)) return 0;
return 1;
case 1: /* HD */
if (rate != 0) return 0;
return 1;
case 2: /* ED */
if (rate < 3) return 0;
return 1;
}
return 1;
}
void d86f_load(int drive, char *fn) void d86f_load(int drive, char *fn)
{ {
uint32_t magic = 0; uint32_t magic = 0;
@@ -183,13 +240,17 @@ void d86f_load(int drive, char *fn)
fread(&version, 2, 1, d86f[drive].f); fread(&version, 2, 1, d86f[drive].f);
if (version != 0x0100) if ((version != 0x0100) && (version != 0x010A))
{ {
/* File is not of a recognized format version abort. */ /* File is not of a recognized format version abort. */
pclog("86F: Unrecognized file version: %04X\n", version); pclog("86F: Unrecognized file version: %i.%02i\n", version >> 8, version & 0xFF);
fclose(d86f[drive].f); fclose(d86f[drive].f);
return; return;
} }
else
{
pclog("86F: Recognized file version: %i.%02i\n", version >> 8, version & 0xFF);
}
fread(&(d86f[drive].disk_flags), 1, 1, d86f[drive].f); fread(&(d86f[drive].disk_flags), 1, 1, d86f[drive].f);
@@ -218,8 +279,17 @@ void d86f_load(int drive, char *fn)
} }
/* Load track 0 flags as default. */ /* Load track 0 flags as default. */
fseek(d86f[drive].f, d86f[drive].track_offset[0], SEEK_SET); if (d86f[drive].version == 0x010A)
fread(&(d86f[drive].track_flags), 1, 1, d86f[drive].f); {
fseek(d86f[drive].f, d86f[drive].track_offset[0], SEEK_SET);
fread(&(d86f[drive].side_flags[0]), 1, 1, d86f[drive].f);
fread(&(d86f[drive].side_flags[1]), 1, 1, d86f[drive].f);
}
else
{
fseek(d86f[drive].f, d86f[drive].track_offset[0], SEEK_SET);
fread(&(d86f[drive].track_flags), 1, 1, d86f[drive].f);
}
fseek(d86f[drive].f, 0, SEEK_END); fseek(d86f[drive].f, 0, SEEK_END);
d86f[drive].file_size = ftell(d86f[drive].f); d86f[drive].file_size = ftell(d86f[drive].f);
@@ -243,9 +313,22 @@ int d86f_hole(int drive)
return (d86f[drive].disk_flags >> 1) & 3; return (d86f[drive].disk_flags >> 1) & 3;
} }
uint8_t d86f_flags(int drive)
{
int side = fdd_get_head(drive);
if (d86f[drive].version == 0x010A)
{
return d86f[drive].side_flags[side];
}
else
{
return d86f[drive].track_flags;
}
}
uint8_t d86f_track_flags(int drive) uint8_t d86f_track_flags(int drive)
{ {
uint8_t tf = d86f[drive].track_flags; uint8_t tf = d86f_flags(drive);
uint8_t rr = tf & 0x27; uint8_t rr = tf & 0x27;
uint8_t dr = fdd_get_flags(drive) & 7; uint8_t dr = fdd_get_flags(drive) & 7;
tf &= ~0x27; tf &= ~0x27;
@@ -306,14 +389,9 @@ void d86f_close(int drive)
d86f[drive].f = NULL; d86f[drive].f = NULL;
} }
int d86f_get_sides(int drive)
{
return (d86f[drive].disk_flags & 8) ? 2 : 1;
}
int d86f_is_mfm(int drive) int d86f_is_mfm(int drive)
{ {
return (d86f[drive].track_flags & 8) ? 1 : 0; return (d86f_track_flags(drive) & 8) ? 1 : 0;
} }
uint16_t d86f_get_raw_size(int drive) uint16_t d86f_get_raw_size(int drive)
@@ -350,14 +428,23 @@ void d86f_seek(int drive, int track)
{ {
int sides = d86f_get_sides(drive); int sides = d86f_get_sides(drive);
int side; int side;
int full_size = 25000;
int store_size = 50000;
int flag_bytes = 2;
if (d86f[drive].version == 0x010A)
{
full_size = d86f_get_array_size(drive);
store_size = full_size << 1;
flag_bytes++;
}
if (d86f_is_40_track(drive) && fdd_doublestep_40(drive)) if (d86f_is_40_track(drive) && fdd_doublestep_40(drive))
track /= 2; track /= 2;
for (side = 0; side < d86f_get_sides(drive); side++) for (side = 0; side < d86f_get_sides(drive); side++)
{ {
memset(d86f[drive].track_layout[side], BYTE_GAP4, 25000); memset(d86f[drive].track_layout[side], BYTE_GAP4, full_size);
memset(d86f[drive].track_data[side], 0xFF, 25000); memset(d86f[drive].track_data[side], 0xFF, full_size);
} }
d86f[drive].cur_track = track; d86f[drive].cur_track = track;
@@ -366,7 +453,15 @@ void d86f_seek(int drive, int track)
{ {
/* Track does not exist in the image, initialize it as unformatted. */ /* Track does not exist in the image, initialize it as unformatted. */
d86f[drive].track_in_file = 0; d86f[drive].track_in_file = 0;
d86f[drive].track_flags = 0x0A; /* 300 rpm, MFM, 250 kbps */ if (d86f[drive].version == 0x010A)
{
d86f[drive].side_flags[0] = 0x0A; /* 300 rpm, MFM, 250 kbps */
d86f[drive].side_flags[1] = 0x0A; /* 300 rpm, MFM, 250 kbps */
}
else
{
d86f[drive].track_flags = 0x0A; /* 300 rpm, MFM, 250 kbps */
}
return; return;
} }
@@ -374,13 +469,21 @@ void d86f_seek(int drive, int track)
fseek(d86f[drive].f, d86f[drive].track_offset[track], SEEK_SET); fseek(d86f[drive].f, d86f[drive].track_offset[track], SEEK_SET);
fread(&(d86f[drive].track_flags), 1, 1, d86f[drive].f); if (d86f[drive].version == 0x010A)
{
fread(&(d86f[drive].side_flags[0]), 1, 1, d86f[drive].f);
fread(&(d86f[drive].side_flags[1]), 1, 1, d86f[drive].f);
}
else
{
fread(&(d86f[drive].track_flags), 1, 1, d86f[drive].f);
}
for (side = 0; side < d86f_get_sides(drive); side++) for (side = 0; side < d86f_get_sides(drive); side++)
{ {
fseek(d86f[drive].f, d86f[drive].track_offset[track] + (side * 50000) + 2, SEEK_SET); fseek(d86f[drive].f, d86f[drive].track_offset[track] + (side * store_size) + flag_bytes, SEEK_SET);
fread(d86f[drive].track_layout[side], 1, d86f_get_raw_size(drive), d86f[drive].f); fread(d86f[drive].track_layout[side], 1, d86f_get_raw_size(drive), d86f[drive].f);
fseek(d86f[drive].f, d86f[drive].track_offset[track] + (side * 50000) + 25002, SEEK_SET); fseek(d86f[drive].f, d86f[drive].track_offset[track] + (side * store_size) + full_size + flag_bytes, SEEK_SET);
fread(d86f[drive].track_data[side], 1, d86f_get_raw_size(drive), d86f[drive].f); fread(d86f[drive].track_data[side], 1, d86f_get_raw_size(drive), d86f[drive].f);
} }
} }
@@ -389,6 +492,15 @@ void d86f_writeback(int drive)
{ {
int track = d86f[drive].cur_track; int track = d86f[drive].cur_track;
int side; int side;
int full_size = 25000;
int store_size = 50000;
int flag_bytes = 2;
if (d86f[drive].version == 0x010A)
{
full_size = d86f_get_array_size(drive);
store_size = full_size << 1;
flag_bytes++;
}
if (!d86f[drive].f) if (!d86f[drive].f)
return; return;
@@ -400,13 +512,21 @@ void d86f_writeback(int drive)
fwrite(d86f[drive].track_offset, 1, 1024, d86f[drive].f); fwrite(d86f[drive].track_offset, 1, 1024, d86f[drive].f);
fseek(d86f[drive].f, d86f[drive].track_offset[track], SEEK_SET); fseek(d86f[drive].f, d86f[drive].track_offset[track], SEEK_SET);
fwrite(&(d86f[drive].track_flags), 1, 1, d86f[drive].f); if (d86f[drive].version == 0x010A)
{
fwrite(&(d86f[drive].side_flags[0]), 1, 1, d86f[drive].f);
fwrite(&(d86f[drive].side_flags[1]), 1, 1, d86f[drive].f);
}
else
{
fwrite(&(d86f[drive].track_flags), 1, 1, d86f[drive].f);
}
for (side = 0; side < d86f_get_sides(drive); side++) for (side = 0; side < d86f_get_sides(drive); side++)
{ {
fseek(d86f[drive].f, d86f[drive].track_offset[track] + (side * 50000) + 2, SEEK_SET); fseek(d86f[drive].f, d86f[drive].track_offset[track] + (side * store_size) + flag_bytes, SEEK_SET);
fwrite(d86f[drive].track_layout[side], 1, d86f_get_raw_size(drive), d86f[drive].f); fwrite(d86f[drive].track_layout[side], 1, d86f_get_raw_size(drive), d86f[drive].f);
fseek(d86f[drive].f, d86f[drive].track_offset[track] + (side * 50000) + 25002, SEEK_SET); fseek(d86f[drive].f, d86f[drive].track_offset[track] + (side * store_size) + full_size + flag_bytes, SEEK_SET);
fwrite(d86f[drive].track_data[side], 1, d86f_get_raw_size(drive), d86f[drive].f); fwrite(d86f[drive].track_data[side], 1, d86f_get_raw_size(drive), d86f[drive].f);
} }
@@ -589,6 +709,16 @@ void d86f_prepare_track_layout(int drive, int side)
void d86f_format(int drive, int track, int side, int rate, uint8_t fill) void d86f_format(int drive, int track, int side, int rate, uint8_t fill)
{ {
int full_size = 25000;
int store_size = 50000;
int flag_bytes = 2;
if (d86f[drive].version == 0x010A)
{
full_size = d86f_get_array_size(drive);
store_size = full_size << 1;
flag_bytes++;
}
d86f[drive].req_sector.id.c = d86f[drive].cur_track; d86f[drive].req_sector.id.c = d86f[drive].cur_track;
d86f[drive].req_sector.id.h = side; d86f[drive].req_sector.id.h = side;
@@ -616,17 +746,21 @@ void d86f_format(int drive, int track, int side, int rate, uint8_t fill)
d86f[drive].track_flags |= (fdd_getrpm(drive ^ fdd_swap) == 360) ? 0x20 : 0; d86f[drive].track_flags |= (fdd_getrpm(drive ^ fdd_swap) == 360) ? 0x20 : 0;
d86f[drive].track_flags |= fdc_get_bit_rate(); d86f[drive].track_flags |= fdc_get_bit_rate();
d86f[drive].track_flags |= fdc_is_mfm() ? 8 : 0; d86f[drive].track_flags |= fdc_is_mfm() ? 8 : 0;
memset(d86f[drive].track_data[side], 0xFF, 25000); if (d86f[drive].version == 0x010A)
{
d86f[drive].side_flags[side] = d86f[drive].track_flags;
}
memset(d86f[drive].track_data[side], 0xFF, full_size);
d86f_prepare_track_layout(drive, side); d86f_prepare_track_layout(drive, side);
if (!d86f[drive].track_in_file) if (!d86f[drive].track_in_file)
{ {
/* Track is absent from the file, let's add it. */ /* Track is absent from the file, let's add it. */
d86f[drive].track_offset[d86f[drive].cur_track] = d86f[drive].file_size; d86f[drive].track_offset[d86f[drive].cur_track] = d86f[drive].file_size;
d86f[drive].file_size += 50002; d86f[drive].file_size += store_size + flag_bytes;
if (d86f_get_sides(drive) == 2) if (d86f_get_sides(drive) == 2)
{ {
d86f[drive].file_size += 50000; d86f[drive].file_size += store_size;
} }
d86f[drive].track_in_file = 1; d86f[drive].track_in_file = 1;
} }
@@ -679,24 +813,6 @@ int d86f_can_read_address(int drive)
return temp; return temp;
} }
int d86f_valid_bit_rate(int drive)
{
int rate = fdc_get_bit_rate();
switch (d86f_hole(drive))
{
case 0: /* DD */
if ((rate < 1) || (rate > 2)) return 0;
return 1;
case 1: /* HD */
if (rate != 0) return 0;
return 1;
case 2: /* ED */
if (rate < 3) return 0;
return 1;
}
return 1;
}
int d86f_can_format(int drive) int d86f_can_format(int drive)
{ {
int temp; int temp;

View File

@@ -978,7 +978,7 @@ void fdc_callback()
discint=-2; discint=-2;
fdc_int(); fdc_int();
fdc.stat=0xD0; fdc.stat=0xD0;
fdc.res[4]=(fdc.head?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;
fdc.res[7]=fdc.rw_track; fdc.res[7]=fdc.rw_track;
fdc.res[8]=fdc.head; fdc.res[8]=fdc.head;
@@ -1015,6 +1015,7 @@ void fdc_callback()
if (fdc.command & 0x80) if (fdc.command & 0x80)
{ {
fdc.head ^= 1; fdc.head ^= 1;
fdd_set_head(fdc.drive, fdd_get_head(fdc.drive ^ fdd_swap) ^ 1);
if (!fdc.head) if (!fdc.head)
{ {
fdc.rw_track++; fdc.rw_track++;
@@ -1038,7 +1039,7 @@ void fdc_callback()
discint=-2; discint=-2;
fdc_int(); fdc_int();
fdc.stat=0xD0; fdc.stat=0xD0;
fdc.res[4]=(fdc.head?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;
fdc.res[7]=fdc.rw_track; fdc.res[7]=fdc.rw_track;
fdc.res[8]=fdc.head; fdc.res[8]=fdc.head;
@@ -1060,6 +1061,7 @@ void fdc_callback()
if (fdc.command & 0x80) if (fdc.command & 0x80)
{ {
fdc.head ^= 1; fdc.head ^= 1;
fdd_set_head(fdc.drive, fdd_get_head(fdc.drive ^ fdd_swap) ^ 1);
if (!fdc.head) if (!fdc.head)
{ {
fdc.rw_track++; fdc.rw_track++;
@@ -1084,7 +1086,7 @@ void fdc_callback()
discint=-2; discint=-2;
fdc_int(); fdc_int();
fdc.stat=0xD0; fdc.stat=0xD0;
fdc.res[4]=(fdc.head?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;
fdc.res[7]=fdc.rw_track; fdc.res[7]=fdc.rw_track;
fdc.res[8]=fdc.head; fdc.res[8]=fdc.head;
@@ -1152,7 +1154,7 @@ void fdc_callback()
discint=-2; discint=-2;
fdc_int(); fdc_int();
fdc.stat=0xD0; fdc.stat=0xD0;
fdc.res[4] = (fdc.head?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;
fdc.res[7] = fdc.track[fdc.drive]; fdc.res[7] = fdc.track[fdc.drive];
fdc.res[8] = fdc.head; fdc.res[8] = fdc.head;
@@ -1267,7 +1269,7 @@ void fdc_overrun()
fdc_int(); fdc_int();
fdc.stat=0xD0; fdc.stat=0xD0;
fdc.res[4]=0x40|(fdc.head?4:0)|fdc.drive; fdc.res[4]=0x40|(fdd_get_head(fdc.drive ^ fdd_swap)?4:0)|fdc.drive;
fdc.res[5]=0x10; /*Overrun*/ fdc.res[5]=0x10; /*Overrun*/
fdc.res[6]=0; fdc.res[6]=0;
fdc.res[7]=0; fdc.res[7]=0;
@@ -1354,7 +1356,7 @@ void fdc_notfound()
fdc_int(); fdc_int();
fdc.stat=0xD0; fdc.stat=0xD0;
fdc.res[4]=0x40|(fdc.head?4:0)|fdc.drive; fdc.res[4]=0x40|(fdd_get_head(fdc.drive ^ fdd_swap)?4:0)|fdc.drive;
fdc.res[5]=5; fdc.res[5]=5;
fdc.res[6]=0; fdc.res[6]=0;
fdc.res[7]=0; fdc.res[7]=0;
@@ -1371,7 +1373,7 @@ void fdc_datacrcerror()
fdc_int(); fdc_int();
fdc.stat=0xD0; fdc.stat=0xD0;
fdc.res[4]=0x40|(fdc.head?4:0)|fdc.drive; fdc.res[4]=0x40|(fdd_get_head(fdc.drive ^ fdd_swap)?4:0)|fdc.drive;
fdc.res[5]=0x20; /*Data error*/ fdc.res[5]=0x20; /*Data error*/
fdc.res[6]=0x20; /*Data error in data field*/ fdc.res[6]=0x20; /*Data error in data field*/
fdc.res[7]=0; fdc.res[7]=0;
@@ -1388,7 +1390,7 @@ void fdc_headercrcerror()
fdc_int(); fdc_int();
fdc.stat=0xD0; fdc.stat=0xD0;
fdc.res[4]=0x40|(fdc.head?4:0)|fdc.drive; fdc.res[4]=0x40|(fdd_get_head(fdc.drive ^ fdd_swap)?4:0)|fdc.drive;
fdc.res[5]=0x20; /*Data error*/ fdc.res[5]=0x20; /*Data error*/
fdc.res[6]=0; fdc.res[6]=0;
fdc.res[7]=0; fdc.res[7]=0;
@@ -1405,7 +1407,7 @@ void fdc_writeprotect()
fdc_int(); fdc_int();
fdc.stat=0xD0; fdc.stat=0xD0;
fdc.res[4]=0x40|(fdc.head?4:0)|fdc.drive; fdc.res[4]=0x40|(fdd_get_head(fdc.drive ^ fdd_swap)?4:0)|fdc.drive;
fdc.res[5]=0x02; /*Not writeable*/ fdc.res[5]=0x02; /*Not writeable*/
fdc.res[6]=0; fdc.res[6]=0;
fdc.res[7]=0; fdc.res[7]=0;
@@ -1472,7 +1474,7 @@ void fdc_sectorid(uint8_t track, uint8_t side, uint8_t sector, uint8_t size, uin
// pclog("SectorID %i %i %i %i\n", track, side, sector, size); // pclog("SectorID %i %i %i %i\n", track, side, sector, size);
fdc_int(); fdc_int();
fdc.stat=0xD0; fdc.stat=0xD0;
fdc.res[4]=(fdc.head?4:0)|fdc.drive; fdc.res[4]=(fdd_get_head(fdc.drive ^ fdd_swap)?4:0)|fdc.drive;
fdc.res[5]=0; fdc.res[5]=0;
fdc.res[6]=0; fdc.res[6]=0;
fdc.res[7]=track; fdc.res[7]=track;