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