WOZ: Support very large 5.25 WOZ images (#1240)

This commit is contained in:
tomcw 2023-06-29 21:52:59 +01:00
parent f8d238f2b0
commit faff74a98d
2 changed files with 43 additions and 8 deletions

View File

@ -1505,13 +1505,22 @@ eDetectResult CWOZHelper::ProcessChunks(ImageInfo* pImageInfo, DWORD& dwOffset)
m_pInfo = (InfoChunkv2*)pImage32;
if (m_pInfo->v1.diskType != InfoChunk::diskType5_25)
return eMismatch;
#ifdef _DEBUG
if (m_pInfo->v1.version >= 3)
{
InfoChunkv3* pInfoV3 = (InfoChunkv3*)pImage32;
LogOutput("WOZ: Largest Flux Track = %d\n", pInfoV3->largestFluxTrack);
}
break;
#endif
case TMAP_CHUNK_ID:
pImageInfo->pWOZTrackMap = (BYTE*) pImage32;
break;
case TRKS_CHUNK_ID:
dwOffset = pImageInfo->uOffset = pImageInfo->uImageSize - imageSizeRemaining; // offset into image of track data
break;
case FLUX_CHUNK_ID: // WOZ v3 (todo)
break;
case WRIT_CHUNK_ID: // WOZ v2 (optional)
break;
case META_CHUNK_ID: // (optional)
@ -1574,14 +1583,29 @@ ImageError_e CImageHelperBase::CheckGZipFile(LPCTSTR pszImageFilename, ImageInfo
if (hGZFile == NULL)
return eIMAGE_ERROR_UNABLE_TO_OPEN_GZ;
const UINT MAX_UNCOMPRESSED_SIZE = GetMaxImageSize() + 1; // +1 to detect images that are too big
pImageInfo->pImageBuffer = new BYTE[MAX_UNCOMPRESSED_SIZE];
// determine uncompressed file length
UINT fileSize = 0;
{
const UINT tempBufferSize = 256 * 1024;
BYTE* tempBuffer = new BYTE[tempBufferSize];
while (int len = gzread(hGZFile, tempBuffer, tempBufferSize))
fileSize += len;
delete[] tempBuffer;
int res = gzrewind(hGZFile);
if (res != 0)
return eIMAGE_ERROR_GZ;
}
int nLen = gzread(hGZFile, pImageInfo->pImageBuffer, MAX_UNCOMPRESSED_SIZE);
if (fileSize == 0 || fileSize > GetMaxImageSize())
return eIMAGE_ERROR_BAD_SIZE;
pImageInfo->pImageBuffer = new BYTE[fileSize];
int nLen = gzread(hGZFile, pImageInfo->pImageBuffer, fileSize);
int nRes = gzclose(hGZFile); // close before returning (due to error) to avoid resource leak
hGZFile = NULL;
if (nLen < 0 || nLen == MAX_UNCOMPRESSED_SIZE)
if (nLen <= 0)
return eIMAGE_ERROR_BAD_SIZE;
if (nRes != Z_OK)
@ -1986,6 +2010,8 @@ bool CImageHelperBase::WOZUpdateInfo(ImageInfo* pImageInfo, DWORD& dwOffset)
CDiskImageHelper::CDiskImageHelper(void) :
CImageHelperBase(true)
{
m_vecImageTypes.push_back( new CWOZ1Image ); // Try to match WOZ1/WOZ2 first, as these can be precisely matched
m_vecImageTypes.push_back( new CWOZ2Image );
m_vecImageTypes.push_back( new CDoImage );
m_vecImageTypes.push_back( new CPoImage );
m_vecImageTypes.push_back( new CNib1Image );
@ -1994,8 +2020,6 @@ 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, ImageInfo* pImageInfo)
@ -2112,8 +2136,11 @@ CImageBase* CDiskImageHelper::GetImageForCreation(const TCHAR* pszExt, DWORD* pC
UINT CDiskImageHelper::GetMaxImageSize(void)
{
// TODO: This doesn't account for .2mg files with comments after the disk-image
return UNIDISK35_800K_SIZE + m_MacBinaryHelper.GetMaxHdrSize() + m_2IMGHelper.GetMaxHdrSize();
// Pathologic largest 5.25 image is a WOZ with FLUX tracks for each 0.25 track (GH#1240)
const UINT largestFluxTrackInBlocks = 100; // typically this is 70-80 blocks
const UINT maxTracks = 35 * 4; // typically only ~10-20 FLUX tracks (the rest TRKS tracks)
const UINT bytesPerBlock = 512;
return largestFluxTrackInBlocks * maxTracks * bytesPerBlock; // ~7MB
}
UINT CDiskImageHelper::GetMinDetectSize(const UINT uImageSize, bool* pTempDetectBuffer)

View File

@ -284,6 +284,7 @@ private:
static const UINT32 TRKS_CHUNK_ID = 'SKRT'; // 'TRKS'
static const UINT32 WRIT_CHUNK_ID = 'TIRW'; // 'WRIT' - WOZv2
static const UINT32 META_CHUNK_ID = 'ATEM'; // 'META'
static const UINT32 FLUX_CHUNK_ID = 'XULF'; // 'FLUX' - WOZv3
static const UINT32 INFO_CHUNK_SIZE = 60; // Fixed size for both WOZv1 & WOZv2
struct InfoChunk
@ -314,6 +315,13 @@ private:
static const BYTE optimalBitTiming5_25 = 32;
};
struct InfoChunkv3
{
InfoChunkv2 v2;
UINT16 fluxBlock; // Block number where the FLUX chuck resides relative to the start of the file.
UINT16 largestFluxTrack; // in blocks (512 bytes)
};
InfoChunkv2* m_pInfo; // NB. image-specific - only valid during Detect(), which calls InvalidateInfo() when done
//