public static CHSVolume Load(String source, Byte[] data) { if (!IsValid(data)) { return(null); } Int32 z1 = 21, z2 = 19, z3 = 18, z4 = 17; Int32 nt = 35; if ((data.Length == 196608) || (data.Length == 197376)) { nt = 40; } else if ((data.Length == 205312) || (data.Length == 206114)) { nt = 42; } else if ((data.Length == 176640) || (data.Length == 177330)) { z2 = 20; } CHSVolume V = new CHSVolume(source, source, 256, 1, nt, 0, 1, 0); for (Int32 t = 1; t <= 17; t++) { V[t, 0] = new Track(z1); } for (Int32 t = 18; t <= 24; t++) { V[t, 0] = new Track(z2); } for (Int32 t = 25; t <= 30; t++) { V[t, 0] = new Track(z3); } for (Int32 t = 31; t <= nt; t++) { V[t, 0] = new Track(z4); } Int32 p = 0; Int32 q = (data.Length == V.BlockCount * 257) ? V.BlockCount * 256 : -1; for (Int32 t = 1; t <= nt; t++) { Track T = V[t, 0]; for (Int32 s = 0; s < T.Length; s++) { Sector S = new Sector(s, 256, data, p); p += 256; if (q != -1) { S.ErrorCode = data[q++]; } T[s] = S; } } return(V); }
public static CHSVolume Load(String source, Byte[] data) { if (!IsValid(data)) { return(null); } Int32 z1 = 29, z2 = 27, z3 = 25, z4 = 23; Int32 nt = 77; CHSVolume V = new CHSVolume(source, source, 256, 1, nt, 0, 1, 0); for (Int32 t = 1; t <= 39; t++) { V[t, 0] = new Track(z1); } for (Int32 t = 40; t <= 53; t++) { V[t, 0] = new Track(z2); } for (Int32 t = 54; t <= 64; t++) { V[t, 0] = new Track(z3); } for (Int32 t = 65; t <= nt; t++) { V[t, 0] = new Track(z4); } Int32 p = 0; Int32 q = (data.Length == V.BlockCount * 257) ? V.BlockCount * 256 : -1; for (Int32 t = 1; t <= nt; t++) { Track T = V[t, 0]; for (Int32 s = 0; s < T.Length; s++) { Sector S = new Sector(s, 256, data, p); p += 256; if (q != -1) { S.ErrorCode = data[q++]; } T[s] = S; } } return(V); }
public CBMDOS(CHSVolume volume) { mVol = volume; mDirTrack = (volume.MaxCylinder <= 42) ? 18 : 39; Byte ver = volume[mDirTrack, 0, 0][2]; if (ver == 1) { mType = "CBMDOS1"; } else if (ver == 65) { mType = "CBMDOS2"; } else if (ver == 67) { mType = (volume.MaxCylinder > 77) ? "CBMDOS2.7" : "CBMDOS2.5"; } mBlocksFree = CountFreeBlocks(); }
private Int32 SPIC; // sectors per (perfect) interleave cycle public InterleavedVolume(CHSVolume volume, Int32 interleave, Int32 headSkew, Int32 cylSkew, Int32 start) { if (interleave < 0) { throw new ArgumentOutOfRangeException("interleave"); } if (interleave == 0) { interleave = 1; } mVol = volume; mSource = String.Format("{0} [I={1:D0},{2:D0},{3:D0}@{4:D0}]", volume.Source, interleave, headSkew, cylSkew, start); mInfo = String.Format("{0}\nInterleave={1:D0},HeadSkew={2:D0},CylSkew={3:D0},Start={4:D0}", volume.Info, interleave, headSkew, cylSkew, start); mInterleave = interleave; mHeadSkew = headSkew; mCylSkew = cylSkew; mStart = start; SPT = mVol.MaxSector(0, 0) - mVol.MinSector(0, 0) + 1; TPC = mVol.MaxHead - mVol.MinHead + 1; SPIC = SPT / GCD(SPT, interleave); }
// Load ImageDisk .IMD image file public static CHSVolume Load(String source, Byte[] data) { Int32 p, n; Int32[] SS = new Int32[0]; // determine disk geometry Int32 nc = -1; Int32 nh = -1; Int32 ss = -1; for (p = 0; data[p++] != 0x1a;) { ; // skip ASCII header } while (p < data.Length) { // track header p++; // skip mode Int32 c = data[p++]; // cylinder num if (c > nc) { nc = c; } Int32 h = data[p++]; // head num Boolean cm = ((h & 0x80) != 0); Boolean hm = ((h & 0x40) != 0); h &= 0x3f; if (h > nh) { nh = h; } Int32 ns = data[p++]; // sectors ss = data[p++]; // sector size ss = (ss == 0xff) ? -1 : (128 << ss); p += ns; // skip sector numbering map if (cm) { p += ns; // skip cylinder map } if (hm) { p += ns; // skip head map } SS = new Int32[ns]; if (ss == -1) // sector size table { for (Int32 i = 0; i < ns; i++) { n = data[p++]; SS[i] = n + (data[p++] << 8); } } // sector data for (Int32 s = 0; s < ns; s++) { switch (data[p++]) // sector data type { case 1: case 3: case 5: case 7: p += (ss == -1) ? SS[s] : ss; break; case 2: case 4: case 6: case 8: p++; break; } } } // read image (use last track's largest sector as default volume sector size) if (ss == -1) { for (Int32 i = 0; i < SS.Length; i++) { if (SS[i] > ss) { ss = SS[i]; } } } for (p = 0; data[p] != 0x1a; p++) { ; // count size of ASCII header } StringBuilder buf = new StringBuilder(p); for (p = 0; data[p] != 0x1a; p++) { buf.Append((Char)data[p]); } p++; // skip 0x1a header terminator CHSVolume image = new CHSVolume(source, buf.ToString(), ss, ++nc, ++nh); while (p < data.Length) { // track header p++; // skip mode Int32 c = data[p++]; // cylinder num Int32 h = data[p++]; // head num Boolean cm = ((h & 0x80) != 0); Boolean hm = ((h & 0x40) != 0); h &= 0x3f; Int32 ns = data[p++]; // sectors Track t = new Track(ns); ss = data[p++]; // sector size ss = (ss == 0xff) ? -1 : (128 << ss); Int32[] SM = new Int32[ns]; for (Int32 i = 0; i < ns; i++) { SM[i] = data[p++]; // sector numbering map } // TODO: don't skip these if (cm) { p += ns; // skip cylinder map } if (hm) { p += ns; // skip head map } SS = new Int32[ns]; if (ss == -1) // sector size table { for (Int32 i = 0; i < ns; i++) { n = data[p++]; SS[i] = n + (data[p++] << 8); } } // sector data for (Int32 s = 0; s < ns; s++) { switch (data[p++]) // sector data type { case 1: case 3: case 5: case 7: n = (ss == -1) ? SS[s] : ss; t[s] = new Sector(SM[s], n, data, p); p += n; break; case 2: case 4: case 6: case 8: n = (ss == -1) ? SS[s] : ss; t[s] = new Sector(SM[s], n, data[p++]); break; } } image[c, h] = t; } return(image); }
public static CHSVolume Load(String source, Byte[] data) { // header if (!HasHeader(data)) { return(null); } Int32 p = 0; Byte b = data[p++]; Byte b2 = data[p++]; Boolean adc = false; if ((b == (Byte)'t') && (b2 == (Byte)'d')) { adc = true; } else if ((b != (Byte)'T') || (b2 != (Byte)'D')) { Debug.WriteLine(1, "File does not appear to be TeleDisk format (no TD header)"); return(null); } if ((b = data[p++]) != 0) { Debug.WriteLine(1, "Multi-file images not supported (volume sequence is {0:D0}, expect 0)", b); return(null); } p++; // skip check signature byte p++; // skip version number byte p++; // skip source density byte p++; // skip drive type byte Int32 stepping = data[p++]; p++; // skip dos mode byte Int32 nh = data[p++]; // number of sides p += 2; // header CRC if (adc) { LZSS.Decompressor D = new LZSS.Decompressor(data, p); data = D.GetBytes(); p = 0; } // comment block Int32 n; String info = source; if ((stepping & 0x80) != 0) { if (p + 10 >= data.Length) { return(null); } p += 2; // CRC n = Buffer.GetUInt16L(data, ref p); p += 6; // date/time StringBuilder buf = new StringBuilder(n); for (Int32 i = 0; i < n; i++) { b = Buffer.GetByte(data, ref p); buf.Append((b == 0) ? '\n' : (Char)b); } info = buf.ToString(); } // determine disk geometry Int32 q = p; Int32 nc = -1; Int32[] ct = new Int32[256]; while (p < data.Length) { // track header Int32 ns = Buffer.GetByte(data, ref p); // number of sectors on this track if (ns == 255) { break; } Int32 c = Buffer.GetByte(data, ref p) + 1; if (c > nc) { nc = c; } Int32 h = Buffer.GetByte(data, ref p) + 1; if (h > nh) { nh = h; } p++; // CRC // sectors for (Int32 s = 0; s < ns; s++) { // sector header p++; // skip cylinder id p++; // skip side id p++; // skip sector id b = Buffer.GetByte(data, ref p); // sector size ct[b]++; Byte f = Buffer.GetByte(data, ref p); // flags p++; // skip CRC if ((f & 0x30) != 0) { continue; } n = Buffer.GetUInt16L(data, ref p); p += n; } } Int32 ss = -1; n = 0; for (Int32 i = 0; i < 256; i++) { if (ct[i] > n) { n = ct[i]; ss = 128 << i; } } CHSVolume vol = new CHSVolume(source, source, ss, nc, nh); // track data p = q; while (p < data.Length) { // track header Int32 ns = Buffer.GetByte(data, ref p); // number of sectors on this track if (ns == 255) { break; } Int32 c = Buffer.GetByte(data, ref p); Int32 h = Buffer.GetByte(data, ref p); p++; // CRC Track T = new Track(ns); vol[c, h] = T; // sectors for (Int32 s = 0; s < ns; s++) { // sector header p++; // skip cylinder id p++; // skip side id Int32 id = Buffer.GetByte(data, ref p); // sector id n = 128 << Buffer.GetByte(data, ref p); // sector size Byte f = Buffer.GetByte(data, ref p); // flags p++; // skip CRC if ((f & 0x30) != 0) { continue; } Int32 l = Buffer.GetUInt16L(data, ref p) - 1; switch (Buffer.GetByte(data, ref p)) { case 0: T[s] = new Sector(id, n, data, p); p += n; break; case 1: T[s] = new Sector(id, n); q = 0; while (n > 0) { Int32 k = Buffer.GetUInt16L(data, ref p); b = Buffer.GetByte(data, ref p); b2 = Buffer.GetByte(data, ref p); for (Int32 i = 0; i < k; i++) { T[s][q++] = b; T[s][q++] = b2; n -= 2; } } break; case 2: T[s] = new Sector(id, n); q = 0; while (n > 0) { Int32 k = Buffer.GetByte(data, ref p); if (k == 0) { k = Buffer.GetByte(data, ref p); T[s].CopyFrom(data, p, q, k); p += k; q += k; n -= k; } else { k *= 2; Int32 z = Buffer.GetByte(data, ref p); for (Int32 i = 0; i < z; i++) { T[s].CopyFrom(data, p, q, k); q += k; n -= k; } p += k; } } break; } } } return(vol); }