Пример #1
0
        protected byte[] GetChecksum(SectorInfo sector, bool header)
        {
            ushort crc  = 0;
            int    mask = (sector.errorCode & 0x18) | (header ? 1 : 0);

            switch (mask)
            {
            case 0:
            case 0x18:
                crc = sector.calcDataCRC;
                break;

            case 1:
            case 0x9:
                crc = sector.calcHeaderCRC;
                break;

            case 0x8:
                crc = sector.imgDataCRC;
                break;

            case 0x19:
                crc = sector.imgHeaderCRC;
                break;
            }
            byte[] crcBytes = BitConverter.GetBytes(crc);
            return(crcBytes);
        }
Пример #2
0
 protected int WriteChecksum(BinaryWriter writer, SectorInfo sector, bool header)
 {
     byte[] crcBytes = GetChecksum(sector, header);
     writer.Write(crcBytes[1]);
     writer.Write(crcBytes[0]);  // in Big Endian
     return(2);
 }
Пример #3
0
        private int FindDataMark(byte[] contents, SectorInfo sector, int offset, out int markPos)
        {
            byte mark         = 0xfb;
            int  pos          = -1;
            bool done         = false;
            int  searchOffset = offset;

            do
            {
                pos  = FindMark(contents, searchOffset, dataMark, 0, out markPos);
                mark = contents[searchOffset + markPos + 3];
                if ((mark & 0xfc) == 0xf8)
                {
                    done = true;
                    if (mark == 0xf8)
                    {
                        sector.errorCode |= 0x20;   // dam deleted
                    }
                }
                else
                {
                    searchOffset += (markPos + 4);
                }
            } while (!done);
            markPos += (searchOffset - offset);
            return(pos + (searchOffset - offset));
        }
Пример #4
0
        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);
        }
Пример #5
0
        private bool UpdateCRCs(TrackSide track, byte[] trackData, List <int> dataStarts)
        {
            Dictionary <SectorInfo, bool> sectorsToUpdate = new Dictionary <SectorInfo, bool>();
            int  sectNum = 0;
            int  numSect = track.sectors.Count;
            bool succes  = true;

            foreach (SectorInfo sector in track.sectors)
            {
                int  sectorOffset = 1;
                bool done         = false;
                int  SectorSize   = SectorSizeFromCode(sector.sizecode);
                bool overlapCRC   = (sector.contents.Length != SectorSize) && ((sector.errorCode & 0x18) == 0);
                if ((overlapCRC) || (sectorsToUpdate.ContainsKey(sector)))
                {
                    ushort crc = CalcCRC16(trackData, dataStarts[sectNum] - 4, SectorSize + 4);
                    if (overlapCRC)
                    {
                        while (!done)
                        {
                            SectorInfo nextSector = track.sectors[sectNum + sectorOffset];
                            if ((SectorSize + dataStarts[sectNum]) < dataStarts[sectNum + sectorOffset] + nextSector.contents.Length)   // falls within this sector?
                            {
                                if ((SectorSize + dataStarts[sectNum]) >= dataStarts[sectNum + sectorOffset])
                                {
                                    sectorsToUpdate[nextSector] = true;
                                }
                                else
                                {
                                    // to do, use gap info
                                    succes = false;
                                }
                                done = true;
                            }
                            else
                            {
                                sectorOffset++;
                                if ((sectNum + sectorOffset) == numSect)    // lead out gap
                                {
                                    done = true;
                                }
                            }
                        }
                    }
                    if (succes)
                    {
                        trackData[dataStarts[sectNum] + SectorSize]     = (byte)((crc & 0xFF00) >> 8);
                        trackData[dataStarts[sectNum] + SectorSize + 1] = (byte)((crc & 0xFF));
                    }
                }
                sectNum++;
            }
            return(succes);
        }
Пример #6
0
        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);
        }
Пример #7
0
        public void WriteExtractedSector(string filename, int num, SectorInfo sector)
        {
            string outputName = filename;

            if (num > 0)
            {
                outputName += num.ToString();
            }
            FileStream   outputStream = new FileStream(outputName, FileMode.Create);
            BinaryWriter writer       = new BinaryWriter(outputStream);

            writer.Write(sector.contents, 0, SectorSizeFromCode(sector.sizecode));
            writer.Close();
        }
Пример #8
0
        private void FixOverlappedGap(TrackSide track)
        {
            bool done       = false;
            int  numSectors = track.sectors.Count;

            for (int i = 0; !done && (i < numSectors); i++)
            {
                SectorInfo sector = track.sectors[i];
                if (sector.contents.Length != SectorSizeFromCode(sector.sizecode))
                {
                    track.gaps[3].Size   = sector.gaps[1];
                    track.gaps[3].Filler = sector.gapFillers[1];
                    if (track.sectors.Count > (i + 1))
                    {
                        track.gaps[2].Size   = track.sectors[i + 1].gaps[0];
                        track.gaps[2].Filler = track.sectors[i + 1].gapFillers[0];
                    }
                    done = true;
                }
            }
        }
