A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
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 Amiga MED module loader
24
25==============================================================================*/
26
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#endif
30
31#ifdef HAVE_UNISTD_H
32#include <unistd.h>
33#endif
34
35#include <stdio.h>
36#ifdef HAVE_MEMORY_H
37#include <memory.h>
38#endif
39#include <string.h>
40
41#include "mikmod_internals.h"
42
43#ifdef SUNOS
44extern int fprintf(FILE *, const char *, ...);
45#endif
46
47/*========== Module information */
48
49#define MEDNOTECNT 120
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
140enum MEDINSTTYPE {
141 INST_HYBRID = -2,
142 INST_SYNTH = -1,
143 INST_SAMPLE = 0,
144 INST_IFFOCT_5 = 1,
145 INST_IFFOCT_3 = 2,
146 INST_IFFOCT_2 = 3,
147 INST_IFFOCT_4 = 4,
148 INST_IFFOCT_6 = 5,
149 INST_IFFOCT_7 = 6,
150 INST_EXTSAMPLE = 7
151};
152
153/*========== Loader variables */
154
155#define MMD0_string 0x4D4D4430
156#define MMD1_string 0x4D4D4431
157
158static MEDHEADER *mh = NULL;
159static MEDSONG *ms = NULL;
160static MEDEXP *me = NULL;
161static ULONG *ba = NULL;
162static MMD0NOTE *mmd0pat = NULL;
163static MMD1NOTE *mmd1pat = NULL;
164
165static UBYTE medversion;
166static int decimalvolumes;
167static int bpmtempos;
168static int is8channel;
169static UWORD rowsperbeat;
170
171#define d0note(row,col) mmd0pat[((row)*(UWORD)of.numchn)+(col)]
172#define d1note(row,col) mmd1pat[((row)*(UWORD)of.numchn)+(col)]
173
174static CHAR MED_Version[] = "OctaMED (MMDx)";
175
176/*========== Loader code */
177
178static int MED_Test(void)
179{
180 UBYTE id[4];
181
182 if (!_mm_read_UBYTES(id, 4, modreader))
183 return 0;
184 if ((!memcmp(id, "MMD0", 4)) || (!memcmp(id, "MMD1", 4)))
185 return 1;
186 return 0;
187}
188
189static int MED_Init(void)
190{
191 if (!(me = (MEDEXP *)MikMod_malloc(sizeof(MEDEXP))))
192 return 0;
193 if (!(mh = (MEDHEADER *)MikMod_malloc(sizeof(MEDHEADER))))
194 return 0;
195 if (!(ms = (MEDSONG *)MikMod_malloc(sizeof(MEDSONG))))
196 return 0;
197 return 1;
198}
199
200static void MED_Cleanup(void)
201{
202 MikMod_free(me);
203 MikMod_free(mh);
204 MikMod_free(ms);
205 MikMod_free(ba);
206 MikMod_free(mmd0pat);
207 MikMod_free(mmd1pat);
208 me = NULL;
209 mh = NULL;
210 ms = NULL;
211 ba = NULL;
212 mmd0pat = NULL;
213 mmd1pat = NULL;
214}
215
216static UWORD MED_ConvertTempo(UWORD tempo)
217{
218 /* MED tempos 1-10 are compatibility tempos that are converted to different values.
219 These were determined by testing with OctaMED 2.00 and roughly correspond to the
220 formula: (195 + speed/2) / speed. Despite being "tracker compatible" these really
221 are supposed to change the tempo and NOT the speed. These are tempo-mode only. */
222 static const UBYTE tempocompat[11] =
223 {
224 0, 195, 97, 65, 49, 39, 32, 28, 24, 22, 20
225 };
226
227 /* MEDs with 8 channels do something completely different with their tempos.
228 This behavior completely overrides normal timing when it is enabled.
229 NOTE: the tempos used for this are directly from OctaMED Soundstudio 2, but
230 in older versions the playback speeds differed slightly between NTSC and PAL.
231 This table seems to have been intended to be a compromise between the two.*/
232 static const UBYTE tempo8channel[11] =
233 {
234 0, 179, 164, 152, 141, 131, 123, 116, 110, 104, 99
235 };
236
237 ULONG result;
238
239 if (is8channel) {
240 tempo = tempo < 10 ? tempo : 10;
241 return tempo8channel[tempo];
242 }
243
244 if (bpmtempos) {
245 /* Convert MED BPM into ProTracker-compatible BPM. All that really needs to be done
246 here is the BPM needs to be multiplied by (rows per beat)/(PT rows per beat = 4).
247 BPM mode doesn't have compatibility tempos like tempo mode but OctaMED does
248 something unusual with BPM<=2 that was found in electrosound 64.med. */
249 result = (tempo > 2) ? ((ULONG)tempo * rowsperbeat + 2) / 4 : 125;
250 } else {
251 if (tempo >= 1 && tempo <= 10)
252 tempo = tempocompat[tempo];
253
254 /* Convert MED tempo into ProTracker-compatble BPM. */
255 result = ((ULONG)tempo * 125) / 33;
256 }
257
258 return result < 65535 ? result : 65535;
259}
260
261static void EffectCvt(UBYTE note, UBYTE eff, UBYTE dat)
262{
263 switch (eff) {
264 /* 0x0: arpeggio */
265 case 0x1: /* portamento up (PT compatible, ignore 0) */
266 if (dat)
267 UniPTEffect(0x1, dat);
268 break;
269 case 0x2: /* portamento down (PT compatible, ignore 0) */
270 if (dat)
271 UniPTEffect(0x2, dat);
272 break;
273 /* 0x3: tone portamento */
274 case 0x4: /* vibrato (~2x the speed/depth of PT vibrato) */
275 UniWriteByte(UNI_MEDEFFECT_VIB);
276 UniWriteByte((dat & 0xf0) >> 3);
277 UniWriteByte((dat & 0x0f) << 1);
278 break;
279 case 0x5: /* tone portamento + volslide (MMD0: old vibrato) */
280 if (medversion == 0) {
281 /* Approximate conversion, probably wrong.
282 The entire param is depth and the rate is fixed. */
283 UniWriteByte(UNI_MEDEFFECT_VIB);
284 UniWriteByte(0x16);
285 UniWriteByte((dat + 3) >> 2);
286 break;
287 }
288 UniPTEffect(eff, dat);
289 break;
290 /* 0x6: vibrato + volslide */
291 /* 0x7: tremolo */
292 case 0x8: /* set hold/decay (FIXME- hold/decay not implemented) */
293 break;
294 case 0x9: /* set speed */
295 /* TODO: Rarely MED modules request values of 0x00 or >0x20. In most Amiga versions
296 these behave as speed=(param & 0x1F) ? (param & 0x1F) : 32. From Soundstudio 2
297 up, these have different behavior. Since the docs/UI insist you shouldn't use
298 these values and not many modules use these, just ignore them for now. */
299 if (dat >= 0x01 && dat <= 0x20) {
300 UniEffect(UNI_S3MEFFECTA, dat);
301 }
302 break;
303 /* 0xa: volslide */
304 /* 0xb: position jump */
305 case 0xc:
306 if (decimalvolumes)
307 dat = (dat >> 4) * 10 + (dat & 0xf);
308 UniPTEffect(0xc, dat);
309 break;
310 case 0xa:
311 case 0xd: /* same as PT volslide */
312 /* if both nibbles are set, a slide up is performed. */
313 if ((dat & 0xf) && (dat & 0xf0))
314 dat &= 0xf0;
315 UniPTEffect(0xa, dat);
316 break;
317 case 0xe: /* synth jump (FIXME- synth instruments not implemented) */
318 break;
319 case 0xf:
320 switch (dat) {
321 case 0: /* patternbreak */
322 UniPTEffect(0xd, 0);
323 break;
324 case 0xf1: /* play note twice */
325 /* Note: OctaMED 6.00d and up will not play FF1/FF3 effects when
326 they are used on a line without a note. Since MMD2/MMD3 support is
327 theoretical at this point, allow these unconditionally for now. */
328 UniWriteByte(UNI_MEDEFFECTF1);
329 break;
330 case 0xf2: /* delay note */
331 UniWriteByte(UNI_MEDEFFECTF2);
332 break;
333 case 0xf3: /* play note three times */
334 UniWriteByte(UNI_MEDEFFECTF3);
335 break;
336 case 0xf8: /* hardware filter off */
337 UniPTEffect(0xe, 0x01);
338 break;
339 case 0xf9: /* hardware filter on */
340 UniPTEffect(0xe, 0x00);
341 break;
342 case 0xfd: /* set pitch */
343 UniWriteByte(UNI_MEDEFFECT_FD);
344 break;
345 case 0xfe: /* stop playing */
346 UniPTEffect(0xb, of.numpat);
347 break;
348 case 0xff: /* note cut */
349 UniPTEffect(0xc, 0);
350 break;
351 default:
352 if (dat <= 240)
353 UniEffect(UNI_MEDSPEED, MED_ConvertTempo(dat));
354 }
355 break;
356 case 0x11: /* fine portamento up */
357 /* fine portamento of 0 does nothing. */
358 if (dat)
359 UniEffect(UNI_XMEFFECTE1, dat);
360 break;
361 case 0x12: /* fine portamento down */
362 if (dat)
363 UniEffect(UNI_XMEFFECTE2, dat);
364 break;
365 case 0x14: /* vibrato (PT compatible depth, ~2x speed) */
366 UniWriteByte(UNI_MEDEFFECT_VIB);
367 UniWriteByte((dat & 0xf0) >> 3);
368 UniWriteByte((dat & 0x0f));
369 break;
370 case 0x15: /* set finetune */
371 /* Valid values are 0x0 to 0x7 and 0xF8 to 0xFF. */
372 if (dat <= 0x7 || dat >= 0xF8)
373 UniPTEffect(0xe, 0x50 | (dat & 0xF));
374 break;
375 case 0x16: /* loop */
376 UniEffect(UNI_MEDEFFECT_16, dat);
377 break;
378 case 0x18: /* cut note */
379 UniEffect(UNI_MEDEFFECT_18, dat);
380 break;
381 case 0x19: /* sample offset */
382 UniPTEffect(0x9, dat);
383 break;
384 case 0x1a: /* fine volslide up */
385 /* volslide of 0 does nothing. */
386 if (dat)
387 UniEffect(UNI_XMEFFECTEA, dat);
388 break;
389 case 0x1b: /* fine volslide down */
390 if (dat)
391 UniEffect(UNI_XMEFFECTEB, dat);
392 break;
393 case 0x1d: /* pattern break */
394 UniPTEffect(0xd, dat);
395 break;
396 case 0x1e: /* pattern delay */
397 UniEffect(UNI_MEDEFFECT_1E, dat);
398 break;
399 case 0x1f: /* combined delay-retrigger */
400 /* This effect does nothing on lines without a note. */
401 if (note)
402 UniEffect(UNI_MEDEFFECT_1F, dat);
403 break;
404 default:
405 if (eff < 0x10)
406 UniPTEffect(eff, dat);
407#ifdef MIKMOD_DEBUG
408 else
409 fprintf(stderr, "unsupported OctaMED command %u\n", eff);
410#endif
411 break;
412 }
413}
414
415static UBYTE *MED_Convert1(int count, int col)
416{
417 int t;
418 UBYTE inst, note, eff, dat;
419 MMD1NOTE *n;
420
421 UniReset();
422 for (t = 0; t < count; t++) {
423 n = &d1note(t, col);
424
425 note = n->a & 0x7f;
426 inst = n->b & 0x3f;
427 eff = n->c;
428 dat = n->d;
429
430 if (inst)
431 UniInstrument(inst - 1);
432 if (note)
433 UniNote(note - 1);
434 EffectCvt(note, eff, dat);
435 UniNewline();
436 }
437 return UniDup();
438}
439
440static UBYTE *MED_Convert0(int count, int col)
441{
442 int t;
443 UBYTE a, b, inst, note, eff, dat;
444 MMD0NOTE *n;
445
446 UniReset();
447 for (t = 0; t < count; t++) {
448 n = &d0note(t, col);
449 a = n->a;
450 b = n->b;
451
452 note = a & 0x3f;
453 a >>= 6;
454 a = ((a & 1) << 1) | (a >> 1);
455 inst = (b >> 4) | (a << 4);
456 eff = b & 0xf;
457 dat = n->c;
458
459 if (inst)
460 UniInstrument(inst - 1);
461 if (note)
462 UniNote(note - 1);
463 EffectCvt(note, eff, dat);
464 UniNewline();
465 }
466 return UniDup();
467}
468
469static int LoadMEDPatterns(void)
470{
471 int t, row, col;
472 UWORD numtracks, numlines, maxlines = 0, track = 0;
473 MMD0NOTE *mmdp;
474
475 /* first, scan patterns to see how many channels are used */
476 for (t = 0; t < of.numpat; t++) {
477 _mm_fseek(modreader, ba[t], SEEK_SET);
478 numtracks = _mm_read_UBYTE(modreader);
479 numlines = _mm_read_UBYTE(modreader);
480
481 if (numtracks > of.numchn)
482 of.numchn = numtracks;
483 if (numlines > maxlines)
484 maxlines = numlines;
485 /* sanity check */
486 if (numtracks > 64)
487 return 0;
488 }
489 /* sanity check */
490 if (! of.numchn || of.numchn > 16) /* docs say 4, 8, 12 or 16 */
491 return 0;
492
493 of.numtrk = of.numpat * of.numchn;
494 if (!AllocTracks())
495 return 0;
496 if (!AllocPatterns())
497 return 0;
498
499 if (!(mmd0pat = (MMD0NOTE *)MikMod_calloc(of.numchn * (maxlines + 1), sizeof(MMD0NOTE))))
500 return 0;
501
502 /* second read: read and convert patterns */
503 for (t = 0; t < of.numpat; t++) {
504 _mm_fseek(modreader, ba[t], SEEK_SET);
505 numtracks = _mm_read_UBYTE(modreader);
506 numlines = _mm_read_UBYTE(modreader);
507
508 of.pattrows[t] = ++numlines;
509 memset(mmdp = mmd0pat, 0, of.numchn * maxlines * sizeof(MMD0NOTE));
510 for (row = numlines; row; row--) {
511 for (col = numtracks; col; col--, mmdp++) {
512 mmdp->a = _mm_read_UBYTE(modreader);
513 mmdp->b = _mm_read_UBYTE(modreader);
514 mmdp->c = _mm_read_UBYTE(modreader);
515 }
516 /* Skip tracks this block doesn't use. */
517 for (col = numtracks; col < of.numchn; col++, mmdp++) {}
518 }
519
520 for (col = 0; col < of.numchn; col++)
521 of.tracks[track++] = MED_Convert0(numlines, col);
522 }
523 return 1;
524}
525
526static int LoadMMD1Patterns(void)
527{
528 int t, row, col;
529 UWORD numtracks, numlines, maxlines = 0, track = 0;
530 MMD1NOTE *mmdp;
531
532 /* first, scan patterns to see how many channels are used */
533 for (t = 0; t < of.numpat; t++) {
534 _mm_fseek(modreader, ba[t], SEEK_SET);
535 numtracks = _mm_read_M_UWORD(modreader);
536 numlines = _mm_read_M_UWORD(modreader);
537 if (numtracks > of.numchn)
538 of.numchn = numtracks;
539 if (numlines > maxlines)
540 maxlines = numlines;
541 /* sanity check */
542 if (numtracks > 64)
543 return 0;
544 if (numlines >= 3200) /* per docs */
545 return 0;
546 }
547 /* sanity check */
548 if (! of.numchn || of.numchn > 16) /* docs say 4, 8, 12 or 16 */
549 return 0;
550
551 of.numtrk = of.numpat * of.numchn;
552 if (!AllocTracks())
553 return 0;
554 if (!AllocPatterns())
555 return 0;
556
557 if (!(mmd1pat = (MMD1NOTE *)MikMod_calloc(of.numchn * (maxlines + 1), sizeof(MMD1NOTE))))
558 return 0;
559
560 /* second read: really read and convert patterns */
561 for (t = 0; t < of.numpat; t++) {
562 _mm_fseek(modreader, ba[t], SEEK_SET);
563 numtracks = _mm_read_M_UWORD(modreader);
564 numlines = _mm_read_M_UWORD(modreader);
565
566 _mm_fseek(modreader, sizeof(ULONG), SEEK_CUR);
567 of.pattrows[t] = ++numlines;
568 memset(mmdp = mmd1pat, 0, of.numchn * maxlines * sizeof(MMD1NOTE));
569
570 for (row = numlines; row; row--) {
571 for (col = numtracks; col; col--, mmdp++) {
572 mmdp->a = _mm_read_UBYTE(modreader);
573 mmdp->b = _mm_read_UBYTE(modreader);
574 mmdp->c = _mm_read_UBYTE(modreader);
575 mmdp->d = _mm_read_UBYTE(modreader);
576 }
577 /* Skip tracks this block doesn't use. */
578 for (col = numtracks; col < of.numchn; col++, mmdp++) {}
579 }
580
581 for (col = 0; col < of.numchn; col++)
582 of.tracks[track++] = MED_Convert1(numlines, col);
583 }
584 return 1;
585}
586
587static int MED_Load(int curious)
588{
589 int t, i;
590 ULONG sa[64];
591 MEDINSTHEADER s;
592 INSTRUMENT *d;
593 SAMPLE *q;
594 MEDSAMPLE *mss;
595
596 /* try to read module header */
597 mh->id = _mm_read_M_ULONG(modreader);
598 mh->modlen = _mm_read_M_ULONG(modreader);
599 mh->MEDSONGP = _mm_read_M_ULONG(modreader);
600 mh->psecnum = _mm_read_M_UWORD(modreader);
601 mh->pseq = _mm_read_M_UWORD(modreader);
602 mh->MEDBlockPP = _mm_read_M_ULONG(modreader);
603 mh->reserved1 = _mm_read_M_ULONG(modreader);
604 mh->MEDINSTHEADERPP = _mm_read_M_ULONG(modreader);
605 mh->reserved2 = _mm_read_M_ULONG(modreader);
606 mh->MEDEXPP = _mm_read_M_ULONG(modreader);
607 mh->reserved3 = _mm_read_M_ULONG(modreader);
608 mh->pstate = _mm_read_M_UWORD(modreader);
609 mh->pblock = _mm_read_M_UWORD(modreader);
610 mh->pline = _mm_read_M_UWORD(modreader);
611 mh->pseqnum = _mm_read_M_UWORD(modreader);
612 mh->actplayline = _mm_read_M_SWORD(modreader);
613 mh->counter = _mm_read_UBYTE(modreader);
614 mh->extra_songs = _mm_read_UBYTE(modreader);
615
616 /* Seek to MEDSONG struct */
617 _mm_fseek(modreader, mh->MEDSONGP, SEEK_SET);
618
619 /* Load the MED Song Header */
620 mss = ms->sample; /* load the sample data first */
621 for (t = 63; t; t--, mss++) {
622 mss->rep = _mm_read_M_UWORD(modreader);
623 mss->replen = _mm_read_M_UWORD(modreader);
624 mss->midich = _mm_read_UBYTE(modreader);
625 mss->midipreset = _mm_read_UBYTE(modreader);
626 mss->svol = _mm_read_UBYTE(modreader);
627 mss->strans = _mm_read_SBYTE(modreader);
628 }
629
630 ms->numblocks = _mm_read_M_UWORD(modreader);
631 ms->songlen = _mm_read_M_UWORD(modreader);
632 _mm_read_UBYTES(ms->playseq, 256, modreader);
633 /* sanity check */
634 if (ms->numblocks > 255 || ms->songlen > 256) {
635 _mm_errno = MMERR_NOT_A_MODULE;
636 return 0;
637 }
638 ms->deftempo = _mm_read_M_UWORD(modreader);
639 ms->playtransp = _mm_read_SBYTE(modreader);
640 ms->flags = _mm_read_UBYTE(modreader);
641 ms->flags2 = _mm_read_UBYTE(modreader);
642 ms->tempo2 = _mm_read_UBYTE(modreader);
643 _mm_read_UBYTES(ms->trkvol, 16, modreader);
644 ms->mastervol = _mm_read_UBYTE(modreader);
645 ms->numsamples = _mm_read_UBYTE(modreader);
646 /* sanity check */
647 if (ms->numsamples > 64) {
648 _mm_errno = MMERR_NOT_A_MODULE;
649 return 0;
650 }
651
652 /* check for a bad header */
653 if (_mm_eof(modreader)) {
654 _mm_errno = MMERR_LOADING_HEADER;
655 return 0;
656 }
657
658 /* load extension structure */
659 if (mh->MEDEXPP) {
660 _mm_fseek(modreader, mh->MEDEXPP, SEEK_SET);
661 me->nextmod = _mm_read_M_ULONG(modreader);
662 me->exp_smp = _mm_read_M_ULONG(modreader);
663 me->s_ext_entries = _mm_read_M_UWORD(modreader);
664 me->s_ext_entrsz = _mm_read_M_UWORD(modreader);
665 me->annotxt = _mm_read_M_ULONG(modreader);
666 me->annolen = _mm_read_M_ULONG(modreader);
667 me->iinfo = _mm_read_M_ULONG(modreader);
668 me->i_ext_entries = _mm_read_M_UWORD(modreader);
669 me->i_ext_entrsz = _mm_read_M_UWORD(modreader);
670 me->jumpmask = _mm_read_M_ULONG(modreader);
671 me->rgbtable = _mm_read_M_ULONG(modreader);
672 me->channelsplit = _mm_read_M_ULONG(modreader);
673 me->n_info = _mm_read_M_ULONG(modreader);
674 me->songname = _mm_read_M_ULONG(modreader);
675 me->songnamelen = _mm_read_M_ULONG(modreader);
676 me->dumps = _mm_read_M_ULONG(modreader);
677 /* sanity check */
678 if (me->annolen > 0xffff) {
679 _mm_errno = MMERR_NOT_A_MODULE;
680 return 0;
681 }
682 /* truncate insane songnamelen (fail instead?) */
683 if (me->songnamelen > 256)
684 me->songnamelen = 256;
685 }
686
687 /* seek to and read the samplepointer array */
688 _mm_fseek(modreader, mh->MEDINSTHEADERPP, SEEK_SET);
689 if (!_mm_read_M_ULONGS(sa, ms->numsamples, modreader)) {
690 _mm_errno = MMERR_LOADING_HEADER;
691 return 0;
692 }
693
694 /* alloc and read the blockpointer array */
695 if (!(ba = (ULONG *)MikMod_calloc(ms->numblocks, sizeof(ULONG))))
696 return 0;
697 _mm_fseek(modreader, mh->MEDBlockPP, SEEK_SET);
698 if (!_mm_read_M_ULONGS(ba, ms->numblocks, modreader)) {
699 _mm_errno = MMERR_LOADING_HEADER;
700 return 0;
701 }
702
703 /* copy song positions */
704 if (!AllocPositions(ms->songlen))
705 return 0;
706 for (t = 0; t < ms->songlen; t++) {
707 of.positions[t] = ms->playseq[t];
708 if (of.positions[t]>ms->numblocks) { /* SANITIY CHECK */
709 /* fprintf(stderr,"positions[%d]=%d > numpat=%d\n",t,of.positions[t],ms->numblocks);*/
710 _mm_errno = MMERR_LOADING_HEADER;
711 return 0;
712 }
713 }
714
715 decimalvolumes = (ms->flags & 0x10) ? 0 : 1;
716 is8channel = (ms->flags & 0x40) ? 1 : 0;
717 bpmtempos = (ms->flags2 & 0x20) ? 1 : 0;
718
719 if (bpmtempos) {
720 rowsperbeat = (ms->flags2 & 0x1f) + 1;
721 of.initspeed = ms->tempo2;
722 of.inittempo = MED_ConvertTempo(ms->deftempo);
723 } else {
724 of.initspeed = ms->tempo2;
725 of.inittempo = ms->deftempo ? MED_ConvertTempo(ms->deftempo) : 128;
726 }
727 of.flags |= UF_HIGHBPM;
728 MED_Version[12] = mh->id;
729 of.modtype = MikMod_strdup(MED_Version);
730 of.numchn = 0; /* will be counted later */
731 of.numpat = ms->numblocks;
732 of.numpos = ms->songlen;
733 of.numins = ms->numsamples;
734 of.numsmp = of.numins;
735 of.reppos = 0;
736 if ((mh->MEDEXPP) && (me->songname) && (me->songnamelen)) {
737 char *name;
738
739 _mm_fseek(modreader, me->songname, SEEK_SET);
740 name = (char *) MikMod_malloc(me->songnamelen);
741 _mm_read_UBYTES(name, me->songnamelen, modreader);
742 of.songname = DupStr(name, me->songnamelen, 1);
743 MikMod_free(name);
744 } else
745 of.songname = DupStr(NULL, 0, 0);
746 if ((mh->MEDEXPP) && (me->annotxt) && (me->annolen)) {
747 _mm_fseek(modreader, me->annotxt, SEEK_SET);
748 ReadComment(me->annolen);
749 }
750
751 /* TODO: should do an initial scan for IFFOCT instruments to determine the
752 actual number of samples (instead of assuming 1-to-1). */
753 if (!AllocSamples() || !AllocInstruments())
754 return 0;
755
756 of.flags |= UF_INST;
757 q = of.samples;
758 d = of.instruments;
759 for (t = 0; t < of.numins; t++) {
760 q->flags = SF_SIGNED;
761 q->volume = 64;
762 s.type = INST_SAMPLE;
763 if (sa[t]) {
764 _mm_fseek(modreader, sa[t], SEEK_SET);
765 s.length = _mm_read_M_ULONG(modreader);
766 s.type = _mm_read_M_SWORD(modreader);
767
768 switch (s.type) {
769 case INST_SAMPLE:
770 case INST_EXTSAMPLE:
771 break;
772
773 default:
774#ifdef MIKMOD_DEBUG
775 fprintf(stderr, "\rNon-sample instruments not supported in MED loader yet\n");
776#endif
777 if (!curious) {
778 _mm_errno = MMERR_MED_SYNTHSAMPLES;
779 return 0;
780 }
781 s.length = 0;
782 }
783
784 if (_mm_eof(modreader)) {
785 _mm_errno = MMERR_LOADING_SAMPLEINFO;
786 return 0;
787 }
788
789 q->length = s.length;
790 q->seekpos = _mm_ftell(modreader);
791 q->loopstart = ms->sample[t].rep << 1;
792 q->loopend = q->loopstart + (ms->sample[t].replen << 1);
793
794 if (ms->sample[t].replen > 1)
795 q->flags |= SF_LOOP;
796
797 if(ms->sample[t].svol <= 64)
798 q->volume = ms->sample[t].svol;
799
800 /* don't load sample if length>='MMD0'...
801 such kluges make libmikmod's code unique !!! */
802 if (q->length >= MMD0_string)
803 q->length = 0;
804 } else
805 q->length = 0;
806
807 if ((mh->MEDEXPP) && (me->exp_smp) &&
808 (t < me->s_ext_entries) && (me->s_ext_entrsz >= 4)) {
809 MEDINSTEXT ie;
810
811 _mm_fseek(modreader, me->exp_smp + t * me->s_ext_entrsz,
812 SEEK_SET);
813 ie.hold = _mm_read_UBYTE(modreader);
814 ie.decay = _mm_read_UBYTE(modreader);
815 ie.suppress_midi_off = _mm_read_UBYTE(modreader);
816 ie.finetune = _mm_read_SBYTE(modreader);
817
818 q->speed = finetune[ie.finetune & 0xf];
819 } else
820 q->speed = 8363;
821
822 if ((mh->MEDEXPP) && (me->iinfo) &&
823 (t < me->i_ext_entries) && (me->i_ext_entrsz >= 40)) {
824 MEDINSTINFO ii;
825
826 _mm_fseek(modreader, me->iinfo + t * me->i_ext_entrsz, SEEK_SET);
827 _mm_read_UBYTES(ii.name, 40, modreader);
828 q->samplename = DupStr((char*)ii.name, 40, 1);
829 d->insname = DupStr((char*)ii.name, 40, 1);
830 } else {
831 q->samplename = NULL;
832 d->insname = NULL;
833 }
834
835 /* Instrument transpose tables. */
836 for (i = 0; i < MEDNOTECNT; i++) {
837 int note = i + 3 * OCTAVE + ms->sample[t].strans + ms->playtransp;
838
839 /* TODO: IFFOCT instruments... */
840 switch (s.type) {
841 case INST_EXTSAMPLE:
842 /* TODO: not clear if this has the same wrapping behavior as regular samples.
843 This is a MMD2/MMD3 extension so it has not been tested. */
844 note -= 2 * OCTAVE;
845 /* fall-through */
846
847 case INST_SAMPLE:
848 /* TODO: in MMD2/MMD3 mixing mode, these wrapping transforms don't apply. */
849 if (note >= 10 * OCTAVE) {
850 /* Buggy octaves 8 through A wrap to 2 octaves below octave 1.
851 Technically they're also a finetune step higher but that's safe
852 to ignore. */
853 note -= 9 * OCTAVE;
854 } else if (note >= 6 * OCTAVE) {
855 /* Octaves 4 through 7 repeat octave 3. */
856 note = (note % 12) + 5 * OCTAVE;
857 }
858 d->samplenumber[i] = t;
859 d->samplenote[i] = note<0 ? 0 : note>255 ? 255 : note;
860 break;
861 }
862 }
863
864 q++;
865 d++;
866 }
867
868 if (mh->id == MMD0_string) {
869 medversion = 0;
870 if (!LoadMEDPatterns()) {
871 _mm_errno = MMERR_LOADING_PATTERN;
872 return 0;
873 }
874 } else if (mh->id == MMD1_string) {
875 medversion = 1;
876 if (!LoadMMD1Patterns()) {
877 _mm_errno = MMERR_LOADING_PATTERN;
878 return 0;
879 }
880 } else {
881 _mm_errno = MMERR_NOT_A_MODULE;
882 return 0;
883 }
884 return 1;
885}
886
887static CHAR *MED_LoadTitle(void)
888{
889 ULONG posit, namelen;
890 CHAR *name, *retvalue = NULL;
891
892 _mm_fseek(modreader, 0x20, SEEK_SET);
893 posit = _mm_read_M_ULONG(modreader);
894
895 if (posit) {
896 _mm_fseek(modreader, posit + 0x2C, SEEK_SET);
897 posit = _mm_read_M_ULONG(modreader);
898 namelen = _mm_read_M_ULONG(modreader);
899
900 _mm_fseek(modreader, posit, SEEK_SET);
901 name = (CHAR*) MikMod_malloc(namelen);
902 _mm_read_UBYTES(name, namelen, modreader);
903 retvalue = DupStr(name, namelen, 1);
904 MikMod_free(name);
905 }
906
907 return retvalue;
908}
909
910/*========== Loader information */
911
912MIKMODAPI MLOADER load_med = {
913 NULL,
914 "MED",
915 "MED (OctaMED)",
916 MED_Init,
917 MED_Test,
918 MED_Load,
919 MED_Cleanup,
920 MED_LoadTitle
921};
922
923/* ex:set ts=4: */