Exemplo n.º 1
0
        public Disk Build()
        {
            const int tracks           = 35;
            var       trackByteOffsets = new int[tracks];
            var       bam      = new BamEntry[tracks];
            var       diskFull = false;

            for (var i = 0; i < tracks; i++)
            {
                bam[i] = new BamEntry(SectorsPerTrack[i]);
                if (i > 0)
                {
                    trackByteOffsets[i] = trackByteOffsets[i - 1] + (SectorsPerTrack[i - 1] * 256);
                }
            }
            var bytes = new byte[trackByteOffsets[tracks - 1] + (SectorsPerTrack[tracks - 1] * 256)];

            var currentTrack     = 16;
            var currentSector    = 0;
            var interleaveStart  = 0;
            var sectorInterleave = 3;
            var directory        = new List <LocatedEntry>();

            Func <int, int, int> GetOutputOffset = (t, s) => trackByteOffsets[t] + (s * 256);

            foreach (var entry in Entries)
            {
                var sourceOffset    = 0;
                var dataLength      = entry.Data == null ? 0 : entry.Data.Length;
                var lengthInSectors = dataLength / 254;
                var dataRemaining   = dataLength;
                var directoryEntry  = new LocatedEntry
                {
                    Entry           = entry,
                    LengthInSectors = lengthInSectors + 1,
                    Track           = currentTrack,
                    Sector          = currentSector
                };
                directory.Add(directoryEntry);

                while (!diskFull)
                {
                    var outputOffset = GetOutputOffset(currentTrack, currentSector);

                    if (dataRemaining > 254)
                    {
                        Array.Copy(entry.Data, sourceOffset, bytes, outputOffset + 2, 254);
                        dataRemaining -= 254;
                        sourceOffset  += 254;
                    }
                    else
                    {
                        if (dataRemaining > 0)
                        {
                            Array.Copy(entry.Data, sourceOffset, bytes, outputOffset + 2, dataRemaining);
                            bytes[outputOffset + 0] = 0;
                            bytes[outputOffset + 1] = (byte)(dataRemaining + 1);
                            dataRemaining           = 0;
                        }
                    }

                    bam[currentTrack].Allocate(currentSector);
                    currentSector += sectorInterleave;
                    if (currentSector >= SectorsPerTrack[currentTrack])
                    {
                        interleaveStart++;
                        if (interleaveStart >= sectorInterleave)
                        {
                            interleaveStart = 0;
                            if (currentTrack >= 17)
                            {
                                currentTrack++;
                                if (currentTrack >= 35)
                                {
                                    diskFull = true;
                                    break;
                                }
                            }
                            else
                            {
                                currentTrack--;
                                if (currentTrack < 0)
                                {
                                    currentTrack = 18;
                                }
                            }
                        }
                        currentSector = interleaveStart;
                    }

                    if (dataRemaining <= 0)
                    {
                        break;
                    }

                    bytes[outputOffset + 0] = (byte)(currentTrack + 1);
                    bytes[outputOffset + 1] = (byte)currentSector;
                }

                if (diskFull)
                {
                    break;
                }
            }

            // write Directory
            var directoryOffset = -(0x20);

            currentTrack  = 17;
            currentSector = 1;
            var directoryOutputOffset = GetOutputOffset(currentTrack, currentSector);
            var fileIndex             = 0;

            bam[currentTrack].Allocate(currentSector);
            foreach (var entry in directory)
            {
                directoryOffset += 0x20;
                if (directoryOffset == 0x100)
                {
                    directoryOffset = 0;
                    currentSector  += 3;
                    bytes[directoryOutputOffset]     = (byte)currentTrack;
                    bytes[directoryOutputOffset + 1] = (byte)currentSector;
                    directoryOutputOffset            = GetOutputOffset(currentTrack, currentSector);
                    bam[currentTrack].Allocate(currentSector);
                }
                bytes[directoryOutputOffset + directoryOffset + 0x00] = 0x00;
                bytes[directoryOutputOffset + directoryOffset + 0x01] = 0x00;
                bytes[directoryOutputOffset + directoryOffset + 0x02] = (byte)((int)entry.Entry.Type | (entry.Entry.Locked ? 0x40 : 0x00) | (entry.Entry.Closed ? 0x80 : 0x00));
                bytes[directoryOutputOffset + directoryOffset + 0x03] = (byte)(entry.Track + 1);
                bytes[directoryOutputOffset + directoryOffset + 0x04] = (byte)entry.Sector;
                for (var i = 0x05; i <= 0x14; i++)
                {
                    bytes[directoryOutputOffset + directoryOffset + i] = 0xA0;
                }
                var fileNameBytes = Encoding.ASCII.GetBytes(entry.Entry.Name ?? string.Format("FILE{0:D3}", fileIndex));
                Array.Copy(fileNameBytes, 0, bytes, directoryOutputOffset + directoryOffset + 0x05, Math.Min(fileNameBytes.Length, 0x10));
                bytes[directoryOutputOffset + directoryOffset + 0x1E] = (byte)(entry.LengthInSectors & 0xFF);
                bytes[directoryOutputOffset + directoryOffset + 0x1F] = (byte)((entry.LengthInSectors >> 8) & 0xFF);
                fileIndex++;
            }
            bytes[directoryOutputOffset + 0x00] = 0x00;
            bytes[directoryOutputOffset + 0x01] = 0xFF;

            // write BAM
            var bamOutputOffset = GetOutputOffset(17, 0);

            bytes[bamOutputOffset + 0x00] = 18;
            bytes[bamOutputOffset + 0x01] = 1;
            bytes[bamOutputOffset + 0x02] = (byte)VersionType;
            for (var i = 0; i < 35; i++)
            {
                Array.Copy(bam[i].GetBytes(), 0, bytes, bamOutputOffset + 4 + (i * 4), 4);
            }
            for (var i = 0x90; i <= 0xAA; i++)
            {
                bytes[bamOutputOffset + i] = 0xA0;
            }
            var titleBytes = Encoding.ASCII.GetBytes(Title ?? "UNTITLED");

            Array.Copy(titleBytes, 0, bytes, bamOutputOffset + 0x90, Math.Min(titleBytes.Length, 0x10));

            return(D64.Read(bytes));
        }
