1 /* MikMod sound library
2 (c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
3 complete list.
4
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of
8 the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18 02111-1307, USA.
19 */
20
21 /*==============================================================================
22
23 $Id$
24
25 Ultratracker (ULT) module loader
26
27 ==============================================================================*/
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <string.h>
34
35 #include "unimod_priv.h"
36
37 /*========== Module structure */
38
39 /* header */
40 typedef struct ULTHEADER
41 {
42 CHAR id[16];
43 CHAR songtitle[32];
44 UBYTE reserved;
45 }
46 ULTHEADER;
47
48 /* sample information */
49 typedef struct ULTSAMPLE
50 {
51 CHAR samplename[32];
52 CHAR dosname[12];
53 SLONG loopstart;
54 SLONG loopend;
55 SLONG sizestart;
56 SLONG sizeend;
57 UBYTE volume;
58 UBYTE flags;
59 UWORD speed;
60 SWORD finetune;
61 }
62 ULTSAMPLE;
63
64 typedef struct ULTEVENT
65 {
66 UBYTE note, sample, eff, dat1, dat2;
67 }
68 ULTEVENT;
69
70 /*========== Loader variables */
71
72 #define ULTS_16BITS 4
73 #define ULTS_LOOP 8
74 #define ULTS_REVERSE 16
75
76 #define ULT_VERSION_LEN 18
77 static CHAR ULT_Version[ULT_VERSION_LEN] = "Ultra Tracker v1.x";
78
79 static ULTEVENT ev;
80
81 /*========== Loader code */
82
83 static BOOL
ULT_Test(void)84 ULT_Test (void)
85 {
86 CHAR id[16];
87
88 if (!_mm_read_string (id, 15, modreader))
89 return 0;
90 if (strncmp (id, "MAS_UTrack_V00", 14))
91 return 0;
92 if ((id[14] < '1') || (id[14] > '4'))
93 return 0;
94 return 1;
95 }
96
97 static BOOL
ULT_Init(void)98 ULT_Init (void)
99 {
100 return 1;
101 }
102
103 static void
ULT_Cleanup(void)104 ULT_Cleanup (void)
105 {
106 }
107
108 static UBYTE
ReadUltEvent(ULTEVENT * event)109 ReadUltEvent (ULTEVENT * event)
110 {
111 UBYTE flag, rep = 1;
112
113 flag = _mm_read_UBYTE (modreader);
114 if (flag == 0xfc)
115 {
116 rep = _mm_read_UBYTE (modreader);
117 event->note = _mm_read_UBYTE (modreader);
118 }
119 else
120 event->note = flag;
121
122 event->sample = _mm_read_UBYTE (modreader);
123 event->eff = _mm_read_UBYTE (modreader);
124 event->dat1 = _mm_read_UBYTE (modreader);
125 event->dat2 = _mm_read_UBYTE (modreader);
126
127 return rep;
128 }
129
130 static BOOL
ULT_Load(BOOL curious)131 ULT_Load (BOOL curious)
132 {
133 int t, u, tracks = 0;
134 SAMPLE *q;
135 ULTSAMPLE s;
136 ULTHEADER mh;
137 UBYTE nos, noc, nop;
138
139 /* try to read module header */
140 _mm_read_string (mh.id, 15, modreader);
141 _mm_read_string (mh.songtitle, 32, modreader);
142 mh.reserved = _mm_read_UBYTE (modreader);
143
144 if (_mm_eof (modreader))
145 {
146 _mm_errno = MMERR_LOADING_HEADER;
147 return 0;
148 }
149
150 ULT_Version[ULT_VERSION_LEN - 1] = '3' + (mh.id[14] - '1');
151 of.modtype = DupStr (ULT_Version, ULT_VERSION_LEN, 1);
152 of.initspeed = 6;
153 of.inittempo = 125;
154 of.reppos = 0;
155
156 /* read songtext */
157 if ((mh.id[14] > '1') && (mh.reserved))
158 if (!ReadLinedComment (mh.reserved, 32))
159 return 0;
160
161 nos = _mm_read_UBYTE (modreader);
162 if (_mm_eof (modreader))
163 {
164 _mm_errno = MMERR_LOADING_HEADER;
165 return 0;
166 }
167
168 of.songname = DupStr (mh.songtitle, 32, 1);
169 of.numins = of.numsmp = nos;
170
171 if (!AllocSamples ())
172 return 0;
173 q = of.samples;
174 for (t = 0; t < nos; t++)
175 {
176 /* try to read sample info */
177 _mm_read_string (s.samplename, 32, modreader);
178 _mm_read_string (s.dosname, 12, modreader);
179 s.loopstart = _mm_read_I_ULONG (modreader);
180 s.loopend = _mm_read_I_ULONG (modreader);
181 s.sizestart = _mm_read_I_ULONG (modreader);
182 s.sizeend = _mm_read_I_ULONG (modreader);
183 s.volume = _mm_read_UBYTE (modreader);
184 s.flags = _mm_read_UBYTE (modreader);
185 s.speed = (mh.id[14] >= '4') ? _mm_read_I_UWORD (modreader) : 8363;
186 s.finetune = _mm_read_I_SWORD (modreader);
187
188 if (_mm_eof (modreader))
189 {
190 _mm_errno = MMERR_LOADING_SAMPLEINFO;
191 return 0;
192 }
193
194 q->samplename = DupStr (s.samplename, 32, 1);
195 /* The correct formula for the coefficient would be
196 pow(2,(double)s.finetume/OCTAVE/32768), but to avoid floating point
197 here, we'll use a first order approximation here.
198 1/567290 == Ln(2)/OCTAVE/32768 */
199 q->speed = s.speed + s.speed * (((SLONG) s.speed * (SLONG) s.finetune) / 567290);
200 q->length = s.sizeend - s.sizestart;
201 q->volume = s.volume >> 2;
202 q->loopstart = s.loopstart;
203 q->loopend = s.loopend;
204 q->flags = SF_SIGNED;
205 if (s.flags & ULTS_LOOP)
206 q->flags |= SF_LOOP;
207 if (s.flags & ULTS_16BITS)
208 {
209 s.sizeend += (s.sizeend - s.sizestart);
210 s.sizestart <<= 1;
211 q->flags |= SF_16BITS;
212 q->loopstart >>= 1;
213 q->loopend >>= 1;
214 }
215 q++;
216 }
217
218 if (!AllocPositions (256))
219 return 0;
220 for (t = 0; t < 256; t++)
221 of.positions[t] = _mm_read_UBYTE (modreader);
222 for (t = 0; t < 256; t++)
223 if (of.positions[t] == 255)
224 break;
225 of.numpos = t;
226
227 noc = _mm_read_UBYTE (modreader);
228 nop = _mm_read_UBYTE (modreader);
229
230 of.numchn = ++noc;
231 of.numpat = ++nop;
232 of.numtrk = of.numchn * of.numpat;
233 if (!AllocTracks ())
234 return 0;
235 if (!AllocPatterns ())
236 return 0;
237 for (u = 0; u < of.numchn; u++)
238 for (t = 0; t < of.numpat; t++)
239 of.patterns[(t * of.numchn) + u] = tracks++;
240
241 /* SA37775, CVE-2009-3996 */
242 if (of.numchn>=UF_MAXCHAN)
243 of.numchn=UF_MAXCHAN - 1;
244
245 /* read pan position table for v1.5 and higher */
246 if (mh.id[14] >= '3')
247 for (t = 0; t < of.numchn; t++)
248 of.panning[t] = _mm_read_UBYTE (modreader) << 4;
249
250 for (t = 0; t < of.numtrk; t++)
251 {
252 int rep, row = 0;
253
254 UniReset ();
255 while (row < 64)
256 {
257 rep = ReadUltEvent (&ev);
258
259 if (_mm_eof (modreader))
260 {
261 _mm_errno = MMERR_LOADING_TRACK;
262 return 0;
263 }
264
265 while (rep--)
266 {
267 UBYTE eff;
268 int offset;
269
270 if (ev.sample)
271 UniInstrument (ev.sample - 1);
272 if (ev.note)
273 UniNote (ev.note + 2 * OCTAVE - 1);
274
275 /* first effect - various fixes by Alexander Kerkhove and
276 Thomas Neumann */
277 eff = ev.eff >> 4;
278 switch (eff)
279 {
280 case 0x3: /* tone portamento */
281 UniEffect (UNI_ITEFFECTG, ev.dat2);
282 break;
283 case 0x5:
284 break;
285 case 0x9: /* sample offset */
286 offset = (ev.dat2 << 8) | ((ev.eff & 0xf) == 9 ? ev.dat1 : 0);
287 UniEffect (UNI_ULTEFFECT9, offset);
288 break;
289 case 0xb: /* panning */
290 UniPTEffect (8, ev.dat2 * 0xf);
291 break;
292 case 0xc: /* volume */
293 UniPTEffect (eff, ev.dat2 >> 2);
294 break;
295 default:
296 UniPTEffect (eff, ev.dat2);
297 break;
298 }
299
300 /* second effect */
301 eff = ev.eff & 0xf;
302 switch (eff)
303 {
304 case 0x3: /* tone portamento */
305 UniEffect (UNI_ITEFFECTG, ev.dat1);
306 break;
307 case 0x5:
308 break;
309 case 0x9: /* sample offset */
310 if ((ev.eff >> 4) != 9)
311 UniEffect (UNI_ULTEFFECT9, ((UWORD) ev.dat1) << 8);
312 break;
313 case 0xb: /* panning */
314 UniPTEffect (8, ev.dat1 * 0xf);
315 break;
316 case 0xc: /* volume */
317 UniPTEffect (eff, ev.dat1 >> 2);
318 break;
319 default:
320 UniPTEffect (eff, ev.dat1);
321 break;
322 }
323
324 UniNewline ();
325 row++;
326 }
327 }
328 if (!(of.tracks[t] = UniDup ()))
329 return 0;
330 }
331 return 1;
332 }
333
334 static CHAR *
ULT_LoadTitle(void)335 ULT_LoadTitle (void)
336 {
337 CHAR s[32];
338
339 _mm_fseek (modreader, 15, SEEK_SET);
340 if (!_mm_read_UBYTES (s, 32, modreader))
341 return NULL;
342
343 return (DupStr (s, 32, 1));
344 }
345
346 /*========== Loader information */
347
348 MLOADER load_ult =
349 {
350 NULL,
351 "ULT",
352 "ULT (UltraTracker)",
353 ULT_Init,
354 ULT_Test,
355 ULT_Load,
356 ULT_Cleanup,
357 ULT_LoadTitle
358 };
359
360
361 /* ex:set ts=4: */
362