Skip to content

Commit 3cfc4c0

Browse files
committed
Can now detect additional data stored in a directory
Can now detect if a copy of the boot sector is stored in a directory Added color coding to the directory hex view Can now view the parent directory from the file context menu Added new tools to manage a boot sector stored in a directory
1 parent 9c47d90 commit 3cfc4c0

18 files changed

+493
-121
lines changed

DiskImageTool/Assets/bootstrap.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@
423423
<oemname name="LHX TWO " company="Electronic Arts" description="LHX: ATTACK CHOPPER Disk Two" />
424424
</bootstrap>
425425
<bootstrap crc32="8CD8F888">
426-
<oemname name="MagicISO" company="MagicISO, Inc." description="MagicISO 4.70" />
426+
<oemname name="MagicISO" company="MagicISO, Inc." description="MagicISO 4.70" note="Not imaged from Original Media" />
427427
</bootstrap>
428428
<bootstrap crc32="5B5678E2">
429429
<oemname name="MSC 3.1 " />

DiskImageTool/Copy Protection.vb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ Module Copy_Protection
5353
'Origin Systems OSI-1
5454
If Not ProtectionFound AndAlso Disk.FAT.BadSectors.Count >= 10 Then
5555
If CheckBadSectors(Disk, {108, 109, 110, 111, 112, 113, 114, 115, 116, 117}) _
56-
AndAlso CheckFileList(Disk, {"2400AD.EXE", "ULTIMA.COM", "ULTIMA.EXE", "ULTIMAII.EXE"}) Then
56+
AndAlso CheckFileList(Disk, {"2400AD.EXE", "ULTIMA.COM", "ULTIMA.EXE", "ULTIMAII.EXE", "LORE.EXE"}) Then
5757

5858
ProtectionFound = True
5959
ProtectionName = "Origin Systems OSI-1"

DiskImageTool/DiskImage/BootSector.vb

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
Imports System.Text
2-
3-
Namespace DiskImage
1+
Namespace DiskImage
42

53
Public Class BootSector
64
Private Const BOOT_SECTOR As UInteger = 0
5+
Public Const BOOT_SECTOR_SIZE As UShort = 512
76
Private ReadOnly _FileBytes As ImageByteArray
87
Public Shared ReadOnly ValidBootStrapSignature As UShort = &HAA55
98
Public Shared ReadOnly ValidBytesPerSector() As UShort = {512, 1024, 2048, 4096}
109
Public Shared ReadOnly ValidDriveNumber() As Byte = {&H0, &H80}
1110
Public Shared ReadOnly ValidExtendedBootSignature() As Byte = {&H28, &H29}
12-
'Private Shared ReadOnly _ValidJumpInstructuon() As Byte = {&HEB, &HE9}
11+
Public Shared ReadOnly ValidJumpInstructuon() As Byte = {&HEB, &HE9}
1312
Public Shared ReadOnly ValidMediaDescriptor() As Byte = {&HF0, &HF8, &HF9, &HFA, &HFB, &HFC, &HFD, &HFE, &HFF}
1413
Public Shared ReadOnly ValidSectorsPerCluster() As Byte = {1, 2, 4, 8, 16, 32, 64, 128}
1514

DiskImageTool/DiskImage/Classes.vb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
Namespace DiskImage
2+
23
Public Structure ExpandedDate
34
Dim DateObject As Date
45
Dim Day As Byte
@@ -178,4 +179,14 @@
178179
Return DataBytes.GetBytes(SectorBlock.Offset, SectorBlock.Size)
179180
End Function
180181
End Class
182+
183+
Public Class DirectoryData
184+
Public Property MaxEntries As UInteger = 0
185+
Public Property EntryCount As UInteger = 0
186+
Public Property FileCount As UInteger = 0
187+
Public Property DeletedFileCount As UInteger = 0
188+
Public Property HasAdditionalData As Boolean = False
189+
Public Property HasBootSector As Boolean = False
190+
Public Property BootSectorOffset As UInteger = 0
191+
End Class
181192
End Namespace

DiskImageTool/DiskImage/DirectoryEntry.vb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Namespace DiskImage
44

55
Public Class DirectoryEntry
66
Private Const CHAR_SPACE As Byte = 32
7-
Private Const CHAR_DELETED As Byte = &HE5
7+
Public Const CHAR_DELETED As Byte = &HE5
88
Public Const DIRECTORY_ENTRY_SIZE As Byte = 32
99
Private ReadOnly _FatChain As FATChain
1010
Private ReadOnly _FAT As FAT12
@@ -200,7 +200,7 @@ Namespace DiskImage
200200
End Get
201201
End Property
202202

203-
Public ReadOnly Property Offset As Integer
203+
Public ReadOnly Property Offset As UInteger
204204
Get
205205
Return _Offset
206206
End Get
@@ -474,7 +474,7 @@ Namespace DiskImage
474474
End Sub
475475

