/// <summary> /// Commits modified sector data back to the emulated disk. /// Intended to be called at the end of the sector / beginning of the next. /// </summary> private void CommitSector() { if (_pack == null) { return; } DiabloDiskSector sector = _pack.GetSector(_cylinder, _head, _sector); // Header (2 words data, 1 word cksum) for (int i = HeaderOffset + 1, j = 1; i < HeaderOffset + 3; i++, j--) { // actual data to be loaded from disk / cksum calculated sector.Header[j] = _sectorData[i].Data; } // Label (8 words data, 1 word cksum) for (int i = LabelOffset + 1, j = 7; i < LabelOffset + 9; i++, j--) { // actual data to be loaded from disk / cksum calculated sector.Label[j] = _sectorData[i].Data; } // sector data (256 words data, 1 word cksum) for (int i = DataOffset + 1, j = 255; i < DataOffset + 257; i++, j--) { // actual data to be loaded from disk / cksum calculated sector.Data[j] = _sectorData[i].Data; } }
public void Save(Stream imageStream) { for (int cylinder = 0; cylinder < _geometry.Cylinders; cylinder++) { for (int track = 0; track < _geometry.Tracks; track++) { for (int sector = 0; sector < _geometry.Sectors; sector++) { byte[] header = new byte[4]; // 2 words byte[] label = new byte[16]; // 8 words byte[] data = new byte[512]; // 256 words // // Bitsavers images have an extra word in the header for some reason. // We will follow this 'standard' when writing out. // TODO: should support different formats ("correct" raw, Alto CopyDisk format, etc.) // byte[] dummy = new byte[2]; imageStream.Write(dummy, 0, 2); DiabloDiskSector s = _sectors[cylinder, track, sector]; WriteWordBuffer(imageStream, s.Header); WriteWordBuffer(imageStream, s.Label); WriteWordBuffer(imageStream, s.Data); } } } }
public DiabloPack(DiabloDiskType type) { _diskType = type; _packName = null; _geometry = new DiskGeometry(type == DiabloDiskType.Diablo31 ? 203 : 406, 2, 12); _sectors = new DiabloDiskSector[_geometry.Cylinders, _geometry.Tracks, _geometry.Sectors]; }
public void Load(Stream imageStream, string path, bool reverseByteOrder) { _packName = path; for (int cylinder = 0; cylinder < _geometry.Cylinders; cylinder++) { for (int track = 0; track < _geometry.Tracks; track++) { for (int sector = 0; sector < _geometry.Sectors; sector++) { byte[] header = new byte[4]; // 2 words byte[] label = new byte[16]; // 8 words byte[] data = new byte[512]; // 256 words // // Bitsavers images have an extra word in the header for some reason. // ignore it. // TODO: should support different formats ("correct" raw, Alto CopyDisk format, etc.) // imageStream.Seek(2, SeekOrigin.Current); if (imageStream.Read(header, 0, header.Length) != header.Length) { throw new InvalidOperationException("Short read while reading sector header."); } if (imageStream.Read(label, 0, label.Length) != label.Length) { throw new InvalidOperationException("Short read while reading sector label."); } if (imageStream.Read(data, 0, data.Length) != data.Length) { throw new InvalidOperationException("Short read while reading sector data."); } if (reverseByteOrder) { SwapBytes(header); SwapBytes(label); SwapBytes(data); } _sectors[cylinder, track, sector] = new DiabloDiskSector(header, label, data); } } } if (imageStream.Position != imageStream.Length) { throw new InvalidOperationException("Extra data at end of image file."); } }
private void LoadSector() { if (_pack == null) { return; } // // Pull data off disk and pack it into our faked-up sector. // Note that this data is packed in in REVERSE ORDER because that's // how it gets written out and it's how the Alto expects it to be read back in. // DiabloDiskSector sector = _pack.GetSector(_cylinder, _head, _sector); // Header (2 words data, 1 word cksum) for (int i = HeaderOffset + 1, j = 1; i < HeaderOffset + 3; i++, j--) { // actual data to be loaded from disk / cksum calculated _sectorData[i] = new DataCell(sector.Header[j], CellType.Data); } ushort checksum = CalculateChecksum(_sectorData, HeaderOffset + 1, 2); _sectorData[HeaderOffset + 3].Data = checksum; Log.Write(LogType.Verbose, LogComponent.DiskController, "Header checksum for C/H/S {0}/{1}/{2} is {3}", _cylinder, _head, _sector, Conversion.ToOctal(checksum)); // Label (8 words data, 1 word cksum) for (int i = LabelOffset + 1, j = 7; i < LabelOffset + 9; i++, j--) { // actual data to be loaded from disk / cksum calculated _sectorData[i] = new DataCell(sector.Label[j], CellType.Data); } checksum = CalculateChecksum(_sectorData, LabelOffset + 1, 8); _sectorData[LabelOffset + 9].Data = checksum; Log.Write(LogType.Verbose, LogComponent.DiskController, "Label checksum for C/H/S {0}/{1}/{2} is {3}", _cylinder, _head, _sector, Conversion.ToOctal(checksum)); // sector data (256 words data, 1 word cksum) for (int i = DataOffset + 1, j = 255; i < DataOffset + 257; i++, j--) { // actual data to be loaded from disk / cksum calculated _sectorData[i] = new DataCell(sector.Data[j], CellType.Data); } checksum = CalculateChecksum(_sectorData, DataOffset + 1, 256); _sectorData[DataOffset + 257].Data = checksum; Log.Write(LogType.Verbose, LogComponent.DiskController, "Data checksum for C/H/S {0}/{1}/{2} is {3}", _cylinder, _head, _sector, Conversion.ToOctal(checksum)); }