Skip to content

Commit f67340f

Browse files
authored
Merge pull request #68 from KOLANICH/xm
added xm
2 parents aec8a3b + 7869d6e commit f67340f

File tree

1 file changed

+303
-0
lines changed

1 file changed

+303
-0
lines changed

media/tracker_modules/xm.ksy

Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
meta:
2+
id: xm
3+
title: Extended Module
4+
application:
5+
- FastTracker 2
6+
- Protracker
7+
- MilkyTracker
8+
- libmodplug
9+
- Mikmod
10+
file-extension: xm
11+
license: Unlicense
12+
endian: le
13+
encoding: utf-8
14+
doc-ref: |
15+
http://sid.ethz.ch/debian/milkytracker/milkytracker-0.90.85%2Bdfsg/resources/reference/xm-form.txt
16+
ftp://ftp.modland.com/pub/documents/format_documentation/FastTracker%202%20v2.04%20(.xm).html
17+
seq:
18+
- id: preheader
19+
type: preheader
20+
- id: header
21+
size: preheader.header_size - 4
22+
type: header
23+
- id: patterns
24+
type: pattern
25+
repeat: expr
26+
repeat-expr: header.number_of_patterns
27+
- id: instruments
28+
type: instrument
29+
repeat: expr
30+
repeat-expr: header.number_of_instruments
31+
types:
32+
preheader:
33+
seq:
34+
- id: signature0
35+
contents: 'Extended Module: '
36+
- id: module_name
37+
size: 20
38+
type: strz
39+
doc: Module name, padded with zeroes
40+
- id: signature1
41+
contents: [0x1a]
42+
- id: tracker_name
43+
size: 20
44+
type: strz
45+
doc: Tracker name
46+
- id: version_number
47+
type: version
48+
doc: "Format versions below [0x01, 0x04] have a LOT of differences. Check this field!"
49+
- id: header_size
50+
type: u4
51+
doc: Header size << Calculated FROM THIS OFFSET, not from the beginning of the file! >>
52+
types:
53+
version:
54+
seq:
55+
- id: minor
56+
type: u1
57+
doc: currently 0x04
58+
- id: major
59+
type: u1
60+
doc: currently 0x01
61+
instances:
62+
value:
63+
value: (major<<8) | minor
64+
header:
65+
seq:
66+
- id: song_length
67+
type: u2
68+
doc: Song length (in pattern order table)
69+
- id: restart_position
70+
type: u2
71+
- id: number_of_channels
72+
type: u2
73+
doc: "(2,4,6,8,10,...,32)"
74+
- id: number_of_patterns
75+
type: u2
76+
doc: "(max 256)"
77+
- id: number_of_instruments
78+
type: u2
79+
doc: "(max 128)"
80+
- id: flags
81+
type: flags
82+
- id: default_tempo
83+
type: u2
84+
- id: default_bpm
85+
type: u2
86+
- id: pattern_order_table
87+
type: u1
88+
doc: "max 256"
89+
repeat: expr
90+
#repeat-expr: song_length
91+
repeat-expr: 256
92+
flags:
93+
seq:
94+
- id: reserved
95+
type: b15
96+
- id: freq_table_type
97+
type: b1
98+
doc: "0 = Amiga frequency table (see below); 1 = Linear frequency table"
99+
pattern:
100+
seq:
101+
- id: header
102+
type: header
103+
- id: packed_data
104+
size: header.main.packed_pattern_data_size
105+
types:
106+
header:
107+
seq:
108+
- id: header_length
109+
type: u4
110+
doc: Pattern header length
111+
- id: main
112+
type: header_main
113+
size: header_length - 4
114+
types:
115+
header_main:
116+
seq:
117+
- id: packing_type
118+
type: u1
119+
doc: Packing type (always 0)
120+
- id: number_of_rows_raw
121+
type:
122+
switch-on: _root.preheader.version_number.value
123+
cases:
124+
0x0102: u1
125+
_: u2
126+
doc: Number of rows in pattern (1..256)
127+
- id: packed_pattern_data_size
128+
type: u2
129+
doc: Packed pattern data size
130+
instances:
131+
number_of_rows:
132+
value: number_of_rows_raw + (_root.preheader.version_number.value==0x0102?1:0)
133+
instrument:
134+
seq:
135+
- id: header_size
136+
type: u4
137+
doc: |
138+
Instrument size << header that is >>
139+
<< "Instrument Size" field tends to be more than the actual size of the structure documented here (it includes also the extended instrument sample header above). So remember to check it and skip the additional bytes before the first sample header >>
140+
- id: header
141+
size: header_size - 4
142+
type: header
143+
- id: samples_headers
144+
type: sample_header
145+
repeat: expr
146+
repeat-expr: header.number_of_samples
147+
- id: samples
148+
type: samples_data(_index)
149+
repeat: expr
150+
repeat-expr: header.number_of_samples
151+
types:
152+
header:
153+
seq:
154+
- id: name
155+
size: 22
156+
type: strz
157+
- id: type
158+
type: u1
159+
doc: Usually zero, but this seems pretty random, don't assume it's zero
160+
- id: number_of_samples
161+
type: u2
162+
- id: extra_header
163+
type: extra_header
164+
if: number_of_samples > 0
165+
extra_header:
166+
seq:
167+
- id: sample_header_size
168+
type: u4
169+
- id: sample_number_for_all_notes
170+
type: u1
171+
repeat: expr
172+
repeat-expr: 96
173+
- id: points_for_volume_envelope
174+
type: envelope_point
175+
repeat: expr
176+
repeat-expr: 12
177+
- id: points_for_panning_envelope
178+
type: envelope_point
179+
repeat: expr
180+
repeat-expr: 12
181+
- id: number_of_volume_points
182+
type: u1
183+
- id: number_of_panning_points
184+
type: u1
185+
186+
- id: volume_sustain_point
187+
type: u1
188+
- id: volume_loop_start_point
189+
type: u1
190+
- id: volume_loop_end_point
191+
type: u1
192+
193+
- id: panning_sustain_point
194+
type: u1
195+
- id: panning_loop_start_point
196+
type: u1
197+
- id: panning_loop_end_point
198+
type: u1
199+
200+
- id: volume_type
201+
type: u1
202+
enum: type
203+
- id: panning_type
204+
type: u1
205+
enum: type
206+
207+
- id: vibrato_type
208+
type: u1
209+
- id: vibrato_sweep
210+
type: u1
211+
- id: vibrato_depth
212+
type: u1
213+
- id: vibrato_rate
214+
type: u1
215+
- id: volume_fadeout
216+
type: u2
217+
- id: reserved
218+
type: u2
219+
types:
220+
envelope_point:
221+
doc: |
222+
Envelope frame-counters work in range 0..FFFFh (0..65535 dec).
223+
BUT! FT2 only itself supports only range 0..FFh (0..255 dec).
224+
Some other trackers (like SoundTracker for Unix), however, can use the full range 0..FFFF, so it should be supported.
225+
!!TIP: This is also a good way to detect if the module has been made with FT2 or not. (In case the tracker name is brain- deadly left unchanged!)
226+
Of course it does not help if all instruments have the values inside FT2 supported range.
227+
The value-field of the envelope point is ranged between 00..3Fh (0..64 dec).
228+
seq:
229+
- id: x
230+
type: u2
231+
doc: Frame number of the point
232+
- id: y
233+
type: u2
234+
doc: Value of the point
235+
enums:
236+
type:
237+
0: on
238+
1: sustain
239+
2: loop
240+
samples_data:
241+
doc: |
242+
The saved data uses simple delta-encoding to achieve better compression ratios (when compressed with pkzip, etc.)
243+
Pseudocode for converting the delta-coded data to normal data,
244+
old = 0;
245+
for i in range(data_len):
246+
new = sample[i] + old;
247+
sample[i] = new;
248+
old = new;
249+
params:
250+
- id: index
251+
type: u2
252+
seq:
253+
- id: samples_data
254+
type:
255+
switch-on: _parent.samples_headers[index].type.is_sample_data_16_bit
256+
cases:
257+
true: u2
258+
false: u1
259+
repeat: expr
260+
repeat-expr: _parent.samples_headers[index].sample_length
261+
sample_header:
262+
seq:
263+
- id: sample_length
264+
type: u4
265+
- id: sample_loop_start
266+
type: u4
267+
- id: sample_loop_length
268+
type: u4
269+
270+
- id: volume
271+
type: u1
272+
- id: fine_tune
273+
type: s1
274+
doc: -16..+15
275+
- id: type
276+
type: loop_type
277+
- id: panning
278+
type: u1
279+
doc: (0-255)
280+
- id: relative_note_number
281+
type: s1
282+
- id: reserved
283+
type: u1
284+
- id: name
285+
size: 22
286+
type: strz
287+
types:
288+
loop_type:
289+
seq:
290+
- id: reserved0
291+
type: b3
292+
- id: is_sample_data_16_bit
293+
type: b1
294+
- id: reserved1
295+
type: b2
296+
- id: loop_type
297+
type: b2
298+
enum: loop_type
299+
enums:
300+
loop_type:
301+
0: none
302+
1: forward
303+
2: ping_pong

0 commit comments

Comments
 (0)