Mercurial > ~darius > hgwebdir.cgi > mikmod
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 |