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 Screamtracker (S3M) module 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 /* header */
40 typedef struct S3MHEADER
41 {
42 CHAR songname[28];
43 UBYTE t1a;
44 UBYTE type;
45 UBYTE unused1[2];
46 UWORD ordnum;
47 UWORD insnum;
48 UWORD patnum;
49 UWORD flags;
50 UWORD tracker;
51 UWORD fileformat;
52 CHAR scrm[4];
53 UBYTE mastervol;
54 UBYTE initspeed;
55 UBYTE inittempo;
56 UBYTE mastermult;
57 UBYTE ultraclick;
58 UBYTE pantable;
59 UBYTE unused2[8];
60 UWORD special;
61 UBYTE channels[32];
62 }
63 S3MHEADER;
64
65 /* sample information */
66 typedef struct S3MSAMPLE
67 {
68 UBYTE type;
69 CHAR filename[12];
70 UBYTE memsegh;
71 UWORD memsegl;
72 ULONG length;
73 ULONG loopbeg;
74 ULONG loopend;
75 UBYTE volume;
76 UBYTE dsk;
77 UBYTE pack;
78 UBYTE flags;
79 ULONG c2spd;
80 UBYTE unused[12];
81 CHAR sampname[28];
82 CHAR scrs[4];
83 }
84 S3MSAMPLE;
85
86 typedef struct S3MNOTE
87 {
88 UBYTE note, ins, vol, cmd, inf;
89 }
90 S3MNOTE;
91
92 /*========== Loader variables */
93
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) */
97
98 /* tracker identifiers */
99 #define NUMTRACKERS 4
100 static const CHAR *S3M_Version[] =
101 {
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)"
108 };
109 /* version number position in above array */
110 static int numeric[NUMTRACKERS] =
111 {14, 14, 16, 16};
112
113 /*========== Loader code */
114
115 static BOOL
S3M_Test(void)116 S3M_Test (void)
117 {
118 UBYTE id[4];
119
120 _mm_fseek (modreader, 0x2c, SEEK_SET);
121 if (!_mm_read_UBYTES (id, 4, modreader))
122 return 0;
123 if (!memcmp (id, "SCRM", 4))
124 return 1;
125 return 0;
126 }
127
128 static BOOL
S3M_Init(void)129 S3M_Init (void)
130 {
131 if (!(s3mbuf = (S3MNOTE *) _mm_malloc (32 * 64 * sizeof (S3MNOTE))))
132 return 0;
133 if (!(mh = (S3MHEADER *) _mm_malloc (sizeof (S3MHEADER))))
134 return 0;
135 if (!(poslookup = (UBYTE *) _mm_malloc (sizeof (UBYTE) * 256)))
136 return 0;
137 memset (poslookup, -1, 256);
138
139 return 1;
140 }
141
142 static void
S3M_Cleanup(void)143 S3M_Cleanup (void)
144 {
145 _mm_free (s3mbuf);
146 _mm_free (paraptr);
147 _mm_free (poslookup);
148 _mm_free (mh);
149 _mm_free (origpositions);
150 }
151
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.
155
156 For every channel that's used, it sets the appropriate array entry of the
157 global variable 'remap'
158
159 NOTE: You must first seek to the file location of the pattern before calling
160 this procedure.
161
162 Returns 1 on fail. */
163 static BOOL
S3M_GetNumChannels(void)164 S3M_GetNumChannels (void)
165 {
166 int row = 0, flag, ch;
167
168 while (row < 64)
169 {
170 flag = _mm_read_UBYTE (modreader);
171
172 if (_mm_eof (modreader))
173 {
174 _mm_errno = MMERR_LOADING_PATTERN;
175 return 1;
176 }
177
178 if (flag)
179 {
180 ch = flag & 31;
181 if (mh->channels[ch] < 32)
182 remap[ch] = 0;
183 if (flag & 32)
184 {
185 _mm_read_UBYTE (modreader);
186 _mm_read_UBYTE (modreader);
187 }
188 if (flag & 64)
189 _mm_read_UBYTE (modreader);
190 if (flag & 128)
191 {
192 _mm_read_UBYTE (modreader);
193 _mm_read_UBYTE (modreader);
194 }
195 }
196 else
197 row++;
198 }
199 return 0;
200 }
201
202 static BOOL
S3M_ReadPattern(void)203 S3M_ReadPattern (void)
204 {
205 int row = 0, flag, ch;
206 S3MNOTE *n, dummy;
207
208 /* clear pattern data */
209 memset (s3mbuf, 255, 32 * 64 * sizeof (S3MNOTE));
210
211 while (row < 64)
212 {
213 flag = _mm_read_UBYTE (modreader);
214
215 if (_mm_eof (modreader))
216 {
217 _mm_errno = MMERR_LOADING_PATTERN;
218 return 0;
219 }
220
221 if (flag)
222 {
223 ch = remap[flag & 31];
224
225 if (ch != -1)
226 n = &s3mbuf[(64U * ch) + row];
227 else
228 n = &dummy;
229
230 if (flag & 32)
231 {
232 n->note = _mm_read_UBYTE (modreader);
233 n->ins = _mm_read_UBYTE (modreader);
234 }
235 if (flag & 64)
236 n->vol = _mm_read_UBYTE (modreader);
237 if (flag & 128)
238 {
239 n->cmd = _mm_read_UBYTE (modreader);
240 n->inf = _mm_read_UBYTE (modreader);
241 }
242 }
243 else
244 row++;
245 }
246 return 1;
247 }
248
249 static UBYTE *
S3M_ConvertTrack(S3MNOTE * tr)250 S3M_ConvertTrack (S3MNOTE * tr)
251 {
252 int t;
253
254 UniReset ();
255 for (t = 0; t < 64; t++)
256 {
257 UBYTE note, ins, vol;
258
259 note = tr[t].note;
260 ins = tr[t].ins;
261 vol = tr[t].vol;
262
263 if ((ins) && (ins != 255))
264 UniInstrument (ins - 1);
265 if (note != 255)
266 {
267 if (note == 254)
268 {
269 UniPTEffect (0xc, 0); /* note cut command */
270 vol = 255;
271 }
272 else
273 UniNote (((note >> 4) * OCTAVE) + (note & 0xf)); /* normal note */
274 }
275 if (vol < 255)
276 UniPTEffect (0xc, vol);
277
278 S3MIT_ProcessCmd (tr[t].cmd, tr[t].inf, 1);
279 UniNewline ();
280 }
281 return UniDup ();
282 }
283
284 static BOOL
S3M_Load(BOOL curious)285 S3M_Load (BOOL curious)
286 {
287 int t, u, track = 0;
288 SAMPLE *q;
289 UBYTE pan[32];
290
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);
312
313 if (_mm_eof (modreader))
314 {
315 _mm_errno = MMERR_LOADING_HEADER;
316 return 0;
317 }
318
319 /* set module variables */
320 of.songname = DupStr (mh->songname, 28, 0);
321 of.numpat = mh->patnum;
322 of.reppos = 0;
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;
330
331 /* read the order data */
332 if (!AllocPositions (mh->ordnum))
333 return 0;
334 if (!(origpositions = _mm_calloc (mh->ordnum, sizeof (UWORD))))
335 return 0;
336
337 for (t = 0; t < mh->ordnum; t++)
338 {
339 origpositions[t] = _mm_read_UBYTE (modreader);
340 if ((origpositions[t] >= mh->patnum) && (origpositions[t] < 254))
341 origpositions[t] = 255 /*mh->patnum-1 */ ;
342 }
343
344 if (_mm_eof (modreader))
345 {
346 _mm_errno = MMERR_LOADING_HEADER;
347 return 0;
348 }
349
350 poslookupcnt = mh->ordnum;
351 S3MIT_CreateOrders (curious);
352
353 if (!(paraptr = (UWORD *) _mm_malloc ((of.numins + of.numpat) * sizeof (UWORD))))
354 return 0;
355
356 /* read the instrument+pattern parapointers */
357 _mm_read_I_UWORDS (paraptr, of.numins + of.numpat, modreader);
358
359 if (mh->pantable == 252)
360 {
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);
364 }
365
366 if (_mm_eof (modreader))
367 {
368 _mm_errno = MMERR_LOADING_HEADER;
369 return 0;
370 }
371
372 /* load samples */
373 if (!AllocSamples ())
374 return 0;
375 q = of.samples;
376 for (t = 0; t < of.numins; t++)
377 {
378 S3MSAMPLE s;
379
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);
398
399 /* ScreamTracker imposes a 64000 bytes (not 64k !) limit */
400 if (s.length > 64000)
401 s.length = 64000;
402
403 if (_mm_eof (modreader))
404 {
405 _mm_errno = MMERR_LOADING_SAMPLEINFO;
406 return 0;
407 }
408
409 q->samplename = DupStr (s.sampname, 28, 0);
410 q->speed = s.c2spd;
411 q->length = s.length;
412 q->loopstart = s.loopbeg > s.length ? s.length : s.loopbeg;
413 q->loopend = s.loopend > s.length ? s.length : s.loopend;
414 q->volume = s.volume;
415 q->seekpos = (((long) s.memsegh) << 16 | s.memsegl) << 4;
416
417 if (s.flags & 1)
418 q->flags |= SF_LOOP;
419 if (s.flags & 4)
420 q->flags |= SF_16BITS;
421 if (mh->fileformat == 1)
422 q->flags |= SF_SIGNED;
423
424 /* don't load sample if it doesn't have the SCRS tag */
425 if (memcmp (s.scrs, "SCRS", 4))
426 q->length = 0;
427
428 q++;
429 }
430
431 /* determine the number of channels actually used. */
432 of.numchn = 0;
433 memset (remap, -1, 32 * sizeof (UBYTE));
434 for (t = 0; t < of.numpat; t++)
435 {
436 /* seek to pattern position (+2 skip pattern length) */
437 _mm_fseek (modreader, (long) ((paraptr[of.numins + t]) << 4) + 2, SEEK_SET);
438 if (S3M_GetNumChannels ())
439 return 0;
440 }
441 /* then we can decide the module type */
442 t = mh->tracker >> 12;
443 if ((!t) || (t > 3))
444 t = NUMTRACKERS - 1; /* unknown tracker */
445 else
446 {
447 if (mh->tracker >= 0x3217)
448 t = NUMTRACKERS + 1; /* IT 2.14p4 */
449 else if (mh->tracker >= 0x3216)
450 t = NUMTRACKERS; /* IT 2.14p3 */
451 else
452 t--;
453 }
454 of.modtype = strdup (S3M_Version[t]);
455 if (t < NUMTRACKERS)
456 {
457 of.modtype[numeric[t]] = ((mh->tracker >> 8) & 0xf) + '0';
458 of.modtype[numeric[t] + 2] = ((mh->tracker >> 4) & 0xf) + '0';
459 of.modtype[numeric[t] + 3] = ((mh->tracker) & 0xf) + '0';
460 }
461
462 /* build the remap array */
463 for (t = 0; t < 32; t++)
464 if (!remap[t])
465 remap[t] = of.numchn++;
466
467 /* set panning positions after building remap chart! */
468 for (t = 0; t < 32; t++)
469 if ((mh->channels[t] < 32) && (remap[t] != -1))
470 {
471 if (mh->channels[t] < 8)
472 of.panning[remap[t]] = 0x20; /* 0x30 = std s3m val */
473 else
474 of.panning[remap[t]] = 0xd0; /* 0xc0 = std s3m val */
475 }
476 if (mh->pantable == 252)
477 /* set panning positions according to panning table (new for st3.2) */
478 for (t = 0; t < 32; t++)
479 if ((pan[t] & 0x20) && (mh->channels[t] < 32) && (remap[t] != -1))
480 of.panning[remap[t]] = (pan[t] & 0xf) << 4;
481
482 /* load pattern info */
483 of.numtrk = of.numpat * of.numchn;
484 if (!AllocTracks ())
485 return 0;
486 if (!AllocPatterns ())
487 return 0;
488
489 for (t = 0; t < of.numpat; t++)
490 {
491 /* seek to pattern position (+2 skip pattern length) */
492 _mm_fseek (modreader, (((long) paraptr[of.numins + t]) << 4) + 2, SEEK_SET);
493 if (!S3M_ReadPattern ())
494 return 0;
495 for (u = 0; u < of.numchn; u++)
496 if (!(of.tracks[track++] = S3M_ConvertTrack (&s3mbuf[u * 64])))
497 return 0;
498 }
499
500 return 1;
501 }
502
503 static CHAR *
S3M_LoadTitle(void)504 S3M_LoadTitle (void)
505 {
506 CHAR s[28];
507
508 _mm_fseek (modreader, 0, SEEK_SET);
509 if (!_mm_read_UBYTES (s, 28, modreader))
510 return NULL;
511
512 return (DupStr (s, 28, 0));
513 }
514
515 /*========== Loader information */
516
517 MLOADER load_s3m =
518 {
519 NULL,
520 "S3M",
521 "S3M (Scream Tracker 3)",
522 S3M_Init,
523 S3M_Test,
524 S3M_Load,
525 S3M_Cleanup,
526 S3M_LoadTitle
527 };
528
529 /* ex:set ts=4: */
530