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