예제 #1
0
        private void SeekAddressData(byte ByteRead, OpStatus NextStatus, bool Check)
        {
            damBytesChecked++;
            switch (opStatus)
            {
            case OpStatus.SeekingIDAM:
                if (IndexesFound >= 5)
                {
                    SeekError = true;
                    opStatus  = OpStatus.NMI;
                }
                else
                {
                    switch (ByteRead)
                    {
                    case Floppy.IDAM:
                        if (track?.HasIdamAt(TrackDataIndex, DoubleDensitySelected) ?? false)
                        {
                            readAddressIndex = 0;
                            ResetCRC();
                            crc      = Lib.Crc(crc, ByteRead);
                            opStatus = OpStatus.ReadingAddressData;
                        }
                        idamBytesFound = 0;
                        break;

                    default:
                        idamBytesFound = 0;
                        break;
                    }
                }
                break;

            case OpStatus.ReadingAddressData:
                readAddressData[readAddressIndex] = ByteRead;
                if (readAddressIndex == ADDRESS_DATA_CRC_HIGH_BYTE - 1)
                {
                    // save the value before the first crc on the sector comes in
                    crcCalc = crc;
                }
                else if (readAddressIndex >= ADDRESS_DATA_CRC_LOW_BYTE)
                {
                    damBytesChecked = 0;

                    crcHigh  = readAddressData[ADDRESS_DATA_CRC_HIGH_BYTE];
                    crcLow   = readAddressData[ADDRESS_DATA_CRC_LOW_BYTE];
                    CrcError = crcCalc != Lib.CombineBytes(crcLow, crcHigh);

                    var match = (TrackRegister == readAddressData[ADDRESS_DATA_TRACK_REGISTER_BYTE] &&
                                 (!command.SideSelectVerify || (command.SideOneExpected == (readAddressData[ADDRESS_DATA_SIDE_ONE_BYTE] != 0))) &&
                                 (SectorRegister == readAddressData[ADDRESS_DATA_SECTOR_REGISTER_BYTE]));

                    if (Check && !match)
                    {
                        opStatus = OpStatus.SeekingIDAM;
                    }
                    else
                    {
                        sectorLength = Floppy.GetDataLengthFromCode(readAddressData[ADDRESS_DATA_SECTOR_SIZE_BYTE]);

                        if (CrcError)
                        {
                            opStatus = OpStatus.SeekingIDAM;
                        }
                        else
                        {
                            opStatus = NextStatus;
                        }
                    }
                }
                readAddressIndex++;
                break;

            default:
                throw new Exception();
            }
        }
