1 /* MikMod sound library
2 (c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
3 AUTHORS for complete list.
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.
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.
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
21 /*==============================================================================
23 $Id: load_stm.c,v 1.3 2005/04/07 19:57:38 realtech Exp $
25 Screamtracker 2 (STM) module loader
27 ==============================================================================*/
43 #include "mikmod_internals.h"
46 extern int fprintf(FILE *, const char *, ...);
49 /*========== Module structure */
51 /* sample information */
52 typedef struct STMSAMPLE
{
54 UBYTE unused
; /* 0x00 */
55 UBYTE instdisk
; /* Instrument disk */
57 UWORD length
; /* Sample length */
58 UWORD loopbeg
; /* Loop start point */
59 UWORD loopend
; /* Loop end point */
60 UBYTE volume
; /* Volume */
62 UWORD c2spd
; /* Good old c2spd */
68 typedef struct STMHEADER
{
70 CHAR trackername
[8]; /* !Scream! for ST 2.xx */
71 UBYTE unused
; /* 0x1A */
72 UBYTE filetype
; /* 1=song, 2=module */
75 UBYTE inittempo
; /* initspeed= stm inittempo>>4 */
76 UBYTE numpat
; /* number of patterns */
79 STMSAMPLE sample
[31]; /* STM sample data */
80 UBYTE patorder
[128]; /* Docs say 64 - actually 128 */
83 typedef struct STMNOTE
{
84 UBYTE note
,insvol
,volcmd
,cmdinf
;
87 /*========== Loader variables */
89 static STMNOTE
*stmbuf
= NULL
;
90 static STMHEADER
*mh
= NULL
;
92 /* tracker identifiers */
93 static CHAR
* STM_Version
[STM_NTRACKERS
] = {
95 "Converted by MOD2STM (STM format)",
96 "Wuzamod (STM format)"
99 /*========== Loader code */
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 */
110 /* Prevent false positives for S3M files */
111 if(!memcmp(str
+40,"SCRM",4))
114 for (t
=0;t
<STM_NTRACKERS
;t
++)
115 if(!memcmp(str
,STM_Signatures
[t
],8))
123 if(!(mh
=(STMHEADER
*)MikMod_malloc(sizeof(STMHEADER
)))) return 0;
124 if(!(stmbuf
=(STMNOTE
*)MikMod_calloc(64U*4,sizeof(STMNOTE
)))) return 0;
129 static void STM_Cleanup(void)
135 static void STM_ConvertNote(STMNOTE
*n
)
137 UBYTE note
,ins
,vol
,cmd
,inf
;
139 /* extract the various information from the 4 bytes that make up a note */
142 vol
= (n
->insvol
&7)+((n
->volcmd
&0x70)>>1);
146 if((ins
)&&(ins
<32)) UniInstrument(ins
-1);
148 /* special values of [SBYTE0] are handled here
149 we have no idea if these strange values will ever be encountered.
150 but it appears as those stms sound correct. */
151 if((note
==254)||(note
==252)) {
152 UniPTEffect(0xc,0); /* note cut */
155 /* if note < 251, then all three bytes are stored in the file */
156 if(note
<251) UniNote((((note
>>4)+2)*OCTAVE
)+(note
&0xf));
158 if((!(n
->volcmd
&0x80))&&(vol
<65)) UniPTEffect(0xc,vol
);
161 case 1: /* Axx set speed to xx */
162 UniPTEffect(0xf,inf
>>4);
164 case 2: /* Bxx position jump */
165 UniPTEffect(0xb,inf
);
167 case 3: /* Cxx patternbreak to row xx */
168 UniPTEffect(0xd,(((inf
&0xf0)>>4)*10)+(inf
&0xf));
170 case 4: /* Dxy volumeslide */
171 UniEffect(UNI_S3MEFFECTD
,inf
);
173 case 5: /* Exy toneslide down */
174 UniEffect(UNI_S3MEFFECTE
,inf
);
176 case 6: /* Fxy toneslide up */
177 UniEffect(UNI_S3MEFFECTF
,inf
);
179 case 7: /* Gxx Tone portamento,speed xx */
180 UniPTEffect(0x3,inf
);
182 case 8: /* Hxy vibrato */
183 UniPTEffect(0x4,inf
);
185 case 9: /* Ixy tremor, ontime x, offtime y */
186 UniEffect(UNI_S3MEFFECTI
,inf
);
188 case 0: /* protracker arpeggio */
191 case 0xa: /* Jxy arpeggio */
192 UniPTEffect(0x0,inf
);
194 case 0xb: /* Kxy Dual command H00 & Dxy */
196 UniEffect(UNI_S3MEFFECTD
,inf
);
198 case 0xc: /* Lxy Dual command G00 & Dxy */
200 UniEffect(UNI_S3MEFFECTD
,inf
);
202 /* Support all these above, since ST2 can LOAD these values but can
203 actually only play up to J - and J is only half-way implemented
205 case 0x18: /* Xxx amiga panning command 8xx */
206 UniPTEffect(0x8,inf
);
207 of
.flags
|= UF_PANNING
;
212 static UBYTE
*STM_ConvertTrack(STMNOTE
*n
)
225 static int STM_LoadPatterns(void)
229 if(!AllocPatterns()) return 0;
230 if(!AllocTracks()) return 0;
232 /* Allocate temporary buffer for loading and converting the patterns */
233 for(t
=0;t
<of
.numpat
;t
++) {
234 for(s
=0;s
<(64U*of
.numchn
);s
++) {
235 stmbuf
[s
].note
= _mm_read_UBYTE(modreader
);
236 stmbuf
[s
].insvol
= _mm_read_UBYTE(modreader
);
237 stmbuf
[s
].volcmd
= _mm_read_UBYTE(modreader
);
238 stmbuf
[s
].cmdinf
= _mm_read_UBYTE(modreader
);
241 if(_mm_eof(modreader
)) {
242 _mm_errno
= MMERR_LOADING_PATTERN
;
246 for(s
=0;s
<of
.numchn
;s
++)
247 if(!(of
.tracks
[tracks
++]=STM_ConvertTrack(stmbuf
+s
))) return 0;
252 int STM_Load(int curious
)
255 ULONG MikMod_ISA
; /* We must generate our own ISA, it's not stored in stm */
258 /* try to read stm header */
259 _mm_read_string(mh
->songname
,20,modreader
);
260 _mm_read_string(mh
->trackername
,8,modreader
);
261 mh
->unused
=_mm_read_UBYTE(modreader
);
262 mh
->filetype
=_mm_read_UBYTE(modreader
);
263 mh
->ver_major
=_mm_read_UBYTE(modreader
);
264 mh
->ver_minor
=_mm_read_UBYTE(modreader
);
265 mh
->inittempo
=_mm_read_UBYTE(modreader
);
267 _mm_errno
=MMERR_NOT_A_MODULE
;
270 mh
->numpat
=_mm_read_UBYTE(modreader
);
271 mh
->globalvol
=_mm_read_UBYTE(modreader
);
272 _mm_read_UBYTES(mh
->reserved
,13,modreader
);
275 STMSAMPLE
*s
=&mh
->sample
[t
]; /* STM sample data */
277 _mm_read_string(s
->filename
,12,modreader
);
278 s
->unused
=_mm_read_UBYTE(modreader
);
279 s
->instdisk
=_mm_read_UBYTE(modreader
);
280 s
->reserved
=_mm_read_I_UWORD(modreader
);
281 s
->length
=_mm_read_I_UWORD(modreader
);
282 s
->loopbeg
=_mm_read_I_UWORD(modreader
);
283 s
->loopend
=_mm_read_I_UWORD(modreader
);
284 s
->volume
=_mm_read_UBYTE(modreader
);
285 s
->reserved2
=_mm_read_UBYTE(modreader
);
286 s
->c2spd
=_mm_read_I_UWORD(modreader
);
287 s
->reserved3
=_mm_read_I_ULONG(modreader
);
288 s
->isa
=_mm_read_I_UWORD(modreader
);
290 _mm_read_UBYTES(mh
->patorder
,128,modreader
);
292 if(_mm_eof(modreader
)) {
293 _mm_errno
= MMERR_LOADING_HEADER
;
297 /* set module variables */
298 for(t
=0;t
<STM_NTRACKERS
;t
++)
299 if(!memcmp(mh
->trackername
,STM_Signatures
[t
],8)) break;
300 of
.modtype
= StrDup(STM_Version
[t
]);
301 of
.songname
= DupStr(mh
->songname
,20,1); /* make a cstr of songname */
302 of
.numpat
= mh
->numpat
;
303 of
.inittempo
= 125; /* mh->inittempo+0x1c; */
304 of
.initspeed
= mh
->inittempo
>>4;
305 of
.numchn
= 4; /* get number of channels */
307 of
.flags
|= UF_S3MSLIDES
;
311 if(!AllocPositions(0x80)) return 0;
312 /* 99 terminates the patorder list */
313 while((mh
->patorder
[t
]<=99)&&(mh
->patorder
[t
]<mh
->numpat
)) {
314 of
.positions
[t
]=mh
->patorder
[t
];
317 if(mh
->patorder
[t
]<=99) t
++;
319 of
.numtrk
=of
.numpat
*of
.numchn
;
320 of
.numins
=of
.numsmp
=31;
322 if(!AllocSamples()) return 0;
323 if(!STM_LoadPatterns()) return 0;
324 MikMod_ISA
=_mm_ftell(modreader
);
325 MikMod_ISA
=(MikMod_ISA
+15)&0xfffffff0; /* normalize */
327 for(q
=of
.samples
,t
=0;t
<of
.numsmp
;t
++,q
++) {
328 /* load sample info */
329 q
->samplename
= DupStr(mh
->sample
[t
].filename
,12,1);
330 q
->speed
= (mh
->sample
[t
].c2spd
* 8363) / 8448;
331 q
->volume
= mh
->sample
[t
].volume
;
332 q
->length
= mh
->sample
[t
].length
;
333 if (/*(!mh->sample[t].volume)||*/(q
->length
==1)) q
->length
=0;
334 q
->loopstart
= mh
->sample
[t
].loopbeg
;
335 q
->loopend
= mh
->sample
[t
].loopend
;
336 q
->seekpos
= MikMod_ISA
;
338 MikMod_ISA
+=q
->length
;
339 MikMod_ISA
=(MikMod_ISA
+15)&0xfffffff0; /* normalize */
341 /* contrary to the STM specs, sample data is signed */
342 q
->flags
= SF_SIGNED
;
344 if(q
->loopend
&& q
->loopend
!= 0xffff)
350 CHAR
*STM_LoadTitle(void)
354 _mm_fseek(modreader
,0,SEEK_SET
);
355 if(!_mm_read_UBYTES(s
,20,modreader
)) return NULL
;
357 return(DupStr(s
,20,1));
360 /*========== Loader information */
362 MIKMODAPI MLOADER load_stm
={
365 "STM (Scream Tracker)",