public override void WriteSector(int track, int head, int sector, byte[] buffer) { int sectorLength = 0; int offset = GetSectorOffset(track, head, sector, ref sectorLength); if (buffer.Length != sectorLength) { throw new IOException(); } if (offset != 0 && sectorLength != 0) { byte[] crc = Crc16.ComputeChecksumBytes(0xE295, buffer); WriteBytes(offset, buffer); WriteByte(offset + buffer.Length, crc[1]); WriteByte(offset + buffer.Length + 1, crc[0]); } }
/// <summary> /// Create DMK basic disk structure on disk image /// </summary> private void LowLevelFormat() { // Prepare blank sector data byte[] sectorData = new byte[this.PhysicalSectorSize]; byte[] sectorCRC = Crc16.ComputeChecksumBytes(0xe295, sectorData); for (int track = 0; track < this.PhysicalTracks; track++) { for (int head = 0; head < this.PhysicalHeads; head++) { byte[] trackData = new byte[this.trackSize]; // First, create the IDAM table byte[] idamtable = new byte[128]; for (int i = 0, sectorOffset = 0x80ab; i < this.PhysicalSectors; i++, sectorOffset += 338) { idamtable[i * 2] = (byte)(sectorOffset & 0xff); idamtable[(i * 2) + 1] = (byte)(sectorOffset >> 8); } Array.Copy(idamtable, 0, trackData, 0, idamtable.Length); // Now lets make the track Array.Copy(new byte[32].Initialize(0x4e), 0, trackData, idamtable.Length, 32); // Lets create each sector int interleavedSector = 1; for (int sector = 1; sector < this.PhysicalSectors; sector++) { // Sector Preamble part byte[] sectorPreamble = new byte[56].Initialize(0x4e); Array.Copy(new byte[0x08], 0, sectorPreamble, 0, 0x08); Array.Copy(new byte[0x03].Initialize(0xa1), 0, sectorPreamble, 0x08, 3); byte[] sectorControl = new byte[] { 0xfe, (byte)track, (byte)head, (byte)sector, 0x01 }; Array.Copy(sectorControl, 0, sectorPreamble, 0x0b, 5); byte[] sectorControlCRC = Crc16.ComputeChecksumBytes(0xcdb4, sectorControl); sectorPreamble[0x10] = sectorControlCRC[1]; sectorPreamble[0x11] = sectorControlCRC[0]; Array.Copy(new byte[12], 0, sectorPreamble, 0x28, 12); Array.Copy(new byte[3].Initialize(0xa1), 0, sectorPreamble, 0x34, 3); sectorPreamble[0x37] = 0xfb; // Sector Post-amble part byte[] sectorPostamble = new byte[26].Initialize(0x4e); sectorPostamble[0] = sectorCRC[1]; sectorPostamble[1] = sectorCRC[0]; // Write the parts to the track data int trackOffset = idamtable.Length + ((interleavedSector - 1) * 338) + 32; Array.Copy(sectorPreamble, 0, trackData, trackOffset, sectorPreamble.Length); Array.Copy(sectorData, 0, trackData, trackOffset + 56, sectorData.Length); Array.Copy(sectorPostamble, 0, trackData, trackOffset + 312, sectorPostamble.Length); // Calculate next interleaved sector position interleavedSector += this.Interleave; if (interleavedSector > this.PhysicalSectors) { interleavedSector -= this.PhysicalSectors; } if (interleavedSector < this.Interleave) { interleavedSector++; } } // Write out the track this.WriteBytes(this.HeaderLength + (track * this.PhysicalHeads * this.trackSize) + (head * this.trackSize), trackData); } } }
/// <summary> /// Initializes a new instance of the <see cref="Crc16CalculatorStream"/> class. /// </summary> /// <param name="stream">Base stream to perform operations on</param> /// <param name="length">Maximum number of stream bytes to process</param> /// <param name="leaveOpen">Leave the base stream open once operations are complete</param> /// <param name="crc16">Initial crc register value</param> public Crc16CalculatorStream(System.IO.Stream stream, long length, bool leaveOpen, Crc16 crc16) : this(leaveOpen, length, stream, crc16) { if (length < 0) { throw new ArgumentException("length"); } }
/// <summary> /// Initializes a new instance of the <see cref="Crc16CalculatorStream"/> class. /// </summary> /// <param name="leaveOpen">Leave the base stream open once operations are complete</param> /// <param name="length">Maximum number of stream bytes to process</param> /// <param name="stream">Base stream to perform operations on</param> /// <param name="crc16">Initial crc register value</param> private Crc16CalculatorStream(bool leaveOpen, long length, System.IO.Stream stream, Crc16 crc16) : base() { this.innerStream = stream; this.crc16 = crc16 ?? new Crc16(); this.lengthLimit = length; this.leaveOpen = leaveOpen; }
private int GetSectorOffset(int track, int head, int sector, ref int sectorsize) { int offset = 0; sectorsize = 0; int trackoffset = this.HeaderLength + (track * this.PhysicalHeads * this.trackLength) + (head * this.trackLength); int idamOffset = 0; int i = 0; byte[] idam = new byte[0]; // Search for sector for (i = 0; i < DMK_TOK_LEN; i++) { idamOffset = ((this.ReadByte(trackoffset + (i * 2) + 1) << 8) + this.ReadByte(trackoffset + (i * 2))) & 0x3fff; if (idamOffset == 0) { i = DMK_TOK_LEN; break; } if ((idamOffset + DMK_IDAM_LENGTH) > trackLength) { continue; } int idamCRC = (this.ReadByte(trackoffset + idamOffset + 5) << 8) + this.ReadByte(trackoffset + idamOffset + 6); idam = this.ReadBytes(trackoffset + idamOffset, DMK_IDAM_LENGTH - 2); int calcCRC = Crc16.ComputeChecksum(0xCDB4, idam); if (idamCRC == calcCRC) { if (sector == idam[3] && track == idam[1] && head == idam[2]) { break; } } } if (i >= DMK_TOK_LEN) { throw new SectorNotFoundException(); } int state = 0; int offs = idamOffset + DMK_IDAM_LENGTH; for (i = 0; i < DMK_DATA_GAP; i++) { if ((i + offs) > trackLength) { throw new SectorNotFoundException(); } if (this.ReadByte(trackoffset + offs + i) == 0xA1) { state++; } else if ((this.ReadByte(trackoffset + offs + i) == 0xFB) && state > 0) { break; } else { state = 0; } } if (i >= DMK_DATA_GAP) { throw new SectorNotFoundException(); } offs += i + 1; int sec_len = 128 << idam[4]; if ((offs + sec_len) > trackLength) { throw new SectorNotFoundException(); } offset = trackoffset + offs; sectorsize = sec_len; return(offset); }
public override void CreateDisk(string filename, int tracks, int heads, int sectors, int sectorsize, byte filldata) { if (this.baseStream != null) { this.baseStream.Close(); this.baseStream = null; } this.filename = filename; try { this.baseStream = File.Open(this.filename, FileMode.Create, FileAccess.ReadWrite, FileShare.Read); physicalTracks = tracks; physicalHeads = heads; physicalSectors = sectors; physicalSectorSize = sectorsize; trackLength = DMK_DEFAULT_TRACK_LENGTH; byte[] sectorData = new byte[this.PhysicalSectorSize].Initialize(filldata); byte[] sectorCRC = Crc16.ComputeChecksumBytes(0xE295, sectorData); byte[] header = new byte[] { 0, (byte)this.PhysicalTracks, (byte)(this.trackLength & 0xff), (byte)(this.trackLength >> 8), (byte)(((this.PhysicalHeads > 1) ? 0 : 1) << 4), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; headerLength = header.Length; this.baseStream.Write(header, 0, HeaderLength); for (int t = 0; t < PhysicalTracks; t++) { for (int h = 0; h < PhysicalHeads; h++) { byte[] trackData = new byte[trackLength].Initialize(0x4E); for (int i = 0; i < 128; i++) { trackData[i] = 0; } int[] sPointers = new int[PhysicalSectors]; for (int s = 0, i = 0x80AB; s < PhysicalSectors; s++, i += 338) { sPointers[s] = i; trackData[2 * s] = (byte)(i & 0xff); trackData[2 * s + 1] = (byte)(i >> 8); } int SectorID = 1; for (int s = 0; s < PhysicalSectors; s++) { int sectorOffset = (sPointers[SectorID - 1] & 0x3fff) - 11; for (int i = 0; i < 8; i++) { trackData[sectorOffset++] = 0; } for (int i = 0; i < 3; i++) { trackData[sectorOffset++] = 0xA1; } byte[] sectorControl = new byte[] { 0xFE, (byte)t, (byte)h, (byte)(s + 1), (byte)((PhysicalSectorSize / 128) >> 1) }; byte[] sectorControlCRC = Crc16.ComputeChecksumBytes(0xCDB4, sectorControl); Array.Copy(sectorControl, 0, trackData, sectorOffset, 5); sectorOffset += 5; trackData[sectorOffset++] = sectorControlCRC[1]; trackData[sectorOffset++] = sectorControlCRC[0]; sectorOffset += 22; for (int i = 0; i < 12; i++) { trackData[sectorOffset++] = 0; } for (int i = 0; i < 3; i++) { trackData[sectorOffset++] = 0xA1; } trackData[sectorOffset++] = 0xFB; Array.Copy(sectorData, 0, trackData, sectorOffset, PhysicalSectorSize); sectorOffset += PhysicalSectorSize; trackData[sectorOffset++] = sectorCRC[1]; trackData[sectorOffset++] = sectorCRC[0]; if (s < PhysicalSectors - 1) { SectorID++; SectorID += interleave; if (SectorID > PhysicalSectors) { SectorID -= PhysicalSectors; } while (trackData[sPointers[SectorID - 1] & 0x3FFF] == 0xFE) { SectorID++; } if (SectorID > PhysicalSectors) { throw new IOException(); } } } this.baseStream.Write(trackData, 0, trackData.Length); } } } catch (IOException) { MessageBox.Show(string.Format(MainForm.ResourceManager.GetString("DiskImageBase_FileOpenError", MainForm.CultureInfo), this.filename), MainForm.ResourceManager.GetString("DiskImageBase_FileOpenErrorCaption", MainForm.CultureInfo), MessageBoxButtons.OK, MessageBoxIcon.Error); this.filename = string.Empty; } }