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 2 (STM) 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 /* sample information */
52 typedef struct STMSAMPLE {
53 CHAR filename[12];
54 UBYTE unused; /* 0x00 */
55 UBYTE instdisk; /* Instrument disk */
56 UWORD reserved;
57 UWORD length; /* Sample length */
58 UWORD loopbeg; /* Loop start point */
59 UWORD loopend; /* Loop end point */
60 UBYTE volume; /* Volume */
61 UBYTE reserved2;
62 UWORD c2spd; /* Good old c2spd */
63 ULONG reserved3;
64 UWORD isa;
65 } STMSAMPLE;
66
67 /* header */
68 typedef struct STMHEADER {
69 CHAR songname[20];
70 CHAR trackername[8]; /* !Scream! for ST 2.xx */
71 UBYTE unused; /* 0x1A */
72 UBYTE filetype; /* 1=song, 2=module */
73 UBYTE ver_major;
74 UBYTE ver_minor;
75 UBYTE inittempo; /* initspeed= stm inittempo>>4 */
76 UBYTE numpat; /* number of patterns */
77 UBYTE globalvol;
78 UBYTE reserved[13];
79 STMSAMPLE sample[31]; /* STM sample data */
80 UBYTE patorder[128]; /* Docs say 64 - actually 128 */
81 } STMHEADER;
82
83 typedef struct STMNOTE {
84 UBYTE note,insvol,volcmd,cmdinf;
85 } STMNOTE;
86
87 /*========== Loader variables */
88
89 static STMNOTE *stmbuf = NULL;
90 static STMHEADER *mh = NULL;
91
92 /* tracker identifiers */
93 static const CHAR * STM_Version[STM_NTRACKERS] = {
94 "Screamtracker 2",
95 "Converted by MOD2STM (STM format)",
96 "Wuzamod (STM format)"
97 };
98
99 /*========== Loader code */
100
STM_Test(void)101 static BOOL STM_Test(void)
102 {
103 UBYTE str[44];
104 int t;
105
106 _mm_fseek(modreader,20,SEEK_SET);
107 _mm_read_UBYTES(str,44,modreader);
108 if(str[9]!=2) return 0; /* STM Module = filetype 2 */
109
110 /* Prevent false positives for S3M files */
111 if(!memcmp(str+40,"SCRM",4))
112 return 0;
113
114 for (t=0;t<STM_NTRACKERS;t++)
115 if(!memcmp(str,STM_Signatures[t],8))
116 return 1;
117
118 return 0;
119 }
120
STM_Init(void)121 static BOOL STM_Init(void)
122 {
123 if(!(mh=(STMHEADER*)MikMod_malloc(sizeof(STMHEADER)))) return 0;
124 if(!(stmbuf=(STMNOTE*)MikMod_calloc(64U*4,sizeof(STMNOTE)))) return 0;
125
126 return 1;
127 }
128
STM_Cleanup(void)129 static void STM_Cleanup(void)
130 {
131 MikMod_free(mh);
132 MikMod_free(stmbuf);
133 mh=NULL;
134 stmbuf=NULL;
135 }
136
STM_ConvertNote(STMNOTE * n)137 static void STM_ConvertNote(STMNOTE *n)
138 {
139 UBYTE note,ins,vol,cmd,inf;
140
141 /* extract the various information from the 4 bytes that make up a note */
142 note = n->note;
143 ins = n->insvol>>3;
144 vol = (n->insvol&7)+((n->volcmd&0x70)>>1);
145 cmd = n->volcmd&15;
146 inf = n->cmdinf;
147
148 if((ins)&&(ins<32)) UniInstrument(ins-1);
149
150 /* special values of [SBYTE0] are handled here
151 we have no idea if these strange values will ever be encountered.
152 but it appears as those stms sound correct. */
153 if((note==254)||(note==252)) {
154 UniPTEffect(0xc,0); /* note cut */
155 n->volcmd|=0x80;
156 } else
157 /* if note < 251, then all three bytes are stored in the file */
158 if(note<251) UniNote((((note>>4)+2)*OCTAVE)+(note&0xf));
159
160 if((!(n->volcmd&0x80))&&(vol<65)) UniPTEffect(0xc,vol);
161 if(cmd!=255)
162 switch(cmd) {
163 case 1: /* Axx set speed to xx */
164 UniPTEffect(0xf,inf>>4);
165 break;
166 case 2: /* Bxx position jump */
167 UniPTEffect(0xb,inf);
168 break;
169 case 3: /* Cxx patternbreak to row xx */
170 UniPTEffect(0xd,(((inf&0xf0)>>4)*10)+(inf&0xf));
171 break;
172 case 4: /* Dxy volumeslide */
173 UniEffect(UNI_S3MEFFECTD,inf);
174 break;
175 case 5: /* Exy toneslide down */
176 UniEffect(UNI_S3MEFFECTE,inf);
177 break;
178 case 6: /* Fxy toneslide up */
179 UniEffect(UNI_S3MEFFECTF,inf);
180 break;
181 case 7: /* Gxx Tone portamento,speed xx */
182 UniPTEffect(0x3,inf);
183 break;
184 case 8: /* Hxy vibrato */
185 UniPTEffect(0x4,inf);
186 break;
187 case 9: /* Ixy tremor, ontime x, offtime y */
188 UniEffect(UNI_S3MEFFECTI,inf);
189 break;
190 case 0: /* protracker arpeggio */
191 if(!inf) break;
192 /* fall through */
193 case 0xa: /* Jxy arpeggio */
194 UniPTEffect(0x0,inf);
195 break;
196 case 0xb: /* Kxy Dual command H00 & Dxy */
197 UniPTEffect(0x4,0);
198 UniEffect(UNI_S3MEFFECTD,inf);
199 break;
200 case 0xc: /* Lxy Dual command G00 & Dxy */
201 UniPTEffect(0x3,0);
202 UniEffect(UNI_S3MEFFECTD,inf);
203 break;
204 /* Support all these above, since ST2 can LOAD these values but can
205 actually only play up to J - and J is only half-way implemented
206 in ST2 */
207 case 0x18: /* Xxx amiga panning command 8xx */
208 UniPTEffect(0x8,inf);
209 of.flags |= UF_PANNING;
210 break;
211 }
212 }
213
STM_ConvertTrack(STMNOTE * n)214 static UBYTE *STM_ConvertTrack(STMNOTE *n)
215 {
216 int t;
217
218 UniReset();
219 for(t=0;t<64;t++) {
220 STM_ConvertNote(n);
221 UniNewline();
222 n+=of.numchn;
223 }
224 return UniDup();
225 }
226
STM_LoadPatterns(void)227 static BOOL STM_LoadPatterns(void)
228 {
229 int t,s,tracks=0;
230
231 if(!AllocPatterns()) return 0;
232 if(!AllocTracks()) return 0;
233
234 /* Allocate temporary buffer for loading and converting the patterns */
235 for(t=0;t<of.numpat;t++) {
236 for(s=0;s<(64U*of.numchn);s++) {
237 stmbuf[s].note = _mm_read_UBYTE(modreader);
238 stmbuf[s].insvol = _mm_read_UBYTE(modreader);
239 stmbuf[s].volcmd = _mm_read_UBYTE(modreader);
240 stmbuf[s].cmdinf = _mm_read_UBYTE(modreader);
241 }
242
243 if(_mm_eof(modreader)) {
244 _mm_errno = MMERR_LOADING_PATTERN;
245 return 0;
246 }
247
248 for(s=0;s<of.numchn;s++)
249 if(!(of.tracks[tracks++]=STM_ConvertTrack(stmbuf+s))) return 0;
250 }
251 return 1;
252 }
253
STM_Load(BOOL curious)254 static BOOL STM_Load(BOOL curious)
255 {
256 int t;
257 ULONG MikMod_ISA; /* We must generate our own ISA, it's not stored in stm */
258 SAMPLE *q;
259
260 /* try to read stm header */
261 _mm_read_string(mh->songname,20,modreader);
262 _mm_read_string(mh->trackername,8,modreader);
263 mh->unused =_mm_read_UBYTE(modreader);
264 mh->filetype =_mm_read_UBYTE(modreader);
265 mh->ver_major =_mm_read_UBYTE(modreader);
266 mh->ver_minor =_mm_read_UBYTE(modreader);
267 mh->inittempo =_mm_read_UBYTE(modreader);
268 if(!mh->inittempo) {
269 _mm_errno=MMERR_NOT_A_MODULE;
270 return 0;
271 }
272 mh->numpat =_mm_read_UBYTE(modreader);
273 mh->globalvol =_mm_read_UBYTE(modreader);
274 _mm_read_UBYTES(mh->reserved,13,modreader);
275 if(mh->numpat > 128) {
276 _mm_errno = MMERR_NOT_A_MODULE;
277 return 0;
278 }
279
280 for(t=0;t<31;t++) {
281 STMSAMPLE *s=&mh->sample[t]; /* STM sample data */
282
283 _mm_read_string(s->filename,12,modreader);
284 s->unused =_mm_read_UBYTE(modreader);
285 s->instdisk =_mm_read_UBYTE(modreader);
286 s->reserved =_mm_read_I_UWORD(modreader);
287 s->length =_mm_read_I_UWORD(modreader);
288 s->loopbeg =_mm_read_I_UWORD(modreader);
289 s->loopend =_mm_read_I_UWORD(modreader);
290 s->volume =_mm_read_UBYTE(modreader);
291 s->reserved2=_mm_read_UBYTE(modreader);
292 s->c2spd =_mm_read_I_UWORD(modreader);
293 s->reserved3=_mm_read_I_ULONG(modreader);
294 s->isa =_mm_read_I_UWORD(modreader);
295 }
296 _mm_read_UBYTES(mh->patorder,128,modreader);
297
298 if(_mm_eof(modreader)) {
299 _mm_errno = MMERR_LOADING_HEADER;
300 return 0;
301 }
302
303 /* set module variables */
304 for(t=0;t<STM_NTRACKERS;t++)
305 if(!memcmp(mh->trackername,STM_Signatures[t],8)) break;
306 of.modtype = MikMod_strdup(STM_Version[t]);
307 of.songname = DupStr(mh->songname,20,1); /* make a cstr of songname */
308 of.numpat = mh->numpat;
309 of.inittempo = 125; /* mh->inittempo+0x1c; */
310 of.initspeed = mh->inittempo>>4;
311 of.numchn = 4; /* get number of channels */
312 of.reppos = 0;
313 of.flags |= UF_S3MSLIDES;
314 of.bpmlimit = 32;
315
316 t=0;
317 if(!AllocPositions(0x80)) return 0;
318 /* 99 terminates the patorder list */
319 while((mh->patorder[t]<=99)&&(mh->patorder[t]<mh->numpat)) {
320 of.positions[t]=mh->patorder[t];
321 if(++t == 0x80) {
322 _mm_errno = MMERR_NOT_A_MODULE;
323 return 0;
324 }
325 }
326 if(mh->patorder[t]<=99) t++;
327 of.numpos=t;
328 of.numtrk=of.numpat*of.numchn;
329 of.numins=of.numsmp=31;
330
331 if(!AllocSamples()) return 0;
332 if(!STM_LoadPatterns()) return 0;
333 MikMod_ISA=_mm_ftell(modreader);
334 MikMod_ISA=(MikMod_ISA+15)&0xfffffff0; /* normalize */
335
336 for(q=of.samples,t=0;t<of.numsmp;t++,q++) {
337 /* load sample info */
338 q->samplename = DupStr(mh->sample[t].filename,12,1);
339 q->speed = (mh->sample[t].c2spd * 8363) / 8448;
340 q->volume = mh->sample[t].volume;
341 q->length = mh->sample[t].length;
342 if (/*!mh->sample[t].volume || */q->length==1) q->length=0;
343 q->loopstart = mh->sample[t].loopbeg;
344 q->loopend = mh->sample[t].loopend;
345 q->seekpos = MikMod_ISA;
346
347 MikMod_ISA+=q->length;
348 MikMod_ISA=(MikMod_ISA+15)&0xfffffff0; /* normalize */
349
350 /* contrary to the STM specs, sample data is signed */
351 q->flags = SF_SIGNED;
352
353 if(q->loopend && q->loopend != 0xffff)
354 q->flags|=SF_LOOP;
355 }
356 return 1;
357 }
358
STM_LoadTitle(void)359 static CHAR *STM_LoadTitle(void)
360 {
361 CHAR s[20];
362
363 _mm_fseek(modreader,0,SEEK_SET);
364 if(!_mm_read_UBYTES(s,20,modreader)) return NULL;
365
366 return(DupStr(s,20,1));
367 }
368
369 /*========== Loader information */
370
371 MIKMODAPI MLOADER load_stm={
372 NULL,
373 "STM",
374 "STM (Scream Tracker)",
375 STM_Init,
376 STM_Test,
377 STM_Load,
378 STM_Cleanup,
379 STM_LoadTitle
380 };
381
382 /* ex:set ts=4: */
383