Skip to content

Commit b42e92a

Browse files
committed
Lots of updates
1 parent 37b5c06 commit b42e92a

18 files changed

+1007
-336
lines changed

DiskImageTool/DiskImage/Directory.vb

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
Namespace DiskImage
22
Public Class Directory
3-
Private ReadOnly _FatClusterList As List(Of UShort)
3+
Private ReadOnly _FatChain As List(Of UShort)
44
Private ReadOnly _Parent As Disk
55
Private ReadOnly _Length As UInteger
66

7-
Sub New(Parent As Disk, Optional FatClusterList As List(Of UShort) = Nothing, Optional Length As UInteger = 0)
7+
Sub New(Parent As Disk, Optional FatChain As List(Of UShort) = Nothing, Optional Length As UInteger = 0)
88
_Parent = Parent
9-
_FatClusterList = FatClusterList
9+
_FatChain = FatChain
1010
_Length = Length
1111
End Sub
1212

1313
Public Function GetContent() As Byte()
14-
If _FatClusterList Is Nothing Then
14+
If _FatChain Is Nothing Then
1515
Return GetContentRoot()
1616
Else
1717
Return GetContentSubDirectory()
@@ -28,7 +28,7 @@
2828
End Function
2929

3030
Private Function GetContentSubDirectory() As Byte()
31-
Dim Content = _Parent.GetDataFromFATClusterList(_FatClusterList)
31+
Dim Content = _Parent.GetDataFromFATClusterList(_FatChain)
3232
If Content.Length <> _Length Then
3333
Array.Resize(Of Byte)(Content, _Length)
3434
End If
@@ -45,13 +45,13 @@
4545
End Function
4646

4747
Private Function GetDataBlocksSubDirectory() As List(Of DataBlock)
48-
Return _Parent.GetDataBlocksFromFATClusterList(_FatClusterList)
48+
Return _Parent.GetDataBlocksFromFATClusterList(_FatChain)
4949
End Function
5050

5151
Private Function GetDirectoryLengthSubDirectory(FileCountOnly As Boolean) As UInteger
5252
Dim Count As UInteger = 0
5353

54-
For Each Cluster In _FatClusterList
54+
For Each Cluster In _FatChain
5555
Dim OffsetStart As UInteger = _Parent.ClusterToOffset(Cluster)
5656
Dim OffsetLength As UInteger = _Parent.BootSector.BytesPerCluster
5757

@@ -73,7 +73,7 @@
7373
Dim EntriesPerCluster As UInteger = _Parent.BootSector.BytesPerCluster / 32
7474
Dim ChainIndex As UInteger = (Index - 1) \ EntriesPerCluster
7575
Dim ClusterIndex As UInteger = (Index - 1) Mod EntriesPerCluster
76-
Dim Offset As UInteger = _Parent.ClusterToOffset(_FatClusterList.Item(ChainIndex)) + ClusterIndex * 32
76+
Dim Offset As UInteger = _Parent.ClusterToOffset(_FatChain.Item(ChainIndex)) + ClusterIndex * 32
7777

7878
Return New DirectoryEntry(_Parent, Offset)
7979
End Function
@@ -85,31 +85,31 @@
8585
End Function
8686

8787
Public Function DirectoryLength() As UInteger
88-
If _FatClusterList Is Nothing Then
88+
If _FatChain Is Nothing Then
8989
Return GetDirectoryLengthRoot(False)
9090
Else
9191
Return GetDirectoryLengthSubDirectory(False)
9292
End If
9393
End Function
9494

9595
Public Function FileCount() As UInteger
96-
If _FatClusterList Is Nothing Then
96+
If _FatChain Is Nothing Then
9797
Return GetDirectoryLengthRoot(True)
9898
Else
9999
Return GetDirectoryLengthSubDirectory(True)
100100
End If
101101
End Function
102102

103103
Public Function GetFile(Index As UInteger) As DirectoryEntry
104-
If _FatClusterList Is Nothing Then
104+
If _FatChain Is Nothing Then
105105
Return GetFileRoot(Index)
106106
Else
107107
Return GetFileSubDirectory(Index)
108108
End If
109109
End Function
110110

111111
Public Function GetDataBlocks() As List(Of DataBlock)
112-
If _FatClusterList Is Nothing Then
112+
If _FatChain Is Nothing Then
113113
Return New List(Of DataBlock) From {
114114
GetDataBlockRoot()
115115
}

DiskImageTool/DiskImage/DirectoryEntry.vb

Lines changed: 70 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,24 @@ Namespace DiskImage
2121
End Enum
2222

