1 /* MikMod sound library
2 (c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
3 AUTHORS for 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 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36
37 #include <stdio.h>
38 #ifdef HAVE_MEMORY_H
39 #include <memory.h>
40 #endif
41 #include <string.h>
42
43 #include "mikmod_internals.h"
44
45 #ifdef SUNOS
46 extern int fprintf(FILE *, const char *, ...);
47 #endif
48
49 /*========== Module structure */
50
51 /* header */
52 typedef struct S3MHEADER {
53 CHAR songname[28];
54 UBYTE t1a;
55 UBYTE type;
56 UBYTE unused1[2];
57 UWORD ordnum;
58 UWORD insnum;
59 UWORD patnum;
60 UWORD flags;
61 UWORD tracker;
62 UWORD fileformat;
63 CHAR scrm[4];
64 UBYTE mastervol;
65 UBYTE initspeed;
66 UBYTE inittempo;
67 UBYTE mastermult;
68 UBYTE ultraclick;
69 UBYTE pantable;
70 UBYTE unused2[8];
71 UWORD special;
72 UBYTE channels[32];
73 } S3MHEADER;
74
75 /* sample information */
76 typedef struct S3MSAMPLE {
77 UBYTE type;
78 CHAR filename[12];
79 UBYTE memsegh;
80 UWORD memsegl;
81 ULONG length;
82 ULONG loopbeg;
83 ULONG loopend;
84 UBYTE volume;
85 UBYTE dsk;
86 UBYTE pack;
87 UBYTE flags;
88 ULONG c2spd;
89 UBYTE unused[12];
90 CHAR sampname[28];
91 CHAR scrs[4];
92 } S3MSAMPLE;
93
94 typedef struct S3MNOTE {
95 UBYTE note,ins,vol,cmd,inf;
96 } S3MNOTE;
97
98 /*========== Loader variables */
99
100 static S3MNOTE *s3mbuf = NULL; /* pointer to a complete S3M pattern */
101 static S3MHEADER *mh = NULL;
102 static UWORD *paraptr = NULL; /* parapointer array (see S3M docs) */
103 static unsigned int tracker; /* tracker id */
104
105 /* tracker identifiers */
106 #define NUMTRACKERS 4
107 static const CHAR * S3M_Version[] = {
108 "Screamtracker x.xx",
109 "Imago Orpheus x.xx (S3M format)",
110 "Impulse Tracker x.xx (S3M format)",
111 "Unknown tracker x.xx (S3M format)",
112 "Impulse Tracker 2.14p3 (S3M format)",
113 "Impulse Tracker 2.14p4 (S3M format)"
114 };
115 /* version number position in above array */
116 static const int numeric[NUMTRACKERS]={14,14,16,16};
117
118 /*========== Loader code */
119
S3M_Test(void)120 static BOOL S3M_Test(void)
121 {
122 UBYTE id[4];
123
124 _mm_fseek(modreader,0x2c,SEEK_SET);
125 if(!_mm_read_UBYTES(id,4,modreader)) return 0;
126 if(!memcmp(id,"SCRM",4)) return 1;
127 return 0;
128 }
129
S3M_Init(void)130 static BOOL S3M_Init(void)
131 {
132 if(!(s3mbuf=(S3MNOTE*)MikMod_malloc(32*64*sizeof(S3MNOTE)))) return 0;
133 if(!(mh=(S3MHEADER*)MikMod_malloc(sizeof(S3MHEADER)))) return 0;
134 if(!(poslookup=(UBYTE*)MikMod_malloc(sizeof(UBYTE)*256))) return 0;
135 memset(poslookup,-1,256);
136
137 return 1;
138 }
139
S3M_Cleanup(void)140 static void S3M_Cleanup(void)
141 {
142 MikMod_free(s3mbuf);
143 MikMod_free(paraptr);
144 MikMod_free(poslookup);
145 MikMod_free(mh);
146 MikMod_free(origpositions);
147 s3mbuf=NULL;
148 paraptr=NULL;
149 poslookup=NULL;
150 mh=NULL;
151 origpositions=NULL;
152 }
153
154 /* Because so many s3m files have 16 channels as the set number used, but really
155 only use far less (usually 8 to 12 still), I had to make this function, which
156 determines the number of channels that are actually USED by a pattern.
157
158 For every channel that's used, it sets the appropriate array entry of the
159 global variable 'remap'
160
161 NOTE: You must first seek to the file location of the pattern before calling
162 this procedure.
163
164 Returns 0 on fail. */
S3M_GetNumChannels(void)165 static BOOL S3M_GetNumChannels(void)
166 {
167 int row=0,flag,ch;
168
169 while(row<64) {
170 flag=_mm_read_UBYTE(modreader);
171
172 if(_mm_eof(modreader)) {
173 _mm_errno = MMERR_LOADING_PATTERN;
174 return 0;
175 }
176
177 if(flag) {
178 ch=flag&31;
179 if(mh->channels[ch]<32) remap[ch] = 0;
180 if(flag&32) {_mm_skip_BYTE(modreader);_mm_skip_BYTE(modreader);}
181 if(flag&64) _mm_skip_BYTE(modreader);
182 if(flag&128){_mm_skip_BYTE(modreader);_mm_skip_BYTE(modreader);}
183 } else row++;
184 }
185 return 1;
186 }
187
S3M_ReadPattern(void)188 static BOOL S3M_ReadPattern(void)
189 {
190 int row=0,flag,ch;
191 S3MNOTE *n,dummy;
192
193 /* clear pattern data */
194 memset(s3mbuf,255,32*64*sizeof(S3MNOTE));
195
196 while(row<64) {
197 flag=_mm_read_UBYTE(modreader);
198
199 if(_mm_eof(modreader)) {
200 _mm_errno = MMERR_LOADING_PATTERN;
201 return 0;
202 }
203
204 if(flag) {
205 ch=remap[flag&31];
206
207 if(ch!=-1)
208 n=&s3mbuf[(64U*ch)+row];
209 else
210 n=&dummy;
211
212 if(flag&32) {
213 n->note=_mm_read_UBYTE(modreader);
214 n->ins=_mm_read_UBYTE(modreader);
215 }
216 if(flag&64) {
217 n->vol=_mm_read_UBYTE(modreader);
218 if (n->vol>64) n->vol=64;
219 }
220 if(flag&128) {
221 n->cmd=_mm_read_UBYTE(modreader);
222 n->inf=_mm_read_UBYTE(modreader);
223 }
224 } else row++;
225 }
226 return 1;
227 }
228
S3M_ConvertTrack(S3MNOTE * tr)229 static UBYTE* S3M_ConvertTrack(S3MNOTE* tr)
230 {
231 int t;
232
233 UniReset();
234 for(t=0;t<64;t++) {
235 UBYTE note,ins,vol;
236
237 note=tr[t].note;
238 ins=tr[t].ins;
239 vol=tr[t].vol;
240
241 if((ins)&&(ins!=255)) UniInstrument(ins-1);
242 if(note!=255) {
243 if(note==254) {
244 UniPTEffect(0xc,0); /* note cut command */
245 vol=255;
246 } else
247 UniNote(((note>>4)*OCTAVE)+(note&0xf)); /* normal note */
248 }
249 if(vol<255) UniPTEffect(0xc,vol);
250
251 S3MIT_ProcessCmd(tr[t].cmd,tr[t].inf,
252 tracker == 1 ? S3MIT_OLDSTYLE | S3MIT_SCREAM : S3MIT_OLDSTYLE);
253 UniNewline();
254 }
255 return UniDup();
256 }
257
S3M_Load(BOOL curious)258 static BOOL S3M_Load(BOOL curious)
259 {
260 int t,u,track = 0;
261 SAMPLE *q;
262 UBYTE pan[32];
263
264 /* try to read module header */
265 _mm_read_string(mh->songname,28,modreader);
266 mh->t1a =_mm_read_UBYTE(modreader);
267 mh->type =_mm_read_UBYTE(modreader);
268 _mm_read_UBYTES(mh->unused1,2,modreader);
269 mh->ordnum =_mm_read_I_UWORD(modreader);
270 mh->insnum =_mm_read_I_UWORD(modreader);
271 mh->patnum =_mm_read_I_UWORD(modreader);
272 mh->flags =_mm_read_I_UWORD(modreader);
273 mh->tracker =_mm_read_I_UWORD(modreader);
274 mh->fileformat =_mm_read_I_UWORD(modreader);
275 _mm_read_string(mh->scrm,4,modreader);
276 mh->mastervol =_mm_read_UBYTE(modreader);
277 mh->initspeed =_mm_read_UBYTE(modreader);
278 mh->inittempo =_mm_read_UBYTE(modreader);
279 mh->mastermult =_mm_read_UBYTE(modreader);
280 mh->ultraclick =_mm_read_UBYTE(modreader);
281 mh->pantable =_mm_read_UBYTE(modreader);
282 _mm_read_UBYTES(mh->unused2,8,modreader);
283 mh->special =_mm_read_I_UWORD(modreader);
284 _mm_read_UBYTES(mh->channels,32,modreader);
285
286 if(_mm_eof(modreader)) {
287 _mm_errno = MMERR_LOADING_HEADER;
288 return 0;
289 }
290 if(mh->ordnum > 255 || mh->insnum > 255 || mh->patnum > 255) {
291 _mm_errno = MMERR_NOT_A_MODULE;
292 return 0;
293 }
294
295 /* then we can decide the module type */
296 tracker=mh->tracker>>12;
297 if((!tracker)||(tracker>=NUMTRACKERS))
298 tracker=NUMTRACKERS-1; /* unknown tracker */
299 else {
300 if(mh->tracker>=0x3217)
301 tracker=NUMTRACKERS+1; /* IT 2.14p4 */
302 else if(mh->tracker>=0x3216)
303 tracker=NUMTRACKERS; /* IT 2.14p3 */
304 else tracker--;
305 }
306 of.modtype = MikMod_strdup(S3M_Version[tracker]);
307 if(tracker<NUMTRACKERS) {
308 of.modtype[numeric[tracker]] = ((mh->tracker>>8) &0xf)+'0';
309 of.modtype[numeric[tracker]+2] = ((mh->tracker>>4)&0xf)+'0';
310 of.modtype[numeric[tracker]+3] = ((mh->tracker)&0xf)+'0';
311 }
312 /* set module variables */
313 of.songname = DupStr(mh->songname,28,0);
314 of.numpat = mh->patnum;
315 of.reppos = 0;
316 of.numins = of.numsmp = mh->insnum;
317 of.initspeed = mh->initspeed;
318 of.inittempo = mh->inittempo;
319 of.initvolume = mh->mastervol<<1;
320 of.flags |= UF_ARPMEM | UF_PANNING;
321 if((mh->tracker==0x1300)||(mh->flags&64))
322 of.flags|=UF_S3MSLIDES;
323 of.bpmlimit = 32;
324
325 /* read the order data */
326 if(!AllocPositions(mh->ordnum)) return 0;
327 if(!(origpositions=(UWORD*)MikMod_calloc(mh->ordnum,sizeof(UWORD)))) return 0;
328
329 for(t=0;t<mh->ordnum;t++) {
330 origpositions[t]=_mm_read_UBYTE(modreader);
331 if((origpositions[t]>=mh->patnum)&&(origpositions[t]<254))
332 origpositions[t]=255/*mh->patnum-1*/;
333 }
334
335 if(_mm_eof(modreader)) {
336 _mm_errno = MMERR_LOADING_HEADER;
337 return 0;
338 }
339
340 poslookupcnt=mh->ordnum;
341 S3MIT_CreateOrders(curious);
342
343 if(!(paraptr=(UWORD*)MikMod_malloc((of.numins+of.numpat)*sizeof(UWORD))))
344 return 0;
345
346 /* read the instrument+pattern parapointers */
347 _mm_read_I_UWORDS(paraptr,of.numins+of.numpat,modreader);
348
349 if(mh->pantable==252) {
350 /* read the panning table (ST 3.2 addition. See below for further
351 portions of channel panning [past reampper]). */
352 _mm_read_UBYTES(pan,32,modreader);
353 }
354
355 if(_mm_eof(modreader)) {
356 _mm_errno = MMERR_LOADING_HEADER;
357 return 0;
358 }
359
360 /* load samples */
361 if(!AllocSamples()) return 0;
362 q = of.samples;
363 for(t=0;t<of.numins;t++) {
364 S3MSAMPLE s;
365
366 /* seek to instrument position */
367 _mm_fseek(modreader,((long)paraptr[t])<<4,SEEK_SET);
368 /* and load sample info */
369 s.type =_mm_read_UBYTE(modreader);
370 _mm_read_string(s.filename,12,modreader);
371 s.memsegh =_mm_read_UBYTE(modreader);
372 s.memsegl =_mm_read_I_UWORD(modreader);
373 s.length =_mm_read_I_ULONG(modreader);
374 s.loopbeg =_mm_read_I_ULONG(modreader);
375 s.loopend =_mm_read_I_ULONG(modreader);
376 s.volume =_mm_read_UBYTE(modreader);
377 s.dsk =_mm_read_UBYTE(modreader);
378 s.pack =_mm_read_UBYTE(modreader);
379 s.flags =_mm_read_UBYTE(modreader);
380 s.c2spd =_mm_read_I_ULONG(modreader);
381 _mm_read_UBYTES(s.unused,12,modreader);
382 _mm_read_string(s.sampname,28,modreader);
383 _mm_read_string(s.scrs,4,modreader);
384
385 /* ScreamTracker imposes a 64000 bytes (not 64k !) limit */
386 /* enforce it, if we'll use S3MIT_SCREAM in S3M_ConvertTrack() */
387 if (s.length > 64000 && tracker == 1)
388 s.length = 64000;
389
390 if(_mm_eof(modreader)) {
391 _mm_errno = MMERR_LOADING_SAMPLEINFO;
392 return 0;
393 }
394
395 q->samplename = DupStr(s.sampname,28,0);
396 q->speed = s.c2spd;
397 q->length = s.length;
398 q->loopstart = s.loopbeg;
399 q->loopend = s.loopend;
400 q->volume = s.volume;
401 q->seekpos = (((ULONG)s.memsegh)<<16|s.memsegl)<<4;
402
403 if(s.flags&1) q->flags |= SF_LOOP;
404 if(s.flags&4) q->flags |= SF_16BITS;
405 if(mh->fileformat==1) q->flags |= SF_SIGNED;
406
407 /* don't load sample if it doesn't have the SCRS tag */
408 if(memcmp(s.scrs,"SCRS",4)) q->length = 0;
409
410 q++;
411 }
412
413 /* determine the number of channels actually used. */
414 of.numchn = 0;
415 memset(remap,-1,32*sizeof(UBYTE));
416 for(t=0;t<of.numpat;t++) {
417 /* seek to pattern position (+2 skip pattern length) */
418 _mm_fseek(modreader,(long)((paraptr[of.numins+t])<<4)+2,SEEK_SET);
419 if(!S3M_GetNumChannels()) return 0;
420 }
421
422 /* build the remap array */
423 for(t=0;t<32;t++)
424 if(!remap[t])
425 remap[t]=of.numchn++;
426
427 /* set panning positions after building remap chart! */
428 for(t=0;t<32;t++)
429 if((mh->channels[t]<32)&&(remap[t]!=-1)) {
430 if(mh->channels[t]<8)
431 of.panning[remap[t]]=0x30;
432 else
433 of.panning[remap[t]]=0xc0;
434 }
435 if(mh->pantable==252)
436 /* set panning positions according to panning table (new for st3.2) */
437 for(t=0;t<32;t++)
438 if((pan[t]&0x20)&&(mh->channels[t]<32)&&(remap[t]!=-1))
439 of.panning[remap[t]]=(pan[t]&0xf)<<4;
440
441 /* load pattern info */
442 of.numtrk=of.numpat*of.numchn;
443 if(!AllocTracks()) return 0;
444 if(!AllocPatterns()) return 0;
445
446 for(t=0;t<of.numpat;t++) {
447 /* seek to pattern position (+2 skip pattern length) */
448 _mm_fseek(modreader,(((long)paraptr[of.numins+t])<<4)+2,SEEK_SET);
449 if(!S3M_ReadPattern()) return 0;
450 for(u=0;u<of.numchn;u++)
451 if(!(of.tracks[track++]=S3M_ConvertTrack(&s3mbuf[u*64]))) return 0;
452 }
453
454 return 1;
455 }
456
S3M_LoadTitle(void)457 static CHAR *S3M_LoadTitle(void)
458 {
459 CHAR s[28];
460
461 _mm_fseek(modreader,0,SEEK_SET);
462 if(!_mm_read_UBYTES(s,28,modreader)) return NULL;
463
464 return(DupStr(s,28,0));
465 }
466
467 /*========== Loader information */
468
469 MIKMODAPI MLOADER load_s3m={
470 NULL,
471 "S3M",
472 "S3M (Scream Tracker 3)",
473 S3M_Init,
474 S3M_Test,
475 S3M_Load,
476 S3M_Cleanup,
477 S3M_LoadTitle
478 };
479
480 /* ex:set ts=4: */
481