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 Composer 669 module loader
27 ==============================================================================*/
35 #include "unimod_priv.h"
37 /*========== Module structure */
40 typedef struct S69HEADER
53 /* sample information */
54 typedef struct S69SAMPLE
64 typedef struct S69NOTE
70 /*========== Loader variables */
73 static S69NOTE *s69pat = NULL;
75 static S69HEADER *mh = NULL;
77 /* file type identification */
78 static CHAR *S69_Version[] =
84 /*========== Loader code */
91 if (!_mm_read_UBYTES (buf, 2, modreader))
94 if (!memcmp (buf, "if", 2) || !memcmp (buf, "JN", 2))
98 /* skip song message */
99 _mm_fseek (modreader, 108, SEEK_CUR);
101 if (_mm_read_UBYTE (modreader) > 64)
103 if (_mm_read_UBYTE (modreader) > 128)
105 if (_mm_read_UBYTE (modreader) > 127)
107 /* check order table */
108 if (!_mm_read_UBYTES (buf, 0x80, modreader))
110 for (i = 0; i < 0x80; i++)
111 if ((buf[i] >= 0x80) && (buf[i] != 0xff))
113 /* check tempos table */
114 if (!_mm_read_UBYTES (buf, 0x80, modreader))
116 for (i = 0; i < 0x80; i++)
117 if ((!buf[i]) || (buf[i] > 32))
119 /* check pattern length table */
120 if (!_mm_read_UBYTES (buf, 0x80, modreader))
122 for (i = 0; i < 0x80; i++)
135 if (!(s69pat = (S69NOTE *) _mm_malloc (64 * 8 * sizeof (S69NOTE))))
137 if (!(mh = (S69HEADER *) _mm_malloc (sizeof (S69HEADER))))
151 S69_LoadPatterns (void)
153 int track, row, channel;
154 UBYTE note, inst, vol, effect, lastfx, lastval;
158 if (!AllocPatterns ())
163 for (track = 0; track < of.numpat; track++)
165 /* set pattern break locations */
166 of.pattrows[track] = mh->breaks[track] + 1;
168 /* load the 669 pattern */
170 for (row = 0; row < 64; row++)
172 for (channel = 0; channel < 8; channel++, cur++)
174 cur->a = _mm_read_UBYTE (modreader);
175 cur->b = _mm_read_UBYTE (modreader);
176 cur->c = _mm_read_UBYTE (modreader);
180 if (_mm_eof (modreader))
182 _mm_errno = MMERR_LOADING_PATTERN;
186 /* translate the pattern */
187 for (channel = 0; channel < 8; channel++)
190 /* set pattern tempo */
191 UniPTEffect (0xf, 78);
192 UniPTEffect (0xf, mh->tempos[track]);
194 lastfx = 0xff, lastval = 0;
196 for (row = 0; row <= mh->breaks[track]; row++)
200 /* fetch the encoded note */
201 a = s69pat[(row * 8) + channel].a;
202 b = s69pat[(row * 8) + channel].b;
203 c = s69pat[(row * 8) + channel].c;
207 inst = ((a & 0x3) << 4) | ((b & 0xf0) >> 4);
214 UniInstrument (inst);
215 UniNote (note + 2 * OCTAVE);
216 lastfx = 0xff; /* reset background effect memory */
218 UniPTEffect (0xc, vol << 2);
221 if ((c != 0xff) || (lastfx != 0xff))
224 c = lastfx, effect = lastval;
230 case 0: /* porta up */
231 UniPTEffect (0x1, effect);
232 lastfx = c, lastval = effect;
234 case 1: /* porta down */
235 UniPTEffect (0x2, effect);
236 lastfx = c, lastval = effect;
238 case 2: /* porta to note */
239 UniPTEffect (0x3, effect);
240 lastfx = c, lastval = effect;
242 case 3: /* frequency adjust */
243 /* DMP converts this effect to S3M FF1. Why not ? */
244 UniEffect (UNI_S3MEFFECTF, 0xf0 | effect);
246 case 4: /* vibrato */
247 UniPTEffect (0x4, effect);
248 lastfx = c, lastval = effect;
250 case 5: /* set speed */
252 UniPTEffect (0xf, effect);
253 else if (mh->marker[0] != 0x69)
256 fprintf (stderr, "\r669: unsupported super fast tempo at pat=%d row=%d chan=%d\n",
257 track, row, channel);
265 if (!(of.tracks[tracks++] = UniDup ()))
274 S69_Load (BOOL curious)
281 _mm_read_UBYTES (mh->marker, 2, modreader);
282 _mm_read_UBYTES (mh->message, 108, modreader);
283 mh->nos = _mm_read_UBYTE (modreader);
284 mh->nop = _mm_read_UBYTE (modreader);
285 mh->looporder = _mm_read_UBYTE (modreader);
286 _mm_read_UBYTES (mh->orders, 0x80, modreader);
287 for (i = 0; i < 0x80; i++)
288 if ((mh->orders[i] >= 0x80) && (mh->orders[i] != 0xff))
290 _mm_errno = MMERR_NOT_A_MODULE;
293 _mm_read_UBYTES (mh->tempos, 0x80, modreader);
294 for (i = 0; i < 0x80; i++)
295 if ((!mh->tempos[i]) || (mh->tempos[i] > 32))
297 _mm_errno = MMERR_NOT_A_MODULE;
300 _mm_read_UBYTES (mh->breaks, 0x80, modreader);
301 for (i = 0; i < 0x80; i++)
302 if (mh->breaks[i] > 0x3f)
304 _mm_errno = MMERR_NOT_A_MODULE;
308 /* set module variables */
311 of.songname = DupStr (mh->message, 36, 1);
312 of.modtype = strdup (S69_Version[memcmp (mh->marker, "JN", 2) == 0]);
315 of.numins = of.numsmp = mh->nos;
316 of.numtrk = of.numchn * of.numpat;
317 of.flags = UF_XMPERIODS | UF_LINEAR;
319 for (i = 35; (i >= 0) && (mh->message[i] == ' '); i--)
321 for (i = 36 + 35; (i >= 36 + 0) && (mh->message[i] == ' '); i--)
323 for (i = 72 + 35; (i >= 72 + 0) && (mh->message[i] == ' '); i--)
325 if ((mh->message[0]) || (mh->message[36]) || (mh->message[72]))
326 if ((of.comment = (CHAR *) _mm_malloc (3 * (36 + 1) + 1)))
328 strncpy (of.comment, mh->message, 36);
329 strcat (of.comment, "\r");
331 strncat (of.comment, mh->message + 36, 36);
332 strcat (of.comment, "\r");
334 strncat (of.comment, mh->message + 72, 36);
335 strcat (of.comment, "\r");
336 of.comment[3 * (36 + 1)] = 0;
339 if (!AllocPositions (0x80))
341 for (i = 0; i < 0x80; i++)
343 if (mh->orders[i] >= mh->nop)
345 of.positions[i] = mh->orders[i];
348 of.reppos = mh->looporder < of.numpos ? mh->looporder : 0;
350 if (!AllocSamples ())
352 current = of.samples;
354 for (i = 0; i < of.numins; i++)
356 /* sample information */
357 _mm_read_UBYTES ((UBYTE *) sample.filename, 13, modreader);
358 sample.length = _mm_read_I_SLONG (modreader);
359 sample.loopbeg = _mm_read_I_SLONG (modreader);
360 sample.loopend = _mm_read_I_SLONG (modreader);
361 if (sample.loopend == 0xfffff)
364 if ((sample.length < 0) || (sample.loopbeg < -1) || (sample.loopend < -1))
366 _mm_errno = MMERR_LOADING_HEADER;
370 current->samplename = DupStr (sample.filename, 13, 1);
371 current->seekpos = 0;
373 current->length = sample.length;
374 current->loopstart = sample.loopbeg;
375 current->loopend = (sample.loopend < sample.length) ? sample.loopend : sample.length;
376 current->flags = (sample.loopbeg < sample.loopend) ? SF_LOOP : 0;
377 current->volume = 64;
382 if (!S69_LoadPatterns ())
393 _mm_fseek (modreader, 2, SEEK_SET);
394 if (!_mm_read_UBYTES (s, 36, modreader))
397 return (DupStr (s, 36, 1));
400 /*========== Loader information */
406 "669 (Composer 669, Unis 669)",