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 /*==============================================================================
23 $Id: load_ult.c,v 1.27 1999/10/25 16:31:41 miod Exp $
25 Ultratracker (ULT) module loader
27 ==============================================================================*/
35 #include "unimod_priv.h"
37 /*========== Module structure */
40 typedef struct ULTHEADER
48 /* sample information */
49 typedef struct ULTSAMPLE
64 typedef struct ULTEVENT
66 UBYTE note, sample, eff, dat1, dat2;
70 /*========== Loader variables */
74 #define ULTS_REVERSE 16
76 #define ULT_VERSION_LEN 18
77 static CHAR ULT_Version[ULT_VERSION_LEN] = "Ultra Tracker v1.x";
81 /*========== Loader code */
88 if (!_mm_read_string (id, 15, modreader))
90 if (strncmp (id, "MAS_UTrack_V00", 14))
92 if ((id[14] < '1') || (id[14] > '4'))
109 ReadUltEvent (ULTEVENT * event)
113 flag = _mm_read_UBYTE (modreader);
116 rep = _mm_read_UBYTE (modreader);
117 event->note = _mm_read_UBYTE (modreader);
122 event->sample = _mm_read_UBYTE (modreader);
123 event->eff = _mm_read_UBYTE (modreader);
124 event->dat1 = _mm_read_UBYTE (modreader);
125 event->dat2 = _mm_read_UBYTE (modreader);
131 ULT_Load (BOOL curious)
133 int t, u, tracks = 0;
139 /* try to read module header */
140 _mm_read_string (mh.id, 15, modreader);
141 _mm_read_string (mh.songtitle, 32, modreader);
142 mh.reserved = _mm_read_UBYTE (modreader);
144 if (_mm_eof (modreader))
146 _mm_errno = MMERR_LOADING_HEADER;
150 ULT_Version[ULT_VERSION_LEN - 1] = '3' + (mh.id[14] - '1');
151 of.modtype = DupStr (ULT_Version, ULT_VERSION_LEN, 1);
157 if ((mh.id[14] > '1') && (mh.reserved))
158 if (!ReadLinedComment (mh.reserved, 32))
161 nos = _mm_read_UBYTE (modreader);
162 if (_mm_eof (modreader))
164 _mm_errno = MMERR_LOADING_HEADER;
168 of.songname = DupStr (mh.songtitle, 32, 1);
169 of.numins = of.numsmp = nos;
171 if (!AllocSamples ())
174 for (t = 0; t < nos; t++)
176 /* try to read sample info */
177 _mm_read_string (s.samplename, 32, modreader);
178 _mm_read_string (s.dosname, 12, modreader);
179 s.loopstart = _mm_read_I_ULONG (modreader);
180 s.loopend = _mm_read_I_ULONG (modreader);
181 s.sizestart = _mm_read_I_ULONG (modreader);
182 s.sizeend = _mm_read_I_ULONG (modreader);
183 s.volume = _mm_read_UBYTE (modreader);
184 s.flags = _mm_read_UBYTE (modreader);
185 s.speed = (mh.id[14] >= '4') ? _mm_read_I_UWORD (modreader) : 8363;
186 s.finetune = _mm_read_I_SWORD (modreader);
188 if (_mm_eof (modreader))
190 _mm_errno = MMERR_LOADING_SAMPLEINFO;
194 q->samplename = DupStr (s.samplename, 32, 1);
195 /* The correct formula for the coefficient would be
196 pow(2,(double)s.finetume/OCTAVE/32768), but to avoid floating point
197 here, we'll use a first order approximation here.
198 1/567290 == Ln(2)/OCTAVE/32768 */
199 q->speed = s.speed + s.speed * (((SLONG) s.speed * (SLONG) s.finetune) / 567290);
200 q->length = s.sizeend - s.sizestart;
201 q->volume = s.volume >> 2;
202 q->loopstart = s.loopstart;
203 q->loopend = s.loopend;
204 q->flags = SF_SIGNED;
205 if (s.flags & ULTS_LOOP)
207 if (s.flags & ULTS_16BITS)
209 s.sizeend += (s.sizeend - s.sizestart);
211 q->flags |= SF_16BITS;
218 if (!AllocPositions (256))
220 for (t = 0; t < 256; t++)
221 of.positions[t] = _mm_read_UBYTE (modreader);
222 for (t = 0; t < 256; t++)
223 if (of.positions[t] == 255)
227 noc = _mm_read_UBYTE (modreader);
228 nop = _mm_read_UBYTE (modreader);
232 of.numtrk = of.numchn * of.numpat;
235 if (!AllocPatterns ())
237 for (u = 0; u < of.numchn; u++)
238 for (t = 0; t < of.numpat; t++)
239 of.patterns[(t * of.numchn) + u] = tracks++;
241 /* read pan position table for v1.5 and higher */
242 if (mh.id[14] >= '3')
243 for (t = 0; t < of.numchn; t++)
244 of.panning[t] = _mm_read_UBYTE (modreader) << 4;
246 for (t = 0; t < of.numtrk; t++)
253 rep = ReadUltEvent (&ev);
255 if (_mm_eof (modreader))
257 _mm_errno = MMERR_LOADING_TRACK;
267 UniInstrument (ev.sample - 1);
269 UniNote (ev.note + 2 * OCTAVE - 1);
271 /* first effect - various fixes by Alexander Kerkhove and
276 case 0x3: /* tone portamento */
277 UniEffect (UNI_ITEFFECTG, ev.dat2);
281 case 0x9: /* sample offset */
282 offset = (ev.dat2 << 8) | ((ev.eff & 0xf) == 9 ? ev.dat1 : 0);
283 UniEffect (UNI_ULTEFFECT9, offset);
285 case 0xb: /* panning */
286 UniPTEffect (8, ev.dat2 * 0xf);
288 case 0xc: /* volume */
289 UniPTEffect (eff, ev.dat2 >> 2);
292 UniPTEffect (eff, ev.dat2);
300 case 0x3: /* tone portamento */
301 UniEffect (UNI_ITEFFECTG, ev.dat1);
305 case 0x9: /* sample offset */
306 if ((ev.eff >> 4) != 9)
307 UniEffect (UNI_ULTEFFECT9, ((UWORD) ev.dat1) << 8);
309 case 0xb: /* panning */
310 UniPTEffect (8, ev.dat1 * 0xf);
312 case 0xc: /* volume */
313 UniPTEffect (eff, ev.dat1 >> 2);
316 UniPTEffect (eff, ev.dat1);
324 if (!(of.tracks[t] = UniDup ()))
335 _mm_fseek (modreader, 15, SEEK_SET);
336 if (!_mm_read_UBYTES (s, 32, modreader))
339 return (DupStr (s, 32, 1));
342 /*========== Loader information */
348 "ULT (UltraTracker)",