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-08-20 03:40:12 +02:00
# include "fdd.h"
# define MAX_SECTORS 256
typedef struct
{
uint8_t c , h , r , n ;
int rate ;
uint8_t * data ;
} sector_t ;
static sector_t d86f_data [ 2 ] [ 2 ] [ MAX_SECTORS ] ;
static int d86f_count [ 2 ] [ 2 ] ;
2016-08-31 22:49:56 +02:00
int d86f_cur_track_pos [ 2 ] = { 0 , 0 } ;
2016-08-20 03:40:12 +02:00
enum
{
STATE_IDLE ,
STATE_READ_FIND_SECTOR ,
STATE_READ_SECTOR ,
STATE_READ_FIND_FIRST_SECTOR ,
STATE_READ_FIRST_SECTOR ,
STATE_READ_FIND_NEXT_SECTOR ,
STATE_READ_NEXT_SECTOR ,
STATE_WRITE_FIND_SECTOR ,
STATE_WRITE_SECTOR ,
STATE_READ_FIND_ADDRESS ,
STATE_READ_ADDRESS ,
STATE_FORMAT_FIND ,
STATE_FORMAT ,
STATE_SEEK
} ;
static int d86f_state [ 2 ] = { 0 , 0 } ;
static int d86f_track [ 2 ] = { 0 , 0 } ;
static int d86f_side [ 2 ] = { 0 , 0 } ;
static int d86f_drive ;
static int d86f_sector [ 2 ] = { 0 , 0 } ;
static int d86f_n [ 2 ] = { 0 , 0 } ;
static uint8_t d86f_fill [ 2 ] = { 0 , 0 } ;
2016-08-31 22:49:56 +02:00
static int cur_sector [ 2 ] /*, cur_byte[2]*/ ;
2016-08-20 03:40:12 +02:00
static int index_count [ 2 ] ;
2016-08-31 22:49:56 +02:00
static int format_sector_count [ 2 ] = { 0 , 0 } ;
2016-08-20 03:40:12 +02:00
static struct
{
FILE * f ;
2016-08-31 22:49:56 +02:00
uint8_t disk_flags ;
uint8_t track_data [ 2 ] [ 25000 ] ;
uint8_t track_layout [ 2 ] [ 25000 ] ;
uint8_t track_flags ;
uint8_t track_in_file ;
uint32_t track_pos [ 256 ] ;
uint16_t raw_track_size ;
2016-09-01 18:52:23 +02:00
uint32_t file_size ;
2016-08-20 03:40:12 +02:00
} d86f [ 2 ] ;
/* Needed for formatting! */
int d86f_realtrack ( int drive , int track )
{
2016-08-31 22:49:56 +02:00
if ( ! ( d86f [ drive ] . track_flags & 0x40 ) & & fdd_doublestep_40 ( drive ) )
2016-08-20 03:40:12 +02:00
track / = 2 ;
return track ;
}
void d86f_writeback ( int drive , int track ) ;
2016-08-31 22:49:56 +02:00
static uint16_t CRCTable [ 256 ] ;
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 ;
}
}
typedef union {
uint16_t word ;
uint8_t bytes [ 2 ] ;
} crc_t ;
static crc_t crc [ 2 ] ;
static void d86f_calccrc ( int drive , uint8_t byte )
{
crc [ drive ] . word = ( crc [ drive ] . word < < 8 ) ^ CRCTable [ ( crc [ drive ] . word > > 8 ) ^ byte ] ;
}
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
}
void d86f_load ( int drive , char * fn )
{
uint32_t magic = 0 ;
uint32_t len = 0 ;
uint16_t version = 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 ;
}
fread ( & version , 2 , 1 , d86f [ drive ] . f ) ;
if ( version ! = 0x0100 )
{
2016-08-31 22:49:56 +02:00
/* File is not of a recognized format version abort. */
pclog ( " 86F: Unrecognized file version: %04X \n " , version ) ;
2016-08-20 03:40:12 +02:00
fclose ( d86f [ drive ] . f ) ;
return ;
}
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-08-31 22:49:56 +02:00
fread ( d86f [ drive ] . track_pos , 1 , 1024 , d86f [ drive ] . f ) ;
2016-08-20 03:40:12 +02:00
2016-08-31 22:49:56 +02:00
if ( ! ( d86f [ drive ] . track_pos [ 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. */
fseek ( d86f [ drive ] . f , d86f [ drive ] . track_pos [ 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-08-31 22:49:56 +02:00
double d86f_byteperiod ( int drive )
2016-08-20 03:40:12 +02:00
{
2016-08-31 22:49:56 +02:00
switch ( d86f [ drive ] . track_flags & 0x0f )
2016-08-20 03:40:12 +02:00
{
2016-08-31 22:49:56 +02:00
case 0x02 : /* 125 kbps, FM */
if ( ! ( d86f [ drive ] . track_flags & 0x20 ) )
{
/* 300 rpm, 125 kbps = 360 rpm, 150 kbps; so we do this trick for 360 rpm-only drives to accept them. */
return ( ( fdd_get_type ( drive ) & 3 ) = = 2 ) ? ( 320.0 / 6.0 ) : 64.0 ;
}
return 64.0 ;
case 0x01 : /* 150 kbps, FM */
if ( d86f [ drive ] . track_flags & 0x20 )
{
/* 360 rpm, 150 kbps = 300 rpm, 125 kbps; so we do this trick for 300 rpm-only drives to accept them. */
return ( ( fdd_get_type ( drive ) & 3 ) = = 1 ) ? 64.0 : ( 320.0 / 6.0 ) ;
}
return 320.0 / 6.0 ;
case 0x0A : /* 250 kbps, MFM */
case 0x00 : /* 250 kbps, FM */
if ( ! ( d86f [ drive ] . track_flags & 0x20 ) )
{
/* 300 rpm, 250 kbps = 360 rpm, 300 kbps; so we do this trick for 360 rpm-only drives to accept them. */
return ( ( fdd_get_type ( drive ) & 3 ) = = 2 ) ? ( 160.0 / 6.0 ) : 32.0 ;
}
return 32.0 ;
case 0x09 : /* 300 kbps, MFM */
if ( d86f [ drive ] . track_flags & 0x20 )
{
/* 360 rpm, 300 kbps = 300 rpm, 250 kbps; so we do this trick for 300 rpm-only drives to accept them. */
return ( ( fdd_get_type ( drive ) & 3 ) = = 1 ) ? 32.0 : ( 160.0 / 6.0 ) ;
}
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
char track_layout [ 2 ] [ 2 ] [ 25512 ] ;
int id_positions [ 2 ] [ 2 ] [ MAX_SECTORS ] ;
/* 0 = MFM, 1 = FM, 2 = MFM perpendicular, 3 = reserved */
/* 4 = ISO, 0 = IBM */
int d86f_media_type = 0 ;
/* Bits 0-3 define byte type, bit 5 defines whether it is a per-track (0) or per-sector (1) byte, if bit 7 is set, the byte is the index hole. */
# define BYTE_GAP0 0x00
# define BYTE_GAP1 0x10
# define BYTE_GAP4 0x20
# define BYTE_GAP2 0x40
# define BYTE_GAP3 0x50
# define BYTE_I_SYNC 0x01
# define BYTE_ID_SYNC 0x41
# define BYTE_DATA_SYNC 0x51
# define BYTE_IAM_SYNC 0x02
# define BYTE_IDAM_SYNC 0x42
# define BYTE_DATAAM_SYNC 0x52
# define BYTE_IAM 0x03
# define BYTE_IDAM 0x43
# define BYTE_DATAAM 0x53
# define BYTE_ID 0x44
# define BYTE_DATA 0x54
# define BYTE_ID_CRC 0x45
# define BYTE_DATA_CRC 0x55
# define BYTE_INDEX_HOLE 0x80 /* 1 = index hole, 0 = regular byte */
# define BYTE_IS_SECTOR 0x40 /* 1 = per-sector, 0 = per-track */
# define BYTE_IS_POST_TRACK 0x20 /* 1 = after all sectors, 0 = before or during all sectors */
# define BYTE_IS_DATA 0x10 /* 1 = data, 0 = id */
# define BYTE_TYPE 0x0F /* 5 = crc, 4 = data, 3 = address mark, 2 = address mark sync, 1 = sync, 0 = gap */
# define BYTE_TYPE_GAP 0x00
# define BYTE_TYPE_SYNC 0x01
# define BYTE_TYPE_AM_SYNC 0x02
# define BYTE_TYPE_AM 0x03
# define BYTE_TYPE_DATA 0x04
# define BYTE_TYPE_CRC 0x05
int d86f_get_sides ( int drive )
{
return ( d86f [ drive ] . disk_flags & 8 ) ? 2 : 1 ;
}
int d86f_is_40_track ( int drive )
{
return ! ( d86f [ drive ] . disk_flags & 1 ) ;
}
int d86f_is_mfm ( int drive )
{
return ( d86f [ drive ] . track_flags & 8 ) ? 1 : 0 ;
}
uint16_t d86f_get_raw_size ( int drive )
{
double rate = 0.0 ;
int mfm = d86f_is_mfm ( drive ) ;
double rpm = ( d86f [ drive ] . track_flags & 0x20 ) ? 360.0 : 300.0 ;
double size = 6250.0 ;
switch ( d86f [ drive ] . track_flags & 7 )
{
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-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-08-31 22:49:56 +02:00
memset ( d86f [ drive ] . track_layout [ 0 ] , BYTE_GAP4 , 25000 ) ;
memset ( d86f [ drive ] . track_data [ 0 ] , 0xFF , 25000 ) ;
2016-08-20 03:40:12 +02:00
2016-08-31 22:49:56 +02:00
if ( d86f_get_sides ( drive ) = = 2 )
2016-08-20 03:40:12 +02:00
{
2016-08-31 22:49:56 +02:00
memset ( d86f [ drive ] . track_layout [ 1 ] , BYTE_GAP4 , 25000 ) ;
memset ( d86f [ drive ] . track_data [ 1 ] , 0xFF , 25000 ) ;
2016-08-20 03:40:12 +02:00
}
2016-08-31 22:49:56 +02:00
if ( ! ( d86f [ drive ] . track_pos [ track ] ) )
{
/* Track does not exist in the image, initialize it as unformatted. */
d86f [ drive ] . track_in_file = 0 ;
d86f [ drive ] . track_flags = 0x0A ; /* 300 rpm, MFM, 250 kbps */
d86f [ drive ] . raw_track_size = 6250 ;
return ;
2016-08-20 03:40:12 +02:00
}
2016-08-31 22:49:56 +02:00
d86f [ drive ] . track_in_file = 1 ;
fseek ( d86f [ drive ] . f , d86f [ drive ] . track_pos [ track ] , SEEK_SET ) ;
fread ( & ( d86f [ drive ] . track_flags ) , 1 , 1 , d86f [ drive ] . f ) ;
d86f [ drive ] . raw_track_size = d86f_get_raw_size ( drive ) ;
fseek ( d86f [ drive ] . f , d86f [ drive ] . track_pos [ track ] + 2 , SEEK_SET ) ;
fread ( d86f [ drive ] . track_layout [ 0 ] , 1 , d86f [ drive ] . raw_track_size , d86f [ drive ] . f ) ;
fseek ( d86f [ drive ] . f , d86f [ drive ] . track_pos [ track ] + 25002 , SEEK_SET ) ;
fread ( d86f [ drive ] . track_data [ 0 ] , 1 , d86f [ drive ] . raw_track_size , d86f [ drive ] . f ) ;
if ( d86f_get_sides ( drive ) = = 2 )
2016-08-20 03:40:12 +02:00
{
2016-08-31 22:49:56 +02:00
fseek ( d86f [ drive ] . f , d86f [ drive ] . track_pos [ track ] + 50002 , SEEK_SET ) ;
fread ( d86f [ drive ] . track_layout [ 1 ] , 1 , d86f [ drive ] . raw_track_size , d86f [ drive ] . f ) ;
fseek ( d86f [ drive ] . f , d86f [ drive ] . track_pos [ track ] + 75002 , SEEK_SET ) ;
fread ( d86f [ drive ] . track_data [ 1 ] , 1 , d86f [ drive ] . raw_track_size , d86f [ drive ] . f ) ;
2016-08-20 03:40:12 +02:00
}
}
void d86f_writeback ( int drive , int track )
{
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-08-31 22:49:56 +02:00
fseek ( d86f [ drive ] . f , d86f [ drive ] . track_pos [ track ] , SEEK_SET ) ;
fwrite ( & ( d86f [ drive ] . track_flags ) , 1 , 1 , d86f [ drive ] . f ) ;
fseek ( d86f [ drive ] . f , d86f [ drive ] . track_pos [ track ] + 2 , SEEK_SET ) ;
fwrite ( d86f [ drive ] . track_layout [ 0 ] , 1 , d86f [ drive ] . raw_track_size , d86f [ drive ] . f ) ;
fseek ( d86f [ drive ] . f , d86f [ drive ] . track_pos [ track ] + 25002 , SEEK_SET ) ;
fwrite ( d86f [ drive ] . track_data [ 0 ] , 1 , d86f [ drive ] . raw_track_size , d86f [ drive ] . f ) ;
if ( d86f_get_sides ( drive ) = = 2 )
{
fseek ( d86f [ drive ] . f , d86f [ drive ] . track_pos [ track ] + 50002 , SEEK_SET ) ;
fwrite ( d86f [ drive ] . track_layout [ 1 ] , 1 , d86f [ drive ] . raw_track_size , d86f [ drive ] . f ) ;
fseek ( d86f [ drive ] . f , d86f [ drive ] . track_pos [ track ] + 75002 , SEEK_SET ) ;
fwrite ( d86f [ drive ] . track_data [ 1 ] , 1 , d86f [ drive ] . raw_track_size , d86f [ drive ] . f ) ;
}
2016-08-20 03:40:12 +02:00
}
void d86f_reset ( int drive , int side )
{
d86f_count [ drive ] [ side ] = 0 ;
if ( side = = 0 )
{
2016-08-31 22:49:56 +02:00
index_count [ drive ] = 0 ;
2016-08-20 03:40:12 +02:00
d86f_state [ drive ] = STATE_SEEK ;
}
}
static int get_bitcell_period ( int drive )
{
2016-08-31 22:49:56 +02:00
double rate = 0.0 ;
int mfm = ( d86f [ drive ] . track_flags & 8 ) ? 1 : 0 ;
double rpm = ( d86f [ drive ] . track_flags & 0x20 ) ? 360.0 : 300.0 ;
double size = 8000.0 ;
switch ( d86f [ drive ] . track_flags & 7 )
{
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-08-31 22:49:56 +02:00
// pclog("d86f_readsector: fdc_period=%i img_period=%i rate=%i sector=%i track=%i side=%i\n", fdc_get_bitcell_period(), get_bitcell_period(drive), rate, sector, track, side);
2016-08-20 03:40:12 +02:00
d86f_track [ drive ] = track ;
d86f_side [ drive ] = side ;
2016-08-31 22:49:56 +02:00
if ( side & & ( d86f_get_sides ( drive ) = = 1 ) )
{
fdc_notfound ( ) ;
d86f_state [ drive ] = STATE_IDLE ;
index_count [ drive ] = 0 ;
return ;
}
2016-08-20 03:40:12 +02:00
d86f_drive = drive ;
d86f_sector [ drive ] = sector ;
d86f_n [ drive ] = sector_size ;
2016-08-31 22:49:56 +02:00
index_count [ drive ] = 0 ;
2016-08-20 03:40:12 +02:00
if ( sector = = SECTOR_FIRST )
d86f_state [ drive ] = STATE_READ_FIND_FIRST_SECTOR ;
else if ( sector = = SECTOR_NEXT )
d86f_state [ drive ] = STATE_READ_FIND_NEXT_SECTOR ;
else
d86f_state [ drive ] = STATE_READ_FIND_SECTOR ;
}
void d86f_writesector ( int drive , int sector , int track , int side , int rate , int sector_size )
{
2016-08-31 22:49:56 +02:00
// pclog("d86f_writesector: fdc_period=%i img_period=%i rate=%i\n", fdc_get_bitcell_period(), get_bitcell_period(drive), rate);
2016-08-20 03:40:12 +02:00
d86f_track [ drive ] = track ;
d86f_side [ drive ] = side ;
2016-08-31 22:49:56 +02:00
if ( side & & ( d86f_get_sides ( drive ) = = 1 ) )
{
fdc_notfound ( ) ;
d86f_state [ drive ] = STATE_IDLE ;
index_count [ drive ] = 0 ;
return ;
}
2016-08-20 03:40:12 +02:00
d86f_drive = drive ;
d86f_sector [ drive ] = sector ;
d86f_n [ drive ] = sector_size ;
2016-08-31 22:49:56 +02:00
index_count [ drive ] = 0 ;
2016-08-20 03:40:12 +02:00
d86f_state [ drive ] = STATE_WRITE_FIND_SECTOR ;
}
void d86f_readaddress ( int drive , int track , int side , int rate )
{
2016-08-31 22:49:56 +02:00
// pclog("d86f_readaddress: fdc_period=%i img_period=%i rate=%i track=%i side=%i\n", fdc_get_bitcell_period(), get_bitcell_period(drive), rate, track, side);
2016-08-20 03:40:12 +02:00
d86f_track [ drive ] = track ;
d86f_side [ drive ] = side ;
2016-08-31 22:49:56 +02:00
if ( side & & ( d86f_get_sides ( drive ) = = 1 ) )
{
fdc_notfound ( ) ;
d86f_state [ drive ] = STATE_IDLE ;
index_count [ drive ] = 0 ;
return ;
}
2016-08-20 03:40:12 +02:00
2016-08-31 22:49:56 +02:00
d86f_drive = drive ;
index_count [ drive ] = 0 ;
d86f_state [ drive ] = STATE_READ_FIND_ADDRESS ;
2016-08-20 03:40:12 +02:00
}
2016-08-31 22:49:56 +02:00
int d86f_is_iso ( int drive )
2016-08-20 03:40:12 +02:00
{
2016-08-31 22:49:56 +02:00
return 0 ; /* Currently, we always use the IBM format, not ISO. */
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 ( ) ;
memset ( d86f [ drive ] . track_layout [ side ] , BYTE_GAP4 , d86f_get_raw_size ( drive ) ) ;
2016-08-20 03:40:12 +02:00
i = 0 ;
2016-08-31 22:49:56 +02:00
if ( ! ( d86f_is_iso ( 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_GAP0 , real_gap0_len ) ;
i + = real_gap0_len ;
memset ( d86f [ drive ] . track_layout [ side ] + i , BYTE_I_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_IAM_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_IAM , 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_GAP1 , real_gap1_len ) ;
2016-08-20 03:40:12 +02:00
i + = real_gap1_len ;
}
else
{
2016-08-31 22:49:56 +02:00
memset ( d86f [ drive ] . track_layout [ side ] + i , BYTE_GAP1 , real_gap1_len ) ;
i + = real_gap1_len ;
2016-08-20 03:40:12 +02:00
}
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 )
{
d86f_track [ drive ] = track ;
d86f_side [ drive ] = 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 ( ) ;
d86f_state [ drive ] = STATE_IDLE ;
index_count [ drive ] = 0 ;
return ;
}
2016-08-20 03:40:12 +02:00
2016-09-01 18:52:23 +02:00
if ( ( track < 0 ) | | ( track > 256 ) )
{
fdc_writeprotect ( ) ;
d86f_state [ drive ] = STATE_IDLE ;
index_count [ drive ] = 0 ;
return ;
}
2016-08-31 22:49:56 +02:00
d86f_drive = drive ;
d86f_fill [ drive ] = fill ;
index_count [ drive ] = 0 ;
/* 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 ;
memset ( d86f [ drive ] . track_data [ side ] , 0xFF , 25000 ) ;
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. */
d86f [ drive ] . track_pos [ track ] = d86f [ drive ] . file_size ;
d86f [ drive ] . file_size + = ( 2 + 50000 ) ;
if ( d86f_get_sides ( drive ) = = 2 )
{
d86f [ drive ] . file_size + = 50000 ;
}
d86f [ drive ] . track_in_file = 1 ;
}
2016-08-31 22:49:56 +02:00
d86f_state [ drive ] = STATE_FORMAT_FIND ;
format_sector_count [ drive ] = 0 ;
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-08-31 22:49:56 +02:00
d86f_state [ drive ] = 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-08-31 22:49:56 +02:00
if ( d86f_state [ drive ] ! = STATE_IDLE ) fdc_indexpulse ( ) ;
2016-08-20 03:40:12 +02:00
}
2016-08-31 22:49:56 +02:00
typedef struct {
uint8_t c ;
uint8_t h ;
uint8_t r ;
uint8_t n ;
} sector_data_t ;
sector_data_t last_sector [ 2 ] ;
2016-08-20 03:40:12 +02:00
int d86f_match ( int drive )
{
int temp ;
2016-08-31 22:49:56 +02:00
temp = ( d86f_track [ drive ] = = last_sector [ drive ] . c ) ;
temp = temp & & ( d86f_side [ drive ] = = last_sector [ drive ] . h ) ;
temp = temp & & ( d86f_sector [ drive ] = = last_sector [ drive ] . r ) ;
temp = temp & & ( d86f_n [ drive ] = = last_sector [ drive ] . n ) ;
return temp ;
}
uint32_t d86f_get_data_len ( int drive )
{
2016-08-20 03:40:12 +02:00
if ( d86f_n [ drive ] )
{
2016-08-31 22:49:56 +02:00
return ( 128 < < ( ( uint32_t ) d86f_n [ drive ] ) ) ;
}
else
{
if ( fdc_get_dtl ( ) < 128 )
{
return fdc_get_dtl ( ) ;
}
else
{
return ( 128 < < ( ( uint32_t ) d86f_n [ drive ] ) ) ;
}
2016-08-20 03:40:12 +02:00
}
}
int d86f_can_read_address ( int drive )
{
int temp ;
temp = ( fdc_get_bitcell_period ( ) = = get_bitcell_period ( drive ) ) ;
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-08-20 03:40:12 +02:00
return temp ;
}
int d86f_find_state ( int drive )
{
int temp ;
temp = ( d86f_state [ drive ] = = STATE_READ_FIND_SECTOR ) ;
temp = temp | | ( d86f_state [ drive ] = = STATE_READ_FIND_FIRST_SECTOR ) ;
temp = temp | | ( d86f_state [ drive ] = = STATE_READ_FIND_NEXT_SECTOR ) ;
temp = temp | | ( d86f_state [ drive ] = = STATE_WRITE_FIND_SECTOR ) ;
temp = temp | | ( d86f_state [ drive ] = = STATE_READ_FIND_ADDRESS ) ;
temp = temp | | ( d86f_state [ drive ] = = STATE_FORMAT_FIND ) ;
return temp ;
}
2016-08-31 22:49:56 +02:00
int d86f_find_state_nf ( int drive )
{
int temp ;
temp = ( d86f_state [ drive ] = = STATE_READ_FIND_SECTOR ) ;
temp = temp | | ( d86f_state [ drive ] = = STATE_READ_FIND_FIRST_SECTOR ) ;
temp = temp | | ( d86f_state [ drive ] = = STATE_READ_FIND_NEXT_SECTOR ) ;
temp = temp | | ( d86f_state [ drive ] = = STATE_WRITE_FIND_SECTOR ) ;
temp = temp | | ( d86f_state [ drive ] = = STATE_READ_FIND_ADDRESS ) ;
return temp ;
}
2016-08-20 03:40:12 +02:00
int d86f_read_state ( int drive )
{
int temp ;
temp = ( d86f_state [ drive ] = = STATE_READ_SECTOR ) ;
temp = temp | | ( d86f_state [ drive ] = = STATE_READ_FIRST_SECTOR ) ;
temp = temp | | ( d86f_state [ drive ] = = STATE_READ_NEXT_SECTOR ) ;
return temp ;
}
2016-08-31 22:49:56 +02:00
int d86f_section_pos [ 2 ] = { 0 , 0 } ;
int data_pos [ 2 ] = { 0 , 0 } ;
int d86f_data_size ( int drive )
{
int temp ;
temp = d86f_n [ drive ] ;
temp = 128 < < temp ;
return temp ;
}
typedef union
{
uint32_t dword ;
uint8_t byte_array [ 4 ] ;
} sector_id ;
sector_id format_sector_id [ 2 ] ;
sector_id rw_sector_id [ 2 ] ;
crc_t crc_bytes [ 2 ] ;
static uint32_t datac [ 2 ] = { 0 , 0 } ;
2016-08-20 03:40:12 +02:00
void d86f_poll ( )
{
sector_t * s ;
int data ;
int drive = d86f_drive ;
int side = d86f_side [ drive ] ;
int found_sector = 0 ;
int b = 0 ;
2016-08-31 22:49:56 +02:00
int cur_id_pos = 0 ;
int cur_gap3_pos = 0 ;
uint8_t track_byte = 0 ;
uint8_t track_index = 0 ;
uint8_t track_sector = 0 ;
uint8_t track_byte_type = 0 ;
uint8_t old_track_byte = 0 ;
uint8_t old_track_index = 0 ;
uint8_t old_track_sector = 0 ;
uint8_t old_track_byte_type = 0 ;
if ( ( d86f_state [ drive ] = = STATE_SEEK ) | | ( d86f_state [ drive ] = = STATE_IDLE ) )
2016-08-20 03:40:12 +02:00
{
2016-08-31 22:49:56 +02:00
d86f_cur_track_pos [ drive ] + + ;
d86f_cur_track_pos [ drive ] % = d86f_get_raw_size ( drive ) ;
2016-08-20 03:40:12 +02:00
return ;
}
if ( d86f_state [ drive ] = = STATE_FORMAT_FIND )
{
if ( ! ( d86f_can_format ( drive ) ) )
{
if ( d86f_can_read_address ( drive ) )
{
2016-08-31 22:49:56 +02:00
// pclog("d86f_poll(): Disk is write protected or attempting to format wrong number of sectors per track\n");
2016-08-20 03:40:12 +02:00
fdc_writeprotect ( ) ;
}
else
{
2016-08-31 22:49:56 +02:00
// pclog("d86f_poll(): Unable to format at the requested density or bitcell period\n");
2016-08-20 03:40:12 +02:00
fdc_notfound ( ) ;
}
d86f_state [ drive ] = STATE_IDLE ;
2016-08-31 22:49:56 +02:00
index_count [ drive ] = 0 ;
d86f_cur_track_pos [ drive ] + + ;
d86f_cur_track_pos [ drive ] % = d86f_get_raw_size ( drive ) ;
2016-08-20 03:40:12 +02:00
return ;
}
}
2016-08-31 22:49:56 +02:00
track_byte = d86f [ drive ] . track_layout [ side ] [ d86f_cur_track_pos [ drive ] ] ;
track_index = track_byte & BYTE_INDEX_HOLE ;
track_sector = track_byte & BYTE_IS_SECTOR ;
track_byte_type = track_byte & BYTE_TYPE ;
if ( track_index )
2016-08-20 03:40:12 +02:00
{
2016-08-31 22:49:56 +02:00
if ( d86f_state [ drive ] ! = STATE_IDLE )
2016-08-20 03:40:12 +02:00
{
2016-08-31 22:49:56 +02:00
index_pulse ( drive ) ;
index_count [ drive ] + + ;
2016-08-20 03:40:12 +02:00
}
2016-08-31 22:49:56 +02:00
if ( d86f_state [ drive ] = = STATE_FORMAT )
2016-08-20 03:40:12 +02:00
{
2016-08-31 22:49:56 +02:00
// pclog("Index hole hit again, format finished\n");
d86f_state [ drive ] = STATE_IDLE ;
if ( ! disable_write ) d86f_writeback ( drive , d86f_track [ drive ] ) ;
fdc_sector_finishread ( drive ) ;
2016-08-20 03:40:12 +02:00
}
2016-08-31 22:49:56 +02:00
if ( ( d86f_state [ drive ] = = STATE_FORMAT_FIND ) & & d86f_can_read_address ( drive ) )
2016-08-20 03:40:12 +02:00
{
2016-08-31 22:49:56 +02:00
// pclog("Index hole hit, formatting track...\n");
d86f_state [ drive ] = STATE_FORMAT ;
2016-08-20 03:40:12 +02:00
}
}
2016-08-31 22:49:56 +02:00
if ( d86f_read_state ( drive ) | | ( d86f_state [ drive ] = = STATE_WRITE_SECTOR ) )
2016-08-20 03:40:12 +02:00
{
2016-08-31 22:49:56 +02:00
/* For the first (data size) bytes, send to the FDC or receive from the FDC and write. */
if ( d86f_read_state ( drive ) & & ( datac [ drive ] < d86f_data_size ( drive ) ) )
2016-08-20 03:40:12 +02:00
{
2016-08-31 22:49:56 +02:00
if ( fdc_data ( d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] ) )
2016-08-20 03:40:12 +02:00
{
/* Data failed to be sent to the FDC, abort. */
2016-08-31 22:49:56 +02:00
// pclog("d86f_poll(): Unable to send further data to the FDC\n");
2016-08-20 03:40:12 +02:00
d86f_state [ drive ] = STATE_IDLE ;
2016-08-31 22:49:56 +02:00
index_count [ drive ] = 0 ;
d86f_cur_track_pos [ drive ] + + ;
d86f_cur_track_pos [ drive ] % = d86f_get_raw_size ( drive ) ;
2016-08-20 03:40:12 +02:00
return ;
}
}
2016-08-31 22:49:56 +02:00
if ( ( d86f_state [ drive ] = = STATE_WRITE_SECTOR ) & & ( datac [ drive ] < d86f_data_size ( drive ) ) )
2016-08-20 03:40:12 +02:00
{
2016-08-31 22:49:56 +02:00
data = fdc_getdata ( datac [ drive ] = = ( ( 128 < < ( ( uint32_t ) last_sector [ drive ] . n ) ) - 1 ) ) ;
if ( data = = - 1 )
2016-08-20 03:40:12 +02:00
{
/* Data failed to be sent from the FDC, abort. */
2016-08-31 22:49:56 +02:00
// pclog("d86f_poll(): Unable to receive further data from the FDC\n");
2016-08-20 03:40:12 +02:00
d86f_state [ drive ] = STATE_IDLE ;
2016-08-31 22:49:56 +02:00
index_count [ drive ] = 0 ;
d86f_cur_track_pos [ drive ] + + ;
d86f_cur_track_pos [ drive ] % = d86f_get_raw_size ( drive ) ;
2016-08-20 03:40:12 +02:00
return ;
}
2016-08-31 22:49:56 +02:00
if ( ! disable_write )
{
d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] = data ;
d86f [ drive ] . track_layout [ side ] [ d86f_cur_track_pos [ drive ] ] = BYTE_DATA ;
if ( ! d86f_cur_track_pos [ drive ] ) d86f [ drive ] . track_layout [ side ] [ d86f_cur_track_pos [ drive ] ] | = BYTE_INDEX_HOLE ;
}
2016-08-20 03:40:12 +02:00
}
2016-08-31 22:49:56 +02:00
if ( datac [ drive ] < d86f_data_size ( drive ) )
2016-08-20 03:40:12 +02:00
{
2016-08-31 22:49:56 +02:00
d86f_calccrc ( drive , d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] ) ;
2016-08-20 03:40:12 +02:00
}
2016-08-31 22:49:56 +02:00
if ( datac [ drive ] = = d86f_data_size ( drive ) )
2016-08-20 03:40:12 +02:00
{
2016-08-31 22:49:56 +02:00
if ( d86f_read_state ( drive ) )
{
crc_bytes [ drive ] . bytes [ 0 ] = d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] ;
}
if ( d86f_state [ drive ] = = STATE_WRITE_SECTOR )
{
if ( ! disable_write )
{
d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] = crc [ drive ] . bytes [ 0 ] ;
d86f [ drive ] . track_layout [ side ] [ d86f_cur_track_pos [ drive ] ] = BYTE_DATA_CRC ;
if ( ! d86f_cur_track_pos [ drive ] ) d86f [ drive ] . track_layout [ side ] [ d86f_cur_track_pos [ drive ] ] | = BYTE_INDEX_HOLE ;
}
}
2016-08-20 03:40:12 +02:00
}
2016-08-31 22:49:56 +02:00
if ( datac [ drive ] = = ( d86f_data_size ( drive ) + 1 ) )
2016-08-20 03:40:12 +02:00
{
2016-08-31 22:49:56 +02:00
if ( d86f_read_state ( drive ) )
2016-08-20 03:40:12 +02:00
{
2016-08-31 22:49:56 +02:00
crc_bytes [ drive ] . bytes [ 1 ] = d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] ;
}
if ( d86f_state [ drive ] = = STATE_WRITE_SECTOR )
{
if ( ! disable_write )
2016-08-20 03:40:12 +02:00
{
2016-08-31 22:49:56 +02:00
d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] = crc [ drive ] . bytes [ 1 ] ;
d86f [ drive ] . track_layout [ side ] [ d86f_cur_track_pos [ drive ] ] = BYTE_DATA_CRC ;
if ( ! d86f_cur_track_pos [ drive ] ) d86f [ drive ] . track_layout [ side ] [ d86f_cur_track_pos [ drive ] ] | = BYTE_INDEX_HOLE ;
2016-08-20 03:40:12 +02:00
}
2016-08-31 22:49:56 +02:00
}
}
if ( ( datac [ drive ] > ( d86f_data_size ( drive ) + 1 ) ) & & ( datac [ drive ] < = ( d86f_data_size ( drive ) + fdc_get_gap ( ) + 1 ) ) & & ( d86f_state [ drive ] = = STATE_WRITE_SECTOR ) & & ! disable_write )
{
d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] = fdc_is_mfm ( ) ? 0x4E : 0xFF ;
d86f [ drive ] . track_layout [ side ] [ d86f_cur_track_pos [ drive ] ] = BYTE_GAP3 ;
if ( ! d86f_cur_track_pos [ drive ] ) d86f [ drive ] . track_layout [ side ] [ d86f_cur_track_pos [ drive ] ] | = BYTE_INDEX_HOLE ;
}
/* At the last data of the FDC-specified gap length, compare the calculated CRC with the one we read and error out if mismatch, otherwise finish with success. */
if ( datac [ drive ] = = ( d86f_data_size ( drive ) + fdc_get_gap ( ) + 1 ) )
{
if ( d86f_read_state ( drive ) )
{
d86f_state [ drive ] = STATE_IDLE ;
if ( crc_bytes [ drive ] . word ! = crc [ drive ] . word )
2016-08-20 03:40:12 +02:00
{
2016-08-31 22:49:56 +02:00
// pclog("d86f_poll(): Data CRC error (%04X, %04X) (%i) (%04X)\n", crc_bytes[drive].word, crc[drive].word, d86f_data_size(drive), d86f_cur_track_pos[drive] - fdc_get_gap() - 1);
fdc_finishread ( ) ;
fdc_datacrcerror ( ) ;
2016-08-20 03:40:12 +02:00
}
2016-08-31 22:49:56 +02:00
else
2016-08-20 03:40:12 +02:00
{
2016-08-31 22:49:56 +02:00
fdc_sector_finishread ( ) ;
2016-08-20 03:40:12 +02:00
}
2016-08-31 22:49:56 +02:00
index_count [ drive ] = 0 ;
d86f_cur_track_pos [ drive ] + + ;
d86f_cur_track_pos [ drive ] % = d86f_get_raw_size ( drive ) ;
return ;
}
if ( d86f_state [ drive ] = = STATE_WRITE_SECTOR )
{
d86f_state [ drive ] = STATE_IDLE ;
if ( ! disable_write ) d86f_writeback ( drive , d86f_track [ drive ] ) ;
fdc_sector_finishread ( drive ) ;
index_count [ drive ] = 0 ;
d86f_cur_track_pos [ drive ] + + ;
d86f_cur_track_pos [ drive ] % = d86f_get_raw_size ( drive ) ;
return ;
2016-08-20 03:40:12 +02:00
}
}
2016-08-31 22:49:56 +02:00
datac [ drive ] + + ;
2016-08-20 03:40:12 +02:00
}
2016-08-31 22:49:56 +02:00
switch ( track_byte & ~ BYTE_INDEX_HOLE )
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 :
if ( ( d86f_state [ drive ] = = STATE_FORMAT ) & & ! disable_write ) d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] = fdc_is_mfm ( ) ? 0x4E : 0xFF ;
break ;
case BYTE_IAM_SYNC :
if ( ( d86f_state [ drive ] = = STATE_FORMAT ) & & ! disable_write ) d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] = 0xC2 ;
break ;
case BYTE_IAM :
if ( ( d86f_state [ drive ] = = STATE_FORMAT ) & & ! disable_write ) d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] = 0xFC ;
break ;
case BYTE_ID_SYNC :
if ( d86f_state [ drive ] = = STATE_FORMAT )
{
cur_id_pos = d86f_cur_track_pos [ drive ] - d86f_section_pos [ drive ] ;
if ( ! disable_write ) d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] = 0 ;
if ( cur_id_pos > 3 ) break ;
data = fdc_getdata ( 0 ) ;
if ( ( data = = - 1 ) & & ( cur_id_pos < 3 ) )
{
/* Data failed to be sent from the FDC, abort. */
// pclog("d86f_poll(): Unable to receive further data from the FDC\n");
d86f_state [ drive ] = STATE_IDLE ;
index_count [ drive ] = 0 ;
d86f_cur_track_pos [ drive ] + + ;
d86f_cur_track_pos [ drive ] % = d86f_get_raw_size ( drive ) ;
return ;
}
format_sector_id [ drive ] . byte_array [ cur_id_pos ] = data & 0xff ;
d86f_calccrc ( drive , format_sector_id [ drive ] . byte_array [ cur_id_pos ] ) ;
// pclog("format_sector_id[%i] = %i\n", cur_id_pos, format_sector_id[drive].byte_array[cur_id_pos]);
if ( cur_id_pos = = 3 )
{
fdc_stop_id_request ( ) ;
// pclog("Formatting sector: %08X...\n", format_sector_id[drive].dword);
}
}
break ;
case BYTE_I_SYNC :
case BYTE_DATA_SYNC :
if ( ( d86f_state [ drive ] = = STATE_FORMAT ) & & ! disable_write ) d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] = 0 ;
break ;
case BYTE_IDAM_SYNC :
case BYTE_DATAAM_SYNC :
if ( ( d86f_state [ drive ] = = STATE_FORMAT ) & & ! disable_write ) d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] = 0xA1 ;
break ;
case BYTE_IDAM :
case BYTE_DATAAM :
if ( d86f_find_state_nf ( drive ) | | ( d86f_state [ drive ] = = STATE_FORMAT ) ) crc [ drive ] . word = fdc_is_mfm ( ) ? 0xcdb4 : 0xffff ;
if ( ( d86f_state [ drive ] = = STATE_FORMAT ) & & ! disable_write ) d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] = ( track_byte = = BYTE_IDAM ) ? 0xFE : 0xFB ;
if ( d86f_state [ drive ] = = STATE_FORMAT ) d86f_calccrc ( drive , d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] ) ;
if ( d86f_find_state_nf ( drive ) & & ( ( d86f_state [ drive ] ! = STATE_WRITE_FIND_SECTOR ) | | ( ( track_byte & ~ BYTE_INDEX_HOLE ) = = BYTE_IDAM ) ) )
{
d86f_calccrc ( drive , d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] ) ;
}
break ;
case BYTE_ID :
cur_id_pos = d86f_cur_track_pos [ drive ] - d86f_section_pos [ drive ] ;
if ( ( d86f_state [ drive ] = = STATE_FORMAT ) & & ! disable_write )
{
d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] = format_sector_id [ drive ] . byte_array [ cur_id_pos ] ;
}
if ( d86f_find_state_nf ( drive ) )
{
rw_sector_id [ drive ] . byte_array [ cur_id_pos ] = d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] ;
}
if ( ( d86f_state [ drive ] = = STATE_FORMAT ) | | d86f_find_state_nf ( drive ) )
{
d86f_calccrc ( drive , d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] ) ;
}
break ;
case BYTE_DATA :
if ( ( d86f_state [ drive ] = = STATE_FORMAT ) & & ! disable_write )
{
d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] = d86f_fill [ drive ] ;
d86f_calccrc ( drive , d86f_fill [ drive ] ) ;
}
break ;
case BYTE_ID_CRC :
cur_id_pos = d86f_cur_track_pos [ drive ] - d86f_section_pos [ drive ] ;
if ( d86f_find_state_nf ( drive ) )
{
crc_bytes [ drive ] . bytes [ 0 ] = d86f [ drive ] . track_data [ side ] [ ( d86f_cur_track_pos [ drive ] - 1 ) % d86f_get_raw_size ( drive ) ] ;
crc_bytes [ drive ] . bytes [ 1 ] = d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] ;
}
if ( ( d86f_state [ drive ] = = STATE_FORMAT ) & & ! disable_write )
{
if ( cur_id_pos )
{
d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] = crc [ drive ] . bytes [ 1 ] ;
}
else
{
d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] = crc [ drive ] . bytes [ 0 ] ;
}
}
break ;
case BYTE_DATA_CRC :
cur_id_pos = d86f_cur_track_pos [ drive ] - d86f_section_pos [ drive ] ;
if ( ( d86f_state [ drive ] = = STATE_FORMAT ) & & ! disable_write )
{
if ( cur_id_pos )
{
d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] = crc [ drive ] . bytes [ 1 ] ;
}
else
{
d86f [ drive ] . track_data [ side ] [ d86f_cur_track_pos [ drive ] ] = crc [ drive ] . bytes [ 0 ] ;
}
}
break ;
2016-08-20 03:40:12 +02:00
}
2016-08-31 22:49:56 +02:00
old_track_byte = track_byte ;
old_track_index = track_index ;
old_track_sector = track_sector ;
old_track_byte_type = track_byte_type ;
d86f_cur_track_pos [ drive ] + + ;
d86f_cur_track_pos [ drive ] % = d86f_get_raw_size ( drive ) ;
track_byte = d86f [ drive ] . track_layout [ side ] [ d86f_cur_track_pos [ drive ] ] ;
track_index = track_byte & BYTE_INDEX_HOLE ;
track_sector = track_byte & BYTE_IS_SECTOR ;
track_byte_type = track_byte & BYTE_TYPE ;
2016-08-20 03:40:12 +02:00
if ( ( d86f_state [ drive ] ! = STATE_IDLE ) & & ( d86f_state [ drive ] ! = STATE_SEEK ) )
{
if ( index_count [ drive ] > 1 )
{
if ( d86f_find_state ( drive ) )
{
/* 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 . */
// pclog("d86f_poll(): Sector not found (%i %i %i %i)\n", d86f_track[drive], d86f_side[drive], d86f_sector[drive], d86f_n[drive]);
fdc_notfound ( ) ;
d86f_state [ drive ] = STATE_IDLE ;
2016-08-31 22:49:56 +02:00
index_count [ drive ] = 0 ;
2016-08-20 03:40:12 +02:00
return ;
}
}
}
2016-08-31 22:49:56 +02:00
if ( ( d86f_state [ drive ] = = STATE_IDLE ) | | ( d86f_state [ drive ] = = STATE_SEEK ) ) return ;
if ( track_byte ! = old_track_byte )
2016-08-20 03:40:12 +02:00
{
2016-08-31 22:49:56 +02:00
// if (d86f_state[drive] == STATE_FORMAT) pclog("Track byte: %02X, old: %02X\n", track_byte, old_track_byte);
d86f_section_pos [ drive ] = d86f_cur_track_pos [ drive ] ;
switch ( track_byte & ~ BYTE_INDEX_HOLE )
{
case BYTE_ID_SYNC :
if ( d86f_state [ drive ] = = STATE_FORMAT )
{
// pclog("Requesting next sector ID...\n");
fdc_request_next_sector_id ( ) ;
}
break ;
case BYTE_GAP2 :
if ( d86f_find_state_nf ( drive ) )
{
if ( d86f_match ( drive ) & & d86f_can_read_address ( drive ) )
{
if ( crc_bytes [ drive ] . word ! = crc [ drive ] . word )
{
// pclog("d86f_poll(): Header CRC error\n");
fdc_finishread ( ) ;
fdc_headercrcerror ( ) ;
d86f_state [ drive ] = STATE_IDLE ;
index_count [ drive ] = 0 ;
return ;
}
}
last_sector [ drive ] . c = rw_sector_id [ drive ] . byte_array [ 0 ] ;
last_sector [ drive ] . h = rw_sector_id [ drive ] . byte_array [ 1 ] ;
last_sector [ drive ] . r = rw_sector_id [ drive ] . byte_array [ 2 ] ;
last_sector [ drive ] . n = rw_sector_id [ drive ] . byte_array [ 3 ] ;
// pclog("Read sector ID in find state: %i %i %i %i (sought: %i, %i, %i, %i)\n", last_sector[drive].c, last_sector[drive].h, last_sector[drive].r, last_sector[drive].n, d86f_track[drive], d86f_side[drive], d86f_sector[drive], d86f_n[drive]);
}
if ( d86f_state [ drive ] = = STATE_FORMAT )
{
last_sector [ drive ] . c = format_sector_id [ drive ] . byte_array [ 0 ] ;
last_sector [ drive ] . h = format_sector_id [ drive ] . byte_array [ 1 ] ;
last_sector [ drive ] . r = format_sector_id [ drive ] . byte_array [ 2 ] ;
last_sector [ drive ] . n = format_sector_id [ drive ] . byte_array [ 3 ] ;
}
if ( ( d86f_state [ drive ] = = STATE_READ_FIND_ADDRESS ) & & d86f_can_read_address ( drive ) )
{
// pclog("Reading sector ID...\n");
fdc_sectorid ( last_sector [ drive ] . c , last_sector [ drive ] . h , last_sector [ drive ] . r , last_sector [ drive ] . n , 0 , 0 ) ;
d86f_state [ drive ] = STATE_IDLE ;
}
break ;
case BYTE_DATA :
if ( d86f_read_state ( drive ) | | ( d86f_state [ drive ] = = STATE_WRITE_SECTOR ) ) return ;
datac [ drive ] = 0 ;
switch ( d86f_state [ drive ] )
{
case STATE_READ_FIND_SECTOR :
if ( d86f_match ( drive ) & & d86f_can_read_address ( drive ) )
{
d86f_state [ drive ] = STATE_READ_SECTOR ;
}
break ;
case STATE_READ_FIND_FIRST_SECTOR :
if ( ( cur_sector [ drive ] = = 0 ) & & d86f_can_read_address ( drive ) ) d86f_state [ drive ] = STATE_READ_FIRST_SECTOR ;
break ;
case STATE_READ_FIND_NEXT_SECTOR :
if ( d86f_can_read_address ( drive ) ) d86f_state [ drive ] = STATE_READ_NEXT_SECTOR ;
break ;
case STATE_WRITE_FIND_SECTOR :
if ( d86f_match ( drive ) & & d86f_can_read_address ( drive ) )
{
if ( ! disable_write )
{
d86f [ drive ] . track_data [ side ] [ ( d86f_cur_track_pos [ drive ] - 1 ) % d86f_get_raw_size ( drive ) ] = 0xFB ;
}
d86f_calccrc ( drive , d86f [ drive ] . track_data [ side ] [ ( d86f_cur_track_pos [ drive ] - 1 ) % d86f_get_raw_size ( drive ) ] ) ;
d86f_state [ drive ] = STATE_WRITE_SECTOR ;
// pclog("Write start: %i %i %i %i, data size: %i (%i)\n", last_sector[drive].c, last_sector[drive].h, last_sector[drive].r, last_sector[drive].n, d86f_data_size(drive), d86f_n[drive]);
}
break ;
/* case STATE_FORMAT:
// pclog("Format: Starting sector fill...\n");
break ; */
}
break ;
}
2016-08-20 03:40:12 +02:00
}
}