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