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 DSIK internal format (DSM) module loader
27 ==============================================================================*/
35 #include "unimod_priv.h"
37 /*========== Module structure */
39 #define DSM_MAXCHAN (16)
40 #define DSM_MAXORDERS (128)
42 typedef struct DSMSONG
56 UBYTE panpos[DSM_MAXCHAN];
57 UBYTE orders[DSM_MAXORDERS];
61 typedef struct DSMINST
76 typedef struct DSMNOTE
78 UBYTE note, ins, vol, cmd, inf;
82 #define DSM_SURROUND (0xa4)
84 /*========== Loader variables */
86 static CHAR *SONGID = "SONG";
87 static CHAR *INSTID = "INST";
88 static CHAR *PATTID = "PATT";
90 static UBYTE blockid[4];
93 static DSMSONG *mh = NULL;
94 static DSMNOTE *dsmbuf = NULL;
96 static CHAR DSM_Version[] = "DSIK DSM-format";
98 static unsigned char DSMSIG[4 + 4] =
99 {'R', 'I', 'F', 'F', 'D', 'S', 'M', 'F'};
101 /*========== Loader code */
108 if (!_mm_read_UBYTES (id, 12, modreader))
110 if (!memcmp (id, DSMSIG, 4) && !memcmp (id + 8, DSMSIG + 4, 4))
119 if (!(dsmbuf = (DSMNOTE *) _mm_malloc (DSM_MAXCHAN * 64 * sizeof (DSMNOTE))))
121 if (!(mh = (DSMSONG *) _mm_calloc (1, sizeof (DSMSONG))))
134 GetBlockHeader (void)
136 /* make sure we're at the right position for reading the
137 next riff block, no matter how many bytes read */
138 _mm_fseek (modreader, blocklp + blockln, SEEK_SET);
142 _mm_read_UBYTES (blockid, 4, modreader);
143 blockln = _mm_read_I_ULONG (modreader);
144 if (_mm_eof (modreader))
146 _mm_errno = MMERR_LOADING_HEADER;
150 if (memcmp (blockid, SONGID, 4) && memcmp (blockid, INSTID, 4) &&
151 memcmp (blockid, PATTID, 4))
154 fprintf (stderr, "\rDSM: Skipping unknown block type %4.4s\n", blockid);
156 _mm_fseek (modreader, blockln, SEEK_CUR);
162 blocklp = _mm_ftell (modreader);
168 DSM_ReadPattern (void)
174 /* clear pattern data */
175 memset (dsmbuf, 255, DSM_MAXCHAN * 64 * sizeof (DSMNOTE));
176 length = _mm_read_I_SWORD (modreader);
180 flag = _mm_read_UBYTE (modreader);
181 if ((_mm_eof (modreader)) || (--length < 0))
183 _mm_errno = MMERR_LOADING_PATTERN;
189 n = &dsmbuf[((flag & 0xf) * 64) + row];
191 n->note = _mm_read_UBYTE (modreader);
193 n->ins = _mm_read_UBYTE (modreader);
195 n->vol = _mm_read_UBYTE (modreader);
198 n->cmd = _mm_read_UBYTE (modreader);
199 n->inf = _mm_read_UBYTE (modreader);
210 DSM_ConvertTrack (DSMNOTE * tr)
213 UBYTE note, ins, vol, cmd, inf;
216 for (t = 0; t < 64; t++)
224 if (ins != 0 && ins != 255)
225 UniInstrument (ins - 1);
227 UniNote (note - 1); /* normal note */
229 UniPTEffect (0xc, vol);
235 if (inf == DSM_SURROUND)
236 UniEffect (UNI_ITEFFECTS0, 0x91);
237 else if (inf <= 0x80)
239 inf = (inf < 0x80) ? inf << 1 : 255;
240 UniPTEffect (cmd, inf);
246 UniPTEffect (cmd, inf);
250 /* Convert pattern jump from Dec to Hex */
252 inf = (((inf & 0xf0) >> 4) * 10) + (inf & 0xf);
253 UniPTEffect (cmd, inf);
262 DSM_Load (BOOL curious)
267 int cursmp = 0, curpat = 0, track = 0;
272 if (!GetBlockHeader ())
274 if (memcmp (blockid, SONGID, 4))
276 _mm_errno = MMERR_LOADING_HEADER;
280 _mm_read_UBYTES (mh->songname, 28, modreader);
281 mh->version = _mm_read_I_UWORD (modreader);
282 mh->flags = _mm_read_I_UWORD (modreader);
283 mh->reserved2 = _mm_read_I_ULONG (modreader);
284 mh->numord = _mm_read_I_UWORD (modreader);
285 mh->numsmp = _mm_read_I_UWORD (modreader);
286 mh->numpat = _mm_read_I_UWORD (modreader);
287 mh->numtrk = _mm_read_I_UWORD (modreader);
288 mh->globalvol = _mm_read_UBYTE (modreader);
289 mh->mastervol = _mm_read_UBYTE (modreader);
290 mh->speed = _mm_read_UBYTE (modreader);
291 mh->bpm = _mm_read_UBYTE (modreader);
292 _mm_read_UBYTES (mh->panpos, DSM_MAXCHAN, modreader);
293 _mm_read_UBYTES (mh->orders, DSM_MAXORDERS, modreader);
295 /* set module variables */
296 of.initspeed = mh->speed;
297 of.inittempo = mh->bpm;
298 of.modtype = strdup (DSM_Version);
299 of.numchn = mh->numtrk;
300 of.numpat = mh->numpat;
301 of.numtrk = of.numchn * of.numpat;
302 of.songname = DupStr (mh->songname, 28, 1); /* make a cstr of songname */
305 for (t = 0; t < DSM_MAXCHAN; t++)
306 of.panning[t] = mh->panpos[t] == DSM_SURROUND ? PAN_SURROUND :
307 mh->panpos[t] < 0x80 ? (mh->panpos[t] << 1) : 255;
309 if (!AllocPositions (mh->numord))
312 for (t = 0; t < mh->numord; t++)
314 of.positions[of.numpos] = mh->orders[t];
315 if (mh->orders[t] < 254)
319 of.numins = of.numsmp = mh->numsmp;
321 if (!AllocSamples ())
325 if (!AllocPatterns ())
328 while (cursmp < of.numins || curpat < of.numpat)
330 if (!GetBlockHeader ())
332 if (!memcmp (blockid, INSTID, 4) && cursmp < of.numins)
334 q = &of.samples[cursmp];
336 /* try to read sample info */
337 _mm_read_UBYTES (s.filename, 13, modreader);
338 s.flags = _mm_read_I_UWORD (modreader);
339 s.volume = _mm_read_UBYTE (modreader);
340 s.length = _mm_read_I_ULONG (modreader);
341 s.loopstart = _mm_read_I_ULONG (modreader);
342 s.loopend = _mm_read_I_ULONG (modreader);
343 s.reserved1 = _mm_read_I_ULONG (modreader);
344 s.c2spd = _mm_read_I_UWORD (modreader);
345 s.period = _mm_read_I_UWORD (modreader);
346 _mm_read_UBYTES (s.samplename, 28, modreader);
348 q->samplename = DupStr (s.samplename, 28, 1);
349 q->seekpos = _mm_ftell (modreader);
351 q->length = s.length;
352 q->loopstart = s.loopstart;
353 q->loopend = s.loopend;
354 q->volume = s.volume;
359 q->flags |= SF_SIGNED;
360 /* (s.flags&4) means packed sample,
361 but did they really exist in dsm ? */
364 else if (!memcmp (blockid, PATTID, 4) && curpat < of.numpat)
367 for (t = 0; t < of.numchn; t++)
368 if (!(of.tracks[track++] = DSM_ConvertTrack (&dsmbuf[t * 64])))
382 _mm_fseek (modreader, 12, SEEK_SET);
383 if (!_mm_read_UBYTES (s, 28, modreader))
386 return (DupStr (s, 28, 1));
389 /*========== Loader information */
395 "DSM (DSIK internal format)",