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   DMP Advanced Module Format 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 typedef struct AMFHEADER
40   {
41     UBYTE id[3];		/* AMF file marker */
42     UBYTE version;		/* upper major, lower nibble minor version number */
43     CHAR songname[32];		/* ASCIIZ songname */
44     UBYTE numsamples;		/* number of samples saved */
45     UBYTE numorders;
46     UWORD numtracks;		/* number of tracks saved */
47     UBYTE numchannels;		/* number of channels used  */
48     SBYTE panpos[32];		/* voice pan positions */
49     UBYTE songbpm;
50     UBYTE songspd;
51   }
52 AMFHEADER;
53 
54 typedef struct AMFSAMPLE
55   {
56     UBYTE type;
57     CHAR samplename[32];
58     CHAR filename[13];
59     ULONG offset;
60     ULONG length;
61     UWORD c2spd;
62     UBYTE volume;
63     ULONG reppos;
64     ULONG repend;
65   }
66 AMFSAMPLE;
67 
68 typedef struct AMFNOTE
69   {
70     UBYTE note, instr, volume, fxcnt;
71     UBYTE effect[3];
72     SBYTE parameter[3];
73   }
74 AMFNOTE;
75 
76 /*========== Loader variables */
77 
78 static AMFHEADER *mh = NULL;
79 #define AMFTEXTLEN 22
80 static CHAR AMF_Version[AMFTEXTLEN + 1] = "DSMI Module Format 0.0";
81 static AMFNOTE *track = NULL;
82 
83 /*========== Loader code */
84 
85 static BOOL
AMF_Test(void)86 AMF_Test (void)
87 {
88   UBYTE id[3], ver;
89 
90   if (!_mm_read_UBYTES (id, 3, modreader))
91     return 0;
92   if (memcmp (id, "AMF", 3))
93     return 0;
94 
95   ver = _mm_read_UBYTE (modreader);
96   if ((ver >= 10) && (ver <= 14))
97     return 1;
98   return 0;
99 }
100 
101 static BOOL
AMF_Init(void)102 AMF_Init (void)
103 {
104   if (!(mh = (AMFHEADER *) _mm_malloc (sizeof (AMFHEADER))))
105     return 0;
106   if (!(track = (AMFNOTE *) _mm_calloc (64, sizeof (AMFNOTE))))
107     return 0;
108 
109   return 1;
110 }
111 
112 static void
AMF_Cleanup(void)113 AMF_Cleanup (void)
114 {
115   _mm_free (mh);
116   _mm_free (track);
117 }
118 
119 static BOOL
AMF_UnpackTrack(URL modreader)120 AMF_UnpackTrack (URL modreader)
121 {
122   ULONG tracksize;
123   UBYTE row, cmd;
124   SBYTE arg;
125 
126   /* empty track */
127   memset (track, 0, 64 * sizeof (AMFNOTE));
128 
129   /* read packed track */
130   if (modreader)
131     {
132       tracksize = _mm_read_I_UWORD (modreader);
133       tracksize += ((ULONG) _mm_read_UBYTE (modreader)) << 16;
134       if (tracksize)
135 	while (tracksize--)
136 	  {
137 	    row = _mm_read_UBYTE (modreader);
138 	    cmd = _mm_read_UBYTE (modreader);
139 	    arg = _mm_read_SBYTE (modreader);
140 	    /* unexpected end of track */
141 	    if (!tracksize)
142 	      {
143 		if ((row == 0xff) && (cmd == 0xff) && (arg == -1))
144 		  break;
145 		/* the last triplet should be FF FF FF, but this is not
146 		   always the case... maybe a bug in m2amf ?
147 		   else
148 		   return 0;
149 		 */
150 
151 	      }
152 	    /* invalid row (probably unexpected end of row) */
153 	    if (row >= 64)
154 	      return 0;
155 	    if (cmd < 0x7f)
156 	      {
157 		/* note, vol */
158 		track[row].note = cmd;
159 		track[row].volume = (UBYTE) arg + 1;
160 	      }
161 	    else if (cmd == 0x7f)
162 	      {
163 		/* duplicate row */
164 		if ((arg < 0) && (row + arg >= 0))
165 		  {
166 		    memcpy (track + row, track + (row + arg), sizeof (AMFNOTE));
167 		  }
168 	      }
169 	    else if (cmd == 0x80)
170 	      {
171 		/* instr */
172 		track[row].instr = arg + 1;
173 	      }
174 	    else if (cmd == 0x83)
175 	      {
176 		/* volume without note */
177 		track[row].volume = (UBYTE) arg + 1;
178 	      }
179 	    else if (track[row].fxcnt < 3)
180 	      {
181 		/* effect, param */
182 		if (cmd > 0x97)
183 		  return 0;
184 		track[row].effect[track[row].fxcnt] = cmd & 0x7f;
185 		track[row].parameter[track[row].fxcnt] = arg;
186 		track[row].fxcnt++;
187 	      }
188 	    else
189 	      return 0;
190 	  }
191     }
192   return 1;
193 }
194 
195 static UBYTE *
AMF_ConvertTrack(void)196 AMF_ConvertTrack (void)
197 {
198   int row, fx4memory = 0;
199 
200   /* convert track */
201   UniReset ();
202   for (row = 0; row < 64; row++)
203     {
204       if (track[row].instr)
205 	UniInstrument (track[row].instr - 1);
206       if (track[row].note > OCTAVE)
207 	UniNote (track[row].note - OCTAVE);
208 
209       /* AMF effects */
210       while (track[row].fxcnt--)
211 	{
212 	  SBYTE inf = track[row].parameter[track[row].fxcnt];
213 
214 	  switch (track[row].effect[track[row].fxcnt])
215 	    {
216 	    case 1:		/* Set speed */
217 	      UniEffect (UNI_S3MEFFECTA, inf);
218 	      break;
219 	    case 2:		/* Volume slide */
220 	      if (inf)
221 		{
222 		  UniWriteByte (UNI_S3MEFFECTD);
223 		  if (inf >= 0)
224 		    UniWriteByte ((inf & 0xf) << 4);
225 		  else
226 		    UniWriteByte ((-inf) & 0xf);
227 		}
228 	      break;
229 	      /* effect 3, set channel volume, done in UnpackTrack */
230 	    case 4:		/* Porta up/down */
231 	      if (inf)
232 		{
233 		  if (inf > 0)
234 		    {
235 		      UniEffect (UNI_S3MEFFECTE, inf);
236 		      fx4memory = UNI_S3MEFFECTE;
237 		    }
238 		  else
239 		    {
240 		      UniEffect (UNI_S3MEFFECTF, -inf);
241 		      fx4memory = UNI_S3MEFFECTF;
242 		    }
243 		}
244 	      else if (fx4memory)
245 		UniEffect (fx4memory, 0);
246 	      break;
247 	      /* effect 5, "Porta abs", not supported */
248 	    case 6:		/* Porta to note */
249 	      UniEffect (UNI_ITEFFECTG, inf);
250 	      break;
251 	    case 7:		/* Tremor */
252 	      UniEffect (UNI_S3MEFFECTI, inf);
253 	      break;
254 	    case 8:		/* Arpeggio */
255 	      UniPTEffect (0x0, inf);
256 	      break;
257 	    case 9:		/* Vibrato */
258 	      UniPTEffect (0x4, inf);
259 	      break;
260 	    case 0xa:		/* Porta + Volume slide */
261 	      UniPTEffect (0x3, 0);
262 	      if (inf)
263 		{
264 		  UniWriteByte (UNI_S3MEFFECTD);
265 		  if (inf >= 0)
266 		    UniWriteByte ((inf & 0xf) << 4);
267 		  else
268 		    UniWriteByte ((-inf) & 0xf);
269 		}
270 	      break;
271 	    case 0xb:		/* Vibrato + Volume slide */
272 	      UniPTEffect (0x4, 0);
273 	      if (inf)
274 		{
275 		  UniWriteByte (UNI_S3MEFFECTD);
276 		  if (inf >= 0)
277 		    UniWriteByte ((inf & 0xf) << 4);
278 		  else
279 		    UniWriteByte ((-inf) & 0xf);
280 		}
281 	      break;
282 	    case 0xc:		/* Pattern break (in hex) */
283 	      UniPTEffect (0xd, inf);
284 	      break;
285 	    case 0xd:		/* Pattern jump */
286 	      UniPTEffect (0xb, inf);
287 	      break;
288 	      /* effect 0xe, "Sync", not supported */
289 	    case 0xf:		/* Retrig */
290 	      UniEffect (UNI_S3MEFFECTQ, inf & 0xf);
291 	      break;
292 	    case 0x10:		/* Sample offset */
293 	      UniPTEffect (0x9, inf);
294 	      break;
295 	    case 0x11:		/* Fine volume slide */
296 	      if (inf)
297 		{
298 		  UniWriteByte (UNI_S3MEFFECTD);
299 		  if (inf >= 0)
300 		    UniWriteByte ((inf & 0xf) << 4 | 0xf);
301 		  else
302 		    UniWriteByte (0xf0 | ((-inf) & 0xf));
303 		}
304 	      break;
305 	    case 0x12:		/* Fine portamento */
306 	      if (inf)
307 		{
308 		  if (inf > 0)
309 		    {
310 		      UniEffect (UNI_S3MEFFECTE, 0xf0 | (inf & 0xf));
311 		      fx4memory = UNI_S3MEFFECTE;
312 		    }
313 		  else
314 		    {
315 		      UniEffect (UNI_S3MEFFECTF, 0xf0 | ((-inf) & 0xf));
316 		      fx4memory = UNI_S3MEFFECTF;
317 		    }
318 		}
319 	      else if (fx4memory)
320 		UniEffect (fx4memory, 0);
321 	      break;
322 	    case 0x13:		/* Delay note */
323 	      UniPTEffect (0xe, 0xd0 | (inf & 0xf));
324 	      break;
325 	    case 0x14:		/* Note cut */
326 	      UniPTEffect (0xc, 0);
327 	      track[row].volume = 0;
328 	      break;
329 	    case 0x15:		/* Set tempo */
330 	      UniEffect (UNI_S3MEFFECTT, inf);
331 	      break;
332 	    case 0x16:		/* Extra fine portamento */
333 	      if (inf)
334 		{
335 		  if (inf > 0)
336 		    {
337 		      UniEffect (UNI_S3MEFFECTE, 0xe0 | ((inf >> 2) & 0xf));
338 		      fx4memory = UNI_S3MEFFECTE;
339 		    }
340 		  else
341 		    {
342 		      UniEffect (UNI_S3MEFFECTF, 0xe0 | (((-inf) >> 2) & 0xf));
343 		      fx4memory = UNI_S3MEFFECTF;
344 		    }
345 		}
346 	      else if (fx4memory)
347 		UniEffect (fx4memory, 0);
348 	      break;
349 	    case 0x17:		/* Panning */
350 	      if (inf > 64)
351 		UniEffect (UNI_ITEFFECTS0, 0x91);	/* surround */
352 	      else
353 		UniPTEffect (0x8, (inf == 64) ? 255 : (inf + 64) << 1);
354 	      break;
355 	    }
356 
357 	}
358       if (track[row].volume)
359 	UniVolEffect (VOL_VOLUME, track[row].volume - 1);
360       UniNewline ();
361     }
362   return UniDup ();
363 }
364 
365 static BOOL
AMF_Load(BOOL curious)366 AMF_Load (BOOL curious)
367 {
368   int t, u, realtrackcnt, realsmpcnt;
369   AMFSAMPLE s;
370   SAMPLE *q;
371   UWORD *track_remap;
372   ULONG samplepos;
373   int channel_remap[16];
374 
375   /* try to read module header  */
376   _mm_read_UBYTES (mh->id, 3, modreader);
377   mh->version = _mm_read_UBYTE (modreader);
378   _mm_read_string (mh->songname, 32, modreader);
379   mh->numsamples = _mm_read_UBYTE (modreader);
380   mh->numorders = _mm_read_UBYTE (modreader);
381   mh->numtracks = _mm_read_I_UWORD (modreader);
382   mh->numchannels = _mm_read_UBYTE (modreader);
383   if ((!mh->numchannels) || (mh->numchannels > (mh->version >= 12 ? 32 : 16)))
384     {
385       _mm_errno = MMERR_NOT_A_MODULE;
386       return 0;
387     }
388 
389   if (mh->version >= 11)
390     {
391       memset (mh->panpos, 0, 32);
392       _mm_read_SBYTES (mh->panpos, (mh->version >= 13) ? 32 : 16, modreader);
393     }
394   else
395     _mm_read_UBYTES (channel_remap, 16, modreader);
396 
397   if (mh->version >= 13)
398     {
399       mh->songbpm = _mm_read_UBYTE (modreader);
400       if (mh->songbpm < 32)
401 	{
402 	  _mm_errno = MMERR_NOT_A_MODULE;
403 	  return 0;
404 	}
405       mh->songspd = _mm_read_UBYTE (modreader);
406       if (mh->songspd > 32)
407 	{
408 	  _mm_errno = MMERR_NOT_A_MODULE;
409 	  return 0;
410 	}
411     }
412   else
413     {
414       mh->songbpm = 125;
415       mh->songspd = 6;
416     }
417 
418   if (_mm_eof (modreader))
419     {
420       _mm_errno = MMERR_LOADING_HEADER;
421       return 0;
422     }
423 
424   /* set module variables */
425   of.initspeed = mh->songspd;
426   of.inittempo = mh->songbpm;
427   AMF_Version[AMFTEXTLEN - 3] = '0' + (mh->version / 10);
428   AMF_Version[AMFTEXTLEN - 1] = '0' + (mh->version % 10);
429   of.modtype = strdup (AMF_Version);
430   of.numchn = mh->numchannels;
431   of.numtrk = mh->numorders * mh->numchannels;
432   if (mh->numtracks > of.numtrk)
433     of.numtrk = mh->numtracks;
434   of.songname = DupStr (mh->songname, 32, 1);
435   of.numpos = mh->numorders;
436   of.numpat = mh->numorders;
437   of.reppos = 0;
438   of.flags |= UF_S3MSLIDES;
439   for (t = 0; t < 32; t++)
440     {
441       if (mh->panpos[t] > 64)
442 	of.panning[t] = PAN_SURROUND;
443       else if (mh->panpos[t] == 64)
444 	of.panning[t] = 255;
445       else
446 	of.panning[t] = (mh->panpos[t] + 64) << 1;
447     }
448   of.numins = of.numsmp = mh->numsamples;
449 
450   if (!AllocPositions (of.numpos))
451     return 0;
452   for (t = 0; t < of.numpos; t++)
453     of.positions[t] = t;
454 
455   if (!AllocTracks ())
456     return 0;
457   if (!AllocPatterns ())
458     return 0;
459 
460   /* read AMF order table */
461   for (t = 0; t < of.numpat; t++)
462     {
463       if (mh->version >= 14)
464 	/* track size */
465 	of.pattrows[t] = _mm_read_I_UWORD (modreader);
466       if (mh->version >= 10)
467 	_mm_read_I_UWORDS (of.patterns + (t * of.numchn), of.numchn, modreader);
468       else
469 	for (u = 0; u < of.numchn; u++)
470 	  of.patterns[t * of.numchn + channel_remap[u]] = _mm_read_I_UWORD (modreader);
471     }
472   if (_mm_eof (modreader))
473     {
474       _mm_errno = MMERR_LOADING_HEADER;
475       return 0;
476     }
477 
478   /* read sample information */
479   if (!AllocSamples ())
480     return 0;
481   q = of.samples;
482   for (t = 0; t < of.numins; t++)
483     {
484       /* try to read sample info */
485       s.type = _mm_read_UBYTE (modreader);
486       _mm_read_string (s.samplename, 32, modreader);
487       _mm_read_string (s.filename, 13, modreader);
488       s.offset = _mm_read_I_ULONG (modreader);
489       s.length = _mm_read_I_ULONG (modreader);
490       s.c2spd = _mm_read_I_UWORD (modreader);
491       if (s.c2spd == 8368)
492 	s.c2spd = 8363;
493       s.volume = _mm_read_UBYTE (modreader);
494       if (mh->version >= 11)
495 	{
496 	  s.reppos = _mm_read_I_ULONG (modreader);
497 	  s.repend = _mm_read_I_ULONG (modreader);
498 	}
499       else
500 	{
501 	  s.reppos = _mm_read_I_UWORD (modreader);
502 	  s.repend = s.length;
503 	}
504 
505       if (_mm_eof (modreader))
506 	{
507 	  _mm_errno = MMERR_LOADING_SAMPLEINFO;
508 	  return 0;
509 	}
510 
511       q->samplename = DupStr (s.samplename, 32, 1);
512       q->speed = s.c2spd;
513       q->volume = s.volume;
514       if (s.type)
515 	{
516 	  q->seekpos = s.offset;
517 	  q->length = s.length;
518 	  q->loopstart = s.reppos;
519 	  q->loopend = s.repend;
520 	  if ((s.repend - s.reppos) > 2)
521 	    q->flags |= SF_LOOP;
522 	}
523       q++;
524     }
525 
526   /* read track table */
527   if (!(track_remap = _mm_calloc (mh->numtracks + 1, sizeof (UWORD))))
528     return 0;
529   _mm_read_I_UWORDS (track_remap + 1, mh->numtracks, modreader);
530   if (_mm_eof (modreader))
531     {
532       free (track_remap);
533       _mm_errno = MMERR_LOADING_TRACK;
534       return 0;
535     }
536 
537   for (realtrackcnt = t = 0; t <= mh->numtracks; t++)
538     if (realtrackcnt < track_remap[t])
539       realtrackcnt = track_remap[t];
540   for (t = 0; t < of.numpat * of.numchn; t++)
541     of.patterns[t] = (of.patterns[t] <= mh->numtracks) ?
542       track_remap[of.patterns[t]] - 1 : realtrackcnt;
543 
544   free (track_remap);
545 
546   /* unpack tracks */
547   for (t = 0; t < realtrackcnt; t++)
548     {
549       if (_mm_eof (modreader))
550 	{
551 	  _mm_errno = MMERR_LOADING_TRACK;
552 	  return 0;
553 	}
554       if (!AMF_UnpackTrack (modreader))
555 	{
556 	  _mm_errno = MMERR_LOADING_TRACK;
557 	  return 0;
558 	}
559       if (!(of.tracks[t] = AMF_ConvertTrack ()))
560 	return 0;
561     }
562   /* add en extra void track */
563   UniReset ();
564   for (t = 0; t < 64; t++)
565     UniNewline ();
566   of.tracks[realtrackcnt++] = UniDup ();
567   for (t = realtrackcnt; t < of.numtrk; t++)
568     of.tracks[t] = NULL;
569 
570   /* compute sample offsets */
571   samplepos = _mm_ftell (modreader);
572   for (realsmpcnt = t = 0; t < of.numsmp; t++)
573     if (realsmpcnt < of.samples[t].seekpos)
574       realsmpcnt = of.samples[t].seekpos;
575   for (t = 1; t <= realsmpcnt; t++)
576     {
577       q = of.samples;
578       while (q->seekpos != t)
579 	q++;
580       q->seekpos = samplepos;
581       samplepos += q->length;
582     }
583 
584   return 1;
585 }
586 
587 static CHAR *
AMF_LoadTitle(void)588 AMF_LoadTitle (void)
589 {
590   CHAR s[32];
591 
592   _mm_fseek (modreader, 4, SEEK_SET);
593   if (!_mm_read_UBYTES (s, 32, modreader))
594     return NULL;
595 
596   return (DupStr (s, 32, 1));
597 }
598 
599 /*========== Loader information */
600 
601 MLOADER load_amf =
602 {
603   NULL,
604   "AMF",
605   "AMF (DSMI Advanced Module Format)",
606   AMF_Init,
607   AMF_Test,
608   AMF_Load,
609   AMF_Cleanup,
610   AMF_LoadTitle
611 };
612 
613 /* ex:set ts=4: */
614