comparison playercode/load_mtm.c @ 4:5d614bcc4287

Initial entry of mikmod into the CVS tree.
author darius
date Fri, 23 Jan 1998 16:05:08 +0000
parents
children
comparison
equal deleted inserted replaced
3:71e20a32bd84 4:5d614bcc4287
1 /*
2
3 Name: LOAD_MTM.C
4
5 Description:
6 MTM module loader
7
8 Portability:
9 All systems - all compilers (hopefully)
10
11 If this module is found to not be portable to any particular platform,
12 please contact Jake Stine at dracoirs@epix.net (see MIKMOD.TXT for
13 more information on contacting the author).
14
15 */
16
17 #include <string.h>
18 #include "mikmod.h"
19
20 /**************************************************************************
21 **************************************************************************/
22
23
24 typedef struct MTMSAMPLE
25 { CHAR samplename[22];
26 ULONG length;
27 ULONG reppos;
28 ULONG repend;
29 UBYTE finetune;
30 UBYTE volume;
31 UBYTE attribute;
32 } MTMSAMPLE;
33
34
35
36 typedef struct MTMHEADER
37 { UBYTE id[3]; // MTM file marker
38 UBYTE version; // upper major, lower nibble minor version number
39 char songname[20]; // ASCIIZ songname
40 UWORD numtracks; // number of tracks saved
41 UBYTE lastpattern; // last pattern number saved
42 UBYTE lastorder; // last order number to play (songlength-1)
43 UWORD commentsize; // length of comment field
44 UBYTE numsamples; // number of samples saved
45 UBYTE attribute; // attribute byte (unused)
46 UBYTE beatspertrack; //
47 UBYTE numchannels; // number of channels used
48 UBYTE panpos[32]; // voice pan positions
49 } MTMHEADER;
50
51
52 typedef struct MTMNOTE
53 { UBYTE a,b,c;
54 } MTMNOTE;
55
56
57 /**************************************************************************
58 **************************************************************************/
59
60
61 static MTMHEADER *mh = NULL;
62 static MTMNOTE *mtmtrk = NULL;
63 static UWORD pat[32];
64
65 char MTM_Version[] = "MTM";
66
67
68
69 BOOL MTM_Test(void)
70 {
71 UBYTE id[3];
72 if(!_mm_read_UBYTES(id,3,modfp)) return 0;
73 if(!memcmp(id,"MTM",3)) return 1;
74 return 0;
75 }
76
77
78 BOOL MTM_Init(void)
79 {
80 if(!(mtmtrk=(MTMNOTE *)_mm_calloc(64,sizeof(MTMNOTE)))) return 0;
81 if(!(mh=(MTMHEADER *)_mm_calloc(1,sizeof(MTMHEADER)))) return 0;
82
83 return 1;
84 }
85
86
87 void MTM_Cleanup(void)
88 {
89 if(mtmtrk!=NULL) free(mtmtrk);
90 if(mh!=NULL) free(mh);
91
92 mtmtrk = NULL;
93 mh = NULL;
94 }
95
96
97 UBYTE *MTM_Convert(void)
98 {
99 int t;
100 UBYTE a,b,c,inst,note,eff,dat;
101
102 UniReset();
103 for(t=0; t<64; t++)
104 { a = mtmtrk[t].a;
105 b = mtmtrk[t].b;
106 c = mtmtrk[t].c;
107
108 inst = ((a&0x3)<<4)|(b>>4);
109 note = a>>2;
110
111 eff = b&0xf;
112 dat = c;
113
114 if(inst!=0) UniInstrument(inst-1);
115 if(note!=0) UniNote(note+24);
116
117 // mtm bug bugfix: when the effect is volslide,
118 // slide-up _always_ overrides slide-dn.
119
120 if(eff==0xa && dat&0xf0) dat&=0xf0;
121
122 // Convert pattern jump from Dec to Hex
123 if(eff == 0xd)
124 dat = (((dat&0xf0)>>4)*10)+(dat&0xf);
125 UniPTEffect(eff,dat);
126 UniNewline();
127 }
128 return UniDup();
129 }
130
131
132 BOOL MTM_Load(void)
133 {
134 MTMSAMPLE s;
135 SAMPLE *q;
136
137 int t,u;
138
139 // try to read module header
140
141 _mm_read_UBYTES(mh->id,3,modfp);
142 mh->version =_mm_read_UBYTE(modfp);
143 _mm_read_string(mh->songname,20,modfp);
144 mh->numtracks =_mm_read_I_UWORD(modfp);
145 mh->lastpattern =_mm_read_UBYTE(modfp);
146 mh->lastorder =_mm_read_UBYTE(modfp);
147 mh->commentsize =_mm_read_I_UWORD(modfp);
148 mh->numsamples =_mm_read_UBYTE(modfp);
149 mh->attribute =_mm_read_UBYTE(modfp);
150 mh->beatspertrack=_mm_read_UBYTE(modfp);
151 mh->numchannels =_mm_read_UBYTE(modfp);
152 _mm_read_UBYTES(mh->panpos,32,modfp);
153
154 if(feof(modfp))
155 { _mm_errno = MMERR_LOADING_HEADER;
156 return 0;
157 }
158
159 // set module variables
160
161 of.initspeed = 6;
162 of.inittempo = 125;
163 of.modtype = strdup(MTM_Version);
164 of.numchn = mh->numchannels;
165 of.numtrk = mh->numtracks+1; // get number of channels
166 of.songname = DupStr(mh->songname,20); // make a cstr of songname
167 of.numpos = mh->lastorder+1; // copy the songlength
168 of.numpat = mh->lastpattern+1;
169 for(t=0; t<32; t++) of.panning[t] = mh->panpos[t] << 4;
170
171 of.numins = of.numsmp = mh->numsamples;
172 if(!AllocSamples()) return 0;
173
174 q = of.samples;
175
176 for(t=0; t<of.numins; t++)
177 { // try to read sample info
178 _mm_read_string(s.samplename,22,modfp);
179 s.length =_mm_read_I_ULONG(modfp);
180 s.reppos =_mm_read_I_ULONG(modfp);
181 s.repend =_mm_read_I_ULONG(modfp);
182 s.finetune =_mm_read_UBYTE(modfp);
183 s.volume =_mm_read_UBYTE(modfp);
184 s.attribute =_mm_read_UBYTE(modfp);
185
186 if(feof(modfp))
187 { _mm_errno = MMERR_LOADING_SAMPLEINFO;
188 return 0;
189 }
190
191 q->samplename = DupStr(s.samplename,22);
192 q->seekpos = 0;
193 q->speed = finetune[s.finetune];
194 q->length = s.length;
195 q->loopstart = s.reppos;
196 q->loopend = s.repend;
197 q->volume = s.volume;
198
199 if((s.repend-s.reppos) > 2) q->flags |= SF_LOOP;
200
201 if(s.attribute & 1)
202 { // If the sample is 16-bits, convert the length
203 // and replen byte-values into sample-values
204
205 q->flags|=SF_16BITS;
206 q->length>>=1;
207 q->loopstart>>=1;
208 q->loopend>>=1;
209 }
210
211 q++;
212 }
213
214 if(!AllocPositions(of.numpos)) return 0;
215 for(t=0; t<of.numpos; t++)
216 of.positions[t] = _mm_read_UBYTE(modfp);
217 for(; t<128; t++) _mm_read_UBYTE(modfp);
218
219 if(feof(modfp))
220 { _mm_errno = MMERR_LOADING_HEADER;
221 return 0;
222 }
223
224 if(!AllocTracks()) return 0;
225 if(!AllocPatterns()) return 0;
226
227 of.tracks[0] = MTM_Convert(); // track 0 is empty
228
229 for(t=1; t<of.numtrk; t++)
230 { int s;
231
232 for(s=0; s<64; s++)
233 { mtmtrk[s].a=_mm_read_UBYTE(modfp);
234 mtmtrk[s].b=_mm_read_UBYTE(modfp);
235 mtmtrk[s].c=_mm_read_UBYTE(modfp);
236 }
237
238 if(feof(modfp))
239 { _mm_errno = MMERR_LOADING_TRACK;
240 return 0;
241 }
242
243 if(!(of.tracks[t]=MTM_Convert())) return 0;
244 }
245
246 for(t=0; t<of.numpat; t++)
247 { _mm_read_I_UWORDS(pat,32,modfp);
248
249 for(u=0; u<of.numchn; u++)
250 of.patterns[((long)t*of.numchn)+u]=pat[u];
251 }
252
253 // read comment field
254
255 if(!ReadComment(mh->commentsize)) return 0;
256
257 return 1;
258 }
259
260
261 CHAR *MTM_LoadTitle(void)
262 {
263 CHAR s[20];
264
265 _mm_fseek(modfp,4,SEEK_SET);
266 if(!fread(s,20,1,modfp)) return NULL;
267
268 return(DupStr(s,20));
269 }
270
271
272 MLOADER load_mtm =
273 { NULL,
274 "MTM",
275 "Portable MTM loader v0.1",
276 MTM_Init,
277 MTM_Test,
278 MTM_Load,
279 MTM_Cleanup,
280 MTM_LoadTitle
281 };
282