capsimg/CAPSImg/CapsAPI.cpp
2014-12-13 19:42:07 +01:00

611 lines
13 KiB
C++

#include "stdafx.h"
using namespace std;
int api_debug_request;
CDiskEncoding dskenc;
CDiskImageFactory imgfactory;
vector <PCDISKIMAGE> img;
// version info size
int sizeversioninfo[]= {
sizeof(CapsVersionInfo)
};
// track info size
int sizetrackinfo[]= {
sizeof(CapsTrackInfo),
sizeof(CapsTrackInfoT1),
sizeof(CapsTrackInfoT2),
};
// start caps image support
SDWORD __cdecl CAPSInit()
{
return imgeOk;
}
// stop caps image support
SDWORD __cdecl CAPSExit()
{
for (PCDISKIMAGE &actimg : img) {
delete actimg;
actimg = NULL;
}
return imgeOk;
}
// add image container
SDWORD __cdecl CAPSAddImage()
{
// use the base image type as a placeholder, returning errors for the functions
PCDISKIMAGE pi = new CDiskImage;
unsigned pos;
for (pos = 0; pos < img.size(); pos++) {
if (img[pos])
continue;
img[pos] = pi;
return pos;
}
img.push_back(pi);
return pos;
}
// delete image container
SDWORD __cdecl CAPSRemImage(SDWORD id)
{
if (id<0 || (unsigned)id>=img.size())
return -1;
delete img[id];
img[id]=NULL;
return id;
}
// lock image using file name
SDWORD __cdecl CAPSLockImage(SDWORD id, PCHAR name)
{
if (id<0 || (unsigned)id >= img.size() || !img[id])
return imgeOutOfRange;
CapsFile cf;
memset(&cf, 0, sizeof(CapsFile));
cf.name=name;
return CAPSLockImage(id, &cf);
}
// lock image using the specified memory buffer
SDWORD __cdecl CAPSLockImageMemory(SDWORD id, PUBYTE buffer, UDWORD length, UDWORD flag)
{
if (id<0 || (unsigned)id >= img.size() || !img[id])
return imgeOutOfRange;
CapsFile cf;
memset(&cf, 0, sizeof(CapsFile));
cf.memmap=buffer;
cf.size=length;
cf.flag|=CFF_MEMMAP;
if (flag & DI_LOCK_MEMREF)
cf.flag|=CFF_MEMREF;
return CAPSLockImage(id, &cf);
}
// lock image using the specified file - internal function
int CAPSLockImage(int id, PCAPSFILE pcf)
{
int res = imgeOk;
// get the possible image type used by the file
int type = imgfactory.GetImageType(pcf);
// check for file errors
switch (type) {
// problem with the file
case citError:
res = imgeOpen;
break;
// unknown file content
case citUnknown:
res = imgeType;
break;
}
// file type is known and supported
if (res == imgeOk) {
PCDISKIMAGE newimg = imgfactory.CreateImage(type);
if (newimg) {
// delete the existing image class regardless of type since it can no longer be used
CAPSRemImage(id);
// add the new image class
img[id] = newimg;
// try to lock the file; this can still give an error as the checks will be more thorough
res = img[id]->Lock(pcf);
} else
res = imgeGeneric;
}
return res;
}
// unlock image
SDWORD __cdecl CAPSUnlockImage(SDWORD id)
{
if (id<0 || (unsigned)id >= img.size() || !img[id])
return imgeOutOfRange;
int res=img[id]->Unlock();
return res;
}
// load and decode complete image
SDWORD __cdecl CAPSLoadImage(SDWORD id, UDWORD flag)
{
if (id<0 || (unsigned)id >= img.size() || !img[id])
return imgeOutOfRange;
int res=img[id]->LoadImage(flag);
return res;
}
// get image information
SDWORD __cdecl CAPSGetImageInfo(PCAPSIMAGEINFO pi, SDWORD id)
{
if (!pi)
return imgeGeneric;
memset(pi, 0, sizeof(CapsImageInfo));
if (id<0 || (unsigned)id >= img.size() || !img[id])
return imgeOutOfRange;
PDISKIMAGEINFO pd=img[id]->GetInfo();
if (!pd)
return imgeGeneric;
// convert image info
if (pd->civalid) {
// use image info if available
switch (pd->ci.type) {
case cpimtFDD:
pi->type = ciitFDD;
break;
default:
pi->type = ciitNA;
break;
}
pi->release = pd->ci.release;
pi->revision = pd->ci.revision;
pi->mincylinder = pd->ci.mincylinder;
pi->maxcylinder = pd->ci.maxcylinder;
pi->minhead = pd->ci.minhead;
pi->maxhead = pd->ci.maxhead;
CDiskImage::DecodeDateTime(&pi->crdt, &pd->ci.crdt);
for (int plt = 0; plt < CAPS_MAXPLATFORM; plt++)
pi->platform[plt] = pd->ci.platform[plt];
} else {
// image info not available
if (pd->dmpcount) {
// if there is at least one track dumped use dump information
pi->type = ciitFDD;
pi->release = 0;
pi->revision = 0;
pi->mincylinder = pd->umincylinder;
pi->maxcylinder = pd->umaxcylinder;
pi->minhead = pd->uminhead;
pi->maxhead = pd->umaxhead;
} else {
// invalid image type if not a dumped image and there is no information available
pi->type = ciitNA;
}
}
return imgeOk;
}
// load and decode track
SDWORD __cdecl CAPSLockTrack(PVOID ptrackinfo, SDWORD id, UDWORD cylinder, UDWORD head, UDWORD flag)
{
if (!ptrackinfo)
return imgeGeneric;
// structure revision is zero, unless newer one requested
unsigned rev=0;
if (flag & DI_LOCK_TYPE)
rev=*(PUDWORD)ptrackinfo;
// if unsupported type set the highest supported version
if (rev > 2) {
*(PUDWORD)ptrackinfo=2;
return imgeUnsupportedType;
}
// check id
if (id < 0 || (unsigned)id >= img.size() || !img[id]) {
// clear structure
memset(ptrackinfo, 0, sizetrackinfo[rev]);
return imgeOutOfRange;
}
// set weak bit generator
if (flag & DI_LOCK_SETWSEED) {
PDISKTRACKINFO pt=img[id]->GetTrack(cylinder, head);
if (pt) {
switch (rev) {
case 2:
pt->wseed=((PCAPSTRACKINFOT2)ptrackinfo)->wseed;
break;
}
}
}
// clear structure
memset(ptrackinfo, 0, sizetrackinfo[rev]);
// lock track
PDISKTRACKINFO pt=img[id]->LockTrack(cylinder, head, flag);
if (!pt) {
PDISKIMAGEINFO pd=img[id]->GetInfo();
return pd ? pd->error : imgeGeneric;
}
// track type conversion
UDWORD ttype;
switch (pt->ci.dentype) {
case cpdenNA:
ttype=ctitNA;
break;
case cpdenNoise:
ttype=ctitNoise;
break;
case cpdenAuto:
ttype=ctitAuto;
break;
default:
ttype=ctitVar;
break;
}
// signal track update
if (pt->fdpsize)
ttype|=CTIT_FLAG_FLAKEY;
// track type is variable density for raw dumps
if (pt->rawdump)
ttype = ctitVar;
// if multiple revolutions used by a raw dump signal track update
if (pt->rawupdate)
ttype |= CTIT_FLAG_FLAKEY;
// get the correct structure
switch (rev) {
case 0:
CAPSLockTrackT0((PCAPSTRACKINFO)ptrackinfo, pt, ttype, flag);
break;
case 1:
CAPSLockTrackT1((PCAPSTRACKINFOT1)ptrackinfo, pt, ttype, flag);
break;
case 2:
CAPSLockTrackT2((PCAPSTRACKINFOT2)ptrackinfo, pt, ttype, flag);
break;
}
return imgeOk;
}
// get track info type 0
void CAPSLockTrackT0(PCAPSTRACKINFO pi, PDISKTRACKINFO pt, UDWORD ttype, UDWORD flag)
{
pi->type=ttype;
pi->cylinder=pt->cylinder;
pi->head=pt->head;
pi->sectorcnt=pt->sectorcnt;
pi->sectorsize=0;
pi->trackcnt=pt->trackcnt;
pi->trackbuf=pt->trackbuf;
pi->tracklen=(flag & DI_LOCK_TRKBIT) ? pt->trackbc : pt->tracklen;
pi->timelen=pt->timecnt;
pi->timebuf=pt->timebuf;
for (int trk=0; trk < pt->trackcnt; trk++) {
pi->trackdata[trk]=pt->trackdata[trk];
pi->tracksize[trk]=pt->tracksize[trk];
}
}
// get track info type 1
void CAPSLockTrackT1(PCAPSTRACKINFOT1 pi, PDISKTRACKINFO pt, UDWORD ttype, UDWORD flag)
{
pi->type=ttype;
pi->cylinder=pt->cylinder;
pi->head=pt->head;
pi->sectorcnt=pt->sectorcnt;
pi->sectorsize=0;
pi->trackbuf=pt->trackbuf;
pi->tracklen=(flag & DI_LOCK_TRKBIT) ? pt->trackbc : pt->tracklen;
pi->timelen=pt->timecnt;
pi->timebuf=pt->timebuf;
pi->overlap=pt->overlap;
}
// get track info type 1
void CAPSLockTrackT2(PCAPSTRACKINFOT2 pi, PDISKTRACKINFO pt, UDWORD ttype, UDWORD flag)
{
pi->type=ttype;
pi->cylinder=pt->cylinder;
pi->head=pt->head;
pi->sectorcnt=pt->sectorcnt;
pi->sectorsize=0;
pi->trackbuf=pt->trackbuf;
pi->tracklen=(flag & DI_LOCK_TRKBIT) ? pt->trackbc : pt->tracklen;
pi->timelen=pt->timecnt;
pi->timebuf=pt->timebuf;
pi->overlap=pt->overlap;
pi->startbit=pt->startbit;
pi->wseed=pt->wseed;
pi->weakcnt=pt->fdpsize;
}
// remove track from cache
SDWORD __cdecl CAPSUnlockTrack(SDWORD id, UDWORD cylinder, UDWORD head)
{
if (id<0 || (unsigned)id >= img.size() || !img[id])
return imgeOutOfRange;
PDISKTRACKINFO pt=img[id]->UnlockTrack(cylinder, head);
return pt ? imgeOk : imgeOutOfRange;
}
// remove all tracks from cache
SDWORD __cdecl CAPSUnlockAllTracks(SDWORD id)
{
if (id<0 || (unsigned)id >= img.size() || !img[id])
return imgeOutOfRange;
img[id]->UnlockTrack();
return imgeOk;
}
// get platform name
PCHAR __cdecl CAPSGetPlatformName(UDWORD pid)
{
return (PCHAR)CDiskImage::GetPlatformName(pid);
}
// get library version
SDWORD __cdecl CAPSGetVersionInfo(PVOID pversioninfo, UDWORD flag)
{
if (!pversioninfo)
return imgeGeneric;
// structure revision is zero, unless newer one requested
unsigned rev=0;
if (flag & DI_LOCK_TYPE)
rev=*(PUDWORD)pversioninfo;
// if unsupported type set the highest supported version
if (rev > 0) {
*(PUDWORD)pversioninfo=0;
return imgeUnsupportedType;
}
// clear structure
memset(pversioninfo, 0, sizeversioninfo[rev]);
// get the correct structure
switch (rev) {
case 0:
CAPSGetVersionInfoT0((PCAPSVERSIONINFO)pversioninfo);
break;
}
return imgeOk;
}
// get library version type 0
void CAPSGetVersionInfoT0(PCAPSVERSIONINFO pi)
{
pi->release=CAPS_LIB_RELEASE;
pi->revision=CAPS_LIB_REVISION;
pi->flag=DI_LOCK_INDEX|
DI_LOCK_ALIGN |
DI_LOCK_DENVAR |
DI_LOCK_DENAUTO |
DI_LOCK_DENNOISE |
DI_LOCK_NOISE |
DI_LOCK_NOISEREV |
DI_LOCK_MEMREF |
DI_LOCK_UPDATEFD |
DI_LOCK_TYPE |
DI_LOCK_DENALT |
DI_LOCK_OVLBIT |
DI_LOCK_TRKBIT |
DI_LOCK_NOUPDATE |
DI_LOCK_SETWSEED;
}
// get various information after decoding
SDWORD __cdecl CAPSGetInfo(PVOID pinfo, SDWORD id, UDWORD cylinder, UDWORD head, UDWORD inftype, UDWORD infid)
{
if (!pinfo)
return imgeGeneric;
if (id<0 || (unsigned)id >= img.size() || !img[id])
return imgeOutOfRange;
PDISKIMAGEINFO pd = img[id]->GetInfo();
PDISKTRACKINFO pt = img[id]->GetTrack(cylinder, head);
int res=imgeUnsupportedType;
switch (inftype) {
case cgiitSector:
res=CAPSGetSectorInfo((PCAPSSECTORINFO)pinfo, pd, pt, infid);
break;
case cgiitWeak:
res=CAPSGetWeakInfo((PCAPSDATAINFO)pinfo, pd, pt, infid);
break;
case cgiitRevolution:
res = CAPSGetRevolutionInfo((PCAPSREVOLUTIONINFO)pinfo, pd, pt, infid);
break;
}
return res;
}
// get sector information
int CAPSGetSectorInfo(PCAPSSECTORINFO pi, PDISKIMAGEINFO pd, PDISKTRACKINFO pt, UDWORD infid)
{
memset(pi, 0, sizeof(CapsSectorInfo));
if (!pt)
return imgeOutOfRange;
if (pt->sipsize <= 0 || !pt->sip)
return imgeOutOfRange;
if (infid >= (unsigned)pt->sipsize)
return imgeOutOfRange;
PDISKSECTORINFO si=pt->sip+infid;
pi->descdatasize=si->descdatasize;
pi->descgapsize=si->descgapsize;
pi->datasize=si->datasize;
pi->gapsize=si->gapsize;
pi->datastart=si->datastart;
pi->gapstart=si->gapstart;
pi->gapsizews0=si->gapsizews0;
pi->gapsizews1=si->gapsizews1;
pi->gapws0mode=si->gapws0mode;
pi->gapws1mode=si->gapws1mode;
pi->celltype=si->celltype;
pi->enctype=si->enctype;
return imgeOk;
}
// get weak data information
int CAPSGetWeakInfo(PCAPSDATAINFO pi, PDISKIMAGEINFO pd, PDISKTRACKINFO pt, UDWORD infid)
{
memset(pi, 0, sizeof(CapsDataInfo));
if (!pt)
return imgeOutOfRange;
if (pt->fdpsize <= 0 || !pt->fdp)
return imgeOutOfRange;
if (infid >= (unsigned)pt->fdpsize)
return imgeOutOfRange;
PDISKDATAMARK dm=pt->fdp+infid;
pi->type=cditWeak;
pi->start=dm->position;
pi->size=dm->size;
return imgeOk;
}
// get revolution information
int CAPSGetRevolutionInfo(PCAPSREVOLUTIONINFO pi, PDISKIMAGEINFO pd, PDISKTRACKINFO pt, UDWORD infid)
{
memset(pi, 0, sizeof(CapsRevolutionInfo));
// set image data if image is valid
if (pd) {
// next, last and real revolution used by lock track
pi->next = pd->nextrev;
pi->last = pd->lastrev;
pi->real = pd->realrev;
}
// set track data if track is valid
if (pt) {
// use the revolutions sampled for raw dumps, -1 (unlimited/randomized) otherwise
pi->max = (pt->rawdump) ? pt->rawtrackcnt : -1;
}
return imgeOk;
}
// set the next revolution to be used by track lock
SDWORD __cdecl CAPSSetRevolution(SDWORD id, UDWORD value)
{
if (id<0 || (unsigned)id >= img.size() || !img[id])
return imgeOutOfRange;
PDISKIMAGEINFO pd = img[id]->GetInfo();
if (!pd)
return imgeGeneric;
// set revolution
pd->nextrev = value;
return imgeOk;
}
// get image type using file name
SDWORD __cdecl CAPSGetImageType(PCHAR name)
{
CapsFile cf;
memset(&cf, 0, sizeof(CapsFile));
cf.name = name;
// get the possible image type used by the file
return imgfactory.GetImageType(&cf);
}
// get image type using the specified memory buffer
SDWORD __cdecl CAPSGetImageTypeMemory(PUBYTE buffer, UDWORD length)
{
CapsFile cf;
memset(&cf, 0, sizeof(CapsFile));
cf.memmap = buffer;
cf.size = length;
cf.flag |= CFF_MEMMAP | CFF_MEMREF;
// get the possible image type used by the file
return imgfactory.GetImageType(&cf);
}
// return the state of host debug request coming from the library and reset the state
SDWORD __cdecl CAPSGetDebugRequest()
{
SDWORD res = api_debug_request;
api_debug_request = 0;
return res;
}