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