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 General DigiMusic (GDM) module loader
26
27 ==============================================================================*/
28
29 /*
30
31 Written by Kev Vance<kvance@zeux.org>
32 based on the file format description written by 'MenTaLguY'
33 <mental@kludge.org>
34
35 */
36
37 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #endif
40
41 #include <stdio.h>
42 #include <string.h>
43
44 #include "unimod_priv.h"
45
46 typedef struct GDMNOTE
47 {
48 UBYTE note;
49 UBYTE samp;
50 struct
51 {
52 UBYTE effect;
53 UBYTE param;
54 }
55 effect[4];
56 }
57 GDMNOTE;
58
59 typedef GDMNOTE GDMTRACK[64];
60
61 typedef struct GDMHEADER
62 {
63 CHAR id1[4];
64 CHAR songname[32];
65 CHAR author[32];
66 CHAR eofmarker[3];
67 CHAR id2[4];
68
69 UBYTE majorver;
70 UBYTE minorver;
71 UWORD trackerid;
72 UBYTE t_majorver;
73 UBYTE t_minorver;
74 UBYTE pantable[32];
75 UBYTE mastervol;
76 UBYTE mastertempo;
77 UBYTE masterbpm;
78 UWORD flags;
79
80 ULONG orderloc;
81 UBYTE ordernum;
82 ULONG patternloc;
83 UBYTE patternnum;
84 ULONG samhead;
85 ULONG samdata;
86 UBYTE samnum;
87 ULONG messageloc;
88 ULONG messagelen;
89 ULONG scrollyloc;
90 UWORD scrollylen;
91 ULONG graphicloc;
92 UWORD graphiclen;
93 }
94 GDMHEADER;
95
96 typedef struct GDMSAMPLE
97 {
98 CHAR sampname[32];
99 CHAR filename[13];
100 UBYTE ems;
101 ULONG length;
102 ULONG loopbeg;
103 ULONG loopend;
104 UBYTE flags;
105 UWORD c4spd;
106 UBYTE vol;
107 UBYTE pan;
108 }
109 GDMSAMPLE;
110
111 static GDMHEADER *mh = NULL; /* pointer to GDM header */
112 static GDMNOTE *gdmbuf = NULL; /* pointer to a complete GDM pattern */
113
114 CHAR GDM_Version[] = "General DigiMusic 1.xx";
115
116 static BOOL
GDM_Test(void)117 GDM_Test (void)
118 {
119 /* test for gdm magic numbers */
120 UBYTE id[4];
121
122 _mm_fseek (modreader, 0x00, SEEK_SET);
123 if (!_mm_read_UBYTES (id, 4, modreader))
124 return 0;
125 if (!memcmp (id, "GDM\xfe", 4))
126 {
127 _mm_fseek (modreader, 71, SEEK_SET);
128 if (!_mm_read_UBYTES (id, 4, modreader))
129 return 0;
130 if (!memcmp (id, "GMFS", 4))
131 return 1;
132 }
133 return 0;
134 }
135
136 static BOOL
GDM_Init(void)137 GDM_Init (void)
138 {
139 if (!(gdmbuf = (GDMNOTE *) _mm_malloc (32 * 64 * sizeof (GDMNOTE))))
140 return 0;
141 if (!(mh = (GDMHEADER *) _mm_malloc (sizeof (GDMHEADER))))
142 return 0;
143
144 return 1;
145 }
146
147 static void
GDM_Cleanup(void)148 GDM_Cleanup (void)
149 {
150 _mm_free (mh);
151 _mm_free (gdmbuf);
152 }
153
154 static BOOL
GDM_ReadPattern(void)155 GDM_ReadPattern (void)
156 {
157 int pos, flag, ch, i, maxch;
158 GDMNOTE n;
159 UWORD length, x = 0;
160
161 /* get pattern length */
162 length = _mm_read_I_UWORD (modreader) - 2;
163
164 /* clear pattern data */
165 memset (gdmbuf, 255, 32 * 64 * sizeof (GDMNOTE));
166 pos = 0;
167 maxch = 0;
168
169 while (x < length)
170 {
171 memset (&n, 255, sizeof (GDMNOTE));
172 flag = _mm_read_UBYTE (modreader);
173 x++;
174
175 if (_mm_eof (modreader))
176 {
177 _mm_errno = MMERR_LOADING_PATTERN;
178 return 0;
179 }
180
181 ch = flag & 31;
182 if (ch > maxch)
183 maxch = ch;
184 if (!flag)
185 {
186 pos++;
187 continue;
188 }
189 if (flag & 0x60)
190 {
191 if (flag & 0x20)
192 {
193 /* new note */
194 n.note = _mm_read_UBYTE (modreader) & 127;
195 n.samp = _mm_read_UBYTE (modreader);
196 x += 2;
197 }
198 if (flag & 0x40)
199 {
200 do
201 {
202 /* effect channel set */
203 i = _mm_read_UBYTE (modreader);
204 n.effect[i >> 6].effect = i & 31;
205 n.effect[i >> 6].param = _mm_read_UBYTE (modreader);
206 x += 2;
207 }
208 while (i & 32);
209 }
210 memcpy (gdmbuf + (64U * ch) + pos, &n, sizeof (GDMNOTE));
211 }
212 }
213 return 1;
214 }
215
216 static UBYTE *
GDM_ConvertTrack(GDMNOTE * tr)217 GDM_ConvertTrack (GDMNOTE * tr)
218 {
219 int t, i = 0;
220 UBYTE note, ins;
221
222 UniReset ();
223 for (t = 0; t < 64; t++)
224 {
225 note = tr[t].note;
226 ins = tr[t].samp;
227
228 if ((ins) && (ins != 255))
229 UniInstrument (ins - 1);
230 if (note != 255)
231 {
232 UniNote (((note >> 4) * OCTAVE) + (note & 0xf) - 1);
233 }
234 for (i = 0; i < 4; i++)
235 {
236 switch (tr[t].effect[i].effect)
237 {
238 case 1: /* toneslide up */
239 UniEffect (UNI_S3MEFFECTF, tr[t].effect[i].param);
240 break;
241 case 2: /* toneslide down */
242 UniEffect (UNI_S3MEFFECTE, tr[t].effect[i].param);
243 break;
244 case 3: /* glissando to note */
245 UniEffect (UNI_ITEFFECTG, tr[t].effect[i].param);
246 break;
247 case 4: /* vibrato */
248 UniEffect (UNI_ITEFFECTH, tr[t].effect[i].param);
249 break;
250 case 5: /* portamento+volslide */
251 UniEffect (UNI_ITEFFECTG, 0);
252 UniEffect (UNI_S3MEFFECTD, tr[t].effect[i].param);
253 break;
254 case 6: /* vibrato+volslide */
255 UniEffect (UNI_ITEFFECTH, 0);
256 UniEffect (UNI_S3MEFFECTD, tr[t].effect[i].param);
257 break;
258 case 7: /* tremolo */
259 UniEffect (UNI_S3MEFFECTR, tr[t].effect[i].param);
260 break;
261 case 8: /* tremor */
262 UniEffect (UNI_S3MEFFECTI, tr[t].effect[i].param);
263 break;
264 case 9: /* offset */
265 UniPTEffect (0x09, tr[t].effect[i].param);
266 break;
267 case 0x0a: /* volslide */
268 UniEffect (UNI_S3MEFFECTD, tr[t].effect[i].param);
269 break;
270 case 0x0b: /* jump to order */
271 UniPTEffect (0x0b, tr[t].effect[i].param);
272 break;
273 case 0x0c: /* volume set */
274 UniPTEffect (0x0c, tr[t].effect[i].param);
275 break;
276 case 0x0d: /* pattern break */
277 UniPTEffect (0x0d, tr[t].effect[i].param);
278 break;
279 case 0x0e: /* extended */
280 switch (tr[t].effect[i].param & 0xf0)
281 {
282 case 0x10: /* fine portamento up */
283 UniEffect (UNI_S3MEFFECTF,
284 0x0f | ((tr[t].effect[i].param << 4) & 0x0f));
285 break;
286 case 0x20: /* fine portamento down */
287 UniEffect (UNI_S3MEFFECTE,
288 0xf0 | (tr[t].effect[i].param & 0x0f));
289 break;
290 case 0x30: /* glissando control */
291 UniEffect (SS_GLISSANDO,
292 tr[t].effect[i].param & 0x0f);
293 break;
294 case 0x40: /* vibrato waveform */
295 UniEffect (SS_VIBWAVE,
296 tr[t].effect[i].param & 0x0f);
297 break;
298 case 0x50: /* set c4spd */
299 UniEffect (SS_FINETUNE,
300 tr[t].effect[i].param & 0x0f);
301 break;
302 case 0x60: /* loop fun */
303 UniEffect (UNI_ITEFFECTS0,
304 (tr[t].effect[i].param & 0x0f) | 0xb0);
305 break;
306 case 0x70: /* tremolo waveform */
307 UniEffect (SS_TREMWAVE,
308 tr[t].effect[i].param & 0x0f);
309 break;
310 case 0x80: /* extra fine porta up */
311 UniEffect (UNI_S3MEFFECTF,
312 0x0e | ((tr[t].effect[i].param << 4) & 0x0f));
313 break;
314 case 0x90: /* extra fine porta down */
315 UniEffect (UNI_S3MEFFECTE,
316 0xe0 | (tr[t].effect[i].param & 0x0f));
317 break;
318 case 0xa0: /* fine volslide up */
319 UniEffect (UNI_S3MEFFECTD,
320 0x0f | ((tr[t].effect[i].param << 4) & 0x0f));
321 break;
322 case 0xb0: /* fine volslide down */
323 UniEffect (UNI_S3MEFFECTE,
324 0xf0 | (tr[t].effect[i].param & 0x0f));
325 break;
326 case 0xc0: /* note cut */
327 case 0xd0: /* note delay */
328 case 0xe0: /* extend row */
329 UniPTEffect (0xe, tr[t].effect[i].param);
330 break;
331 }
332 break;
333 case 0x0f: /* set tempo */
334 UniEffect (UNI_S3MEFFECTA, tr[t].effect[i].param);
335 break;
336 case 0x10: /* arpeggio */
337 UniPTEffect (0x0, tr[t].effect[i].param);
338 break;
339 case 0x12: /* retrigger */
340 UniEffect (UNI_S3MEFFECTQ, tr[t].effect[i].param);
341 break;
342 case 0x13: /* set global volume */
343 UniEffect (UNI_XMEFFECTG, tr[t].effect[i].param);
344 break;
345 case 0x14: /* fine vibrato */
346 UniEffect (UNI_ITEFFECTU, tr[t].effect[i].param);
347 break;
348 case 0x1e: /* special */
349 switch (tr[t].effect[i].param & 0xf0)
350 {
351 case 8: /* set pan position */
352 if (tr[t].effect[i].param >= 128)
353 UniPTEffect (0x08, 255);
354 else
355 UniPTEffect (0x08, tr[t].effect[i].param << 1);
356 break;
357 }
358 break;
359 case 0x1f: /* set bpm */
360 if (tr[t].effect[i].param >= 0x20)
361 UniEffect (UNI_S3MEFFECTT, tr[t].effect[i].param);
362 break;
363 }
364 }
365 UniNewline ();
366 }
367 return UniDup ();
368 }
369
370 static BOOL
GDM_Load(BOOL curious)371 GDM_Load (BOOL curious)
372 {
373 int i, x, u, track;
374 SAMPLE *q;
375 GDMSAMPLE s;
376 ULONG position;
377
378 /* read header */
379 _mm_read_string (mh->id1, 4, modreader);
380 _mm_read_string (mh->songname, 32, modreader);
381 _mm_read_string (mh->author, 32, modreader);
382 _mm_read_string (mh->eofmarker, 3, modreader);
383 _mm_read_string (mh->id2, 4, modreader);
384
385 mh->majorver = _mm_read_UBYTE (modreader);
386 mh->minorver = _mm_read_UBYTE (modreader);
387 mh->trackerid = _mm_read_I_UWORD (modreader);
388 mh->t_majorver = _mm_read_UBYTE (modreader);
389 mh->t_minorver = _mm_read_UBYTE (modreader);
390 _mm_read_UBYTES (mh->pantable, 32, modreader);
391 mh->mastervol = _mm_read_UBYTE (modreader);
392 mh->mastertempo = _mm_read_UBYTE (modreader);
393 mh->masterbpm = _mm_read_UBYTE (modreader);
394 mh->flags = _mm_read_I_UWORD (modreader);
395
396 mh->orderloc = _mm_read_I_ULONG (modreader);
397 mh->ordernum = _mm_read_UBYTE (modreader);
398 mh->patternloc = _mm_read_I_ULONG (modreader);
399 mh->patternnum = _mm_read_UBYTE (modreader);
400 mh->samhead = _mm_read_I_ULONG (modreader);
401 mh->samdata = _mm_read_I_ULONG (modreader);
402 mh->samnum = _mm_read_UBYTE (modreader);
403 mh->messageloc = _mm_read_I_ULONG (modreader);
404 mh->messagelen = _mm_read_I_ULONG (modreader);
405 mh->scrollyloc = _mm_read_I_ULONG (modreader);
406 mh->scrollylen = _mm_read_I_UWORD (modreader);
407 mh->graphicloc = _mm_read_I_ULONG (modreader);
408 mh->graphiclen = _mm_read_I_UWORD (modreader);
409
410 /* have we ended abruptly? */
411 if (_mm_eof (modreader))
412 {
413 _mm_errno = MMERR_LOADING_HEADER;
414 return 0;
415 }
416
417 /* any orders? */
418 if (mh->ordernum == 255)
419 {
420 _mm_errno = MMERR_LOADING_PATTERN;
421 return 0;
422 }
423
424 /* now we fill */
425 of.modtype = strdup (GDM_Version);
426 of.modtype[18] = mh->majorver + '0';
427 of.modtype[20] = mh->minorver / 10 + '0';
428 of.modtype[21] = mh->minorver % 10 + '0';
429 of.songname = DupStr (mh->songname, 32, 0);
430 of.numpat = mh->patternnum + 1;
431 of.reppos = 0;
432 of.numins = of.numsmp = mh->samnum + 1;
433 of.initspeed = mh->mastertempo;
434 of.inittempo = mh->masterbpm;
435 of.initvolume = mh->mastervol << 1;
436 of.flags |= UF_S3MSLIDES;
437
438 /* read the order data */
439 if (!AllocPositions (mh->ordernum + 1))
440 {
441 _mm_errno = MMERR_OUT_OF_MEMORY;
442 return 0;
443 }
444
445 _mm_fseek (modreader, mh->orderloc, SEEK_SET);
446 for (i = 0; i < mh->ordernum + 1; i++)
447 of.positions[i] = _mm_read_UBYTE (modreader);
448
449 of.numpos = 0;
450 for (i = 0; i < mh->ordernum + 1; i++)
451 {
452 of.positions[of.numpos] = of.positions[i];
453 if (of.positions[i] < 254)
454 of.numpos++;
455 }
456
457 /* have we ended abruptly yet? */
458 if (_mm_eof (modreader))
459 {
460 _mm_errno = MMERR_LOADING_HEADER;
461 return 0;
462 }
463
464 /* time to load the samples */
465 if (!AllocSamples ())
466 {
467 _mm_errno = MMERR_OUT_OF_MEMORY;
468 return 0;
469 }
470
471 q = of.samples;
472 position = mh->samdata;
473
474 /* seek to instrument position */
475 _mm_fseek (modreader, mh->samhead, SEEK_SET);
476
477 for (i = 0; i < of.numins; i++)
478 {
479 /* load sample info */
480 _mm_read_UBYTES (s.sampname, 32, modreader);
481 _mm_read_UBYTES (s.filename, 12, modreader);
482 s.ems = _mm_read_UBYTE (modreader);
483 s.length = _mm_read_I_ULONG (modreader);
484 s.loopbeg = _mm_read_I_ULONG (modreader);
485 s.loopend = _mm_read_I_ULONG (modreader);
486 s.flags = _mm_read_UBYTE (modreader);
487 s.c4spd = _mm_read_I_UWORD (modreader);
488 s.vol = _mm_read_UBYTE (modreader);
489 s.pan = _mm_read_UBYTE (modreader);
490
491 if (_mm_eof (modreader))
492 {
493 _mm_errno = MMERR_LOADING_SAMPLEINFO;
494 return 0;
495 }
496 q->samplename = DupStr (s.sampname, 32, 0);
497 q->speed = s.c4spd;
498 q->length = s.length;
499 q->loopstart = s.loopbeg;
500 q->loopend = s.loopend;
501 q->volume = s.vol;
502 q->panning = s.pan;
503 q->seekpos = position;
504
505 position += s.length;
506
507 if (s.flags & 1)
508 q->flags |= SF_LOOP;
509 if (s.flags & 2)
510 q->flags |= SF_16BITS;
511 if (s.flags & 16)
512 q->flags |= SF_STEREO;
513 q++;
514 }
515
516 /* set the panning */
517 for (i = x = 0; i < 32; i++)
518 {
519 of.panning[i] = mh->pantable[i];
520 if (!of.panning[i])
521 of.panning[i] = PAN_LEFT;
522 else if (of.panning[i] == 8)
523 of.panning[i] = PAN_CENTER;
524 else if (of.panning[i] == 15)
525 of.panning[i] = PAN_RIGHT;
526 else if (of.panning[i] == 16)
527 of.panning[i] = PAN_SURROUND;
528 else if (of.panning[i] == 255)
529 of.panning[i] = 128;
530 else
531 of.panning[i] <<= 3;
532 of.panning[i] = PAN_CENTER;
533 if (mh->pantable[i] != 255)
534 x = i;
535 }
536
537 of.numchn = x + 1;
538 if (of.numchn < 1)
539 of.numchn = 1; /* for broken counts */
540
541 /* load the pattern info */
542 of.numtrk = of.numpat * of.numchn;
543
544 /* jump to patterns */
545 _mm_fseek (modreader, mh->patternloc, SEEK_SET);
546
547 if (!AllocTracks ())
548 {
549 _mm_errno = MMERR_OUT_OF_MEMORY;
550 return 0;
551 }
552
553 if (!AllocPatterns ())
554 {
555 _mm_errno = MMERR_OUT_OF_MEMORY;
556 return 0;
557 }
558
559 for (i = track = 0; i < of.numpat; i++)
560 {
561 if (!GDM_ReadPattern ())
562 {
563 _mm_errno = MMERR_LOADING_PATTERN;
564 return 0;
565 }
566 for (u = 0; u < of.numchn; u++, track++)
567 {
568 of.tracks[track] = GDM_ConvertTrack (&gdmbuf[u << 6]);
569 if (!of.tracks[track])
570 {
571 _mm_errno = MMERR_LOADING_TRACK;
572 return 0;
573 }
574 }
575 }
576 return 1;
577 }
578
579 static CHAR *
GDM_LoadTitle(void)580 GDM_LoadTitle (void)
581 {
582 CHAR s[32];
583
584 _mm_fseek (modreader, 4, SEEK_SET);
585 if (!_mm_read_UBYTES (s, 32, modreader))
586 return NULL;
587
588 return DupStr (s, 28, 0);
589 }
590
591 MLOADER load_gdm =
592 {
593 NULL,
594 "GDM",
595 "GDM (General DigiMusic)",
596 GDM_Init,
597 GDM_Test,
598 GDM_Load,
599 GDM_Cleanup,
600 GDM_LoadTitle
601 };
602
603 /* ex:set ts=4: */
604