2323
Public Class DirectoryEntry
24+
Private Shared ReadOnly CP437LookupTable As Integer() = New Integer(255) {
25+
0, 9786, 9787, 9829, 9830, 9827, 9824, 8226, 9688, 9675, 9689, 9794, 9792, 9834, 9835, 9788,
26+
9658, 9668, 8597, 8252, 182, 167, 9644, 8616, 8593, 8595, 8594, 8592, 8735, 8596, 9650, 9660,
27+
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
28+
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
29+
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
30+
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
31+
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
32+
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 8962,
33+
199, 252, 233, 226, 228, 224, 229, 231, 234, 235, 232, 239, 238, 236, 196, 197,
34+
201, 230, 198, 244, 246, 242, 251, 249, 255, 214, 220, 162, 163, 165, 8359, 402,
35+
225, 237, 243, 250, 241, 209, 170, 186, 191, 8976, 172, 189, 188, 161, 171, 187,
36+
9617, 9618, 9619, 9474, 9508, 9569, 9570, 9558, 9557, 9571, 9553, 9559, 9565, 9564, 9563, 9488,
37+
9492, 9524, 9516, 9500, 9472, 9532, 9566, 9567, 9562, 9556, 9577, 9574, 9568, 9552, 9580, 9575,
38+
9576, 9572, 9573, 9561, 9560, 9554, 9555, 9579, 9578, 9496, 9484, 9608, 9604, 9612, 9616, 9600,
39+
945, 223, 915, 960, 931, 963, 181, 964, 934, 920, 937, 948, 8734, 966, 949, 8745,
40+
8801, 177, 8805, 8804, 8992, 8993, 247, 8776, 176, 8729, 183, 8730, 8319, 178, 9632, 160
41+
}
2442
Private Const DIRECTORY_ENTRY_SIZE As Byte = 32
2543
Private Const CHAR_SPACE As Byte = 32
2644
Public Enum AttributeFlags
@@ -61,26 +79,43 @@ Namespace DiskImage
6179
LFNFilePart3 = 4
6280
End Enum
6381

64-
Private ReadOnly _FatClusterList As List(Of UShort)
6582
Private _Data() As Byte
6683
Private ReadOnly _Offset As UInteger
84+
Private ReadOnly _FatChain As FATChain
6785
Private WithEvents Parent As Disk
6886
Private _SubDirectory As Directory
6987

7088
Sub New(Parent As Disk, Offset As UInteger)
7189
Me.Parent = Parent
7290
_Offset = Offset
91+
7392
LoadData()
7493

75-
If IsDeleted() Then
76-
_FatClusterList = New List(Of UShort)
94+
If _Parent.FATChains.ContainsKey(Offset) Then
95+
_FatChain = _Parent.FATChains.Item(Offset)
7796
Else
78-
_FatClusterList = GetFATClusterList()
97+
If IsDeleted() Then
98+
_FatChain = _Parent.InitFATChain(Offset, 0)
99+
ElseIf IsDirectory() AndAlso {".", ".."}.Contains(GetFullFileName) Then
100+
_FatChain = _Parent.InitFATChain(Offset, 0)
101+
Else
102+
_FatChain = _Parent.InitFATChain(Offset, StartingCluster)
103+
End If
79104
End If
80105

81106
InitSubDirectory()
82107
End Sub
83108

109+
Public Shared Function CP437ToUnicode(b() As Byte) As String
110+
Dim b2(b.Length - 1) As UShort
111+
For counter = 0 To b.Length - 1
112+
b2(counter) = CP437LookupTable(b(counter))
113+
Next
114+
ReDim b(b2.Length * 2 - 1)
115+
Buffer.BlockCopy(b2, 0, b, 0, b.Length)
116+
Return Encoding.Unicode.GetString(b)
117+
End Function
118+
84119
Public Shared Function DateToFATDate(D As Date) As UShort
85120
Dim FATDate As UShort = D.Year - 1980
86121

@@ -224,11 +259,11 @@ Namespace DiskImage
224259
End Function
225260

226261
Public Function GetDataBlocks() As List(Of DataBlock)
227-
Return Parent.GetDataBlocksFromFATClusterList(_FatClusterList)
262+
Return Parent.GetDataBlocksFromFATClusterList(_FatChain.Chain)
228263
End Function
229264

230265
Public Function GetContent() As Byte()
231-
Dim Content = Parent.GetDataFromFATClusterList(_FatClusterList)
266+
Dim Content = Parent.GetDataFromFATClusterList(_FatChain.Chain)
232267

233268
If Content.Length <> FileSize Then
234269
Array.Resize(Of Byte)(Content, FileSize)
@@ -237,39 +272,16 @@ Namespace DiskImage
237272
Return Content
238273
End Function
239274

240-
Private Function GetFATClusterList() As List(Of UShort)
241-
Dim FATClusterList = New List(Of UShort)
242-
Dim Cluster As UShort = StartingCluster
243-
Dim AssignedClusters As New Hashtable
244-
Do
245-
If Cluster > 1 And Cluster <= UBound(Parent.FAT12) Then
246-
If AssignedClusters.ContainsKey(Cluster) Then
247-
Exit Do
248-
End If
249-
AssignedClusters.Add(Cluster, Cluster)
250-
FATClusterList.Add(Cluster)
251-
If Not Parent.FileAllocation.ContainsKey(Cluster) Then
252-
Parent.FileAllocation.Add(Cluster, _Offset)
253-
End If
254-
Cluster = Parent.FAT12(Cluster)
255-
Else
256-
Cluster = 0
257-
End If
258-
Loop Until Cluster < &H2 Or Cluster > &HFEF
259-
260-
Return FATClusterList
261-
End Function
262-
263275
Public Function GetFileExtension() As String
264-
Return Encoding.UTF8.GetString(Extension).TrimEnd(" ")
276+
Return CP437ToUnicode(Extension).TrimEnd(" ")
265277
End Function
266278