Пример #9
0
        private SectorInfo AnalyzeSector(byte[] contents, long dataOffset, long adr, int sect)
        {
            SectorInfo sectorData = new SectorInfo();

            sectorData.track    = contents[adr + 0x1A + sect];
            sectorData.head     = contents[adr + 0x38 + sect];
            sectorData.sector   = contents[adr + 0x56 + sect];
            sectorData.sizecode = contents[adr + 0x74 + sect];
            int sectsize = SectorSizeFromCode(sectorData.sizecode);

            sectorData.imgHeaderCRC = (ushort)(((contents[adr + 0x92 + sect] << 8)) + contents[adr + 0xb0 + sect]);
            sectorData.errorCode    = contents[adr + 0xce + sect];
            int realsize     = contents[adr + 0xec + (sect * 2)] + ((contents[adr + 0xed + (sect * 2)]) << 8);
            int sectorLength = sectsize;

            if (realsize != 0)
            {
                sectorLength = realsize;
            }
            sectorData.contents = new byte[sectorLength];
            sectorData.dam      = 0xfb;
            if ((sectorData.errorCode & 0x20) != 0) // dam deleted ?
            {
                sectorData.dam = 0xf8;
            }
            ushort crc = 0xffff;

            CalcCRC16(new byte[] { 0xa1, 0xa1, 0xa1, sectorData.dam }, 0, 4, ref crc);
            CalcCRC16(contents, dataOffset, sectsize, ref crc);
            sectorData.calcDataCRC = crc;
            crc = 0xffff;
            CalcCRC16(new byte[] { 0xa1, 0xa1, 0xa1, 0xfe, sectorData.track, sectorData.head, sectorData.sector, sectorData.sizecode }, 0, 8, ref crc);
            sectorData.calcHeaderCRC = crc;
            Array.Copy(contents, dataOffset, sectorData.contents, 0, sectorLength);
            sectorData.imgDataCRC = (ushort)(((contents[adr + 0x128 + (sect * 2)]) << 8) + contents[adr + 0x129 + (sect * 2)]);
            return(sectorData);
        }
Пример #10
0
        private int WriteSector(BinaryWriter writer, SectorInfo sector, Gap[] gaps)
        {
            int    DamOffset = -1;
            Stream stream    = writer.BaseStream;

            WriteBytes(writer, 0, 12);
            WriteBytes(writer, 0xA1, 3);
            WriteBytes(writer, 0xFE, 1);    // address mark
            WriteBytes(writer, sector.track, 1);
            WriteBytes(writer, sector.head, 1);
            WriteBytes(writer, sector.sector, 1);
            WriteBytes(writer, sector.sizecode, 1);
            WriteChecksum(writer, sector, true);
            WriteGap(writer, gaps[2]);
            WriteBytes(writer, 0, 12);
            WriteBytes(writer, 0xA1, 3);
            if ((sector.errorCode & 0x20) == 0)
            {
                WriteBytes(writer, 0xFB, 1);    // data mark
            }
            else
            {
                WriteBytes(writer, 0xF8, 1);    // deleted data mark
            }
            DamOffset = (int)stream.Position;
            writer.Write(sector.contents, 0, sector.contents.Length);
            if (sector.contents.Length != SectorSizeFromCode(sector.sizecode))
            {
                WriteBytes(writer, 0, 2);    // just use zero, it's not the right position for the checksum
            }
            else
            {
                WriteChecksum(writer, sector, false);
            }
            WriteGap(writer, gaps[3]);
            return(DamOffset);
        }
Пример #11
0
 public void WriteExtractedSector(String filename, int track, int head, int blockOrSector, bool isSectorNumber)
 {
     if (blockOrSector == 0)
     {
         WriteExractedTrack(filename, track, head);
     }
     else if (isSectorNumber)
     {
         int count = 0;
         foreach (SectorInfo sector in Contents.physical.tracks[track].sides[head].sectors)
         {
             if (sector.sector == blockOrSector)
             {
                 WriteExtractedSector(filename, count, sector);
                 count++;
             }
         }
     }
     else
     {
         SectorInfo sector = Contents.physical.tracks[track].sides[head].sectors[blockOrSector];
         WriteExtractedSector(filename, 0, sector);
     }
 }
