mirror of
https://github.com/AppleWin/AppleWin.git
synced 2026-04-20 00:17:16 +00:00
Supports: - all "woz test images" v1.3 (WOZ1, WOZ2) are working, except 3.5" - additionally: Frogger (spiradisc), Choplifter (not Enhanced //e!), Lode Runner, Marble Madness, Skyfox. - woz images can be .gz or .zip compressed (ie. same as other supported images) - save-state Limitations: - read-only, so WOZ images are forced to be write-protected . as a result, games that need r/w images won't work (Stickybear Town Builder, Wizardry) - 5.25" only (not 3.5")
This commit is contained in:
+301
-79
@@ -70,8 +70,8 @@ LPBYTE CImageBase::ms_pWorkBuffer = NULL;
|
||||
|
||||
bool CImageBase::ReadTrack(ImageInfo* pImageInfo, const int nTrack, LPBYTE pTrackBuffer, const UINT uTrackSize)
|
||||
{
|
||||
const long Offset = pImageInfo->uOffset + nTrack * uTrackSize;
|
||||
memcpy(pTrackBuffer, &pImageInfo->pImageBuffer[Offset], uTrackSize);
|
||||
const long offset = pImageInfo->uOffset + nTrack * uTrackSize;
|
||||
memcpy(pTrackBuffer, &pImageInfo->pImageBuffer[offset], uTrackSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -630,18 +630,20 @@ public:
|
||||
return ePossibleMatch;
|
||||
}
|
||||
|
||||
virtual void Read(ImageInfo* pImageInfo, int nTrack, int nQuarterTrack, LPBYTE pTrackImageBuffer, int* pNibbles, bool enhanceDisk)
|
||||
virtual void Read(ImageInfo* pImageInfo, const float phase, LPBYTE pTrackImageBuffer, int* pNibbles, UINT* pBitCount, bool enhanceDisk)
|
||||
{
|
||||
ReadTrack(pImageInfo, nTrack, ms_pWorkBuffer, TRACK_DENIBBLIZED_SIZE);
|
||||
*pNibbles = NibblizeTrack(pTrackImageBuffer, eDOSOrder, nTrack);
|
||||
const UINT track = PhaseToTrack(phase);
|
||||
ReadTrack(pImageInfo, track, ms_pWorkBuffer, TRACK_DENIBBLIZED_SIZE);
|
||||
*pNibbles = NibblizeTrack(pTrackImageBuffer, eDOSOrder, track);
|
||||
if (!enhanceDisk)
|
||||
SkewTrack(nTrack, *pNibbles, pTrackImageBuffer);
|
||||
SkewTrack(track, *pNibbles, pTrackImageBuffer);
|
||||
}
|
||||
|
||||
virtual void Write(ImageInfo* pImageInfo, int nTrack, int nQuarterTrack, LPBYTE pTrackImage, int nNibbles)
|
||||
virtual void Write(ImageInfo* pImageInfo, const float phase, LPBYTE pTrackImageBuffer, int nNibbles)
|
||||
{
|
||||
DenibblizeTrack(pTrackImage, eDOSOrder, nNibbles);
|
||||
WriteTrack(pImageInfo, nTrack, ms_pWorkBuffer, TRACK_DENIBBLIZED_SIZE);
|
||||
const UINT track = PhaseToTrack(phase);
|
||||
DenibblizeTrack(pTrackImageBuffer, eDOSOrder, nNibbles);
|
||||
WriteTrack(pImageInfo, track, ms_pWorkBuffer, TRACK_DENIBBLIZED_SIZE);
|
||||
}
|
||||
|
||||
virtual bool AllowCreate(void) { return true; }
|
||||
@@ -696,23 +698,25 @@ public:
|
||||
return ePossibleMatch;
|
||||
}
|
||||
|
||||
virtual void Read(ImageInfo* pImageInfo, int nTrack, int nQuarterTrack, LPBYTE pTrackImageBuffer, int* pNibbles, bool enhanceDisk)
|
||||
virtual void Read(ImageInfo* pImageInfo, const float phase, LPBYTE pTrackImageBuffer, int* pNibbles, UINT* pBitCount, bool enhanceDisk)
|
||||
{
|
||||
ReadTrack(pImageInfo, nTrack, ms_pWorkBuffer, TRACK_DENIBBLIZED_SIZE);
|
||||
*pNibbles = NibblizeTrack(pTrackImageBuffer, eProDOSOrder, nTrack);
|
||||
const UINT track = PhaseToTrack(phase);
|
||||
ReadTrack(pImageInfo, track, ms_pWorkBuffer, TRACK_DENIBBLIZED_SIZE);
|
||||
*pNibbles = NibblizeTrack(pTrackImageBuffer, eProDOSOrder, track);
|
||||
if (!enhanceDisk)
|
||||
SkewTrack(nTrack, *pNibbles, pTrackImageBuffer);
|
||||
SkewTrack(track, *pNibbles, pTrackImageBuffer);
|
||||
}
|
||||
|
||||
virtual void Write(ImageInfo* pImageInfo, int nTrack, int nQuarterTrack, LPBYTE pTrackImage, int nNibbles)
|
||||
virtual void Write(ImageInfo* pImageInfo, const float phase, LPBYTE pTrackImageBuffer, int nNibbles)
|
||||
{
|
||||
DenibblizeTrack(pTrackImage, eProDOSOrder, nNibbles);
|
||||
WriteTrack(pImageInfo, nTrack, ms_pWorkBuffer, TRACK_DENIBBLIZED_SIZE);
|
||||
const UINT track = PhaseToTrack(phase);
|
||||
DenibblizeTrack(pTrackImageBuffer, eProDOSOrder, nNibbles);
|
||||
WriteTrack(pImageInfo, track, ms_pWorkBuffer, TRACK_DENIBBLIZED_SIZE);
|
||||
}
|
||||
|
||||
virtual eImageType GetType(void) { return eImagePO; }
|
||||
virtual const char* GetCreateExtensions(void) { return ".po"; }
|
||||
virtual const char* GetRejectExtensions(void) { return ".do;.iie;.nib;.prg"; }
|
||||
virtual const char* GetRejectExtensions(void) { return ".do;.iie;.nib;.prg;.woz"; }
|
||||
};
|
||||
|
||||
//-------------------------------------
|
||||
@@ -724,7 +728,7 @@ public:
|
||||
CNib1Image(void) {}
|
||||
virtual ~CNib1Image(void) {}
|
||||
|
||||
static const UINT NIB1_TRACK_SIZE = NIBBLES_PER_TRACK;
|
||||
static const UINT NIB1_TRACK_SIZE = NIBBLES_PER_TRACK_NIB;
|
||||
|
||||
virtual eDetectResult Detect(const LPBYTE pImage, const DWORD dwImageSize, const TCHAR* pszExt)
|
||||
{
|
||||
@@ -735,16 +739,18 @@ public:
|
||||
return eMatch;
|
||||
}
|
||||
|
||||
virtual void Read(ImageInfo* pImageInfo, int nTrack, int nQuarterTrack, LPBYTE pTrackImageBuffer, int* pNibbles, bool enhanceDisk)
|
||||
virtual void Read(ImageInfo* pImageInfo, const float phase, LPBYTE pTrackImageBuffer, int* pNibbles, UINT* pBitCount, bool enhanceDisk)
|
||||
{
|
||||
ReadTrack(pImageInfo, nTrack, pTrackImageBuffer, NIB1_TRACK_SIZE);
|
||||
const UINT track = PhaseToTrack(phase);
|
||||
ReadTrack(pImageInfo, track, pTrackImageBuffer, NIB1_TRACK_SIZE);
|
||||
*pNibbles = NIB1_TRACK_SIZE;
|
||||
}
|
||||
|
||||
virtual void Write(ImageInfo* pImageInfo, int nTrack, int nQuarterTrack, LPBYTE pTrackImage, int nNibbles)
|
||||
virtual void Write(ImageInfo* pImageInfo, const float phase, LPBYTE pTrackImageBuffer, int nNibbles)
|
||||
{
|
||||
_ASSERT(nNibbles == NIB1_TRACK_SIZE); // Must be true - as nNibbles gets init'd by ImageReadTrace()
|
||||
WriteTrack(pImageInfo, nTrack, pTrackImage, nNibbles);
|
||||
const UINT track = PhaseToTrack(phase);
|
||||
WriteTrack(pImageInfo, track, pTrackImageBuffer, nNibbles);
|
||||
}
|
||||
|
||||
virtual bool AllowCreate(void) { return true; }
|
||||
@@ -752,7 +758,7 @@ public:
|
||||
|
||||
virtual eImageType GetType(void) { return eImageNIB1; }
|
||||
virtual const char* GetCreateExtensions(void) { return ".nib"; }
|
||||
virtual const char* GetRejectExtensions(void) { return ".do;.iie;.po;.prg"; }
|
||||
virtual const char* GetRejectExtensions(void) { return ".do;.iie;.po;.prg;.woz"; }
|
||||
};
|
||||
|
||||
//-------------------------------------
|
||||
@@ -775,21 +781,23 @@ public:
|
||||
return eMatch;
|
||||
}
|
||||
|
||||
virtual void Read(ImageInfo* pImageInfo, int nTrack, int nQuarterTrack, LPBYTE pTrackImageBuffer, int* pNibbles, bool enhanceDisk)
|
||||
virtual void Read(ImageInfo* pImageInfo, const float phase, LPBYTE pTrackImageBuffer, int* pNibbles, UINT* pBitCount, bool enhanceDisk)
|
||||
{
|
||||
ReadTrack(pImageInfo, nTrack, pTrackImageBuffer, NIB2_TRACK_SIZE);
|
||||
const UINT track = PhaseToTrack(phase);
|
||||
ReadTrack(pImageInfo, track, pTrackImageBuffer, NIB2_TRACK_SIZE);
|
||||
*pNibbles = NIB2_TRACK_SIZE;
|
||||
}
|
||||
|
||||
virtual void Write(ImageInfo* pImageInfo, int nTrack, int nQuarterTrack, LPBYTE pTrackImage, int nNibbles)
|
||||
virtual void Write(ImageInfo* pImageInfo, const float phase, LPBYTE pTrackImageBuffer, int nNibbles)
|
||||
{
|
||||
_ASSERT(nNibbles == NIB2_TRACK_SIZE); // Must be true - as nNibbles gets init'd by ImageReadTrace()
|
||||
WriteTrack(pImageInfo, nTrack, pTrackImage, nNibbles);
|
||||
const UINT track = PhaseToTrack(phase);
|
||||
WriteTrack(pImageInfo, track, pTrackImageBuffer, nNibbles);
|
||||
}
|
||||
|
||||
virtual eImageType GetType(void) { return eImageNIB2; }
|
||||
virtual const char* GetCreateExtensions(void) { return ".nb2"; }
|
||||
virtual const char* GetRejectExtensions(void) { return ".do;.iie;.po;.prg;.2mg;.2img"; }
|
||||
virtual const char* GetRejectExtensions(void) { return ".do;.iie;.po;.prg;.woz;.2mg;.2img"; }
|
||||
};
|
||||
|
||||
//-------------------------------------
|
||||
@@ -851,8 +859,10 @@ public:
|
||||
return eMatch;
|
||||
}
|
||||
|
||||
virtual void Read(ImageInfo* pImageInfo, int nTrack, int nQuarterTrack, LPBYTE pTrackImageBuffer, int* pNibbles, bool enhanceDisk)
|
||||
virtual void Read(ImageInfo* pImageInfo, const float phase, LPBYTE pTrackImageBuffer, int* pNibbles, UINT* pBitCount, bool enhanceDisk)
|
||||
{
|
||||
UINT track = PhaseToTrack(phase);
|
||||
|
||||
// IF WE HAVEN'T ALREADY DONE SO, READ THE IMAGE FILE HEADER
|
||||
if (!m_pHeader)
|
||||
{
|
||||
@@ -872,19 +882,19 @@ public:
|
||||
if (*(m_pHeader+13) <= 2)
|
||||
{
|
||||
ConvertSectorOrder(m_pHeader+14);
|
||||
SetFilePointer(pImageInfo->hFile, nTrack*TRACK_DENIBBLIZED_SIZE+30, NULL, FILE_BEGIN);
|
||||
SetFilePointer(pImageInfo->hFile, track*TRACK_DENIBBLIZED_SIZE+30, NULL, FILE_BEGIN);
|
||||
ZeroMemory(ms_pWorkBuffer, TRACK_DENIBBLIZED_SIZE);
|
||||
DWORD bytesread;
|
||||
ReadFile(pImageInfo->hFile, ms_pWorkBuffer, TRACK_DENIBBLIZED_SIZE, &bytesread, NULL);
|
||||
*pNibbles = NibblizeTrack(pTrackImageBuffer, eSIMSYSTEMOrder, nTrack);
|
||||
*pNibbles = NibblizeTrack(pTrackImageBuffer, eSIMSYSTEMOrder, track);
|
||||
}
|
||||
// OTHERWISE, IF THIS IMAGE CONTAINS NIBBLE INFORMATION, READ IT DIRECTLY INTO THE TRACK BUFFER
|
||||
else
|
||||
{
|
||||
*pNibbles = *(LPWORD)(m_pHeader+nTrack*2+14);
|
||||
*pNibbles = *(LPWORD)(m_pHeader+track*2+14);
|
||||
LONG Offset = 88;
|
||||
while (nTrack--)
|
||||
Offset += *(LPWORD)(m_pHeader+nTrack*2+14);
|
||||
while (track--)
|
||||
Offset += *(LPWORD)(m_pHeader+track*2+14);
|
||||
SetFilePointer(pImageInfo->hFile, Offset, NULL,FILE_BEGIN);
|
||||
ZeroMemory(pTrackImageBuffer, *pNibbles);
|
||||
DWORD dwBytesRead;
|
||||
@@ -892,14 +902,14 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Write(ImageInfo* pImageInfo, int nTrack, int nQuarterTrack, LPBYTE pTrackImage, int nNibbles)
|
||||
virtual void Write(ImageInfo* pImageInfo, const float phase, LPBYTE pTrackImageBuffer, int nNibbles)
|
||||
{
|
||||
// note: unimplemented
|
||||
}
|
||||
|
||||
virtual eImageType GetType(void) { return eImageIIE; }
|
||||
virtual const char* GetCreateExtensions(void) { return ".iie"; }
|
||||
virtual const char* GetRejectExtensions(void) { return ".do.;.nib;.po;.prg;.2mg;.2img"; }
|
||||
virtual const char* GetRejectExtensions(void) { return ".do.;.nib;.po;.prg;.woz;.2mg;.2img"; }
|
||||
|
||||
private:
|
||||
void ConvertSectorOrder(LPBYTE sourceorder)
|
||||
@@ -973,7 +983,7 @@ public:
|
||||
|
||||
virtual eImageType GetType(void) { return eImageAPL; }
|
||||
virtual const char* GetCreateExtensions(void) { return ".apl"; }
|
||||
virtual const char* GetRejectExtensions(void) { return ".do;.dsk;.iie;.nib;.po;.2mg;.2img"; }
|
||||
virtual const char* GetRejectExtensions(void) { return ".do;.dsk;.iie;.nib;.po;.woz;.2mg;.2img"; }
|
||||
};
|
||||
|
||||
//-------------------------------------
|
||||
@@ -1024,7 +1034,154 @@ public:
|
||||
|
||||
virtual eImageType GetType(void) { return eImagePRG; }
|
||||
virtual const char* GetCreateExtensions(void) { return ".prg"; }
|
||||
virtual const char* GetRejectExtensions(void) { return ".do;.dsk;.iie;.nib;.po;.2mg;.2img"; }
|
||||
virtual const char* GetRejectExtensions(void) { return ".do;.dsk;.iie;.nib;.po;.woz;.2mg;.2img"; }
|
||||
};
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
class CWOZEmptyTrack
|
||||
{
|
||||
public:
|
||||
CWOZEmptyTrack(void)
|
||||
{
|
||||
m_pWOZEmptyTrack = new BYTE[CWOZHelper::EMPTY_TRACK_SIZE];
|
||||
|
||||
srand(1); // Use a fixed seed for determinism
|
||||
for (UINT i = 0; i < CWOZHelper::EMPTY_TRACK_SIZE; i++)
|
||||
{
|
||||
BYTE n = 0;
|
||||
for (UINT j = 0; j < 8; j++)
|
||||
{
|
||||
if (rand() < ((RAND_MAX * 3) / 10)) // ~30% of buffer are 1 bits
|
||||
n |= 1 << j;
|
||||
}
|
||||
m_pWOZEmptyTrack[i] = n;
|
||||
}
|
||||
}
|
||||
virtual ~CWOZEmptyTrack(void) { delete m_pWOZEmptyTrack; }
|
||||
|
||||
void ReadEmptyTrack(LPBYTE pTrackImageBuffer, int* pNibbles, UINT* pBitCount)
|
||||
{
|
||||
memcpy(pTrackImageBuffer, m_pWOZEmptyTrack, CWOZHelper::EMPTY_TRACK_SIZE);
|
||||
*pNibbles = CWOZHelper::EMPTY_TRACK_SIZE;
|
||||
*pBitCount = CWOZHelper::EMPTY_TRACK_SIZE * 8;
|
||||
return;
|
||||
}
|
||||
|
||||
private:
|
||||
BYTE* m_pWOZEmptyTrack;
|
||||
};
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
class CWOZ1Image : public CImageBase, private CWOZEmptyTrack
|
||||
{
|
||||
public:
|
||||
CWOZ1Image(void) {}
|
||||
virtual ~CWOZ1Image(void) {}
|
||||
|
||||
virtual eDetectResult Detect(const LPBYTE pImage, const DWORD dwImageSize, const TCHAR* pszExt)
|
||||
{
|
||||
CWOZHelper::WOZHeader* pWozHdr = (CWOZHelper::WOZHeader*) pImage;
|
||||
|
||||
if (pWozHdr->id1 != CWOZHelper::ID1_WOZ1 || pWozHdr->id2 != CWOZHelper::ID2)
|
||||
return eMismatch;
|
||||
|
||||
if (pWozHdr->crc32)
|
||||
{
|
||||
// TODO: check crc
|
||||
}
|
||||
|
||||
m_uNumTracksInImage = CWOZHelper::MAX_TRACKS_5_25;
|
||||
return eMatch;
|
||||
}
|
||||
|
||||
virtual void Read(ImageInfo* pImageInfo, const float phase, LPBYTE pTrackImageBuffer, int* pNibbles, UINT* pBitCount, bool enhanceDisk)
|
||||
{
|
||||
BYTE*& pTrackMap = pImageInfo->pTrackMap;
|
||||
|
||||
const int trackFromTMAP = pTrackMap[(UINT)(phase * 2)];
|
||||
if (trackFromTMAP == 0xFF)
|
||||
return ReadEmptyTrack(pTrackImageBuffer, pNibbles, pBitCount);
|
||||
|
||||
ReadTrack(pImageInfo, trackFromTMAP, pTrackImageBuffer, CWOZHelper::WOZ1_TRACK_SIZE);
|
||||
CWOZHelper::TRKv1* pTRK = (CWOZHelper::TRKv1*) &pTrackImageBuffer[CWOZHelper::WOZ1_TRK_OFFSET];
|
||||
*pNibbles = pTRK->bytesUsed;
|
||||
*pBitCount = pTRK->bitCount;
|
||||
}
|
||||
|
||||
virtual void Write(ImageInfo* pImageInfo, const float phase, LPBYTE pTrackImageBuffer, int nNibbles)
|
||||
{
|
||||
// TODO
|
||||
_ASSERT(0);
|
||||
}
|
||||
|
||||
// TODO: Uncomment and fix-up if we want to allow .woz image creation (eg. for INIT or FORMAT)
|
||||
// virtual bool AllowCreate(void) { return true; }
|
||||
// virtual UINT GetImageSizeForCreate(void) { return 0; }//TODO
|
||||
|
||||
virtual eImageType GetType(void) { return eImageWOZ1; }
|
||||
virtual const char* GetCreateExtensions(void) { return ".woz"; }
|
||||
virtual const char* GetRejectExtensions(void) { return ".do;.dsk;.nib;.iie;.po;.prg"; }
|
||||
};
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
class CWOZ2Image : public CImageBase, private CWOZEmptyTrack
|
||||
{
|
||||
public:
|
||||
CWOZ2Image(void) {}
|
||||
virtual ~CWOZ2Image(void) {}
|
||||
|
||||
virtual eDetectResult Detect(const LPBYTE pImage, const DWORD dwImageSize, const TCHAR* pszExt)
|
||||
{
|
||||
CWOZHelper::WOZHeader* pWozHdr = (CWOZHelper::WOZHeader*) pImage;
|
||||
|
||||
if (pWozHdr->id1 != CWOZHelper::ID1_WOZ2 || pWozHdr->id2 != CWOZHelper::ID2)
|
||||
return eMismatch;
|
||||
|
||||
if (pWozHdr->crc32)
|
||||
{
|
||||
// TODO: check crc
|
||||
}
|
||||
|
||||
m_uNumTracksInImage = CWOZHelper::MAX_TRACKS_5_25;
|
||||
return eMatch;
|
||||
}
|
||||
|
||||
virtual void Read(ImageInfo* pImageInfo, const float phase, LPBYTE pTrackImageBuffer, int* pNibbles, UINT* pBitCount, bool enhanceDisk)
|
||||
{
|
||||
BYTE*& pTrackMap = pImageInfo->pTrackMap;
|
||||
|
||||
const int trackFromTMAP = pTrackMap[(UINT)(phase * 2)];
|
||||
if (trackFromTMAP == 0xFF)
|
||||
return ReadEmptyTrack(pTrackImageBuffer, pNibbles, pBitCount);
|
||||
|
||||
CWOZHelper::TRKv2* pTRKS = (CWOZHelper::TRKv2*) &pImageInfo->pImageBuffer[pImageInfo->uOffset];
|
||||
CWOZHelper::TRKv2* pTRK = &pTRKS[trackFromTMAP];
|
||||
*pBitCount = pTRK->bitCount;
|
||||
*pNibbles = (pTRK->bitCount+7) / 8;
|
||||
|
||||
_ASSERT(*pNibbles <= NIBBLES_PER_TRACK_WOZ2);
|
||||
if (*pNibbles > NIBBLES_PER_TRACK_WOZ2)
|
||||
return ReadEmptyTrack(pTrackImageBuffer, pNibbles, pBitCount); // TODO: Enlarge track buffer, but for now just return an empty track
|
||||
|
||||
memcpy(pTrackImageBuffer, &pImageInfo->pImageBuffer[pTRK->startBlock*512], *pNibbles);
|
||||
}
|
||||
|
||||
virtual void Write(ImageInfo* pImageInfo, const float phase, LPBYTE pTrackImageBuffer, int nNibbles)
|
||||
{
|
||||
// TODO
|
||||
_ASSERT(0);
|
||||
}
|
||||
|
||||
// TODO: Uncomment and fix-up if we want to allow .woz image creation (eg. for INIT or FORMAT)
|
||||
// virtual bool AllowCreate(void) { return true; }
|
||||
// virtual UINT GetImageSizeForCreate(void) { return 0; }//TODO
|
||||
|
||||
virtual eImageType GetType(void) { return eImageWOZ2; }
|
||||
virtual const char* GetCreateExtensions(void) { return ".woz"; }
|
||||
virtual const char* GetRejectExtensions(void) { return ".do;.dsk;.nib;.iie;.po;.prg"; }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -1048,6 +1205,8 @@ eDetectResult CMacBinaryHelper::DetectHdr(LPBYTE& pImage, DWORD& dwImageSize, DW
|
||||
return eMismatch;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
eDetectResult C2IMGHelper::DetectHdr(LPBYTE& pImage, DWORD& dwImageSize, DWORD& dwOffset)
|
||||
{
|
||||
Header2IMG* pHdr = (Header2IMG*) pImage;
|
||||
@@ -1099,7 +1258,7 @@ eDetectResult C2IMGHelper::DetectHdr(LPBYTE& pImage, DWORD& dwImageSize, DWORD&
|
||||
break;
|
||||
case e2IMGFormatNIBData:
|
||||
{
|
||||
if (pHdr->DiskDataLength != TRACKS_STANDARD*NIBBLES_PER_TRACK)
|
||||
if (pHdr->DiskDataLength != TRACKS_STANDARD*NIBBLES_PER_TRACK_NIB)
|
||||
return eMismatch;
|
||||
}
|
||||
break;
|
||||
@@ -1126,11 +1285,59 @@ bool C2IMGHelper::IsLocked(void)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Pre: already matched the WOZ header
|
||||
eDetectResult CWOZHelper::ProcessChunks(const LPBYTE pImage, const DWORD dwImageSize, DWORD& dwOffset, BYTE*& pTrackMap)
|
||||
{
|
||||
UINT32* pImage32 = (uint32_t*) (pImage + sizeof(WOZHeader));
|
||||
UINT32 imageSizeRemaining = dwImageSize - sizeof(WOZHeader);
|
||||
|
||||
while(imageSizeRemaining > 8)
|
||||
{
|
||||
UINT32 chunkId = *pImage32++;
|
||||
UINT32 chunkSize = *pImage32++;
|
||||
imageSizeRemaining -= 8;
|
||||
|
||||
switch(chunkId)
|
||||
{
|
||||
case INFO_CHUNK_ID:
|
||||
m_pInfo = (InfoChunkv2*)(pImage32-2);
|
||||
if (m_pInfo->v1.version > InfoChunk::maxSupportedVersion)
|
||||
return eMismatch;
|
||||
if (m_pInfo->v1.diskType != InfoChunk::diskType5_25)
|
||||
return eMismatch;
|
||||
break;
|
||||
case TMAP_CHUNK_ID:
|
||||
pTrackMap = (uint8_t*)pImage32;
|
||||
break;
|
||||
case TRKS_CHUNK_ID:
|
||||
dwOffset = dwImageSize - imageSizeRemaining; // offset into image of track data
|
||||
break;
|
||||
case WRIT_CHUNK_ID: // WOZ v2 (optional)
|
||||
break;
|
||||
case META_CHUNK_ID: // (optional)
|
||||
break;
|
||||
default: // no idea what this chunk is, so skip it
|
||||
_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
pImage32 = (UINT32*) ((BYTE*)pImage32 + chunkSize);
|
||||
imageSizeRemaining -= chunkSize;
|
||||
_ASSERT(imageSizeRemaining >= 0);
|
||||
if (imageSizeRemaining < 0)
|
||||
return eMismatch;
|
||||
}
|
||||
|
||||
return eMatch;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// NB. Of the 6 cases (floppy/harddisk x gzip/zip/normal) only harddisk-normal isn't read entirely to memory
|
||||
// - harddisk-normal-create also doesn't create a max size image-buffer
|
||||
|
||||
// DETERMINE THE FILE'S EXTENSION AND CONVERT IT TO LOWERCASE
|
||||
void GetCharLowerExt(TCHAR* pszExt, LPCTSTR pszImageFilename, const UINT uExtSize)
|
||||
void CImageHelperBase::GetCharLowerExt(TCHAR* pszExt, LPCTSTR pszImageFilename, const UINT uExtSize)
|
||||
{
|
||||
LPCTSTR pImageFileExt = pszImageFilename;
|
||||
|
||||
@@ -1146,7 +1353,7 @@ void GetCharLowerExt(TCHAR* pszExt, LPCTSTR pszImageFilename, const UINT uExtSiz
|
||||
CharLowerBuff(pszExt, _tcslen(pszExt));
|
||||
}
|
||||
|
||||
void GetCharLowerExt2(TCHAR* pszExt, LPCTSTR pszImageFilename, const UINT uExtSize)
|
||||
void CImageHelperBase::GetCharLowerExt2(TCHAR* pszExt, LPCTSTR pszImageFilename, const UINT uExtSize)
|
||||
{
|
||||
TCHAR szFilename[MAX_PATH];
|
||||
_tcsncpy(szFilename, pszImageFilename, MAX_PATH);
|
||||
@@ -1187,7 +1394,7 @@ ImageError_e CImageHelperBase::CheckGZipFile(LPCTSTR pszImageFilename, ImageInfo
|
||||
|
||||
DWORD dwSize = nLen;
|
||||
DWORD dwOffset = 0;
|
||||
CImageBase* pImageType = Detect(pImageInfo->pImageBuffer, dwSize, szExt, dwOffset, &pImageInfo->bWriteProtected);
|
||||
CImageBase* pImageType = Detect(pImageInfo->pImageBuffer, dwSize, szExt, dwOffset, pImageInfo->bWriteProtected, pImageInfo->pTrackMap, pImageInfo->optimalBitTiming);
|
||||
|
||||
if (!pImageType)
|
||||
return eIMAGE_ERROR_UNSUPPORTED;
|
||||
@@ -1196,11 +1403,7 @@ ImageError_e CImageHelperBase::CheckGZipFile(LPCTSTR pszImageFilename, ImageInfo
|
||||
if (Type == eImageAPL || Type == eImageIIE || Type == eImagePRG)
|
||||
return eIMAGE_ERROR_UNSUPPORTED;
|
||||
|
||||
pImageInfo->FileType = eFileGZip;
|
||||
pImageInfo->uOffset = dwOffset;
|
||||
pImageInfo->pImageType = pImageType;
|
||||
pImageInfo->uImageSize = dwSize;
|
||||
|
||||
SetImageInfo(pImageInfo, eFileGZip, dwOffset, pImageType, dwSize);
|
||||
return eIMAGE_ERROR_NONE;
|
||||
}
|
||||
|
||||
@@ -1283,7 +1486,7 @@ ImageError_e CImageHelperBase::CheckZipFile(LPCTSTR pszImageFilename, ImageInfo*
|
||||
|
||||
DWORD dwSize = nLen;
|
||||
DWORD dwOffset = 0;
|
||||
CImageBase* pImageType = Detect(pImageInfo->pImageBuffer, dwSize, szExt, dwOffset, &pImageInfo->bWriteProtected);
|
||||
CImageBase* pImageType = Detect(pImageInfo->pImageBuffer, dwSize, szExt, dwOffset, pImageInfo->bWriteProtected, pImageInfo->pTrackMap, pImageInfo->optimalBitTiming);
|
||||
|
||||
if (!pImageType)
|
||||
{
|
||||
@@ -1300,11 +1503,7 @@ ImageError_e CImageHelperBase::CheckZipFile(LPCTSTR pszImageFilename, ImageInfo*
|
||||
if (global_info.number_entry > 1)
|
||||
pImageInfo->bWriteProtected = 1; // Zip archives with multiple files are read-only (for now)
|
||||
|
||||
pImageInfo->FileType = eFileZip;
|
||||
pImageInfo->uOffset = dwOffset;
|
||||
pImageInfo->pImageType = pImageType;
|
||||
pImageInfo->uImageSize = dwSize;
|
||||
|
||||
SetImageInfo(pImageInfo, eFileZip, dwOffset, pImageType, dwSize);
|
||||
return eIMAGE_ERROR_NONE;
|
||||
}
|
||||
|
||||
@@ -1384,7 +1583,7 @@ ImageError_e CImageHelperBase::CheckNormalFile(LPCTSTR pszImageFilename, ImageIn
|
||||
return eIMAGE_ERROR_BAD_SIZE;
|
||||
}
|
||||
|
||||
pImageType = Detect(pImageInfo->pImageBuffer, dwSize, szExt, dwOffset, &pImageInfo->bWriteProtected);
|
||||
pImageType = Detect(pImageInfo->pImageBuffer, dwSize, szExt, dwOffset, pImageInfo->bWriteProtected, pImageInfo->pTrackMap, pImageInfo->optimalBitTiming);
|
||||
if (bTempDetectBuffer)
|
||||
{
|
||||
delete [] pImageInfo->pImageBuffer;
|
||||
@@ -1437,12 +1636,18 @@ ImageError_e CImageHelperBase::CheckNormalFile(LPCTSTR pszImageFilename, ImageIn
|
||||
return eIMAGE_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
pImageInfo->FileType = eFileNormal;
|
||||
SetImageInfo(pImageInfo, eFileNormal, dwOffset, pImageType, dwSize);
|
||||
return eIMAGE_ERROR_NONE;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
void CImageHelperBase::SetImageInfo(ImageInfo* pImageInfo, FileType_e eFileGZip, DWORD dwOffset, CImageBase* pImageType, DWORD dwSize)
|
||||
{
|
||||
pImageInfo->FileType = eFileGZip;
|
||||
pImageInfo->uOffset = dwOffset;
|
||||
pImageInfo->pImageType = pImageType;
|
||||
pImageInfo->uImageSize = dwSize;
|
||||
|
||||
return eIMAGE_ERROR_NONE;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
@@ -1517,54 +1722,68 @@ CDiskImageHelper::CDiskImageHelper(void) :
|
||||
m_vecImageTypes.push_back( new CIIeImage );
|
||||
m_vecImageTypes.push_back( new CAplImage );
|
||||
m_vecImageTypes.push_back( new CPrgImage );
|
||||
m_vecImageTypes.push_back( new CWOZ1Image );
|
||||
m_vecImageTypes.push_back( new CWOZ2Image );
|
||||
}
|
||||
|
||||
CImageBase* CDiskImageHelper::Detect(LPBYTE pImage, DWORD dwSize, const TCHAR* pszExt, DWORD& dwOffset, bool* pWriteProtected_)
|
||||
CImageBase* CDiskImageHelper::Detect(LPBYTE pImage, DWORD dwSize, const TCHAR* pszExt, DWORD& dwOffset, bool& writeProtected, BYTE*& pTrackMap, BYTE& optimalBitTiming)
|
||||
{
|
||||
dwOffset = 0;
|
||||
m_MacBinaryHelper.DetectHdr(pImage, dwSize, dwOffset);
|
||||
m_Result2IMG = m_2IMGHelper.DetectHdr(pImage, dwSize, dwOffset);
|
||||
|
||||
// CALL THE DETECTION FUNCTIONS IN ORDER, LOOKING FOR A MATCH
|
||||
eImageType ImageType = eImageUNKNOWN;
|
||||
eImageType PossibleType = eImageUNKNOWN;
|
||||
eImageType imageType = eImageUNKNOWN;
|
||||
eImageType possibleType = eImageUNKNOWN;
|
||||
|
||||
if (m_Result2IMG == eMatch)
|
||||
{
|
||||
if (m_2IMGHelper.IsImageFormatDOS33())
|
||||
ImageType = eImageDO;
|
||||
imageType = eImageDO;
|
||||
else if (m_2IMGHelper.IsImageFormatProDOS())
|
||||
ImageType = eImagePO;
|
||||
imageType = eImagePO;
|
||||
|
||||
if (ImageType != eImageUNKNOWN)
|
||||
if (imageType != eImageUNKNOWN)
|
||||
{
|
||||
CImageBase* pImageType = GetImage(ImageType);
|
||||
CImageBase* pImageType = GetImage(imageType);
|
||||
if (!pImageType || !pImageType->IsValidImageSize(dwSize))
|
||||
ImageType = eImageUNKNOWN;
|
||||
imageType = eImageUNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
if (ImageType == eImageUNKNOWN)
|
||||
if (imageType == eImageUNKNOWN)
|
||||
{
|
||||
for (UINT uLoop=0; uLoop < GetNumImages() && ImageType == eImageUNKNOWN; uLoop++)
|
||||
for (UINT uLoop=0; uLoop < GetNumImages() && imageType == eImageUNKNOWN; uLoop++)
|
||||
{
|
||||
if (*pszExt && _tcsstr(GetImage(uLoop)->GetRejectExtensions(), pszExt))
|
||||
continue;
|
||||
|
||||
eDetectResult Result = GetImage(uLoop)->Detect(pImage, dwSize, pszExt);
|
||||
if (Result == eMatch)
|
||||
ImageType = GetImage(uLoop)->GetType();
|
||||
else if ((Result == ePossibleMatch) && (PossibleType == eImageUNKNOWN))
|
||||
PossibleType = GetImage(uLoop)->GetType();
|
||||
imageType = GetImage(uLoop)->GetType();
|
||||
else if ((Result == ePossibleMatch) && (possibleType == eImageUNKNOWN))
|
||||
possibleType = GetImage(uLoop)->GetType();
|
||||
}
|
||||
}
|
||||
|
||||
if (ImageType == eImageUNKNOWN)
|
||||
ImageType = PossibleType;
|
||||
if (imageType == eImageUNKNOWN)
|
||||
imageType = possibleType;
|
||||
|
||||
CImageBase* pImageType = GetImage(ImageType);
|
||||
CImageBase* pImageType = GetImage(imageType);
|
||||
if (!pImageType)
|
||||
return NULL;
|
||||
|
||||
if (pImageType)
|
||||
if (imageType == eImageWOZ1 || imageType == eImageWOZ2)
|
||||
{
|
||||
if (m_WOZHelper.ProcessChunks(pImage, dwSize, dwOffset, pTrackMap) != eMatch)
|
||||
return NULL;
|
||||
|
||||
// if (m_WOZHelper.IsWriteProtected() && !writeProtected) // Force write-protected until writing is supported
|
||||
writeProtected = true;
|
||||
|
||||
optimalBitTiming = m_WOZHelper.GetOptimalBitTiming();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pImageType->AllowRW())
|
||||
{
|
||||
@@ -1578,8 +1797,8 @@ CImageBase* CDiskImageHelper::Detect(LPBYTE pImage, DWORD dwSize, const TCHAR* p
|
||||
{
|
||||
pImageType->SetVolumeNumber( m_2IMGHelper.GetVolumeNumber() );
|
||||
|
||||
if (m_2IMGHelper.IsLocked() && !*pWriteProtected_)
|
||||
*pWriteProtected_ = 1;
|
||||
if (m_2IMGHelper.IsLocked() && !writeProtected)
|
||||
writeProtected = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1634,7 +1853,7 @@ CHardDiskImageHelper::CHardDiskImageHelper(void) :
|
||||
m_vecImageTypes.push_back( new CHDVImage );
|
||||
}
|
||||
|
||||
CImageBase* CHardDiskImageHelper::Detect(LPBYTE pImage, DWORD dwSize, const TCHAR* pszExt, DWORD& dwOffset, bool* pWriteProtected_)
|
||||
CImageBase* CHardDiskImageHelper::Detect(LPBYTE pImage, DWORD dwSize, const TCHAR* pszExt, DWORD& dwOffset, bool& writeProtected, BYTE*& pTrackMap, BYTE& optimalBitTiming)
|
||||
{
|
||||
dwOffset = 0;
|
||||
m_Result2IMG = m_2IMGHelper.DetectHdr(pImage, dwSize, dwOffset);
|
||||
@@ -1659,11 +1878,14 @@ CImageBase* CHardDiskImageHelper::Detect(LPBYTE pImage, DWORD dwSize, const TCHA
|
||||
{
|
||||
if (m_Result2IMG == eMatch)
|
||||
{
|
||||
if (m_2IMGHelper.IsLocked() && !*pWriteProtected_)
|
||||
*pWriteProtected_ = 1;
|
||||
if (m_2IMGHelper.IsLocked() && !writeProtected)
|
||||
writeProtected = true;
|
||||
}
|
||||
}
|
||||
|
||||
pTrackMap = 0; // TODO: WOZ
|
||||
optimalBitTiming = 0; // TODO: WOZ
|
||||
|
||||
return pImageType;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user