예제 #2
0
파일: Track.cs 프로젝트: mch2112/Sharp80
        internal static byte[] ToTrackBytes(IEnumerable <SectorDescriptor> Sectors, int Length = 0)
        {
            byte[] ret = new byte[MAX_LENGTH_WITH_HEADER * 2]; // big

            int i = 0;

            ret.SetValues(ref i, HEADER_LENGTH_BYTES, (byte)0x00);

            bool ddAll = Sectors.All(s => s.DoubleDensity);

            int headerCursor = 0;

            // In some places we use fewer bytes than the 1773 tech reference states so that we can fit
            // 18 DD sectors (or 10 SD sectors) in a standard length track. Not sure why WD made it
            // so the standard doesn't work.

            if (ddAll)
            {
                ret.SetValues(ref i, 10, (byte)0x4E)  /* standard is 80 */
                .SetValues(ref i, 12, (byte)0x00)
                .SetValues(ref i, 3, (byte)0xF6)
                .SetValues(ref i, 1, (byte)0xFC)
                .SetValues(ref i, 50, (byte)0x4E);    /* standard is 50 */
            }
            else
            {
                // times two for doubled bytes
                ret.SetValues(ref i, 10 * 2, (byte)0xFF)  /* tech datasheet says 30, not 10 */
                .SetValues(ref i, 6 * 2, (byte)0x00)
                .SetValues(ref i, 1 * 2, (byte)0xFC)
                .SetValues(ref i, 26 * 2, (byte)0xFF);
            }
            byte sideNum;
            byte dataLengthCode;
            byte b;

            foreach (var s in Sectors)
            {
                sideNum        = s.Side;
                dataLengthCode = Floppy.GetDataLengthCode(s.SectorData.Length);
                ushort crc;
                if (s.DoubleDensity)
                {
                    crc = Floppy.CRC_RESET_A1_A1_A1_FE;

                    ret.SetValues(ref i, 12, (byte)0x00)
                    .SetValues(ref i, 3, (byte)0xA1);

                    ((ushort)(i + DOUBLE_DENSITY_MASK)).Split(out ret[headerCursor], out ret[headerCursor + 1]);
                }
                else
                {
                    crc = Floppy.CRC_RESET_FE;
                    ret.SetValues(ref i, 6 * 2, (byte)0x00);

                    ((ushort)i).Split(out ret[headerCursor], out ret[headerCursor + 1]);
                }
                headerCursor += 2;
                ret.SetValues(ref i, !s.DoubleDensity, Floppy.IDAM, s.TrackNumber, sideNum, s.SectorNumber, dataLengthCode);

                crc = Lib.Crc(crc, s.TrackNumber, sideNum, s.SectorNumber, dataLengthCode);
                crc.Split(out byte crcLow, out byte crcHigh);

                if (s.DoubleDensity)
                {
                    ret.SetValues(ref i, false, crcHigh, crcLow)
                    .SetValues(ref i, 22, (byte)0x4E)
                    .SetValues(ref i, 12, (byte)0x00)
                    .SetValues(ref i, false, (byte)0xA1, (byte)0xA1, (byte)0xA1, s.DAM);

                    crc = Lib.Crc(Floppy.CRC_RESET_A1_A1_A1, s.DAM);
                    for (int j = 0; j < s.SectorData.Length; j++)
                    {
                        b        = s.SectorData[j];
                        ret[i++] = b;
                        crc      = Lib.Crc(crc, b);
                    }

                    if (s.CrcError)
                    {
                        crc = (ushort)~crc; // trash the crc
                    }
                    crc.Split(out crcLow, out crcHigh);

                    ret.SetValues(ref i, false, crcHigh, crcLow)
                    .SetValues(ref i, 20, (byte)0x4E);    /* standard is 54 */
                }
                else // single density
                {
                    ret.SetValues(ref i, true, crcHigh, crcLow)
                    .SetValues(ref i, 11 * 2, (byte)0xFF)
                    .SetValues(ref i, 6 * 2, (byte)0x00)
                    .SetValues(ref i, 1 * 2, s.DAM);

                    crc = Floppy.CRC_RESET;
                    crc = Lib.Crc(crc, s.DAM);
                    for (int j = 0; j < s.SectorData.Length; j++)
                    {
                        b        = s.SectorData[j];
                        ret[i++] = b;
                        ret[i++] = b;
                        crc      = Lib.Crc(crc, b);
                    }

                    if (s.CrcError)
                    {
                        crc = (ushort)~crc; // trash the crc
                    }
                    crc.Split(out crcLow, out crcHigh);
                    ret.SetValues(ref i, 1 * 2, crcHigh)
                    .SetValues(ref i, 1 * 2, crcLow)
                    .SetValues(ref i, 17 * 2, (byte)0xFF);    /* spec says 27, not 17 */
                }
            }

            if (Length > 0)
            {
                ret = ret.Pad(Length, ddAll ? Floppy.FILLER_BYTE_DD : Floppy.FILLER_BYTE_SD).Slice(0, Length);
            }

            else if (i <= 0x0CC0)
            {
                ret = ret.Pad(0x0CC0, Floppy.FILLER_BYTE_SD);
            }
            else
            {
                ret = ret.Pad(DEFAULT_LENGTH_WITH_HEADER, ddAll ? Floppy.FILLER_BYTE_DD : Floppy.FILLER_BYTE_SD).Slice(0, MAX_LENGTH_WITH_HEADER);
            }

            return(ret);
        }
