4
|
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 };
|