1 /* MikMod sound library
2 (c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
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.
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.
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
21 /*==============================================================================
25 Screamtracker (S3M) module loader
27 ==============================================================================*/
35 #include "unimod_priv.h"
37 /*========== Module structure */
40 typedef struct S3MHEADER
65 /* sample information */
66 typedef struct S3MSAMPLE
86 typedef struct S3MNOTE
88 UBYTE note, ins, vol, cmd, inf;
92 /*========== Loader variables */
94 static S3MNOTE *s3mbuf = NULL; /* pointer to a complete S3M pattern */
95 static S3MHEADER *mh = NULL;
96 static UWORD *paraptr = NULL; /* parapointer array (see S3M docs) */
98 /* tracker identifiers */
100 static CHAR *S3M_Version[] =
102 "Screamtracker x.xx",
103 "Imago Orpheus x.xx (S3M format)",
104 "Impulse Tracker x.xx (S3M format)",
105 "Unknown tracker x.xx (S3M format)",
106 "Impulse Tracker 2.14p3 (S3M format)",
107 "Impulse Tracker 2.14p4 (S3M format)"
109 /* version number position in above array */
110 static int numeric[NUMTRACKERS] =
113 /*========== Loader code */
120 _mm_fseek (modreader, 0x2c, SEEK_SET);
121 if (!_mm_read_UBYTES (id, 4, modreader))
123 if (!memcmp (id, "SCRM", 4))
131 if (!(s3mbuf = (S3MNOTE *) _mm_malloc (32 * 64 * sizeof (S3MNOTE))))
133 if (!(mh = (S3MHEADER *) _mm_malloc (sizeof (S3MHEADER))))
135 if (!(poslookup = (UBYTE *) _mm_malloc (sizeof (UBYTE) * 256)))
137 memset (poslookup, -1, 256);
147 _mm_free (poslookup);
149 _mm_free (origpositions);
152 /* Because so many s3m files have 16 channels as the set number used, but really
153 only use far less (usually 8 to 12 still), I had to make this function, which
154 determines the number of channels that are actually USED by a pattern.
156 For every channel that's used, it sets the appropriate array entry of the
157 global variable 'remap'
159 NOTE: You must first seek to the file location of the pattern before calling
162 Returns 1 on fail. */
164 S3M_GetNumChannels (void)
166 int row = 0, flag, ch;
170 flag = _mm_read_UBYTE (modreader);
172 if (_mm_eof (modreader))
174 _mm_errno = MMERR_LOADING_PATTERN;
181 if (mh->channels[ch] < 32)
185 _mm_read_UBYTE (modreader);
186 _mm_read_UBYTE (modreader);
189 _mm_read_UBYTE (modreader);
192 _mm_read_UBYTE (modreader);
193 _mm_read_UBYTE (modreader);
203 S3M_ReadPattern (void)
205 int row = 0, flag, ch;
208 /* clear pattern data */
209 memset (s3mbuf, 255, 32 * 64 * sizeof (S3MNOTE));
213 flag = _mm_read_UBYTE (modreader);
215 if (_mm_eof (modreader))
217 _mm_errno = MMERR_LOADING_PATTERN;
223 ch = remap[flag & 31];
226 n = &s3mbuf[(64U * ch) + row];
232 n->note = _mm_read_UBYTE (modreader);
233 n->ins = _mm_read_UBYTE (modreader);
236 n->vol = _mm_read_UBYTE (modreader);
239 n->cmd = _mm_read_UBYTE (modreader);
240 n->inf = _mm_read_UBYTE (modreader);
250 S3M_ConvertTrack (S3MNOTE * tr)
255 for (t = 0; t < 64; t++)
257 UBYTE note, ins, vol;
263 if ((ins) && (ins != 255))
264 UniInstrument (ins - 1);
269 UniPTEffect (0xc, 0); /* note cut command */
273 UniNote (((note >> 4) * OCTAVE) + (note & 0xf)); /* normal note */
276 UniPTEffect (0xc, vol);
278 S3MIT_ProcessCmd (tr[t].cmd, tr[t].inf, 1);
285 S3M_Load (BOOL curious)
291 /* try to read module header */
292 _mm_read_string (mh->songname, 28, modreader);
293 mh->t1a = _mm_read_UBYTE (modreader);
294 mh->type = _mm_read_UBYTE (modreader);
295 _mm_read_UBYTES (mh->unused1, 2, modreader);
296 mh->ordnum = _mm_read_I_UWORD (modreader);
297 mh->insnum = _mm_read_I_UWORD (modreader);
298 mh->patnum = _mm_read_I_UWORD (modreader);
299 mh->flags = _mm_read_I_UWORD (modreader);
300 mh->tracker = _mm_read_I_UWORD (modreader);
301 mh->fileformat = _mm_read_I_UWORD (modreader);
302 _mm_read_string (mh->scrm, 4, modreader);
303 mh->mastervol = _mm_read_UBYTE (modreader);
304 mh->initspeed = _mm_read_UBYTE (modreader);
305 mh->inittempo = _mm_read_UBYTE (modreader);
306 mh->mastermult = _mm_read_UBYTE (modreader);
307 mh->ultraclick = _mm_read_UBYTE (modreader);
308 mh->pantable = _mm_read_UBYTE (modreader);
309 _mm_read_UBYTES (mh->unused2, 8, modreader);
310 mh->special = _mm_read_I_UWORD (modreader);
311 _mm_read_UBYTES (mh->channels, 32, modreader);
313 if (_mm_eof (modreader))
315 _mm_errno = MMERR_LOADING_HEADER;
319 /* set module variables */
320 of.songname = DupStr (mh->songname, 28, 0);
321 of.numpat = mh->patnum;
323 of.numins = of.numsmp = mh->insnum;
324 of.initspeed = mh->initspeed;
325 of.inittempo = mh->inittempo;
326 of.initvolume = mh->mastervol << 1;
327 of.flags |= UF_ARPMEM;
328 if ((mh->tracker == 0x1300) || (mh->flags & 64))
329 of.flags |= UF_S3MSLIDES;
331 /* read the order data */
332 if (!AllocPositions (mh->ordnum))
334 if (!(origpositions = _mm_calloc (mh->ordnum, sizeof (UWORD))))
337 for (t = 0; t < mh->ordnum; t++)
339 origpositions[t] = _mm_read_UBYTE (modreader);
340 if ((origpositions[t] >= mh->patnum) && (origpositions[t] < 254))
341 origpositions[t] = 255 /*mh->patnum-1 */ ;
344 if (_mm_eof (modreader))
346 _mm_errno = MMERR_LOADING_HEADER;
350 poslookupcnt = mh->ordnum;
351 S3MIT_CreateOrders (curious);
353 if (!(paraptr = (UWORD *) _mm_malloc ((of.numins + of.numpat) * sizeof (UWORD))))
356 /* read the instrument+pattern parapointers */
357 _mm_read_I_UWORDS (paraptr, of.numins + of.numpat, modreader);
359 if (mh->pantable == 252)
361 /* read the panning table (ST 3.2 addition. See below for further
362 portions of channel panning [past reampper]). */
363 _mm_read_UBYTES (pan, 32, modreader);
366 if (_mm_eof (modreader))
368 _mm_errno = MMERR_LOADING_HEADER;
373 if (!AllocSamples ())
376 for (t = 0; t < of.numins; t++)
380 /* seek to instrument position */
381 _mm_fseek (modreader, ((long) paraptr[t]) << 4, SEEK_SET);
382 /* and load sample info */
383 s.type = _mm_read_UBYTE (modreader);
384 _mm_read_string (s.filename, 12, modreader);
385 s.memsegh = _mm_read_UBYTE (modreader);
386 s.memsegl = _mm_read_I_UWORD (modreader);
387 s.length = _mm_read_I_ULONG (modreader);
388 s.loopbeg = _mm_read_I_ULONG (modreader);
389 s.loopend = _mm_read_I_ULONG (modreader);
390 s.volume = _mm_read_UBYTE (modreader);
391 s.dsk = _mm_read_UBYTE (modreader);
392 s.pack = _mm_read_UBYTE (modreader);
393 s.flags = _mm_read_UBYTE (modreader);
394 s.c2spd = _mm_read_I_ULONG (modreader);
395 _mm_read_UBYTES (s.unused, 12, modreader);
396 _mm_read_string (s.sampname, 28, modreader);
397 _mm_read_string (s.scrs, 4, modreader);
399 if (_mm_eof (modreader))
401 _mm_errno = MMERR_LOADING_SAMPLEINFO;
405 q->samplename = DupStr (s.sampname, 28, 0);
407 q->length = s.length;
408 q->loopstart = s.loopbeg > s.length ? s.length : s.loopbeg;
409 q->loopend = s.loopend > s.length ? s.length : s.loopend;
410 q->volume = s.volume;
411 q->seekpos = (((long) s.memsegh) << 16 | s.memsegl) << 4;
416 q->flags |= SF_16BITS;
417 if (mh->fileformat == 1)
418 q->flags |= SF_SIGNED;
420 /* don't load sample if it doesn't have the SCRS tag */
421 if (memcmp (s.scrs, "SCRS", 4))
427 /* determine the number of channels actually used. */
429 memset (remap, -1, 32 * sizeof (UBYTE));
430 for (t = 0; t < of.numpat; t++)
432 /* seek to pattern position (+2 skip pattern length) */
433 _mm_fseek (modreader, (long) ((paraptr[of.numins + t]) << 4) + 2, SEEK_SET);
434 if (S3M_GetNumChannels ())
437 /* then we can decide the module type */
438 t = mh->tracker >> 12;
440 t = NUMTRACKERS - 1; /* unknown tracker */
443 if (mh->tracker >= 0x3217)
444 t = NUMTRACKERS + 1; /* IT 2.14p4 */
445 else if (mh->tracker >= 0x3216)
446 t = NUMTRACKERS; /* IT 2.14p3 */
450 of.modtype = strdup (S3M_Version[t]);
453 of.modtype[numeric[t]] = ((mh->tracker >> 8) & 0xf) + '0';
454 of.modtype[numeric[t] + 2] = ((mh->tracker >> 4) & 0xf) + '0';
455 of.modtype[numeric[t] + 3] = ((mh->tracker) & 0xf) + '0';
458 /* build the remap array */
459 for (t = 0; t < 32; t++)
461 remap[t] = of.numchn++;
463 /* set panning positions after building remap chart! */
464 for (t = 0; t < 32; t++)
465 if ((mh->channels[t] < 32) && (remap[t] != -1))
467 if (mh->channels[t] < 8)
468 of.panning[remap[t]] = 0x20; /* 0x30 = std s3m val */
470 of.panning[remap[t]] = 0xd0; /* 0xc0 = std s3m val */
472 if (mh->pantable == 252)
473 /* set panning positions according to panning table (new for st3.2) */
474 for (t = 0; t < 32; t++)
475 if ((pan[t] & 0x20) && (mh->channels[t] < 32) && (remap[t] != -1))
476 of.panning[remap[t]] = (pan[t] & 0xf) << 4;
478 /* load pattern info */
479 of.numtrk = of.numpat * of.numchn;
482 if (!AllocPatterns ())
485 for (t = 0; t < of.numpat; t++)
487 /* seek to pattern position (+2 skip pattern length) */
488 _mm_fseek (modreader, (((long) paraptr[of.numins + t]) << 4) + 2, SEEK_SET);
489 if (!S3M_ReadPattern ())
491 for (u = 0; u < of.numchn; u++)
492 if (!(of.tracks[track++] = S3M_ConvertTrack (&s3mbuf[u * 64])))
504 _mm_fseek (modreader, 0, SEEK_SET);
505 if (!_mm_read_UBYTES (s, 28, modreader))
508 return (DupStr (s, 28, 0));
511 /*========== Loader information */
517 "S3M (Scream Tracker 3)",