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 
AMF_Test(void)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
97 FAR_Test (void)
98 {
99   UBYTE id[47];
100 
101   if (!_mm_read_UBYTES (id, 47, modreader))
AMF_Init(void)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
109 FAR_Init (void)
110 {
111   if (!(mh1 = (FARHEADER1 *) _mm_malloc (sizeof (FARHEADER1))))
112     return 0;
AMF_Cleanup(void)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 }
AMF_UnpackTrack(URL modreader)120 
121 static void
122 FAR_Cleanup (void)
123 {
124   _mm_free (mh1);
125   _mm_free (mh2);
126   _mm_free (pat);
127 }
128 
129 static UBYTE *
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
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);
AMF_ConvertTrack(void)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 *
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 {
AMF_Load(BOOL curious)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