From 035120dd5745c93cc0ba85f48a807e1aa9457fd0 Mon Sep 17 00:00:00 2001 From: tomcw Date: Sun, 10 Sep 2023 16:39:11 +0100 Subject: [PATCH] WOZHelper: ValidateTMAPandFLUX() --- source/DiskImageHelper.cpp | 70 +++++++++++++++++++++++++++++--------- source/DiskImageHelper.h | 24 +++++++------ 2 files changed, 67 insertions(+), 27 deletions(-) diff --git a/source/DiskImageHelper.cpp b/source/DiskImageHelper.cpp index 630779cf..9b9e9d65 100644 --- a/source/DiskImageHelper.cpp +++ b/source/DiskImageHelper.cpp @@ -1502,14 +1502,14 @@ eDetectResult CWOZHelper::ProcessChunks(ImageInfo* pImageInfo, DWORD& dwOffset) switch(chunkId) { case INFO_CHUNK_ID: - m_pInfo = (InfoChunkv2*)pImage32; - if (m_pInfo->v1.diskType != InfoChunk::diskType5_25) + m_pInfo = (InfoChunkv3*)pImage32; + if (m_pInfo->v2.v1.diskType != InfoChunk::diskType5_25) return eMismatch; #ifdef _DEBUG - if (m_pInfo->v1.version >= 3) + if (m_pInfo->v2.v1.version >= 3) { InfoChunkv3* pInfoV3 = (InfoChunkv3*)pImage32; - LogOutput("WOZ: Largest Flux Track = %d\n", pInfoV3->largestFluxTrack); + LogOutput("WOZ: Largest Flux Track (in blocks) = %d\n", pInfoV3->largestFluxTrack); } break; #endif @@ -1519,7 +1519,8 @@ eDetectResult CWOZHelper::ProcessChunks(ImageInfo* pImageInfo, DWORD& dwOffset) case TRKS_CHUNK_ID: dwOffset = pImageInfo->uOffset = pImageInfo->uImageSize - imageSizeRemaining; // offset into image of track data break; - case FLUX_CHUNK_ID: // WOZ v3 (todo) + case FLUX_CHUNK_ID: // WOZ v2.1 (todo) + pImageInfo->pWOZTrackMapFlux = (BYTE*)pImage32; break; case WRIT_CHUNK_ID: // WOZ v2 (optional) break; @@ -1537,9 +1538,46 @@ eDetectResult CWOZHelper::ProcessChunks(ImageInfo* pImageInfo, DWORD& dwOffset) return eMismatch; } + ValidateTMAPandFLUX(pImageInfo); + return eMatch; } +bool CWOZHelper::ValidateTMAPandFLUX(ImageInfo* pImageInfo) +{ + if (pImageInfo->pWOZTrackMap == NULL) + return false; + + if (pImageInfo->pWOZTrackMapFlux == NULL) + return true; + + if ( (m_pInfo->v2.v1.version < 3) || // // must be INFO v3 or more for FLUX tmap + (!m_pInfo->fluxBlock || !m_pInfo->largestFluxTrack) ) // both fluxBlock and largestFluxTrack must be non-zero + { + LogOutput("WOZ image with FLUX invalid\n"); + pImageInfo->pWOZTrackMapFlux = NULL; + return false; + } + + // We have both TMAP and FLUX tmaps so check there's no valid (non-0xFF) entries in both. + + BYTE* pTMAP = (BYTE*)pImageInfo->pWOZTrackMap; + BYTE* pFLUX = (BYTE*)pImageInfo->pWOZTrackMapFlux; + +// LogOutput("----: TMAP FLUX\n"); + for (UINT i = 0; i < MAX_QUARTER_TRACKS_5_25; i++, pTMAP++, pFLUX++) + { +// LogOutput("%04d: %02X %02X\n", i, *pTMAP, *pFLUX); + if (*pTMAP != TMAP_TRACK_EMPTY && *pFLUX != TMAP_TRACK_EMPTY) + { + LogOutput("WOZ image with FLUX not created properly (quarter track: %d)\n", i); + *pTMAP = TMAP_TRACK_EMPTY; // WOZ v2.1 spec says to use FLUX + } + } + + return true; +} + //----------------------------------------------------------------------------- // NB. Of the 6 cases (floppy/harddisk x gzip/zip/normal) only harddisk-normal isn't read entirely to memory @@ -2251,18 +2289,18 @@ BYTE* CWOZHelper::CreateEmptyDisk(DWORD& size) pWOZ->infoHdr.id = INFO_CHUNK_ID; pWOZ->infoHdr.size = (BYTE*)&pWOZ->tmapHdr - (BYTE*)&pWOZ->info; _ASSERT(pWOZ->infoHdr.size == INFO_CHUNK_SIZE); - pWOZ->info.v1.version = 2; - pWOZ->info.v1.diskType = InfoChunk::diskType5_25; - pWOZ->info.v1.cleaned = 1; + pWOZ->info.v2.v1.version = 2; + pWOZ->info.v2.v1.diskType = InfoChunk::diskType5_25; + pWOZ->info.v2.v1.cleaned = 1; std::string creator = "AppleWin v" + g_VERSIONSTRING; - memset(&pWOZ->info.v1.creator[0], ' ', sizeof(pWOZ->info.v1.creator)); - memcpy(&pWOZ->info.v1.creator[0], creator.c_str(), creator.size()); // don't include null - pWOZ->info.diskSides = 1; - pWOZ->info.bootSectorFormat = bootUnknown; // could be INIT'd to 13 or 16 sector - pWOZ->info.optimalBitTiming = InfoChunkv2::optimalBitTiming5_25; - pWOZ->info.compatibleHardware = 0; // unknown - pWOZ->info.requiredRAM = 0; // unknown - pWOZ->info.largestTrack = TRK_DEFAULT_BLOCK_COUNT_5_25; // unknown - but use default + memset(&pWOZ->info.v2.v1.creator[0], ' ', sizeof(pWOZ->info.v2.v1.creator)); + memcpy(&pWOZ->info.v2.v1.creator[0], creator.c_str(), creator.size()); // don't include null + pWOZ->info.v2.diskSides = 1; + pWOZ->info.v2.bootSectorFormat = bootUnknown; // could be INIT'd to 13 or 16 sector + pWOZ->info.v2.optimalBitTiming = InfoChunkv2::optimalBitTiming5_25; + pWOZ->info.v2.compatibleHardware = 0; // unknown + pWOZ->info.v2.requiredRAM = 0; // unknown + pWOZ->info.v2.largestTrack = TRK_DEFAULT_BLOCK_COUNT_5_25; // unknown - but use default // TMAP ASSERT_OFFSET(tmapHdr, 80); diff --git a/source/DiskImageHelper.h b/source/DiskImageHelper.h index 27dec852..c240fb12 100644 --- a/source/DiskImageHelper.h +++ b/source/DiskImageHelper.h @@ -37,6 +37,7 @@ struct ImageInfo UINT uNumTracks; BYTE* pImageBuffer; BYTE* pWOZTrackMap; // WOZ only (points into pImageBuffer) + BYTE* pWOZTrackMapFlux; // WOZ only (points into pImageBuffer) (from WOZv2.1) BYTE optimalBitTiming; // WOZ only BYTE bootSectorFormat; // WOZ only UINT maxNibblesPerTrack; @@ -209,12 +210,13 @@ public: virtual eDetectResult DetectHdr(LPBYTE& pImage, DWORD& dwImageSize, DWORD& dwOffset) { _ASSERT(0); return eMismatch; } virtual UINT GetMaxHdrSize(void) { return sizeof(WOZHeader); } eDetectResult ProcessChunks(ImageInfo* pImageInfo, DWORD& dwOffset); - bool IsWriteProtected(void) { return m_pInfo->v1.writeProtected == 1; } - BYTE GetOptimalBitTiming(void) { return (m_pInfo->v1.version >= 2) ? m_pInfo->optimalBitTiming : InfoChunkv2::optimalBitTiming5_25; } - UINT GetMaxNibblesPerTrack(void) { return (m_pInfo->v1.version >= 2) ? m_pInfo->largestTrack*CWOZHelper::BLOCK_SIZE : WOZ1_TRACK_SIZE; } - BYTE GetBootSectorFormat(void) { return (m_pInfo->v1.version >= 2) ? m_pInfo->bootSectorFormat : bootUnknown; } + bool IsWriteProtected(void) { return m_pInfo->v2.v1.writeProtected == 1; } + BYTE GetOptimalBitTiming(void) { return (m_pInfo->v2.v1.version >= 2) ? m_pInfo->v2.optimalBitTiming : InfoChunkv2::optimalBitTiming5_25; } + UINT GetMaxNibblesPerTrack(void) { return (m_pInfo->v2.v1.version >= 2) ? m_pInfo->v2.largestTrack*CWOZHelper::BLOCK_SIZE : WOZ1_TRACK_SIZE; } + BYTE GetBootSectorFormat(void) { return (m_pInfo->v2.v1.version >= 2) ? m_pInfo->v2.bootSectorFormat : bootUnknown; } void InvalidateInfo(void) { m_pInfo = NULL; } BYTE* CreateEmptyDisk(DWORD& size); + bool ValidateTMAPandFLUX(ImageInfo* pImageInfo); #if _DEBUG BYTE* CreateEmptyDiskv1(DWORD& size); #endif @@ -267,9 +269,9 @@ public: struct TRKv2 { - UINT16 startBlock; // relative to start of file + UINT16 startBlock; // First block of BITS (or flux) data, relative to start of file UINT16 blockCount; // number of blocks for this BITS data - UINT32 bitCount; + UINT32 bitCount; // NB. From WOZv2.1 for flux tracks this is a byte count }; struct Trks @@ -284,8 +286,8 @@ 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 + static const UINT32 FLUX_CHUNK_ID = 'XULF'; // 'FLUX' - WOZv2.1 + static const UINT32 INFO_CHUNK_SIZE = 60; // Fixed size for both WOZv1 & WOZv2.1 struct InfoChunk { @@ -322,7 +324,7 @@ private: UINT16 largestFluxTrack; // in blocks (512 bytes) }; - InfoChunkv2* m_pInfo; // NB. image-specific - only valid during Detect(), which calls InvalidateInfo() when done + InfoChunkv3* m_pInfo; // NB. image-specific - only valid during Detect(), which calls InvalidateInfo() when done // @@ -331,8 +333,8 @@ private: WOZHeader hdr; WOZChunkHdr infoHdr; - InfoChunkv2 info; - BYTE infoPadding[INFO_CHUNK_SIZE-sizeof(InfoChunkv2)]; + InfoChunkv3 info; + BYTE infoPadding[INFO_CHUNK_SIZE-sizeof(InfoChunkv3)]; WOZChunkHdr tmapHdr; Tmap tmap;