Skip to content

Commit 55fc6b4

Browse files
committed
Add full TD0 export support with encoding/decoding
Implemented TD0 (Teledisk) image export, supporting all sector data formats: raw, repeated 2-byte pattern, and RLE. Added BytePattern and RLE modules for encoding/decoding. Refactored TD0 structures and classes for easier serialization and CRC handling. Improved code clarity with named enums and settable encoding methods. Application can now generate valid TD0 disk images.
1 parent bb7b805 commit 55fc6b4

File tree

12 files changed

+547
-146
lines changed

12 files changed

+547
-146
lines changed

DiskImageTool/DiskImageTool.vbproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@
197197
<Compile Include="Forms\ImagePreview.vb">
198198
<SubType>Form</SubType>
199199
</Compile>
200+
<Compile Include="ImageFormats\TD0\TD0BytePattern.vb" />
200201
<Compile Include="ImageFormats\TD0\TD0Comment.vb" />
201202
<Compile Include="ImageFormats\TD0\TD0Crc16.vb" />
202203
<Compile Include="ImageFormats\TD0\TD0Enums.vb" />
@@ -206,6 +207,7 @@
206207
<Compile Include="ImageFormats\TD0\TD0Loader.vb" />
207208
<Compile Include="ImageFormats\TD0\TD0Lzhuf.vb" />
208209
<Compile Include="ImageFormats\TD0\TD0Lzw.vb" />
210+
<Compile Include="ImageFormats\TD0\TD0Rle.vb" />
209211
<Compile Include="ImageFormats\TD0\TD0Sector.vb" />
210212
<Compile Include="ImageFormats\TD0\TD0SectorDataHeader.vb" />
211213
<Compile Include="ImageFormats\TD0\TD0SectorHeader.vb" />
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
Namespace ImageFormats.TD0
2+
Module TD0BytePattern
3+
Friend Function BytePatternCanEncode(data As Byte()) As Boolean
4+
If data Is Nothing OrElse data.Length < 2 Then
5+
Return False
6+
End If
7+
8+
Dim p0 As Byte = data(0)
9+
Dim p1 As Byte = data(1)
10+
11+
Dim i As Integer = 0
12+
Dim n As Integer = data.Length
13+
14+
' Check full 2-byte pairs
15+
While i + 1 < n
16+
If data(i) <> p0 OrElse data(i + 1) <> p1 Then
17+
Return False
18+
End If
19+
i += 2
20+
End While
21+
22+
' Optional odd trailing byte (rare for TD0, but allowed)
23+
If i < n Then
24+
If data(i) <> p0 Then Return False
25+
End If
26+
27+
Return True
28+
End Function
29+
30+
Friend Function BytePatternDecode(src As Byte(),
31+
srcOffset As Integer,
32+
decodedLength As Integer,
33+
payloadBytes As Integer) As (Result As Boolean, Data As Byte(), BytesConsumed As Integer, BytesWritten As Integer)
34+
35+
If src Is Nothing OrElse decodedLength < 0 OrElse payloadBytes < 0 OrElse srcOffset < 0 OrElse srcOffset > src.Length Then
36+
Return (False, Nothing, 0, 0)
37+
End If
38+
39+
Dim dst(decodedLength - 1) As Byte
40+
41+
Dim srcEnd As Integer = Math.Min(src.Length, srcOffset + payloadBytes)
42+
Dim s As Integer = srcOffset
43+
Dim d As Integer = 0
44+
45+
While d < decodedLength AndAlso (s + 4) <= srcEnd
46+
Dim countWords As Integer = ReadUInt16LE(src, s)
47+
Dim p0 As Byte = src(s + 2)
48+
Dim p1 As Byte = src(s + 3)
49+
s += 4
50+
51+
If countWords <= 0 Then Exit While
52+
53+
Dim bytesToWrite As Integer = countWords * 2
54+
Dim remaining As Integer = decodedLength - d
55+
If bytesToWrite > remaining Then bytesToWrite = remaining
56+
57+
Dim pairs As Integer = bytesToWrite \ 2
58+
For i As Integer = 0 To pairs - 1
59+
dst(d) = p0 : d += 1
60+
dst(d) = p1 : d += 1
61+
Next
62+
63+
' odd tail (kept to match your original safety behavior)
64+
If (bytesToWrite And 1) <> 0 Then
65+
dst(d) = p0
66+
d += 1
67+
End If
68+
End While
69+
70+
Return (True, dst, s - srcOffset, d)
71+
End Function
72+
Friend Function BytePatternEncode(data As Byte()) As Byte()
73+
Dim countWords As Integer = data.Length \ 2
74+
75+
Dim out(3) As Byte
76+
WriteUInt16LE(out, 0, countWords)
77+
out(2) = data(0)
78+
out(3) = data(1)
79+
80+
Return out
81+
End Function
82+
83+
End Module
84+
End Namespace

