Пример #1
0
        public static byte[] MarshalSector(RawSector sector)
        {
            if (sector == null)
            {
                return(null);
            }

            MemoryStream raw = new MemoryStream();

            raw.Write(sector.addressField.prologue, 0, sector.addressField.prologue.Length);
            raw.WriteByte(sector.addressField.track);
            raw.WriteByte(sector.addressField.sector);
            raw.WriteByte(sector.addressField.side);
            raw.WriteByte((byte)sector.addressField.format);
            raw.WriteByte(sector.addressField.checksum);
            raw.Write(sector.innerGap, 0, sector.innerGap.Length);
            raw.Write(sector.dataField.prologue, 0, sector.dataField.prologue.Length);
            raw.WriteByte(sector.dataField.spare);
            raw.Write(sector.dataField.data, 0, sector.dataField.data.Length);
            raw.Write(sector.dataField.checksum, 0, sector.dataField.checksum.Length);
            raw.Write(sector.dataField.epilogue, 0, sector.dataField.epilogue.Length);
            raw.Write(sector.gap, 0, sector.gap.Length);

            return(raw.ToArray());
        }
Пример #2
0
        public static byte[] DecodeSector(RawSector sector)
        {
            if (sector.addressField.prologue[0] != 0xD5 || sector.addressField.prologue[1] != 0xAA)
            {
                return(null);
            }
            // Pre DOS 3.3
            if (sector.addressField.prologue[2] == 0xB5)
            {
                return(Decode5and3(sector.dataField.data));
            }
            // DOS 3.3
            return(sector.addressField.prologue[2] == 0x96 ? Decode6and2(sector.dataField.data) : null);
            // Unknown

            // Not Apple ][ GCR?
        }
Пример #3
0
        public static byte[] MarshalSector(RawSector sector)
        {
            if (sector == null)
            {
                return(null);
            }

            var raw = new MemoryStream();

            raw.Write(sector.addressField.prologue, 0, sector.addressField.prologue.Length);
            raw.Write(sector.addressField.volume, 0, sector.addressField.volume.Length);
            raw.Write(sector.addressField.track, 0, sector.addressField.track.Length);
            raw.Write(sector.addressField.sector, 0, sector.addressField.sector.Length);
            raw.Write(sector.addressField.checksum, 0, sector.addressField.checksum.Length);
            raw.Write(sector.addressField.epilogue, 0, sector.addressField.epilogue.Length);
            raw.Write(sector.innerGap, 0, sector.innerGap.Length);
            raw.Write(sector.dataField.prologue, 0, sector.dataField.prologue.Length);
            raw.Write(sector.dataField.data, 0, sector.dataField.data.Length);
            raw.WriteByte(sector.dataField.checksum);
            raw.Write(sector.dataField.epilogue, 0, sector.dataField.epilogue.Length);
            raw.Write(sector.gap, 0, sector.gap.Length);

            return(raw.ToArray());
        }
Пример #4
0
        public static bool IsAppleSonyGCR(byte[] data)
        {
            RawSector sector = MarshalSector(data, out int position);

            return(sector != null && position != 0);
        }
Пример #5
0
        public static RawTrack MarshalTrack(byte[] data, out int endOffset, int offset = 0)
        {
            int              position    = offset;
            bool             firstSector = true;
            bool             onSync      = false;
            MemoryStream     gaps        = new MemoryStream();
            int              count       = 0;
            List <RawSector> sectors     = new List <RawSector>();
            byte             trackNumber = 0;
            byte             sideNumber  = 0;

            endOffset = offset;

            while (position < data.Length && data[position] == 0xFF)
            {
                gaps.WriteByte(data[position]);
                count++;
                position++;
                onSync = count >= 5;
            }

            if (position >= data.Length)
            {
                return(null);
            }

            if (!onSync)
            {
                return(null);
            }

            while (position < data.Length)
            {
                int       oldPosition = position;
                RawSector sector      = MarshalSector(data, out position, position);
                if (sector == null)
                {
                    break;
                }

                if (firstSector)
                {
                    trackNumber = sector.addressField.track;
                    sideNumber  = sector.addressField.side;
                    firstSector = false;
                }

                if (sector.addressField.track != trackNumber || sector.addressField.side != sideNumber)
                {
                    position = oldPosition;
                    break;
                }

                sectors.Add(sector);
            }

            if (sectors.Count == 0)
            {
                return(null);
            }

            RawTrack track = new RawTrack {
                gap = gaps.ToArray(), sectors = sectors.ToArray()
            };

            endOffset = position;
            return(track);
        }