Exemplo n.º 2
0
        public Disk Build()
        {
            const int tracks = 35;
            var trackByteOffsets = new int[tracks];
            var bam = new BamEntry[tracks];
            var diskFull = false;

            for (var i = 0; i < tracks; i++)
            {
                bam[i] = new BamEntry(SectorsPerTrack[i]);
                if (i > 0)
                {
                    trackByteOffsets[i] = trackByteOffsets[i - 1] + (SectorsPerTrack[i - 1] * 256);
                }
            }
            var bytes = new byte[trackByteOffsets[tracks - 1] + (SectorsPerTrack[tracks - 1] *256)];

            var currentTrack = 16;
            var currentSector = 0;
            var interleaveStart = 0;
            var sectorInterleave = 3;
            var directory = new List<LocatedEntry>();

            Func<int, int, int> GetOutputOffset = (t, s) => trackByteOffsets[t] + (s*256);

            foreach (var entry in Entries)
            {
                var sourceOffset = 0;
                var dataLength = entry.Data == null ? 0 : entry.Data.Length;
                var lengthInSectors = dataLength / 254;
                var dataRemaining = dataLength;
                var directoryEntry = new LocatedEntry
                {
                    Entry = entry,
                    LengthInSectors = lengthInSectors + 1,
                    Track = currentTrack,
                    Sector = currentSector
                };
                directory.Add(directoryEntry);

                while (!diskFull)
                {
                    var outputOffset = GetOutputOffset(currentTrack, currentSector);

                    if (dataRemaining > 254)
                    {
                        Array.Copy(entry.Data, sourceOffset, bytes, outputOffset + 2, 254);
                        dataRemaining -= 254;
                        sourceOffset += 254;
                    }
                    else
                    {
                        if (dataRemaining > 0)
                        {
                            Array.Copy(entry.Data, sourceOffset, bytes, outputOffset + 2, dataRemaining);
                            bytes[outputOffset + 0] = 0;
                            bytes[outputOffset + 1] = (byte)(dataRemaining + 1);
                            dataRemaining = 0;
                        }
                    }

                    bam[currentTrack].Allocate(currentSector);
                    currentSector += sectorInterleave;
                    if (currentSector >= SectorsPerTrack[currentTrack])
                    {
                        interleaveStart++;
                        if (interleaveStart >= sectorInterleave)
                        {
                            interleaveStart = 0;
                            if (currentTrack >= 17)
                            {
                                currentTrack++;
                                if (currentTrack >= 35)
                                {
                                    diskFull = true;
                                    break;
                                }
                            }
                            else
                            {
                                currentTrack--;
                                if (currentTrack < 0)
                                    currentTrack = 18;
                            }
                        }
                        currentSector = interleaveStart;
                    }

                    if (dataRemaining <= 0)
                        break;

                    bytes[outputOffset + 0] = (byte)(currentTrack + 1);
                    bytes[outputOffset + 1] = (byte) currentSector;
                }

                if (diskFull)
                    break;
            }

            // write Directory
            var directoryOffset = -(0x20);
            currentTrack = 17;
            currentSector = 1;
            var directoryOutputOffset = GetOutputOffset(currentTrack, currentSector);
            var fileIndex = 0;
            bam[currentTrack].Allocate(currentSector);
            foreach (var entry in directory)
            {
                directoryOffset += 0x20;
                if (directoryOffset == 0x100)
                {
                    directoryOffset = 0;
                    currentSector += 3;
                    bytes[directoryOutputOffset] = (byte) currentTrack;
                    bytes[directoryOutputOffset + 1] = (byte) currentSector;
                    directoryOutputOffset = GetOutputOffset(currentTrack, currentSector);
                    bam[currentTrack].Allocate(currentSector);
                }
                bytes[directoryOutputOffset + directoryOffset + 0x00] = 0x00;
                bytes[directoryOutputOffset + directoryOffset + 0x01] = 0x00;
                bytes[directoryOutputOffset + directoryOffset + 0x02] = (byte)((int)entry.Entry.Type | (entry.Entry.Locked ? 0x40 : 0x00) | (entry.Entry.Closed ? 0x80 : 0x00));
                bytes[directoryOutputOffset + directoryOffset + 0x03] = (byte)(entry.Track + 1);
                bytes[directoryOutputOffset + directoryOffset + 0x04] = (byte)entry.Sector;
                for (var i = 0x05; i <= 0x14; i++)
                    bytes[directoryOutputOffset + directoryOffset + i] = 0xA0;
                var fileNameBytes = Encoding.ASCII.GetBytes(entry.Entry.Name ?? string.Format("FILE{0:D3}", fileIndex));
                Array.Copy(fileNameBytes, 0, bytes, directoryOutputOffset + directoryOffset + 0x05, Math.Min(fileNameBytes.Length, 0x10));
                bytes[directoryOutputOffset + directoryOffset + 0x1E] = (byte)(entry.LengthInSectors & 0xFF);
                bytes[directoryOutputOffset + directoryOffset + 0x1F] = (byte)((entry.LengthInSectors >> 8) & 0xFF);
                fileIndex++;
            }
            bytes[directoryOutputOffset + 0x00] = 0x00;
            bytes[directoryOutputOffset + 0x01] = 0xFF;

            // write BAM
            var bamOutputOffset = GetOutputOffset(17, 0);
            bytes[bamOutputOffset + 0x00] = 18;
            bytes[bamOutputOffset + 0x01] = 1;
            bytes[bamOutputOffset + 0x02] = (byte)VersionType;
            for (var i = 0; i < 35; i++)
            {
                Array.Copy(bam[i].GetBytes(), 0, bytes, bamOutputOffset + 4 + (i * 4), 4);
            }
            for (var i = 0x90; i <= 0xAA; i++)
            {
                bytes[bamOutputOffset + i] = 0xA0;
            }
            var titleBytes = Encoding.ASCII.GetBytes(Title ?? "UNTITLED");
            Array.Copy(titleBytes, 0, bytes, bamOutputOffset + 0x90, Math.Min(titleBytes.Length, 0x10));

            return D64.Read(bytes);
        }