476476
Private Sub InitSubDirectory()
477-
If IsDirectory() And Not IsDeleted() Then
477+
If IsDirectory() AndAlso Not IsLink() AndAlso Not IsDeleted() Then
478478
_SubDirectory = New SubDirectory(_FileBytes, _BootSector, _FAT, _FatChain, FileSize)
479479
Else
480480
_SubDirectory = Nothing

DiskImageTool/DiskImage/Disk.vb

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,7 @@ Namespace DiskImage
2626
_FAT12 = New FAT12(FileBytes, _BootSector, 0, False)
2727
_Directory = New RootDirectory(FileBytes, _BootSector, _FAT12)
2828

29-
If _BootSector.IsValidImage Then
30-
CacheDirectoryEntries(_Directory)
31-
End If
29+
CacheDirectoryEntries()
3230

3331
If Modifications IsNot Nothing Then
3432
FileBytes.ApplyModifications(Modifications)
@@ -95,7 +93,7 @@ Namespace DiskImage
9593

9694
Public Function GetVolumeLabel() As DirectoryEntry
9795
Dim VolumeLabel As DirectoryEntry = Nothing
98-
Dim DirectoryEntryCount = _Directory.DirectoryEntryCount
96+
Dim DirectoryEntryCount = _Directory.Data.EntryCount
9997

10098
If DirectoryEntryCount > 0 Then
10199
For Counter As UInteger = 0 To DirectoryEntryCount - 1
@@ -137,16 +135,25 @@ Namespace DiskImage
137135

138136
Public Sub Reinitialize()
139137
_FAT12.PopulateFAT12(0, False)
138+
_Directory.RefreshData()
139+
140140
_ReinitializeRequired = False
141141
End Sub
142142
Public Sub SaveFile(FilePath As String)
143143
IO.File.WriteAllBytes(FilePath, FileBytes.Data)
144144
FileBytes.ClearChanges()
145-
CacheDirectoryEntries(_Directory)
145+
CacheDirectoryEntries()
146+
End Sub
147+
148+
Private Sub CacheDirectoryEntries()
149+
FileBytes.DirectoryCache.Clear()
150+
If _BootSector.IsValidImage Then
151+
CacheDirectoryEntries(_Directory)
152+
End If
146153
End Sub
147154

148155
Private Sub CacheDirectoryEntries(Directory As DiskImage.IDirectory)
149-
Dim DirectoryEntryCount = Directory.DirectoryEntryCount
156+
Dim DirectoryEntryCount = Directory.Data.EntryCount
150157

151158
If DirectoryEntryCount > 0 Then
152159
For Counter = 0 To DirectoryEntryCount - 1
@@ -155,7 +162,7 @@ Namespace DiskImage
155162
If Not File.IsLink Then
156163
FileBytes.DirectoryCache.Item(File.Offset) = File.Data
157164
If File.IsDirectory And File.SubDirectory IsNot Nothing Then
158-
If File.SubDirectory.DirectoryEntryCount > 0 Then
165+
If File.SubDirectory.Data.EntryCount > 0 Then
159166
CacheDirectoryEntries(File.SubDirectory)
160167
End If
161168
End If

DiskImageTool/DiskImage/FAT12.vb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,15 +245,15 @@
245245
End Sub
246246

247247
Private Sub EnumDirectoryEntries(Directory As DiskImage.IDirectory)
248-
Dim DirectoryEntryCount = Directory.DirectoryEntryCount
248+
Dim DirectoryEntryCount = Directory.Data.EntryCount
249249

250250
If DirectoryEntryCount > 0 Then
251251
For Counter = 0 To DirectoryEntryCount - 1
252252
Dim File = Directory.GetFile(Counter)
253253

254254
If Not File.IsLink Then
255255
If File.IsDirectory And File.SubDirectory IsNot Nothing Then
256-
If File.SubDirectory.DirectoryEntryCount > 0 Then
256+
If File.SubDirectory.Data.EntryCount > 0 Then
257257
EnumDirectoryEntries(File.SubDirectory)
258258
End If
259259
End If

DiskImageTool/DiskImage/Functions.vb

Lines changed: 80 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ Namespace DiskImage
8787
End Function
8888

8989
Public Function BuildBootSectorFromType(Type As FloppyDiskType) As BootSector
90-
Dim Data(511) As Byte
90+
Dim Data(DiskImage.BootSector.BOOT_SECTOR_SIZE - 1) As Byte
9191
Dim FileBytes As New ImageByteArray(Data)
9292
Dim BootSector = New BootSector(FileBytes)
9393

@@ -395,27 +395,88 @@ Namespace DiskImage
395395
Return Content
396396
End Function
397397

