-
Notifications
You must be signed in to change notification settings - Fork 1
/
AtariTFMX.vb
332 lines (262 loc) · 9.08 KB
/
AtariTFMX.vb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
Imports System.IO
' imports an Atari TFMX music file
Public Class AtariTFMX
Dim type1, type2, type3 As String
Dim offsets(6) As Integer
Dim sizes(13) As Short
Private fs As FileStream
Private br As BinaryReader
Private Declare Function htonl Lib "wsock32.dll" (ByVal a As Integer) As Integer
Private Declare Function htons Lib "wsock32.dll" (ByVal a As Integer) As Integer
Public Sub type(ByRef t1 As String, ByRef t2 As String, ByRef t3 As String)
t1 = type1
t2 = type2
t3 = type3
End Sub
Public Function Open(ByVal fname As String) As Boolean
Dim i As Short
fs = New FileStream(fname, FileMode.Open, FileAccess.Read)
br = New BinaryReader(fs)
type1 = br.ReadChars(4)
type2 = ""
If type1 = "COSO" Or type1 = "MMME" Then
For i = 0 To offsets.GetUpperBound(0)
offsets(i) = htonl(br.ReadInt32)
Next
type2 = br.ReadChars(4)
End If
For i = 0 To sizes.GetUpperBound(0)
sizes(i) = htons(br.ReadInt16)
Next
'sizes(0) = 22 - 1 'Instr
'sizes(1) = 32 - 1 'Shapes
End Function
Public Function LoadShapes(ByRef shapes As Shape) As Boolean
Dim i, j, s As Short
Dim b As Byte
Dim f As Boolean
If sizes(1) > shapes.n Then
MsgBox("maximal 64 Shapes")
Return False
End If
Dim s_offsets(sizes(1) + 1) As Integer 'sizes(1): Shape-Offsets-1
Select Case type1
Case "COSO", "MMME"
readOffsets(offsets(1), s_offsets, sizes(1))
s_offsets(sizes(1) + 1) = offsets(2) ' end of shapes is start of sequences
Case "TFMX"
fs.Position = 32 + 64 * (sizes(0) + 1) ' skip header & instruments
For i = 0 To sizes(1) + 1 ' shapes always 64 Bytes long
s_offsets(i) = i * 64
Next
End Select
For i = 0 To sizes(1)
'If s_offsets(i + 1) = 0 Then
' Exit For
'End If
shapes.shape_set(i).para1 = br.ReadByte
shapes.shape_set(i).para2 = br.ReadByte
shapes.shape_set(i).para3 = br.ReadByte
shapes.shape_set(i).para4 = br.ReadByte
shapes.shape_set(i).para5 = br.ReadByte
s = 0 ' data size
f = True
For j = 0 To s_offsets(i + 1) - (s_offsets(i) + 5) - 1
b = br.ReadByte
shapes.shape_set(i).data(j) = b
If f And b < &HE0 Then
s += 1
Else
f = False
End If
Next
shapes.shape_set(i).size = s
shapes.shape_set(i).name = "Shape " & String.Format("{0:00}", i)
Next
Return True
End Function
Public Function LoadInstr(ByRef instrs As Instr) As Boolean
Dim i, j As Short
If sizes(0) > instrs.n Then
Return False
End If
Dim i_offsets(sizes(0) + 1) As Integer 'Instruments-Offsets
Select Case type1
Case "COSO", "MMME"
readOffsets(offsets(0), i_offsets, sizes(0))
i_offsets(sizes(0) + 1) = offsets(1) ' end of instruments is start of shapes
Case "TFMX"
fs.Position = 32
For i = 0 To sizes(0) + 1 ' instr always 64 Bytes long
i_offsets(i) = i * 64
Next
End Select
For i = 0 To sizes(0)
For j = 0 To i_offsets(i + 1) - i_offsets(i) - 1
instrs.instr(i)(j) = br.ReadByte
Next
Next
Return True
End Function
Public Function LoadSeq(ByRef seqs As clSequence) As Boolean
Dim i, j As Short
Dim size As Integer
Dim b As Byte
Dim buffer(255) As Byte
Dim m16_32 As Short
If sizes(2) > seqs.n Then
Return False
End If
Dim s_offsets(sizes(2) + 1) As Integer 'seq-Offsets
seqs.clear()
Select Case type1
Case "COSO", "MMME"
readOffsets(offsets(2), s_offsets, sizes(2))
s_offsets(sizes(2) + 1) = offsets(3) ' end of last seq is start of tracks
Case "TFMX"
fs.Position = 32 + 64 * (sizes(0) + 1) + 64 * (sizes(1) + 1)
For i = 0 To sizes(2) + 1 ' seqs always 64 Bytes long
s_offsets(i) = i * 64
Next
End Select
For i = 0 To sizes(2)
For j = 0 To s_offsets(i + 1) - s_offsets(i) - 1
b = br.ReadByte
' seqs.Seq(i, j) = b
buffer(j) = b
Next
If type1 = "TFMX" Then
seqs.coyp(i, buffer)
Else
seqs.depack(i, buffer)
End If
Next
seqs.count = sizes(2) + 1
'If type1 = "TFMX" Then
' seqs.compress(sizes(2))
'End If
Return True
End Function
Private Sub readOffsets(ByVal pos As Integer, ByRef o() As Integer, ByVal max As Short)
Dim i As Short
Dim m16_32 As Short
fs.Position = pos
m16_32 = htons(br.ReadInt16)
fs.Position = pos
If m16_32 = 0 Then ' some music files use 32-Bit offsets
For i = 0 To max
o(i) = htonl(br.ReadInt32)
Next
Else
For i = 0 To max
o(i) = htons(br.ReadInt16)
Next
End If
End Sub
Public Sub LoadTracks(ByRef tracks As clTracks)
Dim n, i, j, k As Integer
Dim d(3) As Byte
Select Case type1
Case "COSO", "MMME"
fs.Position = offsets(3)
n = (offsets(4) - offsets(3)) / (3 * 4)
Case "TFMX"
fs.Position = 32 + (64 * (sizes(0) + 1 + sizes(1) + 1 + sizes(2) + 1))
n = sizes(3)
' special case
' fs.Position = &HDA0
End Select
For i = 0 To n - 1
For j = 0 To 2
For k = 0 To 3
d(k) = br.ReadByte
Next
tracks.set_entry(j, i, d)
Next
Next
tracks.MaxRow = n - 1
End Sub
Public Sub LoadSndInfo(ByRef si() As Interpreter._SND_INFO)
Dim n, i As Integer
Dim d As Integer
Select Case type1
Case "COSO", "MMME"
fs.Position = offsets(4) 'Soundinfo Table
If offsets(5) = 0 Then
n = (fs.Length - offsets(4))
Else
n = (offsets(5) - offsets(4))
End If
d = fs.Length - offsets(4)
If d < n Then
MsgBox("Missing " & Format(n - d, "0") & " Bytes")
n = d
End If
n = n \ (3 * 2) - 1
ReDim si(n)
For i = 0 To n
si(i).start = htons(br.ReadInt16)
si(i).last = htons(br.ReadInt16)
si(i).speed = htons(br.ReadInt16)
Next
Case "TFMX"
ReDim si(0)
si(0).start = 0
si(0).last = 100
si(0).speed = 5
End Select
End Sub
Public Function LoadSamples(ByRef digi As Sample) As Boolean
Dim s(30) As Integer
Dim i, j, k, l As Integer
Dim d As Short
type3 = ""
If offsets(6) = 0 Then
Return False
End If
If (offsets(6) + 256) > fs.Length Then
Return False
End If
fs.Position = offsets(6) + 248 'Samples
type3 = br.ReadChars(4)
'If type3 <> "MARC" Then
' type3 = ""
' Return False
'End If
fs.Position = offsets(6)
j = 0
For i = 0 To 30 ' max 31 Samples
s(i) = htons(br.ReadInt16) ' Sample Start-Offset
d = htons(br.ReadInt16) ' Flags
j += 1
If d = 16 Then
Exit For
End If
br.ReadBytes(4) ' skip
Next
j -= 2 ' letzter Wert in s(x) ist nur der End-Offset (kein Sample)
ReDim digi.samp(j)
For i = 0 To j
l = (s(i + 1) - s(i)) - 1
digi.samp(i) = New Sample.wave(l)
fs.Position = offsets(6) + s(i)
For k = 0 To l
d = br.ReadByte()
d = (d Xor &H80) * 20
digi.samp(i).data(k) = d
Next
Next
Return True
End Function
Public Function close()
br.Close()
Return True
End Function
' Destructor
Protected Overrides Sub Finalize()
If Not IsNothing(br) Then
br.Close()
End If
MyBase.Finalize()
End Sub
End Class