mirror of https://github.com/wwarthen/RomWBW.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
3.6 KiB
135 lines
3.6 KiB
/* #includes */ /*{{{C}}}*//*{{{*/
|
|
#include "config.h"
|
|
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "device.h"
|
|
|
|
#ifdef USE_DMALLOC
|
|
#include <dmalloc.h>
|
|
#endif
|
|
/*}}}*/
|
|
|
|
static const char *lookupFormat(DSK_GEOMETRY *geom, const char *name)
|
|
{
|
|
dsk_format_t fmt = FMT_180K;
|
|
const char *fname;
|
|
|
|
while (dg_stdformat(NULL, fmt, &fname, NULL) == DSK_ERR_OK)
|
|
{
|
|
if (!strcmp(name, fname))
|
|
{
|
|
dg_stdformat(geom, fmt, &fname, NULL);
|
|
return NULL;
|
|
}
|
|
++fmt;
|
|
}
|
|
return "Unrecognised LibDsk geometry specification";
|
|
}
|
|
|
|
/* Device_open -- Open an image file */ /*{{{*/
|
|
const char *Device_open(struct Device *this, const char *filename, int mode, const char *deviceOpts)
|
|
{
|
|
char *format;
|
|
char driverName[80];
|
|
const char *boo;
|
|
dsk_err_t e;
|
|
|
|
/* Assume driver name & format name both fit in 80 characters, rather than
|
|
* malloccing the exact size */
|
|
if (deviceOpts == NULL)
|
|
{
|
|
e = dsk_open(&this->dev, filename, NULL, NULL);
|
|
format = NULL;
|
|
}
|
|
else
|
|
{
|
|
strncpy(driverName, deviceOpts, 79);
|
|
driverName[79] = 0;
|
|
format = strchr(driverName, ',');
|
|
if (format)
|
|
{
|
|
*format = 0;
|
|
++format;
|
|
}
|
|
e = dsk_open(&this->dev, filename, driverName, NULL);
|
|
}
|
|
this->opened = 0;
|
|
if (e) return dsk_strerror(e);
|
|
this->opened = 1;
|
|
if (format)
|
|
{
|
|
boo = lookupFormat(&this->geom, format);
|
|
if (boo) return boo;
|
|
}
|
|
else
|
|
{
|
|
dsk_getgeom(this->dev, &this->geom);
|
|
}
|
|
return NULL;
|
|
}
|
|
/*}}}*/
|
|
/* Device_setGeometry -- Set disk geometry */ /*{{{*/
|
|
const char *Device_setGeometry(struct Device *this, int secLength, int sectrk, int tracks, off_t offset, const char *libdskGeometry)
|
|
{
|
|
char *boo;
|
|
|
|
this->secLength=secLength;
|
|
this->sectrk=sectrk;
|
|
this->tracks=tracks;
|
|
/* Must be an even multiple of sector size */
|
|
assert(offset%secLength==0);
|
|
this->offset=offset;
|
|
/* If a geometry is named in diskdefs, use it */
|
|
if (libdskGeometry && libdskGeometry[0])
|
|
{
|
|
return lookupFormat(&this->geom, libdskGeometry);
|
|
}
|
|
|
|
this->geom.dg_secsize = secLength;
|
|
this->geom.dg_sectors = sectrk;
|
|
/* Did the autoprobe guess right about the number of sectors & cylinders? */
|
|
if (this->geom.dg_cylinders * this->geom.dg_heads == tracks) return NULL;
|
|
/* Otherwise we guess: <= 43 tracks: single-sided. Else double. This
|
|
* fails for 80-track single-sided if there are any such beasts */
|
|
if (tracks <= 43)
|
|
{
|
|
this->geom.dg_cylinders = tracks;
|
|
this->geom.dg_heads = 1;
|
|
}
|
|
else
|
|
{
|
|
this->geom.dg_cylinders = tracks/2;
|
|
this->geom.dg_heads = 2;
|
|
}
|
|
return NULL;
|
|
}
|
|
/*}}}*/
|
|
/* Device_close -- Close an image file */ /*{{{*/
|
|
const char *Device_close(struct Device *this)
|
|
{
|
|
dsk_err_t e;
|
|
this->opened=0;
|
|
e = dsk_close(&this->dev);
|
|
return (e?dsk_strerror(e):(const char*)0);
|
|
}
|
|
/*}}}*/
|
|
/* Device_readSector -- read a physical sector */ /*{{{*/
|
|
const char *Device_readSector(const struct Device *this, int track, int sector, char *buf)
|
|
{
|
|
dsk_err_t e;
|
|
e = dsk_lread(this->dev, &this->geom, buf, (track * this->sectrk) + sector + this->offset/this->secLength);
|
|
return (e?dsk_strerror(e):(const char*)0);
|
|
}
|
|
/*}}}*/
|
|
/* Device_writeSector -- write physical sector */ /*{{{*/
|
|
const char *Device_writeSector(const struct Device *this, int track, int sector, const char *buf)
|
|
{
|
|
dsk_err_t e;
|
|
e = dsk_lwrite(this->dev, &this->geom, buf, (track * this->sectrk) + sector + this->offset/this->secLength);
|
|
return (e?dsk_strerror(e):(const char*)0);
|
|
}
|
|
/*}}}*/
|
|
|