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 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 int numeric[NUMTRACKERS]={14,14,16,16};
117 
118 /*========== Loader code */
119 
S3M_Test(void)120 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 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 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 }
148 
149 /* Because so many s3m files have 16 channels as the set number used, but really
150    only use far less (usually 8 to 12 still), I had to make this function, which
151    determines the number of channels that are actually USED by a pattern.
152 
153    For every channel that's used, it sets the appropriate array entry of the
154    global variable 'remap'
155 
156    NOTE: You must first seek to the file location of the pattern before calling
157          this procedure.
158 
159    Returns 1 on fail.                                                         */
S3M_GetNumChannels(void)160 static BOOL S3M_GetNumChannels(void)
161 {
162 	int row=0,flag,ch;
163 
164 	while(row<64) {
165 		flag=_mm_read_UBYTE(modreader);
166 
167 		if(_mm_eof(modreader)) {
168 			_mm_errno = MMERR_LOADING_PATTERN;
169 			return 1;
170 		}
171 
172 		if(flag) {
173 			ch=flag&31;
174 			if(mh->channels[ch]<32) remap[ch] = 0;
175 			if(flag&32) {_mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader);}
176 			if(flag&64) _mm_read_UBYTE(modreader);
177 			if(flag&128){_mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader);}
178 		} else row++;
179 	}
180 	return 0;
181 }
182 
S3M_ReadPattern(void)183 static BOOL S3M_ReadPattern(void)
184 {
185 	int row=0,flag,ch;
186 	S3MNOTE *n,dummy;
187 
188 	/* clear pattern data */
189 	memset(s3mbuf,255,32*64*sizeof(S3MNOTE));
190 
191 	while(row<64) {
192 		flag=_mm_read_UBYTE(modreader);
193 
194 		if(_mm_eof(modreader)) {
195 			_mm_errno = MMERR_LOADING_PATTERN;
196 			return 0;
197 		}
198 
199 		if(flag) {
200 			ch=remap[flag&31];
201 
202 			if(ch!=-1)
203 				n=&s3mbuf[(64U*ch)+row];
204 			else
205 				n=&dummy;
206 
207 			if(flag&32) {
208 				n->note=_mm_read_UBYTE(modreader);
209 				n->ins=_mm_read_UBYTE(modreader);
210 			}
211 			if(flag&64) {
212 				n->vol=_mm_read_UBYTE(modreader);
213 				if (n->vol>64) n->vol=64;
214 			}
215 			if(flag&128) {
216 				n->cmd=_mm_read_UBYTE(modreader);
217 				n->inf=_mm_read_UBYTE(modreader);
218 			}
219 		} else row++;
220 	}
221 	return 1;
222 }
223 
S3M_ConvertTrack(S3MNOTE * tr)224 static UBYTE* S3M_ConvertTrack(S3MNOTE* tr)
225 {
226 	int t;
227 
228 	UniReset();
229 	for(t=0;t<64;t++) {
230 		UBYTE note,ins,vol;
231 
232 		note=tr[t].note;
233 		ins=tr[t].ins;
234 		vol=tr[t].vol;
235 
236 		if((ins)&&(ins!=255)) UniInstrument(ins-1);
237 		if(note!=255) {
238 			if(note==254) {
239 				UniPTEffect(0xc,0);	/* note cut command */
240 				vol=255;
241 			} else
242 				UniNote(((note>>4)*OCTAVE)+(note&0xf));	/* normal note */
243 		}
244 		if(vol<255) UniPTEffect(0xc,vol);
245 
246 		S3MIT_ProcessCmd(tr[t].cmd,tr[t].inf,
247 			tracker == 1 ? S3MIT_OLDSTYLE | S3MIT_SCREAM : S3MIT_OLDSTYLE);
248 		UniNewline();
249 	}
250 	return UniDup();
251 }
252 
S3M_Load(BOOL curious)253 BOOL S3M_Load(BOOL curious)
254 {
255 	int t,u,track = 0;
256 	SAMPLE *q;
257 	UBYTE pan[32];
258 
259 	/* try to read module header */
260 	_mm_read_string(mh->songname,28,modreader);
261 	mh->t1a         =_mm_read_UBYTE(modreader);
262 	mh->type        =_mm_read_UBYTE(modreader);
263 	_mm_read_UBYTES(mh->unused1,2,modreader);
264 	mh->ordnum      =_mm_read_I_UWORD(modreader);
265 	mh->insnum      =_mm_read_I_UWORD(modreader);
266 	mh->patnum      =_mm_read_I_UWORD(modreader);
267 	mh->flags       =_mm_read_I_UWORD(modreader);
268 	mh->tracker     =_mm_read_I_UWORD(modreader);
269 	mh->fileformat  =_mm_read_I_UWORD(modreader);
270 	_mm_read_string(mh->scrm,4,modreader);
271 	mh->mastervol   =_mm_read_UBYTE(modreader);
272 	mh->initspeed   =_mm_read_UBYTE(modreader);
273 	mh->inittempo   =_mm_read_UBYTE(modreader);
274 	mh->mastermult  =_mm_read_UBYTE(modreader);
275 	mh->ultraclick  =_mm_read_UBYTE(modreader);
276 	mh->pantable    =_mm_read_UBYTE(modreader);
277 	_mm_read_UBYTES(mh->unused2,8,modreader);
278 	mh->special     =_mm_read_I_UWORD(modreader);
279 	_mm_read_UBYTES(mh->channels,32,modreader);
280 
281 	if(_mm_eof(modreader)) {
282 		_mm_errno = MMERR_LOADING_HEADER;
283 		return 0;
284 	}
285 
286 	/* then we can decide the module type */
287 	tracker=mh->tracker>>12;
288 	if((!tracker)||(tracker>=NUMTRACKERS))
289 		tracker=NUMTRACKERS-1; /* unknown tracker */
290 	else {
291 		if(mh->tracker>=0x3217)
292 			tracker=NUMTRACKERS+1; /* IT 2.14p4 */
293 		else if(mh->tracker>=0x3216)
294 			tracker=NUMTRACKERS; /* IT 2.14p3 */
295 		else tracker--;
296 	}
297 	of.modtype = strdup(S3M_Version[tracker]);
298 	if(tracker<NUMTRACKERS) {
299 		of.modtype[numeric[tracker]] = ((mh->tracker>>8) &0xf)+'0';
300 		of.modtype[numeric[tracker]+2] = ((mh->tracker>>4)&0xf)+'0';
301 		of.modtype[numeric[tracker]+3] = ((mh->tracker)&0xf)+'0';
302 	}
303 	/* set module variables */
304 	of.songname    = DupStr(mh->songname,28,0);
305 	of.numpat      = mh->patnum;
306 	of.reppos      = 0;
307 	of.numins      = of.numsmp = mh->insnum;
308 	of.initspeed   = mh->initspeed;
309 	of.inittempo   = mh->inittempo;
310 	of.initvolume  = mh->mastervol<<1;
311 	of.flags      |= UF_ARPMEM | UF_PANNING;
312 	if((mh->tracker==0x1300)||(mh->flags&64))
313 		of.flags|=UF_S3MSLIDES;
314 	of.bpmlimit    = 32;
315 
316 	/* read the order data */
317 	if(!AllocPositions(mh->ordnum)) return 0;
318 	if(!(origpositions=MikMod_calloc(mh->ordnum,sizeof(UWORD)))) return 0;
319 
320 	for(t=0;t<mh->ordnum;t++) {
321 		origpositions[t]=_mm_read_UBYTE(modreader);
322 		if((origpositions[t]>=mh->patnum)&&(origpositions[t]<254))
323 			origpositions[t]=255/*mh->patnum-1*/;
324 	}
325 
326 	if(_mm_eof(modreader)) {
327 		_mm_errno = MMERR_LOADING_HEADER;
328 		return 0;
329 	}
330 
331 	poslookupcnt=mh->ordnum;
332 	S3MIT_CreateOrders(curious);
333 
334 	if(!(paraptr=(UWORD*)MikMod_malloc((of.numins+of.numpat)*sizeof(UWORD))))
335 		return 0;
336 
337 	/* read the instrument+pattern parapointers */
338 	_mm_read_I_UWORDS(paraptr,of.numins+of.numpat,modreader);
339 
340 	if(mh->pantable==252) {
341 		/* read the panning table (ST 3.2 addition.  See below for further
342 		   portions of channel panning [past reampper]). */
343 		_mm_read_UBYTES(pan,32,modreader);
344 	}
345 
346 	if(_mm_eof(modreader)) {
347 		_mm_errno = MMERR_LOADING_HEADER;
348 		return 0;
349 	}
350 
351 	/* load samples */
352 	if(!AllocSamples()) return 0;
353 	q = of.samples;
354 	for(t=0;t<of.numins;t++) {
355 		S3MSAMPLE s;
356 
357 		/* seek to instrument position */
358 		_mm_fseek(modreader,((long)paraptr[t])<<4,SEEK_SET);
359 		/* and load sample info */
360 		s.type      =_mm_read_UBYTE(modreader);
361 		_mm_read_string(s.filename,12,modreader);
362 		s.memsegh   =_mm_read_UBYTE(modreader);
363 		s.memsegl   =_mm_read_I_UWORD(modreader);
364 		s.length    =_mm_read_I_ULONG(modreader);
365 		s.loopbeg   =_mm_read_I_ULONG(modreader);
366 		s.loopend   =_mm_read_I_ULONG(modreader);
367 		s.volume    =_mm_read_UBYTE(modreader);
368 		s.dsk       =_mm_read_UBYTE(modreader);
369 		s.pack      =_mm_read_UBYTE(modreader);
370 		s.flags     =_mm_read_UBYTE(modreader);
371 		s.c2spd     =_mm_read_I_ULONG(modreader);
372 		_mm_read_UBYTES(s.unused,12,modreader);
373 		_mm_read_string(s.sampname,28,modreader);
374 		_mm_read_string(s.scrs,4,modreader);
375 
376 		/* ScreamTracker imposes a 64000 bytes (not 64k !) limit */
377 		if (s.length > 64000)
378 			s.length = 64000;
379 
380 		if(_mm_eof(modreader)) {
381 			_mm_errno = MMERR_LOADING_SAMPLEINFO;
382 			return 0;
383 		}
384 
385 		q->samplename = DupStr(s.sampname,28,0);
386 		q->speed      = s.c2spd;
387 		q->length     = s.length;
388 		q->loopstart  = s.loopbeg;
389 		q->loopend    = s.loopend;
390 		q->volume     = s.volume;
391 		q->seekpos    = (((long)s.memsegh)<<16|s.memsegl)<<4;
392 
393 		if(s.flags&1) q->flags |= SF_LOOP;
394 		if(s.flags&4) q->flags |= SF_16BITS;
395 		if(mh->fileformat==1) q->flags |= SF_SIGNED;
396 
397 		/* don't load sample if it doesn't have the SCRS tag */
398 		if(memcmp(s.scrs,"SCRS",4)) q->length = 0;
399 
400 		q++;
401 	}
402 
403 	/* determine the number of channels actually used. */
404 	of.numchn = 0;
405 	memset(remap,-1,32*sizeof(UBYTE));
406 	for(t=0;t<of.numpat;t++) {
407 		/* seek to pattern position (+2 skip pattern length) */
408 		_mm_fseek(modreader,(long)((paraptr[of.numins+t])<<4)+2,SEEK_SET);
409 		if(S3M_GetNumChannels()) return 0;
410 	}
411 
412 	/* build the remap array  */
413 	for(t=0;t<32;t++)
414 		if(!remap[t])
415 			remap[t]=of.numchn++;
416 
417 	/* set panning positions after building remap chart! */
418 	for(t=0;t<32;t++)
419 		if((mh->channels[t]<32)&&(remap[t]!=-1)) {
420 			if(mh->channels[t]<8)
421 				of.panning[remap[t]]=0x30;
422 			else
423 				of.panning[remap[t]]=0xc0;
424 		}
425 	if(mh->pantable==252)
426 		/* set panning positions according to panning table (new for st3.2) */
427 		for(t=0;t<32;t++)
428 			if((pan[t]&0x20)&&(mh->channels[t]<32)&&(remap[t]!=-1))
429 				of.panning[remap[t]]=(pan[t]&0xf)<<4;
430 
431 	/* load pattern info */
432 	of.numtrk=of.numpat*of.numchn;
433 	if(!AllocTracks()) return 0;
434 	if(!AllocPatterns()) return 0;
435 
436 	for(t=0;t<of.numpat;t++) {
437 		/* seek to pattern position (+2 skip pattern length) */
438 		_mm_fseek(modreader,(((long)paraptr[of.numins+t])<<4)+2,SEEK_SET);
439 		if(!S3M_ReadPattern()) return 0;
440 		for(u=0;u<of.numchn;u++)
441 			if(!(of.tracks[track++]=S3M_ConvertTrack(&s3mbuf[u*64]))) return 0;
442 	}
443 
444 	return 1;
445 }
446 
S3M_LoadTitle(void)447 CHAR *S3M_LoadTitle(void)
448 {
449 	CHAR s[28];
450 
451 	_mm_fseek(modreader,0,SEEK_SET);
452 	if(!_mm_read_UBYTES(s,28,modreader)) return NULL;
453 
454 	return(DupStr(s,28,0));
455 }
456 
457 /*========== Loader information */
458 
459 MIKMODAPI MLOADER load_s3m={
460 	NULL,
461 	"S3M",
462 	"S3M (Scream Tracker 3)",
463 	S3M_Init,
464 	S3M_Test,
465 	S3M_Load,
466 	S3M_Cleanup,
467 	S3M_LoadTitle
468 };
469 
470 /* ex:set ts=4: */
471