pcem/src/disc_img.c
TomW a8159f8c09 Various changes to FDC emulation.
Support for multiple disc image formats.
Added preliminary FDI support.
2015-03-19 21:33:19 +00:00

307 lines
12 KiB
C

#include "ibm.h"
#include "disc.h"
#include "disc_img.h"
static struct
{
FILE *f;
uint8_t track_data[2][20*1024];
int sectors, tracks, sides;
int sector_size;
int rate;
} 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 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_pause = 0;
static int img_index = 6250;
void img_init()
{
memset(img, 0, sizeof(img));
// adl[0] = adl[1] = 0;
img_notfound = 0;
}
void img_load(int drive, char *fn)
{
int size;
writeprot[drive] = 0;
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];
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*/
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);
}
void img_close(int drive)
{
if (img[drive].f)
fclose(img[drive].f);
img[drive].f = NULL;
}
void img_seek(int drive, int track)
{
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);
disc_track[drive] = track;
if (img[drive].sides == 2)
{
fseek(img[drive].f, track * img[drive].sectors * img[drive].sector_size * 2, SEEK_SET);
fread(img[drive].track_data[0], img[drive].sectors * img[drive].sector_size, 1, img[drive].f);
fread(img[drive].track_data[1], img[drive].sectors * img[drive].sector_size, 1, img[drive].f);
}
else
{
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);
}
}
void img_writeback(int drive, int track)
{
if (!img[drive].f)
return;
if (img[drive].sides == 2)
{
fseek(img[drive].f, track * img[drive].sectors * img[drive].sector_size * 2, SEEK_SET);
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
{
fseek(img[drive].f, track * img[drive].sectors * img[drive].sector_size, SEEK_SET);
fwrite(img[drive].track_data[0], img[drive].sectors * img[drive].sector_size, 1, img[drive].f);
}
}
void img_readsector(int drive, int sector, int track, int side, int rate)
{
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]))
{
// 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 (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]))
{
img_notfound = 500;
return;
}
img_inwrite = 1;
img_readpos = 0;
img_pause = 32;
}
void img_readaddress(int drive, int track, int side, int rate)
{
img_drive = drive;
img_track = track;
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) || (track != disc_track[drive]))
{
// 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)
{
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);
}
}
}
}