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_mtm.c,v 1.3 2005/04/07 19:57:38 realtech Exp $
27 ==============================================================================*/
43 #include "mikmod_internals.h"
46 extern int fprintf(FILE *, const char *, ...);
49 /*========== Module structure */
51 typedef struct MTMHEADER
{
52 UBYTE id
[3]; /* MTM file marker */
53 UBYTE version
; /* upper major, lower nibble minor version number */
54 CHAR songname
[20]; /* ASCIIZ songname */
55 UWORD numtracks
; /* number of tracks saved */
56 UBYTE lastpattern
; /* last pattern number saved */
57 UBYTE lastorder
; /* last order number to play (songlength-1) */
58 UWORD commentsize
; /* length of comment field */
59 UBYTE numsamples
; /* number of samples saved */
60 UBYTE attribute
; /* attribute byte (unused) */
62 UBYTE numchannels
; /* number of channels used */
63 UBYTE panpos
[32]; /* voice pan positions */
66 typedef struct MTMSAMPLE
{
76 typedef struct MTMNOTE
{
80 /*========== Loader variables */
82 static MTMHEADER
*mh
= NULL
;
83 static MTMNOTE
*mtmtrk
= NULL
;
86 static CHAR MTM_Version
[] = "MTM";
88 /*========== Loader code */
94 if(!_mm_read_UBYTES(id
,3,modreader
)) return 0;
95 if(!memcmp(id
,"MTM",3)) return 1;
101 if(!(mtmtrk
=(MTMNOTE
*)MikMod_calloc(64,sizeof(MTMNOTE
)))) return 0;
102 if(!(mh
=(MTMHEADER
*)MikMod_malloc(sizeof(MTMHEADER
)))) return 0;
107 void MTM_Cleanup(void)
113 static UBYTE
* MTM_Convert(void)
116 UBYTE a
,b
,inst
,note
,eff
,dat
;
122 inst
=((a
&0x3)<<4)|(b
>>4);
127 if(inst
) UniInstrument(inst
-1);
128 if(note
) UniNote(note
+2*OCTAVE
);
130 /* MTM bug workaround : when the effect is volslide, slide-up *always*
131 overrides slide-down. */
132 if(eff
==0xa && (dat
&0xf0)) dat
&=0xf0;
134 /* Convert pattern jump from Dec to Hex */
136 dat
=(((dat
&0xf0)>>4)*10)+(dat
&0xf);
137 UniPTEffect(eff
,dat
);
143 int MTM_Load(int curious
)
149 /* try to read module header */
150 _mm_read_UBYTES(mh
->id
,3,modreader
);
151 mh
->version
=_mm_read_UBYTE(modreader
);
152 _mm_read_string(mh
->songname
,20,modreader
);
153 mh
->numtracks
=_mm_read_I_UWORD(modreader
);
154 mh
->lastpattern
=_mm_read_UBYTE(modreader
);
155 mh
->lastorder
=_mm_read_UBYTE(modreader
);
156 mh
->commentsize
=_mm_read_I_UWORD(modreader
);
157 mh
->numsamples
=_mm_read_UBYTE(modreader
);
158 mh
->attribute
=_mm_read_UBYTE(modreader
);
159 mh
->beatspertrack
=_mm_read_UBYTE(modreader
);
160 mh
->numchannels
=_mm_read_UBYTE(modreader
);
161 _mm_read_UBYTES(mh
->panpos
,32,modreader
);
163 if(_mm_eof(modreader
)) {
164 _mm_errno
= MMERR_LOADING_HEADER
;
168 /* set module variables */
171 of
.modtype
= StrDup(MTM_Version
);
172 of
.numchn
= mh
->numchannels
;
173 of
.numtrk
= mh
->numtracks
+1; /* get number of channels */
174 of
.songname
= DupStr(mh
->songname
,20,1); /* make a cstr of songname */
175 of
.numpos
= mh
->lastorder
+1; /* copy the songlength */
176 of
.numpat
= mh
->lastpattern
+1;
178 of
.flags
|= UF_PANNING
;
179 for(t
=0;t
<32;t
++) of
.panning
[t
]=mh
->panpos
[t
]<< 4;
180 of
.numins
=of
.numsmp
=mh
->numsamples
;
182 if(!AllocSamples()) return 0;
184 for(t
=0;t
<of
.numins
;t
++) {
185 /* try to read sample info */
186 _mm_read_string(s
.samplename
,22,modreader
);
187 s
.length
=_mm_read_I_ULONG(modreader
);
188 s
.reppos
=_mm_read_I_ULONG(modreader
);
189 s
.repend
=_mm_read_I_ULONG(modreader
);
190 s
.finetune
=_mm_read_UBYTE(modreader
);
191 s
.volume
=_mm_read_UBYTE(modreader
);
192 s
.attribute
=_mm_read_UBYTE(modreader
);
194 if(_mm_eof(modreader
)) {
195 _mm_errno
= MMERR_LOADING_SAMPLEINFO
;
199 q
->samplename
= DupStr(s
.samplename
,22,1);
201 q
->speed
= finetune
[s
.finetune
];
202 q
->length
= s
.length
;
203 q
->loopstart
= s
.reppos
;
204 q
->loopend
= s
.repend
;
205 q
->volume
= s
.volume
;
206 if((s
.repend
-s
.reppos
)>2) q
->flags
|= SF_LOOP
;
209 /* If the sample is 16-bits, convert the length and replen
210 byte-values into sample-values */
219 if(!AllocPositions(of
.numpos
)) return 0;
220 for(t
=0;t
<of
.numpos
;t
++)
221 of
.positions
[t
]=_mm_read_UBYTE(modreader
);
222 for(;t
<128;t
++) _mm_read_UBYTE(modreader
);
223 if(_mm_eof(modreader
)) {
224 _mm_errno
= MMERR_LOADING_HEADER
;
228 if(!AllocTracks()) return 0;
229 if(!AllocPatterns()) return 0;
231 of
.tracks
[0]=MTM_Convert(); /* track 0 is empty */
232 for(t
=1;t
<of
.numtrk
;t
++) {
236 mtmtrk
[s
].a
=_mm_read_UBYTE(modreader
);
237 mtmtrk
[s
].b
=_mm_read_UBYTE(modreader
);
238 mtmtrk
[s
].c
=_mm_read_UBYTE(modreader
);
241 if(_mm_eof(modreader
)) {
242 _mm_errno
= MMERR_LOADING_TRACK
;
246 if(!(of
.tracks
[t
]=MTM_Convert())) return 0;
249 for(t
=0;t
<of
.numpat
;t
++) {
250 _mm_read_I_UWORDS(pat
,32,modreader
);
251 for(u
=0;u
<of
.numchn
;u
++)
252 of
.patterns
[((long)t
*of
.numchn
)+u
]=pat
[u
];
255 /* read comment field */
257 if(!ReadLinedComment(mh
->commentsize
, 40)) return 0;
262 CHAR
*MTM_LoadTitle(void)
266 _mm_fseek(modreader
,4,SEEK_SET
);
267 if(!_mm_read_UBYTES(s
,20,modreader
)) return NULL
;
269 return(DupStr(s
,20,1));
272 /*========== Loader information */
274 MIKMODAPI MLOADER load_mtm
={
277 "MTM (MultiTracker Module editor)",