1 /* MikMod sound library
2 (c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
3 AUTHORS for complete list.
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.
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.
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
21 /*==============================================================================
23 $Id: load_med.c,v 1.3 2005/04/07 19:57:38 realtech Exp $
25 Amiga MED module loader
27 ==============================================================================*/
43 #include "mikmod_internals.h"
46 extern int fprintf(FILE *, const char *, ...);
49 /*========== Module information */
51 typedef struct MEDHEADER
{
54 ULONG MEDSONGP
; /* struct MEDSONG *song; */
55 UWORD psecnum
; /* for the player routine, MMD2 only */
56 UWORD pseq
; /* " " " " */
57 ULONG MEDBlockPP
; /* struct MEDBlock **blockarr; */
59 ULONG MEDINSTHEADERPP
; /* struct MEDINSTHEADER **smplarr; */
61 ULONG MEDEXPP
; /* struct MEDEXP *expdata; */
63 UWORD pstate
; /* some data for the player routine */
69 UBYTE extra_songs
; /* number of songs - 1 */
72 typedef 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) */
80 typedef 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 */
95 typedef struct MEDEXP
{
96 ULONG nextmod
; /* pointer to next module */
97 ULONG exp_smp
; /* pointer to MEDINSTEXT array */
100 ULONG annotxt
; /* pointer to annotation text */
102 ULONG iinfo
; /* pointer to MEDINSTINFO array */
109 ULONG songname
; /* pointer to songname */
115 typedef struct MMD0NOTE
{
119 typedef struct MMD1NOTE
{
123 typedef struct MEDINSTHEADER
{
126 /* Followed by actual data */
129 typedef struct MEDINSTEXT
{
132 UBYTE suppress_midi_off
;
136 typedef struct MEDINSTINFO
{
140 /*========== Loader variables */
142 #define MMD0_string 0x4D4D4430
143 #define MMD1_string 0x4D4D4431
145 static MEDHEADER
*mh
= NULL
;
146 static MEDSONG
*ms
= NULL
;
147 static MEDEXP
*me
= NULL
;
148 static ULONG
*ba
= NULL
;
149 static MMD0NOTE
*mmd0pat
= NULL
;
150 static MMD1NOTE
*mmd1pat
= NULL
;
152 static int decimalvolumes
;
153 static int bpmtempos
;
155 #define d0note(row,col) mmd0pat[((row)*(UWORD)of.numchn)+(col)]
156 #define d1note(row,col) mmd1pat[((row)*(UWORD)of.numchn)+(col)]
158 static CHAR MED_Version
[] = "OctaMED (MMDx)";
160 /*========== Loader code */
162 static int MED_Test(void)
166 if (!_mm_read_UBYTES(id
, 4, modreader
))
168 if ((!memcmp(id
, "MMD0", 4)) || (!memcmp(id
, "MMD1", 4)))
173 static int MED_Init(void)
175 if (!(me
= (MEDEXP
*)MikMod_malloc(sizeof(MEDEXP
))))
177 if (!(mh
= (MEDHEADER
*)MikMod_malloc(sizeof(MEDHEADER
))))
179 if (!(ms
= (MEDSONG
*)MikMod_malloc(sizeof(MEDSONG
))))
184 static void MED_Cleanup(void)
190 MikMod_free(mmd0pat
);
191 MikMod_free(mmd1pat
);
194 static void EffectCvt(UBYTE eff
, UBYTE dat
)
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));
201 /* 0x6 0x7 not used */
205 case 0x8: /* midi hold/decay */
211 UniEffect(UNI_S3MEFFECTA
, dat
);
218 UniPTEffect(0xf, dat
);
220 UniEffect(UNI_MEDSPEED
, ((UWORD
)dat
* 125) / (33 * 4));
223 /* 0xa 0xb PT effects */
226 dat
= (dat
>> 4) * 10 + (dat
& 0xf);
227 UniPTEffect(0xc, dat
);
229 case 0xd: /* same as PT volslide */
230 UniPTEffect(0xa, dat
);
232 case 0xe: /* synth jmp - midi */
236 case 0: /* patternbreak */
239 case 0xf1: /* play note twice */
240 UniWriteByte(UNI_MEDEFFECTF1
);
242 case 0xf2: /* delay note */
243 UniWriteByte(UNI_MEDEFFECTF2
);
245 case 0xf3: /* play note three times */
246 UniWriteByte(UNI_MEDEFFECTF3
);
248 case 0xfe: /* stop playing */
249 UniPTEffect(0xb, of
.numpat
);
251 case 0xff: /* note cut */
256 UniPTEffect(0xf, dat
);
257 else if (dat
<= 240) {
259 UniPTEffect(0xf, (dat
< 32) ? 32 : dat
);
261 UniEffect(UNI_MEDSPEED
, ((UWORD
)dat
* 125) / 33);
265 default: /* all normal PT effects are handled here */
266 UniPTEffect(eff
, dat
);
271 static UBYTE
*MED_Convert1(int count
, int col
)
274 UBYTE inst
, note
, eff
, dat
;
278 for (t
= 0; t
< count
; t
++) {
287 UniInstrument(inst
- 1);
289 UniNote(note
+ 3 * OCTAVE
- 1);
296 static UBYTE
*MED_Convert0(int count
, int col
)
299 UBYTE a
, b
, inst
, note
, eff
, dat
;
303 for (t
= 0; t
< count
; t
++) {
310 a
= ((a
& 1) << 1) | (a
>> 1);
311 inst
= (b
>> 4) | (a
<< 4);
316 UniInstrument(inst
- 1);
318 UniNote(note
+ 3 * OCTAVE
- 1);
325 static int LoadMEDPatterns(void)
328 UWORD numtracks
, numlines
, maxlines
= 0, track
= 0;
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
);
337 if (numtracks
> of
.numchn
)
338 of
.numchn
= numtracks
;
339 if (numlines
> maxlines
)
343 of
.numtrk
= of
.numpat
* of
.numchn
;
346 if (!AllocPatterns())
351 (MMD0NOTE
*)MikMod_calloc(of
.numchn
* (maxlines
+ 1),
352 sizeof(MMD0NOTE
)))) return 0;
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
);
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
);
370 for (col
= 0; col
< of
.numchn
; col
++)
371 of
.tracks
[track
++] = MED_Convert0(numlines
, col
);
376 static int LoadMMD1Patterns(void)
379 UWORD numtracks
, numlines
, maxlines
= 0, track
= 0;
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
)
393 of
.numtrk
= of
.numpat
* of
.numchn
;
396 if (!AllocPatterns())
401 (MMD1NOTE
*)MikMod_calloc(of
.numchn
* (maxlines
+ 1),
402 sizeof(MMD1NOTE
)))) return 0;
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
);
410 _mm_fseek(modreader
, sizeof(ULONG
), SEEK_CUR
);
411 of
.pattrows
[t
] = ++numlines
;
412 memset(mmdp
= mmd1pat
, 0, of
.numchn
* maxlines
* sizeof(MMD1NOTE
));
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
);
423 for (col
= 0; col
< of
.numchn
; col
++)
424 of
.tracks
[track
++] = MED_Convert1(numlines
, col
);
429 static int MED_Load(int curious
)
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
);
457 /* Seek to MEDSONG struct */
458 _mm_fseek(modreader
, mh
->MEDSONGP
, SEEK_SET
);
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
);
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
);
483 /* check for a bad header */
484 if (_mm_eof(modreader
)) {
485 _mm_errno
= MMERR_LOADING_HEADER
;
489 /* load extension structure */
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
);
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
;
517 /* alloc and read the blockpointer array */
518 if (!(ba
= (ULONG
*)MikMod_calloc(ms
->numblocks
, sizeof(ULONG
))))
520 _mm_fseek(modreader
, mh
->MEDBlockPP
, SEEK_SET
);
521 if (!_mm_read_M_ULONGS(ba
, ms
->numblocks
, modreader
)) {
522 _mm_errno
= MMERR_LOADING_HEADER
;
526 /* copy song positions */
527 if (!AllocPositions(ms
->songlen
))
529 for (t
= 0; t
< ms
->songlen
; t
++)
530 of
.positions
[t
] = ms
->playseq
[t
];
532 decimalvolumes
= (ms
->flags
& 0x10) ? 0 : 1;
533 bpmtempos
= (ms
->flags2
& 0x20) ? 1 : 0;
536 int bpmlen
= (ms
->flags2
& 0x1f) + 1;
537 of
.initspeed
= ms
->tempo2
;
538 of
.inittempo
= ms
->deftempo
* bpmlen
/ 4;
541 /* Let's do some math : compute GCD of BPM beat length and speed */
552 while ((a
!= b
) && (a
)) {
564 of
.inittempo
= ms
->deftempo
* bpmlen
/ (4 * b
);
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
;
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
;
581 if ((mh
->MEDEXPP
) && (me
->songname
) && (me
->songnamelen
)) {
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);
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
);
599 for (t
= 0; t
< of
.numins
; t
++) {
600 q
->flags
= SF_SIGNED
;
603 _mm_fseek(modreader
, sa
[t
], SEEK_SET
);
604 s
.length
= _mm_read_M_ULONG(modreader
);
605 s
.type
= _mm_read_M_SWORD(modreader
);
609 fprintf(stderr
, "\rNon-sample instruments not supported in MED loader yet\n");
612 _mm_errno
= MMERR_MED_SYNTHSAMPLES
;
618 if (_mm_eof(modreader
)) {
619 _mm_errno
= MMERR_LOADING_SAMPLEINFO
;
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);
628 if (ms
->sample
[t
].replen
> 1)
631 /* don't load sample if length>='MMD0'...
632 such kluges make libmikmod's code unique !!! */
633 if (q
->length
>= MMD0_string
)
638 if ((mh
->MEDEXPP
) && (me
->exp_smp
) &&
639 (t
< me
->s_ext_entries
) && (me
->s_ext_entrsz
>= 4)) {
642 _mm_fseek(modreader
, me
->exp_smp
+ t
* me
->s_ext_entrsz
,
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
);
649 q
->speed
= finetune
[ie
.finetune
& 0xf];
653 if ((mh
->MEDEXPP
) && (me
->iinfo
) &&
654 (t
< me
->i_ext_entries
) && (me
->i_ext_entrsz
>= 40)) {
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);
661 q
->samplename
= NULL
;
666 if (mh
->id
== MMD0_string
) {
667 if (!LoadMEDPatterns()) {
668 _mm_errno
= MMERR_LOADING_PATTERN
;
671 } else if (mh
->id
== MMD1_string
) {
672 if (!LoadMMD1Patterns()) {
673 _mm_errno
= MMERR_LOADING_PATTERN
;
677 _mm_errno
= MMERR_NOT_A_MODULE
;
683 static CHAR
*MED_LoadTitle(void)
685 ULONG posit
, namelen
;
686 CHAR
*name
, *retvalue
= NULL
;
688 _mm_fseek(modreader
, 0x20, SEEK_SET
);
689 posit
= _mm_read_M_ULONG(modreader
);
692 _mm_fseek(modreader
, posit
+ 0x2C, SEEK_SET
);
693 posit
= _mm_read_M_ULONG(modreader
);
694 namelen
= _mm_read_M_ULONG(modreader
);
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);
706 /*========== Loader information */
708 MIKMODAPI MLOADER load_med
= {