/// <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); }
/// <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); }
/// <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); }
/// <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)); }