/* * Read SECTOR_DATA CHUNK type */ bool _load_sector_data_chunk(chunk_header chunkhdr, AtxTrack track, BinaryReader reader) { int data_size = (int)chunkhdr.length - chunk_header_bytecount; if (track.sector_count > 0 && track.sectors.Any() == false) { Console.WriteLine($"\tWARNING:: SECTOR_DATA chunk presented before SECTOR_LIST chunk"); } else { int actual_sectors = 0; string missing_sectors = ""; foreach (var s in track.sectors) { if ((s.status & (byte)SectorStatus.MISSING_DATA) == 0) { actual_sectors++; } else { missing_sectors = "; missing sectors accounted for"; } } int calculated_bytes = actual_sectors * _sector_size; if (data_size != calculated_bytes) { Console.WriteLine($"\tWARNING:: Chunk data size as given in header ({data_size:N0}) != expected size ({actual_sectors} * {_sector_size} = {calculated_bytes:N0}){missing_sectors}"); } } Console.WriteLine($"\tReading {data_size:N0} bytes of track sector data"); try { track.data = reader.ReadBytes(data_size); } catch { Console.WriteLine($"\tERROR:: Failed to read sector data"); return(false); } /* * The start_data value in each sector header is an offset into the overall Track Record, * including headers and other chunks that preceed it, where that sector's actual data begins * in the data chunk. * * We record the number of bytes into the Track Record the data chunk begins so we * can adjust the start_data value later when we want to read the right section from this * array of bytes. */ track.offset_to_data_start = track.record_bytes_read; // Keep a count of how many bytes we've read into the Track Record track.record_bytes_read += data_size; _sector_data_bytes += data_size; return(true); }
/* * Read EXTENDED_DATA CHUNK type */ bool _load_extended_sector_chunk(chunk_header chunkhdr, AtxTrack track, BinaryReader reader) { if (chunkhdr.length != chunk_header_bytecount) { Console.WriteLine($"\tERROR:: Chunk length {chunkhdr.length} != expected ({chunk_header_bytecount})"); } if (chunkhdr.sector_index >= track.sector_count) { Console.WriteLine("\tERROR:: Extended sector index > track sector count"); return(false); } UInt16 xsize; switch ((ExtendedSize)chunkhdr.header_data) { case ExtendedSize.EXTENDEDSIZE_128: xsize = 128; break; case ExtendedSize.EXTENDEDSIZE_256: xsize = 256; break; case ExtendedSize.EXTENDEDSIZE_512: xsize = 512; break; case ExtendedSize.EXTENDEDSIZE_1024: xsize = 1024; break; default: Console.WriteLine($"\tERROR:: Invalid extended sector value {chunkhdr.header_data}"); return(false); } track.sectors[chunkhdr.sector_index].extendedsize = xsize; int sector_number = track.sectors[chunkhdr.sector_index].number; int overall_sector_number = track.track_number * _sectors_per_track + sector_number; Console.WriteLine($"\tExtended sector: index={chunkhdr.sector_index}, num={sector_number} ({overall_sector_number}, ${overall_sector_number:x3}), size={xsize}"); return(true); }
/* * Read WEAK_SECTOR CHUNK type */ bool _load_weak_sector_chunk(chunk_header chunkhdr, AtxTrack track, BinaryReader reader) { if (chunkhdr.length != chunk_header_bytecount) { Console.WriteLine($"\tERROR:: Chunk length {chunkhdr.length} != expected ({chunk_header_bytecount})"); } if (chunkhdr.sector_index >= track.sector_count) { Console.WriteLine("\tERROR:: Weak sector index > track sector count"); return(false); } track.sectors[chunkhdr.sector_index].weakoffset = chunkhdr.header_data; int sector_number = track.sectors[chunkhdr.sector_index].number; int overall_sector_number = track.track_number * _sectors_per_track + sector_number; Console.WriteLine($"\tWeak sector: index={chunkhdr.sector_index}, num={sector_number} ({overall_sector_number}, ${overall_sector_number:x3}), offset={chunkhdr.header_data}"); return(true); }
/* * Read UNKNOWN CHUNK type */ bool _load_unknown_chunk(chunk_header chunkhdr, BinaryReader reader) { Console.WriteLine($"WARNING:: Unknown chunk type"); return(true); }
/* * Read SECTOR_LIST CHUNK type */ bool _load_sector_list_chunk(chunk_header chunkhdr, AtxTrack track, BinaryReader reader) { int expected = chunk_header_bytecount + track.sector_count * sector_header_bytecount; if (chunkhdr.length != expected) { Console.WriteLine($"\tWARNING:: Chunk length {chunkhdr.length} != expected ({expected})"); } // Try to read sector data for sector_count sectors for (int i = 0; i < track.sector_count; i++) { AtxSector sect = new AtxSector(); try { sect.number = reader.ReadByte(); sect.status = reader.ReadByte(); sect.position = reader.ReadUInt16(); sect.start_data = reader.ReadUInt32(); track.record_bytes_read += sector_header_bytecount; } catch { Console.WriteLine($"\tERROR:: Failed to read sector list header for sector at index {i}"); return(false); } int overall_sector_number = track.track_number * _sectors_per_track + sect.number; string overall = $"({overall_sector_number}, ${overall_sector_number:x3})"; if (sect.status != 0) { Console.Write($"\tSector index={i}, num={sect.number} {overall}, flags="); if ((sect.status & (byte)SectorStatus.DELETED) != 0) { Console.Write("DELETED "); } if ((sect.status & (byte)SectorStatus.MISSING_DATA) != 0) { Console.Write("MISSING_DATA "); } if ((sect.status & (byte)SectorStatus.EXTENDED) != 0) { Console.Write("EXTENDED "); } if ((sect.status & (byte)SectorStatus.FDC_CRC_ERROR) != 0) { Console.Write("CRC_ERROR "); } if ((sect.status & (byte)SectorStatus.FDC_LOSTDATA_ERROR) != 0) { Console.Write("LOSTDATA_ERROR"); } if ((sect.status & (byte)SectorStatus.FDC_DATAREQ_PENDING) != 0) { Console.Write("DATAREQ_PENDING"); } Console.WriteLine(); if ((sect.status & ~(byte)(SectorStatus.DELETED | SectorStatus.MISSING_DATA | SectorStatus.EXTENDED | SectorStatus.FDC_CRC_ERROR | SectorStatus.FDC_DATAREQ_PENDING | SectorStatus.FDC_LOSTDATA_ERROR)) != 0) { Console.WriteLine($"\tWARNING:: Unknown sector status flag 0x{sect.status:X2}"); } } if (sect.number > _sectors_per_track) { Console.WriteLine($"\tWARNING:: Sector index={i}, number={sect.number} > {_sectors_per_track}"); } if (sect.number == 0) { Console.WriteLine($"\tWARNING:: Sector index={i} has sector #0"); } if (sect.position >= ANGULAR_UNIT_COUNT) { Console.WriteLine($"\tWARNING:: Sector index={i}, num={sect.number} {overall}, angular position {sect.position} > {ANGULAR_UNIT_COUNT - 1}"); } // See if this is a duplicate foreach (var s in track.sectors) { if (s.number == sect.number) { Console.WriteLine($"\tDUPLICATE sector #{sect.number:D2} {overall}"); break; } } // Add to the list track.sectors.Add(sect); } Console.WriteLine($"\tRead {track.sectors.Count} sector headers for track {track.track_number}"); // Report on any missing sectors for (int i = 1; i <= _sectors_per_track; i++) { if (track.sectors.Find(x => x.number == i) == null) { Console.WriteLine($"\tMISSING sector #{i}"); } } return(true); }