Mercurial > ~darius > hgwebdir.cgi > mikmod
comparison playercode/load_xm.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_XM.C | |
4 | |
5 Description: | |
6 Fasttracker (XM) 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 XMHEADER | |
25 { CHAR id[17]; // ID text: 'Extended module: ' | |
26 CHAR songname[21]; // Module name, padded with zeroes and 0x1a at the end | |
27 CHAR trackername[20]; // Tracker name | |
28 UWORD version; // (word) Version number, hi-byte major and low-byte minor | |
29 ULONG headersize; // Header size | |
30 UWORD songlength; // (word) Song length (in patten order table) | |
31 UWORD restart; // (word) Restart position | |
32 UWORD numchn; // (word) Number of channels (2,4,6,8,10,...,32) | |
33 UWORD numpat; // (word) Number of patterns (max 256) | |
34 UWORD numins; // (word) Number of instruments (max 128) | |
35 UWORD flags; // (word) Flags: bit 0: 0 = Amiga frequency table (see below) 1 = Linear frequency table | |
36 UWORD tempo; // (word) Default tempo | |
37 UWORD bpm; // (word) Default BPM | |
38 UBYTE orders[256]; // (byte) Pattern order table | |
39 } XMHEADER; | |
40 | |
41 | |
42 typedef struct XMINSTHEADER | |
43 { ULONG size; // (dword) Instrument size | |
44 CHAR name[22]; // (char) Instrument name | |
45 UBYTE type; // (byte) Instrument type (always 0) | |
46 UWORD numsmp; // (word) Number of samples in instrument | |
47 ULONG ssize; // | |
48 } XMINSTHEADER; | |
49 | |
50 | |
51 typedef struct XMPATCHHEADER | |
52 { UBYTE what[96]; // (byte) Sample number for all notes | |
53 UWORD volenv[24]; // (byte) Points for volume envelope | |
54 UWORD panenv[24]; // (byte) Points for panning envelope | |
55 UBYTE volpts; // (byte) Number of volume points | |
56 UBYTE panpts; // (byte) Number of panning points | |
57 UBYTE volsus; // (byte) Volume sustain point | |
58 UBYTE volbeg; // (byte) Volume loop start point | |
59 UBYTE volend; // (byte) Volume loop end point | |
60 UBYTE pansus; // (byte) Panning sustain point | |
61 UBYTE panbeg; // (byte) Panning loop start point | |
62 UBYTE panend; // (byte) Panning loop end point | |
63 UBYTE volflg; // (byte) Volume type: bit 0: On; 1: Sustain; 2: Loop | |
64 UBYTE panflg; // (byte) Panning type: bit 0: On; 1: Sustain; 2: Loop | |
65 UBYTE vibflg; // (byte) Vibrato type | |
66 UBYTE vibsweep; // (byte) Vibrato sweep | |
67 UBYTE vibdepth; // (byte) Vibrato depth | |
68 UBYTE vibrate; // (byte) Vibrato rate | |
69 UWORD volfade; // (word) Volume fadeout | |
70 UWORD reserved[11]; // (word) Reserved | |
71 } XMPATCHHEADER; | |
72 | |
73 | |
74 typedef struct XMWAVHEADER | |
75 { ULONG length; // (dword) Sample length | |
76 ULONG loopstart; // (dword) Sample loop start | |
77 ULONG looplength; // (dword) Sample loop length | |
78 UBYTE volume; // (byte) Volume | |
79 SBYTE finetune; // (byte) Finetune (signed byte -128..+127) | |
80 UBYTE type; // (byte) Type: Bit 0-1: 0 = No loop, 1 = Forward loop, | |
81 // 2 = Ping-pong loop; | |
82 // 4: 16-bit sampledata | |
83 UBYTE panning; // (byte) Panning (0-255) | |
84 SBYTE relnote; // (byte) Relative note number (signed byte) | |
85 UBYTE reserved; // (byte) Reserved | |
86 CHAR samplename[22]; // (char) Sample name | |
87 | |
88 UBYTE vibtype; // (byte) Vibrato type | |
89 UBYTE vibsweep; // (byte) Vibrato sweep | |
90 UBYTE vibdepth; // (byte) Vibrato depth | |
91 UBYTE vibrate; // (byte) Vibrato rate | |
92 } XMWAVHEADER; | |
93 | |
94 | |
95 typedef struct XMPATHEADE | |
96 { ULONG size; // (dword) Pattern header length | |
97 UBYTE packing; // (byte) Packing type (always 0) | |
98 UWORD numrows; // (word) Number of rows in pattern (1..256) | |
99 UWORD packsize; // (word) Packed patterndata size | |
100 } XMPATHEADER; | |
101 | |
102 typedef struct MTMNOTE | |
103 { UBYTE a,b,c; | |
104 } MTMNOTE; | |
105 | |
106 | |
107 typedef struct XMNOTE | |
108 { UBYTE note,ins,vol,eff,dat; | |
109 }XMNOTE; | |
110 | |
111 /************************************************************************** | |
112 **************************************************************************/ | |
113 | |
114 static XMNOTE *xmpat = NULL; | |
115 static XMHEADER *mh = NULL; | |
116 | |
117 BOOL XM_Test(void) | |
118 { | |
119 UBYTE id[17]; | |
120 | |
121 if(!_mm_read_UBYTES(id,17,modfp)) return 0; | |
122 if(!memcmp(id,"Extended Module: ",17)) return 1; | |
123 return 0; | |
124 } | |
125 | |
126 | |
127 BOOL XM_Init(void) | |
128 { | |
129 if(!(mh=(XMHEADER *)_mm_calloc(1,sizeof(XMHEADER)))) return 0; | |
130 return 1; | |
131 } | |
132 | |
133 | |
134 void XM_Cleanup(void) | |
135 { | |
136 if(mh!=NULL) free(mh); | |
137 mh = NULL; | |
138 } | |
139 | |
140 | |
141 void XM_ReadNote(XMNOTE *n) | |
142 { | |
143 UBYTE cmp; | |
144 | |
145 memset(n,0,sizeof(XMNOTE)); | |
146 | |
147 cmp = _mm_read_UBYTE(modfp); | |
148 | |
149 if(cmp&0x80) | |
150 { if(cmp&1) n->note = _mm_read_UBYTE(modfp); | |
151 if(cmp&2) n->ins = _mm_read_UBYTE(modfp); | |
152 if(cmp&4) n->vol = _mm_read_UBYTE(modfp); | |
153 if(cmp&8) n->eff = _mm_read_UBYTE(modfp); | |
154 if(cmp&16) n->dat = _mm_read_UBYTE(modfp); | |
155 } | |
156 else | |
157 { n->note = cmp; | |
158 n->ins = _mm_read_UBYTE(modfp); | |
159 n->vol = _mm_read_UBYTE(modfp); | |
160 n->eff = _mm_read_UBYTE(modfp); | |
161 n->dat = _mm_read_UBYTE(modfp); | |
162 } | |
163 } | |
164 | |
165 | |
166 UBYTE *XM_Convert(XMNOTE *xmtrack,UWORD rows) | |
167 { | |
168 int t; | |
169 UBYTE note,ins,vol,eff,dat; | |
170 | |
171 UniReset(); | |
172 | |
173 for(t=0; t<rows; t++) | |
174 { note = xmtrack->note; | |
175 ins = xmtrack->ins; | |
176 vol = xmtrack->vol; | |
177 eff = xmtrack->eff; | |
178 dat = xmtrack->dat; | |
179 | |
180 if(note!=0) | |
181 { if(note==97) | |
182 { UniWrite(UNI_KEYFADE); | |
183 UniWrite(0); | |
184 } else | |
185 UniNote(note-1); | |
186 } | |
187 | |
188 if(ins!=0) UniInstrument(ins-1); | |
189 | |
190 switch(vol>>4) | |
191 { | |
192 case 0x6: // volslide down | |
193 if(vol&0xf) | |
194 { UniWrite(UNI_XMEFFECTA); | |
195 UniWrite(vol&0xf); | |
196 } | |
197 break; | |
198 | |
199 case 0x7: // volslide up | |
200 if(vol&0xf) | |
201 { UniWrite(UNI_XMEFFECTA); | |
202 UniWrite(vol<<4); | |
203 } | |
204 break; | |
205 | |
206 // volume-row fine volume slide is compatible with protracker | |
207 // EBx and EAx effects i.e. a zero nibble means DO NOT SLIDE, as | |
208 // opposed to 'take the last sliding value'. | |
209 | |
210 case 0x8: // finevol down | |
211 UniPTEffect(0xe,0xb0 | (vol&0xf)); | |
212 break; | |
213 | |
214 case 0x9: // finevol up | |
215 UniPTEffect(0xe,0xa0 | (vol&0xf)); | |
216 break; | |
217 | |
218 case 0xa: // set vibrato speed | |
219 UniPTEffect(0x4,vol<<4); | |
220 break; | |
221 | |
222 case 0xb: // vibrato | |
223 UniPTEffect(0x4,vol&0xf); | |
224 break; | |
225 | |
226 case 0xc: // set panning | |
227 UniPTEffect(0x8,vol<<4); | |
228 break; | |
229 | |
230 case 0xd: // panning slide left | |
231 // only slide when data nibble not zero: | |
232 | |
233 if(vol&0xf) | |
234 { UniWrite(UNI_XMEFFECTP); | |
235 UniWrite(vol&0xf); | |
236 } | |
237 break; | |
238 | |
239 case 0xe: // panning slide right | |
240 // only slide when data nibble not zero: | |
241 | |
242 if(vol&0xf) | |
243 { UniWrite(UNI_XMEFFECTP); | |
244 UniWrite(vol<<4); | |
245 } | |
246 break; | |
247 | |
248 case 0xf: // tone porta | |
249 UniPTEffect(0x3,vol<<4); | |
250 break; | |
251 | |
252 default: | |
253 if(vol>=0x10 && vol<=0x50) | |
254 UniPTEffect(0xc,vol-0x10); | |
255 } | |
256 | |
257 switch(eff) | |
258 { | |
259 case 0x4: // Effect 4: Vibrato | |
260 UniWrite(UNI_XMEFFECT4); | |
261 UniWrite(dat); | |
262 break; | |
263 | |
264 case 0xa: | |
265 UniWrite(UNI_XMEFFECTA); | |
266 UniWrite(dat); | |
267 break; | |
268 | |
269 case 0xe: | |
270 switch(dat>>4) | |
271 { case 0x1: // XM fine porta up | |
272 UniWrite(UNI_XMEFFECTE1); | |
273 UniWrite(dat&0xf); | |
274 break; | |
275 | |
276 case 0x2: // XM fine porta down | |
277 UniWrite(UNI_XMEFFECTE2); | |
278 UniWrite(dat&0xf); | |
279 break; | |
280 | |
281 case 0xa: // XM fine volume up | |
282 UniWrite(UNI_XMEFFECTEA); | |
283 UniWrite(dat&0xf); | |
284 break; | |
285 | |
286 case 0xb: // XM fine volume down | |
287 UniWrite(UNI_XMEFFECTEB); | |
288 UniWrite(dat&0xf); | |
289 break; | |
290 | |
291 default: | |
292 UniPTEffect(0x0e,dat); | |
293 } | |
294 break; | |
295 | |
296 case 'G'-55: // G - set global volume | |
297 if(dat>64) dat = 64; | |
298 UniWrite(UNI_XMEFFECTG); | |
299 UniWrite(dat); | |
300 break; | |
301 | |
302 case 'H'-55: // H - global volume slide | |
303 UniWrite(UNI_XMEFFECTH); | |
304 UniWrite(dat); | |
305 break; | |
306 | |
307 case 'K'-55: // K - keyOff and KeyFade | |
308 UniWrite(UNI_KEYFADE); | |
309 UniWrite(dat); | |
310 break; | |
311 | |
312 case 'L'-55: // L - set envelope position | |
313 UniWrite(UNI_XMEFFECTL); | |
314 UniWrite(dat); | |
315 break; | |
316 | |
317 case 'P'-55: // P - panning slide | |
318 UniWrite(UNI_XMEFFECTP); | |
319 UniWrite(dat); | |
320 break; | |
321 | |
322 case 'R'-55: // R - multi retrig note | |
323 UniWrite(UNI_S3MEFFECTQ); | |
324 UniWrite(dat); | |
325 break; | |
326 | |
327 case 'T'-55: // T - Tremor !! (== S3M effect I) | |
328 UniWrite(UNI_S3MEFFECTI); | |
329 UniWrite(dat); | |
330 break; | |
331 | |
332 case 'X'-55: | |
333 if((dat>>4) == 1) // X1 - Extra Fine Porta up | |
334 { UniWrite(UNI_XMEFFECTX1); | |
335 UniWrite(dat & 0xf); | |
336 } else if((dat>>4) == 2) // X2 - Extra Fine Porta down | |
337 { UniWrite(UNI_XMEFFECTX2); | |
338 UniWrite(dat & 0xf); | |
339 } | |
340 break; | |
341 | |
342 default: | |
343 if(eff <= 0xf) | |
344 { // Convert pattern jump from Dec to Hex | |
345 if(eff == 0xd) | |
346 dat = (((dat&0xf0)>>4)*10)+(dat&0xf); | |
347 UniPTEffect(eff,dat); | |
348 } | |
349 break; | |
350 } | |
351 | |
352 UniNewline(); | |
353 xmtrack++; | |
354 } | |
355 return UniDup(); | |
356 } | |
357 | |
358 | |
359 | |
360 BOOL XM_Load(void) | |
361 { | |
362 INSTRUMENT *d; | |
363 SAMPLE *q; | |
364 XMWAVHEADER *wh,*s; | |
365 int t,u,v,p,numtrk; | |
366 long next; | |
367 ULONG nextwav[256]; | |
368 BOOL dummypat=0; | |
369 | |
370 // try to read module header | |
371 | |
372 _mm_read_string(mh->id,17,modfp); | |
373 _mm_read_string(mh->songname,21,modfp); | |
374 _mm_read_string(mh->trackername,20,modfp); | |
375 mh->version =_mm_read_I_UWORD(modfp); | |
376 mh->headersize =_mm_read_I_ULONG(modfp); | |
377 mh->songlength =_mm_read_I_UWORD(modfp); | |
378 mh->restart =_mm_read_I_UWORD(modfp); | |
379 mh->numchn =_mm_read_I_UWORD(modfp); | |
380 mh->numpat =_mm_read_I_UWORD(modfp); | |
381 mh->numins =_mm_read_I_UWORD(modfp); | |
382 mh->flags =_mm_read_I_UWORD(modfp); | |
383 mh->tempo =_mm_read_I_UWORD(modfp); | |
384 mh->bpm =_mm_read_I_UWORD(modfp); | |
385 _mm_read_UBYTES(mh->orders,256,modfp); | |
386 | |
387 if(feof(modfp)) | |
388 { _mm_errno = MMERR_LOADING_HEADER; | |
389 return 0; | |
390 } | |
391 | |
392 // set module variables | |
393 of.initspeed = mh->tempo; | |
394 of.inittempo = mh->bpm; | |
395 of.modtype = DupStr(mh->trackername,20); | |
396 of.numchn = mh->numchn; | |
397 of.numpat = mh->numpat; | |
398 of.numtrk = (UWORD)of.numpat*of.numchn; // get number of channels | |
399 of.songname = DupStr(mh->songname,20); // make a cstr of songname | |
400 of.numpos = mh->songlength; // copy the songlength | |
401 of.reppos = mh->restart; | |
402 of.numins = mh->numins; | |
403 of.flags |= UF_XMPERIODS | UF_INST; | |
404 if(mh->flags&1) of.flags |= UF_LINEAR; | |
405 | |
406 memset(of.chanvol,64,of.numchn); // store channel volumes | |
407 | |
408 if(!AllocPositions(of.numpos+3)) return 0; | |
409 for(t=0; t<of.numpos; t++) | |
410 of.positions[t] = mh->orders[t]; | |
411 | |
412 /* | |
413 WHY THIS CODE HERE?? I CAN'T REMEMBER! | |
414 | |
415 Well, I do know why, mikmak! Seems that FT2 doesn't always count blank | |
416 patterns AT ALL if they are at the END of the song. So, we have to check | |
417 for any patter numbers in the order list greater than the number of pat- | |
418 terns total. If one or more is found, we set it equal to the pattern total | |
419 and make a dummy pattern to accomidate for the discrepency! | |
420 */ | |
421 | |
422 for(t=0; t<of.numpos; t++) | |
423 { if(of.positions[t] > of.numpat) | |
424 { of.positions[t] = of.numpat; | |
425 dummypat = 1; | |
426 } | |
427 } | |
428 | |
429 if(dummypat) { of.numpat++; of.numtrk+=of.numchn; } | |
430 | |
431 if(!AllocTracks()) return 0; | |
432 if(!AllocPatterns()) return 0; | |
433 | |
434 numtrk = 0; | |
435 for(t=0; t<mh->numpat; t++) | |
436 { XMPATHEADER ph; | |
437 | |
438 ph.size =_mm_read_I_ULONG(modfp); | |
439 ph.packing =_mm_read_UBYTE(modfp); | |
440 ph.numrows =_mm_read_I_UWORD(modfp); | |
441 ph.packsize =_mm_read_I_UWORD(modfp); | |
442 | |
443 of.pattrows[t] = ph.numrows; | |
444 | |
445 // Gr8.. when packsize is 0, don't try to load a pattern.. it's empty. | |
446 // This bug was discovered thanks to Khyron's module.. | |
447 | |
448 if(!(xmpat=(XMNOTE *)_mm_calloc(ph.numrows*of.numchn,sizeof(XMNOTE)))) return 0; | |
449 | |
450 if(ph.packsize>0) | |
451 { for(u=0; u<ph.numrows; u++) | |
452 { for(v=0; v<of.numchn; v++) | |
453 XM_ReadNote(&xmpat[(v*ph.numrows)+u]); | |
454 } | |
455 } | |
456 | |
457 if(feof(modfp)) | |
458 { _mm_errno = MMERR_LOADING_PATTERN; | |
459 return 0; | |
460 } | |
461 | |
462 for(v=0; v<of.numchn; v++) | |
463 of.tracks[numtrk++] = XM_Convert(&xmpat[v*ph.numrows],ph.numrows); | |
464 | |
465 free(xmpat); | |
466 } | |
467 | |
468 if(dummypat) | |
469 { of.pattrows[t] = 64; | |
470 if(!(xmpat=(XMNOTE *)_mm_calloc(64*of.numchn,sizeof(XMNOTE)))) return 0; | |
471 for(v=0; v<of.numchn; v++) | |
472 of.tracks[numtrk++] = XM_Convert(&xmpat[v*64],64); | |
473 free(xmpat); | |
474 } | |
475 | |
476 if(!AllocInstruments()) return 0; | |
477 if((wh = (XMWAVHEADER *)_mm_calloc(256,sizeof(XMWAVHEADER))) == NULL) return 0; | |
478 d = of.instruments; | |
479 s = wh; | |
480 | |
481 | |
482 for(t=0; t<of.numins; t++) | |
483 { XMINSTHEADER ih; | |
484 int headend; | |
485 | |
486 memset(d->samplenumber,255,120); | |
487 | |
488 // read instrument header | |
489 | |
490 headend = _mm_ftell(modfp); | |
491 ih.size = _mm_read_I_ULONG(modfp); | |
492 headend += ih.size; | |
493 _mm_read_string(ih.name, 22, modfp); | |
494 ih.type = _mm_read_UBYTE(modfp); | |
495 ih.numsmp = _mm_read_I_UWORD(modfp); | |
496 d->insname = DupStr(ih.name,22); | |
497 | |
498 if(ih.size > 29) | |
499 { ih.ssize = _mm_read_I_ULONG(modfp); | |
500 if(ih.numsmp > 0) | |
501 { XMPATCHHEADER pth; | |
502 | |
503 _mm_read_UBYTES (pth.what, 96, modfp); | |
504 _mm_read_I_UWORDS (pth.volenv, 24, modfp); | |
505 _mm_read_I_UWORDS (pth.panenv, 24, modfp); | |
506 pth.volpts = _mm_read_UBYTE(modfp); | |
507 pth.panpts = _mm_read_UBYTE(modfp); | |
508 pth.volsus = _mm_read_UBYTE(modfp); | |
509 pth.volbeg = _mm_read_UBYTE(modfp); | |
510 pth.volend = _mm_read_UBYTE(modfp); | |
511 pth.pansus = _mm_read_UBYTE(modfp); | |
512 pth.panbeg = _mm_read_UBYTE(modfp); | |
513 pth.panend = _mm_read_UBYTE(modfp); | |
514 pth.volflg = _mm_read_UBYTE(modfp); | |
515 pth.panflg = _mm_read_UBYTE(modfp); | |
516 pth.vibflg = _mm_read_UBYTE(modfp); | |
517 pth.vibsweep = _mm_read_UBYTE(modfp); | |
518 pth.vibdepth = _mm_read_UBYTE(modfp); | |
519 pth.vibrate = _mm_read_UBYTE(modfp); | |
520 pth.volfade = _mm_read_I_UWORD(modfp); | |
521 | |
522 // read the remainder of the header | |
523 for(u=headend-_mm_ftell(modfp); u; u--) _mm_read_UBYTE(modfp); | |
524 | |
525 if(feof(modfp)) | |
526 { _mm_errno = MMERR_LOADING_SAMPLEINFO; | |
527 return 0; | |
528 } | |
529 | |
530 for(u=0; u<96; u++) | |
531 d->samplenumber[u] = pth.what[u] + of.numsmp; | |
532 | |
533 d->volfade = pth.volfade; | |
534 | |
535 memcpy(d->volenv,pth.volenv,24); | |
536 if(pth.volflg & 1) d->volflg |= EF_ON; | |
537 if(pth.volflg & 2) d->volflg |= EF_SUSTAIN; | |
538 if(pth.volflg & 4) d->volflg |= EF_LOOP; | |
539 d->volsusbeg = d->volsusend = pth.volsus; | |
540 d->volbeg = pth.volbeg; | |
541 d->volend = pth.volend; | |
542 d->volpts = pth.volpts; | |
543 | |
544 // scale volume envelope: | |
545 | |
546 for(p=0; p<12; p++) | |
547 d->volenv[p].val <<= 2; | |
548 | |
549 if((d->volflg & EF_ON) && (d->volpts < 2)) | |
550 d->volflg &= ~EF_ON; | |
551 | |
552 memcpy(d->panenv,pth.panenv,24); | |
553 d->panflg = pth.panflg; | |
554 d->pansusbeg = d->pansusend = pth.pansus; | |
555 d->panbeg = pth.panbeg; | |
556 d->panend = pth.panend; | |
557 d->panpts = pth.panpts; | |
558 | |
559 // scale panning envelope: | |
560 | |
561 for(p=0; p<12; p++) | |
562 d->panenv[p].val <<= 2; | |
563 if((d->panflg & EF_ON) && (d->panpts < 2)) | |
564 d->panflg &= ~EF_ON; | |
565 | |
566 next = 0; | |
567 | |
568 // Samples are stored outside the instrument struct now, so we have | |
569 // to load them all into a temp area, count the of.numsmp along the | |
570 // way and then do an AllocSamples() and move everything over | |
571 | |
572 for(u=0; u<ih.numsmp; u++,s++) | |
573 { s->length =_mm_read_I_ULONG (modfp); | |
574 s->loopstart =_mm_read_I_ULONG (modfp); | |
575 s->looplength =_mm_read_I_ULONG (modfp); | |
576 s->volume =_mm_read_UBYTE (modfp); | |
577 s->finetune =_mm_read_SBYTE (modfp); | |
578 s->type =_mm_read_UBYTE (modfp); | |
579 s->panning =_mm_read_UBYTE (modfp); | |
580 s->relnote =_mm_read_SBYTE (modfp); | |
581 s->vibtype = pth.vibflg; | |
582 s->vibsweep = pth.vibsweep; | |
583 s->vibdepth = pth.vibdepth*4; | |
584 s->vibrate = pth.vibrate; | |
585 | |
586 s->reserved =_mm_read_UBYTE (modfp); | |
587 _mm_read_string(s->samplename, 22, modfp); | |
588 | |
589 nextwav[of.numsmp+u] = next; | |
590 next += s->length; | |
591 | |
592 if(feof(modfp)) | |
593 { _mm_errno = MMERR_LOADING_SAMPLEINFO; | |
594 return 0; | |
595 } | |
596 } | |
597 | |
598 for(u=0; u<ih.numsmp; u++) nextwav[of.numsmp++] += _mm_ftell(modfp); | |
599 _mm_fseek(modfp,next,SEEK_CUR); | |
600 } | |
601 } | |
602 | |
603 d++; | |
604 } | |
605 | |
606 if(!AllocSamples()) return 0; | |
607 q = of.samples; | |
608 s = wh; | |
609 | |
610 for(u=0; u<of.numsmp; u++,q++,s++) | |
611 { q->samplename = DupStr(s->samplename,22); | |
612 q->length = s->length; | |
613 q->loopstart = s->loopstart; | |
614 q->loopend = s->loopstart+s->looplength; | |
615 q->volume = s->volume; | |
616 q->speed = s->finetune+128; | |
617 q->panning = s->panning; | |
618 q->seekpos = nextwav[u]; | |
619 q->vibtype = s->vibtype; | |
620 q->vibsweep = s->vibsweep; | |
621 q->vibdepth = s->vibdepth; | |
622 q->vibrate = s->vibrate; | |
623 | |
624 if(s->type & 0x10) | |
625 { q->length >>= 1; | |
626 q->loopstart >>= 1; | |
627 q->loopend >>= 1; | |
628 } | |
629 | |
630 q->flags|=SF_OWNPAN; | |
631 if(s->type&0x3) q->flags|=SF_LOOP; | |
632 if(s->type&0x2) q->flags|=SF_BIDI; | |
633 | |
634 if(s->type&0x10) q->flags|=SF_16BITS; | |
635 q->flags|=SF_DELTA; | |
636 q->flags|=SF_SIGNED; | |
637 } | |
638 | |
639 d = of.instruments; | |
640 s = wh; | |
641 for(u=0; u<of.numins; u++, d++) | |
642 { /*for(t=0; t<3; t++) | |
643 if((s[d->samplenumber[t]].relnote / 12) > ) | |
644 { s[d->samplenumber[t]].relnote -= 12; | |
645 of.samples[d->samplenumber[t]].speed <<= 1; | |
646 } | |
647 */ | |
648 for(t=0; t<96; t++) | |
649 d->samplenote[t] = (d->samplenumber[t]==of.numsmp) ? 255 : (t+s[d->samplenumber[t]].relnote); | |
650 } | |
651 | |
652 free(wh); | |
653 return 1; | |
654 } | |
655 | |
656 | |
657 | |
658 CHAR *XM_LoadTitle(void) | |
659 { | |
660 CHAR s[21]; | |
661 | |
662 _mm_fseek(modfp,17,SEEK_SET); | |
663 if(!fread(s,21,1,modfp)) return NULL; | |
664 | |
665 return(DupStr(s,21)); | |
666 } | |
667 | |
668 | |
669 | |
670 MLOADER load_xm = | |
671 { NULL, | |
672 "XM", | |
673 "Portable XM loader v0.5", | |
674 XM_Init, | |
675 XM_Test, | |
676 XM_Load, | |
677 XM_Cleanup, | |
678 XM_LoadTitle | |
679 }; |