private PhysicalContents Analyse() { PhysicalContents _contents = new PhysicalContents(); byte[] contents = File.ReadAllBytes(_filename); int bytesPerSector = contents[11] + (contents[12] << 8); int sectorsPerTrack = contents[24] + (contents[25] << 8); int sides = contents[26] + (contents[27] << 8); byte diskFormat = contents[21]; int trackSize = bytesPerSector * sectorsPerTrack; int numTracks = contents.Length / (trackSize * sides); for (int trk = 0; trk < numTracks; trk++) { TrackInfo info = new TrackInfo(); for (int side = 0; side < sides; side++) { TrackSide ts = new TrackSide(); for (int sector = 0; sector < sectorsPerTrack; sector++) { SectorInfo sec = new SectorInfo(); sec.contents = new byte[bytesPerSector]; int index = (((trk * sides) + side) * trackSize) + (sector * bytesPerSector); Array.Copy(contents, index, sec.contents, 0, bytesPerSector); ts.sectors.Add(sec); } info.sides.Add(ts); } _contents.tracks.Add(info); } FillPhysicalDefaults(_contents, bytesPerSector, diskFormat); return(_contents); }
private PhysicalContents Analyze() { PhysicalContents _contents = new PhysicalContents(); byte[] contents = File.ReadAllBytes(_filename); int NumTrackBlocks = contents.Length / 0x2B00; _contents.diskformat = contents[0x08]; bool DS = ((_contents.diskformat & 1) == 1); for (int i = 0; i < NumTrackBlocks; i++) { TrackInfo trackInfo = new TrackInfo(); for (int j = 0; j < 2; j++) { TrackSide trackside = new TrackSide(); if (!DS || j == 0) { trackInfo = new TrackInfo(); trackInfo.sides = new List <TrackSide>(); _contents.tracks.Add(trackInfo); } trackInfo.sides.Add(trackside); int PhysTrack = DS ? i : i / 2; int PhysHead = DS ? j : 0; trackInfo.sides[PhysHead] = trackside; trackside.physicalTrackNr = PhysTrack; trackside.HeadNr = PhysHead; trackside.sectors = new List <SectorInfo>(); long adr = (i * 0x2B00) + j * 0x180; trackside.diskformat = contents[adr + 0x08]; int Sectors = contents[adr + 0x09]; trackside.flag = contents[adr + 0x0A]; trackside.gaps = new Gap[5]; for (int k = 0; k < 5; k++) { trackside.gaps[k] = new Gap(((contents[adr + (k * 2) + 0x11]) << 8) + (contents[adr + (k * 2) + 0x10]), contents[adr + k + 0x0B]); } long dataAddr = (i * 0x2B00) + 0x300 + (j * 0x1400); long sectOffset = 0; for (int sect = 0; sect < Sectors; sect++) { SectorInfo sectInfo = AnalyzeSector(contents, dataAddr + sectOffset, adr, sect); sectOffset += sectInfo.contents.Length; trackside.sectors.Add(sectInfo); } } } return(_contents); }
private PhysicalContents Analyze() { PhysicalContents _contents = new PhysicalContents(); byte[] contents = File.ReadAllBytes(_filename); int numTracks = contents[0x01]; int trackSize = contents[0x02] + (contents[0x03] << 8); bool SSOnly = (contents[0x04] & 0x10) == 0x10; // ignore the rest for now for (int t = 0; t < numTracks; t++) { TrackInfo track = new TrackInfo(); for (int s = 0; s < 2; s++) { TrackSide side = new TrackSide(); side.physicalTrackNr = t; side.HeadNr = s; int headerOffset = ((t * 2) + s) * trackSize + 0x10; AnalyzeTrack(side, contents, headerOffset, trackSize); track.sides.Add(side); } _contents.tracks.Add(track); } TrackSide track0 = _contents.tracks[0].sides[0]; _contents.diskformat = 0xFC; foreach (SectorInfo sector in track0.sectors) { if (sector.sector == 1) // found the boot { _contents.diskformat = sector.contents[0x15]; } } if (SSOnly) { _contents.diskformat |= 0x01; // force double sided } if (numTracks > 42) { _contents.diskformat &= 0xFB; // force 80 tracks } foreach (TrackInfo track in _contents.tracks) { foreach (TrackSide side in track.sides) { side.diskformat = _contents.diskformat; } } return(_contents); }
private void FillPhysicalDefaults(PhysicalContents _contents, int bytesPerSector, byte diskFormat) { byte[] sizecodes = new byte[] { 0, 1, 0, 2, 0, 0, 0, 3 }; _contents.diskformat = diskFormat; byte trk = 0; byte head = 0; byte sec = 1; foreach (TrackInfo track in _contents.tracks) { head = 0; foreach (TrackSide side in track.sides) { sec = 1; foreach (SectorInfo sector in side.sectors) { sector.dam = 0xFB; sector.gapFillers = new byte[2] { 0x4E, 0x4E }; sector.gaps = new int[2] { 22, 54 }; sector.head = head; sector.track = trk; sector.sector = sec; sector.sizecode = sizecodes[((bytesPerSector / 128) - 1)]; sector.calcHeaderCRC = CalcCRC16(new byte[] { 0xA1, 0xA1, 0xA1, 0xFE, trk, head, sec, sector.sizecode }, 0, 8); ushort dataCRC = CalcCRC16(new byte[] { 0xA1, 0xA1, 0xA1, 0xFB }, 0, 4); CalcCRC16(sector.contents, 0, bytesPerSector, ref dataCRC); sector.calcDataCRC = dataCRC; sec++; } side.physicalTrackNr = trk; side.HeadNr = head; int[] gapsizes = new int[] { 80, 50, 22, 54, 598 }; for (int g = 0; g < 5; g++) { side.gaps[g] = new Gap(gapsizes[g], 0x4E); } side.flag = 1; side.diskformat = diskFormat; head++; } trk++; } }
private void WritePDI(string filename) { PhysicalContents _contents = Contents.physical; byte[] buffer = new byte[0x180]; FileStream outputStream = new FileStream(filename, FileMode.Create); BinaryWriter writer = new BinaryWriter(outputStream); int numTracks = _contents.tracks.Count; int numSides = (_contents.diskformat & 1) + 1; if ((numSides == 1) && ((numTracks % 2) == 1)) // we can't have an odd track { TrackInfo track = new TrackInfo(); track.sides.Add(new TrackSide()); _contents.tracks.Add(track); } int numBlocks = numTracks * numSides; for (int block = 0; block < numBlocks; block += 2) { for (int i = 0; i < 2; i++) { Array.Clear(buffer, 0, 0x180); int track = (block + i) / numSides; int side = (block + i) % numSides; TrackSide ts = _contents.tracks[track].sides[side]; Array.Copy(new ASCIIEncoding().GetBytes("PDI-MSX"), 0, buffer, 0, 7); buffer[0x07] = 0x20; buffer[0x08] = _contents.diskformat; buffer[0x09] = (byte)ts.sectors.Count; buffer[0x0a] = (byte)1; for (int g = 0; g < 5; g++) { buffer[0x0b + g] = (byte)ts.gaps[g].Filler; buffer[0x10 + (g * 2)] = (byte)(ts.gaps[g].Size & 0xFF); buffer[0x11 + (g * 2)] = (byte)((ts.gaps[g].Size & 0xFF00) >> 8); } int count = 0; foreach (SectorInfo sector in ts.sectors) { buffer[0x1A + count] = sector.track; buffer[0x38 + count] = sector.head; buffer[0x56 + count] = sector.sector; buffer[0x74 + count] = sector.sizecode; buffer[0x92 + count] = (byte)((sector.imgHeaderCRC & 0xFF00) >> 8); buffer[0xb0 + count] = (byte)(sector.imgHeaderCRC & 0xFF); buffer[0xce + count] = sector.errorCode; int dataSize = SectorSizeFromCode(sector.sizecode); int realSize = 0; if (sector.contents.Length != dataSize) { realSize = sector.contents.Length; if (realSize == 0) { realSize = 1; // PDI doesn't support a zero size sector. } } buffer[0xec + (2 * count)] = (byte)(realSize & 0xFF); buffer[0xed + (2 * count)] = (byte)((realSize & 0xFF00) >> 8); buffer[0x128 + (2 * count)] = (byte)(sector.imgDataCRC & 0xFF); buffer[0x129 + (2 * count)] = (byte)((sector.imgDataCRC & 0xFF00) >> 8); count++; } writer.Write(buffer, 0, 0x180); } for (int i = 0; i < 2; i++) { int track = (block + i) / numSides; int side = (block + i) % numSides; TrackSide ts = _contents.tracks[track].sides[side]; int byteCount = 0; foreach (SectorInfo sector in ts.sectors) { writer.Write(sector.contents, 0, sector.contents.Length); byteCount += sector.contents.Length; } WriteBytes(writer, 0xF7, (0x1400 - byteCount)); } } }