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-07 20:59:08 +02:00
# include "disc_random.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 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-09-07 21:03:46 +02:00
uint16_t index_hole_pos [ 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 ;
2016-09-22 21:22:56 +02:00
uint32_t track_pos ;
uint32_t datac ;
uint32_t id_pos ;
uint32_t section_pos ;
2016-09-03 18:07:46 +02:00
crc_t calc_crc ;
crc_t track_crc ;
uint8_t track_byte ;
uint8_t track_index ;
2016-09-14 23:18:14 +02:00
uint8_t track_fuzzy ;
uint8_t track_data_byte ;
2016-09-03 18:07:46 +02:00
uint8_t old_track_byte ;
uint8_t old_track_index ;
2016-09-14 23:18:14 +02:00
uint8_t old_track_fuzzy ;
uint8_t old_track_data_byte ;
2016-09-04 03:50:06 +02:00
uint8_t cur_track ;
2016-09-07 20:59:08 +02:00
uint8_t side_flag_bytes ;
2016-09-22 21:22:56 +02:00
uint8_t wait_state ;
uint8_t id_am_counter ;
uint8_t id_counter ;
uint8_t id_match ;
uint8_t data_am_counter ;
2016-08-20 03:40:12 +02:00
} d86f [ 2 ] ;
2016-09-22 21:22:56 +02:00
uint8_t * d86f_track_data ( int drive , int side )
{
return d86f [ drive ] . track_data [ side ] ;
}
uint8_t * d86f_track_layout ( int drive , int side )
{
return d86f [ drive ] . track_layout [ side ] ;
}
uint8_t d86f_side_flags ( int drive ) ;
int d86f_is_mfm ( int drive ) ;
void d86f_writeback ( int drive ) ;
void d86f_set_sector ( int drive , int side , uint8_t c , uint8_t h , uint8_t r , uint8_t n ) ;
uint8_t d86f_poll_read_data ( int drive , int side , uint16_t pos ) ;
void d86f_poll_write_data ( int drive , int side , uint16_t pos , uint8_t data ) ;
int d86f_format_conditions ( int drive ) ;
uint8_t d86f_disk_flags ( int drive )
{
return d86f [ drive ] . disk_flags ;
}
uint8_t null_disk_flags ( int drive )
{
return 0x09 ;
}
uint8_t null_side_flags ( int drive )
{
return 0x0A ;
}
void null_writeback ( int drive )
{
return ;
}
void null_set_sector ( int drive , int side , uint8_t c , uint8_t h , uint8_t r , uint8_t n )
{
return ;
}
uint8_t null_poll_read_data ( int drive , int side , uint16_t pos )
{
return 0xf6 ;
}
void null_poll_write_data ( int drive , int side , uint16_t pos , uint8_t data )
{
return ;
}
int null_format_conditions ( int drive )
{
return 1 ;
}
void d86f_unregister ( int drive )
{
d86f_handler [ drive ] . disk_flags = null_disk_flags ;
d86f_handler [ drive ] . side_flags = null_side_flags ;
d86f_handler [ drive ] . writeback = null_writeback ;
d86f_handler [ drive ] . set_sector = null_set_sector ;
d86f_handler [ drive ] . read_data = null_poll_read_data ;
d86f_handler [ drive ] . write_data = null_poll_write_data ;
d86f_handler [ drive ] . format_conditions = null_format_conditions ;
d86f_handler [ drive ] . check_crc = 0 ;
d86f [ drive ] . version = 0x0063 ; /* Proxied formats report as version 0.99. */
}
void d86f_register_86f ( int drive )
{
d86f_handler [ drive ] . disk_flags = d86f_disk_flags ;
d86f_handler [ drive ] . side_flags = d86f_side_flags ;
d86f_handler [ drive ] . writeback = d86f_writeback ;
d86f_handler [ drive ] . set_sector = d86f_set_sector ;
d86f_handler [ drive ] . read_data = d86f_poll_read_data ;
d86f_handler [ drive ] . write_data = d86f_poll_write_data ;
d86f_handler [ drive ] . format_conditions = d86f_format_conditions ;
d86f_handler [ drive ] . check_crc = 1 ;
}
2016-08-20 03:40:12 +02:00
/* Needed for formatting! */
2016-09-04 03:50:06 +02:00
int d86f_is_40_track ( int drive )
{
2016-09-22 21:22:56 +02:00
return ( d86f_handler [ drive ] . disk_flags ( drive ) & 1 ) ? 0 : 1 ;
2016-09-04 03:50:06 +02:00
}
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 ;
}
}
2016-09-22 21:22:56 +02:00
void disc_calccrc ( int drive , uint8_t byte , crc_t * crc_var )
{
crc_var - > word = ( crc_var - > word < < 8 ) ^ CRCTable [ ( crc_var - > word > > 8 ) ^ byte ] ;
}
2016-08-31 22:49:56 +02:00
static void d86f_calccrc ( int drive , uint8_t byte )
{
2016-09-22 21:22:56 +02:00
// d86f[drive].calc_crc.word = (d86f[drive].calc_crc.word << 8) ^ CRCTable[(d86f[drive].calc_crc.word >> 8)^byte];
disc_calccrc ( drive , byte , & ( d86f [ drive ] . calc_crc ) ) ;
2016-08-31 22:49:56 +02:00
}
2016-08-20 03:40:12 +02:00
void d86f_init ( )
{
2016-09-07 20:59:08 +02:00
disc_random_init ( ) ;
2016-08-20 03:40:12 +02:00
memset ( d86f , 0 , sizeof ( d86f ) ) ;
2016-08-31 22:49:56 +02:00
d86f_setupcrc ( 0x1021 , 0xcdb4 ) ;
2016-09-22 21:22:56 +02:00
// d86f_unregister(0);
// d86f_unregister(1);
2016-08-20 03:40:12 +02:00
}
2016-09-05 21:58:28 +02:00
int d86f_get_sides ( int drive )
{
2016-09-22 21:22:56 +02:00
return ( d86f_handler [ drive ] . disk_flags ( drive ) & 8 ) ? 2 : 1 ;
}
int d86f_get_rpm_mode ( int drive )
{
if ( d86f [ drive ] . version ! = 0x0115 ) return 0 ;
return ( d86f_handler [ drive ] . disk_flags ( drive ) & 0x60 ) > > 5 ;
2016-09-05 21:58:28 +02:00
}
int d86f_get_array_size ( int drive )
{
2016-09-22 21:22:56 +02:00
int pos = 0 ;
int rm = 0 ;
rm = d86f_get_rpm_mode ( drive ) ;
2016-09-05 21:58:28 +02:00
switch ( d86f_hole ( drive ) )
{
case 0 :
2016-09-22 21:22:56 +02:00
default :
2016-09-05 21:58:28 +02:00
pos = 7500 ;
2016-09-22 21:22:56 +02:00
if ( d86f [ drive ] . version ! = 0x0115 ) return pos ;
switch ( rm )
{
case 1 :
pos = 7575 ;
break ;
case 2 :
pos = 7614 ;
break ;
case 3 :
pos = 7653 ;
break ;
default :
pos = 7500 ;
break ;
}
2016-09-05 21:58:28 +02:00
break ;
case 1 :
pos = 12500 ;
2016-09-22 21:22:56 +02:00
if ( d86f [ drive ] . version ! = 0x0115 ) return pos ;
switch ( rm )
{
case 1 :
pos = 12626 ;
break ;
case 2 :
pos = 12690 ;
break ;
case 3 :
pos = 12755 ;
break ;
default :
pos = 12500 ;
break ;
}
2016-09-05 21:58:28 +02:00
break ;
case 2 :
pos = 50000 ;
2016-09-22 21:22:56 +02:00
if ( d86f [ drive ] . version ! = 0x0115 ) return pos ;
switch ( rm )
{
case 1 :
pos = 50505 ;
break ;
case 2 :
pos = 50761 ;
break ;
case 3 :
pos = 51020 ;
break ;
default :
pos = 50000 ;
break ;
}
2016-09-05 21:58:28 +02:00
break ;
}
2016-09-07 00:40:29 +02:00
return pos ;
2016-09-05 21:58:28 +02:00
}
int d86f_valid_bit_rate ( int drive )
{
2016-09-22 21:22:56 +02:00
int rate = 0 ;
rate = fdc_get_bit_rate ( ) ;
2016-09-05 21:58:28 +02:00
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-09-22 21:22:56 +02:00
void d86f_common_handlers ( int drive )
{
drives [ drive ] . readsector = d86f_readsector ;
drives [ drive ] . writesector = d86f_writesector ;
drives [ drive ] . readaddress = d86f_readaddress ;
drives [ drive ] . hole = d86f_hole ;
drives [ drive ] . byteperiod = d86f_byteperiod ;
drives [ drive ] . poll = d86f_poll ;
drives [ drive ] . format = d86f_format ;
drives [ drive ] . realtrack = d86f_realtrack ;
drives [ drive ] . stop = d86f_stop ;
}
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-09-07 20:59:08 +02:00
uint8_t temp = 0 ;
2016-09-22 21:22:56 +02:00
d86f_unregister ( drive ) ;
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 ;
}
2016-09-22 21:22:56 +02:00
if ( ui_writeprot [ drive ] )
{
writeprot [ drive ] = 1 ;
}
2016-08-20 03:40:12 +02:00
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-22 21:22:56 +02:00
if ( ( d86f [ drive ] . version ! = 0x0100 ) & & ( d86f [ drive ] . version ! = 0x010A ) & & ( d86f [ drive ] . version ! = 0x0114 ) & & ( d86f [ drive ] . version ! = 0x0115 ) )
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-07 20:59:08 +02:00
d86f [ drive ] . side_flag_bytes = d86f_get_sides ( drive ) ;
2016-09-22 21:22:56 +02:00
if ( ( d86f [ drive ] . version = = 0x010A ) | | ( d86f [ drive ] . version = = 0x0114 ) | | ( d86f [ drive ] . version = = 0x0115 ) )
2016-09-05 21:58:28 +02:00
{
2016-09-07 20:59:08 +02:00
if ( ( d86f [ drive ] . version = = 0x010A ) & & ( d86f_get_sides ( drive ) = = 1 ) )
{
/* This is needed to detect the early variant of 86F version 1.10 images and handle it correctly. */
fseek ( d86f [ drive ] . f , d86f [ drive ] . track_offset [ 0 ] + 3 , SEEK_SET ) ;
fread ( & temp , 1 , 1 , d86f [ drive ] . f ) ;
if ( temp & 0x80 ) d86f [ drive ] . side_flag_bytes = 2 ;
}
2016-09-05 21:58:28 +02:00
fseek ( d86f [ drive ] . f , d86f [ drive ] . track_offset [ 0 ] , SEEK_SET ) ;
fread ( & ( d86f [ drive ] . side_flags [ 0 ] ) , 1 , 1 , d86f [ drive ] . f ) ;
2016-09-06 02:17:05 +02:00
if ( d86f_get_sides ( drive ) = = 2 )
{
fread ( & ( d86f [ drive ] . side_flags [ 1 ] ) , 1 , 1 , d86f [ drive ] . f ) ;
}
2016-09-05 21:58:28 +02:00
}
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-09-22 21:22:56 +02:00
d86f_register_86f ( drive ) ;
2016-08-20 03:40:12 +02:00
drives [ drive ] . seek = d86f_seek ;
2016-09-22 21:22:56 +02:00
d86f_common_handlers ( drive ) ;
2016-08-20 03:40:12 +02:00
}
int d86f_hole ( int drive )
{
2016-09-22 21:22:56 +02:00
return ( d86f_handler [ drive ] . disk_flags ( drive ) > > 1 ) & 3 ;
2016-08-20 03:40:12 +02:00
}
2016-09-22 21:22:56 +02:00
uint8_t d86f_side_flags ( int drive )
2016-09-05 21:58:28 +02:00
{
2016-09-22 21:22:56 +02:00
int side = 0 ;
side = fdd_get_head ( drive ) ;
if ( ( d86f [ drive ] . version = = 0x010A ) | | ( d86f [ drive ] . version = = 0x0114 ) | | ( d86f [ drive ] . version = = 0x0115 ) )
2016-09-05 21:58:28 +02:00
{
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-22 21:22:56 +02:00
uint8_t tf = 0 ;
uint8_t rr = 0 ;
uint8_t dr = 0 ;
tf = d86f_handler [ drive ] . side_flags ( drive ) ;
rr = tf & 0x27 ;
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 ;
2016-09-22 21:22:56 +02:00
int mfm = 0 ;
double rpm = 300.0 ;
double rpm_diff = 0.0 ;
2016-08-31 22:49:56 +02:00
double size = 6250.0 ;
2016-09-22 21:22:56 +02:00
mfm = d86f_is_mfm ( drive ) ;
rpm = ( d86f_track_flags ( drive ) & 0x20 ) ? 360.0 : 300.0 ;
rpm_diff = rpm * 0.005 ;
if ( d86f [ drive ] . version = = 0x0115 )
{
switch ( d86f_get_rpm_mode ( drive ) )
{
2016-09-22 22:48:31 +02:00
case 1 :
2016-09-22 21:22:56 +02:00
rpm_diff * = 2.0 ;
break ;
2016-09-22 22:48:31 +02:00
case 2 :
2016-09-22 21:22:56 +02:00
rpm_diff * = 3.0 ;
break ;
2016-09-22 22:48:31 +02:00
case 3 :
2016-09-22 21:22:56 +02:00
rpm_diff * = 4.0 ;
break ;
default :
rpm_diff = 0.0 ;
break ;
}
rpm - = rpm_diff ;
}
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 ;
2016-09-22 21:22:56 +02:00
default :
rate = 250.0 ;
break ;
2016-08-31 22:49:56 +02:00
}
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-09-22 21:22:56 +02:00
int sides ;
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 ;
2016-09-22 21:22:56 +02:00
sides = d86f_get_sides ( drive ) ;
if ( ( d86f [ drive ] . version = = 0x010A ) | | ( d86f [ drive ] . version = = 0x0114 ) | | ( d86f [ drive ] . version = = 0x0115 ) )
2016-09-05 21:58:28 +02:00
{
full_size = d86f_get_array_size ( drive ) ;
store_size = full_size < < 1 ;
2016-09-07 20:59:08 +02:00
if ( d86f [ drive ] . side_flag_bytes = = 2 ) flag_bytes + + ;
2016-09-22 21:22:56 +02:00
if ( ( d86f [ drive ] . version = = 0x0114 ) | | ( d86f [ drive ] . version = = 0x0115 ) ) flag_bytes + = 4 ;
2016-09-05 21:58:28 +02:00
}
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-06 23:52:08 +02:00
memset ( d86f [ drive ] . track_layout [ side ] , BYTE_GAP4 , 50000 ) ;
memset ( d86f [ drive ] . track_data [ side ] , 0xFF , 50000 ) ;
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-22 21:22:56 +02:00
if ( ( d86f [ drive ] . version = = 0x010A ) | | ( d86f [ drive ] . version = = 0x0114 ) | | ( d86f [ drive ] . version = = 0x0115 ) )
2016-09-05 21:58:28 +02:00
{
2016-09-07 00:40:29 +02:00
for ( side = 0 ; side < d86f_get_sides ( drive ) ; side + + )
2016-09-06 02:17:05 +02:00
{
2016-09-07 00:40:29 +02:00
d86f [ drive ] . side_flags [ side ] = 0x0A ; /* 300 rpm, MFM, 250 kbps */
2016-09-06 02:17:05 +02:00
}
2016-09-05 21:58:28 +02:00
}
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-22 21:22:56 +02:00
if ( ( d86f [ drive ] . version = = 0x010A ) | | ( d86f [ drive ] . version = = 0x0114 ) | | ( d86f [ drive ] . version = = 0x0115 ) )
2016-09-05 21:58:28 +02:00
{
2016-09-07 20:59:08 +02:00
for ( side = 0 ; side < d86f [ drive ] . side_flag_bytes ; side + + )
2016-09-06 02:17:05 +02:00
{
2016-09-07 00:40:29 +02:00
fread ( & ( d86f [ drive ] . side_flags [ side ] ) , 1 , 1 , d86f [ drive ] . f ) ;
2016-09-06 02:17:05 +02:00
}
2016-09-07 20:59:08 +02:00
2016-09-22 21:22:56 +02:00
if ( ( d86f [ drive ] . version = = 0x0114 ) | | ( d86f [ drive ] . version = = 0x0115 ) )
2016-09-07 20:59:08 +02:00
{
for ( side = 0 ; side < d86f [ drive ] . side_flag_bytes ; side + + )
{
fread ( & ( d86f [ drive ] . index_hole_pos [ side ] ) , 2 , 1 , d86f [ drive ] . f ) ;
}
}
2016-09-05 21:58:28 +02:00
}
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-07 20:59:08 +02:00
uint8_t track_id = 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 ;
2016-09-22 21:22:56 +02:00
if ( ( d86f [ drive ] . version = = 0x010A ) | | ( d86f [ drive ] . version = = 0x0114 ) | | ( d86f [ drive ] . version = = 0x0115 ) )
2016-09-05 21:58:28 +02:00
{
full_size = d86f_get_array_size ( drive ) ;
2016-09-07 20:59:08 +02:00
store_size = full_size < < 1 ;
if ( d86f [ drive ] . side_flag_bytes = = 2 ) flag_bytes + + ;
2016-09-22 21:22:56 +02:00
if ( ( d86f [ drive ] . version = = 0x0114 ) | | ( d86f [ drive ] . version = = 0x0115 ) ) flag_bytes + = 4 ;
2016-09-05 21:58:28 +02:00
}
2016-09-03 18:07:46 +02:00
2016-08-20 03:40:12 +02:00
if ( ! d86f [ drive ] . f )
2016-09-22 21:22:56 +02:00
{
2016-08-20 03:40:12 +02:00
return ;
2016-09-22 21:22:56 +02:00
}
2016-08-20 03:40:12 +02:00
2016-08-31 22:49:56 +02:00
if ( ! d86f [ drive ] . track_in_file )
2016-09-22 21:22:56 +02:00
{
2016-08-20 03:40:12 +02:00
return ; /*Should never happen*/
2016-09-22 21:22:56 +02:00
}
2016-08-20 03:40:12 +02:00
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-07 20:59:08 +02:00
2016-09-22 21:22:56 +02:00
if ( ( d86f [ drive ] . version = = 0x010A ) | | ( d86f [ drive ] . version = = 0x0114 ) | | ( d86f [ drive ] . version = = 0x0115 ) )
2016-09-05 21:58:28 +02:00
{
2016-09-07 20:59:08 +02:00
for ( side = 0 ; side < d86f [ drive ] . side_flag_bytes ; side + + )
2016-09-06 02:17:05 +02:00
{
2016-09-07 00:40:29 +02:00
fwrite ( & ( d86f [ drive ] . side_flags [ side ] ) , 1 , 1 , d86f [ drive ] . f ) ;
2016-09-06 02:17:05 +02:00
}
2016-09-07 20:59:08 +02:00
2016-09-22 21:22:56 +02:00
if ( ( d86f [ drive ] . version = = 0x0114 ) | | ( d86f [ drive ] . version = = 0x0115 ) )
2016-09-07 20:59:08 +02:00
{
for ( side = 0 ; side < d86f [ drive ] . side_flag_bytes ; side + + )
{
fwrite ( & ( d86f [ drive ] . index_hole_pos [ side ] ) , 2 , 1 , d86f [ drive ] . f ) ;
}
}
2016-09-05 21:58:28 +02:00
}
else
{
fwrite ( & ( d86f [ drive ] . track_flags ) , 1 , 1 , d86f [ drive ] . f ) ;
}
2016-09-07 20:59:08 +02:00
fwrite ( & track_id , 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-22 21:22:56 +02:00
int mfm = 0 ;
int tflags = 0 ;
double rpm = 0 ;
2016-08-31 22:49:56 +02:00
double size = 8000.0 ;
2016-09-22 21:22:56 +02:00
tflags = d86f_track_flags ( drive ) ;
mfm = ( tflags & 8 ) ? 1 : 0 ;
rpm = ( tflags & 0x20 ) ? 360.0 : 300.0 ;
switch ( tflags & 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 ;
2016-09-07 03:00:52 +02:00
size = ( size * fdd_getrpm ( drive ^ fdd_swap ) ) / 300.0 ;
2016-08-31 22:49:56 +02:00
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
2016-09-07 20:59:08 +02:00
if ( fdd_get_head ( drive ) & & ( d86f_get_sides ( drive ) = = 1 ) )
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
d86f_drive = drive ;
2016-09-07 20:59:08 +02:00
if ( sector = = SECTOR_FIRST )
d86f [ drive ] . req_sector . id . r = 1 ;
else if ( sector = = SECTOR_NEXT )
d86f [ drive ] . req_sector . id . r + + ;
else
d86f [ drive ] . req_sector . id . r = sector ;
2016-09-22 21:22:56 +02:00
d86f [ drive ] . rw_sector_id . dword = 0xFFFFFFFF ;
d86f [ drive ] . last_sector . dword = 0xFFFFFFFF ;
2016-09-03 18:07:46 +02:00
d86f [ drive ] . req_sector . id . n = sector_size ;
d86f [ drive ] . index_count = 0 ;
2016-09-22 21:22:56 +02:00
d86f [ drive ] . wait_state = 1 ;
2016-09-07 20:59:08 +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-23 01:06:05 +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
2016-09-22 21:22:56 +02:00
if ( writeprot [ drive ] | | swwp )
{
// pclog("Write protected\n");
fdc_writeprotect ( ) ;
return ;
}
2016-09-07 20:59:08 +02:00
if ( fdd_get_head ( drive ) & & ( d86f_get_sides ( drive ) = = 1 ) )
2016-08-31 22:49:56 +02:00
{
2016-09-22 21:22:56 +02:00
// pclog("Wrong side\n");
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-09-22 21:22:56 +02:00
d86f [ drive ] . rw_sector_id . dword = 0xFFFFFFFF ;
d86f [ drive ] . last_sector . dword = 0xFFFFFFFF ;
2016-08-20 03:40:12 +02:00
d86f_drive = drive ;
2016-09-03 18:07:46 +02:00
d86f [ drive ] . index_count = 0 ;
2016-09-22 21:22:56 +02:00
d86f [ drive ] . wait_state = 1 ;
2016-09-03 18:07:46 +02:00
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-09-07 20:59:08 +02:00
if ( fdd_get_head ( drive ) & & ( d86f_get_sides ( drive ) = = 1 ) )
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-22 21:22:56 +02:00
d86f [ drive ] . rw_sector_id . dword = 0xFFFFFFFF ;
d86f [ drive ] . last_sector . dword = 0xFFFFFFFF ;
2016-08-31 22:49:56 +02:00
d86f_drive = drive ;
2016-09-03 18:07:46 +02:00
d86f [ drive ] . index_count = 0 ;
2016-09-22 21:22:56 +02:00
d86f [ drive ] . wait_state = 1 ;
2016-09-03 18:07:46 +02:00
d86f [ drive ] . state = STATE_READ_FIND_ADDRESS ;
2016-08-20 03:40:12 +02:00
}
2016-09-22 21:22:56 +02:00
uint16_t d86f_prepare_pretrack ( int drive , int side , int iso , int write_data )
2016-08-20 03:40:12 +02:00
{
2016-09-22 21:22:56 +02:00
uint16_t i ;
int mfm = 0 ;
int real_gap0_len = 0 ;
int sync_len = 0 ;
int real_gap1_len = 0 ;
mfm = d86f_is_mfm ( drive ) ;
real_gap0_len = mfm ? 80 : 40 ;
sync_len = mfm ? 12 : 6 ;
real_gap1_len = mfm ? 50 : 26 ;
d86f [ drive ] . index_hole_pos [ side ] = 0 ;
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-09-22 21:22:56 +02:00
if ( write_data ) memset ( d86f [ drive ] . track_data [ side ] , mfm ? 0x4E : 0xFF , d86f_get_raw_size ( drive ) ) ;
2016-08-20 03:40:12 +02:00
i = 0 ;
2016-09-03 18:07:46 +02:00
2016-09-22 21:22:56 +02:00
if ( ! iso )
2016-08-20 03:40:12 +02:00
{
2016-09-22 21:22:56 +02:00
memset ( d86f [ drive ] . track_layout [ side ] + i , BYTE_GAP0 , real_gap0_len ) ;
if ( write_data ) memset ( d86f [ drive ] . track_data [ side ] + i , mfm ? 0x4E : 0xFF , real_gap0_len ) ;
i + = real_gap0_len ;
memset ( d86f [ drive ] . track_layout [ side ] + i , BYTE_I_SYNC , sync_len ) ;
if ( write_data ) memset ( d86f [ drive ] . track_data [ side ] + i , 0 , sync_len ) ;
i + = sync_len ;
if ( mfm )
{
memset ( d86f [ drive ] . track_layout [ side ] + i , BYTE_IAM_SYNC , 3 ) ;
if ( write_data ) memset ( d86f [ drive ] . track_data [ side ] + i , 0xC2 , 3 ) ;
i + = 3 ;
}
memset ( d86f [ drive ] . track_layout [ side ] + i , BYTE_IAM , 1 ) ;
if ( write_data ) memset ( d86f [ drive ] . track_data [ side ] + i , 0xFC , 1 ) ;
i + + ;
2016-08-20 03:40:12 +02:00
}
2016-09-03 18:07:46 +02:00
memset ( d86f [ drive ] . track_layout [ side ] + i , BYTE_GAP1 , real_gap1_len ) ;
2016-09-22 21:22:56 +02:00
if ( write_data ) memset ( d86f [ drive ] . track_data [ side ] + i , mfm ? 0x4E : 0xFF , real_gap1_len ) ;
2016-09-03 18:07:46 +02:00
i + = real_gap1_len ;
2016-09-22 21:22:56 +02:00
return i ;
}
void d86f_calccrc_buf ( int drive , uint8_t * buf , uint16_t len )
{
uint16_t i = 0 ;
for ( i = 0 ; i < len ; i + + )
2016-09-07 20:59:08 +02:00
{
2016-09-22 21:22:56 +02:00
d86f_calccrc ( drive , buf [ i ] ) ;
2016-09-07 20:59:08 +02:00
}
2016-09-22 21:22:56 +02:00
}
2016-09-23 01:06:05 +02:00
static void * d86f_memset ( void * str , int c , size_t n , size_t s , uint16_t rs , int limit )
2016-09-22 21:22:56 +02:00
{
void * temp ;
size_t wrap_n [ 2 ] ;
uint8_t * wrap_str [ 2 ] ;
if ( ( n + s - 1 ) > = rs )
2016-08-20 03:40:12 +02:00
{
2016-09-22 21:22:56 +02:00
/* This is going to wrap around, so we need to split the data in two. */
wrap_n [ 0 ] = ( ( rs - 1 ) - s ) + 1 ;
wrap_n [ 1 ] = n - wrap_n [ 0 ] ;
wrap_str [ 0 ] = ( uint8_t * ) str ;
wrap_str [ 1 ] = wrap_str [ 0 ] - s ;
temp = memset ( wrap_str [ 0 ] , c , wrap_n [ 0 ] ) ;
2016-09-23 01:06:05 +02:00
if ( limit ) temp = memset ( wrap_str [ 1 ] , c , wrap_n [ 1 ] ) ;
2016-09-22 21:22:56 +02:00
}
else
{
/* No wrap around, do a standard memcpy. */
temp = memset ( str , c , n ) ;
}
return temp ;
}
2016-09-23 01:06:05 +02:00
static void * d86f_memcpy ( void * str1 , const void * str2 , size_t n , size_t s , uint16_t rs , int limit )
2016-09-22 21:22:56 +02:00
{
void * temp ;
size_t wrap_n [ 2 ] ;
uint8_t * wrap_str1 [ 2 ] ;
uint8_t * wrap_str2 [ 2 ] ;
if ( ( n + s - 1 ) > = rs )
{
/* This is going to wrap around, so we need to split the data in two. */
wrap_n [ 0 ] = ( ( rs - 1 ) - s ) + 1 ;
wrap_n [ 1 ] = n - wrap_n [ 0 ] ;
wrap_str1 [ 0 ] = ( uint8_t * ) str1 ;
wrap_str2 [ 0 ] = ( uint8_t * ) str2 ;
wrap_str1 [ 1 ] = wrap_str1 [ 0 ] - s ;
wrap_str2 [ 1 ] = wrap_str2 [ 0 ] + wrap_n [ 0 ] ;
temp = memcpy ( wrap_str1 [ 0 ] , wrap_str2 [ 0 ] , wrap_n [ 0 ] ) ;
2016-09-23 01:06:05 +02:00
if ( limit ) temp = memcpy ( wrap_str1 [ 1 ] , wrap_str2 [ 1 ] , wrap_n [ 1 ] ) ;
2016-09-22 21:22:56 +02:00
}
else
{
/* No wrap around, do a standard memcpy. */
temp = memcpy ( str1 , str2 , n ) ;
}
return temp ;
}
2016-09-23 01:06:05 +02:00
uint16_t d86f_prepare_sector ( int drive , int side , int pos , uint8_t * id_buf , uint8_t * data_buf , int data_len , int write_data , int gap2 , int gap3 , int limit )
2016-09-22 21:22:56 +02:00
{
uint16_t i = pos ;
uint16_t j = 0 ;
uint16_t rs = 0 ;
uint8_t am [ 4 ] = { 0xA1 , 0xA1 , 0xA1 } ;
int real_gap2_len = gap2 ;
int real_gap3_len = gap3 ;
int mfm = 0 ;
int sync_len = 0 ;
rs = d86f_get_raw_size ( drive ) ;
mfm = d86f_is_mfm ( drive ) ;
sync_len = mfm ? 12 : 6 ;
d86f_memset ( d86f [ drive ] . track_layout [ side ] + i , BYTE_ID_SYNC , sync_len , i , rs ) ;
2016-09-23 01:06:05 +02:00
if ( write_data ) d86f_memset ( d86f [ drive ] . track_data [ side ] + i , 0 , sync_len , i , rs , limit ) ;
2016-09-22 21:22:56 +02:00
i + = sync_len ;
2016-09-23 01:06:05 +02:00
if ( ( i > = rs ) & & limit ) return 0 ;
2016-09-22 21:22:56 +02:00
i % = rs ;
if ( mfm )
{
2016-09-23 01:06:05 +02:00
d86f_memset ( d86f [ drive ] . track_layout [ side ] + i , BYTE_IDAM_SYNC , 3 , i , rs , limit ) ;
2016-09-22 21:22:56 +02:00
if ( write_data )
2016-08-20 03:40:12 +02:00
{
2016-09-22 21:22:56 +02:00
d86f [ drive ] . calc_crc . word = 0xffff ;
2016-09-23 01:06:05 +02:00
d86f_memset ( d86f [ drive ] . track_data [ side ] + i , 0xA1 , 3 , i , rs , limit ) ;
2016-09-22 21:22:56 +02:00
d86f_calccrc_buf ( drive , am , 3 ) ;
2016-08-20 03:40:12 +02:00
}
2016-09-22 21:22:56 +02:00
i + = 3 ;
2016-09-23 01:06:05 +02:00
if ( ( i > = rs ) & & limit ) return 0 ;
2016-09-22 21:22:56 +02:00
i % = rs ;
}
2016-09-23 01:06:05 +02:00
d86f_memset ( d86f [ drive ] . track_layout [ side ] + i , BYTE_IDAM , 1 , i , rs , limit ) ;
2016-09-22 21:22:56 +02:00
if ( write_data )
{
if ( ! mfm ) d86f [ drive ] . calc_crc . word = 0xffff ;
2016-09-23 01:06:05 +02:00
d86f_memset ( d86f [ drive ] . track_data [ side ] + i , 0xFE , 1 , i , rs , limit ) ;
2016-09-22 21:22:56 +02:00
d86f_calccrc ( drive , 0xFE ) ;
}
i + + ;
2016-09-23 01:06:05 +02:00
if ( ( i > = rs ) & & limit ) return 0 ;
2016-09-22 21:22:56 +02:00
i % = rs ;
2016-09-23 01:06:05 +02:00
d86f_memset ( d86f [ drive ] . track_layout [ side ] + i , BYTE_ID , 4 , i , rs , limit ) ;
2016-09-22 21:22:56 +02:00
if ( write_data )
{
2016-09-23 01:06:05 +02:00
d86f_memcpy ( d86f [ drive ] . track_data [ side ] + i , id_buf , 4 , i , rs , limit ) ;
2016-09-22 21:22:56 +02:00
d86f_calccrc_buf ( drive , id_buf , 4 ) ;
// if ((id_buf[0] == 4) && (id_buf[1] == 0) && (id_buf[2] == 19) && (id_buf[3] == 2)) pclog("Prepare (%i %i %i %i): ID CRC %04X\n", id_buf[0], id_buf[1], id_buf[2], id_buf[3], d86f[drive].calc_crc);
}
i + = 4 ;
2016-09-23 01:06:05 +02:00
if ( ( i > = rs ) & & limit ) return 0 ;
2016-09-22 21:22:56 +02:00
i % = rs ;
2016-09-23 01:06:05 +02:00
d86f_memset ( d86f [ drive ] . track_layout [ side ] + i , BYTE_ID_CRC , 2 , i , rs , limit ) ;
2016-09-22 21:22:56 +02:00
if ( write_data )
{
d86f [ drive ] . track_data [ side ] [ i ] = d86f [ drive ] . calc_crc . bytes [ 1 ] ;
d86f [ drive ] . track_data [ side ] [ ( i + 1 ) % rs ] = d86f [ drive ] . calc_crc . bytes [ 0 ] ;
}
i + = 2 ;
2016-09-23 01:06:05 +02:00
if ( ( i > = rs ) & & limit ) return 0 ;
2016-09-22 21:22:56 +02:00
i % = rs ;
2016-09-23 01:06:05 +02:00
d86f_memset ( d86f [ drive ] . track_layout [ side ] + i , BYTE_GAP2 , real_gap2_len , i , rs , limit ) ;
if ( write_data ) d86f_memset ( d86f [ drive ] . track_data [ side ] + i , mfm ? 0x4E : 0xFF , real_gap2_len , i , rs , limit ) ;
2016-09-22 21:22:56 +02:00
i + = real_gap2_len ;
2016-09-23 01:06:05 +02:00
if ( ( i > = rs ) & & limit ) return 0 ;
2016-09-22 21:22:56 +02:00
i % = rs ;
2016-09-23 01:06:05 +02:00
d86f_memset ( d86f [ drive ] . track_layout [ side ] + i , BYTE_DATA_SYNC , sync_len , i , rs , limit ) ;
if ( write_data ) d86f_memset ( d86f [ drive ] . track_data [ side ] + i , 0 , sync_len , i , rs , limit ) ;
2016-09-22 21:22:56 +02:00
i + = sync_len ;
2016-09-23 01:06:05 +02:00
if ( ( i > = rs ) & & limit ) return 0 ;
2016-09-22 21:22:56 +02:00
i % = rs ;
if ( mfm )
{
2016-09-23 01:06:05 +02:00
d86f_memset ( d86f [ drive ] . track_layout [ side ] + i , BYTE_DATAAM_SYNC , 3 , i , rs , limit ) ;
2016-09-22 21:22:56 +02:00
if ( write_data )
2016-08-20 03:40:12 +02:00
{
2016-09-22 21:22:56 +02:00
d86f [ drive ] . calc_crc . word = 0xffff ;
2016-09-23 01:06:05 +02:00
d86f_memset ( d86f [ drive ] . track_data [ side ] + i , 0xA1 , 3 , i , rs , limit ) ;
2016-09-22 21:22:56 +02:00
d86f_calccrc_buf ( drive , am , 3 ) ;
2016-08-20 03:40:12 +02:00
}
2016-09-22 21:22:56 +02:00
i + = 3 ;
2016-09-23 01:06:05 +02:00
if ( ( i > = rs ) & & limit ) return 0 ;
2016-09-22 21:22:56 +02:00
i % = rs ;
}
2016-09-23 01:06:05 +02:00
d86f_memset ( d86f [ drive ] . track_layout [ side ] + i , BYTE_DATAAM , 1 , i , rs , limit ) ;
2016-09-22 21:22:56 +02:00
if ( write_data )
{
if ( ! mfm ) d86f [ drive ] . calc_crc . word = 0xffff ;
2016-09-23 01:06:05 +02:00
d86f_memset ( d86f [ drive ] . track_data [ side ] + i , 0xFB , 1 , i , rs , limit ) ;
2016-09-22 21:22:56 +02:00
d86f_calccrc ( drive , 0xFB ) ;
}
i + + ;
2016-09-23 01:06:05 +02:00
if ( ( i > = rs ) & & limit ) return 0 ;
2016-09-22 21:22:56 +02:00
i % = rs ;
2016-09-23 01:06:05 +02:00
d86f_memset ( d86f [ drive ] . track_layout [ side ] + i , BYTE_DATA , data_len , i , rs , limit ) ;
2016-09-22 21:22:56 +02:00
if ( write_data )
{
2016-09-23 01:06:05 +02:00
d86f_memcpy ( d86f [ drive ] . track_data [ side ] + i , data_buf , data_len , i , rs , limit ) ;
2016-09-22 21:22:56 +02:00
d86f_calccrc_buf ( drive , data_buf , data_len ) ;
// if ((id_buf[0] == 4) && (id_buf[1] == 0) && (id_buf[2] == 19) && (id_buf[3] == 2)) pclog("Prepare (%i %i %i %i): Data CRC %04X\n", id_buf[0], id_buf[1], id_buf[2], id_buf[3], d86f[drive].calc_crc);
}
i + = data_len ;
2016-09-23 01:06:05 +02:00
if ( ( i > = rs ) & & limit ) return 0 ;
2016-09-22 21:22:56 +02:00
i % = rs ;
2016-09-23 01:06:05 +02:00
d86f_memset ( d86f [ drive ] . track_layout [ side ] + i , BYTE_DATA_CRC , 2 , i , rs , limit ) ;
2016-09-22 21:22:56 +02:00
if ( write_data )
{
d86f [ drive ] . track_data [ side ] [ i ] = d86f [ drive ] . calc_crc . bytes [ 1 ] ;
d86f [ drive ] . track_data [ side ] [ ( i + 1 ) % rs ] = d86f [ drive ] . calc_crc . bytes [ 0 ] ;
}
i + = 2 ;
2016-09-23 01:06:05 +02:00
if ( ( i > = rs ) & & limit ) return 0 ;
2016-09-22 21:22:56 +02:00
i % = rs ;
2016-09-23 01:06:05 +02:00
d86f_memset ( d86f [ drive ] . track_layout [ side ] + i , BYTE_GAP3 , real_gap3_len , i , rs , limit ) ;
d86f_memset ( d86f [ drive ] . track_data [ side ] + i , mfm ? 0x4E : 0xFF , real_gap3_len , i , rs , limit ) ;
2016-09-22 21:22:56 +02:00
i + = real_gap3_len ;
2016-09-23 01:06:05 +02:00
if ( ( i > = rs ) & & limit ) return 0 ;
2016-09-22 21:22:56 +02:00
i % = rs ;
return i ;
}
void d86f_prepare_track_layout ( int drive , int side )
{
uint16_t i = 0 ;
uint16_t j = 0 ;
uint16_t sc = 0 ;
uint16_t dtl = 0 ;
int real_gap2_len = 0 ;
int real_gap3_len = 0 ;
sc = fdc_get_format_sectors ( ) ;
dtl = 128 < < fdc_get_format_n ( ) ;
real_gap2_len = fdc_get_gap2 ( drive ^ fdd_swap ) ;
real_gap3_len = fdc_get_gap ( ) ;
i = d86f_prepare_pretrack ( drive , side , 0 , 0 ) ;
for ( j = 0 ; j < sc ; j + + )
{
2016-09-23 01:06:05 +02:00
/* Always limit to prevent wraparounds when formatting! */
i = d86f_prepare_sector ( drive , side , i , NULL , NULL , dtl , 0 , real_gap2_len , real_gap3_len , 1 ) ;
2016-08-20 03:40:12 +02:00
}
2016-08-31 22:49:56 +02:00
}
2016-09-22 21:22:56 +02:00
int d86f_format_conditions ( int drive )
{
return d86f_valid_bit_rate ( drive ) ;
}
2016-09-17 20:22:02 +02:00
int d86f_can_format ( int drive )
{
int temp ;
temp = ! writeprot [ drive ] ;
temp = temp & & ! swwp ;
temp = temp & & fdd_can_read_medium ( drive ^ fdd_swap ) ;
2016-09-22 21:22:56 +02:00
temp = temp & & d86f_handler [ drive ] . format_conditions ( drive ) ; /* Allows proxied formats to add their own extra conditions to formatting. */
2016-09-17 20:22:02 +02:00
return temp ;
}
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 ;
2016-09-22 21:22:56 +02:00
if ( ( d86f [ drive ] . version = = 0x010A ) | | ( d86f [ drive ] . version = = 0x0114 ) | | ( d86f [ drive ] . version = = 0x0115 ) )
2016-09-05 21:58:28 +02:00
{
full_size = d86f_get_array_size ( drive ) ;
store_size = full_size < < 1 ;
2016-09-07 20:59:08 +02:00
if ( d86f [ drive ] . side_flag_bytes = = 2 ) flag_bytes + + ;
2016-09-22 21:22:56 +02:00
if ( ( d86f [ drive ] . version = = 0x0114 ) | | ( d86f [ drive ] . version = = 0x0115 ) ) flag_bytes + = 4 ;
2016-09-05 21:58:28 +02:00
}
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-17 20:22:02 +02:00
if ( ( side & & ( d86f_get_sides ( drive ) = = 1 ) ) | | ! ( d86f_can_format ( drive ) ) )
2016-08-31 22:49:56 +02:00
{
2016-09-22 21:22:56 +02:00
/* if (side && (d86f_get_sides(drive) == 1)) pclog("Wrong side\n");
if ( ! ( d86f_can_format ( drive ) ) )
{
if ( writeprot [ drive ] ) pclog ( " Drive is write-protected \n " ) ;
if ( swwp ) pclog ( " Software write-protect is enabled \n " ) ;
if ( ! fdd_can_read_medium ( drive ^ fdd_swap ) ) pclog ( " Drive can't read medium \n " ) ; ;
pclog ( " Extra conditions: %i \n " , d86f_handler [ drive ] . format_conditions ( drive ) ) ;
pclog ( " Hole: %i, rate: %i \n " , d86f_hole ( drive ) , fdc_get_bit_rate ( ) ) ;
} */
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
{
2016-09-22 21:22:56 +02:00
// pclog("Track below 0 or above 256\n");
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. */
2016-09-22 21:22:56 +02:00
if ( d86f [ drive ] . version ! = 0x0063 )
2016-09-05 21:58:28 +02:00
{
2016-09-22 21:22:56 +02:00
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 ;
if ( ( d86f [ drive ] . version = = 0x010A ) | | ( d86f [ drive ] . version = = 0x0114 ) | | ( d86f [ drive ] . version = = 0x0115 ) )
2016-09-08 00:04:04 +02:00
{
2016-09-22 21:22:56 +02:00
d86f [ drive ] . side_flags [ side ] = d86f [ drive ] . track_flags ;
if ( ( d86f [ drive ] . version = = 0x0114 ) | | ( d86f [ drive ] . version = = 0x0115 ) )
{
d86f [ drive ] . index_hole_pos [ side ] = 0 ;
}
2016-09-08 00:04:04 +02:00
}
2016-09-07 20:59:08 +02:00
}
2016-09-05 21:58:28 +02:00
memset ( d86f [ drive ] . track_data [ side ] , 0xFF , full_size ) ;
2016-09-22 21:22:56 +02:00
/* For version 0.99 (= another format proxied to the 86F handler), the track layout is fixed. */
if ( d86f [ drive ] . version ! = 0x0063 )
2016-09-01 18:52:23 +02:00
{
2016-09-22 21:22:56 +02:00
d86f_prepare_track_layout ( drive , side ) ;
if ( ! d86f [ drive ] . track_in_file )
2016-09-01 18:52:23 +02:00
{
2016-09-22 21:22:56 +02:00
/* Track is absent from the file, let's add it. */
d86f [ drive ] . track_offset [ d86f [ drive ] . cur_track ] = d86f [ drive ] . file_size ;
d86f [ drive ] . file_size + = store_size + flag_bytes ;
if ( d86f_get_sides ( drive ) = = 2 )
{
d86f [ drive ] . file_size + = store_size ;
}
d86f [ drive ] . track_in_file = 1 ;
2016-09-01 18:52:23 +02:00
}
}
2016-09-22 21:22:56 +02:00
// pclog("Formatting track %i side %i\n", d86f[drive].cur_track, side);
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
}
2016-08-31 22:49:56 +02:00
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 ;
}
2016-09-22 21:22:56 +02:00
int d86f_find_state_nf_ignore_id ( int drive )
2016-09-14 23:18:14 +02:00
{
int temp ;
2016-09-22 21:22:56 +02:00
temp = temp | | ( d86f [ drive ] . state = = STATE_READ_FIND_FIRST_SECTOR ) ;
temp = temp | | ( d86f [ drive ] . state = = STATE_READ_FIND_NEXT_SECTOR ) ;
2016-09-14 23:18:14 +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 ) ;
2016-09-22 21:22:56 +02:00
temp = temp | | d86f_find_state_nf_ignore_id ( drive ) ;
2016-09-03 18:07:46 +02:00
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-22 21:22:56 +02:00
uint32_t d86f_get_pos ( int drive )
{
uint32_t pos ;
if ( d86f [ drive ] . track_pos > = d86f [ drive ] . section_pos )
{
pos = d86f [ drive ] . track_pos - d86f [ drive ] . section_pos ;
}
else
{
/* A wrap arround has occurred, let's add the raw size to the position. */
pos = d86f_get_raw_size ( drive ) + d86f [ drive ] . track_pos ;
pos - = d86f [ drive ] . section_pos ;
}
return pos ;
}
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 ;
2016-09-22 21:22:56 +02:00
d86f [ drive ] . id_pos = d86f_get_pos ( drive ) ;
2016-09-14 23:18:14 +02:00
d86f [ drive ] . track_data [ side ] [ d86f [ drive ] . track_pos ] = d86f [ drive ] . track_data_byte = d86f [ drive ] . calc_crc . bytes [ d86f [ drive ] . id_pos ^ 1 ] ;
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_advancebyte ( int drive , int side )
{
2016-09-22 21:22:56 +02:00
if ( d86f_handler [ drive ] . side_flags = = NULL )
{
fatal ( " NULL side flags handler \n " ) ;
}
2016-09-03 18:07:46 +02:00
d86f [ drive ] . old_track_byte = d86f [ drive ] . track_byte ;
d86f [ drive ] . old_track_index = d86f [ drive ] . track_index ;
2016-09-14 23:18:14 +02:00
d86f [ drive ] . old_track_data_byte = d86f [ drive ] . track_data_byte ;
2016-09-22 21:22:56 +02:00
if ( ( d86f [ drive ] . version = = 0x0114 ) | | ( d86f [ drive ] . version = = 0x0115 ) )
2016-09-14 23:18:14 +02:00
{
d86f [ drive ] . old_track_fuzzy = d86f [ drive ] . track_fuzzy ;
}
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-07 20:59:08 +02:00
if ( ( d86f [ drive ] . version = = 0x0100 ) | | ( d86f [ drive ] . version = = 0x010A ) )
{
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-09-14 23:18:14 +02:00
d86f [ drive ] . track_data_byte = d86f [ drive ] . track_data [ side ] [ d86f [ drive ] . track_pos ] ;
2016-09-22 21:22:56 +02:00
d86f [ drive ] . track_fuzzy = 0 ;
2016-09-07 20:59:08 +02:00
}
2016-09-22 21:22:56 +02:00
else if ( ( d86f [ drive ] . version = = 0x0114 ) | | ( d86f [ drive ] . version = = 0x0115 ) )
2016-09-07 20:59:08 +02:00
{
d86f [ drive ] . track_byte = d86f [ drive ] . track_layout [ side ] [ d86f [ drive ] . track_pos ] & ~ BYTE_IS_FUZZY ;
d86f [ drive ] . track_index = ( d86f [ drive ] . track_pos = = d86f [ drive ] . index_hole_pos [ side ] ) ;
2016-09-14 23:18:14 +02:00
d86f [ drive ] . track_fuzzy = d86f [ drive ] . track_layout [ side ] [ d86f [ drive ] . track_pos ] & BYTE_IS_FUZZY ;
if ( d86f [ drive ] . track_fuzzy )
{
d86f [ drive ] . track_data_byte = disc_random_generate ( ) ;
}
else
{
d86f [ drive ] . track_data_byte = d86f [ drive ] . track_data [ side ] [ d86f [ drive ] . track_pos ] ;
}
2016-09-07 20:59:08 +02:00
}
2016-09-22 21:22:56 +02:00
else if ( d86f [ drive ] . version = = 0x0063 )
{
d86f [ drive ] . track_byte = d86f [ drive ] . track_layout [ side ] [ d86f [ drive ] . track_pos ] & ~ BYTE_INDEX_HOLE ;
d86f [ drive ] . track_index = ( d86f [ drive ] . track_pos = = 0 ) ;
d86f [ drive ] . track_data_byte = d86f [ drive ] . track_data [ side ] [ d86f [ drive ] . track_pos ] ;
d86f [ drive ] . track_fuzzy = 0 ;
}
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_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 ;
2016-09-15 03:59:49 +02:00
d86f [ drive ] . datac = 0 ;
2016-09-03 18:07:46 +02:00
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-23 01:06:05 +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-07 20:59:08 +02:00
int d86f_mark_index_hole ( int drive )
{
2016-09-22 21:22:56 +02:00
int temp ;
temp = ( d86f [ drive ] . version = = 0x0100 ) ;
2016-09-07 20:59:08 +02:00
temp = temp | | ( d86f [ drive ] . version = = 0x010A ) ;
return temp ;
}
2016-09-14 23:18:14 +02:00
void d86f_poll_write ( int drive , int side , uint8_t data , uint8_t type )
{
d86f [ drive ] . track_data [ side ] [ d86f [ drive ] . track_pos ] = d86f [ drive ] . track_data_byte = data ;
d86f [ drive ] . track_layout [ side ] [ d86f [ drive ] . track_pos ] = type ;
if ( ! d86f [ drive ] . track_pos & & d86f_mark_index_hole ( drive ) ) d86f [ drive ] . track_layout [ side ] [ d86f [ drive ] . track_pos ] | = BYTE_INDEX_HOLE ;
}
2016-09-23 01:06:05 +02:00
void d86f_poll_fill ( int drive , int side )
{
d86f_handler [ drive ] . write_data ( drive , side , d86f [ drive ] . id_pos , d86f [ drive ] . fill ) ;
d86f_calccrc ( drive , d86f [ drive ] . fill ) ;
if ( d86f [ drive ] . calc_crc . word = = 0xDC25 ) pclog ( " d86f_poll_fill(): CRC is DC25! \n "
}
2016-09-22 21:22:56 +02:00
void d86f_set_sector ( int drive , int side , uint8_t c , uint8_t h , uint8_t r , uint8_t n )
{
return ;
}
uint8_t d86f_poll_read_data ( int drive , int side , uint16_t pos )
{
return d86f [ drive ] . track_data_byte ;
}
void d86f_poll_write_data ( int drive , int side , uint16_t pos , uint8_t data )
{
d86f_poll_write ( drive , side , data , BYTE_DATA ) ;
}
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 ) ;
2016-09-22 21:22:56 +02:00
data = d86f_handler [ drive ] . read_data ( drive , side , d86f [ drive ] . datac ) ;
2016-09-03 18:07:46 +02:00
if ( d86f [ drive ] . datac < d86f_get_data_len ( drive ) )
{
2016-09-07 20:59:08 +02:00
fdc_data ( data ) ;
2016-09-03 18:07:46 +02:00
}
2016-09-07 20:59:08 +02:00
d86f_calccrc ( drive , data ) ;
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 ) ;
2016-09-22 21:22:56 +02:00
2016-09-03 18:07:46 +02:00
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 ) ) ;
2016-09-22 21:22:56 +02:00
2016-09-03 18:07:46 +02:00
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-22 21:22:56 +02:00
d86f_handler [ drive ] . write_data ( drive , side , d86f [ drive ] . datac , data ) ;
2016-08-20 03:40:12 +02:00
}
2016-09-22 21:22:56 +02:00
// d86f_calccrc(drive, d86f[drive].track_data_byte);
d86f_calccrc ( drive , data & 0xff ) ;
2016-09-03 18:07:46 +02:00
}
else if ( d86f_read_state_crc ( drive ) )
{
max_len = 2 ;
2016-09-14 23:18:14 +02:00
d86f [ drive ] . track_crc . bytes [ d86f [ drive ] . datac ^ 1 ] = d86f [ drive ] . track_data_byte ;
2016-09-03 18:07:46 +02:00
}
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-14 23:18:14 +02:00
d86f_poll_write ( drive , side , d86f [ drive ] . calc_crc . bytes [ d86f [ drive ] . datac ^ 1 ] , BYTE_DATA_CRC ) ;
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-22 21:22:56 +02:00
d86f_poll_reset ( drive , side ) ;
if ( ( d86f [ drive ] . track_crc . word ! = d86f [ drive ] . calc_crc . word ) & & d86f_handler [ drive ] . check_crc )
2016-08-20 03:40:12 +02:00
{
2016-09-23 01:06:05 +02:00
// pclog("d86f_poll(): Data CRC error (%i %i %i %i) (%04X %04X)\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, d86f[drive].track_crc.word, d86f[drive].calc_crc.word);
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-22 21:22:56 +02:00
// pclog("Read finished (%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);
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 ( ) ;
2016-09-15 03:59:49 +02:00
if ( ! disable_write & & ! d86f [ drive ] . datac )
{
d86f_poll_write ( drive , side , fdc_is_mfm ( ) ? 0x4E : 0xFF , BYTE_GAP3 ) ;
}
if ( d86f [ drive ] . datac = = ( max_len - 1 ) )
2016-09-03 18:07:46 +02:00
{
2016-09-14 23:18:14 +02:00
if ( ! disable_write )
{
2016-09-22 21:22:56 +02:00
d86f_handler [ drive ] . writeback ( drive ) ;
2016-09-14 23:18:14 +02:00
}
2016-09-22 21:22:56 +02:00
d86f_poll_reset ( drive , side ) ;
// pclog("Write finished (%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);
2016-09-03 18:07:46 +02:00
fdc_sector_finishread ( drive ) ;
return ;
}
}
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 + + ;
}
}
2016-09-22 21:22:56 +02:00
int d86f_end_wait_state ( int drive )
{
int temp = 0 ;
int fdc_mfm = 0 ;
int disk_mfm = 0 ;
fdc_mfm = fdc_is_mfm ( ) ;
disk_mfm = d86f_is_mfm ( drive ) ;
temp = temp | | ( ( d86f [ drive ] . track_byte = = BYTE_IDAM_SYNC ) & & fdc_mfm & & disk_mfm ) ;
temp = temp | | ( ( d86f [ drive ] . track_byte = = BYTE_IDAM ) & & ! fdc_mfm & & ! disk_mfm ) ;
temp = temp & & d86f_can_read_address ( drive ) ; /* This is so the wait state never ends if the data rate or encoding is wrong. */
return temp ;
}
void d86f_poll_find_nf_wait ( int drive , int side )
{
if ( d86f [ drive ] . track_index )
{
// pclog("d86f_poll_find_nf(): Index pulse\n");
index_pulse ( drive ) ;
d86f [ drive ] . index_count + + ;
}
d86f_poll_advancebyte ( drive , side ) ;
if ( d86f_poll_check_notfound ( drive ) ) return ;
if ( d86f [ drive ] . track_byte ! = d86f [ drive ] . old_track_byte )
{
if ( d86f_end_wait_state ( drive ) )
{
d86f [ drive ] . calc_crc . word = 0xffff ;
d86f [ drive ] . id_am_counter = d86f [ drive ] . id_counter = d86f [ drive ] . id_match = d86f [ drive ] . data_am_counter = d86f [ drive ] . wait_state = 0 ;
}
}
}
2016-09-03 18:07:46 +02:00
void d86f_poll_find_nf ( int drive , int side )
{
2016-09-22 21:22:56 +02:00
uint8_t mfm = 0 ;
uint8_t am_len = 0 ;
mfm = fdc_is_mfm ( ) ;
am_len = mfm ? 4 : 1 ;
2016-09-07 20:59:08 +02:00
2016-09-03 18:07:46 +02:00
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 )
{
2016-09-14 23:18:14 +02:00
case BYTE_DATAAM_SYNC :
2016-09-22 21:22:56 +02:00
if ( ( d86f [ drive ] . id_match ) | | d86f_find_state_nf_ignore_id ( drive ) )
2016-09-14 23:18:14 +02:00
{
2016-09-22 21:22:56 +02:00
d86f [ drive ] . data_am_counter + + ;
if ( mfm )
{
d86f_calccrc ( drive , d86f [ drive ] . track_data_byte ) ;
}
2016-09-14 23:18:14 +02:00
}
2016-09-22 21:22:56 +02:00
break ;
2016-09-14 23:18:14 +02:00
case BYTE_IDAM_SYNC :
2016-09-22 21:22:56 +02:00
d86f [ drive ] . id_am_counter + + ;
if ( mfm )
2016-09-14 23:18:14 +02:00
{
d86f_calccrc ( drive , d86f [ drive ] . track_data_byte ) ;
}
2016-09-03 18:07:46 +02:00
break ;
case BYTE_DATAAM :
2016-09-22 21:22:56 +02:00
if ( ( d86f [ drive ] . id_match ) | | d86f_find_state_nf_ignore_id ( drive ) )
2016-08-31 22:49:56 +02:00
{
2016-09-22 21:22:56 +02:00
if ( ( d86f [ drive ] . state = = STATE_WRITE_FIND_SECTOR ) & & ( d86f [ drive ] . data_am_counter = = ( am_len - 1 ) ) )
{
d86f_poll_write ( drive , side , 0xFB , BYTE_DATAAM ) ;
}
d86f [ drive ] . data_am_counter + + ;
d86f [ drive ] . id_match = 0 ;
d86f_calccrc ( drive , d86f [ drive ] . track_data_byte ) ;
2016-08-31 22:49:56 +02:00
}
2016-09-22 21:22:56 +02:00
break ;
2016-09-14 23:18:14 +02:00
case BYTE_IDAM :
2016-09-22 21:22:56 +02:00
d86f [ drive ] . id_am_counter + + ;
2016-09-14 23:18:14 +02:00
d86f_calccrc ( drive , d86f [ drive ] . track_data_byte ) ;
2016-09-03 18:07:46 +02:00
break ;
2016-09-14 23:18:14 +02:00
2016-09-03 18:07:46 +02:00
case BYTE_ID :
2016-09-22 21:22:56 +02:00
d86f [ drive ] . id_pos = d86f_get_pos ( drive ) ;
d86f [ drive ] . last_sector . byte_array [ d86f [ drive ] . id_pos ] = d86f [ drive ] . track_data_byte ;
2016-09-15 03:59:49 +02:00
d86f_calccrc ( drive , d86f [ drive ] . track_data_byte ) ;
2016-09-22 21:22:56 +02:00
if ( d86f [ drive ] . id_am_counter = = am_len )
{
d86f [ drive ] . id_counter + + ;
}
2016-09-03 18:07:46 +02:00
break ;
case BYTE_ID_CRC :
2016-09-22 21:22:56 +02:00
d86f [ drive ] . id_pos = d86f_get_pos ( drive ) ;
2016-09-14 23:18:14 +02:00
d86f [ drive ] . track_crc . bytes [ d86f [ drive ] . id_pos ^ 1 ] = d86f [ drive ] . track_data_byte ;
2016-09-03 18:07:46 +02:00
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 )
{
2016-09-14 23:18:14 +02:00
case BYTE_IDAM_SYNC :
case BYTE_DATAAM_SYNC :
2016-09-22 21:22:56 +02:00
if ( mfm )
2016-09-14 23:18:14 +02:00
{
d86f [ drive ] . calc_crc . word = 0xffff ;
}
break ;
case BYTE_IDAM :
case BYTE_DATAAM :
2016-09-22 21:22:56 +02:00
if ( ! mfm )
2016-09-14 23:18:14 +02:00
{
d86f [ drive ] . calc_crc . word = 0xffff ;
}
break ;
2016-09-03 18:07:46 +02:00
case BYTE_GAP2 :
2016-09-22 21:22:56 +02:00
d86f [ drive ] . id_match = 0 ;
d86f [ drive ] . data_am_counter = 0 ;
if ( d86f [ drive ] . id_counter ! = 4 )
{
d86f [ drive ] . id_am_counter = d86f [ drive ] . id_counter = 0 ;
break ;
}
d86f [ drive ] . id_am_counter = d86f [ drive ] . id_counter = 0 ;
if ( ( d86f [ drive ] . req_sector . dword = = d86f [ drive ] . last_sector . dword ) | | ( d86f [ drive ] . state = = STATE_READ_FIND_ADDRESS ) )
2016-08-31 22:49:56 +02:00
{
2016-09-22 21:22:56 +02:00
if ( ( d86f [ drive ] . track_crc . word ! = d86f [ drive ] . calc_crc . word ) & & d86f_handler [ drive ] . check_crc )
2016-09-03 18:07:46 +02:00
{
2016-09-22 21:22:56 +02:00
if ( d86f [ drive ] . state ! = STATE_READ_FIND_ADDRESS )
2016-09-03 18:07:46 +02:00
{
2016-09-23 01:06:05 +02:00
// pclog("d86f_poll(): Header CRC error (mfm=%i) (%i %i %i %i) (%04X %04X)\n", d86f_is_mfm(drive), d86f[drive].req_sector.id.c, d86f[drive].req_sector.id.h, d86f[drive].req_sector.id.r, d86f[drive].req_sector.id.n, d86f[drive].track_crc.word, d86f[drive].calc_crc.word);
2016-09-22 21:22:56 +02:00
fdc_finishread ( ) ;
fdc_headercrcerror ( ) ;
d86f [ drive ] . state = STATE_IDLE ;
d86f [ drive ] . index_count = 0 ;
return ;
2016-09-03 18:07:46 +02:00
}
2016-09-07 00:40:29 +02:00
else
{
2016-09-23 01:06:05 +02:00
// pclog("d86f_poll(): Header CRC error at read sector ID (mfm=%i) (%i %i %i %i) (%04X %04X)\n", d86f_is_mfm(drive), d86f[drive].req_sector.id.c, d86f[drive].req_sector.id.h, d86f[drive].req_sector.id.r, d86f[drive].req_sector.id.n, d86f[drive].track_crc.word, d86f[drive].calc_crc.word);
2016-09-07 00:40:29 +02:00
}
2016-09-22 21:22:56 +02:00
}
else
{
if ( d86f [ drive ] . state ! = STATE_READ_FIND_ADDRESS ) d86f [ drive ] . id_match = 1 ;
// 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);
if ( d86f [ drive ] . state = = STATE_READ_FIND_ADDRESS )
{
// pclog("Reading sector ID (%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);
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 ;
}
else
{
d86f_handler [ drive ] . set_sector ( drive , side , d86f [ drive ] . last_sector . id . c , d86f [ drive ] . last_sector . id . h , d86f [ drive ] . last_sector . id . r , d86f [ drive ] . last_sector . id . n ) ;
}
}
}
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 :
case STATE_READ_FIND_FIRST_SECTOR :
case STATE_READ_FIND_NEXT_SECTOR :
2016-09-22 21:22:56 +02:00
/* If the data address mark counter is anything other than 0, then either the ID matches or the FDC is in the ignore sector ID mode (ie. the READ TRACK command).
Also , the bitcell period , etc . are already checked during the wait state which is designed to never end in case of a mismatch .
Therefore , ensuring the data address mark acounter is at a correct length is all we need to do . */
if ( d86f [ drive ] . data_am_counter = = am_len )
2016-09-03 18:07:46 +02:00
{
d86f [ drive ] . state + + ;
}
2016-09-22 21:22:56 +02:00
/* Data address mark counter always reset to 0. */
d86f [ drive ] . data_am_counter = 0 ;
2016-09-03 18:07:46 +02:00
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 )
{
2016-09-14 23:18:14 +02:00
d86f_poll_advancebyte ( drive , side ) ;
if ( d86f [ drive ] . track_index )
2016-09-03 18:07:46 +02:00
{
2016-09-22 21:22:56 +02:00
// pclog("Index hole hit, formatting track...\n");
2016-09-03 18:07:46 +02:00
d86f [ drive ] . state = STATE_FORMAT ;
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
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-14 23:18:14 +02:00
if ( ! disable_write )
{
d86f [ drive ] . track_data [ side ] [ d86f [ drive ] . track_pos ] = d86f [ drive ] . track_data_byte = fdc_is_mfm ( ) ? 0x4E : 0xFF ;
}
2016-08-31 22:49:56 +02:00
break ;
case BYTE_IAM_SYNC :
2016-09-14 23:18:14 +02:00
if ( ! disable_write )
{
d86f [ drive ] . track_data [ side ] [ d86f [ drive ] . track_pos ] = d86f [ drive ] . track_data_byte = 0xC2 ;
}
2016-08-31 22:49:56 +02:00
break ;
case BYTE_IAM :
2016-09-14 23:18:14 +02:00
if ( ! disable_write )
{
d86f [ drive ] . track_data [ side ] [ d86f [ drive ] . track_pos ] = d86f [ drive ] . track_data_byte = 0xFC ;
}
2016-08-31 22:49:56 +02:00
break ;
case BYTE_ID_SYNC :
2016-09-22 21:22:56 +02:00
d86f [ drive ] . id_pos = d86f_get_pos ( drive ) ;
2016-09-17 20:22:02 +02:00
if ( d86f [ drive ] . id_pos < = 3 )
2016-09-03 18:07:46 +02:00
{
2016-09-17 20:22:02 +02:00
data = fdc_getdata ( 0 ) ;
if ( ( data = = - 1 ) & & ( d86f [ drive ] . id_pos < 3 ) )
{
data = 0 ;
}
2016-09-22 21:22:56 +02:00
if ( d86f [ drive ] . version ! = 0063 )
{
d86f [ drive ] . format_sector_id . byte_array [ d86f [ drive ] . id_pos ] = data & 0xff ;
}
2016-09-17 20:22:02 +02:00
// 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 ( ) ;
2016-09-22 21:22:56 +02:00
if ( d86f [ drive ] . version ! = 0063 )
{
d86f_handler [ drive ] . set_sector ( drive , side , d86f [ drive ] . format_sector_id . id . c , d86f [ drive ] . format_sector_id . id . h , d86f [ drive ] . format_sector_id . id . r , d86f [ drive ] . format_sector_id . id . n ) ;
}
2016-09-17 20:22:02 +02:00
// pclog("Formatting sector: %08X...\n", d86f[drive].format_sector_id.dword);
}
2016-08-31 22:49:56 +02:00
}
2016-09-17 20:22:02 +02:00
2016-08-31 22:49:56 +02:00
case BYTE_I_SYNC :
case BYTE_DATA_SYNC :
2016-09-14 23:18:14 +02:00
if ( ! disable_write )
{
d86f [ drive ] . track_data [ side ] [ d86f [ drive ] . track_pos ] = d86f [ drive ] . track_data_byte = 0 ;
}
2016-08-31 22:49:56 +02:00
break ;
case BYTE_IDAM_SYNC :
case BYTE_DATAAM_SYNC :
2016-09-14 23:18:14 +02:00
if ( ! disable_write )
{
d86f [ drive ] . track_data [ side ] [ d86f [ drive ] . track_pos ] = d86f [ drive ] . track_data_byte = 0xA1 ;
}
if ( d86f_is_mfm ( drive ) )
{
d86f_calccrc ( drive , d86f [ drive ] . track_data_byte ) ;
}
2016-08-31 22:49:56 +02:00
break ;
case BYTE_IDAM :
case BYTE_DATAAM :
2016-09-03 18:07:46 +02:00
// pclog("CRC reset: %02X\n", d86f[drive].track_byte);
2016-09-14 23:18:14 +02:00
if ( ! disable_write )
{
d86f [ drive ] . track_data [ side ] [ d86f [ drive ] . track_pos ] = d86f [ drive ] . track_data_byte = ( d86f [ drive ] . track_byte = = BYTE_IDAM ) ? 0xFE : 0xFB ;
}
d86f_calccrc ( drive , d86f [ drive ] . track_data_byte ) ;
2016-08-31 22:49:56 +02:00
break ;
case BYTE_ID :
2016-09-22 21:22:56 +02:00
d86f [ drive ] . id_pos = d86f_get_pos ( drive ) ;
if ( d86f [ drive ] . version ! = 0063 )
{
if ( ! disable_write )
{
d86f [ drive ] . track_data [ side ] [ d86f [ drive ] . track_pos ] = d86f [ drive ] . track_data_byte = d86f [ drive ] . format_sector_id . byte_array [ d86f [ drive ] . id_pos ] ;
}
}
else
2016-08-31 22:49:56 +02:00
{
2016-09-22 21:22:56 +02:00
d86f [ drive ] . format_sector_id . byte_array [ d86f [ drive ] . id_pos ] = d86f [ drive ] . track_data_byte ;
if ( d86f [ drive ] . id_pos = = 3 )
{
d86f_handler [ drive ] . set_sector ( drive , side , d86f [ drive ] . format_sector_id . id . c , d86f [ drive ] . format_sector_id . id . h , d86f [ drive ] . format_sector_id . id . r , d86f [ drive ] . format_sector_id . id . n ) ;
}
2016-08-31 22:49:56 +02:00
}
2016-09-14 23:18:14 +02:00
d86f_calccrc ( drive , d86f [ drive ] . track_data_byte ) ;
2016-08-31 22:49:56 +02:00
break ;
case BYTE_DATA :
2016-09-22 21:22:56 +02:00
d86f [ drive ] . id_pos = d86f_get_pos ( drive ) ;
2016-09-03 18:07:46 +02:00
if ( ! disable_write )
2016-08-31 22:49:56 +02:00
{
2016-09-23 01:06:05 +02:00
// d86f_handler[drive].write_data(drive, side, d86f[drive].id_pos, d86f[drive].fill);
d86f_poll_fill ( drive , side ) ;
}
else
{
d86f_calccrc ( drive , d86f [ drive ] . track_data_byte ) ;
2016-08-31 22:49:56 +02:00
}
break ;
case BYTE_ID_CRC :
case BYTE_DATA_CRC :
2016-09-03 18:07:46 +02:00
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-14 23:18:14 +02:00
if ( d86f [ drive ] . track_index )
{
2016-09-23 01:06:05 +02:00
pclog ( " Track position %08X \n " , d86f [ drive ] . track_pos ) ;
pclog ( " Index hole hit again, format finished \n " ) ;
2016-09-14 23:18:14 +02:00
d86f [ drive ] . state = STATE_IDLE ;
2016-09-22 21:22:56 +02:00
if ( ! disable_write ) d86f_handler [ drive ] . writeback ( drive ) ;
2016-09-14 23:18:14 +02:00
fdc_sector_finishread ( drive ) ;
d86f [ drive ] . index_count = 0 ;
return ;
}
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-14 23:18:14 +02:00
case BYTE_IDAM :
case BYTE_DATAAM :
if ( ! d86f_is_mfm ( drive ) )
{
d86f [ drive ] . calc_crc . word = 0xffff ;
}
break ;
case BYTE_IDAM_SYNC :
case BYTE_DATAAM_SYNC :
if ( d86f_is_mfm ( drive ) )
{
d86f [ drive ] . calc_crc . word = 0xffff ;
}
break ;
2016-09-03 18:07:46 +02:00
case BYTE_ID_SYNC :
// pclog("Requesting next sector ID...\n");
fdc_request_next_sector_id ( ) ;
break ;
2016-09-22 21:22:56 +02:00
case BYTE_GAP2 :
2016-09-03 18:07:46 +02:00
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 ( )
{
2016-09-22 21:22:56 +02:00
// int drive = d86f_drive;
int drive = 0 ;
int side = 0 ;
drive = fdc_get_drive ( ) ;
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 ) )
{
2016-09-22 21:22:56 +02:00
if ( d86f [ drive ] . wait_state )
{
d86f_poll_find_nf_wait ( drive , side ) ;
}
else
{
d86f_poll_find_nf ( drive , side ) ;
}
2016-09-03 18:07:46 +02:00
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
}
}