Пример #6
0
        public static RawSector MarshalSector(byte[] data, out int endOffset, int offset = 0)
        {
            endOffset = offset;

            // Not an Apple ][ GCR sector
            if (data == null || data.Length < 363)
            {
                return(null);
            }

            int position = offset;

            try
            {
                while (position < data.Length)
                {
                    // Prologue found
                    if (data[position] == 0xD5 && data[position + 1] == 0xAA && data[position + 2] == 0x96)
                    {
                        // Epilogue not in correct position
                        if (data[position + 8] != 0xDE || data[position + 9] != 0xAA)
                        {
                            return(null);
                        }

                        RawSector sector = new RawSector
                        {
                            addressField = new RawAddressField
                            {
                                prologue = new[] { data[position], data[position + 1], data[position + 2] },
                                track    = data[position + 3],
                                sector   = data[position + 4],
                                side     = data[position + 5],
                                format   = (AppleEncodedFormat)data[position + 6],
                                checksum = data[position + 7],
                                epilogue = new[] { data[position + 8], data[position + 9] }
                            }
                        };

                        position += 10;
                        int          syncCount = 0;
                        bool         onSync    = false;
                        MemoryStream gaps      = new MemoryStream();

                        while (data[position] == 0xFF)
                        {
                            gaps.WriteByte(data[position]);
                            syncCount++;
                            onSync = syncCount >= 5;
                            position++;
                        }

                        // Lost sync
                        if (!onSync)
                        {
                            return(null);
                        }

                        // Prologue not found
                        if (data[position] != 0xDE || data[position + 1] != 0xAA || data[position + 2] != 0xAD)
                        {
                            return(null);
                        }

                        sector.innerGap  = gaps.ToArray();
                        sector.dataField = new RawDataField
                        {
                            prologue = new[] { data[position], data[position + 1], data[position + 2] },
                            spare    = data[position + 3]
                        };
                        position += 4;

                        gaps = new MemoryStream();
                        // Read data until epilogue is found
                        while (data[position + 4] != 0xD5 || data[position + 5] != 0xAA)
                        {
                            gaps.WriteByte(data[position]);
                            position++;

                            // No space left for epilogue
                            if (position + 7 > data.Length)
                            {
                                return(null);
                            }
                        }

                        sector.dataField.data        = gaps.ToArray();
                        sector.dataField.checksum    = new byte[4];
                        sector.dataField.checksum[0] = data[position];
                        sector.dataField.checksum[1] = data[position + 2];
                        sector.dataField.checksum[2] = data[position + 3];
                        sector.dataField.checksum[3] = data[position + 4];
                        sector.dataField.epilogue    = new byte[2];
                        sector.dataField.epilogue[0] = data[position + 5];
                        sector.dataField.epilogue[1] = data[position + 6];

                        position += 7;
                        gaps      = new MemoryStream();
                        // Read gap, if any
                        while (position < data.Length && data[position] == 0xFF)
                        {
                            gaps.WriteByte(data[position]);
                            position++;
                        }

                        // Reduces last sector gap so doesn't eat next tracks's gap
                        if (gaps.Length > 5)
                        {
                            gaps.SetLength(gaps.Length / 2);
                            position -= (int)gaps.Length;
                        }

                        sector.gap = gaps.ToArray();
                        // Return current position to be able to read separate sectors
                        endOffset = position;
                        return(sector);
                    }

                    if (data[position] == 0xFF)
                    {
                        position++;
                    }
                    // Found data that is not sync or a prologue
                    else
                    {
                        return(null);
                    }
                }
            }
            catch (IndexOutOfRangeException) { return(null); }

            return(null);
        }
