1 /* MikMod sound library
2 (c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
3 complete list.
4
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.
9
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.
14
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
18 02111-1307, USA.
19 */
20
21 /*==============================================================================
22
23 $Id$
24
25 Farandole (FAR) module loader
26
27 ==============================================================================*/
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <string.h>
34
35 #include "unimod_priv.h"
36
37 /*========== Module structure */
38
39 typedef struct FARHEADER1
40 {
41 UBYTE id[4]; /* file magic */
42 CHAR songname[40]; /* songname */
43 CHAR blah[3]; /* 13,10,26 */
44 UWORD headerlen; /* remaining length of header in bytes */
45 UBYTE version;
46 UBYTE onoff[16];
47 UBYTE edit1[9];
48 UBYTE speed;
49 UBYTE panning[16];
50 UBYTE edit2[4];
51 UWORD stlen;
52 }
53 FARHEADER1;
54
55 typedef struct FARHEADER2
56 {
57 UBYTE orders[256];
58 UBYTE numpat;
59 UBYTE snglen;
60 UBYTE loopto;
61 UWORD patsiz[256];
62 }
63 FARHEADER2;
64
65 typedef struct FARSAMPLE
66 {
67 CHAR samplename[32];
68 ULONG length;
69 UBYTE finetune;
70 UBYTE volume;
71 ULONG reppos;
72 ULONG repend;
73 UBYTE type;
74 UBYTE loop;
75 }
76 FARSAMPLE;
77
78 typedef struct FARNOTE
79 {
80 UBYTE note, ins, vol, eff;
81 }
82 FARNOTE;
83
84 /*========== Loader variables */
85
86 static CHAR FAR_Version[] = "Farandole";
87 static FARHEADER1 *mh1 = NULL;
88 static FARHEADER2 *mh2 = NULL;
89 static FARNOTE *pat = NULL;
90
91 static unsigned char FARSIG[4 + 3] =
92 {'F', 'A', 'R', 0xfe, 13, 10, 26};
93
94 /*========== Loader code */
95
96 static BOOL
FAR_Test(void)97 FAR_Test (void)
98 {
99 UBYTE id[47];
100
101 if (!_mm_read_UBYTES (id, 47, modreader))
102 return 0;
103 if ((memcmp (id, FARSIG, 4)) || (memcmp (id + 44, FARSIG + 4, 3)))
104 return 0;
105 return 1;
106 }
107
108 static BOOL
FAR_Init(void)109 FAR_Init (void)
110 {
111 if (!(mh1 = (FARHEADER1 *) _mm_malloc (sizeof (FARHEADER1))))
112 return 0;
113 if (!(mh2 = (FARHEADER2 *) _mm_malloc (sizeof (FARHEADER2))))
114 return 0;
115 if (!(pat = (FARNOTE *) _mm_malloc (256 * 16 * 4 * sizeof (FARNOTE))))
116 return 0;
117
118 return 1;
119 }
120
121 static void
FAR_Cleanup(void)122 FAR_Cleanup (void)
123 {
124 _mm_free (mh1);
125 _mm_free (mh2);
126 _mm_free (pat);
127 }
128
129 static UBYTE *
FAR_ConvertTrack(FARNOTE * n,int rows)130 FAR_ConvertTrack (FARNOTE * n, int rows)
131 {
132 int t, vibdepth = 1;
133
134 UniReset ();
135 for (t = 0; t < rows; t++)
136 {
137 if (n->note)
138 {
139 UniInstrument (n->ins);
140 UniNote (n->note + 3 * OCTAVE - 1);
141 }
142 if (n->vol & 0xf)
143 UniPTEffect (0xc, (n->vol & 0xf) << 2);
144 if (n->eff)
145 switch (n->eff >> 4)
146 {
147 case 0x3: /* porta to note */
148 UniPTEffect (0x3, (n->eff & 0xf) << 4);
149 break;
150 case 0x5: /* set vibrato depth */
151 vibdepth = n->eff & 0xf;
152 break;
153 case 0x6: /* vibrato */
154 UniPTEffect (0x4, ((n->eff & 0xf) << 4) | vibdepth);
155 break;
156 case 0x7: /* volume slide up */
157 UniPTEffect (0xa, (n->eff & 0xf) << 4);
158 break;
159 case 0x8: /* volume slide down */
160 UniPTEffect (0xa, n->eff & 0xf);
161 break;
162 case 0xf: /* set speed */
163 UniPTEffect (0xf, n->eff & 0xf);
164 break;
165
166 /* others not yet implemented */
167 default:
168 #ifdef MIKMOD_DEBUG
169 fprintf (stderr, "\rFAR: unsupported effect %02X\n", n->eff);
170 #endif
171 break;
172 }
173
174 UniNewline ();
175 n += 16;
176 }
177 return UniDup ();
178 }
179
180 static BOOL
FAR_Load(BOOL curious)181 FAR_Load (BOOL curious)
182 {
183 int t, u, tracks = 0;
184 SAMPLE *q;
185 FARSAMPLE s;
186 FARNOTE *crow;
187 UBYTE smap[8];
188
189 /* try to read module header (first part) */
190 _mm_read_UBYTES (mh1->id, 4, modreader);
191 _mm_read_SBYTES (mh1->songname, 40, modreader);
192 _mm_read_SBYTES (mh1->blah, 3, modreader);
193 mh1->headerlen = _mm_read_I_UWORD (modreader);
194 mh1->version = _mm_read_UBYTE (modreader);
195 _mm_read_UBYTES (mh1->onoff, 16, modreader);
196 _mm_read_UBYTES (mh1->edit1, 9, modreader);
197 mh1->speed = _mm_read_UBYTE (modreader);
198 _mm_read_UBYTES (mh1->panning, 16, modreader);
199 _mm_read_UBYTES (mh1->edit2, 4, modreader);
200 mh1->stlen = _mm_read_I_UWORD (modreader);
201
202 /* init modfile data */
203 of.modtype = strdup (FAR_Version);
204 of.songname = DupStr (mh1->songname, 40, 1);
205 of.numchn = 16;
206 of.initspeed = mh1->speed;
207 of.inittempo = 80;
208 of.reppos = 0;
209 for (t = 0; t < 16; t++)
210 of.panning[t] = mh1->panning[t] << 4;
211
212 /* read songtext into comment field */
213 if (mh1->stlen)
214 if (!ReadComment (mh1->stlen))
215 return 0;
216
217 /* try to read module header (second part) */
218 _mm_read_UBYTES (mh2->orders, 256, modreader);
219 mh2->numpat = _mm_read_UBYTE (modreader);
220 mh2->snglen = _mm_read_UBYTE (modreader);
221 mh2->loopto = _mm_read_UBYTE (modreader);
222 _mm_read_I_UWORDS (mh2->patsiz, 256, modreader);
223
224 of.numpos = mh2->snglen;
225 if (!AllocPositions (of.numpos))
226 return 0;
227 for (t = 0; t < of.numpos; t++)
228 {
229 if (mh2->orders[t] == 0xff)
230 break;
231 of.positions[t] = mh2->orders[t];
232 }
233
234 /* count number of patterns stored in file */
235 of.numpat = 0;
236 for (t = 0; t < 256; t++)
237 if (mh2->patsiz[t])
238 if ((t + 1) > of.numpat)
239 of.numpat = t + 1;
240 of.numtrk = of.numpat * of.numchn;
241
242 /* seek across eventual new data */
243 _mm_fseek (modreader, mh1->headerlen - (869 + mh1->stlen), SEEK_CUR);
244
245 /* alloc track and pattern structures */
246 if (!AllocTracks ())
247 return 0;
248 if (!AllocPatterns ())
249 return 0;
250
251 for (t = 0; t < of.numpat; t++)
252 {
253 UBYTE rows = 0;
254
255 memset (pat, 0, 256 * 16 * 4 * sizeof (FARNOTE));
256 if (mh2->patsiz[t])
257 {
258 rows = _mm_read_UBYTE (modreader);
259 /* tempo = */ _mm_read_UBYTE (modreader);
260
261 crow = pat;
262 /* file often allocates 64 rows even if there are less in pattern */
263 if (mh2->patsiz[t] < 2 + (rows * 16 * 4))
264 {
265 _mm_errno = MMERR_LOADING_PATTERN;
266 return 0;
267 }
268 for (u = (mh2->patsiz[t] - 2) / 4; u; u--, crow++)
269 {
270 crow->note = _mm_read_UBYTE (modreader);
271 crow->ins = _mm_read_UBYTE (modreader);
272 crow->vol = _mm_read_UBYTE (modreader);
273 crow->eff = _mm_read_UBYTE (modreader);
274 }
275
276 if (_mm_eof (modreader))
277 {
278 _mm_errno = MMERR_LOADING_PATTERN;
279 return 0;
280 }
281
282 crow = pat;
283 of.pattrows[t] = rows;
284 for (u = 16; u; u--, crow++)
285 if (!(of.tracks[tracks++] = FAR_ConvertTrack (crow, rows)))
286 {
287 _mm_errno = MMERR_LOADING_PATTERN;
288 return 0;
289 }
290 }
291 else
292 tracks += 16;
293 }
294
295 /* read sample map */
296 if (!_mm_read_UBYTES (smap, 8, modreader))
297 {
298 _mm_errno = MMERR_LOADING_HEADER;
299 return 0;
300 }
301
302 /* count number of samples used */
303 of.numins = 0;
304 for (t = 0; t < 64; t++)
305 if (smap[t >> 3] & (1 << (t & 7)))
306 of.numins = t + 1;
307 of.numsmp = of.numins;
308
309 /* alloc sample structs */
310 if (!AllocSamples ())
311 return 0;
312
313 q = of.samples;
314 for (t = 0; t < of.numsmp; t++)
315 {
316 q->speed = 8363;
317 q->flags = SF_SIGNED;
318 if (smap[t >> 3] & (1 << (t & 7)))
319 {
320 _mm_read_SBYTES (s.samplename, 32, modreader);
321 s.length = _mm_read_I_ULONG (modreader);
322 s.finetune = _mm_read_UBYTE (modreader);
323 s.volume = _mm_read_UBYTE (modreader);
324 s.reppos = _mm_read_I_ULONG (modreader);
325 s.repend = _mm_read_I_ULONG (modreader);
326 s.type = _mm_read_UBYTE (modreader);
327 s.loop = _mm_read_UBYTE (modreader);
328
329 q->samplename = DupStr (s.samplename, 32, 1);
330 q->length = s.length;
331 q->loopstart = s.reppos;
332 q->loopend = s.repend;
333 q->volume = s.volume << 2;
334
335 if (s.type & 1)
336 q->flags |= SF_16BITS;
337 if (s.loop & 8)
338 q->flags |= SF_LOOP;
339
340 q->seekpos = _mm_ftell (modreader);
341 _mm_fseek (modreader, q->length, SEEK_CUR);
342 }
343 else
344 q->samplename = DupStr (NULL, 0, 0);
345 q++;
346 }
347 return 1;
348 }
349
350 static CHAR *
FAR_LoadTitle(void)351 FAR_LoadTitle (void)
352 {
353 CHAR s[40];
354
355 _mm_fseek (modreader, 4, SEEK_SET);
356 if (!_mm_read_UBYTES (s, 40, modreader))
357 return NULL;
358
359 return (DupStr (s, 40, 1));
360 }
361
362 /*========== Loader information */
363
364 MLOADER load_far =
365 {
366 NULL,
367 "FAR",
368 "FAR (Farandole Composer)",
369 FAR_Init,
370 FAR_Test,
371 FAR_Load,
372 FAR_Cleanup,
373 FAR_LoadTitle
374 };
375
376 /* ex:set ts=4: */
377