7 ScreamTracker 2 (STM) module Loader - Version 1.oOo Release 2
8 A Coding Nightmare by Rao and Air Richter of HaRDCoDE
9 You can now play all of those wonderful old C.C. Catch STM's!
12 All systems - all compilers (hopefully)
21 typedef struct STMNOTE{
22 UBYTE note,insvol,volcmd,cmdinf;
26 /* Raw STM sampleinfo struct: */
28 typedef struct STMSAMPLE{
29 char filename[12]; /* Can't have long comments - just filename comments :) */
30 char unused; /* 0x00 */
31 UBYTE instdisk; /* Instrument disk */
32 UWORD reserved; /* ISA in memory when in ST 2 */
33 UWORD length; /* Sample length */
34 UWORD loopbeg; /* Loop start point */
35 UWORD loopend; /* Loop end point */
36 UBYTE volume; /* Volume */
37 UBYTE reserved2; /* More reserved crap */
38 UWORD c2spd; /* Good old c2spd */
39 UBYTE reserved3[4]; /* Yet more of PSi's reserved crap */
40 UWORD isa; /* Internal Segment Address -> */
41 /* contrary to the tech specs, this is NOT actually */
42 /* written to the stm file. */
45 /* Raw STM header struct: */
47 typedef struct STMHEADER{
49 char trackername[8]; /* !SCREAM! for ST 2.xx */
50 char unused; /* 0x1A */
51 char filetype; /* 1=song, 2=module (only 2 is supported, of course) :) */
52 char ver_major; /* Like 2 */
53 char ver_minor; /* "ditto" */
54 UBYTE inittempo; /* initspeed= stm inittempo>>4 */
55 UBYTE numpat; /* number of patterns */
56 UBYTE globalvol; /* <- WoW! a RiGHT TRiANGLE =8*) */
57 UBYTE reserved[13]; /* More of PSi's internal crap */
58 STMSAMPLE sample[31]; /* STM sample data */
59 UBYTE patorder[128]; /* Docs say 64 - actually 128 */
63 static STMNOTE *stmbuf;
66 char STM_Version[]="Screamtracker 2";
74 _mm_fseek(modfp,21,SEEK_SET);
76 fread(&filetype,1,1,modfp);
77 if(!memcmp(str,"!SCREAM!",8) || (filetype!=2)) /* STM Module = filetype 2 */
87 if(!(mh=(STMHEADER *)MyCalloc(1,sizeof(STMHEADER)))) return 0;
91 void STM_Cleanup(void)
93 if(mh!=NULL) free(mh);
94 if(stmbuf!=NULL) free(stmbuf);
99 void STM_ConvertNote(STMNOTE *n)
101 UBYTE note,ins,vol,cmd,inf;
103 /* extract the various information from the 4 bytes that
104 make up a single note */
108 vol=(n->insvol&7)+(n->volcmd>>1);
112 if(ins!=0 && ins<32){
113 UniInstrument(ins-1);
116 /* special values of [SBYTE0] are handled here -> */
117 /* we have no idea if these strange values will ever be encountered */
118 /* but it appears as though stms sound correct. */
119 if(note==254 || note==252) UniPTEffect(0xc,0); /* <- note off command (???) */
121 /* if note < 251, then all three bytes are stored in the file */
122 if(note<251) UniNote((((note>>4)+2)*12)+(note&0xf)); /* <- normal note and up the octave by two */
125 UniPTEffect(0xc,vol);
131 case 1: /* Axx set speed to xx and add 0x1c to fix StoOoPiD STM 2.x */
132 UniPTEffect(0xf,inf>>4);
135 case 2: /* Bxx position jump */
136 UniPTEffect(0xb,inf);
139 case 3: /* Cxx patternbreak to row xx */
140 UniPTEffect(0xd,inf);
143 case 4: /* Dxy volumeslide */
144 UniWrite(UNI_S3MEFFECTD);
148 case 5: /* Exy toneslide down */
149 UniWrite(UNI_S3MEFFECTE);
153 case 6: /* Fxy toneslide up */
154 UniWrite(UNI_S3MEFFECTF);
158 case 7: /* Gxx Tone portamento,speed xx */
159 UniPTEffect(0x3,inf);
162 case 8: /* Hxy vibrato */
163 UniPTEffect(0x4,inf);
166 case 9: /* Ixy tremor, ontime x, offtime y */
167 UniWrite(UNI_S3MEFFECTI);
171 case 0xa: /* Jxy arpeggio */
172 UniPTEffect(0x0,inf);
175 case 0xb: /* Kxy Dual command H00 & Dxy */
177 UniWrite(UNI_S3MEFFECTD);
181 case 0xc: /* Lxy Dual command G00 & Dxy */
183 UniWrite(UNI_S3MEFFECTD);
187 /* Support all these above, since ST2 can LOAD these values */
188 /* but can actually only play up to J - and J is only */
189 /* half-way implemented in ST2 */
191 case 0x18: /* Xxx amiga command 8xx - What the hell, support panning. :) */
192 UniPTEffect(0x8,inf);
200 UBYTE *STM_ConvertTrack(STMNOTE *n)
206 { STM_ConvertNote(n);
216 BOOL STM_LoadPatterns(void)
220 if(!AllocPatterns()) return 0;
221 if(!AllocTracks()) return 0;
223 /* Allocate temporary buffer for loading
224 and converting the patterns */
226 if(!(stmbuf=(STMNOTE *)MyCalloc(64U*of.numchn,sizeof(STMNOTE)))) return 0;
228 for(t=0;t<of.numpat;t++){
230 for(s=0;s<(64U*of.numchn);s++){
231 stmbuf[s].note=_mm_read_UBYTE(modfp);
232 stmbuf[s].insvol=_mm_read_UBYTE(modfp);
233 stmbuf[s].volcmd=_mm_read_UBYTE(modfp);
234 stmbuf[s].cmdinf=_mm_read_UBYTE(modfp);
238 myerr=ERROR_LOADING_PATTERN;
242 for(s=0;s<of.numchn;s++){
243 if(!(of.tracks[tracks++]=STM_ConvertTrack(stmbuf+s))) return 0;
255 ULONG MikMod_ISA; /* We MUST generate our own ISA - NOT stored in the stm */
259 /* try to read stm header */
261 _mm_read_str(mh->songname,20,modfp);
262 _mm_read_str(mh->trackername,8,modfp);
263 mh->unused =_mm_read_UBYTE(modfp);
264 mh->filetype =_mm_read_UBYTE(modfp);
265 mh->ver_major =_mm_read_UBYTE(modfp);
266 mh->ver_minor =_mm_read_UBYTE(modfp);
267 mh->inittempo =_mm_read_UBYTE(modfp);
268 mh->numpat =_mm_read_UBYTE(modfp);
269 mh->globalvol =_mm_read_UBYTE(modfp);
270 _mm_read_UBYTES(mh->reserved,13,modfp);
273 STMSAMPLE *s=&mh->sample[t]; /* STM sample data */
274 _mm_read_str(s->filename,12,modfp);
275 s->unused =_mm_read_UBYTE(modfp);
276 s->instdisk =_mm_read_UBYTE(modfp);
277 s->reserved =_mm_read_I_UWORD(modfp);
278 s->length =_mm_read_I_UWORD(modfp);
279 s->loopbeg =_mm_read_I_UWORD(modfp);
280 s->loopend =_mm_read_I_UWORD(modfp);
281 s->volume =_mm_read_UBYTE(modfp);
282 s->reserved2=_mm_read_UBYTE(modfp);
283 s->c2spd =_mm_read_I_UWORD(modfp);
284 _mm_read_UBYTES(s->reserved3,4,modfp);
285 s->isa =_mm_read_I_UWORD(modfp);
287 _mm_read_UBYTES(mh->patorder,128,modfp);
290 myerr=ERROR_LOADING_HEADER;
294 /* set module variables */
296 of.modtype=strdup(STM_Version);
297 of.songname=DupStr(mh->songname,20); /* make a cstr of songname */
299 of.numpat=mh->numpat;
301 of.initspeed=6; /* Always this */
303 /* STM 2.x tempo has always been fucked... The default of 96 */
304 /* is actually 124, so we add 1ch to the initial value of 60h */
306 /* MikMak: No it's not.. STM tempo is UNI speed << 4 */
308 of.inittempo=125; /* mh->inittempo+0x1c; */
309 of.initspeed=mh->inittempo>>4;
310 of.numchn=4; /* get number of channels */
313 while(mh->patorder[t]!=99){ /* 99 terminates the patorder list */
314 of.positions[t]=mh->patorder[t];
318 of.numtrk=of.numpat*of.numchn;
320 /* Finally, init the sampleinfo structures */
322 of.numins=31; /* always this */
324 if(!AllocInstruments()) return 0;
325 if(!STM_LoadPatterns()) return 0;
329 MikMod_ISA=ftell(modfp);
330 MikMod_ISA=(MikMod_ISA+15)&0xfffffff0;
332 for(t=0;t<of.numins;t++){
335 if(!AllocSamples(d)) return 0;
338 /* load sample info */
340 d->insname=DupStr(mh->sample[t].filename,12);
341 q->c2spd=mh->sample[t].c2spd;
342 q->volume=mh->sample[t].volume;
343 q->length=mh->sample[t].length;
344 if (!mh->sample[t].volume || q->length==1 ) q->length = 0; /* if vol = 0 or length = 1, then no sample */
345 q->loopstart=mh->sample[t].loopbeg;
346 q->loopend=mh->sample[t].loopend;
347 q->seekpos=MikMod_ISA;
349 MikMod_ISA+=q->length;
351 MikMod_ISA=(MikMod_ISA+15)&0xfffffff0;
353 /* Once again, contrary to the STM specs, all the sample data is */
354 /* actually SIGNED! Sheesh */
358 if(mh->sample[t].loopend>0 && mh->sample[t].loopend!=0xffff) q->flags|=SF_LOOP;
360 /* fix replen if repend>length */
362 if(q->loopend>q->length) q->loopend=q->length;
374 "Portable STM Loader - V 1.2 - A Coding Nightmare by Rao and Air Richter of HaRDCoDE",