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 15 instrument MOD loader
26 Also supports Ultimate Sound Tracker (old M15 format)
27
28 ==============================================================================*/
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include <string.h>
35
36 #include "unimod_priv.h"
37
38 /*========== Module Structure */
39
40 typedef struct MSAMPINFO
41 {
42 CHAR samplename[23]; /* 22 in module, 23 in memory */
43 UWORD length;
44 UBYTE finetune;
45 UBYTE volume;
46 UWORD reppos;
47 UWORD replen;
48 }
49 MSAMPINFO;
50
51 typedef struct MODULEHEADER
52 {
53 CHAR songname[21]; /* the songname.., 20 in module, 21 in memory */
54 MSAMPINFO samples[15]; /* all sampleinfo */
55 UBYTE songlength; /* number of patterns used */
56 UBYTE magic1; /* should be 127 */
57 UBYTE positions[128]; /* which pattern to play at pos */
58 }
59 MODULEHEADER;
60
61 typedef struct MODNOTE
62 {
63 UBYTE a, b, c, d;
64 }
65 MODNOTE;
66
67 /*========== Loader variables */
68
69 static MODULEHEADER *mh = NULL;
70 static MODNOTE *patbuf = NULL;
71 static BOOL ust_loader = 0; /* if TRUE, load as an ust module. */
72
73 /* known file formats which can confuse the loader */
74 #define REJECT 2
75 static const char *signatures[REJECT] =
76 {
77 "CAKEWALK", /* cakewalk midi files */
78 "SZDD" /* Microsoft compressed files */
79 };
80 static int siglen[REJECT] =
81 {8, 4};
82
83 /*========== Loader code */
84
85 static BOOL
86 LoadModuleHeader (MODULEHEADER * mh)
87 {
88 int t, u;
89
90 _mm_read_string (mh->songname, 20, modreader);
91 mh->songname[20] = 0; /* just in case */
92
93 /* sanity check : title should contain printable characters and a bunch
94 of null chars */
95 for (t = 0; t < 20; t++)
96 if ((mh->songname[t]) && (mh->songname[t] < 32))
97 return 0;
98 for (t = 0; (mh->songname[t]) && (t < 20); t++);
99 if (t < 20)
100 for (; t < 20; t++)
101 if (mh->songname[t])
102 return 0;
103
104 for (t = 0; t < 15; t++)
105 {
106 MSAMPINFO *s = &mh->samples[t];
107
108 _mm_read_string (s->samplename, 22, modreader);
109 s->samplename[22] = 0; /* just in case */
110 s->length = _mm_read_M_UWORD (modreader);
111 s->finetune = _mm_read_UBYTE (modreader);
112 s->volume = _mm_read_UBYTE (modreader);
113 s->reppos = _mm_read_M_UWORD (modreader);
114 s->replen = _mm_read_M_UWORD (modreader);
115
116 /* sanity check : sample title should contain printable characters and
117 a bunch of null chars */
118 for (u = 0; u < 20; u++)
119 if ((s->samplename[u]) && (s->samplename[u] < /*32 */ 14))
120 return 0;
121 for (u = 0; (s->samplename[u]) && (u < 20); u++);
122 if (u < 20)
123 for (; u < 20; u++)
124 if (s->samplename[u])
125 return 0;
126
IMF_Test(void)127 /* sanity check : finetune values */
128 if (s->finetune >> 4)
129 return 0;
130 }
131
132 mh->songlength = _mm_read_UBYTE (modreader);
133 mh->magic1 = _mm_read_UBYTE (modreader); /* should be 127 */
134
135 /* sanity check : no more than 128 positions, restart position in range */
136 if ((!mh->songlength) || (mh->songlength > 128))
137 return 0;
138 /* values encountered so far are 0x6a and 0x78 */
139 if (((mh->magic1 & 0xf8) != 0x78) && (mh->magic1 != 0x6a) && (mh->magic1 > mh->songlength))
IMF_Init(void)140 return 0;
141
142 _mm_read_UBYTES (mh->positions, 128, modreader);
143
144 /* sanity check : pattern range is 0..63 */
145 for (t = 0; t < 128; t++)
146 if (mh->positions[t] > 63)
147 return 0;
148
149 return (!_mm_eof (modreader));
150 }
IMF_Cleanup(void)151
152 /* Checks the patterns in the modfile for UST / 15-inst indications.
153 For example, if an effect 3xx is found, it is assumed that the song
154 is 15-inst. If a 1xx effect has dat greater than 0x20, it is UST.
155
156 Returns: 0 indecisive; 1 = UST; 2 = 15-inst */
157 static int
158 CheckPatternType (int numpat)
159 {
160 int t;
161 UBYTE eff, dat;
162
163 for (t = 0; t < numpat * (64U * 4); t++)
164 {
165 /* Load the pattern into the temp buffer and scan it */
166 _mm_read_UBYTE (modreader);
167 _mm_read_UBYTE (modreader);
168 eff = _mm_read_UBYTE (modreader);
169 dat = _mm_read_UBYTE (modreader);
170
171 switch (eff)
172 {
173 case 1:
174 if (dat > 0x1f)
175 return 1;
176 if (dat < 0x3)
177 return 2;
178 break;
179 case 2:
180 if (dat > 0x1f)
181 return 1;
182 return 2;
183 case 3:
184 if (dat)
185 return 2;
186 break;
187 default:
188 return 2;
189 }
190 }
191 return 0;
192 }
193
194 static BOOL
195 M15_Test (void)
196 {
197 int t, numpat;
198 MODULEHEADER mh;
199
200 ust_loader = 0;
201 if (!LoadModuleHeader (&mh))
202 return 0;
203
204 /* reject other file types */
205 for (t = 0; t < REJECT; t++)
206 if (!memcmp (mh.songname, signatures[t], siglen[t]))
207 return 0;
208
209 if (mh.magic1 > 127)
210 return 0;
211 if ((!mh.songlength) || (mh.songlength > mh.magic1))
212 return 0;
213
214 for (t = 0; t < 15; t++)
215 {
216 /* all finetunes should be zero */
217 if (mh.samples[t].finetune)
218 return 0;
219
220 /* all volumes should be <= 64 */
IMF_ProcessCmd(UBYTE eff,UBYTE inf)221 if (mh.samples[t].volume > 64)
222 return 0;
223
224 /* all instrument names should begin with s, st-, or a number */
225 if (mh.samples[t].samplename[0] == 's')
226 {
227 if ((memcmp (mh.samples[t].samplename, "st-", 3)) &&
228 (memcmp (mh.samples[t].samplename, "ST-", 3)) &&
229 (*mh.samples[t].samplename))
230 ust_loader = 1;
231 }
232 else if ((mh.samples[t].samplename[0] < '0') ||
233 (mh.samples[t].samplename[0] > '9'))
234 ust_loader = 1;
235
236 if (mh.samples[t].length > 4999 || mh.samples[t].reppos > 9999)
237 {
238 ust_loader = 0;
239 if (mh.samples[t].length > 32768)
240 return 0;
241 }
242
243 /* if loop information is incorrect as words, but correct as bytes,
244 this is likely to be an ust-style module */
245 if((mh.samples[t].reppos + mh.samples[t].replen > mh.samples[t].length) &&
246 (mh.samples[t].reppos + mh.samples[t].replen < (mh.samples[t].length << 1)))
247 {
248 ust_loader = 1;
249 return 1;
250 }
251
252 if (!ust_loader)
253 return 1;
254 }
255
256 for (numpat = 0, t = 0; t < mh.songlength; t++)
257 if (mh.positions[t] > numpat)
258 numpat = mh.positions[t];
259 numpat++;
260 switch (CheckPatternType (numpat))
261 {
262 case 0: /* indecisive, so check more clues... */
263 break;
264 case 1:
265 ust_loader = 1;
266 break;
267 case 2:
268 ust_loader = 0;
269 break;
270 }
271 return 1;
272 }
273
274 static BOOL
275 M15_Init (void)
276 {
277 if (!(mh = (MODULEHEADER *) _mm_malloc (sizeof (MODULEHEADER))))
278 return 0;
279 return 1;
280 }
281
282 static void
283 M15_Cleanup (void)
284 {
285 _mm_free (mh);
286 _mm_free (patbuf);
287 }
288
289 /*
290 Old (amiga) noteinfo:
291
292 _____byte 1_____ byte2_ _____byte 3_____ byte4_
293 / \ / \ / \ / \
294 0000 0000-00000000 0000 0000-00000000
295
296 Upper four 12 bits for Lower four Effect command.
297 bits of sam- note period. bits of sam-
298 ple number. ple number.
299 */
300
301 static UWORD npertab[7 * OCTAVE] =
302 {
303 /* -> Tuning 0 */
304 1712, 1616, 1524, 1440, 1356, 1280, 1208, 1140, 1076, 1016, 960, 906,
305 856, 808, 762, 720, 678, 640, 604, 570, 538, 508, 480, 453,
306 428, 404, 381, 360, 339, 320, 302, 285, 269, 254, 240, 226,
307 214, 202, 190, 180, 170, 160, 151, 143, 135, 127, 120, 113,
308 107, 101, 95, 90, 85, 80, 75, 71, 67, 63, 60, 56,
309
310 53, 50, 47, 45, 42, 40, 37, 35, 33, 31, 30, 28,
311 27, 25, 24, 22, 21, 20, 19, 18, 17, 16, 15, 14
312 };
313
314
315 static void
316 M15_ConvertNote (MODNOTE * n)
317 {
318 UBYTE instrument, effect, effdat, note;
319 UWORD period;
320 UBYTE lastnote = 0;
321
322 /* decode the 4 bytes that make up a single note */
323 instrument = n->c >> 4;
324 period = (((UWORD) n->a & 0xf) << 8) + n->b;
325 effect = n->c & 0xf;
326 effdat = n->d;
327
328 /* Convert the period to a note number */
329 note = 0;
330 if (period)
331 {
332 for (note = 0; note < 7 * OCTAVE; note++)
333 if (period >= npertab[note])
334 break;
335 if (note == 7 * OCTAVE)
336 note = 0;
337 else
338 note++;
339 }
340
341 if (instrument)
342 {
343 /* if instrument does not exist, note cut */
344 if ((instrument > 15) || (!mh->samples[instrument - 1].length))
345 {
346 UniPTEffect (0xc, 0);
347 if (effect == 0xc)
348 effect = effdat = 0;
349 }
350 else
351 {
352 /* if we had a note, then change instrument... */
353 if (note)
354 UniInstrument (instrument - 1);
355 /* ...otherwise, only adjust volume... */
356 else
357 {
358 /* ...unless an effect was specified, which forces a new note
359 to be played */
360 if (effect || effdat)
361 {
362 UniInstrument (instrument - 1);
363 note = lastnote;
364 }
365 else
366 UniPTEffect (0xc, mh->samples[instrument - 1].volume & 0x7f);
367 }
368 }
369 }
370 if (note)
371 {
372 UniNote (note + 2 * OCTAVE - 1);
373 lastnote = note;
374 }
375
376 /* Handle ``heavy'' volumes correctly */
377 if ((effect == 0xc) && (effdat > 0x40))
378 effdat = 0x40;
379
380 /* Convert pattern jump from Dec to Hex */
381 if (effect == 0xd)
382 effdat = (((effdat & 0xf0) >> 4) * 10) + (effdat & 0xf);
383
IMF_ConvertTrack(IMFNOTE * tr,UWORD rows)384 /* Volume slide, up has priority */
385 if ((effect == 0xa) && (effdat & 0xf) && (effdat & 0xf0))
386 effdat &= 0xf0;
387
388 if (ust_loader)
389 {
390 switch (effect)
391 {
392 case 0:
393 case 3:
394 break;
395 case 1:
396 UniPTEffect (0, effdat);
397 break;
398 case 2:
399 if (effdat & 0xf)
400 UniPTEffect (1, effdat & 0xf);
401 if (effdat >> 2)
402 UniPTEffect (2, effdat >> 2);
403 break;
404 default:
405 UniPTEffect (effect, effdat);
406 break;
407 }
408 }
409 else {
410 /* Ignore 100, 200 and 300 (there is no porta memory in mod files) */
411 if ((!effdat) && ((effect == 1)||(effect == 2)||(effect == 3)))
412 effect = 0;
413
414 UniPTEffect (effect, effdat);
415 }
416 }
417
418 static UBYTE *
IMF_Load(BOOL curious)419 M15_ConvertTrack (MODNOTE * n)
420 {
421 int t;
422
423 UniReset ();
424 for (t = 0; t < 64; t++)
425 {
426 M15_ConvertNote (n);
427 UniNewline ();
428 n += 4;
429 }
430 return UniDup ();
431 }
432
433 /* Loads all patterns of a modfile and converts them into the 3 byte format. */
434 static BOOL
435 M15_LoadPatterns (void)
436 {
437 int t, s, tracks = 0;
438
439 if (!AllocPatterns ())
440 return 0;
441 if (!AllocTracks ())
442 return 0;
443
444 /* Allocate temporary buffer for loading and converting the patterns */
445 if (!(patbuf = (MODNOTE *) _mm_calloc (64U * 4, sizeof (MODNOTE))))
446 return 0;
447
448 for (t = 0; t < of.numpat; t++)
449 {
450 /* Load the pattern into the temp buffer and convert it */
451 for (s = 0; s < (64U * 4); s++)
452 {
453 patbuf[s].a = _mm_read_UBYTE (modreader);
454 patbuf[s].b = _mm_read_UBYTE (modreader);
455 patbuf[s].c = _mm_read_UBYTE (modreader);
456 patbuf[s].d = _mm_read_UBYTE (modreader);
457 }
458
459 for (s = 0; s < 4; s++)
460 if (!(of.tracks[tracks++] = M15_ConvertTrack (patbuf + s)))
461 return 0;
462 }
463 return 1;
464 }
465
466 static BOOL
467 M15_Load (BOOL curious)
468 {
469 int t, scan;
470 SAMPLE *q;
471 MSAMPINFO *s;
472
473 /* try to read module header */
474 if (!LoadModuleHeader (mh))
475 {
476 _mm_errno = MMERR_LOADING_HEADER;
477 return 0;
478 }
479
480 if (ust_loader)
481 of.modtype = strdup ("Ultimate Soundtracker");
482 else
483 of.modtype = strdup ("Soundtracker");
484
485 /* set module variables */
486 of.initspeed = 6;
487 of.inittempo = 125;
488 of.numchn = 4;
489 of.songname = DupStr (mh->songname, 21, 1);
490 of.numpos = mh->songlength;
491 of.reppos = 0;
492
493 /* Count the number of patterns */
494 of.numpat = 0;
495 for (t = 0; t < of.numpos; t++)
496 if (mh->positions[t] > of.numpat)
497 of.numpat = mh->positions[t];
498 /* since some old modules embed extra patterns, we have to check the
499 whole list to get the samples' file offsets right - however we can find
500 garbage here, so check carefully */
501 scan = 1;
502 for (t = of.numpos; t < 128; t++)
503 if (mh->positions[t] >= 0x80)
504 scan = 0;
505 if (scan)
506 for (t = of.numpos; t < 128; t++)
507 {
508 if (mh->positions[t] > of.numpat)
509 of.numpat = mh->positions[t];
510 if ((curious) && (mh->positions[t]))
511 of.numpos = t + 1;
512 }
513 of.numpat++;
514 of.numtrk = of.numpat * of.numchn;
515
516 if (!AllocPositions (of.numpos))
517 return 0;
518 for (t = 0; t < of.numpos; t++)
519 of.positions[t] = mh->positions[t];
520
521 /* Finally, init the sampleinfo structures */
522 of.numins = of.numsmp = 15;
523 if (!AllocSamples ())
524 return 0;
525
526 s = mh->samples;
527 q = of.samples;
528
529 for (t = 0; t < of.numins; t++)
530 {
531 /* convert the samplename */
532 q->samplename = DupStr (s->samplename, 23, 1);
533
534 /* init the sampleinfo variables and convert the size pointers */
535 q->speed = finetune[s->finetune & 0xf];
536 q->volume = s->volume;
537 if (ust_loader)
538 q->loopstart = s->reppos;
539 else
540 q->loopstart = s->reppos << 1;
541 q->loopend = q->loopstart + (s->replen << 1);
542 q->length = s->length << 1;
543
544 q->flags = SF_SIGNED;
545 if(ust_loader)
546 q->flags |= SF_UST_LOOP;
547 if(s->replen > 2)
548 q->flags |= SF_LOOP;
549
550 /* fix replen if repend>length */
551 if (q->loopend > q->length)
552 q->loopend = q->length;
553
554 s++;
555 q++;
556 }
557
558 if (!M15_LoadPatterns ())
559 return 0;
560 ust_loader = 0;
561
562 return 1;
563 }
564
565 static CHAR *
566 M15_LoadTitle (void)
567 {
568 CHAR s[21];
569
570 _mm_fseek (modreader, 0, SEEK_SET);
571 if (!_mm_read_UBYTES (s, 20, modreader))
572 return NULL;
573 s[20] = 0; /* just in case */
574 return (DupStr (s, 21, 1));
575 }
576
577 /*========== Loader information */
578
579 MLOADER load_m15 =
580 {
581 NULL,
582 "15-instrument module",
583 "MOD (15 instruments)",
584 M15_Init,
585 M15_Test,
586 M15_Load,
587 M15_Cleanup,
588 M15_LoadTitle
589 };
590
591 /* ex:set ts=4: */
592