Пример #7
0
        public static byte[] DecodeSector(RawSector sector)
        {
            if (sector.addressField.prologue[0] != 0xD5 || sector.addressField.prologue[1] != 0xAA ||
                sector.addressField.prologue[2] != 0x96)
            {
                return(null);
            }

            byte[]       bf1      = new byte[175];
            byte[]       bf2      = new byte[175];
            byte[]       bf3      = new byte[175];
            byte[]       nib_data = sector.dataField.data;
            MemoryStream ms       = new MemoryStream();

            int  j  = 0;
            byte w3 = 0;

            for (int i = 0; i <= 174; i++)
            {
                byte w4 = nib_data[j++];
                byte w1 = nib_data[j++];
                byte w2 = nib_data[j++];

                if (i != 174)
                {
                    w3 = nib_data[j++];
                }

                bf1[i] = (byte)(((w1 & 0x3F) | ((w4 << 2) & 0xC0)) & 0x0F);
                bf2[i] = (byte)(((w2 & 0x3F) | ((w4 << 4) & 0xC0)) & 0x0F);
                bf3[i] = (byte)(((w3 & 0x3F) | ((w4 << 6) & 0xC0)) & 0x0F);
            }

            j = 0;
            uint ck1 = 0;
            uint ck2 = 0;
            uint ck3 = 0;

            while (true)
            {
                ck1 = (ck1 & 0xFF) << 1;
                if ((ck1 & 0x0100) > 0)
                {
                    ck1++;
                }

                byte carry = (byte)((bf1[j] ^ ck1) & 0xFF);
                ck3 += carry;
                if ((ck1 & 0x0100) > 0)
                {
                    ck3++;
                    ck1 &= 0xFF;
                }

                ms.WriteByte(carry);

                carry = (byte)((bf2[j] ^ ck3) & 0xFF);
                ck2  += carry;
                if (ck3 > 0xFF)
                {
                    ck2++;
                    ck3 &= 0xFF;
                }

                ms.WriteByte(carry);

                if (ms.Length == 524)
                {
                    break;
                }

                carry = (byte)((bf3[j] ^ ck2) & 0xFF);
                ck1  += carry;
                if (ck2 > 0xFF)
                {
                    ck1++;
                    ck2 &= 0xFF;
                }

                ms.WriteByte(carry);
                j++;
            }

            return(ms.ToArray());

            // Not Apple Sony GCR?
        }
Пример #8
0
        public static RawTrack MarshalTrack(byte[] data, out int endOffset, int offset = 0)
        {
            int              position    = offset;
            bool             firstSector = true;
            bool             onSync      = false;
            MemoryStream     gaps        = new MemoryStream();
            int              count       = 0;
            List <RawSector> sectors     = new List <RawSector>();

            byte[] trackNumber = new byte[2];
            endOffset = offset;

            while (position < data.Length && data[position] == 0xFF)
            {
                gaps.WriteByte(data[position]);
                count++;
                position++;
                onSync = count >= 5;
            }

            if (position >= data.Length)
            {
                return(null);
            }

            if (!onSync)
            {
                return(null);
            }

            while (position < data.Length)
            {
                int       oldPosition = position;
                RawSector sector      = MarshalSector(data, out position, position);
                if (sector == null)
                {
                    break;
                }

                if (firstSector)
                {
                    trackNumber[0] = sector.addressField.track[0];
                    trackNumber[1] = sector.addressField.track[1];
                    firstSector    = false;
                }

                if (sector.addressField.track[0] != trackNumber[0] || sector.addressField.track[1] != trackNumber[1])
                {
                    position = oldPosition;
                    break;
                }

                DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Adding sector {0} of track {1}",
                                          (((sector.addressField.sector[0] & 0x55) << 1) |
                                           (sector.addressField.sector[1] & 0x55)) & 0xFF,
                                          (((sector.addressField.track[0] & 0x55) << 1) |
                                           (sector.addressField.track[1] & 0x55)) & 0xFF);
                sectors.Add(sector);
            }

            if (sectors.Count == 0)
            {
                return(null);
            }

            RawTrack track = new RawTrack {
                gap = gaps.ToArray(), sectors = sectors.ToArray()
            };

            endOffset = position;
            return(track);
        }
