1 /* MikMod sound library
2 (c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
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 /*==============================================================================
25 STMIK 0.2 (STX) module loader
27 ==============================================================================*/
31 Written by Claudio Matsuoka <claudio@helllabs.org>
41 #include "unimod_priv.h"
43 /*========== Module structure */
46 typedef struct STXHEADER
54 UWORD chnptr; /* not sure */
71 /* sample information */
72 typedef struct STXSAMPLE
92 typedef struct STXNOTE
94 UBYTE note, ins, vol, cmd, inf;
98 /*========== Loader variables */
100 static STXNOTE *stxbuf = NULL; /* pointer to a complete STX pattern */
101 static STXHEADER *mh = NULL;
102 static UWORD *paraptr = NULL; /* parapointer array (see STX docs) */
104 /*========== Loader code */
112 _mm_fseek(modreader,0x14,SEEK_SET);
113 if(!_mm_read_UBYTES(id, 8, modreader))
116 for(t=0;t<STM_NTRACKERS;t++)
117 if(!memcmp(id,STM_Signatures[t],8)) return 1;
119 _mm_fseek (modreader, 0x3C, SEEK_SET);
120 if (!_mm_read_UBYTES (id, 4, modreader))
122 if (memcmp (id, "SCRM", 4))
131 if (!(stxbuf = (STXNOTE *) _mm_malloc (4 * 64 * sizeof (STXNOTE))))
133 if (!(mh = (STXHEADER *) _mm_malloc (sizeof (STXHEADER))))
135 if (!(poslookup = (UBYTE *) _mm_malloc (sizeof (UBYTE) * 256)))
137 memset (poslookup, -1, 256);
147 _mm_free (poslookup);
152 STX_ReadPattern (void)
154 int row = 0, flag, ch;
157 /* clear pattern data */
158 memset (stxbuf, 255, 4 * 64 * sizeof (STXNOTE));
162 flag = _mm_read_UBYTE (modreader);
164 if (_mm_eof (modreader))
166 _mm_errno = MMERR_LOADING_PATTERN;
174 if ((ch >= 0) && (ch < 4))
175 n = &stxbuf[(64U * ch) + row];
181 n->note = _mm_read_UBYTE (modreader);
182 n->ins = _mm_read_UBYTE (modreader);
186 n->vol = _mm_read_UBYTE (modreader);
192 n->cmd = _mm_read_UBYTE (modreader);
193 n->inf = _mm_read_UBYTE (modreader);
203 STX_ConvertTrack (STXNOTE * tr)
208 for (t = 0; t < 64; t++)
210 UBYTE note, ins, vol, cmd, inf;
218 if ((ins) && (ins != 255))
219 UniInstrument (ins - 1);
220 if ((note) && (note != 255))
224 UniPTEffect (0xc, 0); /* note cut command */
228 UniNote (24 + ((note >> 4) * OCTAVE) + (note & 0xf)); /* normal note */
232 UniPTEffect (0xc, vol);
237 case 1: /* Axx set speed to xx */
238 UniPTEffect (0xf, inf >> 4);
240 case 2: /* Bxx position jump */
241 UniPTEffect (0xb, inf);
243 case 3: /* Cxx patternbreak to row xx */
244 UniPTEffect (0xd, (((inf & 0xf0) >> 4) * 10) + (inf & 0xf));
246 case 4: /* Dxy volumeslide */
247 UniEffect (UNI_S3MEFFECTD, inf);
249 case 5: /* Exy toneslide down */
250 UniEffect (UNI_S3MEFFECTE, inf);
252 case 6: /* Fxy toneslide up */
253 UniEffect (UNI_S3MEFFECTF, inf);
255 case 7: /* Gxx Tone portamento,speed xx */
256 UniPTEffect (0x3, inf);
258 case 8: /* Hxy vibrato */
259 UniPTEffect (0x4, inf);
261 case 9: /* Ixy tremor, ontime x, offtime y */
262 UniEffect (UNI_S3MEFFECTI, inf);
264 case 0: /* protracker arpeggio */
268 case 0xa: /* Jxy arpeggio */
269 UniPTEffect (0x0, inf);
271 case 0xb: /* Kxy Dual command H00 & Dxy */
272 UniPTEffect (0x4, 0);
273 UniEffect (UNI_S3MEFFECTD, inf);
275 case 0xc: /* Lxy Dual command G00 & Dxy */
276 UniPTEffect (0x3, 0);
277 UniEffect (UNI_S3MEFFECTD, inf);
279 /* Support all these above, since ST2 can LOAD these values but can
280 actually only play up to J - and J is only half-way implemented
282 case 0x18: /* Xxx amiga panning command 8xx */
283 UniPTEffect (0x8, inf);
292 STX_Load (BOOL curious)
299 /* try to read module header */
300 _mm_read_string (mh->songname, 20, modreader);
301 _mm_read_string (mh->trackername, 8, modreader);
302 mh->patsize = _mm_read_I_UWORD (modreader);
303 mh->unknown1 = _mm_read_I_UWORD (modreader);
304 mh->patptr = _mm_read_I_UWORD (modreader);
305 mh->insptr = _mm_read_I_UWORD (modreader);
306 mh->chnptr = _mm_read_I_UWORD (modreader);
307 mh->unknown2 = _mm_read_I_UWORD (modreader);
308 mh->unknown3 = _mm_read_I_UWORD (modreader);
309 mh->mastermult = _mm_read_UBYTE (modreader);
310 mh->initspeed = _mm_read_UBYTE (modreader) >> 4;
311 mh->unknown4 = _mm_read_I_UWORD (modreader);
312 mh->unknown5 = _mm_read_I_UWORD (modreader);
313 mh->patnum = _mm_read_I_UWORD (modreader);
314 mh->insnum = _mm_read_I_UWORD (modreader);
315 mh->ordnum = _mm_read_I_UWORD (modreader);
316 mh->unknown6 = _mm_read_I_UWORD (modreader);
317 mh->unknown7 = _mm_read_I_UWORD (modreader);
318 mh->unknown8 = _mm_read_I_UWORD (modreader);
319 _mm_read_string (mh->scrm, 4, modreader);
321 if (_mm_eof (modreader))
323 _mm_errno = MMERR_LOADING_HEADER;
327 tracker = "unknown tracker";
328 for (t = 0; t < STM_NTRACKERS; t++)
329 if (!memcmp (mh->trackername, STM_Signatures[t], 8))
331 tracker = STM_Version[t];
335 of.modtype = _mm_malloc(
337 strlen("STM2STX 1.x ()") + 1);
339 sprintf(of.modtype, "STM2STX 1.x (%s)", tracker);
341 /* set module variables */
342 of.songname = DupStr (mh->songname, 20, 1);
343 of.numpat = mh->patnum;
345 of.numins = of.numsmp = mh->insnum;
346 of.initspeed = mh->initspeed;
349 of.flags |= UF_S3MSLIDES;
351 if (!(paraptr = (UWORD *) _mm_malloc ((of.numins + of.numpat) * sizeof (UWORD))))
354 /* read the instrument+pattern parapointers */
355 _mm_fseek (modreader, mh->insptr << 4, SEEK_SET);
356 _mm_read_I_UWORDS (paraptr, of.numins, modreader);
357 _mm_fseek (modreader, mh->patptr << 4, SEEK_SET);
358 _mm_read_I_UWORDS (paraptr + of.numins, of.numpat, modreader);
360 /* check module version */
361 _mm_fseek (modreader, paraptr[of.numins] << 4, SEEK_SET);
362 version = _mm_read_I_UWORD (modreader);
363 if (version == mh->patsize)
366 of.modtype[10] = '0';
371 of.modtype[10] = '1';
374 /* read the order data */
375 _mm_fseek (modreader, (mh->chnptr << 4) + 32, SEEK_SET);
376 if (!AllocPositions (mh->ordnum))
378 for (t = 0; t < mh->ordnum; t++)
380 of.positions[t] = _mm_read_UBYTE (modreader);
381 _mm_fseek (modreader, 4, SEEK_CUR);
385 poslookupcnt = mh->ordnum;
386 for (t = 0; t < mh->ordnum; t++)
388 of.positions[of.numpos] = of.positions[t];
389 poslookup[t] = of.numpos; /* bug fix for freaky S3Ms */
390 if (of.positions[t] < 254)
393 /* special end of song pattern */
394 if ((of.positions[t] == 255) && (!curious))
398 if (_mm_eof (modreader))
400 _mm_errno = MMERR_LOADING_HEADER;
405 if (!AllocSamples ())
407 for (q = of.samples, t = 0; t < of.numins; t++, q++)
411 /* seek to instrument position */
412 _mm_fseek (modreader, ((long) paraptr[t]) << 4, SEEK_SET);
413 /* and load sample info */
414 s.type = _mm_read_UBYTE (modreader);
415 _mm_read_string (s.filename, 12, modreader);
416 s.memsegh = _mm_read_UBYTE (modreader);
417 s.memsegl = _mm_read_I_UWORD (modreader);
418 s.length = _mm_read_I_ULONG (modreader);
419 s.loopbeg = _mm_read_I_ULONG (modreader);
420 s.loopend = _mm_read_I_ULONG (modreader);
421 s.volume = _mm_read_UBYTE (modreader);
422 s.dsk = _mm_read_UBYTE (modreader);
423 s.pack = _mm_read_UBYTE (modreader);
424 s.flags = _mm_read_UBYTE (modreader);
425 s.c2spd = _mm_read_I_ULONG (modreader);
426 _mm_read_UBYTES (s.unused, 12, modreader);
427 _mm_read_string (s.sampname, 28, modreader);
428 _mm_read_string (s.scrs, 4, modreader);
430 if (_mm_eof (modreader))
432 _mm_errno = MMERR_LOADING_SAMPLEINFO;
436 q->samplename = DupStr (s.sampname, 28, 1);
437 q->speed = (s.c2spd * 8363) / 8448;
438 q->length = s.length;
439 q->loopstart = s.loopbeg;
440 q->loopend = s.loopend;
441 q->volume = s.volume;
442 q->seekpos = (((long) s.memsegh) << 16 | s.memsegl) << 4;
443 q->flags |= SF_SIGNED;
445 /* fix for bad converted STMs */
446 if (q->loopstart >= q->length)
447 q->loopstart = q->loopend = 0;
449 /* some modules come with loopstart == loopend == 0, yet have the
450 * looping flag set */
451 if ((s.flags & 1) && (q->loopstart != q->loopend))
454 if (q->loopend > q->length)
455 q->loopend = q->length;
458 q->flags |= SF_16BITS;
461 /* load pattern info */
462 of.numtrk = of.numpat * of.numchn;
465 if (!AllocPatterns ())
468 for (t = 0; t < of.numpat; t++)
470 /* seek to pattern position (+2 skip pattern length) */
471 _mm_fseek (modreader, (((long) paraptr[of.numins + t]) << 4) +
472 (version == 0x10 ? 2 : 0), SEEK_SET);
473 if (!STX_ReadPattern ())
475 for (u = 0; u < of.numchn; u++)
476 if (!(of.tracks[track++] = STX_ConvertTrack (&stxbuf[u * 64])))
488 _mm_fseek (modreader, 0, SEEK_SET);
489 if (!_mm_read_UBYTES (s, 20, modreader))
492 return (DupStr (s, 28, 1));
495 /*========== Loader information */
501 "STX (Scream Tracker Music Interface Kit)",