From faff74a98d822ca5ec60ca934bcef2f54b63f51b Mon Sep 17 00:00:00 2001 From: tomcw Date: Thu, 29 Jun 2023 21:52:59 +0100 Subject: [PATCH] WOZ: Support very large 5.25 WOZ images (#1240) --- source/DiskImageHelper.cpp | 43 +++++++++++++++++++++++++++++++------- source/DiskImageHelper.h | 8 +++++++ 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/source/DiskImageHelper.cpp b/source/DiskImageHelper.cpp index 30aba234..630779cf 100644 --- a/source/DiskImageHelper.cpp +++ b/source/DiskImageHelper.cpp @@ -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) diff --git a/source/DiskImageHelper.h b/source/DiskImageHelper.h index 38ecddbf..27dec852 100644 --- a/source/DiskImageHelper.h +++ b/source/DiskImageHelper.h @@ -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 //