2016-06-26 00:34:39 +02:00
# include "ibm.h"
# include "fdd.h"
# include "disc.h"
# include "disc_img.h"
# include "disc_sector.h"
static struct
{
FILE * f ;
// uint8_t track_data[2][20*1024];
uint8_t track_data [ 2 ] [ 50000 ] ;
int sectors , tracks , sides ;
int sector_size ;
int rate ;
int xdf_type ; /* 0 = not XDF, 1-5 = one of the five XDF types */
int hole ;
int byte_period ;
double bitcell_period_300rpm ;
2016-08-15 03:26:37 +02:00
uint32_t base ;
2016-06-26 00:34:39 +02:00
} img [ 2 ] ;
#if 0
static uint8_t xdf_track0 [ 5 ] [ 3 ] ;
static uint8_t xdf_spt [ 5 ] ;
static uint8_t xdf_map [ 5 ] [ 24 ] [ 3 ] ;
# endif
static uint8_t xdf_track0 [ 3 ] [ 3 ] ;
static uint8_t xdf_spt [ 3 ] ;
static uint8_t xdf_map [ 3 ] [ 24 ] [ 3 ] ;
static uint16_t xdf_track0_layout [ 3 ] [ 92 ] = { { 0x8100 , 0x8200 , 0x8300 , 0x8400 , 0x8500 , 0x8600 , 0x8700 , 0x8800 ,
0x8101 , 0x8201 , 0x0100 , 0x0200 , 0x0300 , 0x0400 , 0x0500 , 0x0600 ,
0x0700 , 0x0800 , 0 , 0x8301 , 0x8401 , 0x8501 , 0x8601 , 0x8701 ,
0x8801 , 0x8901 , 0x8A01 , 0x8B01 , 0x8C01 , 0x8D01 , 0x8E01 , 0x8F01 ,
0x9001 } , /* 5.25" 2HD */
{ 0x8100 , 0x8200 , 0x8300 , 0x8400 , 0x8500 , 0x8600 , 0x8700 , 0x8800 ,
0x8900 , 0x8A00 , 0x8B00 , 0x8101 , 0x0100 , 0x0200 , 0x0300 , 0x0400 ,
0x0500 , 0x0600 , 0x0700 , 0x0800 , 0 , 0 , 0 , 0x8201 ,
0x8301 , 0x8401 , 0x8501 , 0x8601 , 0x8701 , 0x8801 , 0x8901 , 0x8A01 ,
0x8B01 , 0x8C01 , 0x8D01 , 0x8E01 , 0x8F01 , 0 , 0 , 0 ,
0 , 0 , 0x9001 , 0x9101 , 0x9201 , 0x9301 } , /* 3.5" 2HD */
{ 0x8100 , 0x8200 , 0x8300 , 0x8400 , 0x8500 , 0x8600 , 0x8700 , 0x8800 ,
0x8900 , 0x8A00 , 0x8B00 , 0x8C00 , 0x0100 , 0x0200 , 0x0300 , 0x0400 ,
0x0500 , 0x0600 , 0x0700 , 0x0800 , 0x9500 , 0x9600 , 0x9700 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0x8D00 , 0x8E00 , 0x8F00 , 0x9000 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0x9800 , 0x9900 , 0x9A00 ,
0x9B00 , 0x9C00 , 0x9D00 , 0x9E00 , 0x8101 , 0x8201 , 0x8301 , 0x8401 ,
0x8501 , 0x8601 , 0x8701 , 0x9100 , 0x9200 , 0x9300 , 0x9400 , 0x8801 ,
0x8901 , 0x8A01 , 0x8B01 , 0x8C01 , 0x8D01 , 0x8E01 , 0x8F01 , 0x9001 ,
0x9101 , 0x9201 , 0x9301 , 0x9401 , 0x9501 , 0x9601 , 0x9701 , 0x9801 ,
0x9901 , 0x9A01 , 0x9B01 , 0x9C01 , 0x9D01 , 0x9E01 , 0x9F01 , 0xA001 ,
0xA101 , 0xA201 , 0xA301 , 0xA401 } , /* 3.5" 2ED - sectors 0x91 to 0x94 of side 0 are not written to the IMG file but
we read them in from the null - filled areas in order to have them as XDFCOPY
still expects their existence even if it does nothing with them . */
} ;
/* First dimension is possible sector sizes (0 = 128, 7 = 16384), second is possible bit rates (250/360, 250, 300, 500/360, 500, 1000). */
/* Disks formatted at 250 kbps @ 360 RPM can be read with a 360 RPM single-RPM 5.25" drive by setting the rate to 250 kbps.
Disks formatted at 300 kbps @ 300 RPM can be read with any 300 RPM single - RPM drive by setting the rate rate to 300 kbps . */
static uint8_t maximum_sectors [ 8 ] [ 6 ] = { { 26 , 31 , 38 , 53 , 64 , 118 } , /* 128 */
{ 15 , 19 , 23 , 32 , 38 , 73 } , /* 256 */
{ 7 , 10 , 12 , 19 , 23 , 46 } , /* 512 */
{ 3 , 5 , 6 , 9 , 11 , 22 } , /* 1024 */
{ 2 , 2 , 3 , 4 , 5 , 11 } , /* 2048 */
{ 1 , 1 , 1 , 2 , 2 , 5 } , /* 4096 */
{ 0 , 0 , 0 , 1 , 1 , 3 } , /* 8192 */
{ 0 , 0 , 0 , 0 , 0 , 1 } } ; /* 16384 */
static int gap3_sizes [ 5 ] [ 8 ] [ 256 ] = { [ 0 ] [ 1 ] [ 16 ] = 0x54 ,
[ 0 ] [ 2 ] [ 18 ] = 0x6C ,
[ 0 ] [ 2 ] [ 19 ] = 0x48 ,
[ 0 ] [ 2 ] [ 20 ] = 0x2A ,
[ 0 ] [ 2 ] [ 21 ] = 0x0C ,
// [0][2][23] = 0x7A,
[ 0 ] [ 2 ] [ 23 ] = 0x01 ,
// [0][2][24] = 0x38,
[ 2 ] [ 1 ] [ 10 ] = 0x32 ,
[ 2 ] [ 1 ] [ 11 ] = 0x0C ,
[ 2 ] [ 1 ] [ 15 ] = 0x36 ,
[ 2 ] [ 1 ] [ 16 ] = 0x32 ,
[ 2 ] [ 2 ] [ 8 ] = 0x58 ,
[ 2 ] [ 2 ] [ 9 ] = 0x50 ,
[ 2 ] [ 2 ] [ 10 ] = 0x2E ,
[ 2 ] [ 2 ] [ 11 ] = 0x02 ,
[ 2 ] [ 2 ] [ 21 ] = 0x1C ,
[ 2 ] [ 3 ] [ 4 ] = 0xF0 ,
[ 2 ] [ 3 ] [ 5 ] = 0x74 ,
[ 3 ] [ 2 ] [ 36 ] = 0x53 ,
[ 3 ] [ 2 ] [ 39 ] = 0x20 ,
// [3][2][46] = 0x0E,
[ 3 ] [ 2 ] [ 46 ] = 0x01 ,
// [3][2][48] = 0x51,
[ 4 ] [ 1 ] [ 32 ] = 0x36 ,
[ 4 ] [ 2 ] [ 15 ] = 0x54 ,
[ 4 ] [ 2 ] [ 17 ] = 0x23 ,
[ 4 ] [ 2 ] [ 18 ] = 0x02 ,
// [4][2][19] = 0x29,
[ 4 ] [ 2 ] [ 19 ] = 0x01 ,
[ 4 ] [ 3 ] [ 8 ] = 0x74 ,
[ 4 ] [ 3 ] [ 9 ] = 0x74 ,
[ 4 ] [ 3 ] [ 10 ] = 0x74
} ;
/* Needed for formatting! */
int img_realtrack ( int drive , int track )
{
# ifdef MAINLINE
if ( ( img [ drive ] . tracks < = 41 ) & & fdd_doublestep_40 ( drive ) )
# else
if ( ( img [ drive ] . tracks < = 43 ) & & fdd_doublestep_40 ( drive ) )
# endif
track / = 2 ;
return track ;
}
void img_writeback ( int drive , int track ) ;
static int img_sector_size_code ( int drive )
{
switch ( img [ drive ] . sector_size )
{
case 128 :
return 0 ;
case 256 :
return 1 ;
default :
case 512 :
return 2 ;
case 1024 :
return 3 ;
case 2048 :
return 4 ;
case 4096 :
return 5 ;
case 8192 :
return 6 ;
case 16384 :
return 7 ;
}
}
static int sector_size_code ( int sector_size )
{
switch ( sector_size )
{
case 128 :
return 0 ;
case 256 :
return 1 ;
default :
case 512 :
return 2 ;
case 1024 :
return 3 ;
case 2048 :
return 4 ;
case 4096 :
return 5 ;
case 8192 :
return 6 ;
case 16384 :
return 7 ;
}
}
void img_init ( )
{
memset ( img , 0 , sizeof ( img ) ) ;
// adl[0] = adl[1] = 0;
}
static void add_to_map ( uint8_t * arr , uint8_t p1 , uint8_t p2 , uint8_t p3 )
{
arr [ 0 ] = p1 ;
arr [ 1 ] = p2 ;
arr [ 2 ] = p3 ;
}
static int xdf_maps_initialized = 0 ;
static void initialize_xdf_maps ( )
{
// XDF 5.25" 2HD
/* Adds, in this order: sectors per FAT, sectors per each side of track 0, difference between that and virtual sector number specified in BPB. */
add_to_map ( xdf_track0 [ 0 ] , 9 , 17 , 2 ) ;
xdf_spt [ 0 ] = 3 ;
/* Adds, in this order: side, sequential order (not used in PCem), sector size. */
add_to_map ( xdf_map [ 0 ] [ 0 ] , 0 , 0 , 3 ) ;
add_to_map ( xdf_map [ 0 ] [ 1 ] , 0 , 2 , 6 ) ;
add_to_map ( xdf_map [ 0 ] [ 2 ] , 1 , 0 , 2 ) ;
add_to_map ( xdf_map [ 0 ] [ 3 ] , 0 , 1 , 2 ) ;
add_to_map ( xdf_map [ 0 ] [ 4 ] , 1 , 2 , 6 ) ;
add_to_map ( xdf_map [ 0 ] [ 5 ] , 1 , 1 , 3 ) ;
// XDF 3.5" 2HD
add_to_map ( xdf_track0 [ 1 ] , 11 , 19 , 4 ) ;
xdf_spt [ 1 ] = 4 ;
add_to_map ( xdf_map [ 1 ] [ 0 ] , 0 , 0 , 3 ) ;
add_to_map ( xdf_map [ 1 ] [ 1 ] , 0 , 2 , 4 ) ;
add_to_map ( xdf_map [ 1 ] [ 2 ] , 1 , 3 , 6 ) ;
add_to_map ( xdf_map [ 1 ] [ 3 ] , 0 , 1 , 2 ) ;
add_to_map ( xdf_map [ 1 ] [ 4 ] , 1 , 1 , 2 ) ;
add_to_map ( xdf_map [ 1 ] [ 5 ] , 0 , 3 , 6 ) ;
add_to_map ( xdf_map [ 1 ] [ 6 ] , 1 , 0 , 4 ) ;
add_to_map ( xdf_map [ 1 ] [ 7 ] , 1 , 2 , 3 ) ;
// XDF 3.5" 2ED
add_to_map ( xdf_track0 [ 2 ] , 22 , 37 , 9 ) ;
xdf_spt [ 2 ] = 4 ;
add_to_map ( xdf_map [ 2 ] [ 0 ] , 0 , 0 , 3 ) ;
add_to_map ( xdf_map [ 2 ] [ 1 ] , 0 , 1 , 4 ) ;
add_to_map ( xdf_map [ 2 ] [ 2 ] , 0 , 2 , 5 ) ;
add_to_map ( xdf_map [ 2 ] [ 3 ] , 0 , 3 , 7 ) ;
add_to_map ( xdf_map [ 2 ] [ 4 ] , 1 , 0 , 3 ) ;
add_to_map ( xdf_map [ 2 ] [ 5 ] , 1 , 1 , 4 ) ;
add_to_map ( xdf_map [ 2 ] [ 6 ] , 1 , 2 , 5 ) ;
add_to_map ( xdf_map [ 2 ] [ 7 ] , 1 , 3 , 7 ) ;
#if 0
// XXDF 3.5" 2HD
add_to_map ( xdf_track0 [ 3 ] , 12 , 20 , 4 ) ;
xdf_spt [ 3 ] = 2 ;
add_to_map ( xdf_map [ 3 ] [ 0 ] , 0 , 0 , 5 ) ;
add_to_map ( xdf_map [ 3 ] [ 1 ] , 1 , 1 , 6 ) ;
add_to_map ( xdf_map [ 3 ] [ 2 ] , 0 , 1 , 6 ) ;
add_to_map ( xdf_map [ 3 ] [ 3 ] , 1 , 0 , 5 ) ;
// XXDF 3.5" 2ED
add_to_map ( xdf_track0 [ 4 ] , 21 , 39 , 9 ) ;
xdf_spt [ 4 ] = 2 ;
add_to_map ( xdf_map [ 4 ] [ 0 ] , 0 , 0 , 6 ) ;
add_to_map ( xdf_map [ 4 ] [ 1 ] , 1 , 1 , 7 ) ;
add_to_map ( xdf_map [ 4 ] [ 2 ] , 0 , 1 , 7 ) ;
add_to_map ( xdf_map [ 4 ] [ 3 ] , 1 , 0 , 6 ) ;
# endif
xdf_maps_initialized = 1 ;
}
void img_load ( int drive , char * fn )
{
int size ;
double bit_rate_300 ;
uint16_t bpb_bps ;
uint16_t bpb_total ;
uint8_t bpb_mid ; /* Media type ID. */
uint8_t bpb_sectors ;
uint8_t bpb_sides ;
uint32_t bpt ;
uint8_t max_spt ; /* Used for XDF detection. */
int temp_rate ;
2016-08-15 03:26:37 +02:00
char ext [ 4 ] ;
int fdi ;
2016-06-26 00:34:39 +02:00
if ( ! xdf_maps_initialized ) initialize_xdf_maps ( ) ; /* Initialize XDF maps, will need them to properly register sectors in tracks. */
2016-08-15 03:26:37 +02:00
ext [ 0 ] = fn [ strlen ( fn ) - 3 ] | 0x60 ;
ext [ 1 ] = fn [ strlen ( fn ) - 2 ] | 0x60 ;
ext [ 2 ] = fn [ strlen ( fn ) - 1 ] | 0x60 ;
ext [ 3 ] = 0 ;
writeprot [ drive ] = 0 ;
2016-06-26 00:34:39 +02:00
img [ drive ] . f = fopen ( fn , " rb+ " ) ;
if ( ! img [ drive ] . f )
{
img [ drive ] . f = fopen ( fn , " rb " ) ;
if ( ! img [ drive ] . f )
return ;
writeprot [ drive ] = 1 ;
}
fwriteprot [ drive ] = writeprot [ drive ] ;
2016-08-15 03:26:37 +02:00
if ( strcmp ( ext , " fdi " ) = = 0 )
{
/* This is a Japanese FDI image, so let's read the header */
pclog ( " img_load(): File is a Japanese FDI image... \n " ) ;
fseek ( img [ drive ] . f , 0x10 , SEEK_SET ) ;
fread ( & bpb_bps , 1 , 2 , img [ drive ] . f ) ;
fseek ( img [ drive ] . f , 0x0C , SEEK_SET ) ;
fread ( & size , 1 , 4 , img [ drive ] . f ) ;
bpb_total = size / bpb_bps ;
fseek ( img [ drive ] . f , 0x08 , SEEK_SET ) ;
fread ( & ( img [ drive ] . base ) , 1 , 4 , img [ drive ] . f ) ;
fseek ( img [ drive ] . f , base + 0x15 , SEEK_SET ) ;
bpb_mid = fgetc ( img [ drive ] . f ) ;
if ( bpb_mid < 0xF0 ) bpb_mid = 0xF0 ;
fseek ( img [ drive ] . f , 0x14 , SEEK_SET ) ;
bpb_sectors = fgetc ( img [ drive ] . f ) ;
fseek ( img [ drive ] . f , 0x18 , SEEK_SET ) ;
bpb_sides = fgetc ( img [ drive ] . f ) ;
fdi = 1 ;
}
else
{
/* Read the BPB */
pclog ( " img_load(): File is a raw image... \n " ) ;
fseek ( img [ drive ] . f , 0x0B , SEEK_SET ) ;
fread ( & bpb_bps , 1 , 2 , img [ drive ] . f ) ;
fseek ( img [ drive ] . f , 0x13 , SEEK_SET ) ;
fread ( & bpb_total , 1 , 2 , img [ drive ] . f ) ;
fseek ( img [ drive ] . f , 0x15 , SEEK_SET ) ;
bpb_mid = fgetc ( img [ drive ] . f ) ;
fseek ( img [ drive ] . f , 0x18 , SEEK_SET ) ;
bpb_sectors = fgetc ( img [ drive ] . f ) ;
fseek ( img [ drive ] . f , 0x1A , SEEK_SET ) ;
bpb_sides = fgetc ( img [ drive ] . f ) ;
base = 0 ;
fdi = 0 ;
fseek ( img [ drive ] . f , - 1 , SEEK_END ) ;
size = ftell ( img [ drive ] . f ) + 1 ;
}
2016-06-26 00:34:39 +02:00
img [ drive ] . sides = 2 ;
img [ drive ] . sector_size = 512 ;
img [ drive ] . hole = 0 ;
pclog ( " BPB reports %i sides and %i bytes per sector \n " , bpb_sides , bpb_bps ) ;
2016-08-15 03:26:37 +02:00
if ( ( ( bpb_sides < 1 ) | | ( bpb_sides > 2 ) | | ( bpb_bps < 128 ) | | ( bpb_bps > 2048 ) ) & & ! fdi )
2016-06-26 00:34:39 +02:00
{
/* The BPB is giving us a wacky number of sides and/or bytes per sector, therefore it is most probably
not a BPB at all , so we have to guess the parameters from file size . */
if ( size < = ( 160 * 1024 ) ) { img [ drive ] . sectors = 8 ; img [ drive ] . tracks = 40 ; img [ drive ] . sides = 1 ; bit_rate_300 = 250 ; raw_tsize [ drive ] = 6250 ; }
else if ( size < = ( 180 * 1024 ) ) { img [ drive ] . sectors = 9 ; img [ drive ] . tracks = 40 ; img [ drive ] . sides = 1 ; bit_rate_300 = 250 ; raw_tsize [ drive ] = 6250 ; }
else if ( size < = ( 320 * 1024 ) ) { img [ drive ] . sectors = 8 ; img [ drive ] . tracks = 40 ; bit_rate_300 = 250 ; raw_tsize [ drive ] = 6250 ; }
else if ( size < = ( 360 * 1024 ) ) { img [ drive ] . sectors = 9 ; img [ drive ] . tracks = 40 ; bit_rate_300 = 250 ; raw_tsize [ drive ] = 6250 ; } /*Double density*/
else if ( size < = ( 640 * 1024 ) ) { img [ drive ] . sectors = 8 ; img [ drive ] . tracks = 80 ; bit_rate_300 = 250 ; raw_tsize [ drive ] = 6250 ; } /*Double density 640k*/
else if ( size < ( 1024 * 1024 ) ) { img [ drive ] . sectors = 9 ; img [ drive ] . tracks = 80 ; bit_rate_300 = 250 ; raw_tsize [ drive ] = 6250 ; } /*Double density*/
else if ( size < = 1228800 ) { img [ drive ] . sectors = 15 ; img [ drive ] . tracks = 80 ; bit_rate_300 = ( 500.0 * 300.0 ) / 360.0 ; raw_tsize [ drive ] = 10416 ; } /*High density 1.2MB*/
else if ( size < = 1261568 ) { img [ drive ] . sectors = 8 ; img [ drive ] . tracks = 77 ; img [ drive ] . sector_size = 1024 ; bit_rate_300 = ( 500.0 * 300.0 ) / 360.0 ; raw_tsize [ drive ] = 10416 ; } /*High density 1.25MB Japanese format*/
else if ( size < = ( 0x1A4000 - 1 ) ) { img [ drive ] . sectors = 18 ; img [ drive ] . tracks = 80 ; bit_rate_300 = 500 ; raw_tsize [ drive ] = 12500 ; } /*High density (not supported by Tandy 1000)*/
else if ( size < = 1556480 ) { img [ drive ] . sectors = 19 ; img [ drive ] . tracks = 80 ; bit_rate_300 = 500 ; raw_tsize [ drive ] = 12500 ; } /*High density (not supported by Tandy 1000)*/
else if ( size < = 1638400 ) { img [ drive ] . sectors = 10 ; img [ drive ] . tracks = 80 ; img [ drive ] . sector_size = 1024 ; bit_rate_300 = 500 ; raw_tsize [ drive ] = 12500 ; } /*High density (not supported by Tandy 1000)*/
// else if (size == 1884160) { img[drive].sectors = 23; img[drive].tracks = 80; bit_rate_300 = 500; } /*XDF format - used by OS/2 Warp*/
// else if (size == 1763328) { img[drive].sectors = 21; img[drive].tracks = 82; bit_rate_300 = 500; } /*XDF format - used by OS/2 Warp*/
else if ( size < = 2000000 ) { img [ drive ] . sectors = 21 ; img [ drive ] . tracks = 80 ; bit_rate_300 = 500 ; raw_tsize [ drive ] = 12500 ; } /*DMF format - used by Windows 95 - changed by OBattler to 2000000, ie. the real unformatted capacity @ 500 kbps and 300 rpm */
else if ( size < = 2949120 ) { img [ drive ] . sectors = 36 ; img [ drive ] . tracks = 80 ; bit_rate_300 = 1000 ; raw_tsize [ drive ] = 25000 ; } /*E density*/
2016-07-19 02:44:32 +02:00
temp_rate = 2 ;
bpb_bps = img [ drive ] . sector_size ;
bpt = bpb_bps * img [ drive ] . sectors ;
if ( bpt < = ( maximum_sectors [ sector_size_code ( bpb_bps ) ] [ 0 ] * bpb_bps ) )
{
temp_rate = 2 ;
raw_tsize [ drive ] = 5208 ;
}
else if ( bpt < = ( maximum_sectors [ sector_size_code ( bpb_bps ) ] [ 1 ] * bpb_bps ) )
{
temp_rate = 2 ;
raw_tsize [ drive ] = 6250 ;
}
else if ( bpt < = ( maximum_sectors [ sector_size_code ( bpb_bps ) ] [ 2 ] * bpb_bps ) )
{
temp_rate = 1 ;
raw_tsize [ drive ] = 7500 ;
}
else if ( bpt < = ( maximum_sectors [ sector_size_code ( bpb_bps ) ] [ 3 ] * bpb_bps ) )
{
if ( bpb_bps = = 512 ) max_spt = ( bit_rate_300 = = 500 ) ? 21 : 17 ;
temp_rate = ( bit_rate_300 = = 500 ) ? 0 : 4 ;
raw_tsize [ drive ] = ( bit_rate_300 = = 500 ) ? 12500 : 10416 ;
}
else if ( bpt < = ( maximum_sectors [ sector_size_code ( bpb_bps ) ] [ 4 ] * bpb_bps ) )
{
if ( bpb_bps = = 512 ) max_spt = 21 ;
pclog ( " max_spt is %i \n " , max_spt ) ;
temp_rate = 0 ;
raw_tsize [ drive ] = 12500 ;
}
else if ( bpt < = ( maximum_sectors [ sector_size_code ( bpb_bps ) ] [ 5 ] * bpb_bps ) )
{
if ( bpb_bps = = 512 ) max_spt = 41 ;
temp_rate = 3 ;
raw_tsize [ drive ] = 25000 ;
}
else /* Image too big, eject */
{
pclog ( " Image is bigger than can fit on an ED floppy, ejecting... \n " ) ;
fclose ( img [ drive ] . f ) ;
return ;
}
pclog ( " Temporary rate: %i (%i bytes per track) \n " , temp_rate , bpt ) ;
2016-06-26 00:34:39 +02:00
img [ drive ] . xdf_type = 0 ;
}
else
{
/* The BPB readings appear to be valid, so let's set the values. */
/* Number of tracks = number of total sectors divided by sides times sectors per track. */
2016-08-15 03:26:37 +02:00
if ( fdi )
{
/* The image is a Japanese FDI, therefore we read the number of tracks from the header. */
fseek ( img [ drive ] . f , 0x1C , SEEK_SET ) ;
fread ( & ( img [ drive ] . tracks ) , 1 , 4 , img [ drive ] . f ) ;
}
else
{
img [ drive ] . tracks = ( ( uint32_t ) bpb_total ) / ( ( ( uint32_t ) bpb_sides ) * ( ( uint32_t ) bpb_sectors ) ) ;
}
2016-06-26 00:34:39 +02:00
/* The rest we just set directly from the BPB. */
img [ drive ] . sectors = bpb_sectors ;
img [ drive ] . sides = bpb_sides ;
2016-07-27 04:32:08 +02:00
/* The sector size. */
img [ drive ] . sector_size = bpb_bps ;
2016-06-26 00:34:39 +02:00
/* Now we calculate bytes per track, which is bpb_sectors * bpb_bps. */
bpt = ( uint32_t ) bpb_sectors * ( uint32_t ) bpb_bps ;
/* Now we should be able to calculate the bit rate. */
pclog ( " The image has %i bytes per track \n " , bpt ) ;
temp_rate = 2 ;
if ( bpt < = ( maximum_sectors [ sector_size_code ( bpb_bps ) ] [ 0 ] * bpb_bps ) )
{
bit_rate_300 = ( ( 250.0 * 300.0 ) / 360.0 ) ;
temp_rate = 2 ;
raw_tsize [ drive ] = 5208 ;
}
else if ( bpt < = ( maximum_sectors [ sector_size_code ( bpb_bps ) ] [ 1 ] * bpb_bps ) )
{
bit_rate_300 = 250 ;
temp_rate = 2 ;
raw_tsize [ drive ] = 6250 ;
}
else if ( bpt < = ( maximum_sectors [ sector_size_code ( bpb_bps ) ] [ 2 ] * bpb_bps ) )
{
bit_rate_300 = 300 ;
temp_rate = 1 ;
raw_tsize [ drive ] = 7500 ;
}
else if ( bpt < = ( maximum_sectors [ sector_size_code ( bpb_bps ) ] [ 3 ] * bpb_bps ) )
{
bit_rate_300 = ( bpb_mid = = 0xF0 ) ? 500 : ( ( 500.0 * 300.0 ) / 360.0 ) ;
if ( bpb_bps = = 512 ) max_spt = ( bit_rate_300 = = 500 ) ? 21 : 17 ;
temp_rate = ( bit_rate_300 = = 500 ) ? 0 : 4 ;
raw_tsize [ drive ] = ( bit_rate_300 = = 500 ) ? 12500 : 10416 ;
}
else if ( bpt < = ( maximum_sectors [ sector_size_code ( bpb_bps ) ] [ 4 ] * bpb_bps ) )
{
bit_rate_300 = 500 ;
if ( bpb_bps = = 512 ) max_spt = 21 ;
pclog ( " max_spt is %i \n " , max_spt ) ;
temp_rate = 0 ;
raw_tsize [ drive ] = 12500 ;
}
else if ( bpt < = ( maximum_sectors [ sector_size_code ( bpb_bps ) ] [ 5 ] * bpb_bps ) )
{
bit_rate_300 = 1000 ;
if ( bpb_bps = = 512 ) max_spt = 41 ;
temp_rate = 3 ;
raw_tsize [ drive ] = 25000 ;
}
else /* Image too big, eject */
{
pclog ( " Image is bigger than can fit on an ED floppy, ejecting... \n " ) ;
fclose ( img [ drive ] . f ) ;
return ;
}
if ( bpb_bps = = 512 ) /* BPB reports 512 bytes per sector, let's see if it's XDF or not */
{
if ( bit_rate_300 < = 300 ) /* Double-density disk, not XDF */
{
img [ drive ] . xdf_type = 0 ;
}
else
{
pclog ( " bpb_sectors is %i \n " , bpb_sectors ) ;
if ( bpb_sectors > max_spt )
{
switch ( bpb_sectors )
{
case 19 : /* High density XDF @ 360 rpm */
img [ drive ] . xdf_type = 1 ;
break ;
case 23 : /* High density XDF @ 300 rpm */
img [ drive ] . xdf_type = 2 ;
pclog ( " XDF type is 2 @ %i kbps \n " , bit_rate_300 ) ;
break ;
#if 0
case 24 : /* High density XXDF @ 300 rpm */
img [ drive ] . xdf_type = 4 ;
break ;
# endif
case 46 : /* Extended density XDF */
img [ drive ] . xdf_type = 3 ;
break ;
#if 0
case 48 : /* Extended density XXDF */
img [ drive ] . xdf_type = 5 ;
break ;
# endif
default : /* Unknown, as we're beyond maximum sectors, get out */
fclose ( img [ drive ] . f ) ;
return ;
}
}
else /* Amount of sectors per track that fits into a track, therefore not XDF */
{
img [ drive ] . xdf_type = 0 ;
}
}
}
else /* BPB reports sector size other than 512, can't possibly be XDF */
{
img [ drive ] . xdf_type = 0 ;
}
}
gap2_size [ drive ] = ( temp_rate = = 3 ) ? 41 : 22 ;
pclog ( " GAP2 size: %i bytes \n " , gap2_size [ drive ] ) ;
gap3_size [ drive ] = gap3_sizes [ temp_rate ] [ sector_size_code ( img [ drive ] . sector_size ) ] [ img [ drive ] . sectors ] ;
if ( gap3_size )
{
pclog ( " GAP3 size: %i bytes \n " , gap3_size [ drive ] ) ;
}
else
{
// fclose(img[drive].f);
gap3_size [ drive ] = 40 ;
pclog ( " WARNING: Floppy image of unknown format was inserted into drive %c:! \n " , drive + 0x41 ) ;
}
2016-07-19 02:44:32 +02:00
gap4_size [ drive ] = raw_tsize [ drive ] - ( ( ( pre_gap + gap2_size [ drive ] + pre_data + img [ drive ] . sector_size + post_gap + gap3_size [ drive ] ) * img [ drive ] . sectors ) + pre_track ) ;
2016-06-26 00:34:39 +02:00
pclog ( " GAP4 size: %i bytes \n " , gap4_size [ drive ] ) ;
if ( img [ drive ] . xdf_type )
{
gap4_size [ drive ] = 1 ;
}
if ( bit_rate_300 = = 250 )
{
img [ drive ] . hole = 0 ;
/* If drive does not support 300 RPM, the medium is to be read at a period of 26 (300 kbps). */
img [ drive ] . byte_period = 29 ;
}
else if ( bit_rate_300 = = 300 )
{
img [ drive ] . hole = 0 ;
img [ drive ] . byte_period = 26 ;
}
else if ( bit_rate_300 = = 1000 )
{
img [ drive ] . hole = 2 ;
img [ drive ] . byte_period = 8 ;
}
else if ( bit_rate_300 < 250 )
{
img [ drive ] . hole = 0 ;
img [ drive ] . byte_period = 32 ;
}
else
{
img [ drive ] . hole = 1 ;
img [ drive ] . byte_period = 16 ;
}
if ( img [ drive ] . xdf_type ) /* In case of XDF-formatted image, write-protect */
{
writeprot [ drive ] = 1 ;
fwriteprot [ drive ] = writeprot [ drive ] ;
}
drives [ drive ] . seek = img_seek ;
drives [ drive ] . readsector = disc_sector_readsector ;
drives [ drive ] . writesector = disc_sector_writesector ;
drives [ drive ] . readaddress = disc_sector_readaddress ;
drives [ drive ] . hole = img_hole ;
drives [ drive ] . byteperiod = img_byteperiod ;
drives [ drive ] . poll = disc_sector_poll ;
drives [ drive ] . format = disc_sector_format ;
drives [ drive ] . realtrack = img_realtrack ;
drives [ drive ] . stop = disc_sector_stop ;
disc_sector_writeback [ drive ] = img_writeback ;
img [ drive ] . bitcell_period_300rpm = 1000000.0 / bit_rate_300 * 2.0 ;
pclog ( " bit_rate_300=%g \n " , bit_rate_300 ) ;
pclog ( " bitcell_period_300=%g \n " , img [ drive ] . bitcell_period_300rpm ) ;
// img[drive].bitcell_period_300rpm = disc_get_bitcell_period(img[drive].rate);
pclog ( " img_load %d %p sectors=%i tracks=%i sides=%i sector_size=%i hole=%i \n " , drive , drives , img [ drive ] . sectors , img [ drive ] . tracks , img [ drive ] . sides , img [ drive ] . sector_size , img [ drive ] . hole ) ;
}
int img_hole ( int drive )
{
return img [ drive ] . hole ;
}
int img_byteperiod ( int drive )
{
if ( img [ drive ] . byte_period = = 29 )
{
return ( fdd_get_type ( drive ) & 1 ) ? 32 : 26 ;
}
return img [ drive ] . byte_period ;
}
void img_close ( int drive )
{
if ( img [ drive ] . f )
fclose ( img [ drive ] . f ) ;
img [ drive ] . f = NULL ;
}
void img_seek ( int drive , int track )
{
int side ;
int current_xdft = img [ drive ] . xdf_type - 1 ;
uint8_t sectors_fat , effective_sectors , sector_gap ; /* Needed for XDF */
2016-08-01 19:14:54 +02:00
int sector , current_pos , sh , sr , spos , sside ;
2016-06-26 00:34:39 +02:00
if ( ! img [ drive ] . f )
return ;
// pclog("Seek drive=%i track=%i sectors=%i sector_size=%i sides=%i\n", drive, track, img[drive].sectors,img[drive].sector_size, img[drive].sides);
// pclog(" %i %i\n", drive_type[drive], img[drive].tracks);
# ifdef MAINLINE
if ( ( img [ drive ] . tracks < = 41 ) & & fdd_doublestep_40 ( drive ) )
# else
if ( ( img [ drive ] . tracks < = 43 ) & & fdd_doublestep_40 ( drive ) )
# endif
track / = 2 ;
// pclog("Disk seeked to track %i\n", track);
disc_track [ drive ] = track ;
if ( img [ drive ] . sides = = 2 )
{
2016-08-15 03:26:37 +02:00
fseek ( img [ drive ] . f , base + ( track * img [ drive ] . sectors * img [ drive ] . sector_size * 2 ) , SEEK_SET ) ;
2016-06-26 00:34:39 +02:00
// pclog("Seek: Current file position (H0) is: %08X\n", ftell(img[drive].f));
fread ( img [ drive ] . track_data [ 0 ] , img [ drive ] . sectors * img [ drive ] . sector_size , 1 , img [ drive ] . f ) ;
// pclog("Seek: Current file position (H1) is: %08X\n", ftell(img[drive].f));
fread ( img [ drive ] . track_data [ 1 ] , img [ drive ] . sectors * img [ drive ] . sector_size , 1 , img [ drive ] . f ) ;
}
else
{
2016-08-15 03:26:37 +02:00
fseek ( img [ drive ] . f , base + ( track * img [ drive ] . sectors * img [ drive ] . sector_size ) , SEEK_SET ) ;
2016-06-26 00:34:39 +02:00
fread ( img [ drive ] . track_data [ 0 ] , img [ drive ] . sectors * img [ drive ] . sector_size , 1 , img [ drive ] . f ) ;
}
disc_sector_reset ( drive , 0 ) ;
disc_sector_reset ( drive , 1 ) ;
if ( img [ drive ] . xdf_type )
{
sectors_fat = xdf_track0 [ current_xdft ] [ 0 ] ;
effective_sectors = xdf_track0 [ current_xdft ] [ 1 ] ;
sector_gap = xdf_track0 [ current_xdft ] [ 2 ] ;
if ( ! track )
{
/* Track 0, register sectors according to track 0 layout. */
current_pos = 0 ;
for ( sector = 0 ; sector < ( img [ drive ] . sectors * 2 ) ; sector + + )
{
if ( xdf_track0_layout [ current_xdft ] [ sector ] )
{
sh = xdf_track0_layout [ current_xdft ] [ sector ] & 0xFF ;
sr = xdf_track0_layout [ current_xdft ] [ sector ] > > 8 ;
spos = current_pos ;
sside = 0 ;
if ( spos > ( img [ drive ] . sectors * img [ drive ] . sector_size ) )
{
spos - = ( img [ drive ] . sectors * img [ drive ] . sector_size ) ;
sside = 1 ;
}
disc_sector_add ( drive , sh , track , sh , sr , 2 ,
img [ drive ] . bitcell_period_300rpm ,
& img [ drive ] . track_data [ sside ] [ spos ] ) ;
}
current_pos + = 512 ;
}
#if 0
/* Track 0, register sectors according to track 0 map. */
/* First, the "Side 0" buffer, will also contain one sector from side 1. */
current_pos = 0 ;
for ( sector = 0 ; sector < sectors_fat ; sector + + )
{
if ( ( sector + 0x81 ) > = 0x91 )
{
disc_sector_add ( drive , 0 , track , 0 , sector + 0x85 , 2 ,
img [ drive ] . bitcell_period_300rpm ,
& img [ drive ] . track_data [ 0 ] [ current_pos ] ) ;
}
else
{
disc_sector_add ( drive , 0 , track , 0 , sector + 0x81 , 2 ,
img [ drive ] . bitcell_period_300rpm ,
& img [ drive ] . track_data [ 0 ] [ current_pos ] ) ;
}
current_pos + = 512 ;
}
disc_sector_add ( drive , 1 , track , 1 , 0x81 , 2 ,
img [ drive ] . bitcell_period_300rpm ,
& img [ drive ] . track_data [ 0 ] [ current_pos ] ) ;
current_pos + = 512 ;
for ( sector = 0 ; sector < 7 ; sector + + )
{
disc_sector_add ( drive , 0 , track , 0 , sector + 1 , 2 ,
img [ drive ] . bitcell_period_300rpm ,
& img [ drive ] . track_data [ 0 ] [ current_pos ] ) ;
current_pos + = 512 ;
}
disc_sector_add ( drive , 0 , track , 0 , 0x9B , 2 ,
img [ drive ] . bitcell_period_300rpm ,
& img [ drive ] . track_data [ 0 ] [ current_pos ] ) ;
current_pos + = 512 ;
disc_sector_add ( drive , 0 , track , 0 , 0x9C , 2 ,
img [ drive ] . bitcell_period_300rpm ,
& img [ drive ] . track_data [ 0 ] [ current_pos ] ) ;
current_pos + = 512 ;
disc_sector_add ( drive , 0 , track , 0 , 0x9D , 2 ,
img [ drive ] . bitcell_period_300rpm ,
& img [ drive ] . track_data [ 0 ] [ current_pos ] ) ;
current_pos + = 512 ;
disc_sector_add ( drive , 0 , track , 0 , 0x9E , 2 ,
img [ drive ] . bitcell_period_300rpm ,
& img [ drive ] . track_data [ 0 ] [ current_pos ] ) ;
current_pos + = 512 ;
/* Now the "Side 1" buffer, will also contain one sector from side 0. */
current_pos = 0 ;
for ( sector = 0 ; ( sector < effective_sectors - 1 ) ; sector + + )
{
disc_sector_add ( drive , 1 , track , 1 , sector + 0x82 , 2 ,
img [ drive ] . bitcell_period_300rpm ,
& img [ drive ] . track_data [ 1 ] [ current_pos ] ) ;
current_pos + = 512 ;
}
disc_sector_add ( drive , 0 , track , 0 , 8 , 2 ,
img [ drive ] . bitcell_period_300rpm ,
& img [ drive ] . track_data [ 1 ] [ current_pos ] ) ;
current_pos + = 512 ;
# endif
}
else
{
/* Non-zero track, this will have sectors of various sizes. */
/* First, the "Side 0" buffer. */
current_pos = 0 ;
for ( sector = 0 ; sector < xdf_spt [ current_xdft ] ; sector + + )
{
disc_sector_add ( drive , xdf_map [ current_xdft ] [ sector ] [ 0 ] , track , xdf_map [ current_xdft ] [ sector ] [ 0 ] ,
xdf_map [ current_xdft ] [ sector ] [ 2 ] + 0x80 , xdf_map [ current_xdft ] [ sector ] [ 2 ] ,
img [ drive ] . bitcell_period_300rpm ,
& img [ drive ] . track_data [ 0 ] [ current_pos ] ) ;
current_pos + = ( 128 < < xdf_map [ current_xdft ] [ sector ] [ 2 ] ) ;
}
/* Then, the "Side 1" buffer. */
current_pos = 0 ;
for ( sector = xdf_spt [ current_xdft ] ; sector < ( xdf_spt [ current_xdft ] < < 1 ) ; sector + + )
{
disc_sector_add ( drive , xdf_map [ current_xdft ] [ sector ] [ 0 ] , track , xdf_map [ current_xdft ] [ sector ] [ 0 ] ,
xdf_map [ current_xdft ] [ sector ] [ 2 ] + 0x80 , xdf_map [ current_xdft ] [ sector ] [ 2 ] ,
img [ drive ] . bitcell_period_300rpm ,
& img [ drive ] . track_data [ 1 ] [ current_pos ] ) ;
current_pos + = ( 128 < < xdf_map [ current_xdft ] [ sector ] [ 2 ] ) ;
}
}
}
else
{
for ( side = 0 ; side < img [ drive ] . sides ; side + + )
{
for ( sector = 0 ; sector < img [ drive ] . sectors ; sector + + )
disc_sector_add ( drive , side , track , side , sector + 1 , img_sector_size_code ( drive ) ,
img [ drive ] . bitcell_period_300rpm ,
& img [ drive ] . track_data [ side ] [ sector * img [ drive ] . sector_size ] ) ;
}
}
2016-08-15 01:34:46 +02:00
for ( side = img [ drive ] . sides - 1 ; side > = 0 ; side - - )
{
disc_sector_prepare_track_layout ( drive , side ) ;
}
2016-06-26 00:34:39 +02:00
}
2016-08-15 01:34:46 +02:00
2016-06-26 00:34:39 +02:00
void img_writeback ( int drive , int track )
{
if ( ! img [ drive ] . f )
return ;
if ( img [ drive ] . xdf_type )
return ; /*Should never happen*/
if ( img [ drive ] . sides = = 2 )
{
2016-08-15 03:26:37 +02:00
fseek ( img [ drive ] . f , base + ( track * img [ drive ] . sectors * img [ drive ] . sector_size * 2 ) , SEEK_SET ) ;
2016-06-26 00:34:39 +02:00
fwrite ( img [ drive ] . track_data [ 0 ] , img [ drive ] . sectors * img [ drive ] . sector_size , 1 , img [ drive ] . f ) ;
fwrite ( img [ drive ] . track_data [ 1 ] , img [ drive ] . sectors * img [ drive ] . sector_size , 1 , img [ drive ] . f ) ;
}
else
{
2016-08-15 03:26:37 +02:00
fseek ( img [ drive ] . f , base + ( track * img [ drive ] . sectors * img [ drive ] . sector_size ) , SEEK_SET ) ;
2016-06-26 00:34:39 +02:00
fwrite ( img [ drive ] . track_data [ 0 ] , img [ drive ] . sectors * img [ drive ] . sector_size , 1 , img [ drive ] . f ) ;
}
}