2016-08-20 03:40:12 +02:00
|
|
|
/* Copyright holders: Tenshi
|
|
|
|
|
see COPYING for more details
|
|
|
|
|
*/
|
|
|
|
|
#include "ibm.h"
|
|
|
|
|
#include "disc.h"
|
2016-08-31 22:49:56 +02:00
|
|
|
#include "disc_86f.h"
|
2016-09-03 18:07:46 +02:00
|
|
|
#include "fdc.h"
|
2016-08-20 03:40:12 +02:00
|
|
|
#include "fdd.h"
|
|
|
|
|
|
|
|
|
|
#define MAX_SECTORS 256
|
|
|
|
|
|
|
|
|
|
enum
|
|
|
|
|
{
|
|
|
|
|
STATE_IDLE,
|
|
|
|
|
STATE_READ_FIND_SECTOR,
|
|
|
|
|
STATE_READ_SECTOR,
|
2016-09-03 18:07:46 +02:00
|
|
|
STATE_READ_SECTOR_CRC,
|
|
|
|
|
STATE_READ_SECTOR_GAP3,
|
2016-08-20 03:40:12 +02:00
|
|
|
STATE_READ_FIND_FIRST_SECTOR,
|
|
|
|
|
STATE_READ_FIRST_SECTOR,
|
2016-09-03 18:07:46 +02:00
|
|
|
STATE_READ_FIRST_SECTOR_CRC,
|
|
|
|
|
STATE_READ_FIRST_SECTOR_GAP3,
|
2016-08-20 03:40:12 +02:00
|
|
|
STATE_READ_FIND_NEXT_SECTOR,
|
|
|
|
|
STATE_READ_NEXT_SECTOR,
|
2016-09-03 18:07:46 +02:00
|
|
|
STATE_READ_NEXT_SECTOR_CRC,
|
|
|
|
|
STATE_READ_NEXT_SECTOR_GAP3,
|
2016-08-20 03:40:12 +02:00
|
|
|
STATE_WRITE_FIND_SECTOR,
|
|
|
|
|
STATE_WRITE_SECTOR,
|
2016-09-03 18:07:46 +02:00
|
|
|
STATE_WRITE_SECTOR_CRC,
|
|
|
|
|
STATE_WRITE_SECTOR_GAP3,
|
2016-08-20 03:40:12 +02:00
|
|
|
STATE_READ_FIND_ADDRESS,
|
|
|
|
|
STATE_READ_ADDRESS,
|
|
|
|
|
STATE_FORMAT_FIND,
|
|
|
|
|
STATE_FORMAT,
|
2016-09-03 18:07:46 +02:00
|
|
|
STATE_SEEK,
|
2016-08-20 03:40:12 +02:00
|
|
|
};
|
|
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
static uint16_t CRCTable[256];
|
|
|
|
|
|
2016-08-20 03:40:12 +02:00
|
|
|
static int d86f_drive;
|
|
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
typedef union {
|
|
|
|
|
uint16_t word;
|
|
|
|
|
uint8_t bytes[2];
|
|
|
|
|
} crc_t;
|
|
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
uint8_t c;
|
|
|
|
|
uint8_t h;
|
|
|
|
|
uint8_t r;
|
|
|
|
|
uint8_t n;
|
|
|
|
|
} sector_id_fields_t;
|
|
|
|
|
|
|
|
|
|
typedef union
|
|
|
|
|
{
|
|
|
|
|
uint32_t dword;
|
|
|
|
|
uint8_t byte_array[4];
|
|
|
|
|
sector_id_fields_t id;
|
|
|
|
|
} sector_id_t;
|
|
|
|
|
|
2016-08-20 03:40:12 +02:00
|
|
|
static struct
|
|
|
|
|
{
|
|
|
|
|
FILE *f;
|
2016-09-05 22:03:33 +02:00
|
|
|
uint16_t version;
|
2016-08-31 22:49:56 +02:00
|
|
|
uint8_t disk_flags;
|
2016-09-05 21:58:28 +02:00
|
|
|
uint8_t track_data[2][50000];
|
|
|
|
|
uint8_t track_layout[2][50000];
|
2016-08-31 22:49:56 +02:00
|
|
|
uint8_t track_flags;
|
2016-09-05 22:10:04 +02:00
|
|
|
uint8_t side_flags[2];
|
2016-08-31 22:49:56 +02:00
|
|
|
uint8_t track_in_file;
|
2016-09-03 18:07:46 +02:00
|
|
|
uint32_t track_offset[256];
|
2016-09-01 18:52:23 +02:00
|
|
|
uint32_t file_size;
|
2016-09-03 18:07:46 +02:00
|
|
|
sector_id_t format_sector_id;
|
|
|
|
|
sector_id_t rw_sector_id;
|
|
|
|
|
sector_id_t last_sector;
|
|
|
|
|
sector_id_t req_sector;
|
|
|
|
|
uint32_t index_count;
|
|
|
|
|
uint8_t state;
|
|
|
|
|
uint8_t fill;
|
|
|
|
|
uint16_t track_pos;
|
|
|
|
|
uint16_t datac;
|
|
|
|
|
uint16_t id_pos;
|
|
|
|
|
uint16_t section_pos;
|
|
|
|
|
crc_t calc_crc;
|
|
|
|
|
crc_t track_crc;
|
|
|
|
|
uint8_t track_byte;
|
|
|
|
|
uint8_t track_index;
|
|
|
|
|
uint8_t old_track_byte;
|
|
|
|
|
uint8_t old_track_index;
|
2016-09-04 03:50:06 +02:00
|
|
|
uint8_t cur_track;
|
2016-08-20 03:40:12 +02:00
|
|
|
} d86f[2];
|
|
|
|
|
|
|
|
|
|
/* Needed for formatting! */
|
2016-09-04 03:50:06 +02:00
|
|
|
int d86f_is_40_track(int drive)
|
|
|
|
|
{
|
|
|
|
|
return (d86f[drive].disk_flags & 1) ? 0 : 1;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-20 03:40:12 +02:00
|
|
|
int d86f_realtrack(int drive, int track)
|
|
|
|
|
{
|
2016-09-04 03:50:06 +02:00
|
|
|
if (d86f_is_40_track(drive) && fdd_doublestep_40(drive))
|
2016-08-20 03:40:12 +02:00
|
|
|
track /= 2;
|
|
|
|
|
|
|
|
|
|
return track;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-31 22:49:56 +02:00
|
|
|
static void d86f_setupcrc(uint16_t poly, uint16_t rvalue)
|
|
|
|
|
{
|
|
|
|
|
int c = 256, bc;
|
|
|
|
|
uint16_t crctemp;
|
|
|
|
|
|
|
|
|
|
while(c--)
|
|
|
|
|
{
|
|
|
|
|
crctemp = c << 8;
|
|
|
|
|
bc = 8;
|
|
|
|
|
|
|
|
|
|
while(bc--)
|
|
|
|
|
{
|
|
|
|
|
if(crctemp & 0x8000)
|
|
|
|
|
{
|
|
|
|
|
crctemp = (crctemp << 1) ^ poly;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
crctemp <<= 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CRCTable[c] = crctemp;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void d86f_calccrc(int drive, uint8_t byte)
|
|
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].calc_crc.word = (d86f[drive].calc_crc.word << 8) ^ CRCTable[(d86f[drive].calc_crc.word >> 8)^byte];
|
2016-08-31 22:49:56 +02:00
|
|
|
}
|
|
|
|
|
|
2016-08-20 03:40:12 +02:00
|
|
|
void d86f_init()
|
|
|
|
|
{
|
|
|
|
|
memset(d86f, 0, sizeof(d86f));
|
2016-08-31 22:49:56 +02:00
|
|
|
d86f_setupcrc(0x1021, 0xcdb4);
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
|
|
|
|
|
2016-09-05 21:58:28 +02:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-20 03:40:12 +02:00
|
|
|
void d86f_load(int drive, char *fn)
|
|
|
|
|
{
|
|
|
|
|
uint32_t magic = 0;
|
|
|
|
|
uint32_t len = 0;
|
|
|
|
|
|
2016-08-31 22:49:56 +02:00
|
|
|
int i = 0;
|
|
|
|
|
int j = 0;
|
|
|
|
|
|
2016-08-20 03:40:12 +02:00
|
|
|
writeprot[drive] = 0;
|
|
|
|
|
d86f[drive].f = fopen(fn, "rb+");
|
|
|
|
|
if (!d86f[drive].f)
|
|
|
|
|
{
|
|
|
|
|
d86f[drive].f = fopen(fn, "rb");
|
|
|
|
|
if (!d86f[drive].f)
|
|
|
|
|
return;
|
|
|
|
|
writeprot[drive] = 1;
|
|
|
|
|
}
|
|
|
|
|
fwriteprot[drive] = writeprot[drive];
|
|
|
|
|
|
|
|
|
|
fseek(d86f[drive].f, 0, SEEK_END);
|
2016-08-31 22:49:56 +02:00
|
|
|
len = ftell(d86f[drive].f);
|
2016-08-20 03:40:12 +02:00
|
|
|
fseek(d86f[drive].f, 0, SEEK_SET);
|
|
|
|
|
|
|
|
|
|
if (len < 52056)
|
|
|
|
|
{
|
|
|
|
|
/* File too small, abort. */
|
|
|
|
|
fclose(d86f[drive].f);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fread(&magic, 4, 1, d86f[drive].f);
|
|
|
|
|
|
2016-08-31 22:49:56 +02:00
|
|
|
if (magic != 0x46423638)
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
|
|
|
|
/* File is not of the valid format, abort. */
|
2016-08-31 22:49:56 +02:00
|
|
|
pclog("86F: Unrecognized magic bytes: %08X\n", magic);
|
2016-08-20 03:40:12 +02:00
|
|
|
fclose(d86f[drive].f);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-05 22:03:33 +02:00
|
|
|
fread(&(d86f[drive].version), 2, 1, d86f[drive].f);
|
2016-08-20 03:40:12 +02:00
|
|
|
|
2016-09-05 22:03:33 +02:00
|
|
|
if ((d86f[drive].version != 0x0100) && (d86f[drive].version != 0x010A))
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-08-31 22:49:56 +02:00
|
|
|
/* File is not of a recognized format version abort. */
|
2016-09-05 22:03:33 +02:00
|
|
|
pclog("86F: Unrecognized file version: %i.%02i\n", d86f[drive].version >> 8, d86f[drive].version & 0xFF);
|
2016-08-20 03:40:12 +02:00
|
|
|
fclose(d86f[drive].f);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2016-09-05 21:58:28 +02:00
|
|
|
else
|
|
|
|
|
{
|
2016-09-05 22:03:33 +02:00
|
|
|
pclog("86F: Recognized file version: %i.%02i\n", d86f[drive].version >> 8, d86f[drive].version & 0xFF);
|
2016-09-05 21:58:28 +02:00
|
|
|
}
|
2016-08-20 03:40:12 +02:00
|
|
|
|
2016-08-31 22:49:56 +02:00
|
|
|
fread(&(d86f[drive].disk_flags), 1, 1, d86f[drive].f);
|
2016-08-20 03:40:12 +02:00
|
|
|
|
2016-08-31 22:49:56 +02:00
|
|
|
if (((d86f[drive].disk_flags >> 1) & 3) == 3)
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-08-31 22:49:56 +02:00
|
|
|
/* Invalid disk hole. */
|
|
|
|
|
pclog("86F: Unrecognized disk hole type 3\n");
|
|
|
|
|
fclose(d86f[drive].f);
|
|
|
|
|
return;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
|
|
|
|
|
2016-08-31 22:49:56 +02:00
|
|
|
if (!writeprot[drive])
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-08-31 22:49:56 +02:00
|
|
|
writeprot[drive] = (d86f[drive].disk_flags & 0x10) ? 1 : 0;
|
|
|
|
|
fwriteprot[drive] = writeprot[drive];
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
|
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
fread(d86f[drive].track_offset, 1, 1024, d86f[drive].f);
|
2016-08-20 03:40:12 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
if (!(d86f[drive].track_offset[0]))
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-08-31 22:49:56 +02:00
|
|
|
/* File has no track 0, abort. */
|
|
|
|
|
pclog("86F: No Track 0\n");
|
|
|
|
|
fclose(d86f[drive].f);
|
|
|
|
|
return;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
|
|
|
|
|
2016-08-31 22:49:56 +02:00
|
|
|
/* Load track 0 flags as default. */
|
2016-09-05 21:58:28 +02:00
|
|
|
if (d86f[drive].version == 0x010A)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
}
|
2016-09-01 18:52:23 +02:00
|
|
|
|
|
|
|
|
fseek(d86f[drive].f, 0, SEEK_END);
|
|
|
|
|
d86f[drive].file_size = ftell(d86f[drive].f);
|
|
|
|
|
|
2016-08-31 22:49:56 +02:00
|
|
|
fseek(d86f[drive].f, 0, SEEK_SET);
|
|
|
|
|
|
2016-08-20 03:40:12 +02:00
|
|
|
drives[drive].seek = d86f_seek;
|
2016-08-31 22:49:56 +02:00
|
|
|
drives[drive].readsector = d86f_readsector;
|
|
|
|
|
drives[drive].writesector = d86f_writesector;
|
|
|
|
|
drives[drive].readaddress = d86f_readaddress;
|
2016-08-20 03:40:12 +02:00
|
|
|
drives[drive].hole = d86f_hole;
|
|
|
|
|
drives[drive].byteperiod = d86f_byteperiod;
|
2016-08-31 22:49:56 +02:00
|
|
|
drives[drive].poll = d86f_poll;
|
|
|
|
|
drives[drive].format = d86f_format;
|
2016-08-20 03:40:12 +02:00
|
|
|
drives[drive].realtrack = d86f_realtrack;
|
2016-08-31 22:49:56 +02:00
|
|
|
drives[drive].stop = d86f_stop;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int d86f_hole(int drive)
|
|
|
|
|
{
|
2016-08-31 22:49:56 +02:00
|
|
|
return (d86f[drive].disk_flags >> 1) & 3;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
|
|
|
|
|
2016-09-05 21:58:28 +02:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-04 19:37:08 +02:00
|
|
|
uint8_t d86f_track_flags(int drive)
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-05 21:58:28 +02:00
|
|
|
uint8_t tf = d86f_flags(drive);
|
2016-09-04 19:37:08 +02:00
|
|
|
uint8_t rr = tf & 0x27;
|
2016-09-04 22:20:32 +02:00
|
|
|
uint8_t dr = fdd_get_flags(drive) & 7;
|
2016-09-04 19:37:08 +02:00
|
|
|
tf &= ~0x27;
|
|
|
|
|
|
|
|
|
|
switch (rr)
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-04 19:37:08 +02:00
|
|
|
case 0x02:
|
|
|
|
|
case 0x21:
|
|
|
|
|
/* 1 MB unformatted medium, treat these two as equivalent. */
|
|
|
|
|
switch (dr)
|
2016-08-31 22:49:56 +02:00
|
|
|
{
|
2016-09-04 19:37:08 +02:00
|
|
|
case 0x06:
|
|
|
|
|
/* 5.25" Single-RPM HD drive, treat as 300 kbps, 360 rpm. */
|
|
|
|
|
tf |= 0x21;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
/* Any other drive, treat as 250 kbps, 300 rpm. */
|
|
|
|
|
tf |= 0x02;
|
|
|
|
|
break;
|
2016-08-31 22:49:56 +02:00
|
|
|
}
|
2016-09-04 19:37:08 +02:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
tf |= rr;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return tf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double d86f_byteperiod(int drive)
|
|
|
|
|
{
|
|
|
|
|
switch (d86f_track_flags(drive) & 0x0f)
|
|
|
|
|
{
|
|
|
|
|
case 0x02: /* 125 kbps, FM */
|
2016-08-31 22:49:56 +02:00
|
|
|
return 64.0;
|
|
|
|
|
case 0x01: /* 150 kbps, FM */
|
|
|
|
|
return 320.0 / 6.0;
|
|
|
|
|
case 0x0A: /* 250 kbps, MFM */
|
|
|
|
|
case 0x00: /* 250 kbps, FM */
|
|
|
|
|
return 32.0;
|
|
|
|
|
case 0x09: /* 300 kbps, MFM */
|
|
|
|
|
return 160.0 / 6.0;
|
|
|
|
|
case 0x08: /* 500 kbps, MFM */
|
|
|
|
|
return 16.0;
|
|
|
|
|
case 0x0B: /* 1000 kbps, MFM */
|
|
|
|
|
return 8.0;
|
|
|
|
|
case 0x0D: /* 2000 kbps, MFM */
|
|
|
|
|
return 4.0;
|
|
|
|
|
default:
|
|
|
|
|
return 32.0;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
return 32.0;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void d86f_close(int drive)
|
|
|
|
|
{
|
|
|
|
|
if (d86f[drive].f)
|
|
|
|
|
fclose(d86f[drive].f);
|
|
|
|
|
d86f[drive].f = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-31 22:49:56 +02:00
|
|
|
int d86f_is_mfm(int drive)
|
|
|
|
|
{
|
2016-09-05 21:58:28 +02:00
|
|
|
return (d86f_track_flags(drive) & 8) ? 1 : 0;
|
2016-08-31 22:49:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint16_t d86f_get_raw_size(int drive)
|
|
|
|
|
{
|
|
|
|
|
double rate = 0.0;
|
|
|
|
|
int mfm = d86f_is_mfm(drive);
|
2016-09-04 19:37:08 +02:00
|
|
|
double rpm = (d86f_track_flags(drive) & 0x20) ? 360.0 : 300.0;
|
2016-08-31 22:49:56 +02:00
|
|
|
double size = 6250.0;
|
2016-09-04 19:37:08 +02:00
|
|
|
switch (d86f_track_flags(drive) & 7)
|
2016-08-31 22:49:56 +02:00
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
rate = 500.0;
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
rate = 300.0;
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
rate = 250.0;
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
rate = 1000.0;
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
rate = 2000.0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!mfm) rate /= 2.0;
|
|
|
|
|
size = (size / 250.0) * rate;
|
|
|
|
|
size = (size * 300.0) / rpm;
|
|
|
|
|
return (uint16_t) size;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-20 03:40:12 +02:00
|
|
|
void d86f_seek(int drive, int track)
|
|
|
|
|
{
|
2016-08-31 22:49:56 +02:00
|
|
|
int sides = d86f_get_sides(drive);
|
2016-08-20 03:40:12 +02:00
|
|
|
int side;
|
2016-09-05 21:58:28 +02:00
|
|
|
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++;
|
|
|
|
|
}
|
2016-08-20 03:40:12 +02:00
|
|
|
|
2016-08-31 22:49:56 +02:00
|
|
|
if (d86f_is_40_track(drive) && fdd_doublestep_40(drive))
|
2016-08-20 03:40:12 +02:00
|
|
|
track /= 2;
|
|
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
for (side = 0; side < d86f_get_sides(drive); side++)
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-05 21:58:28 +02:00
|
|
|
memset(d86f[drive].track_layout[side], BYTE_GAP4, full_size);
|
|
|
|
|
memset(d86f[drive].track_data[side], 0xFF, full_size);
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-04 03:50:06 +02:00
|
|
|
d86f[drive].cur_track = track;
|
|
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
if (!(d86f[drive].track_offset[track]))
|
2016-08-31 22:49:56 +02:00
|
|
|
{
|
|
|
|
|
/* Track does not exist in the image, initialize it as unformatted. */
|
|
|
|
|
d86f[drive].track_in_file = 0;
|
2016-09-05 21:58:28 +02:00
|
|
|
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 */
|
|
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
return;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
|
|
|
|
|
d86f[drive].track_in_file = 1;
|
|
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
fseek(d86f[drive].f, d86f[drive].track_offset[track], SEEK_SET);
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-05 21:58:28 +02:00
|
|
|
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);
|
|
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
for (side = 0; side < d86f_get_sides(drive); side++)
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-05 21:58:28 +02:00
|
|
|
fseek(d86f[drive].f, d86f[drive].track_offset[track] + (side * store_size) + flag_bytes, SEEK_SET);
|
2016-09-03 18:07:46 +02:00
|
|
|
fread(d86f[drive].track_layout[side], 1, d86f_get_raw_size(drive), d86f[drive].f);
|
2016-09-05 21:58:28 +02:00
|
|
|
fseek(d86f[drive].f, d86f[drive].track_offset[track] + (side * store_size) + full_size + flag_bytes, SEEK_SET);
|
2016-09-03 18:07:46 +02:00
|
|
|
fread(d86f[drive].track_data[side], 1, d86f_get_raw_size(drive), d86f[drive].f);
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-04 03:50:06 +02:00
|
|
|
void d86f_writeback(int drive)
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-04 03:50:06 +02:00
|
|
|
int track = d86f[drive].cur_track;
|
2016-09-03 18:07:46 +02:00
|
|
|
int side;
|
2016-09-05 21:58:28 +02:00
|
|
|
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++;
|
|
|
|
|
}
|
2016-09-03 18:07:46 +02:00
|
|
|
|
2016-08-20 03:40:12 +02:00
|
|
|
if (!d86f[drive].f)
|
|
|
|
|
return;
|
|
|
|
|
|
2016-08-31 22:49:56 +02:00
|
|
|
if (!d86f[drive].track_in_file)
|
2016-08-20 03:40:12 +02:00
|
|
|
return; /*Should never happen*/
|
|
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
fseek(d86f[drive].f, 7, SEEK_SET);
|
|
|
|
|
fwrite(d86f[drive].track_offset, 1, 1024, d86f[drive].f);
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
fseek(d86f[drive].f, d86f[drive].track_offset[track], SEEK_SET);
|
2016-09-05 21:58:28 +02:00
|
|
|
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);
|
|
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
for (side = 0; side < d86f_get_sides(drive); side++)
|
2016-08-31 22:49:56 +02:00
|
|
|
{
|
2016-09-05 21:58:28 +02:00
|
|
|
fseek(d86f[drive].f, d86f[drive].track_offset[track] + (side * store_size) + flag_bytes, SEEK_SET);
|
2016-09-03 18:07:46 +02:00
|
|
|
fwrite(d86f[drive].track_layout[side], 1, d86f_get_raw_size(drive), d86f[drive].f);
|
2016-09-05 21:58:28 +02:00
|
|
|
fseek(d86f[drive].f, d86f[drive].track_offset[track] + (side * store_size) + full_size + flag_bytes, SEEK_SET);
|
2016-09-03 18:07:46 +02:00
|
|
|
fwrite(d86f[drive].track_data[side], 1, d86f_get_raw_size(drive), d86f[drive].f);
|
2016-08-31 22:49:56 +02:00
|
|
|
}
|
2016-09-03 18:07:46 +02:00
|
|
|
|
|
|
|
|
// pclog("d86f_writeback(): %08X\n", d86f[drive].track_offset[track]);
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void d86f_reset(int drive, int side)
|
|
|
|
|
{
|
|
|
|
|
if (side == 0)
|
|
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].index_count = 0;
|
|
|
|
|
d86f[drive].state = STATE_SEEK;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-04 19:37:08 +02:00
|
|
|
static int d86f_get_bitcell_period(int drive)
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-08-31 22:49:56 +02:00
|
|
|
double rate = 0.0;
|
2016-09-04 19:37:08 +02:00
|
|
|
int mfm = (d86f_track_flags(drive) & 8) ? 1 : 0;
|
|
|
|
|
double rpm = (d86f_track_flags(drive) & 0x20) ? 360.0 : 300.0;
|
2016-08-31 22:49:56 +02:00
|
|
|
double size = 8000.0;
|
2016-09-04 19:37:08 +02:00
|
|
|
switch (d86f_track_flags(drive) & 7)
|
2016-08-31 22:49:56 +02:00
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
rate = 500.0;
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
rate = 300.0;
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
rate = 250.0;
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
rate = 1000.0;
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
rate = 2000.0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!mfm) rate /= 2.0;
|
|
|
|
|
size = (size * 250.0) / rate;
|
|
|
|
|
size = (size * 300.0) / rpm;
|
|
|
|
|
size = (size * fdd_getrpm(drive)) / 300.0;
|
|
|
|
|
return (int) size;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void d86f_readsector(int drive, int sector, int track, int side, int rate, int sector_size)
|
|
|
|
|
{
|
2016-09-04 19:37:08 +02:00
|
|
|
// pclog("d86f_readsector: fdc_period=%i img_period=%i rate=%i sector=%i track=%i side=%i\n", fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), rate, sector, track, side);
|
2016-08-20 03:40:12 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].req_sector.id.c = track;
|
|
|
|
|
d86f[drive].req_sector.id.h = side;
|
2016-08-31 22:49:56 +02:00
|
|
|
|
|
|
|
|
if (side && (d86f_get_sides(drive) == 1))
|
|
|
|
|
{
|
|
|
|
|
fdc_notfound();
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].state = STATE_IDLE;
|
|
|
|
|
d86f[drive].index_count = 0;
|
2016-08-31 22:49:56 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-20 03:40:12 +02:00
|
|
|
d86f_drive = drive;
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].req_sector.id.r = sector;
|
|
|
|
|
d86f[drive].req_sector.id.n = sector_size;
|
|
|
|
|
d86f[drive].index_count = 0;
|
2016-08-20 03:40:12 +02:00
|
|
|
if (sector == SECTOR_FIRST)
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].state = STATE_READ_FIND_FIRST_SECTOR;
|
2016-08-20 03:40:12 +02:00
|
|
|
else if (sector == SECTOR_NEXT)
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].state = STATE_READ_FIND_NEXT_SECTOR;
|
2016-08-20 03:40:12 +02:00
|
|
|
else
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].state = STATE_READ_FIND_SECTOR;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void d86f_writesector(int drive, int sector, int track, int side, int rate, int sector_size)
|
|
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].req_sector.id.c = track;
|
|
|
|
|
d86f[drive].req_sector.id.h = side;
|
|
|
|
|
d86f[drive].req_sector.id.r = sector;
|
|
|
|
|
d86f[drive].req_sector.id.n = sector_size;
|
2016-08-20 03:40:12 +02:00
|
|
|
|
2016-09-04 19:37:08 +02:00
|
|
|
// pclog("d86f_writesector: drive=%c: fdc_period=%i img_period=%i rate=%i chrn=%08X\n", drive + 0x41, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), rate, d86f[drive].req_sector.dword);
|
2016-08-31 22:49:56 +02:00
|
|
|
|
|
|
|
|
if (side && (d86f_get_sides(drive) == 1))
|
|
|
|
|
{
|
|
|
|
|
fdc_notfound();
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].state = STATE_IDLE;
|
|
|
|
|
d86f[drive].index_count = 0;
|
2016-08-31 22:49:56 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-20 03:40:12 +02:00
|
|
|
d86f_drive = drive;
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].index_count = 0;
|
|
|
|
|
d86f[drive].state = STATE_WRITE_FIND_SECTOR;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void d86f_readaddress(int drive, int track, int side, int rate)
|
|
|
|
|
{
|
2016-09-04 19:37:08 +02:00
|
|
|
// pclog("d86f_readaddress: fdc_period=%i img_period=%i rate=%i track=%i side=%i\n", fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), rate, track, side);
|
2016-08-20 03:40:12 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].req_sector.id.c = track;
|
|
|
|
|
d86f[drive].req_sector.id.h = side;
|
2016-08-20 03:40:12 +02:00
|
|
|
|
2016-08-31 22:49:56 +02:00
|
|
|
if (side && (d86f_get_sides(drive) == 1))
|
|
|
|
|
{
|
|
|
|
|
fdc_notfound();
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].state = STATE_IDLE;
|
|
|
|
|
d86f[drive].index_count = 0;
|
2016-08-31 22:49:56 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2016-08-20 03:40:12 +02:00
|
|
|
|
2016-08-31 22:49:56 +02:00
|
|
|
d86f_drive = drive;
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].index_count = 0;
|
|
|
|
|
d86f[drive].state = STATE_READ_FIND_ADDRESS;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void d86f_prepare_track_layout(int drive, int side)
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
int j = 0;
|
2016-08-31 22:49:56 +02:00
|
|
|
int real_gap0_len = d86f_is_mfm(drive) ? 80 : 40;
|
|
|
|
|
int sync_len = d86f_is_mfm(drive) ? 12 : 6;
|
|
|
|
|
int am_len = d86f_is_mfm(drive) ? 4 : 1;
|
|
|
|
|
int real_gap1_len = d86f_is_mfm(drive) ? 50 : 26;
|
|
|
|
|
int real_gap2_len = (fdc_get_bit_rate() >= 1000) ? 41 : 22;
|
|
|
|
|
int real_gap3_len = fdc_get_gap();
|
2016-09-03 18:07:46 +02:00
|
|
|
|
2016-08-31 22:49:56 +02:00
|
|
|
memset(d86f[drive].track_layout[side], BYTE_GAP4, d86f_get_raw_size(drive));
|
2016-08-20 03:40:12 +02:00
|
|
|
i = 0;
|
2016-09-03 18:07:46 +02:00
|
|
|
|
|
|
|
|
memset(d86f[drive].track_layout[side] + i, BYTE_GAP0, real_gap0_len);
|
|
|
|
|
i += real_gap0_len;
|
|
|
|
|
memset(d86f[drive].track_layout[side] + i, BYTE_I_SYNC, sync_len);
|
|
|
|
|
i += sync_len;
|
|
|
|
|
if (d86f_is_mfm(drive))
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
memset(d86f[drive].track_layout[side] + i, BYTE_IAM_SYNC, 3);
|
|
|
|
|
i += 3;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
2016-09-03 18:07:46 +02:00
|
|
|
memset(d86f[drive].track_layout[side] + i, BYTE_IAM, 1);
|
|
|
|
|
i++;
|
|
|
|
|
memset(d86f[drive].track_layout[side] + i, BYTE_GAP1, real_gap1_len);
|
|
|
|
|
i += real_gap1_len;
|
|
|
|
|
|
2016-08-31 22:49:56 +02:00
|
|
|
d86f[drive].track_layout[side][0] |= BYTE_INDEX_HOLE;
|
|
|
|
|
for (j = 0; j < fdc_get_format_sectors(); j++)
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
|
|
|
|
// pclog("Sector %i (%i)\n", j, s->n);
|
2016-08-31 22:49:56 +02:00
|
|
|
memset(d86f[drive].track_layout[side] + i, BYTE_ID_SYNC, sync_len);
|
2016-08-20 03:40:12 +02:00
|
|
|
i += sync_len;
|
2016-08-31 22:49:56 +02:00
|
|
|
if (d86f_is_mfm(drive))
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-08-31 22:49:56 +02:00
|
|
|
memset(d86f[drive].track_layout[side] + i, BYTE_IDAM_SYNC, 3);
|
2016-08-20 03:40:12 +02:00
|
|
|
i += 3;
|
|
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
memset(d86f[drive].track_layout[side] + i, BYTE_IDAM, 1);
|
2016-08-20 03:40:12 +02:00
|
|
|
i++;
|
2016-08-31 22:49:56 +02:00
|
|
|
memset(d86f[drive].track_layout[side] + i, BYTE_ID, 4);
|
2016-08-20 03:40:12 +02:00
|
|
|
i += 4;
|
2016-08-31 22:49:56 +02:00
|
|
|
memset(d86f[drive].track_layout[side] + i, BYTE_ID_CRC, 2);
|
2016-08-20 03:40:12 +02:00
|
|
|
i += 2;
|
2016-08-31 22:49:56 +02:00
|
|
|
memset(d86f[drive].track_layout[side] + i, BYTE_GAP2, real_gap2_len);
|
|
|
|
|
i += real_gap2_len;
|
|
|
|
|
memset(d86f[drive].track_layout[side] + i, BYTE_DATA_SYNC, sync_len);
|
2016-08-20 03:40:12 +02:00
|
|
|
i += sync_len;
|
2016-08-31 22:49:56 +02:00
|
|
|
if (d86f_is_mfm(drive))
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-08-31 22:49:56 +02:00
|
|
|
memset(d86f[drive].track_layout[side] + i, BYTE_DATAAM_SYNC, 3);
|
2016-08-20 03:40:12 +02:00
|
|
|
i += 3;
|
|
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
memset(d86f[drive].track_layout[side] + i, BYTE_DATAAM, 1);
|
2016-08-20 03:40:12 +02:00
|
|
|
i++;
|
2016-08-31 22:49:56 +02:00
|
|
|
memset(d86f[drive].track_layout[side] + i, BYTE_DATA, (128 << fdc_get_format_n()));
|
|
|
|
|
i += (128 << fdc_get_format_n());
|
|
|
|
|
memset(d86f[drive].track_layout[side] + i, BYTE_DATA_CRC, 2);
|
2016-08-20 03:40:12 +02:00
|
|
|
i += 2;
|
2016-08-31 22:49:56 +02:00
|
|
|
memset(d86f[drive].track_layout[side] + i, BYTE_GAP3, real_gap3_len);
|
|
|
|
|
i += real_gap3_len;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void d86f_format(int drive, int track, int side, int rate, uint8_t fill)
|
|
|
|
|
{
|
2016-09-05 21:58:28 +02:00
|
|
|
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++;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-04 03:50:06 +02:00
|
|
|
d86f[drive].req_sector.id.c = d86f[drive].cur_track;
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].req_sector.id.h = side;
|
2016-08-20 03:40:12 +02:00
|
|
|
|
2016-09-04 19:37:08 +02:00
|
|
|
if ((side && (d86f_get_sides(drive) == 1)) || !d86f_valid_bit_rate(drive))
|
2016-08-31 22:49:56 +02:00
|
|
|
{
|
|
|
|
|
fdc_notfound();
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].state = STATE_IDLE;
|
|
|
|
|
d86f[drive].index_count = 0;
|
2016-08-31 22:49:56 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2016-08-20 03:40:12 +02:00
|
|
|
|
2016-09-04 03:50:06 +02:00
|
|
|
if ((d86f[drive].cur_track < 0) || (d86f[drive].cur_track > 256))
|
2016-09-01 18:52:23 +02:00
|
|
|
{
|
|
|
|
|
fdc_writeprotect();
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].state = STATE_IDLE;
|
|
|
|
|
d86f[drive].index_count = 0;
|
2016-09-01 18:52:23 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-31 22:49:56 +02:00
|
|
|
d86f_drive = drive;
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].fill = fill;
|
|
|
|
|
d86f[drive].index_count = 0;
|
2016-08-31 22:49:56 +02:00
|
|
|
/* Let's prepare the track space and layout before filling. */
|
|
|
|
|
d86f[drive].track_flags &= 0xc0;
|
|
|
|
|
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_is_mfm() ? 8 : 0;
|
2016-09-05 21:58:28 +02:00
|
|
|
if (d86f[drive].version == 0x010A)
|
|
|
|
|
{
|
|
|
|
|
d86f[drive].side_flags[side] = d86f[drive].track_flags;
|
|
|
|
|
}
|
|
|
|
|
memset(d86f[drive].track_data[side], 0xFF, full_size);
|
2016-08-31 22:49:56 +02:00
|
|
|
d86f_prepare_track_layout(drive, side);
|
2016-09-01 18:52:23 +02:00
|
|
|
|
|
|
|
|
if (!d86f[drive].track_in_file)
|
|
|
|
|
{
|
|
|
|
|
/* Track is absent from the file, let's add it. */
|
2016-09-04 03:50:06 +02:00
|
|
|
d86f[drive].track_offset[d86f[drive].cur_track] = d86f[drive].file_size;
|
2016-09-05 21:58:28 +02:00
|
|
|
d86f[drive].file_size += store_size + flag_bytes;
|
2016-09-01 18:52:23 +02:00
|
|
|
if (d86f_get_sides(drive) == 2)
|
|
|
|
|
{
|
2016-09-05 21:58:28 +02:00
|
|
|
d86f[drive].file_size += store_size;
|
2016-09-01 18:52:23 +02:00
|
|
|
}
|
|
|
|
|
d86f[drive].track_in_file = 1;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].state = STATE_FORMAT_FIND;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
|
|
|
|
|
2016-08-31 22:49:56 +02:00
|
|
|
void d86f_stop(int drive)
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].state = STATE_IDLE;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
|
|
|
|
|
2016-08-31 22:49:56 +02:00
|
|
|
static void index_pulse(int drive)
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
if (d86f[drive].state != STATE_IDLE) fdc_indexpulse();
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int d86f_match(int drive)
|
|
|
|
|
{
|
|
|
|
|
int temp;
|
2016-09-03 18:07:46 +02:00
|
|
|
temp = (d86f[drive].req_sector.dword == d86f[drive].last_sector.dword);
|
2016-08-31 22:49:56 +02:00
|
|
|
return temp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t d86f_get_data_len(int drive)
|
|
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
if (d86f[drive].req_sector.id.n)
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
return (128 << ((uint32_t) d86f[drive].req_sector.id.n));
|
2016-08-31 22:49:56 +02:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (fdc_get_dtl() < 128)
|
|
|
|
|
{
|
|
|
|
|
return fdc_get_dtl();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
return (128 << ((uint32_t) d86f[drive].req_sector.id.n));
|
2016-08-31 22:49:56 +02:00
|
|
|
}
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int d86f_can_read_address(int drive)
|
|
|
|
|
{
|
|
|
|
|
int temp;
|
2016-09-04 19:37:08 +02:00
|
|
|
temp = (fdc_get_bitcell_period() == d86f_get_bitcell_period(drive));
|
2016-08-20 03:40:12 +02:00
|
|
|
temp = temp && fdd_can_read_medium(drive ^ fdd_swap);
|
2016-08-31 22:49:56 +02:00
|
|
|
temp = temp && (fdc_is_mfm() == d86f_is_mfm(drive));
|
2016-08-20 03:40:12 +02:00
|
|
|
return temp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int d86f_can_format(int drive)
|
|
|
|
|
{
|
|
|
|
|
int temp;
|
|
|
|
|
temp = !writeprot[drive];
|
|
|
|
|
temp = temp && !swwp;
|
2016-08-31 22:49:56 +02:00
|
|
|
temp = temp && fdd_can_read_medium(drive ^ fdd_swap);
|
2016-09-04 19:37:08 +02:00
|
|
|
temp = temp & d86f_valid_bit_rate(drive);
|
2016-08-20 03:40:12 +02:00
|
|
|
return temp;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
int d86f_find_state_nf(int drive)
|
|
|
|
|
{
|
|
|
|
|
int temp;
|
|
|
|
|
temp = (d86f[drive].state == STATE_READ_FIND_SECTOR);
|
|
|
|
|
temp = temp || (d86f[drive].state == STATE_READ_FIND_FIRST_SECTOR);
|
|
|
|
|
temp = temp || (d86f[drive].state == STATE_READ_FIND_NEXT_SECTOR);
|
|
|
|
|
temp = temp || (d86f[drive].state == STATE_WRITE_FIND_SECTOR);
|
|
|
|
|
temp = temp || (d86f[drive].state == STATE_READ_FIND_ADDRESS);
|
|
|
|
|
return temp;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-20 03:40:12 +02:00
|
|
|
int d86f_find_state(int drive)
|
|
|
|
|
{
|
|
|
|
|
int temp;
|
2016-09-03 18:07:46 +02:00
|
|
|
temp = d86f_find_state_nf(drive);
|
|
|
|
|
temp = temp || (d86f[drive].state == STATE_FORMAT_FIND);
|
2016-08-20 03:40:12 +02:00
|
|
|
return temp;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
int d86f_read_state_data(int drive)
|
2016-08-31 22:49:56 +02:00
|
|
|
{
|
|
|
|
|
int temp;
|
2016-09-03 18:07:46 +02:00
|
|
|
temp = (d86f[drive].state == STATE_READ_SECTOR);
|
|
|
|
|
temp = temp || (d86f[drive].state == STATE_READ_FIRST_SECTOR);
|
|
|
|
|
temp = temp || (d86f[drive].state == STATE_READ_NEXT_SECTOR);
|
2016-08-31 22:49:56 +02:00
|
|
|
return temp;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
int d86f_read_state_crc(int drive)
|
|
|
|
|
{
|
|
|
|
|
int temp;
|
|
|
|
|
temp = (d86f[drive].state == STATE_READ_SECTOR_CRC);
|
|
|
|
|
temp = temp || (d86f[drive].state == STATE_READ_FIRST_SECTOR_CRC);
|
|
|
|
|
temp = temp || (d86f[drive].state == STATE_READ_NEXT_SECTOR_CRC);
|
|
|
|
|
return temp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int d86f_read_state_gap3(int drive)
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
|
|
|
|
int temp;
|
2016-09-03 18:07:46 +02:00
|
|
|
temp = (d86f[drive].state == STATE_READ_SECTOR_GAP3);
|
|
|
|
|
temp = temp || (d86f[drive].state == STATE_READ_FIRST_SECTOR_GAP3);
|
|
|
|
|
temp = temp || (d86f[drive].state == STATE_READ_NEXT_SECTOR_GAP3);
|
2016-08-20 03:40:12 +02:00
|
|
|
return temp;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
int d86f_write_state(int drive)
|
|
|
|
|
{
|
|
|
|
|
int temp;
|
|
|
|
|
temp = (d86f[drive].state == STATE_WRITE_SECTOR);
|
|
|
|
|
temp = temp || (d86f[drive].state == STATE_WRITE_SECTOR_CRC);
|
|
|
|
|
temp = temp || (d86f[drive].state == STATE_WRITE_SECTOR_GAP3);
|
|
|
|
|
return temp;
|
|
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
int d86f_read_state(int drive)
|
|
|
|
|
{
|
|
|
|
|
int temp;
|
|
|
|
|
temp = d86f_read_state_data(drive);
|
|
|
|
|
temp = temp || d86f_read_state_crc(drive);
|
|
|
|
|
temp = temp || d86f_read_state_gap3(drive);
|
|
|
|
|
return temp;
|
|
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
|
|
|
|
|
int d86f_data_size(int drive)
|
|
|
|
|
{
|
|
|
|
|
int temp;
|
2016-09-03 18:07:46 +02:00
|
|
|
temp = d86f[drive].req_sector.id.n;
|
2016-08-31 22:49:56 +02:00
|
|
|
temp = 128 << temp;
|
|
|
|
|
return temp;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
void d86f_poll_write_crc(int drive, int side)
|
2016-08-31 22:49:56 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
if (d86f[drive].state != STATE_FORMAT) return;
|
|
|
|
|
d86f[drive].id_pos = d86f[drive].track_pos - d86f[drive].section_pos;
|
|
|
|
|
if (d86f[drive].id_pos)
|
|
|
|
|
{
|
|
|
|
|
d86f[drive].track_data[side][d86f[drive].track_pos] = d86f[drive].calc_crc.bytes[1];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
d86f[drive].track_data[side][d86f[drive].track_pos] = d86f[drive].calc_crc.bytes[0];
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
void d86f_poll_advancebyte(int drive, int side)
|
|
|
|
|
{
|
|
|
|
|
d86f[drive].old_track_byte = d86f[drive].track_byte;
|
|
|
|
|
d86f[drive].old_track_index = d86f[drive].track_index;
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].track_pos++;
|
|
|
|
|
d86f[drive].track_pos %= d86f_get_raw_size(drive);
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].track_byte = d86f[drive].track_layout[side][d86f[drive].track_pos] & ~BYTE_INDEX_HOLE;
|
|
|
|
|
d86f[drive].track_index = d86f[drive].track_layout[side][d86f[drive].track_pos] & BYTE_INDEX_HOLE;
|
|
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
void d86f_poll_reset(int drive, int side)
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].state = STATE_IDLE;
|
|
|
|
|
d86f[drive].index_count = 0;
|
|
|
|
|
d86f_poll_advancebyte(drive, side);
|
|
|
|
|
}
|
2016-08-20 03:40:12 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
int d86f_poll_check_notfound(int drive)
|
|
|
|
|
{
|
|
|
|
|
if (d86f[drive].index_count > 1)
|
|
|
|
|
{
|
|
|
|
|
/* The index hole has been hit twice and we're still in a find state.
|
|
|
|
|
This means sector finding has failed for whatever reason.
|
|
|
|
|
Abort with sector not found and set state to idle. */
|
2016-09-04 19:37:08 +02:00
|
|
|
// pclog("d86f_poll(): Sector not found (%i %i %i %i) (%i, %i)\n", d86f[drive].req_sector.id.c, d86f[drive].req_sector.id.h, d86f[drive].req_sector.id.r, d86f[drive].req_sector.id.n, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive));
|
2016-09-03 18:07:46 +02:00
|
|
|
fdc_notfound();
|
|
|
|
|
d86f[drive].state = STATE_IDLE;
|
|
|
|
|
d86f[drive].index_count = 0;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
void d86f_poll_finish(int drive, int side)
|
|
|
|
|
{
|
|
|
|
|
d86f_poll_reset(drive, side);
|
|
|
|
|
d86f_poll_advancebyte(drive, side);
|
|
|
|
|
d86f[drive].last_sector.dword = 0xFFFFFFFF;
|
|
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
void d86f_poll_readwrite(int drive, int side)
|
|
|
|
|
{
|
|
|
|
|
int data;
|
|
|
|
|
uint16_t max_len;
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
if (d86f_read_state_data(drive))
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
max_len = d86f_data_size(drive);
|
|
|
|
|
if (d86f[drive].datac < d86f_get_data_len(drive))
|
|
|
|
|
{
|
|
|
|
|
fdc_data(d86f[drive].track_data[side][d86f[drive].track_pos]);
|
|
|
|
|
}
|
|
|
|
|
d86f_calccrc(drive, d86f[drive].track_data[side][d86f[drive].track_pos]);
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
2016-09-03 18:07:46 +02:00
|
|
|
else if (d86f[drive].state == STATE_WRITE_SECTOR)
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
max_len = d86f_data_size(drive);
|
|
|
|
|
if (d86f[drive].datac < d86f_get_data_len(drive))
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
data = fdc_getdata(d86f[drive].datac == ((128 << ((uint32_t) d86f[drive].last_sector.id.n)) - 1));
|
|
|
|
|
if (data == -1)
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
data = 0;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
2016-09-03 18:07:46 +02:00
|
|
|
else
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
data = 0;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
2016-09-03 18:07:46 +02:00
|
|
|
if (!disable_write)
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].track_data[side][d86f[drive].track_pos] = data;
|
|
|
|
|
d86f[drive].track_layout[side][d86f[drive].track_pos] = BYTE_DATA;
|
|
|
|
|
if (!d86f[drive].track_pos) d86f[drive].track_layout[side][d86f[drive].track_pos] |= BYTE_INDEX_HOLE;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f_calccrc(drive, d86f[drive].track_data[side][d86f[drive].track_pos]);
|
|
|
|
|
}
|
|
|
|
|
else if (d86f_read_state_crc(drive))
|
|
|
|
|
{
|
|
|
|
|
max_len = 2;
|
|
|
|
|
d86f[drive].track_crc.bytes[d86f[drive].datac] = d86f[drive].track_data[side][d86f[drive].track_pos];
|
|
|
|
|
}
|
|
|
|
|
else if (d86f[drive].state == STATE_WRITE_SECTOR_CRC)
|
|
|
|
|
{
|
|
|
|
|
max_len = 2;
|
|
|
|
|
if (!disable_write)
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].track_data[side][d86f[drive].track_pos] = d86f[drive].calc_crc.bytes[d86f[drive].datac];
|
|
|
|
|
d86f[drive].track_layout[side][d86f[drive].track_pos] = BYTE_DATA_CRC;
|
|
|
|
|
if (!d86f[drive].track_pos) d86f[drive].track_layout[side][d86f[drive].track_pos] |= BYTE_INDEX_HOLE;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
2016-09-03 18:07:46 +02:00
|
|
|
else if (d86f_read_state_gap3(drive))
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
max_len = fdc_get_gap();
|
|
|
|
|
if (d86f[drive].datac == (fdc_get_gap() - 1))
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f_poll_finish(drive, side);
|
|
|
|
|
if (d86f[drive].track_crc.word != d86f[drive].calc_crc.word)
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
fdc_finishread();
|
|
|
|
|
fdc_datacrcerror();
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
2016-09-03 18:07:46 +02:00
|
|
|
else
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
fdc_sector_finishread();
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
2016-09-03 18:07:46 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (d86f[drive].state == STATE_WRITE_SECTOR_GAP3)
|
|
|
|
|
{
|
|
|
|
|
max_len = fdc_get_gap();
|
|
|
|
|
if (d86f[drive].datac == (fdc_get_gap() - 1))
|
|
|
|
|
{
|
2016-09-04 03:50:06 +02:00
|
|
|
if (!disable_write) d86f_writeback(drive);
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f_poll_finish(drive, side);
|
|
|
|
|
fdc_sector_finishread(drive);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2016-08-31 22:49:56 +02:00
|
|
|
if (!disable_write)
|
|
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].track_data[side][d86f[drive].track_pos] = fdc_is_mfm() ? 0x4E : 0xFF;
|
|
|
|
|
d86f[drive].track_layout[side][d86f[drive].track_pos] = BYTE_GAP3;
|
|
|
|
|
if (!d86f[drive].track_pos) d86f[drive].track_layout[side][d86f[drive].track_pos] |= BYTE_INDEX_HOLE;
|
2016-08-31 22:49:56 +02:00
|
|
|
}
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
2016-09-03 18:07:46 +02:00
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].datac++;
|
|
|
|
|
d86f_poll_advancebyte(drive, side);
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
if (d86f[drive].datac >= max_len)
|
|
|
|
|
{
|
|
|
|
|
d86f[drive].datac = 0;
|
|
|
|
|
d86f[drive].state++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void d86f_poll_find_nf(int drive, int side)
|
|
|
|
|
{
|
|
|
|
|
if (d86f[drive].track_index)
|
|
|
|
|
{
|
|
|
|
|
// pclog("d86f_poll_find_nf(): Index pulse\n");
|
|
|
|
|
index_pulse(drive);
|
|
|
|
|
d86f[drive].index_count++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch(d86f[drive].track_byte)
|
|
|
|
|
{
|
|
|
|
|
case BYTE_IDAM:
|
|
|
|
|
d86f[drive].calc_crc.word = fdc_is_mfm() ? 0xcdb4 : 0xffff;
|
|
|
|
|
// pclog("CRC reset: %02X\n", d86f[drive].track_byte);
|
|
|
|
|
d86f_calccrc(drive, d86f[drive].track_data[side][d86f[drive].track_pos]);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case BYTE_DATAAM:
|
|
|
|
|
d86f[drive].calc_crc.word = fdc_is_mfm() ? 0xcdb4 : 0xffff;
|
|
|
|
|
// pclog("CRC reset: %02X\n", d86f[drive].track_byte);
|
|
|
|
|
|
|
|
|
|
if ((d86f[drive].state &= STATE_WRITE_FIND_SECTOR) && d86f_match(drive) && d86f_can_read_address(drive))
|
2016-08-31 22:49:56 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].track_data[side][d86f[drive].track_pos] = 0xFB;
|
2016-08-31 22:49:56 +02:00
|
|
|
}
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f_calccrc(drive, d86f[drive].track_data[side][d86f[drive].track_pos]);
|
|
|
|
|
break;
|
|
|
|
|
case BYTE_ID:
|
|
|
|
|
d86f[drive].id_pos = d86f[drive].track_pos - d86f[drive].section_pos;
|
|
|
|
|
d86f[drive].rw_sector_id.byte_array[d86f[drive].id_pos] = d86f[drive].track_data[side][d86f[drive].track_pos];
|
|
|
|
|
d86f_calccrc(drive, d86f[drive].track_data[side][d86f[drive].track_pos]);
|
|
|
|
|
break;
|
|
|
|
|
case BYTE_ID_CRC:
|
|
|
|
|
d86f[drive].id_pos = d86f[drive].track_pos - d86f[drive].section_pos;
|
|
|
|
|
d86f[drive].track_crc.bytes[d86f[drive].id_pos] = d86f[drive].track_data[side][d86f[drive].track_pos];
|
|
|
|
|
break;
|
|
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f_poll_advancebyte(drive, side);
|
|
|
|
|
|
|
|
|
|
if (d86f_poll_check_notfound(drive)) return;
|
|
|
|
|
|
|
|
|
|
if (d86f[drive].track_byte != d86f[drive].old_track_byte)
|
|
|
|
|
{
|
|
|
|
|
d86f[drive].section_pos = d86f[drive].track_pos;
|
|
|
|
|
|
|
|
|
|
switch(d86f[drive].track_byte)
|
|
|
|
|
{
|
|
|
|
|
case BYTE_GAP2:
|
|
|
|
|
if (d86f_can_read_address(drive))
|
2016-08-31 22:49:56 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
if (d86f_match(drive) || (d86f[drive].state == STATE_READ_FIND_ADDRESS))
|
|
|
|
|
{
|
|
|
|
|
if (d86f[drive].track_crc.word != d86f[drive].calc_crc.word)
|
|
|
|
|
{
|
|
|
|
|
// pclog("d86f_poll(): Header CRC error (%i %i %i %i)\n", d86f[drive].req_sector.id.c, d86f[drive].req_sector.id.h, d86f[drive].req_sector.id.r, d86f[drive].req_sector.id.n);
|
|
|
|
|
fdc_finishread();
|
|
|
|
|
fdc_headercrcerror();
|
|
|
|
|
d86f[drive].state = STATE_IDLE;
|
|
|
|
|
d86f[drive].index_count = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
}
|
|
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].last_sector.dword = d86f[drive].rw_sector_id.dword;
|
|
|
|
|
// pclog("Read sector ID in find state: %i %i %i %i (sought: %i, %i, %i, %i)\n", d86f[drive].last_sector.id.c, d86f[drive].last_sector.id.h, d86f[drive].last_sector.id.r, d86f[drive].last_sector.id.n, d86f[drive].req_sector.id.c, d86f[drive].req_sector.id.h, d86f[drive].req_sector.id.r, d86f[drive].req_sector.id.n);
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
if ((d86f[drive].state == STATE_READ_FIND_ADDRESS) && d86f_can_read_address(drive))
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
// pclog("Reading sector ID...\n");
|
|
|
|
|
fdc_sectorid(d86f[drive].last_sector.id.c, d86f[drive].last_sector.id.h, d86f[drive].last_sector.id.r, d86f[drive].last_sector.id.n, 0, 0);
|
|
|
|
|
d86f[drive].state = STATE_IDLE;
|
|
|
|
|
d86f[drive].index_count = 0;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
2016-09-03 18:07:46 +02:00
|
|
|
break;
|
|
|
|
|
case BYTE_DATA:
|
|
|
|
|
d86f[drive].datac = 0;
|
|
|
|
|
switch (d86f[drive].state)
|
|
|
|
|
{
|
|
|
|
|
case STATE_READ_FIND_SECTOR:
|
|
|
|
|
case STATE_WRITE_FIND_SECTOR:
|
|
|
|
|
if (d86f_match(drive) && d86f_can_read_address(drive))
|
|
|
|
|
{
|
|
|
|
|
d86f[drive].state++;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case STATE_READ_FIND_FIRST_SECTOR:
|
|
|
|
|
case STATE_READ_FIND_NEXT_SECTOR:
|
|
|
|
|
if (d86f_can_read_address(drive))
|
|
|
|
|
{
|
|
|
|
|
d86f[drive].state++;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2016-08-31 22:49:56 +02:00
|
|
|
}
|
2016-09-03 18:07:46 +02:00
|
|
|
}
|
|
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
void d86f_poll_find_format(int drive, int side)
|
|
|
|
|
{
|
|
|
|
|
if (!(d86f_can_format(drive)))
|
|
|
|
|
{
|
|
|
|
|
if (d86f_can_read_address(drive))
|
2016-08-31 22:49:56 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
// pclog("d86f_poll(): Disk is write protected or attempting to format wrong number of sectors per track\n");
|
|
|
|
|
fdc_writeprotect();
|
2016-08-31 22:49:56 +02:00
|
|
|
}
|
2016-09-03 18:07:46 +02:00
|
|
|
else
|
2016-08-31 22:49:56 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
// pclog("d86f_poll(): Unable to format at the requested density or bitcell period\n");
|
|
|
|
|
fdc_notfound();
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f_poll_reset(drive, side);
|
|
|
|
|
d86f_poll_advancebyte(drive, side);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (d86f[drive].track_index && d86f_can_read_address(drive))
|
|
|
|
|
{
|
|
|
|
|
// pclog("Index hole hit, formatting track...\n");
|
|
|
|
|
d86f[drive].state = STATE_FORMAT;
|
|
|
|
|
d86f_poll_advancebyte(drive, side);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
d86f_poll_advancebyte(drive, side);
|
|
|
|
|
|
|
|
|
|
if (d86f_poll_check_notfound(drive)) return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void d86f_poll_format(int drive, int side)
|
|
|
|
|
{
|
|
|
|
|
int data;
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
if (d86f[drive].track_index)
|
|
|
|
|
{
|
|
|
|
|
// pclog("Index hole hit again, format finished\n");
|
|
|
|
|
d86f[drive].state = STATE_IDLE;
|
2016-09-04 03:50:06 +02:00
|
|
|
if (!disable_write) d86f_writeback(drive);
|
2016-09-03 18:07:46 +02:00
|
|
|
fdc_sector_finishread(drive);
|
|
|
|
|
d86f[drive].index_count = 0;
|
|
|
|
|
d86f_poll_advancebyte(drive, side);
|
|
|
|
|
return;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
switch(d86f[drive].track_byte)
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-08-31 22:49:56 +02:00
|
|
|
case BYTE_GAP0:
|
|
|
|
|
case BYTE_GAP1:
|
|
|
|
|
case BYTE_GAP2:
|
|
|
|
|
case BYTE_GAP3:
|
|
|
|
|
case BYTE_GAP4:
|
2016-09-03 18:07:46 +02:00
|
|
|
if (!disable_write) d86f[drive].track_data[side][d86f[drive].track_pos] = fdc_is_mfm() ? 0x4E : 0xFF;
|
2016-08-31 22:49:56 +02:00
|
|
|
break;
|
|
|
|
|
case BYTE_IAM_SYNC:
|
2016-09-03 18:07:46 +02:00
|
|
|
if (!disable_write) d86f[drive].track_data[side][d86f[drive].track_pos] = 0xC2;
|
2016-08-31 22:49:56 +02:00
|
|
|
break;
|
|
|
|
|
case BYTE_IAM:
|
2016-09-03 18:07:46 +02:00
|
|
|
if (!disable_write) d86f[drive].track_data[side][d86f[drive].track_pos] = 0xFC;
|
2016-08-31 22:49:56 +02:00
|
|
|
break;
|
|
|
|
|
case BYTE_ID_SYNC:
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].id_pos = d86f[drive].track_pos - d86f[drive].section_pos;
|
|
|
|
|
if (!disable_write) d86f[drive].track_data[side][d86f[drive].track_pos] = 0;
|
|
|
|
|
if (d86f[drive].id_pos > 3) break;
|
|
|
|
|
data = fdc_getdata(0);
|
|
|
|
|
if ((data == -1) && (d86f[drive].id_pos < 3))
|
2016-08-31 22:49:56 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
data = 0;
|
|
|
|
|
}
|
|
|
|
|
d86f[drive].format_sector_id.byte_array[d86f[drive].id_pos] = data & 0xff;
|
|
|
|
|
d86f_calccrc(drive, d86f[drive].format_sector_id.byte_array[d86f[drive].id_pos]);
|
|
|
|
|
// pclog("format_sector_id[%i] = %i\n", cur_id_pos, d86f[drive].format_sector_id.byte_array[d86f[drive].id_pos]);
|
|
|
|
|
if (d86f[drive].id_pos == 3)
|
|
|
|
|
{
|
|
|
|
|
fdc_stop_id_request();
|
|
|
|
|
// pclog("Formatting sector: %08X...\n", d86f[drive].format_sector_id.dword);
|
2016-08-31 22:49:56 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case BYTE_I_SYNC:
|
|
|
|
|
case BYTE_DATA_SYNC:
|
2016-09-03 18:07:46 +02:00
|
|
|
if (!disable_write) d86f[drive].track_data[side][d86f[drive].track_pos] = 0;
|
2016-08-31 22:49:56 +02:00
|
|
|
break;
|
|
|
|
|
case BYTE_IDAM_SYNC:
|
|
|
|
|
case BYTE_DATAAM_SYNC:
|
2016-09-03 18:07:46 +02:00
|
|
|
if (!disable_write) d86f[drive].track_data[side][d86f[drive].track_pos] = 0xA1;
|
2016-08-31 22:49:56 +02:00
|
|
|
break;
|
|
|
|
|
case BYTE_IDAM:
|
|
|
|
|
case BYTE_DATAAM:
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].calc_crc.word = fdc_is_mfm() ? 0xcdb4 : 0xffff;
|
|
|
|
|
// pclog("CRC reset: %02X\n", d86f[drive].track_byte);
|
|
|
|
|
|
|
|
|
|
if (!disable_write) d86f[drive].track_data[side][d86f[drive].track_pos] = (d86f[drive].track_byte == BYTE_IDAM) ? 0xFE : 0xFB;
|
|
|
|
|
d86f_calccrc(drive, d86f[drive].track_data[side][d86f[drive].track_pos]);
|
2016-08-31 22:49:56 +02:00
|
|
|
break;
|
|
|
|
|
case BYTE_ID:
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].id_pos = d86f[drive].track_pos - d86f[drive].section_pos;
|
|
|
|
|
if (!disable_write)
|
2016-08-31 22:49:56 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].track_data[side][d86f[drive].track_pos] = d86f[drive].format_sector_id.byte_array[d86f[drive].id_pos];
|
2016-08-31 22:49:56 +02:00
|
|
|
}
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f_calccrc(drive, d86f[drive].track_data[side][d86f[drive].track_pos]);
|
2016-08-31 22:49:56 +02:00
|
|
|
break;
|
|
|
|
|
case BYTE_DATA:
|
2016-09-03 18:07:46 +02:00
|
|
|
if (!disable_write)
|
2016-08-31 22:49:56 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].track_data[side][d86f[drive].track_pos] = d86f[drive].fill;
|
|
|
|
|
d86f_calccrc(drive, d86f[drive].fill);
|
2016-08-31 22:49:56 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case BYTE_ID_CRC:
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f_poll_write_crc(drive, side);
|
2016-08-31 22:49:56 +02:00
|
|
|
break;
|
|
|
|
|
case BYTE_DATA_CRC:
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f[drive].id_pos = d86f[drive].track_pos - d86f[drive].section_pos;
|
|
|
|
|
d86f_poll_write_crc(drive, side);
|
2016-08-31 22:49:56 +02:00
|
|
|
break;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f_poll_advancebyte(drive, side);
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
if (d86f[drive].track_byte != d86f[drive].old_track_byte)
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
// pclog("Track byte: %02X, old: %02X\n", track_byte, old_track_byte);
|
|
|
|
|
d86f[drive].section_pos = d86f[drive].track_pos;
|
|
|
|
|
|
|
|
|
|
switch(d86f[drive].track_byte & ~BYTE_INDEX_HOLE)
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
case BYTE_ID_SYNC:
|
|
|
|
|
// pclog("Requesting next sector ID...\n");
|
|
|
|
|
fdc_request_next_sector_id();
|
|
|
|
|
break;
|
|
|
|
|
case BYTE_GAP2:
|
|
|
|
|
d86f[drive].last_sector.dword = d86f[drive].format_sector_id.dword;
|
|
|
|
|
break;
|
|
|
|
|
case BYTE_DATA:
|
|
|
|
|
d86f[drive].datac = 0;
|
|
|
|
|
break;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
2016-09-03 18:07:46 +02:00
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
void d86f_poll()
|
|
|
|
|
{
|
|
|
|
|
int drive = d86f_drive;
|
2016-09-05 20:53:46 +02:00
|
|
|
int side = fdd_get_head(drive);
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
if (d86f[drive].state == STATE_FORMAT)
|
2016-08-20 03:40:12 +02:00
|
|
|
{
|
2016-09-03 18:07:46 +02:00
|
|
|
d86f_poll_format(drive, side);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
if (d86f[drive].state == STATE_FORMAT_FIND)
|
|
|
|
|
{
|
|
|
|
|
d86f_poll_find_format(drive, side);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
if (d86f_find_state_nf(drive))
|
|
|
|
|
{
|
|
|
|
|
d86f_poll_find_nf(drive, side);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
if (d86f_read_state(drive) || d86f_write_state(drive))
|
|
|
|
|
{
|
|
|
|
|
d86f_poll_readwrite(drive, side);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2016-08-31 22:49:56 +02:00
|
|
|
|
2016-09-03 18:07:46 +02:00
|
|
|
if ((d86f[drive].state == STATE_SEEK) || (d86f[drive].state == STATE_IDLE))
|
|
|
|
|
{
|
|
|
|
|
d86f_poll_advancebyte(drive, side);
|
|
|
|
|
return;
|
2016-08-20 03:40:12 +02:00
|
|
|
}
|
|
|
|
|
}
|