Пример #12
0
        private void AnalyzeTrack(TrackSide track, byte[] contents, int offset, int tracksize)
        {
            int        markPos;
            int        startTrack = offset;
            List <int> IDAMS      = new List <int>();
            int        index      = 0;

            while ((index < 64) && GetMultiByteVal(contents, offset + (index * 2), 2, false) != 0)
            {
                int idam = (int)GetMultiByteVal(contents, offset + (index * 2), 2, false);
                IDAMS.Add(idam);
                index++;
            }
            IDAMS.Add(0);         // add end marker
            index = offset + 128; // end of IDAM block
            int trackstart = index;
            int pos        = FindMark(contents, index, indexMark, startTrack + (IDAMS[0] & 0x3FFF), out markPos);

            if (pos != -1)
            {
                track.gaps[0].Size   = pos;
                track.gaps[0].Filler = FindMostOccuringByte(contents, index, pos);
                index += markPos + 4;
            }
            int count = 0;

            foreach (int idam in IDAMS)
            {
                if (idam != 0)
                {
                    int nextIdamOffset = 0;
                    if (IDAMS[count + 1] > 0)
                    {
                        nextIdamOffset = (IDAMS[count + 1] & 0x3FFF) + startTrack;
                    }
                    else
                    {
                        nextIdamOffset = (startTrack + tracksize) * -1; // negative to indicate start of next track instead
                    }
                    SectorInfo sector = AnalyzeSector(contents, track, ref index, count + 1, nextIdamOffset);
                    if (sector != null)
                    {
                        track.sectors.Add(sector);
                    }
                    count++;
                }
            }
            if (count > 0)
            {
                track.gaps[2].Size /= count;
            }
            if (count > 1)
            {
                track.gaps[3].Size /= (count - 1);
            }
            else
            {
                track.gaps[3].Size = 54;   // set to default
            }
            if (track.sectors.Count > 0)
            {
                track.sectors[track.sectors.Count - 1].gaps[1]       = track.gaps[3].Size;
                track.sectors[track.sectors.Count - 1].gapFillers[1] = FindMostOccuringByte(contents, index, track.gaps[3].Size);
            }
            if ((index + track.gaps[3].Size) < (startTrack + tracksize))
            {
                index += track.gaps[3].Size;
            }
            track.gaps[4].Size   = tracksize - (index - trackstart) - 128;
            track.gaps[4].Filler = FindMostOccuringByte(contents, index, (tracksize + startTrack) - index);
            if (track.gaps[0].Size > 4)
            {
                track.gaps[0].Size -= 4;
            }
            FixOverlappedGap(track);
        }
Пример #13
0
        private SectorInfo AnalyzeSector(byte[] contents, TrackSide track, ref int index, int sectorBlock, int nextIdamOffset)
        {
            int        markPos;
            SectorInfo sector = new SectorInfo();
            int        offset = 0;
            int        pos    = FindMark(contents, index + offset, addressMark, 0, out markPos);

            if (sectorBlock == 1)
            {
                track.gaps[1].Size   = pos;
                track.gaps[1].Filler = FindMostOccuringByte(contents, index, pos);
            }
            else
            {
                track.gaps[3].Size += (pos);
                byte filler = FindMostOccuringByte(contents, index, pos);
                if (track.sectors.Count > (sectorBlock - 2))
                {
                    track.sectors[sectorBlock - 2].gaps[1]       = pos;
                    track.sectors[sectorBlock - 2].gapFillers[1] = filler;
                }
                if (sectorBlock == 2) // if we're at the 2nd sector, we're actually looking for the endgap of the first sector
                {
                    track.gaps[3].Filler = filler;
                }
            }
            index          += markPos + 4;
            sector.track    = contents[index++];
            sector.head     = contents[index++];
            sector.sector   = contents[index++];
            sector.sizecode = contents[index++];
            int size = SectorSizeFromCode(sector.sizecode);

            sector.calcHeaderCRC = CalcCRC16(new byte[] { 0xa1, 0xa1, 0xa1, 0xfe, sector.track, sector.head, sector.sector, sector.sizecode }, 0, 8);
            sector.imgHeaderCRC  = (ushort)GetMultiByteVal(contents, index, 2, true);
            index += 2;
            pos    = FindDataMark(contents, sector, index, out markPos);
            if ((nextIdamOffset <= 0) || ((index + pos) < nextIdamOffset))
            {
                sector.dam           = contents[index + markPos + 3];
                track.gaps[2].Size  += pos;
                sector.gaps[0]       = pos;
                sector.gapFillers[0] = FindMostOccuringByte(contents, index, pos);
                if (sectorBlock == 1)
                {
                    track.gaps[2].Filler = sector.gapFillers[0];
                }
                index += markPos + 4;
                ushort dataCRC = CalcCRC16(new byte[] { 0xa1, 0xa1, 0xa1, sector.dam }, 0, 4);
                CalcCRC16(contents, index, size, ref dataCRC);
                sector.calcDataCRC = dataCRC;
                int realSize = FindRealDataSize(contents, size, index, nextIdamOffset);
                sector.contents = new byte[realSize];
                Array.Copy(contents, index, sector.contents, 0, realSize);
                sector.imgDataCRC = (ushort)GetMultiByteVal(contents, index + size, 2, true);
                index            += realSize;
                if (sector.calcHeaderCRC != sector.imgHeaderCRC)
                {
                    sector.errorCode |= 0x18;
                }
                else if (sector.calcDataCRC != sector.imgDataCRC)
                {
                    sector.errorCode |= 0x08;
                }
                index += 2;  // checksum
            }
            else
            {
                sector = null;  // ignore this one for now.
            }
            return(sector);
        }