398-
Public Function GetDirectoryEntryCount(FileBytes As ByteArray, OffsetStart As UInteger, OffsetEnd As UInteger, FileCountOnly As Boolean, ExcludeDeleted As Boolean) As UInteger
399-
Dim Count As UInteger = 0
400-
401-
Do While FileBytes.GetByte(OffsetStart) > 0
402-
If Not ExcludeDeleted OrElse FileBytes.GetByte(OffsetStart) <> &HE5 Then
403-
If Not FileCountOnly Then
404-
Count += 1
405-
ElseIf FileBytes.GetByte(OffsetStart + 11) <> &HF Then 'Exclude LFN entries
406-
Dim FilePart = FileBytes.ToUInt16(OffsetStart)
407-
If FilePart <> &H202E And FilePart <> &H2E2E Then 'Exclude '.' and '..' entries
408-
Count += 1
409-
End If
398+
Public Function DirectoryEntryHasData(FileBytes As ByteArray, Offset As UInteger) As Boolean
399+
Dim Result As Boolean = False
400+
401+
402+
If FileBytes.GetByte(Offset) = &HE5 Then
403+
For Offset2 As UInteger = Offset + 1 To Offset + DirectoryEntry.DIRECTORY_ENTRY_SIZE - 1
404+
If FileBytes.GetByte(Offset2) <> 0 Then
405+
Result = True
406+
Exit For
407+
End If
408+
Next
409+
ElseIf FileBytes.GetByte(Offset) <> 0 Then
410+
Result = True
411+
Else
412+
Dim HexF6Count As UInteger = 0
413+
For Offset2 As UInteger = Offset + 1 To Offset + DirectoryEntry.DIRECTORY_ENTRY_SIZE - 1
414+
If FileBytes.GetByte(Offset2) = &HF6 Then
415+
HexF6Count += 1
416+
ElseIf FileBytes.GetByte(Offset2) <> 0 Then
417+
Result = True
418+
Exit For
419+
End If
420+
Next
421+
If Not Result Then
422+
If HexF6Count > 0 And HexF6Count < DirectoryEntry.DIRECTORY_ENTRY_SIZE - 2 Then
423+
Result = True
410424
End If
411425
End If
412-
OffsetStart += 32
413-
If OffsetEnd > 0 And OffsetStart >= OffsetEnd Then
414-
Exit Do
415-
End If
416-
Loop
426+
End If
427+
428+
Return Result
429+
End Function
430+
431+
Public Function GetDirectoryData(Data As DirectoryData, FileBytes As ByteArray, OffsetStart As UInteger, OffsetEnd As UInteger, EndOfDirectory As Boolean, CheckBootSector As Boolean) As Boolean
432+
Dim EntryCount = (OffsetEnd - OffsetStart) \ DirectoryEntry.DIRECTORY_ENTRY_SIZE
433+
434+
Data.MaxEntries += EntryCount
435+
436+
If EntryCount > 0 Then
437+
For Entry As UInteger = 0 To EntryCount - 1
438+
Dim Offset = OffsetStart + (Entry * DirectoryEntry.DIRECTORY_ENTRY_SIZE)
439+
Dim FirstByte = FileBytes.GetByte(Offset)
440+
If FirstByte = 0 Then
441+
EndOfDirectory = True
442+
End If
443+
If Not Data.HasBootSector And CheckBootSector Then
444+
If BootSector.ValidJumpInstructuon.Contains(FirstByte) Then
445+
If OffsetEnd - Offset >= BootSector.BOOT_SECTOR_SIZE Then
446+
Dim BootSectorData = FileBytes.GetBytes(Offset, DiskImage.BootSector.BOOT_SECTOR_SIZE)
447+
Dim BootSector = New BootSector(New ImageByteArray(BootSectorData))
448+
If BootSector.IsValidImage Then
449+
Data.HasBootSector = True
450+
Data.BootSectorOffset = Offset
451+
EndOfDirectory = True
452+
End If
453+
End If
454+
End If
455+
End If
456+
If EndOfDirectory Then
457+
If Not Data.HasAdditionalData Then
458+
If Not Data.HasBootSector Or Offset < Data.BootSectorOffset Or Offset > Data.BootSectorOffset + DiskImage.BootSector.BOOT_SECTOR_SIZE Then
459+
If DirectoryEntryHasData(FileBytes, Offset) Then
460+
Data.HasAdditionalData = True
461+
End If
462+
End If
463+
End If
464+
Else
465+
Data.EntryCount += 1
466+
If FileBytes.GetByte(Offset + 11) <> &HF Then 'Exclude LFN entries
467+
Dim FilePart = FileBytes.ToUInt16(Offset)
468+
If FilePart <> &H202E And FilePart <> &H2E2E Then 'Exclude '.' and '..' entries
469+
Data.FileCount += 1
470+
If FirstByte = DirectoryEntry.CHAR_DELETED Then
471+
Data.DeletedFileCount += 1
472+
End If
473+
End If
474+
End If
475+
End If
476+
Next
477+
End If
417478

