OSDN Git Service

Merge unkotim217
[timidity41/timidity41.git] / libunimod / load_s3m.c
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 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 BOOL 
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 BOOL 
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 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 
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 
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 *
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 BOOL 
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       if (_mm_eof (modreader))
400         {
401           _mm_errno = MMERR_LOADING_SAMPLEINFO;
402           return 0;
403         }
404
405       q->samplename = DupStr (s.sampname, 28, 0);
406       q->speed = s.c2spd;
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;
412
413       if (s.flags & 1)
414         q->flags |= SF_LOOP;
415       if (s.flags & 4)
416         q->flags |= SF_16BITS;
417       if (mh->fileformat == 1)
418         q->flags |= SF_SIGNED;
419
420       /* don't load sample if it doesn't have the SCRS tag */
421       if (memcmp (s.scrs, "SCRS", 4))
422         q->length = 0;
423
424       q++;
425     }
426
427   /* determine the number of channels actually used. */
428   of.numchn = 0;
429   memset (remap, -1, 32 * sizeof (UBYTE));
430   for (t = 0; t < of.numpat; t++)
431     {
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 ())
435         return 0;
436     }
437   /* then we can decide the module type */
438   t = mh->tracker >> 12;
439   if ((!t) || (t > 3))
440     t = NUMTRACKERS - 1;        /* unknown tracker */
441   else
442     {
443       if (mh->tracker >= 0x3217)
444         t = NUMTRACKERS + 1;    /* IT 2.14p4 */
445       else if (mh->tracker >= 0x3216)
446         t = NUMTRACKERS;        /* IT 2.14p3 */
447       else
448         t--;
449     }
450   of.modtype = strdup (S3M_Version[t]);
451   if (t < NUMTRACKERS)
452     {
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';
456     }
457
458   /* build the remap array  */
459   for (t = 0; t < 32; t++)
460     if (!remap[t])
461       remap[t] = of.numchn++;
462
463   /* set panning positions after building remap chart! */
464   for (t = 0; t < 32; t++)
465     if ((mh->channels[t] < 32) && (remap[t] != -1))
466       {
467         if (mh->channels[t] < 8)
468           of.panning[remap[t]] = 0x20;  /* 0x30 = std s3m val */
469         else
470           of.panning[remap[t]] = 0xd0;  /* 0xc0 = std s3m val */
471       }
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;
477
478   /* load pattern info */
479   of.numtrk = of.numpat * of.numchn;
480   if (!AllocTracks ())
481     return 0;
482   if (!AllocPatterns ())
483     return 0;
484
485   for (t = 0; t < of.numpat; t++)
486     {
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 ())
490         return 0;
491       for (u = 0; u < of.numchn; u++)
492         if (!(of.tracks[track++] = S3M_ConvertTrack (&s3mbuf[u * 64])))
493           return 0;
494     }
495
496   return 1;
497 }
498
499 CHAR *
500 S3M_LoadTitle (void)
501 {
502   CHAR s[28];
503
504   _mm_fseek (modreader, 0, SEEK_SET);
505   if (!_mm_read_UBYTES (s, 28, modreader))
506     return NULL;
507
508   return (DupStr (s, 28, 0));
509 }
510
511 /*========== Loader information */
512
513 MLOADER load_s3m =
514 {
515   NULL,
516   "S3M",
517   "S3M (Scream Tracker 3)",
518   S3M_Init,
519   S3M_Test,
520   S3M_Load,
521   S3M_Cleanup,
522   S3M_LoadTitle
523 };
524
525 /* ex:set ts=4: */