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 */
90 static int MTM_Test(void)
94 if(!_mm_read_UBYTES(id
,3,modreader
)) return 0;
95 if(!memcmp(id
,"MTM",3)) return 1;
99 static int MTM_Init(void)
101 if(!(mtmtrk
=(MTMNOTE
*)MikMod_calloc(64,sizeof(MTMNOTE
)))) return 0;
102 if(!(mh
=(MTMHEADER
*)MikMod_malloc(sizeof(MTMHEADER
)))) return 0;
107 static 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 static int MTM_Load(int curious
)
150 /* try to read module header */
151 _mm_read_UBYTES(mh
->id
,3,modreader
);
152 mh
->version
=_mm_read_UBYTE(modreader
);
153 _mm_read_string(mh
->songname
,20,modreader
);
154 mh
->numtracks
=_mm_read_I_UWORD(modreader
);
155 mh
->lastpattern
=_mm_read_UBYTE(modreader
);
156 mh
->lastorder
=_mm_read_UBYTE(modreader
);
157 mh
->commentsize
=_mm_read_I_UWORD(modreader
);
158 mh
->numsamples
=_mm_read_UBYTE(modreader
);
159 mh
->attribute
=_mm_read_UBYTE(modreader
);
160 mh
->beatspertrack
=_mm_read_UBYTE(modreader
);
161 mh
->numchannels
=_mm_read_UBYTE(modreader
);
162 _mm_read_UBYTES(mh
->panpos
,32,modreader
);
164 if(_mm_eof(modreader
)) {
165 _mm_errno
= MMERR_LOADING_HEADER
;
169 /* set module variables */
172 of
.modtype
= StrDup(MTM_Version
);
173 of
.numchn
= mh
->numchannels
;
174 of
.numtrk
= mh
->numtracks
+1; /* get number of channels */
175 of
.songname
= DupStr(mh
->songname
,20,1); /* make a cstr of songname */
176 of
.numpos
= mh
->lastorder
+1; /* copy the songlength */
177 of
.numpat
= mh
->lastpattern
+1;
179 of
.flags
|= UF_PANNING
;
180 for(t
=0;t
<32;t
++) of
.panning
[t
]=mh
->panpos
[t
]<< 4;
181 of
.numins
=of
.numsmp
=mh
->numsamples
;
183 if(!AllocSamples()) return 0;
185 for(t
=0;t
<of
.numins
;t
++) {
186 /* try to read sample info */
187 _mm_read_string(s
.samplename
,22,modreader
);
188 s
.length
=_mm_read_I_ULONG(modreader
);
189 s
.reppos
=_mm_read_I_ULONG(modreader
);
190 s
.repend
=_mm_read_I_ULONG(modreader
);
191 s
.finetune
=_mm_read_UBYTE(modreader
);
192 s
.volume
=_mm_read_UBYTE(modreader
);
193 s
.attribute
=_mm_read_UBYTE(modreader
);
195 if(_mm_eof(modreader
)) {
196 _mm_errno
= MMERR_LOADING_SAMPLEINFO
;
200 q
->samplename
= DupStr(s
.samplename
,22,1);
202 q
->speed
= finetune
[s
.finetune
];
203 q
->length
= s
.length
;
204 q
->loopstart
= s
.reppos
;
205 q
->loopend
= s
.repend
;
206 q
->volume
= s
.volume
;
207 if((s
.repend
-s
.reppos
)>2) q
->flags
|= SF_LOOP
;
210 /* If the sample is 16-bits, convert the length and replen
211 byte-values into sample-values */
220 if(!AllocPositions(of
.numpos
)) return 0;
221 for(t
=0;t
<of
.numpos
;t
++)
222 of
.positions
[t
]=_mm_read_UBYTE(modreader
);
223 for(;t
<128;t
++) (void)_mm_read_UBYTE(modreader
);
224 if(_mm_eof(modreader
)) {
225 _mm_errno
= MMERR_LOADING_HEADER
;
229 if(!AllocTracks()) return 0;
230 if(!AllocPatterns()) return 0;
232 of
.tracks
[0]=MTM_Convert(); /* track 0 is empty */
233 for(t
=1;t
<of
.numtrk
;t
++) {
237 mtmtrk
[s
].a
=_mm_read_UBYTE(modreader
);
238 mtmtrk
[s
].b
=_mm_read_UBYTE(modreader
);
239 mtmtrk
[s
].c
=_mm_read_UBYTE(modreader
);
242 if(_mm_eof(modreader
)) {
243 _mm_errno
= MMERR_LOADING_TRACK
;
247 if(!(of
.tracks
[t
]=MTM_Convert())) return 0;
250 for(t
=0;t
<of
.numpat
;t
++) {
251 _mm_read_I_UWORDS(pat
,32,modreader
);
252 for(u
=0;u
<of
.numchn
;u
++)
253 of
.patterns
[((long)t
*of
.numchn
)+u
]=pat
[u
];
256 /* read comment field */
258 if(!ReadLinedComment(mh
->commentsize
, 40)) return 0;
263 static CHAR
*MTM_LoadTitle(void)
267 _mm_fseek(modreader
,4,SEEK_SET
);
268 if(!_mm_read_UBYTES(s
,20,modreader
)) return NULL
;
270 return(DupStr(s
,20,1));
273 /*========== Loader information */
275 MIKMODAPI MLOADER load_mtm
={
278 "MTM (MultiTracker Module editor)",