2016-08-14 22:07:17 -04:00
|
|
|
/* Copyright holders: Sarah Walker, Tenshi
|
|
|
|
|
see COPYING for more details
|
|
|
|
|
*/
|
2016-06-26 00:34:39 +02:00
|
|
|
#include "ibm.h"
|
|
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
#include "disc.h"
|
|
|
|
|
#include "disc_fdi.h"
|
|
|
|
|
#include "disc_img.h"
|
2016-08-31 22:49:56 +02:00
|
|
|
#include "disc_86f.h"
|
2016-09-29 21:54:34 +02:00
|
|
|
#include "disc_td0.h"
|
2016-10-04 17:25:16 +02:00
|
|
|
#include "disc_imd.h"
|
2016-06-26 00:34:39 +02:00
|
|
|
#include "fdc.h"
|
|
|
|
|
#include "fdd.h"
|
|
|
|
|
#include "timer.h"
|
|
|
|
|
|
2016-11-08 03:58:36 +01:00
|
|
|
int disc_poll_time[2][2] = { { 16, 16 }, { 16, 16 } };
|
|
|
|
|
int disc_poll_enable[2][2] = { { 0, 0 }, { 0, 0 } };
|
2016-06-26 00:34:39 +02:00
|
|
|
|
|
|
|
|
int disc_track[2];
|
|
|
|
|
int writeprot[2], fwriteprot[2];
|
|
|
|
|
|
|
|
|
|
DRIVE drives[2];
|
|
|
|
|
int drive_type[2];
|
|
|
|
|
|
|
|
|
|
int curdrive = 0;
|
|
|
|
|
|
|
|
|
|
int swwp = 0;
|
|
|
|
|
int disable_write = 0;
|
|
|
|
|
|
|
|
|
|
//char discfns[2][260] = {"", ""};
|
|
|
|
|
int defaultwriteprot = 0;
|
|
|
|
|
|
|
|
|
|
int fdc_time;
|
|
|
|
|
int disc_time;
|
|
|
|
|
|
|
|
|
|
int fdc_ready;
|
|
|
|
|
|
|
|
|
|
int drive_empty[2] = {1, 1};
|
|
|
|
|
int disc_changed[2];
|
|
|
|
|
|
|
|
|
|
int motorspin;
|
2016-11-07 06:39:20 +01:00
|
|
|
int motoron[2];
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2016-11-08 03:58:36 +01:00
|
|
|
int do_poll[2];
|
|
|
|
|
|
|
|
|
|
int head_enable[2][2] = { 0, 0 };
|
|
|
|
|
int head_time[2][2] = { 0, 0 };
|
|
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
int fdc_indexcount = 52;
|
|
|
|
|
|
|
|
|
|
/*void (*fdc_callback)();
|
|
|
|
|
void (*fdc_data)(uint8_t dat);
|
|
|
|
|
void (*fdc_spindown)();
|
|
|
|
|
void (*fdc_finishread)();
|
|
|
|
|
void (*fdc_notfound)();
|
|
|
|
|
void (*fdc_datacrcerror)();
|
|
|
|
|
void (*fdc_headercrcerror)();
|
|
|
|
|
void (*fdc_writeprotect)();
|
|
|
|
|
int (*fdc_getdata)(int last);
|
|
|
|
|
void (*fdc_sectorid)(uint8_t track, uint8_t side, uint8_t sector, uint8_t size, uint8_t crc1, uint8_t crc2);
|
|
|
|
|
void (*fdc_indexpulse)();*/
|
|
|
|
|
|
|
|
|
|
static struct
|
|
|
|
|
{
|
|
|
|
|
char *ext;
|
|
|
|
|
void (*load)(int drive, char *fn);
|
|
|
|
|
void (*close)(int drive);
|
|
|
|
|
int size;
|
|
|
|
|
}
|
|
|
|
|
loaders[]=
|
|
|
|
|
{
|
2016-08-15 03:26:37 +02:00
|
|
|
{"12", img_load, img_close, -1},
|
|
|
|
|
{"144", img_load, img_close, -1},
|
|
|
|
|
{"360", img_load, img_close, -1},
|
|
|
|
|
{"720", img_load, img_close, -1},
|
2016-08-31 22:49:56 +02:00
|
|
|
{"86F", d86f_load, d86f_close, -1},
|
2016-10-05 00:59:04 +02:00
|
|
|
{"BIN", img_load, img_close, -1},
|
2016-08-15 03:26:37 +02:00
|
|
|
{"DSK", img_load, img_close, -1},
|
2016-10-04 17:25:16 +02:00
|
|
|
{"FDI", fdi_load, fdi_close, -1},
|
2016-08-15 03:26:37 +02:00
|
|
|
{"FLP", img_load, img_close, -1},
|
2016-10-05 00:59:04 +02:00
|
|
|
{"HDM", img_load, img_close, -1},
|
2016-06-26 00:34:39 +02:00
|
|
|
{"IMA", img_load, img_close, -1},
|
2016-10-04 17:25:16 +02:00
|
|
|
{"IMD", imd_load, imd_close, -1},
|
|
|
|
|
{"IMG", img_load, img_close, -1},
|
2016-09-29 21:54:34 +02:00
|
|
|
{"TD0", td0_load, td0_close, -1},
|
2016-08-15 03:26:37 +02:00
|
|
|
{"VFD", img_load, img_close, -1},
|
2016-06-26 00:34:39 +02:00
|
|
|
{"XDF", img_load, img_close, -1},
|
|
|
|
|
{0,0,0}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static int driveloaders[4];
|
|
|
|
|
|
|
|
|
|
void disc_load(int drive, char *fn)
|
|
|
|
|
{
|
|
|
|
|
int c = 0, size;
|
|
|
|
|
char *p;
|
|
|
|
|
FILE *f;
|
|
|
|
|
// pclog("disc_load %i %s\n", drive, fn);
|
|
|
|
|
// setejecttext(drive, "");
|
|
|
|
|
if (!fn) return;
|
|
|
|
|
p = get_extension(fn);
|
|
|
|
|
if (!p) return;
|
|
|
|
|
// setejecttext(drive, fn);
|
2016-09-22 21:22:56 +02:00
|
|
|
// pclog("Loading :%i %s %s\n", drive, fn,p);
|
2016-06-26 00:34:39 +02:00
|
|
|
f = fopen(fn, "rb");
|
|
|
|
|
if (!f) return;
|
|
|
|
|
fseek(f, -1, SEEK_END);
|
|
|
|
|
size = ftell(f) + 1;
|
|
|
|
|
fclose(f);
|
|
|
|
|
while (loaders[c].ext)
|
|
|
|
|
{
|
|
|
|
|
if (!strcasecmp(p, loaders[c].ext) && (size == loaders[c].size || loaders[c].size == -1))
|
|
|
|
|
{
|
2016-09-22 21:22:56 +02:00
|
|
|
// pclog("Loading as %s (UI write protected = %s)\n", p, ui_writeprot[drive] ? "yes" : "no");
|
2016-06-26 00:34:39 +02:00
|
|
|
driveloaders[drive] = c;
|
|
|
|
|
loaders[c].load(drive, fn);
|
|
|
|
|
drive_empty[drive] = 0;
|
|
|
|
|
strcpy(discfns[drive], fn);
|
2016-09-05 21:58:28 +02:00
|
|
|
fdd_set_head(drive ^ fdd_swap, 0);
|
2016-09-26 20:43:09 +02:00
|
|
|
fdd_forced_seek(drive ^ fdd_swap, 0);
|
2016-09-05 20:34:10 +02:00
|
|
|
disc_changed[drive] = 1;
|
2016-06-26 00:34:39 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
c++;
|
|
|
|
|
}
|
|
|
|
|
pclog("Couldn't load %s %s\n",fn,p);
|
|
|
|
|
drive_empty[drive] = 1;
|
2016-09-05 21:58:28 +02:00
|
|
|
fdd_set_head(drive ^ fdd_swap, 0);
|
2016-06-26 00:34:39 +02:00
|
|
|
discfns[drive][0] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void disc_close(int drive)
|
|
|
|
|
{
|
|
|
|
|
// pclog("disc_close %i\n", drive);
|
|
|
|
|
if (loaders[driveloaders[drive]].close) loaders[driveloaders[drive]].close(drive);
|
|
|
|
|
drive_empty[drive] = 1;
|
2016-09-05 21:58:28 +02:00
|
|
|
fdd_set_head(drive ^ fdd_swap, 0);
|
2016-06-26 00:34:39 +02:00
|
|
|
discfns[drive][0] = 0;
|
|
|
|
|
drives[drive].hole = NULL;
|
|
|
|
|
drives[drive].poll = NULL;
|
|
|
|
|
drives[drive].seek = NULL;
|
|
|
|
|
drives[drive].readsector = NULL;
|
|
|
|
|
drives[drive].writesector = NULL;
|
2016-10-05 05:37:07 +02:00
|
|
|
drives[drive].comparesector = NULL;
|
2016-06-26 00:34:39 +02:00
|
|
|
drives[drive].readaddress = NULL;
|
|
|
|
|
drives[drive].format = NULL;
|
2016-07-19 02:44:32 +02:00
|
|
|
drives[drive].byteperiod = NULL;
|
2016-06-26 00:34:39 +02:00
|
|
|
drives[drive].stop = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-31 22:49:56 +02:00
|
|
|
double disc_byteperiod(int drive)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
|
|
|
|
drive ^= fdd_swap;
|
|
|
|
|
|
|
|
|
|
if (drives[drive].byteperiod)
|
|
|
|
|
{
|
|
|
|
|
return drives[drive].byteperiod(drive);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2016-08-31 22:49:56 +02:00
|
|
|
return 32.0;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-02 22:39:07 +01:00
|
|
|
double disc_real_period(int drive)
|
2016-07-19 02:44:32 +02:00
|
|
|
{
|
2016-08-01 19:14:54 +02:00
|
|
|
double ddbp;
|
|
|
|
|
double dusec;
|
|
|
|
|
|
2016-11-02 22:39:07 +01:00
|
|
|
ddbp = disc_byteperiod(drive ^ fdd_swap);
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2016-08-01 19:14:54 +02:00
|
|
|
dusec = (double) TIMER_USEC;
|
2016-07-19 02:44:32 +02:00
|
|
|
|
|
|
|
|
return (ddbp * dusec);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2016-11-08 03:58:36 +01:00
|
|
|
void disc_poll(int drive, int head)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2016-11-08 03:58:36 +01:00
|
|
|
if ((drive > 1) || !motoron[drive])
|
2016-09-27 21:38:29 +02:00
|
|
|
{
|
2016-11-08 03:58:36 +01:00
|
|
|
disc_poll_time[drive][head] += (int) (32.0 * TIMER_USEC);
|
2016-09-27 21:38:29 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-08 03:58:36 +01:00
|
|
|
disc_poll_time[drive][head] += (int) disc_real_period(drive);
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2016-11-02 22:39:07 +01:00
|
|
|
if (drives[drive].poll)
|
2016-11-08 03:58:36 +01:00
|
|
|
drives[drive].poll(drive, head);
|
2016-06-26 00:34:39 +02:00
|
|
|
|
|
|
|
|
if (disc_notfound)
|
|
|
|
|
{
|
|
|
|
|
disc_notfound--;
|
|
|
|
|
if (!disc_notfound)
|
|
|
|
|
fdc_notfound();
|
|
|
|
|
}
|
2016-11-09 00:15:43 +01:00
|
|
|
|
|
|
|
|
/* If both heads are enabled and this is head 1, do not advance to avoid double advancing. */
|
|
|
|
|
if ((disc_poll_enable[drive][head] && disc_poll_enable[drive][head ^ 1]) && head)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (drives[drive].advance)
|
|
|
|
|
drives[drive].advance(drive);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2016-11-08 03:58:36 +01:00
|
|
|
void disc_poll_00()
|
|
|
|
|
{
|
|
|
|
|
disc_poll(0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void disc_poll_01()
|
|
|
|
|
{
|
|
|
|
|
disc_poll(0, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void disc_poll_10()
|
2016-11-02 22:39:07 +01:00
|
|
|
{
|
2016-11-08 03:58:36 +01:00
|
|
|
disc_poll(1, 0);
|
2016-11-02 22:39:07 +01:00
|
|
|
}
|
|
|
|
|
|
2016-11-08 03:58:36 +01:00
|
|
|
void disc_poll_11()
|
2016-11-02 22:39:07 +01:00
|
|
|
{
|
2016-11-08 03:58:36 +01:00
|
|
|
disc_poll(1, 1);
|
2016-11-02 22:39:07 +01:00
|
|
|
}
|
|
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
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*/
|
|
|
|
|
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;
|
|
|
|
|
case 3: /*Extended density*/
|
|
|
|
|
disc_period = 8;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-08 03:58:36 +01:00
|
|
|
/* void disc_head_unload_no_callback(int drive, int head)
|
|
|
|
|
{
|
|
|
|
|
disc_head_unload(drive, head);
|
|
|
|
|
head_callback[drive][head] = 0;
|
|
|
|
|
} */
|
|
|
|
|
|
|
|
|
|
void disc_head_load(int drive, int head)
|
|
|
|
|
{
|
|
|
|
|
drive ^= fdd_swap;
|
|
|
|
|
|
|
|
|
|
// pclog("Head load start (%i, %i) (%i)\n", drive, head, head_time[drive][head]);
|
|
|
|
|
|
|
|
|
|
if (head_time[drive][head])
|
|
|
|
|
{
|
|
|
|
|
if (!disc_poll_enable[drive][head])
|
|
|
|
|
{
|
|
|
|
|
/* If enabling, do nothing and let it enable. */
|
|
|
|
|
// pclog("Already enabling head (%i, %i)...\n", drive, head);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* If disabling, stop the timer so it stays enabled. */
|
|
|
|
|
// pclog("Currently disabling head (%i, %i)...\n", drive, head);
|
|
|
|
|
head_time[drive][head] = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (disc_poll_enable[drive][head])
|
|
|
|
|
{
|
|
|
|
|
/* If it's already enabled, do nothing. */
|
|
|
|
|
// pclog("Head (%i, %i) already enabled...\n", drive, head);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Enable or disable not in progress, start enabling. */
|
|
|
|
|
head_time[drive][head] = fdc_get_hlt();
|
|
|
|
|
|
|
|
|
|
// pclog("Head load finished (%i, %i) (%i)\n", drive, head, head_time[drive][head]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void disc_head_unload(int drive, int head)
|
|
|
|
|
{
|
|
|
|
|
drive ^= fdd_swap;
|
|
|
|
|
|
|
|
|
|
// pclog("Head unload start (%i, %i) (%i)\n", drive, head, head_time[drive][head]);
|
|
|
|
|
|
|
|
|
|
if (head_time[drive][head])
|
|
|
|
|
{
|
|
|
|
|
if (disc_poll_enable[drive][head])
|
|
|
|
|
{
|
|
|
|
|
/* If disabling, do nothing and let it disable. */
|
|
|
|
|
// pclog("Already disabling head (%i, %i)...\n", drive, head);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* If enabling, stop the timer so it stays disabled. */
|
|
|
|
|
// pclog("Currently enabling head (%i, %i)...\n", drive, head);
|
|
|
|
|
head_time[drive][head] = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!disc_poll_enable[drive][head])
|
|
|
|
|
{
|
|
|
|
|
/* If it's already disabled, do nothing. */
|
|
|
|
|
// pclog("Head (%i, %i) already disabled...\n", drive, head);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Enable or disable not in progress, start disabling. */
|
|
|
|
|
head_time[drive][head] = fdc_get_hut();
|
|
|
|
|
|
|
|
|
|
// pclog("Head unload finished (%i, %i) (%i)\n", drive, head, head_time[drive][head]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void disc_head_poll_common(int drive, int head)
|
|
|
|
|
{
|
|
|
|
|
disc_poll_enable[drive][head] ^= 1;
|
|
|
|
|
head_time[drive][head] = 0;
|
|
|
|
|
// pclog("Head (%i, %i) %s\n", drive, head, disc_poll_enable[drive][head] ? "enabled" : "disabled");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void disc_head_poll_00()
|
|
|
|
|
{
|
|
|
|
|
disc_head_poll_common(0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void disc_head_poll_01()
|
|
|
|
|
{
|
|
|
|
|
disc_head_poll_common(0, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void disc_head_poll_10()
|
|
|
|
|
{
|
|
|
|
|
disc_head_poll_common(1, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void disc_head_poll_11()
|
|
|
|
|
{
|
|
|
|
|
disc_head_poll_common(1, 1);
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-26 00:34:39 +02:00
|
|
|
void disc_reset()
|
|
|
|
|
{
|
|
|
|
|
curdrive = 0;
|
|
|
|
|
disc_period = 32;
|
2016-11-08 03:58:36 +01:00
|
|
|
|
|
|
|
|
timer_add(disc_poll_00, &(disc_poll_time[0][0]), &(disc_poll_enable[0][0]), NULL);
|
|
|
|
|
timer_add(disc_poll_01, &(disc_poll_time[0][1]), &(disc_poll_enable[0][1]), NULL);
|
|
|
|
|
timer_add(disc_poll_10, &(disc_poll_time[1][0]), &(disc_poll_enable[1][0]), NULL);
|
|
|
|
|
timer_add(disc_poll_11, &(disc_poll_time[1][1]), &(disc_poll_enable[1][1]), NULL);
|
|
|
|
|
|
|
|
|
|
timer_add(disc_head_poll_00, &(head_time[0][0]), &(head_time[0][0]), NULL);
|
|
|
|
|
timer_add(disc_head_poll_01, &(head_time[0][1]), &(head_time[0][1]), NULL);
|
|
|
|
|
timer_add(disc_head_poll_10, &(head_time[1][0]), &(head_time[1][0]), NULL);
|
|
|
|
|
timer_add(disc_head_poll_11, &(head_time[1][1]), &(head_time[1][1]), NULL);
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void disc_init()
|
|
|
|
|
{
|
|
|
|
|
// pclog("disc_init %p\n", drives);
|
|
|
|
|
drives[0].poll = drives[1].poll = 0;
|
|
|
|
|
drives[0].seek = drives[1].seek = 0;
|
|
|
|
|
drives[0].readsector = drives[1].readsector = 0;
|
|
|
|
|
disc_reset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
// ddnoise_seek(track - oldtrack[drive]);
|
|
|
|
|
// oldtrack[drive] = track;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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, sector_size);
|
|
|
|
|
else
|
|
|
|
|
disc_notfound = 1000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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, sector_size);
|
2016-10-05 05:37:07 +02:00
|
|
|
else
|
|
|
|
|
disc_notfound = 1000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void disc_comparesector(int drive, int sector, int track, int side, int density, int sector_size)
|
|
|
|
|
{
|
|
|
|
|
drive ^= fdd_swap;
|
|
|
|
|
|
|
|
|
|
if (drives[drive].comparesector)
|
|
|
|
|
drives[drive].comparesector(drive, sector, track, side, density, sector_size);
|
2016-06-26 00:34:39 +02:00
|
|
|
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, uint8_t fill)
|
|
|
|
|
{
|
|
|
|
|
drive ^= fdd_swap;
|
|
|
|
|
|
|
|
|
|
if (drives[drive].format)
|
|
|
|
|
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);
|
|
|
|
|
}
|