예제 #3
0
파일: Track.cs 프로젝트: mch2112/Sharp80
        private List <SectorDescriptor> GetSectorDescriptorCache()
        {
            var sds = new List <SectorDescriptor>();

            for (int SectorIndex = 0; SectorIndex < HEADER_LENGTH && Header[SectorIndex] > 0; SectorIndex++)
            {
                bool density      = Header[SectorIndex] >= DOUBLE_DENSITY_MASK;
                int  byteMultiple = density ? 1 : 2;
                int  offset       = (Header[SectorIndex] & OFFSET_MASK) - HEADER_LENGTH_BYTES;
                if (data[offset] != Floppy.IDAM)
                {
                    continue;
                }

                byte trackNum  = data[offset + 1 * byteMultiple];
                bool sideOne   = data[offset + 2 * byteMultiple] > 0;
                byte sectorNum = data[offset + 3 * byteMultiple];

                byte dam       = 0x00;
                int  dataStart = 0x00;
                bool deleted   = false;
                for (int i = offset + 7 * byteMultiple; i < offset + (7 + (density ? 43 : 30)) * byteMultiple; i += byteMultiple)
                {
                    if (FloppyController.IsDAM(data[i], out deleted))
                    {
                        dam       = data[i];
                        dataStart = i + byteMultiple;
                        break;
                    }
                }

                var  sizeCode   = data[offset + 4 * byteMultiple];
                var  dataLength = Floppy.GetDataLengthFromCode(sizeCode);
                var  sectorData = new byte[dataLength];
                bool crcError;
                bool inUse;
                if (dam == 0x00)
                {
                    crcError = true;
                    inUse    = false;
                }
                else
                {
                    inUse = !deleted;
                    ushort actualCrc = Lib.Crc(density ? Floppy.CRC_RESET_A1_A1_A1 : Floppy.CRC_RESET, dam);
                    for (int i = 0; i < dataLength; i++)
                    {
                        sectorData[i] = data[dataStart + i * byteMultiple];
                        actualCrc     = Lib.Crc(actualCrc, sectorData[i]);
                    }
                    ushort recordedCrc = Lib.CombineBytes(data[dataStart + (dataLength + 1) * byteMultiple], data[dataStart + dataLength * byteMultiple]);
                    crcError = actualCrc != recordedCrc;
                }
                sds.Add(new SectorDescriptor(trackNum,
                                             sectorNum,
                                             sideOne,
                                             density,
                                             dam,
                                             sectorData,
                                             inUse,
                                             crcError));
            }
            return(sds.OrderBy(s => s.SectorNumber).ToList());
        }
예제 #4
0
파일: Track.cs 프로젝트: mch2112/Sharp80
        private ushort[] RebuildHeader()
        {
            var header = new ushort[HEADER_LENGTH];

            int headerCursor = 0;

            int end = data.Length - 10;
            int i   = 4;

            while (i < end)
            {
                bool density = GetDensity(i);

                if (data[i] == Floppy.IDAM)
                {
                    // is it a real IDAM? Check preceding bytes
                    if (density)
                    {
                        if (data[i - 1] != 0xA1 || data[i - 2] != 0xA1 || data[i - 3] != 0xA1)
                        {
                            i++;
                            continue;
                        }
                    }
                    else
                    {
                        if (data[i - 2] != 0x00)
                        {
                            i += 2;
                            continue;
                        }
                    }

                    // commit without checking address crc, since could be intentional error
                    header[headerCursor++] = (ushort)(i + HEADER_LENGTH_BYTES + (density ? DOUBLE_DENSITY_MASK : 0));

                    // now skip forward past the sector contents
                    // advance to length
                    if (density)
                    {
                        i += 4;
                    }
                    else
                    {
                        i += 8;
                    }
                    i += Floppy.GetDataLengthFromCode(data[i]) * (density ? 1 : 2);
                    i += 20 * (density ? 1 : 2); // filler minimum
                }
                else
                {
                    if (density)
                    {
                        i++;
                    }
                    else
                    {
                        i += 2;
                    }
                }
            }
            this.header = header;
            return(this.header);
        }