FDC changes :
- Seperated disk and disk drive emulation - Support more drive types - 5.25" dual RPM, 3.5" DD, 3.5" HD, 3.5" HD 3-Mode - Support drive swapping (FDC37c665 only) - Support FDC FIFO - Support other FDC 'enhanced mode' behaviour - Support IBM XDF format images - Formatting now formats both tracks, and uses correct 'fill' byte - Various other improvements Many of these changes provided by Battler
This commit is contained in:
parent
2ca86ba028
commit
eebdc165b2
16 changed files with 1530 additions and 340 deletions
|
|
@ -5,7 +5,7 @@ WINDRES = windres.exe
|
|||
CFLAGS = -O3 -march=i686 -fomit-frame-pointer
|
||||
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o \
|
||||
codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_pentium.o codegen_x86.o compaq.o config.o cpu.o dac.o \
|
||||
device.o disc.o disc_fdi.o disc_img.o dma.o fdc.o fdc37c665.o fdi2raw.o gameport.o headland.o i430lx.o i430fx.o \
|
||||
device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o headland.o i430lx.o i430fx.o \
|
||||
i430vx.o ide.o intel.o intel_flash.o io.o jim.o keyboard.o keyboard_amstrad.o keyboard_at.o \
|
||||
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o model.o mouse.o mouse_ps2.o \
|
||||
mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o \
|
||||
|
|
|
|||
93
src/disc.c
93
src/disc.c
|
|
@ -5,6 +5,7 @@
|
|||
#include "disc_fdi.h"
|
||||
#include "disc_img.h"
|
||||
#include "fdc.h"
|
||||
#include "fdd.h"
|
||||
#include "timer.h"
|
||||
|
||||
int disc_drivesel = 0;
|
||||
|
|
@ -57,6 +58,8 @@ loaders[]=
|
|||
{
|
||||
{"IMG", img_load, img_close, -1},
|
||||
{"IMA", img_load, img_close, -1},
|
||||
{"360", img_load, img_close, -1},
|
||||
{"XDF", img_load, img_close, -1},
|
||||
{"FDI", fdi_load, fdi_close, -1},
|
||||
{0,0,0}
|
||||
};
|
||||
|
|
@ -105,6 +108,7 @@ void disc_close(int drive)
|
|||
if (loaders[driveloaders[drive]].close) loaders[driveloaders[drive]].close(drive);
|
||||
drive_empty[drive] = 1;
|
||||
discfns[drive][0] = 0;
|
||||
drives[drive].hole = NULL;
|
||||
drives[drive].poll = NULL;
|
||||
drives[drive].seek = NULL;
|
||||
drives[drive].readsector = NULL;
|
||||
|
|
@ -116,6 +120,20 @@ void disc_close(int drive)
|
|||
int disc_notfound=0;
|
||||
static int disc_period = 32;
|
||||
|
||||
int disc_hole(int drive)
|
||||
{
|
||||
drive ^= fdd_swap;
|
||||
|
||||
if (drives[drive].hole)
|
||||
{
|
||||
return drives[drive].hole(drive);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void disc_poll()
|
||||
{
|
||||
disc_poll_time += disc_period * TIMER_USEC;
|
||||
|
|
@ -131,14 +149,50 @@ void disc_poll()
|
|||
}
|
||||
}
|
||||
|
||||
void disc_set_rate(int rate)
|
||||
int disc_get_bitcell_period(int rate)
|
||||
{
|
||||
int bit_rate;
|
||||
|
||||
switch (rate)
|
||||
{
|
||||
case 0: /*High density*/
|
||||
bit_rate = 500;
|
||||
break;
|
||||
case 1: /*Double density (360 rpm)*/
|
||||
bit_rate = 300;
|
||||
break;
|
||||
case 2: /*Double density*/
|
||||
bit_rate = 250;
|
||||
break;
|
||||
case 3: /*Extended density*/
|
||||
bit_rate = 1000;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1000000 / bit_rate*2; /*Bitcell period in ns*/
|
||||
}
|
||||
|
||||
|
||||
void disc_set_rate(int drive, int drvden, int rate)
|
||||
{
|
||||
switch (rate)
|
||||
{
|
||||
case 0: /*High density*/
|
||||
case 1: /*High density (360 rpm)*/
|
||||
disc_period = 16;
|
||||
break;
|
||||
case 1:
|
||||
switch(drvden)
|
||||
{
|
||||
case 0: /*Double density (360 rpm)*/
|
||||
disc_period = 26;
|
||||
break;
|
||||
case 1: /*High density (360 rpm)*/
|
||||
disc_period = 16;
|
||||
break;
|
||||
case 2:
|
||||
disc_period = 4;
|
||||
break;
|
||||
}
|
||||
case 2: /*Double density*/
|
||||
disc_period = 32;
|
||||
break;
|
||||
|
|
@ -167,47 +221,64 @@ void disc_init()
|
|||
int oldtrack[2] = {0, 0};
|
||||
void disc_seek(int drive, int track)
|
||||
{
|
||||
// pclog("disc_seek: drive=%i track=%i\n", drive, track);
|
||||
if (drives[drive].seek)
|
||||
drives[drive].seek(drive, track);
|
||||
// if (track != oldtrack[drive])
|
||||
fdc_discchange_clear(drive);
|
||||
// fdc_discchange_clear(drive);
|
||||
// ddnoise_seek(track - oldtrack[drive]);
|
||||
oldtrack[drive] = track;
|
||||
disctime = 5000;
|
||||
// oldtrack[drive] = track;
|
||||
}
|
||||
|
||||
void disc_readsector(int drive, int sector, int track, int side, int density)
|
||||
void disc_readsector(int drive, int sector, int track, int side, int density, int sector_size)
|
||||
{
|
||||
drive ^= fdd_swap;
|
||||
|
||||
if (drives[drive].readsector)
|
||||
drives[drive].readsector(drive, sector, track, side, density);
|
||||
drives[drive].readsector(drive, sector, track, side, density, sector_size);
|
||||
else
|
||||
disc_notfound = 1000;
|
||||
}
|
||||
|
||||
void disc_writesector(int drive, int sector, int track, int side, int density)
|
||||
void disc_writesector(int drive, int sector, int track, int side, int density, int sector_size)
|
||||
{
|
||||
drive ^= fdd_swap;
|
||||
|
||||
if (drives[drive].writesector)
|
||||
drives[drive].writesector(drive, sector, track, side, density);
|
||||
drives[drive].writesector(drive, sector, track, side, density, sector_size);
|
||||
else
|
||||
disc_notfound = 1000;
|
||||
}
|
||||
|
||||
void disc_readaddress(int drive, int track, int side, int density)
|
||||
{
|
||||
drive ^= fdd_swap;
|
||||
|
||||
if (drives[drive].readaddress)
|
||||
drives[drive].readaddress(drive, track, side, density);
|
||||
}
|
||||
|
||||
void disc_format(int drive, int track, int side, int density)
|
||||
void disc_format(int drive, int track, int side, int density, uint8_t fill)
|
||||
{
|
||||
drive ^= fdd_swap;
|
||||
|
||||
if (drives[drive].format)
|
||||
drives[drive].format(drive, track, side, density);
|
||||
drives[drive].format(drive, track, side, density, fill);
|
||||
else
|
||||
disc_notfound = 1000;
|
||||
}
|
||||
|
||||
void disc_stop(int drive)
|
||||
{
|
||||
drive ^= fdd_swap;
|
||||
|
||||
if (drives[drive].stop)
|
||||
drives[drive].stop(drive);
|
||||
}
|
||||
|
||||
void disc_set_drivesel(int drive)
|
||||
{
|
||||
drive ^= fdd_swap;
|
||||
|
||||
disc_drivesel = drive;
|
||||
}
|
||||
|
|
|
|||
17
src/disc.h
17
src/disc.h
|
|
@ -1,10 +1,11 @@
|
|||
typedef struct
|
||||
{
|
||||
void (*seek)(int drive, int track);
|
||||
void (*readsector)(int drive, int sector, int track, int side, int density);
|
||||
void (*writesector)(int drive, int sector, int track, int side, int density);
|
||||
void (*readsector)(int drive, int sector, int track, int side, int density, int sector_size);
|
||||
void (*writesector)(int drive, int sector, int track, int side, int density, int sector_size);
|
||||
void (*readaddress)(int drive, int track, int side, int density);
|
||||
void (*format)(int drive, int track, int side, int density);
|
||||
void (*format)(int drive, int track, int side, int density, uint8_t fill);
|
||||
uint8_t (*hole)(int drive);
|
||||
void (*stop)();
|
||||
void (*poll)();
|
||||
} DRIVE;
|
||||
|
|
@ -20,13 +21,15 @@ void disc_init();
|
|||
void disc_reset();
|
||||
void disc_poll();
|
||||
void disc_seek(int drive, int track);
|
||||
void disc_readsector(int drive, int sector, int track, int side, int density);
|
||||
void disc_writesector(int drive, int sector, int track, int side, int density);
|
||||
void disc_readsector(int drive, int sector, int track, int side, int density, int sector_size);
|
||||
void disc_writesector(int drive, int sector, int track, int side, int density, int sector_size);
|
||||
void disc_readaddress(int drive, int track, int side, int density);
|
||||
void disc_format(int drive, int track, int side, int density);
|
||||
void disc_format(int drive, int track, int side, int density, uint8_t fill);
|
||||
int disc_hole(int drive);
|
||||
void disc_stop(int drive);
|
||||
int disc_empty(int drive);
|
||||
void disc_set_rate(int rate);
|
||||
void disc_set_rate(int drive, int drvden, int rate);
|
||||
void disc_set_drivesel(int drive);
|
||||
extern int disc_time;
|
||||
extern int disc_poll_time;
|
||||
extern int disc_drivesel;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ static uint8_t fdi_timing[256*1024];
|
|||
static int fdi_pos;
|
||||
static int fdi_revs;
|
||||
|
||||
static int fdi_sector, fdi_track, fdi_side, fdi_drive, fdi_density;
|
||||
static int fdi_sector, fdi_track, fdi_side, fdi_drive, fdi_density, fdi_n;
|
||||
static int fdi_inread, fdi_inwrite, fdi_readpos, fdi_inreadaddr;
|
||||
|
||||
static uint16_t CRCTable[256];
|
||||
|
|
@ -62,6 +62,19 @@ void fdi_init()
|
|||
fdi_setupcrc(0x1021, 0xcdb4);
|
||||
}
|
||||
|
||||
int fdi_hole(int drive)
|
||||
{
|
||||
switch (fdi2raw_get_bit_rate(fdi[drive].h))
|
||||
{
|
||||
case 1000:
|
||||
return 2;
|
||||
case 500:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void fdi_load(int drive, char *fn)
|
||||
{
|
||||
writeprot[drive] = fwriteprot[drive] = 1;
|
||||
|
|
@ -76,6 +89,7 @@ void fdi_load(int drive, char *fn)
|
|||
drives[drive].readsector = fdi_readsector;
|
||||
drives[drive].writesector = fdi_writesector;
|
||||
drives[drive].readaddress = fdi_readaddress;
|
||||
drives[drive].hole = fdi_hole;
|
||||
drives[drive].poll = fdi_poll;
|
||||
drives[drive].format = fdi_format;
|
||||
drives[drive].stop = fdi_stop;
|
||||
|
|
@ -137,12 +151,13 @@ void fdi_writeback(int drive, int track)
|
|||
return;
|
||||
}
|
||||
|
||||
void fdi_readsector(int drive, int sector, int track, int side, int rate)
|
||||
void fdi_readsector(int drive, int sector, int track, int side, int rate, int sector_size)
|
||||
{
|
||||
fdi_revs = 0;
|
||||
fdi_sector = sector;
|
||||
fdi_track = track;
|
||||
fdi_side = side;
|
||||
fdi_n = sector_size;
|
||||
fdi_drive = drive;
|
||||
if (rate == 2)
|
||||
fdi_density = 1;
|
||||
|
|
@ -161,12 +176,13 @@ void fdi_readsector(int drive, int sector, int track, int side, int rate)
|
|||
fdi_readpos = 0;
|
||||
}
|
||||
|
||||
void fdi_writesector(int drive, int sector, int track, int side, int rate)
|
||||
void fdi_writesector(int drive, int sector, int track, int side, int rate, int sector_size)
|
||||
{
|
||||
fdi_revs = 0;
|
||||
fdi_sector = sector;
|
||||
fdi_track = track;
|
||||
fdi_side = side;
|
||||
fdi_n = sector_size;
|
||||
fdi_drive = drive;
|
||||
if (rate == 2)
|
||||
fdi_density = 1;
|
||||
|
|
@ -202,7 +218,7 @@ void fdi_readaddress(int drive, int track, int side, int rate)
|
|||
fdi_readpos = 0;
|
||||
}
|
||||
|
||||
void fdi_format(int drive, int track, int side, int rate)
|
||||
void fdi_format(int drive, int track, int side, int rate, uint8_t fill)
|
||||
{
|
||||
fdi_revs = 0;
|
||||
fdi_track = track;
|
||||
|
|
@ -324,7 +340,7 @@ void fdi_poll()
|
|||
if (!pollbytesleft)
|
||||
{
|
||||
// pclog("Header over %i,%i %i,%i\n", fdi_sectordat[0], fdi_sectordat[2], fdi_track, fdi_sector);
|
||||
if ((fdi_sectordat[0] == fdi_track && (fdi_sectordat[2] == fdi_sector || fdi_sector == SECTOR_NEXT)) || fdi_inreadaddr)
|
||||
if ((fdi_sectordat[0] == fdi_track && (fdi_sectordat[3] == fdi_n) && (fdi_sectordat[2] == fdi_sector || fdi_sector == SECTOR_NEXT)) || fdi_inreadaddr)
|
||||
{
|
||||
crc = (fdi_density) ? 0xcdb4 : 0xffff;
|
||||
calccrc(0xFE);
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@ void fdi_init();
|
|||
void fdi_load(int drive, char *fn);
|
||||
void fdi_close(int drive);
|
||||
void fdi_seek(int drive, int track);
|
||||
void fdi_readsector(int drive, int sector, int track, int side, int density);
|
||||
void fdi_writesector(int drive, int sector, int track, int side, int density);
|
||||
void fdi_readsector(int drive, int sector, int track, int side, int density, int sector_size);
|
||||
void fdi_writesector(int drive, int sector, int track, int side, int density, int sector_size);
|
||||
void fdi_readaddress(int drive, int sector, int side, int density);
|
||||
void fdi_format(int drive, int sector, int side, int density);
|
||||
void fdi_format(int drive, int sector, int side, int density, uint8_t fill);
|
||||
int fdi_hole(int drive);
|
||||
void fdi_stop();
|
||||
void fdi_poll();
|
||||
|
|
|
|||
603
src/disc_img.c
603
src/disc_img.c
|
|
@ -1,6 +1,8 @@
|
|||
#include "ibm.h"
|
||||
#include "fdd.h"
|
||||
#include "disc.h"
|
||||
#include "disc_img.h"
|
||||
#include "disc_sector.h"
|
||||
|
||||
static struct
|
||||
{
|
||||
|
|
@ -9,35 +11,126 @@ static struct
|
|||
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;
|
||||
double bitcell_period_300rpm;
|
||||
} img[2];
|
||||
|
||||
//static FILE *img_f[2];
|
||||
//static uint8_t trackinfoa[2][2][20*1024];
|
||||
//static int img_dblside[2];
|
||||
//static int img_sectors[2], img_size[2], img_trackc[2];
|
||||
//static int img_dblstep[2];
|
||||
//static int img_density[2];
|
||||
static uint8_t xdf_track0[5][3];
|
||||
static uint8_t xdf_spt[5];
|
||||
static uint8_t xdf_map[5][24][3];
|
||||
|
||||
static int img_sector, img_track, img_side, img_drive;
|
||||
static int img_inread, img_readpos, img_inwrite, img_inreadaddr;
|
||||
static int img_notfound;
|
||||
static int img_rsector=0;
|
||||
static int img_informat=0;
|
||||
static int img_sector_next;
|
||||
void img_writeback(int drive, int track);
|
||||
|
||||
static int img_pause = 0;
|
||||
static int img_index = 6250;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void img_init()
|
||||
{
|
||||
memset(img, 0, sizeof(img));
|
||||
// adl[0] = adl[1] = 0;
|
||||
img_notfound = 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);
|
||||
|
||||
// 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);
|
||||
|
||||
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. */
|
||||
|
||||
if (!xdf_maps_initialized) initialize_xdf_maps(); /* Initialize XDF maps, will need them to properly register sectors in tracks. */
|
||||
|
||||
writeprot[drive] = 0;
|
||||
img[drive].f = fopen(fn, "rb+");
|
||||
|
|
@ -49,32 +142,167 @@ void img_load(int drive, char *fn)
|
|||
writeprot[drive] = 1;
|
||||
}
|
||||
fwriteprot[drive] = writeprot[drive];
|
||||
|
||||
/* Read the BPB */
|
||||
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);
|
||||
|
||||
fseek(img[drive].f, -1, SEEK_END);
|
||||
size = ftell(img[drive].f) + 1;
|
||||
|
||||
img[drive].sides = 2;
|
||||
img[drive].sector_size = 512;
|
||||
if (size <= (160*1024)) { img[drive].sectors = 8; img[drive].tracks = 40; img[drive].sides = 1; img[drive].rate = 2; }
|
||||
else if (size <= (180*1024)) { img[drive].sectors = 9; img[drive].tracks = 40; img[drive].sides = 1; img[drive].rate = 2; }
|
||||
else if (size <= (320*1024)) { img[drive].sectors = 8; img[drive].tracks = 40; img[drive].rate = 2; }
|
||||
else if (size <= (360*1024)) { img[drive].sectors = 9; img[drive].tracks = 40; img[drive].rate = 2; } /*Double density*/
|
||||
else if (size < (1024*1024)) { img[drive].sectors = 9; img[drive].tracks = 80; img[drive].rate = 2; } /*Double density*/
|
||||
else if (size <= 1228800) { img[drive].sectors = 15; img[drive].tracks = 80; img[drive].rate = 0; } /*High density 1.2MB*/
|
||||
else if (size <= (0x1A4000-1)) { img[drive].sectors = 18; img[drive].tracks = 80; img[drive].rate = 0; } /*High density (not supported by Tandy 1000)*/
|
||||
else if (size == 1884160) { img[drive].sectors = 23; img[drive].tracks = 80; img[drive].rate = 0; } /*XDF format - used by OS/2 Warp*/
|
||||
else if (size == 1763328) { img[drive].sectors = 21; img[drive].tracks = 82; img[drive].rate = 0; } /*XDF format - used by OS/2 Warp*/
|
||||
else if (size < (2048*1024)) { img[drive].sectors = 21; img[drive].tracks = 80; img[drive].rate = 0; } /*DMF format - used by Windows 95*/
|
||||
else { img[drive].sectors = 36; img[drive].tracks = 80; img[drive].rate = 3; } /*E density*/
|
||||
|
||||
pclog("BPB reports %i sides and %i bytes per sector\n", bpb_sides, bpb_bps);
|
||||
|
||||
if ((bpb_sides < 1) || (bpb_sides > 2) || (bpb_bps < 128) || (bpb_bps > 2048))
|
||||
{
|
||||
/* 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; }
|
||||
else if (size <= (180*1024)) { img[drive].sectors = 9; img[drive].tracks = 40; img[drive].sides = 1; bit_rate_300 = 250; }
|
||||
else if (size <= (320*1024)) { img[drive].sectors = 8; img[drive].tracks = 40; bit_rate_300 = 250; }
|
||||
else if (size <= (360*1024)) { img[drive].sectors = 9; img[drive].tracks = 40; bit_rate_300 = 250; } /*Double density*/
|
||||
else if (size < (1024*1024)) { img[drive].sectors = 9; img[drive].tracks = 80; bit_rate_300 = 250; } /*Double density*/
|
||||
else if (size <= 1228800) { img[drive].sectors = 15; img[drive].tracks = 80; bit_rate_300 = (500.0 * 300.0) / 360.0; } /*High density 1.2MB*/
|
||||
else if (size <= (0x1A4000-1)) { img[drive].sectors = 18; img[drive].tracks = 80; bit_rate_300 = 500; } /*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; } /*DMF format - used by Windows 95 - changed by OBattler to 2000000, ie. the real unformatted capacity @ 500 kbps and 300 rpm */
|
||||
else { img[drive].sectors = 36; img[drive].tracks = 80; bit_rate_300 = 1000; } /*E density*/
|
||||
|
||||
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. */
|
||||
img[drive].tracks = ((uint32_t) bpb_total) / (((uint32_t) bpb_sides) * ((uint32_t) bpb_sectors));
|
||||
/* The rest we just set directly from the BPB. */
|
||||
img[drive].sectors = bpb_sectors;
|
||||
img[drive].sides = bpb_sides;
|
||||
/* 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);
|
||||
if (bpt <= 6250)
|
||||
bit_rate_300 = 250; /* Double-density */
|
||||
else if (bpt <= 7500)
|
||||
bit_rate_300 = 300; /* Double-density, 300 kbps @ 300 rpm */
|
||||
else if (bpt <= 10416)
|
||||
{
|
||||
bit_rate_300 = (bpb_mid == 0xF0) ? 500 : ((500.0 * 300.0) / 360.0); /* High-density @ 300 or 360 rpm, depending on media type ID */
|
||||
max_spt = (bpb_mid == 0xF0) ? 22 : 18;
|
||||
}
|
||||
else if (bpt <= 12500) /* High-density @ 300 rpm */
|
||||
{
|
||||
bit_rate_300 = 500;
|
||||
max_spt = 22;
|
||||
}
|
||||
else if (bpt <= 25000) /* Extended density @ 300 rpm */
|
||||
{
|
||||
bit_rate_300 = 1000;
|
||||
max_spt = 45;
|
||||
}
|
||||
else /* Image too big, eject */
|
||||
{
|
||||
pclog("Image has more than 25000 bytes per track, 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
|
||||
{
|
||||
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;
|
||||
break;
|
||||
case 24: /* High density XXDF @ 300 rpm */
|
||||
img[drive].xdf_type = 4;
|
||||
break;
|
||||
case 46: /* Extended density XDF */
|
||||
img[drive].xdf_type = 3;
|
||||
break;
|
||||
case 48: /* Extended density XXDF */
|
||||
img[drive].xdf_type = 5;
|
||||
break;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if ((bit_rate_300 == 250) || (bit_rate_300 == 300))
|
||||
{
|
||||
img[drive].hole = 0;
|
||||
}
|
||||
else if (bit_rate_300 == 1000)
|
||||
{
|
||||
img[drive].hole = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
img[drive].hole = 1;
|
||||
}
|
||||
|
||||
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 = img_readsector;
|
||||
drives[drive].writesector = img_writesector;
|
||||
drives[drive].readaddress = img_readaddress;
|
||||
drives[drive].poll = img_poll;
|
||||
drives[drive].format = img_format;
|
||||
// pclog("img_load %d %p sectors=%i tracks=%i sides=%i sector_size=%i\n", drive, drives, img[drive].sectors, img[drive].tracks, img[drive].sides, img[drive].sector_size);
|
||||
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].poll = disc_sector_poll;
|
||||
drives[drive].format = disc_sector_format;
|
||||
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;
|
||||
}
|
||||
|
||||
void img_close(int drive)
|
||||
{
|
||||
|
|
@ -85,13 +313,19 @@ void img_close(int drive)
|
|||
|
||||
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 */
|
||||
|
||||
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);
|
||||
|
||||
if (drive_type[drive] && img[drive].tracks == 40)
|
||||
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);
|
||||
if (img[drive].tracks <= 41 && fdd_doublestep_40(drive))
|
||||
track /= 2;
|
||||
|
||||
pclog("Disk seeked to track %i\n", track);
|
||||
disc_track[drive] = track;
|
||||
|
||||
if (img[drive].sides == 2)
|
||||
|
|
@ -105,12 +339,99 @@ void img_seek(int drive, int track)
|
|||
fseek(img[drive].f, track * img[drive].sectors * img[drive].sector_size, SEEK_SET);
|
||||
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);
|
||||
|
||||
int sector, current_pos;
|
||||
|
||||
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 map. */
|
||||
/* First, the "Side 0" buffer, will also contain one sector from side 1. */
|
||||
current_pos = 0;
|
||||
for (sector = 0; sector < sectors_fat; sector++)
|
||||
{
|
||||
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;
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
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->sector_size]);
|
||||
}
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
fseek(img[drive].f, track * img[drive].sectors * img[drive].sector_size * 2, SEEK_SET);
|
||||
|
|
@ -124,215 +445,3 @@ void img_writeback(int drive, int track)
|
|||
}
|
||||
}
|
||||
|
||||
void img_readsector(int drive, int sector, int track, int side, int rate)
|
||||
{
|
||||
if (drive_type[drive] && rate == 1)
|
||||
rate = 2;
|
||||
|
||||
if (sector == SECTOR_FIRST)
|
||||
{
|
||||
img_sector = 1 - 1;
|
||||
img_sector_next = 2;
|
||||
}
|
||||
else if (sector == SECTOR_NEXT)
|
||||
{
|
||||
img_sector = img_sector_next - 1;
|
||||
img_sector_next++;
|
||||
}
|
||||
else
|
||||
img_sector = sector - 1;
|
||||
img_track = track;
|
||||
img_side = side;
|
||||
img_drive = drive;
|
||||
// pclog("imgS Read sector drive=%i side=%i track=%i sector=%i rate=%i\n",drive,side,track,sector, rate);
|
||||
|
||||
if (!img[drive].f || (side && img[drive].sides == 1) ||
|
||||
(rate != img[drive].rate) || (track != disc_track[drive]) ||
|
||||
img_sector > img[drive].sectors)
|
||||
{
|
||||
// pclog("Sector not found rate %i,%i track %i,%i\n", rate, img[drive].rate, track, disc_track[drive]);
|
||||
img_notfound=500;
|
||||
return;
|
||||
}
|
||||
// printf("Found\n");
|
||||
img_inread = 1;
|
||||
img_readpos = 0;
|
||||
img_pause = 32;
|
||||
}
|
||||
|
||||
void img_writesector(int drive, int sector, int track, int side, int rate)
|
||||
{
|
||||
if (drive_type[drive] && rate == 1)
|
||||
rate = 2;
|
||||
|
||||
// if (imgdblstep[drive]) track/=2;
|
||||
img_sector = sector - 1;
|
||||
img_track = track;
|
||||
img_side = side;
|
||||
img_drive = drive;
|
||||
// printf("imgS Write sector %i %i %i %i\n",drive,side,track,sector);
|
||||
|
||||
if (!img[drive].f || (side && img[drive].sides == 1) ||
|
||||
(rate != img[drive].rate) || (track != disc_track[drive]) ||
|
||||
sector > img[drive].sectors)
|
||||
{
|
||||
img_notfound = 500;
|
||||
return;
|
||||
}
|
||||
img_inwrite = 1;
|
||||
img_readpos = 0;
|
||||
img_pause = 32;
|
||||
}
|
||||
|
||||
void img_readaddress(int drive, int track, int side, int rate)
|
||||
{
|
||||
if (drive_type[drive] && rate == 1)
|
||||
rate = 2;
|
||||
|
||||
img_drive = drive;
|
||||
img_track = disc_track[drive];
|
||||
img_side = side;
|
||||
// pclog("Read address %i %i %i %i\n",drive,side,track, rate);
|
||||
|
||||
if (!img[drive].f || (side && img[drive].sides == 1) ||
|
||||
(rate != img[drive].rate))
|
||||
{
|
||||
// pclog("Address not found rate %i,%i track %i,%i\n", rate, img[drive].rate, track, disc_track[drive]);
|
||||
img_notfound=500;
|
||||
return;
|
||||
}
|
||||
img_inreadaddr = 1;
|
||||
img_readpos = 0;
|
||||
img_pause = 100;//500;
|
||||
img_pause = 32;
|
||||
}
|
||||
|
||||
void img_format(int drive, int track, int side, int rate)
|
||||
{
|
||||
if (drive_type[drive] && rate == 1)
|
||||
rate = 2;
|
||||
|
||||
img_drive = drive;
|
||||
img_track = track;
|
||||
img_side = side;
|
||||
|
||||
if (!img[drive].f || (side && img[drive].sides == 1) ||
|
||||
(rate != img[drive].rate) || (track != disc_track[drive]))
|
||||
{
|
||||
img_notfound = 500;
|
||||
return;
|
||||
}
|
||||
img_sector = 0;
|
||||
img_readpos = 0;
|
||||
img_informat = 1;
|
||||
img_pause = 32;
|
||||
}
|
||||
|
||||
void img_stop()
|
||||
{
|
||||
img_pause = img_notfound = img_inread = img_inwrite = img_inreadaddr = img_informat = 0;
|
||||
}
|
||||
|
||||
void img_poll()
|
||||
{
|
||||
// pclog("img_poll %i %i %p\n", img_inread, img_readpos, img[img_drive].f);
|
||||
img_index--;
|
||||
if (!img_index)
|
||||
{
|
||||
img_index = 6250;
|
||||
fdc_indexpulse();
|
||||
}
|
||||
|
||||
if (img_pause)
|
||||
{
|
||||
img_pause--;
|
||||
if (img_pause)
|
||||
return;
|
||||
}
|
||||
|
||||
if (img_notfound)
|
||||
{
|
||||
img_notfound--;
|
||||
if (!img_notfound)
|
||||
{
|
||||
// pclog("Not found!\n");
|
||||
fdc_notfound();
|
||||
}
|
||||
}
|
||||
if (img_inread && img[img_drive].f)
|
||||
{
|
||||
// pclog("Read pos %i\n", img_readpos);
|
||||
// if (!imgreadpos) pclog("%i\n",imgsector*imgsize[imgdrive]);
|
||||
if (fdc_data(img[img_drive].track_data[img_side][(img_sector * img[img_drive].sector_size) + img_readpos]))
|
||||
return;
|
||||
|
||||
img_readpos++;
|
||||
if (img_readpos == img[img_drive].sector_size)
|
||||
{
|
||||
// pclog("Read %i bytes\n",img_readpos);
|
||||
img_inread = 0;
|
||||
fdc_finishread();
|
||||
}
|
||||
}
|
||||
if (img_inwrite && img[img_drive].f)
|
||||
{
|
||||
int data;
|
||||
|
||||
if (writeprot[img_drive])
|
||||
{
|
||||
// pclog("writeprotect\n");
|
||||
fdc_writeprotect();
|
||||
img_inwrite = 0;
|
||||
return;
|
||||
}
|
||||
// pclog("Write data %i\n",img_readpos);
|
||||
data = fdc_getdata(img_readpos == (img[img_drive].sector_size - 1));
|
||||
if (data == -1)
|
||||
return;
|
||||
|
||||
img[img_drive].track_data[img_side][(img_sector * img[img_drive].sector_size) + img_readpos] = data;
|
||||
img_readpos++;
|
||||
if (img_readpos == img[img_drive].sector_size)
|
||||
{
|
||||
// pclog("write over\n");
|
||||
img_inwrite = 0;
|
||||
fdc_finishread();
|
||||
img_writeback(img_drive, img_track);
|
||||
}
|
||||
}
|
||||
if (img_inreadaddr && img[img_drive].f)
|
||||
{
|
||||
// pclog("img_inreadaddr %08X\n", fdc_sectorid);
|
||||
fdc_sectorid(img_track, img_side,
|
||||
img_rsector + ((img[img_drive].sector_size == 512) ? 1 : 0), (img[img_drive].sector_size == 256) ? 1 : ((img[img_drive].sector_size == 512) ? 2 : 3), 0, 0);
|
||||
img_inreadaddr = 0;
|
||||
img_rsector++;
|
||||
if (img_rsector == img[img_drive].sectors)
|
||||
{
|
||||
img_rsector=0;
|
||||
// pclog("img_rsector reset\n");
|
||||
}
|
||||
}
|
||||
if (img_informat && img[img_drive].f)
|
||||
{
|
||||
if (writeprot[img_drive])
|
||||
{
|
||||
fdc_writeprotect();
|
||||
img_informat = 0;
|
||||
return;
|
||||
}
|
||||
img[img_drive].track_data[img_side][(img_sector * img[img_drive].sector_size) + img_readpos] = 0;
|
||||
img_readpos++;
|
||||
if (img_readpos == img[img_drive].sector_size)
|
||||
{
|
||||
img_readpos = 0;
|
||||
img_sector++;
|
||||
if (img_sector == img[img_drive].sectors)
|
||||
{
|
||||
img_informat = 0;
|
||||
fdc_finishread();
|
||||
img_writeback(img_drive, img_track);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,5 +6,6 @@ void img_readsector(int drive, int sector, int track, int side, int density);
|
|||
void img_writesector(int drive, int sector, int track, int side, int density);
|
||||
void img_readaddress(int drive, int sector, int side, int density);
|
||||
void img_format(int drive, int sector, int side, int density);
|
||||
int img_hole(int drive);
|
||||
void img_stop();
|
||||
void img_poll();
|
||||
|
|
|
|||
385
src/disc_sector.c
Normal file
385
src/disc_sector.c
Normal file
|
|
@ -0,0 +1,385 @@
|
|||
#include "ibm.h"
|
||||
#include "disc.h"
|
||||
#include "disc_sector.h"
|
||||
#include "fdd.h"
|
||||
|
||||
/*Handling for 'sector based' image formats (like .IMG) as opposed to 'stream based' formats (eg .FDI)*/
|
||||
|
||||
#define MAX_SECTORS 256
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t c, h, r, n;
|
||||
int rate;
|
||||
uint8_t *data;
|
||||
} sector_t;
|
||||
|
||||
static sector_t disc_sector_data[2][2][MAX_SECTORS];
|
||||
static int disc_sector_count[2][2];
|
||||
void (*disc_sector_writeback[2])(int drive, int track);
|
||||
|
||||
enum
|
||||
{
|
||||
STATE_IDLE,
|
||||
STATE_READ_FIND_SECTOR,
|
||||
STATE_READ_SECTOR,
|
||||
STATE_READ_FIND_FIRST_SECTOR,
|
||||
STATE_READ_FIRST_SECTOR,
|
||||
STATE_READ_FIND_NEXT_SECTOR,
|
||||
STATE_READ_NEXT_SECTOR,
|
||||
STATE_WRITE_FIND_SECTOR,
|
||||
STATE_WRITE_SECTOR,
|
||||
STATE_READ_FIND_ADDRESS,
|
||||
STATE_READ_ADDRESS,
|
||||
STATE_FORMAT_FIND,
|
||||
STATE_FORMAT
|
||||
};
|
||||
|
||||
static int disc_sector_state;
|
||||
static int disc_sector_track;
|
||||
static int disc_sector_side;
|
||||
static int disc_sector_drive;
|
||||
static int disc_sector_sector;
|
||||
static int disc_sector_n;
|
||||
static int disc_intersector_delay = 0;
|
||||
static uint8_t disc_sector_fill;
|
||||
static int cur_sector, cur_byte;
|
||||
static int index_count;
|
||||
|
||||
void disc_sector_reset(int drive, int side)
|
||||
{
|
||||
disc_sector_count[drive][side] = 0;
|
||||
}
|
||||
|
||||
void disc_sector_add(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n, int rate, uint8_t *data)
|
||||
{
|
||||
sector_t *s = &disc_sector_data[drive][side][disc_sector_count[drive][side]];
|
||||
//pclog("disc_sector_add: drive=%i side=%i %i r=%i\n", drive, side, disc_sector_count[drive][side],r );
|
||||
if (disc_sector_count[drive][side] >= MAX_SECTORS)
|
||||
return;
|
||||
|
||||
s->c = c;
|
||||
s->h = h;
|
||||
s->r = r;
|
||||
s->n = n;
|
||||
s->rate = rate;
|
||||
s->data = data;
|
||||
|
||||
disc_sector_count[drive][side]++;
|
||||
}
|
||||
|
||||
static int get_bitcell_period()
|
||||
{
|
||||
return (disc_sector_data[disc_sector_drive][disc_sector_side][cur_sector].rate * 300) / fdd_getrpm(disc_sector_drive);
|
||||
}
|
||||
|
||||
void disc_sector_readsector(int drive, int sector, int track, int side, int rate, int sector_size)
|
||||
{
|
||||
// pclog("disc_sector_readsector: fdc_period=%i img_period=%i rate=%i sector=%i track=%i side=%i\n", fdc_get_bitcell_period(), get_bitcell_period(), rate, sector, track, side);
|
||||
|
||||
if (sector == SECTOR_FIRST)
|
||||
disc_sector_state = STATE_READ_FIND_FIRST_SECTOR;
|
||||
else if (sector == SECTOR_NEXT)
|
||||
disc_sector_state = STATE_READ_FIND_NEXT_SECTOR;
|
||||
else
|
||||
disc_sector_state = STATE_READ_FIND_SECTOR;
|
||||
disc_sector_track = track;
|
||||
disc_sector_side = side;
|
||||
disc_sector_drive = drive;
|
||||
disc_sector_sector = sector;
|
||||
disc_sector_n = sector_size;
|
||||
index_count = 0;
|
||||
}
|
||||
|
||||
void disc_sector_writesector(int drive, int sector, int track, int side, int rate, int sector_size)
|
||||
{
|
||||
// pclog("disc_sector_writesector: fdc_period=%i img_period=%i rate=%i\n", fdc_get_bitcell_period(), get_bitcell_period(), rate);
|
||||
|
||||
disc_sector_state = STATE_WRITE_FIND_SECTOR;
|
||||
disc_sector_track = track;
|
||||
disc_sector_side = side;
|
||||
disc_sector_drive = drive;
|
||||
disc_sector_sector = sector;
|
||||
disc_sector_n = sector_size;
|
||||
index_count = 0;
|
||||
}
|
||||
|
||||
void disc_sector_readaddress(int drive, int track, int side, int rate)
|
||||
{
|
||||
// pclog("disc_sector_readaddress: fdc_period=%i img_period=%i rate=%i track=%i side=%i\n", fdc_get_bitcell_period(), get_bitcell_period(), rate, track, side);
|
||||
|
||||
disc_sector_state = STATE_READ_FIND_ADDRESS;
|
||||
disc_sector_track = track;
|
||||
disc_sector_side = side;
|
||||
disc_sector_drive = drive;
|
||||
index_count = 0;
|
||||
}
|
||||
|
||||
void disc_sector_format(int drive, int track, int side, int rate, uint8_t fill)
|
||||
{
|
||||
disc_sector_state = STATE_FORMAT_FIND;
|
||||
disc_sector_track = track;
|
||||
disc_sector_side = side;
|
||||
disc_sector_drive = drive;
|
||||
disc_sector_fill = fill;
|
||||
index_count = 0;
|
||||
}
|
||||
|
||||
void disc_sector_stop()
|
||||
{
|
||||
disc_sector_state = STATE_IDLE;
|
||||
}
|
||||
|
||||
static void advance_byte()
|
||||
{
|
||||
if (disc_intersector_delay)
|
||||
{
|
||||
disc_intersector_delay--;
|
||||
return;
|
||||
}
|
||||
cur_byte++;
|
||||
if (cur_byte >= (128 << disc_sector_data[disc_sector_drive][disc_sector_side][cur_sector].n))
|
||||
{
|
||||
cur_byte = 0;
|
||||
cur_sector++;
|
||||
if (cur_sector >= disc_sector_count[disc_sector_drive][disc_sector_side])
|
||||
{
|
||||
cur_sector = 0;
|
||||
fdc_indexpulse();
|
||||
index_count++;
|
||||
}
|
||||
disc_intersector_delay = 40;
|
||||
}
|
||||
}
|
||||
|
||||
void disc_sector_poll()
|
||||
{
|
||||
sector_t *s;
|
||||
int data;
|
||||
|
||||
if (cur_sector >= disc_sector_count[disc_sector_drive][disc_sector_side])
|
||||
cur_sector = 0;
|
||||
if (cur_byte >= (128 << disc_sector_data[disc_sector_drive][disc_sector_side][cur_sector].n))
|
||||
cur_byte = 0;
|
||||
|
||||
s = &disc_sector_data[disc_sector_drive][disc_sector_side][cur_sector];
|
||||
switch (disc_sector_state)
|
||||
{
|
||||
case STATE_IDLE:
|
||||
break;
|
||||
|
||||
case STATE_READ_FIND_SECTOR:
|
||||
/* pclog("STATE_READ_FIND_SECTOR: cur_sector=%i cur_byte=%i sector=%i,%i side=%i,%i track=%i,%i period=%i,%i\n",
|
||||
cur_sector, cur_byte,
|
||||
disc_sector_sector, s->r,
|
||||
disc_sector_side, s->h,
|
||||
disc_sector_track, s->c,
|
||||
fdc_get_bitcell_period(), get_bitcell_period());*/
|
||||
if (index_count > 1)
|
||||
{
|
||||
// pclog("Find sector not found\n");
|
||||
fdc_notfound();
|
||||
disc_sector_state = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
/* pclog("%i %i %i %i %i\n", cur_byte, disc_sector_track != s->c,
|
||||
disc_sector_side != s->h,
|
||||
disc_sector_sector != s->r,
|
||||
fdc_get_bitcell_period() != get_bitcell_period());*/
|
||||
if (cur_byte || disc_sector_track != s->c ||
|
||||
disc_sector_side != s->h ||
|
||||
disc_sector_sector != s->r ||
|
||||
disc_sector_n != s->n ||
|
||||
fdc_get_bitcell_period() != get_bitcell_period() ||
|
||||
!fdd_can_read_medium(disc_sector_drive ^ fdd_swap) ||
|
||||
disc_intersector_delay)
|
||||
{
|
||||
advance_byte();
|
||||
break;
|
||||
}
|
||||
disc_sector_state = STATE_READ_SECTOR;
|
||||
case STATE_READ_SECTOR:
|
||||
// pclog("STATE_READ_SECTOR: cur_byte=%i %i\n", cur_byte, disc_intersector_delay);
|
||||
if (fdc_data(s->data[cur_byte]))
|
||||
{
|
||||
// pclog("fdc_data failed\n");
|
||||
return;
|
||||
}
|
||||
advance_byte();
|
||||
if (!cur_byte)
|
||||
{
|
||||
disc_sector_state = STATE_IDLE;
|
||||
fdc_finishread();
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_READ_FIND_FIRST_SECTOR:
|
||||
if (!(fdd_can_read_medium(disc_sector_drive ^ fdd_swap)))
|
||||
{
|
||||
// pclog("Medium is of a density not supported by the drive\n");
|
||||
fdc_notfound();
|
||||
disc_sector_state = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
if (cur_byte || !index_count || fdc_get_bitcell_period() != get_bitcell_period() ||
|
||||
disc_intersector_delay)
|
||||
{
|
||||
advance_byte();
|
||||
break;
|
||||
}
|
||||
disc_sector_state = STATE_READ_FIRST_SECTOR;
|
||||
case STATE_READ_FIRST_SECTOR:
|
||||
if (fdc_data(s->data[cur_byte]))
|
||||
return;
|
||||
advance_byte();
|
||||
if (!cur_byte)
|
||||
{
|
||||
disc_sector_state = STATE_IDLE;
|
||||
fdc_finishread();
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_READ_FIND_NEXT_SECTOR:
|
||||
if (!(fdd_can_read_medium(disc_sector_drive ^ fdd_swap)))
|
||||
{
|
||||
// pclog("Medium is of a density not supported by the drive\n");
|
||||
fdc_notfound();
|
||||
disc_sector_state = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
if (index_count)
|
||||
{
|
||||
// pclog("Find next sector hit end of track\n");
|
||||
fdc_notfound();
|
||||
disc_sector_state = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
if (cur_byte || fdc_get_bitcell_period() != get_bitcell_period() ||
|
||||
disc_intersector_delay)
|
||||
{
|
||||
advance_byte();
|
||||
break;
|
||||
}
|
||||
disc_sector_state = STATE_READ_NEXT_SECTOR;
|
||||
case STATE_READ_NEXT_SECTOR:
|
||||
if (fdc_data(s->data[cur_byte]))
|
||||
break;
|
||||
advance_byte();
|
||||
if (!cur_byte)
|
||||
{
|
||||
disc_sector_state = STATE_IDLE;
|
||||
fdc_finishread();
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_WRITE_FIND_SECTOR:
|
||||
if (!(fdd_can_read_medium(disc_sector_drive ^ fdd_swap)))
|
||||
{
|
||||
// pclog("Medium is of a density not supported by the drive\n");
|
||||
fdc_notfound();
|
||||
disc_sector_state = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
if (writeprot[disc_sector_drive])
|
||||
{
|
||||
fdc_writeprotect();
|
||||
return;
|
||||
}
|
||||
if (index_count > 1)
|
||||
{
|
||||
// pclog("Write find sector not found\n");
|
||||
fdc_notfound();
|
||||
disc_sector_state = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
if (cur_byte || disc_sector_track != s->c ||
|
||||
disc_sector_side != s->h ||
|
||||
disc_sector_sector != s->r ||
|
||||
disc_sector_n != s->n ||
|
||||
fdc_get_bitcell_period() != get_bitcell_period() ||
|
||||
disc_intersector_delay)
|
||||
{
|
||||
advance_byte();
|
||||
break;
|
||||
}
|
||||
disc_sector_state = STATE_WRITE_SECTOR;
|
||||
case STATE_WRITE_SECTOR:
|
||||
data = fdc_getdata(cur_byte == ((128 << s->n) - 1));
|
||||
if (data == -1)
|
||||
break;
|
||||
s->data[cur_byte] = data;
|
||||
advance_byte();
|
||||
if (!cur_byte)
|
||||
{
|
||||
disc_sector_state = STATE_IDLE;
|
||||
disc_sector_writeback[disc_sector_drive](disc_sector_drive, disc_sector_track);
|
||||
fdc_finishread();
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_READ_FIND_ADDRESS:
|
||||
if (!(fdd_can_read_medium(disc_sector_drive ^ fdd_swap)))
|
||||
{
|
||||
// pclog("Medium is of a density not supported by the drive\n");
|
||||
fdc_notfound();
|
||||
disc_sector_state = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
if (index_count)
|
||||
{
|
||||
// pclog("Find next sector hit end of track\n");
|
||||
fdc_notfound();
|
||||
disc_sector_state = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
if (cur_byte || fdc_get_bitcell_period() != get_bitcell_period() ||
|
||||
disc_intersector_delay)
|
||||
{
|
||||
advance_byte();
|
||||
break;
|
||||
}
|
||||
disc_sector_state = STATE_READ_ADDRESS;
|
||||
case STATE_READ_ADDRESS:
|
||||
fdc_sectorid(s->c, s->h, s->r, s->n, 0, 0);
|
||||
disc_sector_state = STATE_IDLE;
|
||||
break;
|
||||
|
||||
case STATE_FORMAT_FIND:
|
||||
if (writeprot[disc_sector_drive])
|
||||
{
|
||||
fdc_writeprotect();
|
||||
return;
|
||||
}
|
||||
if (!index_count || fdc_get_bitcell_period() != get_bitcell_period() ||
|
||||
disc_intersector_delay)
|
||||
{
|
||||
advance_byte();
|
||||
break;
|
||||
}
|
||||
if (!(fdd_can_read_medium(disc_sector_drive ^ fdd_swap)))
|
||||
{
|
||||
// pclog("Medium is of a density not supported by the drive\n");
|
||||
fdc_notfound();
|
||||
disc_sector_state = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
if (fdc_get_bitcell_period() != get_bitcell_period())
|
||||
{
|
||||
fdc_notfound();
|
||||
disc_sector_state = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
disc_sector_state = STATE_FORMAT;
|
||||
case STATE_FORMAT:
|
||||
if (!disc_intersector_delay && fdc_get_bitcell_period() == get_bitcell_period())
|
||||
s->data[cur_byte] = disc_sector_fill;
|
||||
advance_byte();
|
||||
if (index_count == 2)
|
||||
{
|
||||
disc_sector_writeback[disc_sector_drive](disc_sector_drive, disc_sector_track);
|
||||
fdc_finishread();
|
||||
disc_sector_state = STATE_IDLE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
11
src/disc_sector.h
Normal file
11
src/disc_sector.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
void disc_sector_reset(int drive, int side);
|
||||
void disc_sector_add(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n, int rate, uint8_t *data);
|
||||
void disc_sector_readsector(int drive, int sector, int track, int side, int density, int sector_size);
|
||||
void disc_sector_writesector(int drive, int sector, int track, int side, int density, int sector_size);
|
||||
void disc_sector_readaddress(int drive, int sector, int side, int density);
|
||||
void disc_sector_format(int drive, int sector, int side, int density, uint8_t fill);
|
||||
void disc_sector_stop();
|
||||
void disc_sector_poll();
|
||||
void disc_sector_stop();
|
||||
|
||||
extern void (*disc_sector_writeback[2])(int drive, int track);
|
||||
453
src/fdc.c
453
src/fdc.c
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "disc.h"
|
||||
#include "dma.h"
|
||||
#include "fdd.h"
|
||||
#include "io.h"
|
||||
#include "pic.h"
|
||||
#include "timer.h"
|
||||
|
|
@ -16,6 +17,7 @@ typedef struct FDC
|
|||
{
|
||||
uint8_t dor,stat,command,dat,st0;
|
||||
int head,track[256],sector,drive,lastdrive;
|
||||
int rw_track;
|
||||
int pos;
|
||||
uint8_t params[256];
|
||||
uint8_t res[256];
|
||||
|
|
@ -42,6 +44,22 @@ typedef struct FDC
|
|||
|
||||
int dskchg_activelow;
|
||||
int enable_3f1;
|
||||
|
||||
int bitcell_period;
|
||||
|
||||
int is_nsc; /* 1 = FDC is on a National Semiconductor Super I/O chip, 0 = other FDC. This is needed,
|
||||
because the National Semiconductor Super I/O chips add some FDC commands. */
|
||||
int enh_mode;
|
||||
int rwc[2];
|
||||
int boot_drive;
|
||||
int densel_polarity;
|
||||
int densel_force;
|
||||
int drvrate[2];
|
||||
|
||||
int dma;
|
||||
int fifo, tfifo;
|
||||
int fifobufpos;
|
||||
uint8_t fifobuf[16];
|
||||
} FDC;
|
||||
|
||||
static FDC fdc;
|
||||
|
|
@ -65,11 +83,59 @@ void fdc_reset()
|
|||
fdc.head = 0;
|
||||
fdc.abort = 0;
|
||||
if (!AT)
|
||||
fdc.rate=2;
|
||||
{
|
||||
fdc.rate = 2;
|
||||
// fdc_update_rate();
|
||||
}
|
||||
// pclog("Reset FDC\n");
|
||||
}
|
||||
int ins;
|
||||
|
||||
void fdc_reset_fifo_buf()
|
||||
{
|
||||
int i = 0;
|
||||
memset(fdc.fifobuf, 0, 16);
|
||||
fdc.fifobufpos = 0;
|
||||
}
|
||||
|
||||
void fdc_fifo_buf_write(int val)
|
||||
{
|
||||
if (fdc.fifobufpos < fdc.tfifo)
|
||||
{
|
||||
fdc.fifobuf[fdc.fifobufpos] = val;
|
||||
fdc.fifobufpos++;
|
||||
fdc.fifobufpos %= fdc.tfifo;
|
||||
// pclog("FIFO buffer position = %02X\n", fdc.fifobufpos);
|
||||
if (fdc.fifobufpos == fdc.tfifo) fdc.fifobufpos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int fdc_fifo_buf_read()
|
||||
{
|
||||
int temp = 0;
|
||||
if (fdc.fifobufpos < fdc.tfifo)
|
||||
{
|
||||
temp = fdc.fifobuf[fdc.fifobufpos];
|
||||
fdc.fifobufpos++;
|
||||
fdc.fifobufpos %= fdc.tfifo;
|
||||
// pclog("FIFO buffer position = %02X\n", fdc.fifobufpos);
|
||||
if (fdc.fifobufpos == fdc.tfifo) fdc.fifobufpos = 0;
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
/* For DMA mode, just goes ahead in FIFO buffer but doesn't actually read or write anything. */
|
||||
void fdc_fifo_buf_dummy()
|
||||
{
|
||||
if (fdc.fifobufpos < fdc.tfifo)
|
||||
{
|
||||
fdc.fifobufpos++;
|
||||
fdc.fifobufpos %= fdc.tfifo;
|
||||
// pclog("FIFO buffer position = %02X\n", fdc.fifobufpos);
|
||||
if (fdc.fifobufpos == fdc.tfifo) fdc.fifobufpos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void fdc_int()
|
||||
{
|
||||
if (!fdc.pcjr)
|
||||
|
|
@ -93,9 +159,164 @@ static void fdc_watchdog_poll(void *p)
|
|||
}
|
||||
}
|
||||
|
||||
/* fdc.rwc per Winbond W83877F datasheet:
|
||||
0 = normal;
|
||||
1 = 500 kbps, 360 rpm;
|
||||
2 = 500 kbps, 300 rpm;
|
||||
3 = 250 kbps
|
||||
|
||||
Drive is only aware of selected rate and densel, so on real hardware, the rate expected by FDC and the rate actually being
|
||||
processed by drive can mismatch, in which case the FDC won't receive the correct data.
|
||||
*/
|
||||
|
||||
int bit_rate = 250;
|
||||
|
||||
void fdc_update_is_nsc(int is_nsc)
|
||||
{
|
||||
fdc.is_nsc = is_nsc;
|
||||
}
|
||||
|
||||
void fdc_update_enh_mode(int enh_mode)
|
||||
{
|
||||
fdc.enh_mode = enh_mode;
|
||||
}
|
||||
|
||||
int fdc_get_rwc(int drive)
|
||||
{
|
||||
return fdc.rwc[drive];
|
||||
}
|
||||
|
||||
void fdc_update_rwc(int drive, int rwc)
|
||||
{
|
||||
fdc.rwc[drive] = rwc;
|
||||
}
|
||||
|
||||
int fdc_get_boot_drive()
|
||||
{
|
||||
return fdc.boot_drive;
|
||||
}
|
||||
|
||||
void fdc_update_boot_drive(int boot_drive)
|
||||
{
|
||||
fdc.boot_drive = boot_drive;
|
||||
}
|
||||
|
||||
void fdc_update_densel_polarity(int densel_polarity)
|
||||
{
|
||||
fdc.densel_polarity = densel_polarity;
|
||||
}
|
||||
|
||||
void fdc_update_densel_force(int densel_force)
|
||||
{
|
||||
fdc.densel_force = densel_force;
|
||||
}
|
||||
|
||||
void fdc_update_drvrate(int drive, int drvrate)
|
||||
{
|
||||
fdc.drvrate[drive] = drvrate;
|
||||
}
|
||||
|
||||
void fdc_update_rate(int drive)
|
||||
{
|
||||
if ((fdc.rwc[drive] == 1) || (fdc.rwc[drive] == 2))
|
||||
{
|
||||
bit_rate = 500;
|
||||
}
|
||||
else if (fdc.rwc[drive] == 3)
|
||||
{
|
||||
bit_rate = 250;
|
||||
}
|
||||
else switch (fdc.rate)
|
||||
{
|
||||
case 0: /*High density*/
|
||||
bit_rate = 500;
|
||||
break;
|
||||
case 1: /*Double density (360 rpm)*/
|
||||
switch(fdc.drvrate[drive])
|
||||
{
|
||||
case 0:
|
||||
bit_rate = 300;
|
||||
break;
|
||||
case 1:
|
||||
bit_rate = 500;
|
||||
break;
|
||||
case 2:
|
||||
bit_rate = 2000;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2: /*Double density*/
|
||||
bit_rate = 250;
|
||||
break;
|
||||
case 3: /*Extended density*/
|
||||
bit_rate = 1000;
|
||||
break;
|
||||
}
|
||||
|
||||
fdc.bitcell_period = 1000000 / bit_rate*2; /*Bitcell period in ns*/
|
||||
// pclog("fdc_update_rate: rate=%i bit_rate=%i bitcell_period=%i\n", fdc.rate, bit_rate, fdc.bitcell_period);
|
||||
}
|
||||
|
||||
int fdc_get_bitcell_period()
|
||||
{
|
||||
return fdc.bitcell_period;
|
||||
}
|
||||
|
||||
static int fdc_get_densel(int drive)
|
||||
{
|
||||
switch (fdc.rwc[drive])
|
||||
{
|
||||
case 1:
|
||||
case 3:
|
||||
return 0;
|
||||
case 2:
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!fdc.is_nsc)
|
||||
{
|
||||
switch (fdc.densel_force)
|
||||
{
|
||||
case 2:
|
||||
return 1;
|
||||
case 3:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (fdc.densel_force)
|
||||
{
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
switch (fdc.rate)
|
||||
{
|
||||
case 0:
|
||||
case 3:
|
||||
return fdc.densel_polarity ? 1 : 0;
|
||||
case 1:
|
||||
case 2:
|
||||
return fdc.densel_polarity ? 0 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void fdc_rate(int drive)
|
||||
{
|
||||
fdc_update_rate(drive);
|
||||
disc_set_rate(drive, fdc.drvrate[drive], fdc.rate);
|
||||
fdd_set_densel(fdc_get_densel(drive));
|
||||
}
|
||||
|
||||
void fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
// pclog("Write FDC %04X %02X %04X:%04X %i %02X %i rate=%i %i\n",addr,val,cs>>4,pc,ins,fdc.st0,ins,fdc.rate, fdc.data_ready);
|
||||
int drive;
|
||||
|
||||
switch (addr&7)
|
||||
{
|
||||
case 1: return;
|
||||
|
|
@ -149,6 +370,14 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
|
|||
fdc.dor=val;
|
||||
// printf("DOR now %02X\n",val);
|
||||
return;
|
||||
case 3:
|
||||
/* TDR */
|
||||
if (fdc.enh_mode)
|
||||
{
|
||||
drive = (fdc.dor & 1) ^ fdd_swap;
|
||||
fdc.rwc[drive] = (val & 0x30) >> 4;
|
||||
}
|
||||
return;
|
||||
case 4:
|
||||
if (val & 0x80)
|
||||
{
|
||||
|
|
@ -162,8 +391,16 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
|
|||
case 5: /*Command register*/
|
||||
if ((fdc.stat & 0xf0) == 0xb0)
|
||||
{
|
||||
fdc.dat = val;
|
||||
fdc.stat &= ~0x80;
|
||||
if (fdc.pcjr || !fdc.fifo)
|
||||
{
|
||||
fdc.dat = val;
|
||||
fdc.stat &= ~0x80;
|
||||
}
|
||||
else
|
||||
{
|
||||
fdc_fifo_buf_write(val);
|
||||
if (fdc.fifobufpos == 0) fdc.stat &= ~0x80;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// if (fdc.inread)
|
||||
|
|
@ -178,6 +415,15 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
|
|||
// pclog("Starting FDC command %02X\n",fdc.command);
|
||||
switch (fdc.command&0x1F)
|
||||
{
|
||||
case 1: /*Mode*/
|
||||
if (!fdc.is_nsc) goto bad_command;
|
||||
fdc.pnum=0;
|
||||
fdc.ptot=4;
|
||||
fdc.stat=0x90;
|
||||
fdc.pos=0;
|
||||
fdc.format_state = 0;
|
||||
break;
|
||||
|
||||
case 2: /*Read track*/
|
||||
fdc.pnum=0;
|
||||
fdc.ptot=8;
|
||||
|
|
@ -273,13 +519,19 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
|
|||
break;
|
||||
|
||||
case 0x18:
|
||||
fdc.stat = 0x10;
|
||||
discint = 0xfc;
|
||||
if (!fdc.is_nsc) goto bad_command;
|
||||
fdc.lastdrive = fdc.drive;
|
||||
discint = 0x10;
|
||||
fdc.pos = 0;
|
||||
fdc_callback();
|
||||
/* fdc.stat = 0x10;
|
||||
discint = 0xfc;
|
||||
fdc_callback(); */
|
||||
break;
|
||||
|
||||
default:
|
||||
fatal("Bad FDC command %02X\n",val);
|
||||
bad_command:
|
||||
// fatal("Bad FDC command %02X\n",val);
|
||||
// dumpregs();
|
||||
// exit(-1);
|
||||
fdc.stat=0x10;
|
||||
|
|
@ -304,31 +556,35 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
|
|||
// fdc.drive = fdc.params[0] & 3;
|
||||
disc_drivesel = fdc.drive & 1;
|
||||
fdc_reset_stat = 0;
|
||||
disc_set_drivesel(fdc.drive & 1);
|
||||
switch (discint)
|
||||
{
|
||||
case 2: /*Read a track*/
|
||||
fdc.track[fdc.drive]=fdc.params[1];
|
||||
fdc_rate(fdc.drive);
|
||||
fdc.head=fdc.params[2];
|
||||
fdc.sector=fdc.params[3];
|
||||
fdc.eot[fdc.drive] = fdc.params[5];
|
||||
if (fdc.config & 0x40)
|
||||
disc_seek(fdc.drive, fdc.track[fdc.drive]);
|
||||
fdd_seek(fdc.drive, fdc.params[1] - fdc.track[fdc.drive]);
|
||||
fdc.track[fdc.drive]=fdc.params[1];
|
||||
// pclog("Read a track track=%i head=%i sector=%i eot=%i\n", fdc.track[fdc.drive], fdc.head, fdc.sector, fdc.eot[fdc.drive]);
|
||||
disc_readsector(fdc.drive, SECTOR_FIRST, fdc.track[fdc.drive], fdc.head, fdc.rate);
|
||||
disc_readsector(fdc.drive, SECTOR_FIRST, fdc.track[fdc.drive], fdc.head, fdc.rate, fdc.params[4]);
|
||||
disctime = 0;
|
||||
readflash = 1;
|
||||
fdc.inread = 1;
|
||||
break;
|
||||
|
||||
case 5: /*Write data*/
|
||||
fdc.track[fdc.drive]=fdc.params[1];
|
||||
fdc_rate(fdc.drive);
|
||||
fdc.head=fdc.params[2];
|
||||
fdc.sector=fdc.params[3];
|
||||
fdc.eot[fdc.drive] = fdc.params[4];
|
||||
fdc.eot[fdc.drive] = fdc.params[5];
|
||||
if (fdc.config & 0x40)
|
||||
disc_seek(fdc.drive, fdc.track[fdc.drive]);
|
||||
fdd_seek(fdc.drive, fdc.params[1] - fdc.track[fdc.drive]);
|
||||
fdc.track[fdc.drive]=fdc.params[1];
|
||||
fdc.rw_track = fdc.params[1];
|
||||
|
||||
disc_writesector(fdc.drive, fdc.sector, fdc.track[fdc.drive], fdc.head, fdc.rate);
|
||||
disc_writesector(fdc.drive, fdc.sector, fdc.track[fdc.drive], fdc.head, fdc.rate, fdc.params[4]);
|
||||
disctime = 0;
|
||||
fdc.written = 0;
|
||||
readflash = 1;
|
||||
|
|
@ -339,14 +595,16 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
|
|||
break;
|
||||
|
||||
case 6: /*Read data*/
|
||||
fdc.track[fdc.drive]=fdc.params[1];
|
||||
fdc_rate(fdc.drive);
|
||||
fdc.head=fdc.params[2];
|
||||
fdc.sector=fdc.params[3];
|
||||
fdc.eot[fdc.drive] = fdc.params[4];
|
||||
fdc.eot[fdc.drive] = fdc.params[5];
|
||||
if (fdc.config & 0x40)
|
||||
disc_seek(fdc.drive, fdc.track[fdc.drive]);
|
||||
fdd_seek(fdc.drive, fdc.params[1] - fdc.track[fdc.drive]);
|
||||
fdc.track[fdc.drive]=fdc.params[1];
|
||||
fdc.rw_track = fdc.params[1];
|
||||
|
||||
disc_readsector(fdc.drive, fdc.sector, fdc.track[fdc.drive], fdc.head, fdc.rate);
|
||||
disc_readsector(fdc.drive, fdc.sector, fdc.track[fdc.drive], fdc.head, fdc.rate, fdc.params[4]);
|
||||
disctime = 0;
|
||||
readflash = 1;
|
||||
fdc.inread = 1;
|
||||
|
|
@ -355,10 +613,12 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
|
|||
case 7: /*Recalibrate*/
|
||||
fdc.stat = 1 << fdc.drive;
|
||||
disctime = 0;
|
||||
disc_seek(fdc.drive, 0);
|
||||
fdd_seek(fdc.drive, SEEK_RECALIBRATE);
|
||||
break;
|
||||
|
||||
case 0x0d: /*Format*/
|
||||
fdc_rate(fdc.drive);
|
||||
fdc.head = (fdc.params[0] & 4) ? 1 : 0;
|
||||
fdc.format_state = 1;
|
||||
fdc.pos = 0;
|
||||
fdc.stat = 0x30;
|
||||
|
|
@ -368,13 +628,15 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
|
|||
fdc.stat = 1 << fdc.drive;
|
||||
fdc.head = (fdc.params[0] & 4) ? 1 : 0;
|
||||
disctime = 0;
|
||||
disc_seek(fdc.drive, fdc.params[1]);
|
||||
fdd_seek(fdc.drive, fdc.params[1] - fdc.track[fdc.drive]);
|
||||
// pclog("Seek to %i\n", fdc.params[1]);
|
||||
break;
|
||||
|
||||
case 10: /*Read sector ID*/
|
||||
fdc_rate(fdc.drive);
|
||||
disctime = 0;
|
||||
fdc.head = (fdc.params[0] & 4) ? 1 : 0;
|
||||
// rpclog("Read sector ID %i %i\n", fdc.rate, fdc.drive);
|
||||
// pclog("Read sector ID %i %i\n", fdc.rate, fdc.drive);
|
||||
disc_readaddress(fdc.drive, fdc.track[fdc.drive], fdc.head, fdc.rate);
|
||||
break;
|
||||
}
|
||||
|
|
@ -384,7 +646,6 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv)
|
|||
case 7:
|
||||
if (!AT) return;
|
||||
fdc.rate=val&3;
|
||||
disc_set_rate(fdc.rate);
|
||||
|
||||
disc_3f7=val;
|
||||
return;
|
||||
|
|
@ -398,21 +659,28 @@ int paramstogo=0;
|
|||
uint8_t fdc_read(uint16_t addr, void *priv)
|
||||
{
|
||||
uint8_t temp;
|
||||
int drive;
|
||||
// /*if (addr!=0x3f4) */printf("Read FDC %04X %04X:%04X %04X %i %02X %02x %i ",addr,cs>>4,pc,BX,fdc.pos,fdc.st0,fdc.stat,ins);
|
||||
switch (addr&7)
|
||||
{
|
||||
case 1: /*???*/
|
||||
drive = (fdc.dor & 1) ^ fdd_swap;
|
||||
if (!fdc.enable_3f1)
|
||||
return 0xff;
|
||||
// temp=0x50;
|
||||
temp = 0x70;
|
||||
if (fdc.dor & 1)
|
||||
if (drive)
|
||||
temp &= ~0x40;
|
||||
else
|
||||
temp &= ~0x20;
|
||||
break;
|
||||
case 3:
|
||||
temp = 0x20;
|
||||
if (!fdc.enh_mode)
|
||||
temp = 0x20;
|
||||
else
|
||||
{
|
||||
temp = fdc.rwc[drive] << 4;
|
||||
}
|
||||
break;
|
||||
case 4: /*Status*/
|
||||
temp=fdc.stat;
|
||||
|
|
@ -421,7 +689,12 @@ uint8_t fdc_read(uint16_t addr, void *priv)
|
|||
fdc.stat&=~0x80;
|
||||
if ((fdc.stat & 0xf0) == 0xf0)
|
||||
{
|
||||
temp = fdc.dat;
|
||||
if (fdc.pcjr || !fdc.fifo)
|
||||
temp = fdc.dat;
|
||||
else
|
||||
{
|
||||
temp = fdc_fifo_buf_read();
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (paramstogo)
|
||||
|
|
@ -457,8 +730,9 @@ uint8_t fdc_read(uint16_t addr, void *priv)
|
|||
fdc.stat &= 0xf0;
|
||||
break;
|
||||
case 7: /*Disk change*/
|
||||
if (fdc.dor & (0x10 << (fdc.dor & 1)))
|
||||
temp = (disc_changed[fdc.drive] || drive_empty[fdc.drive]) ? 0x80 : 0;
|
||||
drive = (fdc.dor & 1) ^ fdd_swap;
|
||||
if (fdc.dor & (0x10 << drive))
|
||||
temp = (disc_changed[drive] || drive_empty[drive])?0x80:0;
|
||||
else
|
||||
temp = 0;
|
||||
if (fdc.dskchg_activelow) /*PC2086/3086 seem to reverse this bit*/
|
||||
|
|
@ -497,6 +771,11 @@ void fdc_callback()
|
|||
fdc_int();
|
||||
fdc_reset_stat = 4;
|
||||
return;
|
||||
case 1: /*Mode*/
|
||||
fdc.stat=0x80;
|
||||
fdc.densel_force = (fdc.params[2] & 0xC0) >> 6;
|
||||
return;
|
||||
|
||||
case 2: /*Read track*/
|
||||
readflash = 1;
|
||||
fdc.eot[fdc.drive]--;
|
||||
|
|
@ -518,17 +797,18 @@ void fdc_callback()
|
|||
return;
|
||||
}
|
||||
else
|
||||
disc_readsector(fdc.drive, SECTOR_NEXT, fdc.track[fdc.drive], fdc.head, fdc.rate);
|
||||
disc_readsector(fdc.drive, SECTOR_NEXT, fdc.track[fdc.drive], fdc.head, fdc.rate, fdc.params[4]);
|
||||
fdc.inread = 1;
|
||||
return;
|
||||
case 3: /*Specify*/
|
||||
fdc.stat=0x80;
|
||||
fdc.specify[0] = fdc.params[0];
|
||||
fdc.specify[1] = fdc.params[1];
|
||||
fdc.dma = (fdc.specify[1] & 1) ^ 1;
|
||||
return;
|
||||
case 4: /*Sense drive status*/
|
||||
fdc.res[10] = (fdc.params[0] & 7) | 0x28;
|
||||
if (!fdc.track[fdc.drive])
|
||||
if (fdd_track0(fdc.drive))
|
||||
fdc.res[10] |= 0x10;
|
||||
if (writeprot[fdc.drive])
|
||||
fdc.res[10] |= 0x40;
|
||||
|
|
@ -549,7 +829,8 @@ void fdc_callback()
|
|||
fdc.head ^= 1;
|
||||
if (!fdc.head)
|
||||
{
|
||||
fdc.track[fdc.drive]++;
|
||||
fdc.rw_track++;
|
||||
// fdc.track[fdc.drive]++;
|
||||
/* if (fdc.track[fdc.drive] >= 79)
|
||||
{
|
||||
fdc.track[fdc.drive] = 79;
|
||||
|
|
@ -559,7 +840,8 @@ void fdc_callback()
|
|||
}
|
||||
else
|
||||
{
|
||||
fdc.track[fdc.drive]++;
|
||||
fdc.rw_track++;
|
||||
// fdc.track[fdc.drive]++;
|
||||
fdc.tc = 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -570,14 +852,14 @@ void fdc_callback()
|
|||
fdc.stat=0xD0;
|
||||
fdc.res[4]=(fdc.head?4:0)|fdc.drive;
|
||||
fdc.res[5]=fdc.res[6]=0;
|
||||
fdc.res[7]=fdc.track[fdc.drive];
|
||||
fdc.res[7]=fdc.rw_track;
|
||||
fdc.res[8]=fdc.head;
|
||||
fdc.res[9]=fdc.sector;
|
||||
fdc.res[10]=fdc.params[4];
|
||||
paramstogo=7;
|
||||
return;
|
||||
}
|
||||
disc_writesector(fdc.drive, fdc.sector, fdc.track[fdc.drive], fdc.head, fdc.rate);
|
||||
disc_writesector(fdc.drive, fdc.sector, fdc.rw_track, fdc.head, fdc.rate, fdc.params[4]);
|
||||
// ioc_fiq(IOC_FIQ_DISC_DATA);
|
||||
return;
|
||||
case 6: /*Read data*/
|
||||
|
|
@ -592,7 +874,8 @@ void fdc_callback()
|
|||
fdc.head ^= 1;
|
||||
if (!fdc.head)
|
||||
{
|
||||
fdc.track[fdc.drive]++;
|
||||
fdc.rw_track++;
|
||||
// fdc.track[fdc.drive]++;
|
||||
/* if (fdc.track[fdc.drive] >= 79)
|
||||
{
|
||||
fdc.track[fdc.drive] = 79;
|
||||
|
|
@ -602,7 +885,8 @@ void fdc_callback()
|
|||
}
|
||||
else
|
||||
{
|
||||
fdc.track[fdc.drive]++;
|
||||
fdc.rw_track++;
|
||||
// fdc.track[fdc.drive]++;
|
||||
fdc.tc = 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -614,14 +898,14 @@ void fdc_callback()
|
|||
fdc.stat=0xD0;
|
||||
fdc.res[4]=(fdc.head?4:0)|fdc.drive;
|
||||
fdc.res[5]=fdc.res[6]=0;
|
||||
fdc.res[7]=fdc.track[fdc.drive];
|
||||
fdc.res[7]=fdc.rw_track;
|
||||
fdc.res[8]=fdc.head;
|
||||
fdc.res[9]=fdc.sector;
|
||||
fdc.res[10]=fdc.params[4];
|
||||
paramstogo=7;
|
||||
return;
|
||||
}
|
||||
disc_readsector(fdc.drive, fdc.sector, fdc.track[fdc.drive], fdc.head, fdc.rate);
|
||||
disc_readsector(fdc.drive, fdc.sector, fdc.rw_track, fdc.head, fdc.rate, fdc.params[4]);
|
||||
fdc.inread = 1;
|
||||
return;
|
||||
|
||||
|
|
@ -686,10 +970,10 @@ void fdc_callback()
|
|||
disctime = 128 * (1 << TIMER_SHIFT);
|
||||
timer_update_outstanding();
|
||||
}
|
||||
else if (fdc.format_state == 4)
|
||||
else if (fdc.format_state == 3)
|
||||
{
|
||||
// rpclog("Format next stage\n");
|
||||
disc_format(fdc.drive, fdc.track[fdc.drive], fdc.head, fdc.rate);
|
||||
// pclog("Format next stage track %i head %i\n", fdc.track[fdc.drive], fdc.head);
|
||||
disc_format(fdc.drive, fdc.track[fdc.drive], fdc.head, fdc.rate, fdc.params[4]);
|
||||
fdc.format_state = 4;
|
||||
}
|
||||
else
|
||||
|
|
@ -756,6 +1040,9 @@ void fdc_callback()
|
|||
case 0x13: /*Configure*/
|
||||
fdc.config = fdc.params[1];
|
||||
fdc.pretrk = fdc.params[2];
|
||||
fdc.fifo = (fdc.params[1] & 0x20) ? 0 : 1;
|
||||
fdc.tfifo = (fdc.params[1] & 0xF) + 1;
|
||||
pclog("FIFO is now %02X, threshold is %02X\n", fdc.fifo, fdc.tfifo);
|
||||
fdc.stat = 0x80;
|
||||
disctime = 0;
|
||||
// picint(0x40);
|
||||
|
|
@ -777,6 +1064,13 @@ void fdc_callback()
|
|||
disctime = 0;
|
||||
return;
|
||||
|
||||
case 0x18: /*NSC*/
|
||||
fdc.stat = (fdc.stat & 0xf) | 0xd0;
|
||||
fdc.res[10] = 0x73;
|
||||
paramstogo=1;
|
||||
discint=0;
|
||||
disctime = 0;
|
||||
return;
|
||||
|
||||
case 0xfc: /*Invalid*/
|
||||
fdc.dat = fdc.st0 = 0x80;
|
||||
|
|
@ -797,7 +1091,7 @@ void fdc_callback()
|
|||
|
||||
void fdc_overrun()
|
||||
{
|
||||
img_stop();
|
||||
disc_sector_stop();
|
||||
disctime = 0;
|
||||
|
||||
fdc_int();
|
||||
|
|
@ -817,7 +1111,7 @@ int fdc_data(uint8_t data)
|
|||
if (fdc.tc)
|
||||
return 0;
|
||||
|
||||
if (fdc.pcjr)
|
||||
if (fdc.pcjr || !fdc.dma)
|
||||
{
|
||||
if (fdc.data_ready)
|
||||
{
|
||||
|
|
@ -826,15 +1120,44 @@ int fdc_data(uint8_t data)
|
|||
return -1;
|
||||
}
|
||||
|
||||
fdc.dat = data;
|
||||
fdc.data_ready = 1;
|
||||
fdc.stat = 0xf0;
|
||||
// pclog("fdc_data\n");
|
||||
if (fdc.pcjr || !fdc.fifo)
|
||||
{
|
||||
fdc.dat = data;
|
||||
fdc.data_ready = 1;
|
||||
fdc.stat = 0xf0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIFO enabled
|
||||
fdc_fifo_buf_write(data);
|
||||
if (fdc.fifobufpos == 0)
|
||||
{
|
||||
// We have wrapped around, means FIFO is over
|
||||
fdc.data_ready = 1;
|
||||
fdc.stat = 0xf0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dma_channel_write(2, data) & DMA_OVER)
|
||||
fdc.tc = 1;
|
||||
|
||||
if (!fdc.fifo)
|
||||
{
|
||||
fdc.data_ready = 1;
|
||||
fdc.stat = 0xd0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fdc_fifo_buf_dummy();
|
||||
if (fdc.fifobufpos == 0)
|
||||
{
|
||||
// We have wrapped around, means FIFO is over
|
||||
fdc.data_ready = 1;
|
||||
fdc.stat = 0xd0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -918,7 +1241,7 @@ int fdc_getdata(int last)
|
|||
{
|
||||
int data;
|
||||
|
||||
if (fdc.pcjr)
|
||||
if (fdc.pcjr || !fdc.dma)
|
||||
{
|
||||
if (fdc.written)
|
||||
{
|
||||
|
|
@ -926,14 +1249,38 @@ int fdc_getdata(int last)
|
|||
// pclog("Overrun\n");
|
||||
return -1;
|
||||
}
|
||||
data = fdc.dat;
|
||||
if (!last)
|
||||
fdc.stat = 0xb0;
|
||||
if (fdc.pcjr || !fdc.fifo)
|
||||
{
|
||||
data = fdc.dat;
|
||||
|
||||
if (!last)
|
||||
fdc.stat = 0xb0;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = fdc_fifo_buf_read();
|
||||
|
||||
if (!last && (fdc.fifobufpos == 0))
|
||||
fdc.stat = 0xb0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
data = dma_channel_read(2);
|
||||
|
||||
if (!fdc.fifo)
|
||||
{
|
||||
if (!last)
|
||||
fdc.stat = 0x90;
|
||||
}
|
||||
else
|
||||
{
|
||||
fdc_fifo_buf_dummy();
|
||||
|
||||
if (!last && (fdc.fifobufpos == 0))
|
||||
fdc.stat = 0x90;
|
||||
}
|
||||
|
||||
if (data & DMA_OVER)
|
||||
fdc.tc = 1;
|
||||
}
|
||||
|
|
@ -968,6 +1315,14 @@ void fdc_init()
|
|||
timer_add(fdc_callback, &disctime, &disctime, NULL);
|
||||
fdc.dskchg_activelow = 0;
|
||||
fdc.enable_3f1 = 1;
|
||||
|
||||
fdc_update_enh_mode(0);
|
||||
fdc_update_densel_polarity(1);
|
||||
fdc_update_rwc(0, 0);
|
||||
fdc_update_rwc(1, 0);
|
||||
fdc_update_densel_force(0);
|
||||
|
||||
fdc.fifo = fdc.tfifo = 0;
|
||||
}
|
||||
|
||||
void fdc_add()
|
||||
|
|
|
|||
12
src/fdc.h
12
src/fdc.h
|
|
@ -9,3 +9,15 @@ void fdc_abort();
|
|||
void fdc_discchange_clear(int drive);
|
||||
void fdc_set_dskchg_activelow();
|
||||
void fdc_3f1_enable(int enable);
|
||||
int fdc_get_bitcell_period();
|
||||
|
||||
/* A few functions to communicate between Super I/O chips and the FDC. */
|
||||
void fdc_update_is_nsc(int is_nsc);
|
||||
void fdc_update_enh_mode(int enh_mode);
|
||||
int fdc_get_rwc(int drive);
|
||||
void fdc_update_rwc(int drive, int rwc);
|
||||
int fdc_get_boot_drive();
|
||||
void fdc_update_boot_drive(int boot_drive);
|
||||
void fdc_update_densel_polarity(int densel_polarity);
|
||||
void fdc_update_densel_force(int densel_force);
|
||||
void fdc_update_drvrate(int drive, int drvrate);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "ibm.h"
|
||||
|
||||
#include "fdc.h"
|
||||
#include "fdd.h"
|
||||
#include "io.h"
|
||||
#include "lpt.h"
|
||||
#include "serial.h"
|
||||
|
|
@ -109,6 +110,11 @@ void fdc37c665_write(uint16_t port, uint8_t val, void *priv)
|
|||
lpt1_init(0x278);
|
||||
break;
|
||||
}
|
||||
|
||||
fdc_update_enh_mode((fdc37c665_regs[3] & 2) ? 1 : 0);
|
||||
|
||||
fdc_update_densel_force((fdc37c665_regs[5] & 0x18) >> 3);
|
||||
fdd_swap = ((fdc37c665_regs[5] & 0x20) >> 5);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -133,6 +139,8 @@ void fdc37c665_init()
|
|||
{
|
||||
io_sethandler(0x03f0, 0x0002, fdc37c665_read, NULL, NULL, fdc37c665_write, NULL, NULL, NULL);
|
||||
|
||||
fdc_update_is_nsc(0);
|
||||
|
||||
fdc37c665_lock[0] = fdc37c665_lock[1] = 0;
|
||||
fdc37c665_regs[0x0] = 0x3b;
|
||||
fdc37c665_regs[0x1] = 0x9f;
|
||||
|
|
@ -150,4 +158,8 @@ void fdc37c665_init()
|
|||
fdc37c665_regs[0xd] = 0x65;
|
||||
fdc37c665_regs[0xe] = 0x01;
|
||||
fdc37c665_regs[0xf] = 0x00;
|
||||
|
||||
fdc_update_densel_polarity(1);
|
||||
fdc_update_densel_force(0);
|
||||
fdd_swap = 0;
|
||||
}
|
||||
|
|
|
|||
183
src/fdd.c
Normal file
183
src/fdd.c
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
#include "ibm.h"
|
||||
#include "disc.h"
|
||||
#include "fdc.h"
|
||||
#include "fdd.h"
|
||||
|
||||
static struct
|
||||
{
|
||||
int type;
|
||||
|
||||
int track;
|
||||
|
||||
int densel;
|
||||
|
||||
int drate;
|
||||
|
||||
int kbps;
|
||||
int fdc_kbps;
|
||||
} fdd[2];
|
||||
|
||||
/* Flags:
|
||||
Bit 0: 300 rpm supported;
|
||||
Bit 1: 360 rpm supported;
|
||||
Bit 2: size (0 = 3.5", 1 = 5.25");
|
||||
Bit 3: double density supported;
|
||||
Bit 4: high density supported;
|
||||
Bit 5: extended density supported;
|
||||
Bit 6: double step for 40-track media;
|
||||
*/
|
||||
#define FLAG_RPM_300 1
|
||||
#define FLAG_RPM_360 2
|
||||
#define FLAG_525 4
|
||||
#define FLAG_HOLE0 8
|
||||
#define FLAG_HOLE1 16
|
||||
#define FLAG_HOLE2 32
|
||||
#define FLAG_DOUBLE_STEP 64
|
||||
|
||||
static struct
|
||||
{
|
||||
int max_track;
|
||||
int flags;
|
||||
} drive_types[] =
|
||||
{
|
||||
{ /*None*/
|
||||
.max_track = 0,
|
||||
.flags = 0
|
||||
},
|
||||
{ /*5.25" DD*/
|
||||
.max_track = 41,
|
||||
.flags = FLAG_RPM_300 | FLAG_525 | FLAG_HOLE0
|
||||
},
|
||||
{ /*5.25" HD*/
|
||||
.max_track = 82,
|
||||
.flags = FLAG_RPM_360 | FLAG_525 | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP
|
||||
},
|
||||
{ /*5.25" HD Dual RPM*/
|
||||
.max_track = 82,
|
||||
.flags = FLAG_RPM_300 | FLAG_RPM_360 | FLAG_525 | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP
|
||||
},
|
||||
{ /*3.5" DD*/
|
||||
.max_track = 82,
|
||||
.flags = FLAG_RPM_300 | FLAG_HOLE0
|
||||
},
|
||||
{ /*3.5" HD*/
|
||||
.max_track = 82,
|
||||
.flags = FLAG_RPM_300 | FLAG_HOLE0 | FLAG_HOLE1
|
||||
},
|
||||
{ /*3.5" HD 3-Mode*/
|
||||
.max_track = 82,
|
||||
.flags = FLAG_RPM_300 | FLAG_RPM_360 | FLAG_HOLE0 | FLAG_HOLE1
|
||||
},
|
||||
{ /*3.5" ED*/
|
||||
.max_track = 82,
|
||||
.flags = FLAG_RPM_300 | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_HOLE2
|
||||
}
|
||||
};
|
||||
|
||||
int fdd_swap = 0;
|
||||
|
||||
void fdd_seek(int drive, int track_diff)
|
||||
{
|
||||
int old_track;
|
||||
|
||||
drive ^= fdd_swap;
|
||||
|
||||
old_track = fdd[drive].track;
|
||||
|
||||
fdd[drive].track += track_diff;
|
||||
|
||||
if (fdd[drive].track < 0)
|
||||
fdd[drive].track = 0;
|
||||
|
||||
if (fdd[drive].track > drive_types[fdd[drive].type].max_track)
|
||||
fdd[drive].track = drive_types[fdd[drive].type].max_track;
|
||||
|
||||
// pclog("fdd_seek: drive=%i track_diff=%i old_track=%i track=%i\n", drive, track_diff, old_track, fdd[drive].track);
|
||||
if (fdd[drive].track != old_track)
|
||||
fdc_discchange_clear(drive);
|
||||
disc_seek(drive, fdd[drive].track);
|
||||
disctime = 5000;
|
||||
}
|
||||
|
||||
int fdd_track0(int drive)
|
||||
{
|
||||
drive ^= fdd_swap;
|
||||
|
||||
/* If drive is disabled, TRK0 never gets set. */
|
||||
if (!drive_types[fdd[drive].type].max_track) return 0;
|
||||
|
||||
return !fdd[drive].track;
|
||||
}
|
||||
|
||||
void fdd_set_densel(int densel)
|
||||
{
|
||||
fdd[0].densel = densel;
|
||||
fdd[1].densel = densel;
|
||||
}
|
||||
|
||||
int fdd_getrpm(int drive)
|
||||
{
|
||||
int hole = disc_hole(drive);
|
||||
|
||||
drive ^= fdd_swap;
|
||||
|
||||
if (!(drive_types[fdd[drive].type].flags & FLAG_RPM_360)) return 300;
|
||||
if (!(drive_types[fdd[drive].type].flags & FLAG_RPM_300)) return 360;
|
||||
|
||||
if (drive_types[fdd[drive].type].flags & FLAG_525)
|
||||
{
|
||||
return fdd[drive].densel ? 360 : 300;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* disc_hole(drive) returns 0 for double density media, 1 for high density, and 2 for extended density. */
|
||||
if (hole == 1)
|
||||
{
|
||||
return fdd[drive].densel ? 300 : 360;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 300;
|
||||
}
|
||||
}
|
||||
|
||||
switch (fdd[drive].type)
|
||||
{
|
||||
case 0:
|
||||
return 300;
|
||||
case 1:
|
||||
return 360;
|
||||
}
|
||||
}
|
||||
|
||||
void fdd_setswap(int swap)
|
||||
{
|
||||
fdd_swap = swap ? 1 : 0;
|
||||
}
|
||||
|
||||
int fdd_can_read_medium(int drive)
|
||||
{
|
||||
int hole = disc_hole(drive);
|
||||
|
||||
drive ^= fdd_swap;
|
||||
|
||||
hole = 1 << (hole + 3);
|
||||
|
||||
// pclog("Drive %02X, type %02X, hole flag %02X, flags %02X, result %02X\n", drive, fdd[drive].type, hole, drive_types[fdd[drive].type].flags, drive_types[fdd[drive].type].flags & hole);
|
||||
return (drive_types[fdd[drive].type].flags & hole) ? 1 : 0;
|
||||
}
|
||||
|
||||
int fdd_doublestep_40(int drive)
|
||||
{
|
||||
return drive_types[fdd[drive].type].flags & FLAG_DOUBLE_STEP;
|
||||
}
|
||||
|
||||
void fdd_set_type(int drive, int type)
|
||||
{
|
||||
fdd[drive].type = type;
|
||||
}
|
||||
|
||||
int fdd_get_type(int drive)
|
||||
{
|
||||
return fdd[drive].type;
|
||||
}
|
||||
12
src/fdd.h
Normal file
12
src/fdd.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#define SEEK_RECALIBRATE -999
|
||||
void fdd_seek(int drive, int track_diff);
|
||||
int fdd_track0(int drive);
|
||||
int fdd_getrpm(int drive);
|
||||
void fdd_set_densel(int densel);
|
||||
int fdd_can_read_medium(int drive);
|
||||
int fdd_doublestep_40(int drive);
|
||||
|
||||
void fdd_set_type(int drive, int type);
|
||||
int fdd_get_type(int drive);
|
||||
|
||||
extern int fdd_swap;
|
||||
9
src/pc.c
9
src/pc.c
|
|
@ -16,6 +16,7 @@
|
|||
#include "cpu.h"
|
||||
#include "dma.h"
|
||||
#include "fdc.h"
|
||||
#include "fdd.h"
|
||||
#include "sound_gus.h"
|
||||
#include "ide.h"
|
||||
#include "keyboard.h"
|
||||
|
|
@ -596,8 +597,8 @@ void loadconfig(char *fn)
|
|||
if (p) strcpy(ide_fn[3], p);
|
||||
else strcpy(ide_fn[3], "");
|
||||
|
||||
drive_type[0] = config_get_int(NULL, "drive_a_type", 0);
|
||||
drive_type[1] = config_get_int(NULL, "drive_b_type", 0);
|
||||
fdd_set_type(0, config_get_int(NULL, "drive_a_type", 0));
|
||||
fdd_set_type(1, config_get_int(NULL, "drive_b_type", 0));
|
||||
}
|
||||
|
||||
void saveconfig()
|
||||
|
|
@ -647,8 +648,8 @@ void saveconfig()
|
|||
config_set_int(NULL, "hdf_cylinders", hdc[3].tracks);
|
||||
config_set_string(NULL, "hdf_fn", ide_fn[3]);
|
||||
|
||||
config_set_int(NULL, "drive_a_type", drive_type[0]);
|
||||
config_set_int(NULL, "drive_b_type", drive_type[1]);
|
||||
config_set_int(NULL, "drive_a_type", fdd_get_type(0));
|
||||
config_set_int(NULL, "drive_b_type", fdd_get_type(1));
|
||||
|
||||
config_save(config_file_default);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include "ibm.h"
|
||||
#include "cpu.h"
|
||||
#include "device.h"
|
||||
#include "disc.h"
|
||||
#include "fdd.h"
|
||||
#include "model.h"
|
||||
#include "resources.h"
|
||||
#include "sound.h"
|
||||
|
|
@ -30,6 +30,8 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR
|
|||
int temp_GAMEBLASTER, temp_GUS, temp_SSI2001, temp_voodoo, temp_sound_card_current;
|
||||
int temp_dynarec;
|
||||
int cpu_flags;
|
||||
int temp_fda_type, temp_fdb_type;
|
||||
|
||||
UDACCEL accel;
|
||||
// pclog("Dialog msg %i %08X\n",message,message);
|
||||
switch (message)
|
||||
|
|
@ -190,13 +192,25 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR
|
|||
EnableWindow(h, FALSE);
|
||||
|
||||
h = GetDlgItem(hdlg, IDC_COMBODRA);
|
||||
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"5.25\" 360k / 3.5\"");
|
||||
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"None");
|
||||
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"5.25\" 360k");
|
||||
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"5.25\" 1.2M");
|
||||
SendMessage(h, CB_SETCURSEL, drive_type[0], 0);
|
||||
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"5.25\" 1.2M Dual RPM");
|
||||
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 720k");
|
||||
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 1.44M");
|
||||
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 1.44M 3-Mode");
|
||||
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 2.88M");
|
||||
SendMessage(h, CB_SETCURSEL, fdd_get_type(0), 0);
|
||||
h = GetDlgItem(hdlg, IDC_COMBODRB);
|
||||
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"5.25\" 360k / 3.5\"");
|
||||
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"None");
|
||||
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"5.25\" 360k");
|
||||
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"5.25\" 1.2M");
|
||||
SendMessage(h, CB_SETCURSEL, drive_type[1], 0);
|
||||
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"5.25\" 1.2M Dual RPM");
|
||||
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 720k");
|
||||
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 1.44M");
|
||||
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 1.44M 3-Mode");
|
||||
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"3.5\" 2.88M");
|
||||
SendMessage(h, CB_SETCURSEL, fdd_get_type(1), 0);
|
||||
|
||||
h = GetDlgItem(hdlg, IDC_TEXT_MB);
|
||||
if (models[model].is_at)
|
||||
|
|
@ -251,10 +265,16 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR
|
|||
h = GetDlgItem(hdlg, IDC_CHECKDYNAREC);
|
||||
temp_dynarec = SendMessage(h, BM_GETCHECK, 0, 0);
|
||||
|
||||
h = GetDlgItem(hdlg, IDC_COMBODRA);
|
||||
temp_fda_type = SendMessage(h, CB_GETCURSEL, 0, 0);
|
||||
h = GetDlgItem(hdlg, IDC_COMBODRB);
|
||||
temp_fdb_type = SendMessage(h, CB_GETCURSEL, 0, 0);
|
||||
|
||||
if (temp_model != model || gfx != gfxcard || mem != mem_size ||
|
||||
fpu != hasfpu || temp_GAMEBLASTER != GAMEBLASTER || temp_GUS != GUS ||
|
||||
temp_SSI2001 != SSI2001 || temp_sound_card_current != sound_card_current ||
|
||||
temp_voodoo != voodoo_enabled || temp_dynarec != cpu_use_dynarec)
|
||||
temp_voodoo != voodoo_enabled || temp_dynarec != cpu_use_dynarec ||
|
||||
temp_fda_type != fdd_get_type(0) || temp_fdb_type != fdd_get_type(1))
|
||||
{
|
||||
if (MessageBox(NULL,"This will reset PCem!\nOkay to continue?","PCem",MB_OKCANCEL)==IDOK)
|
||||
{
|
||||
|
|
@ -271,6 +291,9 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR
|
|||
voodoo_enabled = temp_voodoo;
|
||||
cpu_use_dynarec = temp_dynarec;
|
||||
|
||||
fdd_set_type(0, temp_fda_type);
|
||||
fdd_set_type(1, temp_fdb_type);
|
||||
|
||||
mem_resize();
|
||||
loadbios();
|
||||
resetpchard();
|
||||
|
|
@ -297,11 +320,6 @@ static BOOL CALLBACK config_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR
|
|||
cache=SendMessage(h, CB_GETCURSEL, 0, 0);
|
||||
mem_updatecache();
|
||||
|
||||
h = GetDlgItem(hdlg, IDC_COMBODRA);
|
||||
drive_type[0] = SendMessage(h, CB_GETCURSEL, 0, 0);
|
||||
h = GetDlgItem(hdlg, IDC_COMBODRB);
|
||||
drive_type[1] = SendMessage(h, CB_GETCURSEL, 0, 0);
|
||||
|
||||
saveconfig();
|
||||
|
||||
speedchanged();
|
||||
|
|
|
|||
Loading…
Reference in a new issue