Пример #9
0
        public static RawSector MarshalSector(byte[] data, out int endOffset, int offset = 0)
        {
            endOffset = offset;

            // Not an Apple ][ GCR sector
            if (data == null || data.Length < 363)
            {
                return(null);
            }

            int position = offset;

            try
            {
                while (position < data.Length)
                {
                    // Prologue found
                    if (data[position] == 0xD5 && data[position + 1] == 0xAA)
                    {
                        DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Prologue found at {0}", position);

                        // Epilogue not in correct position
                        if (data[position + 11] != 0xDE || data[position + 12] != 0xAA)
                        {
                            return(null);
                        }

                        RawSector sector = new RawSector
                        {
                            addressField = new RawAddressField
                            {
                                prologue = new[] { data[position], data[position + 1], data[position + 2] },
                                volume   = new[] { data[position + 3], data[position + 4] },
                                track    = new[] { data[position + 5], data[position + 6] },
                                sector   = new[] { data[position + 7], data[position + 8] },
                                checksum = new[] { data[position + 9], data[position + 10] },
                                epilogue = new[]
                                { data[position + 11], data[position + 12], data[position + 13] }
                            }
                        };

                        DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Volume {0}",
                                                  (((sector.addressField.volume[0] & 0x55) << 1) |
                                                   (sector.addressField.volume[1] & 0x55)) & 0xFF);
                        DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Track {0}",
                                                  (((sector.addressField.track[0] & 0x55) << 1) |
                                                   (sector.addressField.track[1] & 0x55)) & 0xFF);
                        DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Sector {0}",
                                                  (((sector.addressField.sector[0] & 0x55) << 1) |
                                                   (sector.addressField.sector[1] & 0x55)) & 0xFF);
                        DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Checksum {0}",
                                                  (((sector.addressField.checksum[0] & 0x55) << 1) |
                                                   (sector.addressField.checksum[1] & 0x55)) & 0xFF);
                        DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Epilogue {0:X2}{1:X2}{2:X2}",
                                                  sector.addressField.epilogue[0], sector.addressField.epilogue[1],
                                                  sector.addressField.epilogue[2]);

                        position += 14;
                        int          syncCount = 0;
                        bool         onSync    = false;
                        MemoryStream gaps      = new MemoryStream();

                        while (data[position] == 0xFF)
                        {
                            gaps.WriteByte(data[position]);
                            syncCount++;
                            onSync = syncCount >= 5;
                            position++;
                        }

                        // Lost sync
                        if (!onSync)
                        {
                            return(null);
                        }

                        // Prologue not found
                        if (data[position] != 0xD5 || data[position + 1] != 0xAA)
                        {
                            return(null);
                        }

                        sector.innerGap  = gaps.ToArray();
                        sector.dataField = new RawDataField();

                        DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Inner gap has {0} bytes",
                                                  sector.innerGap.Length);
                        DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Prologue found at {0}", position);
                        sector.dataField.prologue    = new byte[3];
                        sector.dataField.prologue[0] = data[position];
                        sector.dataField.prologue[1] = data[position + 1];
                        sector.dataField.prologue[2] = data[position + 2];
                        position += 3;

                        gaps = new MemoryStream();
                        // Read data until epilogue is found
                        while (data[position + 1] != 0xDE || data[position + 2] != 0xAA)
                        {
                            gaps.WriteByte(data[position]);
                            position++;

                            // No space left for epilogue
                            if (position + 4 > data.Length)
                            {
                                return(null);
                            }
                        }

                        sector.dataField.data = gaps.ToArray();
                        DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Data has {0} bytes",
                                                  sector.dataField.data.Length);
                        sector.dataField.checksum    = data[position];
                        sector.dataField.epilogue    = new byte[3];
                        sector.dataField.epilogue[0] = data[position + 1];
                        sector.dataField.epilogue[1] = data[position + 2];
                        sector.dataField.epilogue[2] = data[position + 3];

                        position += 4;
                        gaps      = new MemoryStream();
                        // Read gap, if any
                        while (position < data.Length && data[position] == 0xFF)
                        {
                            gaps.WriteByte(data[position]);
                            position++;
                        }

                        // Reduces last sector gap so doesn't eat next tracks's gap
                        if (gaps.Length > 5)
                        {
                            gaps.SetLength(gaps.Length / 2);
                            position -= (int)gaps.Length;
                        }

                        sector.gap = gaps.ToArray();
                        // Return current position to be able to read separate sectors
                        endOffset = position;
                        DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Got {0} bytes of gap", sector.gap.Length);
                        DicConsole.DebugWriteLine("Apple ][ GCR Decoder", "Finished sector at {0}", position);
                        return(sector);
                    }

                    if (data[position] == 0xFF)
                    {
                        position++;
                    }
                    // Found data that is not sync or a prologue
                    else
                    {
                        return(null);
                    }
                }
            }
            catch (IndexOutOfRangeException) { return(null); }

            return(null);
        }