267279
Public Function GetFileName() As String
268-
Return Encoding.UTF8.GetString(FileName).TrimEnd(" ")
280+
Return CP437ToUnicode(FileName).TrimEnd(" ")
269281
End Function
270282

271283
Public Function GetVolumeName() As String
272-
Return Encoding.UTF8.GetString(FileName) & Encoding.UTF8.GetString(Extension).TrimEnd(" ")
284+
Return CP437ToUnicode(FileName) & CP437ToUnicode(Extension).TrimEnd(" ")
273285
End Function
274286

275287
Public Function GetFullFileName() As String
@@ -328,13 +340,17 @@ Namespace DiskImage
328340
Return FileSize > Parent.BootSector.ImageSize
329341
End Function
330342

343+
Public Function HasInvalidStartingCluster() As Boolean
344+
Return StartingCluster = 1 Or StartingCluster > _Parent.BootSector.NumberOfFATEntries + 1
345+
End Function
346+
331347
Public Function HasIncorrectFileSize() As Boolean
332348
If IsDirectory() Then
333349
Return False
334350
End If
335351

336352
Dim AllocatedSize As UInteger = Math.Ceiling(FileSize / _Parent.BootSector.BytesPerCluster) * _Parent.BootSector.BytesPerCluster
337-
Dim AllocatedSizeFromFAT As UInteger = _FatClusterList.Count * _Parent.BootSector.BytesPerCluster
353+
Dim AllocatedSizeFromFAT As UInteger = _FatChain.Chain.Count * _Parent.BootSector.BytesPerCluster
338354

339355
Return AllocatedSize <> AllocatedSizeFromFAT
340356
End Function
@@ -345,7 +361,7 @@ Namespace DiskImage
345361

346362
Private Sub InitSubDirectory()
347363
If IsDirectory() And Not IsDeleted() Then
348-
_SubDirectory = New Directory(Parent, _FatClusterList, FileSize)
364+
_SubDirectory = New Directory(Parent, _FatChain.Chain, FileSize)
349365
Else
350366
_SubDirectory = Nothing
351367
End If
@@ -355,6 +371,10 @@ Namespace DiskImage
355371
Return (Attributes And AttributeFlags.ArchiveFlag) > 0
356372
End Function
357373

374+
Public Function IsCrossLinked() As Boolean
375+
Return _FatChain.CrossLinks.Count > 0
376+
End Function
377+
358378
Public Function IsDeleted() As Boolean
359379
Return FileName(0) = &HE5
360380
End Function
@@ -374,8 +394,8 @@ Namespace DiskImage
374394
Public Function IsModified() As Boolean
375395
Dim HasModification As Boolean = Parent.HasModification(_Offset)
376396
If Not HasModification Then
377-
If _FatClusterList.Count > 0 Then
378-
Dim ClusterOffset = _Parent.ClusterToOffset(_FatClusterList(0))
397+
If _FatChain.Chain.Count > 0 Then
398+
Dim ClusterOffset = _Parent.ClusterToOffset(_FatChain.Chain(0))
379399
HasModification = Parent.HasModification(ClusterOffset)
380400
End If
381401
End If
@@ -453,6 +473,12 @@ Namespace DiskImage
453473
End Set
454474
End Property
455475

476+
Public ReadOnly Property CrossLinks() As List(Of UInteger)
477+
Get
478+
Return _FatChain.CrossLinks
479+
End Get
480+
End Property
481+
456482
Public Property Extension() As Byte()
457483
Get
458484
Return GetBytes(DirectoryEntryOffset.Extension, DirectoryEntrySize.Extension)
@@ -462,9 +488,9 @@ Namespace DiskImage
462488
End Set
463489
End Property
464490

465-
Public ReadOnly Property FatClusterList As List(Of UShort)
491+
Public ReadOnly Property FATChain As List(Of UShort)
466492
Get
467-
Return _FatClusterList
493+
Return _FatChain.Chain
468494
End Get
469495
End Property
470496

@@ -486,6 +512,12 @@ Namespace DiskImage
486512
End Set
487513
End Property
488514

515+
Public ReadOnly Property HasCircularChain As Boolean
516+
Get
517+
Return _FatChain.HasCircularChain
518+
End Get
519+
End Property
520+
489521
Public Property LastAccessDate() As UShort
490522
Get
491523
Return GetBytesShort(DirectoryEntryOffset.LastAccessDate)

0 commit comments

Comments
 (0)