DiskImageTool/ImageFormats/TD0/TD0Comment.vb

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,23 @@
33
Namespace ImageFormats.TD0
44
Public NotInheritable Class TD0Comment
55
Public Const HEADER_LENGTH As Integer = 10
6+
Private Const CRC_START As Integer = Offset.DataLength
7+
Private Const CRC_END As Integer = Offset.Second
68

79
Private ReadOnly _data As Byte()
810
Private ReadOnly _header As Byte()
911

12+
Private Enum Offset As Integer
13+
Crc16 = 0
14+
DataLength = 2
15+
Year = 4
16+
Month0 = 5
17+
Day = 6
18+
Hour = 7
19+
Minute = 8
20+
Second = 9
21+
End Enum
22+
1023
Public Sub New(imagebuf As Byte(), offset As Integer)
1124
_header = New Byte(HEADER_LENGTH - 1) {}
1225
_data = Array.Empty(Of Byte)()
@@ -35,33 +48,44 @@ Namespace ImageFormats.TD0
3548
End If
3649
End Sub
3750

51+
Public Function GetBytes() As Byte()
52+
Dim totalLen As Integer = TotalLength
53+
Dim buf(totalLen - 1) As Byte
54+
' header
55+
Array.Copy(_header, 0, buf, 0, HEADER_LENGTH)
56+
' data
57+
Array.Copy(_data, 0, buf, HEADER_LENGTH, _data.Length)
58+
59+
Return buf
60+
End Function
61+
3862
Public ReadOnly Property DataLength As Integer
3963
Get
40-
Return ReadUInt16LE(_header, 2)
64+
Return ReadUInt16LE(_header, Offset.DataLength)
4165
End Get
4266
End Property
4367

4468
Public ReadOnly Property Day As Integer
4569
Get
46-
Return _header(6)
70+
Return _header(Offset.Day)
4771
End Get
4872
End Property
4973

5074
Public ReadOnly Property Hour As Integer
5175
Get
52-
Return _header(7)
76+
Return _header(Offset.Hour)
5377
End Get
5478
End Property
5579

5680
Public ReadOnly Property Minute As Integer
5781
Get
58-
Return _header(8)
82+
Return _header(Offset.Minute)
5983
End Get
6084
End Property
6185

6286
Public ReadOnly Property Month As Integer
6387
Get
64-
Return _header(5) + 1
88+
Return _header(Offset.Month0) + 1
6589
End Get
6690
End Property
6791

@@ -73,13 +97,13 @@ Namespace ImageFormats.TD0
7397

7498
Public ReadOnly Property Second As Integer
7599
Get
76-
Return _header(9)
100+
Return _header(Offset.Second)
77101
End Get
78102
End Property
79103

80104
Public ReadOnly Property StoredCrc16 As UShort
81105
Get
82-
Return ReadUInt16LE(_header, 0)
106+
Return ReadUInt16LE(_header, Offset.Crc16)
83107
End Get
84108
End Property
85109

@@ -102,7 +126,7 @@ Namespace ImageFormats.TD0
102126
Public ReadOnly Property Year As Integer
103127
Get
104128
' year since 1900
105-
Return 1900 + _header(4)
129+
Return 1900 + _header(Offset.Year)
106130
End Get
107131
End Property
108132

@@ -113,8 +137,7 @@ Namespace ImageFormats.TD0
113137
Public Function ComputedCrc16() As UShort
114138
Dim crc As UShort = 0US
115139

116-
' header bytes [2..9]
117-
For i = 2 To 9
140+
For i = CRC_START To CRC_END
118141
crc = TD0Crc16.Update(crc, _header(i))
119142
Next
120143

DiskImageTool/ImageFormats/TD0/TD0Enums.vb

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,20 @@
1616
Rle = 2
1717
End Enum
1818

19-
Friend Module TD0Constants
19+
Friend Module TD0Helpers
2020
Friend Const TD0_MAX_BUFSZ As Integer = 1024 * 1024 * 4 ' 4 MiB
2121
Friend Function ReadUInt16LE(buf As Byte(), offset As Integer) As Integer
2222
Return CInt(buf(offset)) Or (CInt(buf(offset + 1)) << 8)
2323
End Function
24+
25+
Friend Sub WriteUInt16LE(buf As Byte(), offset As Integer, value As UShort)
26+
buf(offset) = CByte(value And &HFFUS)
27+
buf(offset + 1) = CByte((value >> 8) And &HFFUS)
28+
End Sub
29+
30+
Friend Sub WriteUInt16LE(buf As Byte(), offset As Integer, value As Integer)
31+
buf(offset) = CByte(value And &HFF)
32+
buf(offset + 1) = CByte((value >> 8) And &HFF)
33+
End Sub
2434
End Module
2535
End Namespace

0 commit comments

Comments
 (0)