418-
Return Count
479+
Return EndOfDirectory
419480
End Function
420481

421482
Public Function GetObjectSize(o As Object) As Integer
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
Namespace DiskImage
22
Public Interface IDirectory
3+
ReadOnly Property Data As DirectoryData
34
ReadOnly Property SectorChain As List(Of UInteger)
4-
Function DirectoryEntryCount() As UInteger
5-
Function FileCount(ExcludeDeleted As Boolean) As UInteger
65
Function GetContent() As Byte()
76
Function GetFile(Index As UInteger) As DirectoryEntry
87
Function HasFile(Filename As String) As Boolean
8+
Sub RefreshData()
99
End Interface
1010
End Namespace

DiskImageTool/DiskImage/RootDirectory.vb

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,25 @@
55
Private ReadOnly _BootSector As BootSector
66
Private ReadOnly _FAT As FAT12
77
Private ReadOnly _FileBytes As ImageByteArray
8+
Private _DirectoryData As DirectoryData
89

910
Sub New(FileBytes As ImageByteArray, BootSector As BootSector, FAT As FAT12)
1011
_BootSector = BootSector
1112
_FAT = FAT
1213
_FileBytes = FileBytes
14+
If BootSector.IsValidImage Then
15+
_DirectoryData = GetDirectoryData()
16+
Else
17+
_DirectoryData = New DirectoryData
18+
End If
1319
End Sub
1420

21+
Public ReadOnly Property Data As DirectoryData Implements IDirectory.Data
22+
Get
23+
Return _DirectoryData
24+
End Get
25+
End Property
26+
1527
Public ReadOnly Property SectorChain As List(Of UInteger) Implements IDirectory.SectorChain
1628
Get
1729
Dim Chain = New List(Of UInteger)
@@ -24,14 +36,6 @@
2436
End Get
2537
End Property
2638

27-
Public Function DirectoryEntryCount() As UInteger Implements IDirectory.DirectoryEntryCount
28-
Return GetDirectoryEntryCount(False, False)
29-
End Function
30-
31-
Public Function FileCount(ExcludeDeleted As Boolean) As UInteger Implements IDirectory.FileCount
32-
Return GetDirectoryEntryCount(True, ExcludeDeleted)
33-
End Function
34-
3539
Public Function GetContent() As Byte() Implements IDirectory.GetContent
3640
Dim SectorStart = _BootSector.RootDirectoryRegionStart
3741
Dim SectorEnd = _BootSector.DataRegionStart
@@ -42,13 +46,13 @@
4246
End Function
4347

4448
Public Function GetFile(Index As UInteger) As DirectoryEntry Implements IDirectory.GetFile
45-
Dim Offset As UInteger = SectorToBytes(_BootSector.RootDirectoryRegionStart) + Index * 32
49+
Dim Offset As UInteger = SectorToBytes(_BootSector.RootDirectoryRegionStart) + Index * DirectoryEntry.DIRECTORY_ENTRY_SIZE
4650

4751
Return New DirectoryEntry(_FileBytes, _BootSector, _FAT, Offset)
4852
End Function
4953

5054
Public Function HasFile(Filename As String) As Boolean Implements IDirectory.HasFile
51-
Dim Count = GetDirectoryEntryCount(False, False)
55+
Dim Count = _DirectoryData.EntryCount
5256
If Count > 0 Then
5357
For Counter As UInteger = 0 To Count - 1
5458
Dim File = GetFile(Counter)
@@ -63,11 +67,22 @@
6367
Return False
6468
End Function
6569

66-
Private Function GetDirectoryEntryCount(FileCountOnly As Boolean, ExcludeDeleted As Boolean) As UInteger
70+
Public Sub RefreshData() Implements IDirectory.RefreshData
71+
If _BootSector.IsValidImage Then
72+
_DirectoryData = GetDirectoryData()
73+
Else
74+
_DirectoryData = New DirectoryData
75+
End If
76+
End Sub
77+
78+
Private Function GetDirectoryData() As DirectoryData
6779
Dim OffsetStart As UInteger = SectorToBytes(_BootSector.RootDirectoryRegionStart)
6880
Dim OffsetEnd As UInteger = SectorToBytes(_BootSector.DataRegionStart)
81+
Dim Data As New DirectoryData
82+
83+
Functions.GetDirectoryData(Data, _FileBytes, OffsetStart, OffsetEnd, False, True)
6984

70-
Return Functions.GetDirectoryEntryCount(_FileBytes, OffsetStart, OffsetEnd, FileCountOnly, ExcludeDeleted)
85+
Return Data
7186
End Function
7287
End Class
7388
End Namespace

0 commit comments

Comments
 (0)