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   Amiga MED 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 information */
38 
39 typedef struct MEDHEADER
40   {
41     ULONG id;
42     ULONG modlen;
43     ULONG pMEDSONG;		/* struct MEDSONG *song; */
44     UWORD psecnum;		/* for the player routine, MMD2 only */
45     UWORD pseq;			/*  "   "   "   " */
46     ULONG pMEDBLOCKP;		/* struct MMD0Block **blockarr; */
47     ULONG reserved1;
48     ULONG ppMedInstrHdr;		/* struct InstrHdr **smplarr; */
49     ULONG reserved2;
50     ULONG pMEDEXP;		/* struct MEDEXP *expdata; */
51     ULONG reserved3;
52     UWORD pstate;		/* some data for the player routine */
53     UWORD pblock;
54     UWORD pline;
55     UWORD pseqnum;
56     SWORD actplayline;
57     UBYTE counter;
58     UBYTE extra_songs;		/* number of songs - 1 */
59   }
60 MEDHEADER;
61 
62 typedef struct MEDSAMPLE
63   {
64     UWORD rep, replen;		/* offs: 0(s), 2(s) */
65     UBYTE midich;		/* offs: 4(s) */
66     UBYTE midipreset;		/* offs: 5(s) */
67     UBYTE svol;			/* offs: 6(s) */
68     SBYTE strans;		/* offs: 7(s) */
69   }
70 MEDSAMPLE;
71 
72 typedef struct MEDSONG
73   {
74     MEDSAMPLE sample[63];	/* 63 * 8 bytes = 504 bytes */
75     UWORD numblocks;		/* offs: 504 */
76     UWORD songlen;		/* offs: 506 */
77     UBYTE playseq[256];		/* offs: 508 */
78     UWORD deftempo;		/* offs: 764 */
79     SBYTE playtransp;		/* offs: 766 */
80     UBYTE flags;		/* offs: 767 */
81     UBYTE flags2;		/* offs: 768 */
82     UBYTE tempo2;		/* offs: 769 */
83     UBYTE trkvol[16];		/* offs: 770 */
84     UBYTE mastervol;		/* offs: 786 */
85     UBYTE numsamples;		/* offs: 787 */
86   }
87 MEDSONG;
88 
89 typedef struct MEDEXP
90   {
91     ULONG nextmod;		/* pointer to next module */
92     ULONG exp_smp;		/* pointer to InstrExt array */
93     UWORD s_ext_entries;
94     UWORD s_ext_entrsz;
95     ULONG annotxt;		/* pointer to annotation text */
96     ULONG annolen;
97     ULONG iinfo;		/* pointer to InstrInfo array */
98     UWORD i_ext_entries;
99     UWORD i_ext_entrsz;
100     ULONG jumpmask;
101     ULONG rgbtable;
102     ULONG channelsplit;
103     ULONG n_info;
104     ULONG songname;		/* pointer to songname */
105     ULONG songnamelen;
106     ULONG dumps;
107     ULONG reserved2[7];
108   }
109 MEDEXP;
110 
111 typedef struct MMD0NOTE
112   {
113     UBYTE a, b, c;
114   }
115 MMD0NOTE;
116 
117 typedef struct MMD1NOTE
118   {
119     UBYTE a, b, c, d;
120   }
121 MMD1NOTE;
122 
123 typedef struct MEDINSTHEADER
124   {
125     ULONG length;
126     SWORD type;
127     /* Followed by actual data */
128   }
129 MEDINSTHEADER;
130 
131 typedef struct MEDINSTEXT
132   {
133     UBYTE hold;
134     UBYTE decay;
135     UBYTE suppress_midi_off;
136     SBYTE finetune;
137   }
138 MEDINSTEXT;
139 
140 typedef struct MEDINSTINFO
141   {
142     UBYTE name[40];
143   }
144 MEDINSTINFO;
145 
146 /*========== Loader variables */
147 
148 #define MMD0_string 0x4D4D4430
149 #define MMD1_string 0x4D4D4431
150 
151 static MEDHEADER *mh = NULL;
152 static MEDSONG *ms = NULL;
153 static MEDEXP *me = NULL;
154 static ULONG *ba = NULL;
155 static MMD0NOTE *mmd0pat = NULL;
156 static MMD1NOTE *mmd1pat = NULL;
157 
158 static BOOL decimalvolumes;
159 static BOOL bpmtempos;
160 
161 #define d0note(row,col) mmd0pat[((row)*(UWORD)of.numchn)+(col)]
162 #define d1note(row,col) mmd1pat[((row)*(UWORD)of.numchn)+(col)]
163 
164 static CHAR MED_Version[] = "OctaMED (MMDx)";
165 
166 /*========== Loader code */
167 
168 static BOOL
MED_Test(void)169 MED_Test (void)
170 {
171   UBYTE id[4];
172 
173   if (!_mm_read_UBYTES (id, 4, modreader))
174     return 0;
175   if ((!memcmp (id, "MMD0", 4)) || (!memcmp (id, "MMD1", 4)))
176     return 1;
177   return 0;
178 }
179 
180 static BOOL
MED_Init(void)181 MED_Init (void)
182 {
183   if (!(me = (MEDEXP *) _mm_malloc (sizeof (MEDEXP))))
184     return 0;
185   if (!(mh = (MEDHEADER *) _mm_malloc (sizeof (MEDHEADER))))
186     return 0;
187   if (!(ms = (MEDSONG *) _mm_malloc (sizeof (MEDSONG))))
188     return 0;
189   return 1;
190 }
191 
192 static void
MED_Cleanup(void)193 MED_Cleanup (void)
194 {
195   _mm_free (me);
196   _mm_free (mh);
197   _mm_free (ms);
198   _mm_free (ba);
199   _mm_free (mmd0pat);
200   _mm_free (mmd1pat);
201 }
202 
203 static void
EffectCvt(UBYTE eff,UBYTE dat)204 EffectCvt (UBYTE eff, UBYTE dat)
205 {
206   switch (eff)
207     {
208       /* 0x0 0x1 0x2 0x3 0x4 PT effects */
209     case 0x5:			/* PT vibrato with speed/depth nibbles swapped */
210       UniPTEffect (0x4, (dat >> 4) | ((dat & 0xf) << 4));
211       break;
212       /* 0x6 0x7 not used */
213     case 0x6:
214     case 0x7:
215       break;
216     case 0x8:			/* midi hold/decay */
217       break;
218     case 0x9:
219       if (bpmtempos)
220 	{
221 	  if (!dat)
222 	    dat = of.initspeed;
223 	  UniEffect (UNI_S3MEFFECTA, dat);
224 	}
225       else
226 	{
227 	  if (dat <= 0x20)
228 	    {
229 	      if (!dat)
230 		dat = of.initspeed;
231 	      else
232 		dat /= 4;
233 	      UniPTEffect (0xf, dat);
234 	    }
235 	  else
236 	    UniEffect (UNI_MEDSPEED, ((UWORD) dat * 125) / (33 * 4));
237 	}
238       break;
239       /* 0xa 0xb PT effects */
240     case 0xc:
241       if (decimalvolumes)
242 	dat = (dat >> 4) * 10 + (dat & 0xf);
243       UniPTEffect (0xc, dat);
244       break;
245     case 0xd:			/* same as PT volslide */
246       UniPTEffect (0xa, dat);
247       break;
248     case 0xe:			/* synth jmp - midi */
249       break;
250     case 0xf:
251       switch (dat)
252 	{
253 	case 0:		/* patternbreak */
254 	  UniPTEffect (0xd, 0);
255 	  break;
256 	case 0xf1:		/* play note twice */
257 	  UniWriteByte (UNI_MEDEFFECTF1);
258 	  break;
259 	case 0xf2:		/* delay note */
260 	  UniWriteByte (UNI_MEDEFFECTF2);
261 	  break;
262 	case 0xf3:		/* play note three times */
263 	  UniWriteByte (UNI_MEDEFFECTF3);
264 	  break;
265 	case 0xfe:		/* stop playing */
266 	  UniPTEffect (0xb, of.numpat);
267 	  break;
268 	case 0xff:		/* note cut */
269 	  UniPTEffect (0xc, 0);
270 	  break;
271 	default:
272 	  if (dat <= 10)
273 	    UniPTEffect (0xf, dat);
274 	  else if (dat <= 240)
275 	    {
276 	      if (bpmtempos)
277 		UniPTEffect (0xf, (dat < 32) ? 32 : dat);
278 	      else
279 		UniEffect (UNI_MEDSPEED, ((UWORD) dat * 125) / 33);
280 	    }
281 	}
282       break;
283     default:			/* all normal PT effects are handled here */
284       UniPTEffect (eff, dat);
285       break;
286     }
287 }
288 
289 static UBYTE *
MED_Convert1(int count,int col)290 MED_Convert1 (int count, int col)
291 {
292   int t;
293   UBYTE inst, note, eff, dat;
294   MMD1NOTE *n;
295 
296   UniReset ();
297   for (t = 0; t < count; t++)
298     {
299       n = &d1note (t, col);
300 
301       note = n->a & 0x7f;
302       inst = n->b & 0x3f;
303       eff = n->c & 0xf;
304       dat = n->d;
305 
306       if (inst)
307 	UniInstrument (inst - 1);
308       if (note)
309 	UniNote (note + 3 * OCTAVE - 1);
310       EffectCvt (eff, dat);
311       UniNewline ();
312     }
313   return UniDup ();
314 }
315 
316 static UBYTE *
MED_Convert0(int count,int col)317 MED_Convert0 (int count, int col)
318 {
319   int t;
320   UBYTE a, b, inst, note, eff, dat;
321   MMD0NOTE *n;
322 
323   UniReset ();
324   for (t = 0; t < count; t++)
325     {
326       n = &d0note (t, col);
327       a = n->a;
328       b = n->b;
329 
330       note = a & 0x3f;
331       a >>= 6;
332       a = ((a & 1) << 1) | (a >> 1);
333       inst = (b >> 4) | (a << 4);
334       eff = b & 0xf;
335       dat = n->c;
336 
337       if (inst)
338 	UniInstrument (inst - 1);
339       if (note)
340 	UniNote (note + 3 * OCTAVE - 1);
341       EffectCvt (eff, dat);
342       UniNewline ();
343     }
344   return UniDup ();
345 }
346 
347 static BOOL
LoadMMD0Patterns(void)348 LoadMMD0Patterns (void)
349 {
350   int t, row, col;
351   UWORD numtracks, numlines, maxlines = 0, track = 0;
352   MMD0NOTE *mmdp;
353 
354   /* first, scan patterns to see how many channels are used */
355   for (t = 0; t < of.numpat; t++)
356     {
357       _mm_fseek (modreader, ba[t], SEEK_SET);
358       numtracks = _mm_read_UBYTE (modreader);
359       numlines = _mm_read_UBYTE (modreader);
360 
361       if (numtracks > of.numchn)
362 	of.numchn = numtracks;
363       if (numlines > maxlines)
364 	maxlines = numlines;
365     }
366 
367   of.numtrk = of.numpat * of.numchn;
368   if (!AllocTracks ())
369     return 0;
370   if (!AllocPatterns ())
371     return 0;
372 
373   if (!(mmd0pat = (MMD0NOTE *) _mm_calloc (of.numchn * (maxlines + 1), sizeof (MMD0NOTE))))
374     return 0;
375 
376   /* second read: read and convert patterns */
377   for (t = 0; t < of.numpat; t++)
378     {
379       _mm_fseek (modreader, ba[t], SEEK_SET);
380       numtracks = _mm_read_UBYTE (modreader);
381       numlines = _mm_read_UBYTE (modreader);
382 
383       of.pattrows[t] = ++numlines;
384       memset (mmdp = mmd0pat, 0, of.numchn * maxlines * sizeof (MMD0NOTE));
385       for (row = numlines; row; row--)
386 	{
387 	  for (col = numtracks; col; col--, mmdp++)
388 	    {
389 	      mmdp->a = _mm_read_UBYTE (modreader);
390 	      mmdp->b = _mm_read_UBYTE (modreader);
391 	      mmdp->c = _mm_read_UBYTE (modreader);
392 	    }
393 	}
394 
395       for (col = 0; col < of.numchn; col++)
396 	of.tracks[track++] = MED_Convert0 (numlines, col);
397     }
398   return 1;
399 }
400 
401 static BOOL
LoadMMD1Patterns(void)402 LoadMMD1Patterns (void)
403 {
404   int t, row, col;
405   UWORD numtracks, numlines, maxlines = 0, track = 0;
406   MMD1NOTE *mmdp;
407 
408   /* first, scan patterns to see how many channels are used */
409   for (t = 0; t < of.numpat; t++)
410     {
411       _mm_fseek (modreader, ba[t], SEEK_SET);
412       numtracks = _mm_read_M_UWORD (modreader);
413       numlines = _mm_read_M_UWORD (modreader);
414       if (numtracks > of.numchn)
415 	of.numchn = numtracks;
416       if (numlines > maxlines)
417 	maxlines = numlines;
418     }
419 
420   of.numtrk = of.numpat * of.numchn;
421   if (!AllocTracks ())
422     return 0;
423   if (!AllocPatterns ())
424     return 0;
425 
426   if (!(mmd1pat = (MMD1NOTE *) _mm_calloc (of.numchn * (maxlines + 1), sizeof (MMD1NOTE))))
427     return 0;
428 
429   /* second read: really read and convert patterns */
430   for (t = 0; t < of.numpat; t++)
431     {
432       _mm_fseek (modreader, ba[t], SEEK_SET);
433       numtracks = _mm_read_M_UWORD (modreader);
434       numlines = _mm_read_M_UWORD (modreader);
435 
436       _mm_fseek (modreader, sizeof (ULONG), SEEK_CUR);
437       of.pattrows[t] = ++numlines;
438       memset (mmdp = mmd1pat, 0, of.numchn * maxlines * sizeof (MMD1NOTE));
439 
440       for (row = numlines; row; row--)
441 	{
442 	  for (col = numtracks; col; col--, mmdp++)
443 	    {
444 	      mmdp->a = _mm_read_UBYTE (modreader);
445 	      mmdp->b = _mm_read_UBYTE (modreader);
446 	      mmdp->c = _mm_read_UBYTE (modreader);
447 	      mmdp->d = _mm_read_UBYTE (modreader);
448 	    }
449 	}
450 
451       for (col = 0; col < of.numchn; col++)
452 	of.tracks[track++] = MED_Convert1 (numlines, col);
453     }
454   return 1;
455 }
456 
457 static BOOL
MED_Load(BOOL curious)458 MED_Load (BOOL curious)
459 {
460   int t;
461   ULONG sa[64];
462   MEDINSTHEADER s;
463   SAMPLE *q;
464   MEDSAMPLE *mss;
465 
466   /* try to read module header */
467   mh->id = _mm_read_M_ULONG (modreader);
468   mh->modlen = _mm_read_M_ULONG (modreader);
469   mh->pMEDSONG = _mm_read_M_ULONG (modreader);
470   mh->psecnum = _mm_read_M_UWORD (modreader);
471   mh->pseq = _mm_read_M_UWORD (modreader);
472   mh->pMEDBLOCKP = _mm_read_M_ULONG (modreader);
473   mh->reserved1 = _mm_read_M_ULONG (modreader);
474   mh->ppMedInstrHdr = _mm_read_M_ULONG (modreader);
475   mh->reserved2 = _mm_read_M_ULONG (modreader);
476   mh->pMEDEXP = _mm_read_M_ULONG (modreader);
477   mh->reserved3 = _mm_read_M_ULONG (modreader);
478   mh->pstate = _mm_read_M_UWORD (modreader);
479   mh->pblock = _mm_read_M_UWORD (modreader);
480   mh->pline = _mm_read_M_UWORD (modreader);
481   mh->pseqnum = _mm_read_M_UWORD (modreader);
482   mh->actplayline = _mm_read_M_SWORD (modreader);
483   mh->counter = _mm_read_UBYTE (modreader);
484   mh->extra_songs = _mm_read_UBYTE (modreader);
485 
486   /* Seek to MEDSONG struct */
487   _mm_fseek (modreader, mh->pMEDSONG, SEEK_SET);
488 
489   /* Load the MMD0 Song Header */
490   mss = ms->sample;		/* load the sample data first */
491   for (t = 63; t; t--, mss++)
492     {
493       mss->rep = _mm_read_M_UWORD (modreader);
494       mss->replen = _mm_read_M_UWORD (modreader);
495       mss->midich = _mm_read_UBYTE (modreader);
496       mss->midipreset = _mm_read_UBYTE (modreader);
497       mss->svol = _mm_read_UBYTE (modreader);
498       mss->strans = _mm_read_SBYTE (modreader);
499     }
500 
501   ms->numblocks = _mm_read_M_UWORD (modreader);
502   ms->songlen = _mm_read_M_UWORD (modreader);
503   _mm_read_UBYTES (ms->playseq, 256, modreader);
504   ms->deftempo = _mm_read_M_UWORD (modreader);
505   ms->playtransp = _mm_read_SBYTE (modreader);
506   ms->flags = _mm_read_UBYTE (modreader);
507   ms->flags2 = _mm_read_UBYTE (modreader);
508   ms->tempo2 = _mm_read_UBYTE (modreader);
509   _mm_read_UBYTES (ms->trkvol, 16, modreader);
510   ms->mastervol = _mm_read_UBYTE (modreader);
511   ms->numsamples = _mm_read_UBYTE (modreader);
512 
513   /* check for a bad header */
514   if (_mm_eof (modreader))
515     {
516       _mm_errno = MMERR_LOADING_HEADER;
517       return 0;
518     }
519 
520   /* load extension structure */
521   if (mh->pMEDEXP)
522     {
523       _mm_fseek (modreader, mh->pMEDEXP, SEEK_SET);
524       me->nextmod = _mm_read_M_ULONG (modreader);
525       me->exp_smp = _mm_read_M_ULONG (modreader);
526       me->s_ext_entries = _mm_read_M_UWORD (modreader);
527       me->s_ext_entrsz = _mm_read_M_UWORD (modreader);
528       me->annotxt = _mm_read_M_ULONG (modreader);
529       me->annolen = _mm_read_M_ULONG (modreader);
530       me->iinfo = _mm_read_M_ULONG (modreader);
531       me->i_ext_entries = _mm_read_M_UWORD (modreader);
532       me->i_ext_entrsz = _mm_read_M_UWORD (modreader);
533       me->jumpmask = _mm_read_M_ULONG (modreader);
534       me->rgbtable = _mm_read_M_ULONG (modreader);
535       me->channelsplit = _mm_read_M_ULONG (modreader);
536       me->n_info = _mm_read_M_ULONG (modreader);
537       me->songname = _mm_read_M_ULONG (modreader);
538       me->songnamelen = _mm_read_M_ULONG (modreader);
539       me->dumps = _mm_read_M_ULONG (modreader);
540     }
541 
542   /* seek to and read the samplepointer array */
543   _mm_fseek (modreader, mh->ppMedInstrHdr, SEEK_SET);
544   if (!_mm_read_M_ULONGS (sa, ms->numsamples, modreader))
545     {
546       _mm_errno = MMERR_LOADING_HEADER;
547       return 0;
548     }
549 
550   /* alloc and read the blockpointer array */
551   if (!(ba = (ULONG *) _mm_calloc (ms->numblocks, sizeof (ULONG))))
552     return 0;
553   _mm_fseek (modreader, mh->pMEDBLOCKP, SEEK_SET);
554   if (!_mm_read_M_ULONGS (ba, ms->numblocks, modreader))
555     {
556       _mm_errno = MMERR_LOADING_HEADER;
557       return 0;
558     }
559 
560   /* copy song positions */
561   if (!AllocPositions (ms->songlen))
562     return 0;
563   for (t = 0; t < ms->songlen; t++)
564     of.positions[t] = ms->playseq[t];
565 
566   decimalvolumes = (ms->flags & 0x10) ? 0 : 1;
567   bpmtempos = (ms->flags2 & 0x20) ? 1 : 0;
568 
569   if (bpmtempos)
570     {
571       int bpmlen = (ms->flags2 & 0x1f) + 1;
572       of.initspeed = ms->tempo2;
573       of.inittempo = ms->deftempo * bpmlen / 4;
574 
575       if (bpmlen != 4)
576 	{
577 	  /* Let's do some math : compute GCD of BPM beat length and speed */
578 	  int a, b;
579 
580 	  a = bpmlen;
581 	  b = ms->tempo2;
582 
583 	  if (a > b)
584 	    {
585 	      t = b;
586 	      b = a;
587 	      a = t;
588 	    }
589 	  while ((a != b) && (a))
590 	    {
591 	      t = a;
592 	      a = b - a;
593 	      b = t;
594 	      if (a > b)
595 		{
596 		  t = b;
597 		  b = a;
598 		  a = t;
599 		}
600 	    }
601 
602 	  of.initspeed /= b;
603 	  of.inittempo = ms->deftempo * bpmlen / (4 * b);
604 	}
605     }
606   else
607     {
608       of.initspeed = ms->tempo2;
609       of.inittempo = ms->deftempo ? ((UWORD) ms->deftempo * 125) / 33 : 128;
610       if ((ms->deftempo <= 10) && (ms->deftempo))
611 	of.inittempo = (of.inittempo * 33) / 6;
612       of.flags |= UF_HIGHBPM;
613     }
614   MED_Version[12] = mh->id;
615   of.modtype = strdup (MED_Version);
616   of.numchn = 0;		/* will be counted later */
617   of.numpat = ms->numblocks;
618   of.numpos = ms->songlen;
619   of.numins = ms->numsamples;
620   of.numsmp = of.numins;
621   of.reppos = 0;
622   if ((mh->pMEDEXP) && (me->songname) && (me->songnamelen))
623     {
624       char *name;
625 
626       _mm_fseek (modreader, me->songname, SEEK_SET);
627       name = _mm_malloc (me->songnamelen);
628       _mm_read_UBYTES (name, me->songnamelen, modreader);
629       of.songname = DupStr (name, me->songnamelen, 1);
630       free (name);
631     }
632   else
633     of.songname = DupStr (NULL, 0, 0);
634   if ((mh->pMEDEXP) && (me->annotxt) && (me->annolen))
635     {
636       _mm_fseek (modreader, me->annotxt, SEEK_SET);
637       ReadComment (me->annolen);
638     }
639 
640   if (!AllocSamples ())
641     return 0;
642   q = of.samples;
643   for (t = 0; t < of.numins; t++)
644     {
645       q->flags = SF_SIGNED;
646       q->volume = 64;
647       if (sa[t])
648 	{
649 	  _mm_fseek (modreader, sa[t], SEEK_SET);
650 	  s.length = _mm_read_M_ULONG (modreader);
651 	  s.type = _mm_read_M_SWORD (modreader);
652 
653 	  if (s.type)
654 	    {
655 #ifdef MIKMOD_DEBUG
656 	      fputs ("\rNon-sample instruments not supported in MED loader yet\n", stderr);
657 #endif
658 	      if (!curious)
659 		{
660 		  _mm_errno = MMERR_MED_SYNTHSAMPLES;
661 		  return 0;
662 		}
663 	      s.length = 0;
664 	    }
665 
666 	  if (_mm_eof (modreader))
667 	    {
668 	      _mm_errno = MMERR_LOADING_SAMPLEINFO;
669 	      return 0;
670 	    }
671 
672 	  q->length = s.length;
673 	  q->seekpos = _mm_ftell (modreader);
674 	  q->loopstart = ms->sample[t].rep << 1;
675 	  q->loopend = q->loopstart + (ms->sample[t].replen << 1);
676 
677 	  if (ms->sample[t].replen > 1)
678 	    q->flags |= SF_LOOP;
679 
680 	  /* don't load sample if length>='MMD0'...
681 	     such kluges make libmikmod's code unique !!! */
682 	  if (q->length >= MMD0_string)
683 	    q->length = 0;
684 	}
685       else
686 	q->length = 0;
687 
688       if ((mh->pMEDEXP) && (me->exp_smp) &&
689 	  (t < me->s_ext_entries) && (me->s_ext_entrsz >= 4))
690 	{
691 	  MEDINSTEXT ie;
692 
693 	  _mm_fseek (modreader, me->exp_smp + t * me->s_ext_entrsz, SEEK_SET);
694 	  ie.hold = _mm_read_UBYTE (modreader);
695 	  ie.decay = _mm_read_UBYTE (modreader);
696 	  ie.suppress_midi_off = _mm_read_UBYTE (modreader);
697 	  ie.finetune = _mm_read_SBYTE (modreader);
698 
699 	  q->speed = finetune[ie.finetune & 0xf];
700 	}
701       else
702 	q->speed = 8363;
703 
704       if ((mh->pMEDEXP) && (me->iinfo) &&
705 	  (t < me->i_ext_entries) && (me->i_ext_entrsz >= 40))
706 	{
707 	  MEDINSTINFO ii;
708 
709 	  _mm_fseek (modreader, me->iinfo + t * me->i_ext_entrsz, SEEK_SET);
710 	  _mm_read_UBYTES (ii.name, 40, modreader);
711 	  q->samplename = DupStr ((CHAR *) ii.name, 40, 1);
712 	}
713       else
714 	q->samplename = NULL;
715 
716       q++;
717     }
718 
719   if (mh->id == MMD0_string)
720     {
721       if (!LoadMMD0Patterns ())
722 	{
723 	  _mm_errno = MMERR_LOADING_PATTERN;
724 	  return 0;
725 	}
726     }
727   else if (mh->id == MMD1_string)
728     {
729       if (!LoadMMD1Patterns ())
730 	{
731 	  _mm_errno = MMERR_LOADING_PATTERN;
732 	  return 0;
733 	}
734     }
735   else
736     {
737       _mm_errno = MMERR_NOT_A_MODULE;
738       return 0;
739     }
740   return 1;
741 }
742 
743 /*========== Loader information */
744 
745 MLOADER load_med =
746 {
747   NULL,
748   "MED",
749   "MED (OctaMED)",
750   MED_Init,
751   MED_Test,
752   MED_Load,
753   MED_Cleanup,
754   NULL
755 };
756 
757 /* ex:set ts=4: */
758