/// <summary>
        /// Returns an empty directory entry, suitable for writing to a newly created disk or sanitizing a directory track.
        /// </summary>
        /// <returns></returns>
        public static DragonDosDirectoryEntry GetEmptyEntry()
        {
            var entry = new DragonDosDirectoryEntry();

            entry.Flags = DirectoryFlags.Invalid | DirectoryFlags.EndOfDirectory;
            return(entry);
        }
예제 #2
0
        /// <summary>
        /// Sets the directory entry at a given index.
        /// </summary>
        /// <param name="index"></param>
        /// <param name="entry"></param>
        private void SetDirectoryEntry(int index, DragonDosDirectoryEntry entry)
        {
            int sector = index / DirectoryEntryCount + DirectoryEntryOffset;
            int offset = index % DirectoryEntryCount * DirectoryEntrySize;

            entry.Encode(directoryTrack[sector], offset);
        }
예제 #3
0
        /// <summary>
        /// Create a set of directory entries for a file.
        /// </summary>
        /// <param name="filename">Filename</param>
        /// <param name="extents">Ordered list of extents containing the file payload data.</param>
        /// <param name="dirInx">Orderes list of directory entry indexes to use.</param>
        /// <returns>Orderes list of directory entries</returns>
        private DragonDosDirectoryEntry[] CreateDirectoryEntries(string filename, DragonDosDirectoryEntry.Extent[] extents, int[] dirInx, int lastSectorSize)
        {
            var dirEntries = new DragonDosDirectoryEntry[dirInx.Length];

            int maxExtents;
            int extentOffset = 0;

            for (int i = 0; i < dirInx.Length; i++)
            {
                var dir = new DragonDosDirectoryEntry()
                {
                    Flags = 0
                };
                if (i == 0)
                {
                    dir.Filename         = filename;
                    dir.IsExtensionEntry = false;
                    maxExtents           = 4;
                }
                else
                {
                    dir.IsExtensionEntry = true;
                    maxExtents           = 7;
                }

                if (i == dirInx.Length - 1)
                {
                    dir.LastSectorSize = lastSectorSize;
                }
                else
                {
                    dir.NextEntry = dirInx[i + 1];
                }

                dir.Extents = new DragonDosDirectoryEntry.Extent[Math.Min(maxExtents, extents.Length - extentOffset)];
                Array.Copy(extents, extentOffset, dir.Extents, 0, dir.Extents.Length);
                extentOffset += dir.Extents.Length;

                dirEntries[i] = dir;
            }

            return(dirEntries);
        }
예제 #4
0
        /// <summary>
        /// Initialize an empty DragonDos filesystem on a disk.
        /// </summary>
        /// <param name="disk">Disk to initialize filesystem on.</param>
        /// <returns>DragonDos filesystem.</returns>
        /// <exception cref="DiskNotWriteableException">The disk does not support write operations.</exception>
        /// <exception cref="UnsupportedGeometryException">The disk geometry is not supported by DragonDos.</exception>
        public static DragonDos Initialize(IDisk disk)
        {
            if (disk == null)
            {
                throw new ArgumentNullException("disk");
            }
            if (!disk.IsWriteable)
            {
                throw new DiskNotWriteableException();
            }

            if (disk.Tracks != 40 && disk.Tracks != 80)
            {
                throw new UnsupportedGeometryException(String.Format("DragonDos only supports 40 or 80 tracks while this disk has {0} tracks", disk.Tracks));
            }
            if (disk.Heads != 1 && disk.Heads != 2)
            {
                throw new UnsupportedGeometryException(String.Format("DragonDos only supports single or double sided disks while this disk has {0} sides", disk.Heads));
            }

            /* Write blank data to all sectors. */
            var sectorData = new byte[SectorSize];

            for (int t = 0; t < disk.Tracks; t++)
            {
                for (int h = 0; h < disk.Heads; h++)
                {
                    for (int s = 1; s < SectorsPerHead; s++)
                    {
                        disk.WriteSector(h, t, s, sectorData);
                    }
                }
            }

            /* Write empty directory entries to the directory track. */
            var emptyDirEntry     = DragonDosDirectoryEntry.GetEmptyEntry();
            var emptyEncodedEntry = new byte[DirectoryEntrySize];

            emptyDirEntry.Encode(emptyEncodedEntry, 0);
            for (int i = 0; i < DirectoryEntryCount; i++)
            {
                Array.Copy(emptyEncodedEntry, 0, sectorData, i * DirectoryEntrySize, DirectoryEntrySize);
            }
            for (int s = DirectoryEntryOffset + 1; s <= SectorsPerHead; s++)
            {
                disk.WriteSector(0, DirectoryTrackPrimary, s, sectorData);
                disk.WriteSector(0, DirectoryTrackBackup, s, sectorData);
            }

            /* Write the sector allocation map. */
            var allocationmap = new byte[2][];

            allocationmap[0] = new byte[SectorSize];
            allocationmap[1] = new byte[SectorSize];

            int sectors = SectorsPerHead * disk.Heads;

            allocationmap[0][252] = (byte)disk.Tracks;                          // encode disk geometry
            allocationmap[0][253] = (byte)sectors;
            allocationmap[0][254] = (byte)(~disk.Tracks & 0xff);
            allocationmap[0][255] = (byte)(~sectors & 0xff);

            for (var i = 0; i < disk.Tracks * disk.Heads * SectorsPerHead; i++)              // mark all sectors as unallocated
            {
                SetSectorAllocated(i, false, allocationmap);
            }

            int lsnPrimaryDirectory = DirectoryTrackPrimary * disk.Heads * SectorsPerHead;      // mark directory track as allocated
            int lsnBackupDirectory  = DirectoryTrackBackup * disk.Heads * SectorsPerHead;

            for (var i = 0; i < SectorsPerHead; i++)
            {
                SetSectorAllocated(lsnPrimaryDirectory++, true, allocationmap);
                SetSectorAllocated(lsnBackupDirectory++, true, allocationmap);
            }

            for (var i = 0; i < 2; i++)
            {
                disk.WriteSector(0, DirectoryTrackPrimary, i + 1, allocationmap[i]);
                disk.WriteSector(0, DirectoryTrackBackup, i + 1, allocationmap[i]);
            }

            return(new DragonDos(disk, true));
        }