1 /* MikMod sound library
2 (c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
3 AUTHORS for complete list.
4
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.
9
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.
14
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
18 02111-1307, USA.
19 */
20
21 /*==============================================================================
22
23 $Id$
24
25 Fasttracker (XM) module loader
26
27 ==============================================================================*/
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36
37 #include <stdio.h>
38 #ifdef HAVE_MEMORY_H
39 #include <memory.h>
40 #endif
41 #include <string.h>
42
43 #include "mikmod_internals.h"
44
45 #ifdef SUNOS
46 extern int fprintf(FILE *, const char *, ...);
47 #endif
48
49 /*========== Module structure */
50
51 typedef struct XMHEADER {
52 CHAR id[17]; /* ID text: 'Extended module: ' */
53 CHAR songname[21]; /* Module name */
54 CHAR trackername[20]; /* Tracker name */
55 UWORD version; /* Version number */
56 ULONG headersize; /* Header size */
57 UWORD songlength; /* Song length (in patten order table) */
58 UWORD restart; /* Restart position */
59 UWORD numchn; /* Number of channels (2,4,6,8,10,...,32) */
60 UWORD numpat; /* Number of patterns (max 256) */
61 UWORD numins; /* Number of instruments (max 128) */
62 UWORD flags;
63 UWORD tempo; /* Default tempo */
64 UWORD bpm; /* Default BPM */
65 UBYTE orders[256]; /* Pattern order table */
66 } XMHEADER;
67
68 typedef struct XMINSTHEADER {
69 ULONG size; /* Instrument size */
70 CHAR name[22]; /* Instrument name */
71 UBYTE type; /* Instrument type (always 0) */
72 UWORD numsmp; /* Number of samples in instrument */
73 ULONG ssize;
74 } XMINSTHEADER;
75
76 #define XMENVCNT (12*2)
77 #define XMNOTECNT (8*OCTAVE)
78 typedef struct XMPATCHHEADER {
79 UBYTE what[XMNOTECNT]; /* Sample number for all notes */
80 UWORD volenv[XMENVCNT]; /* Points for volume envelope */
81 UWORD panenv[XMENVCNT]; /* Points for panning envelope */
82 UBYTE volpts; /* Number of volume points */
83 UBYTE panpts; /* Number of panning points */
84 UBYTE volsus; /* Volume sustain point */
85 UBYTE volbeg; /* Volume loop start point */
86 UBYTE volend; /* Volume loop end point */
87 UBYTE pansus; /* Panning sustain point */
88 UBYTE panbeg; /* Panning loop start point */
89 UBYTE panend; /* Panning loop end point */
90 UBYTE volflg; /* Volume type: bit 0: On; 1: Sustain; 2: Loop */
91 UBYTE panflg; /* Panning type: bit 0: On; 1: Sustain; 2: Loop */
92 UBYTE vibflg; /* Vibrato type */
93 UBYTE vibsweep; /* Vibrato sweep */
94 UBYTE vibdepth; /* Vibrato depth */
95 UBYTE vibrate; /* Vibrato rate */
96 UWORD volfade; /* Volume fadeout */
97 } XMPATCHHEADER;
98
99 typedef struct XMWAVHEADER {
100 ULONG length; /* Sample length */
101 ULONG loopstart; /* Sample loop start */
102 ULONG looplength; /* Sample loop length */
103 UBYTE volume; /* Volume */
104 SBYTE finetune; /* Finetune (signed byte -128..+127) */
105 UBYTE type; /* Loop type */
106 UBYTE panning; /* Panning (0-255) */
107 SBYTE relnote; /* Relative note number (signed byte) */
108 UBYTE reserved;
109 CHAR samplename[22]; /* Sample name */
110 UBYTE vibtype; /* Vibrato type */
111 UBYTE vibsweep; /* Vibrato sweep */
112 UBYTE vibdepth; /* Vibrato depth */
113 UBYTE vibrate; /* Vibrato rate */
114 } XMWAVHEADER;
115
116 typedef struct XMPATHEADER {
117 ULONG size; /* Pattern header length */
118 UBYTE packing; /* Packing type (always 0) */
119 UWORD numrows; /* Number of rows in pattern (1..256) */
120 SWORD packsize; /* Packed patterndata size */
121 } XMPATHEADER;
122
123 typedef struct XMNOTE {
124 UBYTE note,ins,vol,eff,dat;
125 } XMNOTE;
126
127 /*========== Loader variables */
128
129 static XMNOTE *xmpat=NULL;
130 static XMHEADER *mh=NULL;
131
132 /* increment unit for sample array reallocation */
133 #define XM_SMPINCR 64
134 static ULONG *nextwav=NULL;
135 static XMWAVHEADER *wh=NULL,*s=NULL;
136
137 /*========== Loader code */
138
XM_Test(void)139 static BOOL XM_Test(void)
140 {
141 UBYTE id[38];
142
143 if(!_mm_read_UBYTES(id,38,modreader)) return 0;
144 if(memcmp(id,"Extended Module: ",17)) return 0;
145 if(id[37]==0x1a) return 1;
146 return 0;
147 }
148
XM_Init(void)149 static BOOL XM_Init(void)
150 {
151 if(!(mh=(XMHEADER *)MikMod_malloc(sizeof(XMHEADER)))) return 0;
152 return 1;
153 }
154
XM_Cleanup(void)155 static void XM_Cleanup(void)
156 {
157 MikMod_free(mh);
158 mh=NULL;
159 }
160
XM_ReadNote(XMNOTE * n)161 static int XM_ReadNote(XMNOTE* n)
162 {
163 UBYTE cmp,result=1;
164
165 memset(n,0,sizeof(XMNOTE));
166 cmp=_mm_read_UBYTE(modreader);
167
168 if(cmp&0x80) {
169 if(cmp&1) { result++;n->note = _mm_read_UBYTE(modreader); }
170 if(cmp&2) { result++;n->ins = _mm_read_UBYTE(modreader); }
171 if(cmp&4) { result++;n->vol = _mm_read_UBYTE(modreader); }
172 if(cmp&8) { result++;n->eff = _mm_read_UBYTE(modreader); }
173 if(cmp&16) { result++;n->dat = _mm_read_UBYTE(modreader); }
174 } else {
175 n->note = cmp;
176 n->ins = _mm_read_UBYTE(modreader);
177 n->vol = _mm_read_UBYTE(modreader);
178 n->eff = _mm_read_UBYTE(modreader);
179 n->dat = _mm_read_UBYTE(modreader);
180 result += 4;
181 }
182 return result;
183 }
184
XM_Convert(XMNOTE * xmtrack,UWORD rows)185 static UBYTE* XM_Convert(XMNOTE* xmtrack,UWORD rows)
186 {
187 int t;
188 UBYTE note,ins,vol,eff,dat;
189
190 UniReset();
191 for(t=0;t<rows;t++) {
192 note = xmtrack->note;
193 ins = xmtrack->ins;
194 vol = xmtrack->vol;
195 eff = xmtrack->eff;
196 dat = xmtrack->dat;
197
198 if(note) {
199 if(note>XMNOTECNT)
200 UniEffect(UNI_KEYFADE,0);
201 else
202 UniNote(note-1);
203 }
204 if(ins) UniInstrument(ins-1);
205
206 switch(vol>>4) {
207 case 0x6: /* volslide down */
208 if(vol&0xf) UniEffect(UNI_XMEFFECTA,vol&0xf);
209 break;
210 case 0x7: /* volslide up */
211 if(vol&0xf) UniEffect(UNI_XMEFFECTA,vol<<4);
212 break;
213
214 /* volume-row fine volume slide is compatible with protracker
215 EBx and EAx effects i.e. a zero nibble means DO NOT SLIDE, as
216 opposed to 'take the last sliding value'. */
217 case 0x8: /* finevol down */
218 UniPTEffect(0xe,0xb0|(vol&0xf));
219 break;
220 case 0x9: /* finevol up */
221 UniPTEffect(0xe,0xa0|(vol&0xf));
222 break;
223 case 0xa: /* set vibrato speed */
224 UniEffect(UNI_XMEFFECT4,vol<<4);
225 break;
226 case 0xb: /* vibrato */
227 UniEffect(UNI_XMEFFECT4,vol&0xf);
228 break;
229 case 0xc: /* set panning */
230 UniPTEffect(0x8,vol<<4);
231 break;
232 case 0xd: /* panning slide left (only slide when data not zero) */
233 if(vol&0xf) UniEffect(UNI_XMEFFECTP,vol&0xf);
234 break;
235 case 0xe: /* panning slide right (only slide when data not zero) */
236 if(vol&0xf) UniEffect(UNI_XMEFFECTP,vol<<4);
237 break;
238 case 0xf: /* tone porta */
239 UniPTEffect(0x3,vol<<4);
240 break;
241 default:
242 if((vol>=0x10)&&(vol<=0x50))
243 UniPTEffect(0xc,vol-0x10);
244 }
245
246 switch(eff) {
247 case 0x4:
248 UniEffect(UNI_XMEFFECT4,dat);
249 break;
250 case 0x6:
251 UniEffect(UNI_XMEFFECT6,dat);
252 break;
253 case 0xa:
254 UniEffect(UNI_XMEFFECTA,dat);
255 break;
256 case 0xe: /* Extended effects */
257 switch(dat>>4) {
258 case 0x1: /* XM fine porta up */
259 UniEffect(UNI_XMEFFECTE1,dat&0xf);
260 break;
261 case 0x2: /* XM fine porta down */
262 UniEffect(UNI_XMEFFECTE2,dat&0xf);
263 break;
264 case 0xa: /* XM fine volume up */
265 UniEffect(UNI_XMEFFECTEA,dat&0xf);
266 break;
267 case 0xb: /* XM fine volume down */
268 UniEffect(UNI_XMEFFECTEB,dat&0xf);
269 break;
270 default:
271 UniPTEffect(eff,dat);
272 }
273 break;
274 case 'G'-55: /* G - set global volume */
275 UniEffect(UNI_XMEFFECTG,dat>64?128:dat<<1);
276 break;
277 case 'H'-55: /* H - global volume slide */
278 UniEffect(UNI_XMEFFECTH,dat);
279 break;
280 case 'K'-55: /* K - keyOff and KeyFade */
281 UniEffect(UNI_KEYFADE,dat);
282 break;
283 case 'L'-55: /* L - set envelope position */
284 UniEffect(UNI_XMEFFECTL,dat);
285 break;
286 case 'P'-55: /* P - panning slide */
287 UniEffect(UNI_XMEFFECTP,dat);
288 break;
289 case 'R'-55: /* R - multi retrig note */
290 UniEffect(UNI_S3MEFFECTQ,dat);
291 break;
292 case 'T'-55: /* T - Tremor */
293 UniEffect(UNI_S3MEFFECTI,dat);
294 break;
295 case 'X'-55:
296 switch(dat>>4) {
297 case 1: /* X1 - Extra Fine Porta up */
298 UniEffect(UNI_XMEFFECTX1,dat&0xf);
299 break;
300 case 2: /* X2 - Extra Fine Porta down */
301 UniEffect(UNI_XMEFFECTX2,dat&0xf);
302 break;
303 }
304 break;
305 default:
306 if(eff<=0xf) {
307 /* the pattern jump destination is written in decimal,
308 but it seems some poor tracker software writes them
309 in hexadecimal... (sigh) */
310 if (eff==0xd)
311 /* don't change anything if we're sure it's in hexa */
312 if ((((dat&0xf0)>>4)<=9)&&((dat&0xf)<=9))
313 /* otherwise, convert from dec to hex */
314 dat=(((dat&0xf0)>>4)*10)+(dat&0xf);
315 UniPTEffect(eff,dat);
316 }
317 break;
318 }
319 UniNewline();
320 xmtrack++;
321 }
322 return UniDup();
323 }
324
LoadPatterns(BOOL dummypat)325 static BOOL LoadPatterns(BOOL dummypat)
326 {
327 int t,u,v,numtrk;
328
329 if(!AllocTracks()) return 0;
330 if(!AllocPatterns()) return 0;
331
332 numtrk=0;
333 for(t=0;t<mh->numpat;t++) {
334 XMPATHEADER ph;
335
336 ph.size =_mm_read_I_ULONG(modreader);
337 if (ph.size<(mh->version==0x0102?8:9)) {
338 _mm_errno=MMERR_LOADING_PATTERN;
339 return 0;
340 }
341 ph.packing =_mm_read_UBYTE(modreader);
342 if(ph.packing) {
343 _mm_errno=MMERR_LOADING_PATTERN;
344 return 0;
345 }
346 if(mh->version==0x0102)
347 ph.numrows =_mm_read_UBYTE(modreader)+1;
348 else
349 ph.numrows =_mm_read_I_UWORD(modreader);
350 ph.packsize =_mm_read_I_UWORD(modreader);
351
352 ph.size-=(mh->version==0x0102?8:9);
353 if(ph.size)
354 _mm_fseek(modreader,ph.size,SEEK_CUR);
355
356 of.pattrows[t]=ph.numrows;
357
358 if(ph.numrows) {
359 if(!(xmpat=(XMNOTE*)MikMod_calloc(ph.numrows*of.numchn,sizeof(XMNOTE))))
360 return 0;
361
362 /* when packsize is 0, don't try to load a pattern.. it's empty. */
363 if(ph.packsize)
364 for(u=0;u<ph.numrows;u++)
365 for(v=0;v<of.numchn;v++) {
366 if(!ph.packsize) break;
367
368 ph.packsize-=XM_ReadNote(&xmpat[(v*ph.numrows)+u]);
369 if(ph.packsize<0) {
370 MikMod_free(xmpat);xmpat=NULL;
371 _mm_errno=MMERR_LOADING_PATTERN;
372 return 0;
373 }
374 }
375
376 if(ph.packsize) {
377 _mm_fseek(modreader,ph.packsize,SEEK_CUR);
378 }
379
380 if(_mm_eof(modreader)) {
381 MikMod_free(xmpat);xmpat=NULL;
382 _mm_errno=MMERR_LOADING_PATTERN;
383 return 0;
384 }
385
386 for(v=0;v<of.numchn;v++)
387 of.tracks[numtrk++]=XM_Convert(&xmpat[v*ph.numrows],ph.numrows);
388
389 MikMod_free(xmpat);xmpat=NULL;
390 } else {
391 for(v=0;v<of.numchn;v++)
392 of.tracks[numtrk++]=XM_Convert(NULL,ph.numrows);
393 }
394 }
395
396 if(dummypat) {
397 of.pattrows[t]=64;
398 if(!(xmpat=(XMNOTE*)MikMod_calloc(64*of.numchn,sizeof(XMNOTE)))) return 0;
399 for(v=0;v<of.numchn;v++)
400 of.tracks[numtrk++]=XM_Convert(&xmpat[v*64],64);
401 MikMod_free(xmpat);xmpat=NULL;
402 }
403
404 return 1;
405 }
406
FixEnvelope(ENVPT * cur,int pts)407 static void FixEnvelope(ENVPT *cur, int pts)
408 {
409 int u, old, tmp;
410 ENVPT *prev;
411
412 /* Some broken XM editing program will only save the low byte
413 of the position value. Try to compensate by adding the
414 missing high byte. */
415
416 prev = cur++;
417 old = prev->pos;
418
419 for (u = 1; u < pts; u++, prev++, cur++) {
420 if (cur->pos < prev->pos) {
421 if (cur->pos < 0x100) {
422 if (cur->pos > old) /* same hex century */
423 tmp = cur->pos + (prev->pos - old);
424 else
425 tmp = cur->pos | ((prev->pos + 0x100) & 0xff00);
426 old = cur->pos;
427 cur->pos = tmp;
428 #ifdef MIKMOD_DEBUG
429 fprintf(stderr, "\rbroken envelope position(%d/%d), %d %d -> %d\n",
430 u, pts, prev->pos, old, cur->pos);
431 #endif
432 } else {
433 #ifdef MIKMOD_DEBUG
434 /* different brokenness style... fix unknown */
435 fprintf(stderr, "\rbroken envelope position(%d/%d), %d %d\n",
436 u, pts, old, cur->pos);
437 #endif
438 old = cur->pos;
439 }
440 } else
441 old = cur->pos;
442 }
443 }
444
LoadInstruments(void)445 static BOOL LoadInstruments(void)
446 {
447 long filend,ck;
448 int t,u;
449 INSTRUMENT *d;
450 ULONG next=0;
451 UWORD wavcnt=0;
452
453 ck = _mm_ftell(modreader);
454 _mm_fseek(modreader,0,SEEK_END);
455 filend = _mm_ftell(modreader);
456 _mm_fseek(modreader,ck,SEEK_SET);
457
458 if(!AllocInstruments()) return 0;
459 d=of.instruments;
460 for(t=0;t<of.numins;t++,d++) {
461 XMINSTHEADER ih;
462 long headend;
463
464 memset(d->samplenumber,0xff,INSTNOTES*sizeof(UWORD));
465
466 /* read instrument header */
467 headend = _mm_ftell(modreader);
468 ih.size = _mm_read_I_ULONG(modreader);
469 headend += ih.size;
470 ck = _mm_ftell(modreader);
471 if ((headend<0) || (filend<headend) || (headend<ck)) {
472 break;
473 }
474 _mm_read_string(ih.name, 22, modreader);
475 ih.type = _mm_read_UBYTE(modreader);
476 ih.numsmp = _mm_read_I_UWORD(modreader);
477
478 d->insname = DupStr(ih.name,22,1);
479
480 if((SWORD)ih.size>29) {
481 ih.ssize = _mm_read_I_ULONG(modreader);
482 if(((SWORD)ih.numsmp>0)&&(ih.numsmp<=XMNOTECNT)) {
483 XMPATCHHEADER pth;
484 int p;
485
486 _mm_read_UBYTES (pth.what,XMNOTECNT,modreader);
487 _mm_read_I_UWORDS (pth.volenv, XMENVCNT, modreader);
488 _mm_read_I_UWORDS (pth.panenv, XMENVCNT, modreader);
489 pth.volpts = _mm_read_UBYTE(modreader);
490 pth.panpts = _mm_read_UBYTE(modreader);
491 pth.volsus = _mm_read_UBYTE(modreader);
492 pth.volbeg = _mm_read_UBYTE(modreader);
493 pth.volend = _mm_read_UBYTE(modreader);
494 pth.pansus = _mm_read_UBYTE(modreader);
495 pth.panbeg = _mm_read_UBYTE(modreader);
496 pth.panend = _mm_read_UBYTE(modreader);
497 pth.volflg = _mm_read_UBYTE(modreader);
498 pth.panflg = _mm_read_UBYTE(modreader);
499 pth.vibflg = _mm_read_UBYTE(modreader);
500 pth.vibsweep = _mm_read_UBYTE(modreader);
501 pth.vibdepth = _mm_read_UBYTE(modreader);
502 pth.vibrate = _mm_read_UBYTE(modreader);
503 pth.volfade = _mm_read_I_UWORD(modreader);
504
505 /* read the remainder of the header
506 (2 bytes for 1.03, 22 for 1.04) */
507 if (headend>=_mm_ftell(modreader)) {
508 for(u=headend-_mm_ftell(modreader);u;u--) {
509 _mm_skip_BYTE(modreader);
510 }
511 }
512
513 /* we can't trust the envelope point count here, as some
514 modules have incorrect values (K_OSPACE.XM reports 32 volume
515 points, for example). */
516 if(pth.volpts>XMENVCNT/2) pth.volpts=XMENVCNT/2;
517 if(pth.panpts>XMENVCNT/2) pth.panpts=XMENVCNT/2;
518
519 if((_mm_eof(modreader))||(pth.volpts>XMENVCNT/2)||(pth.panpts>XMENVCNT/2)) {
520 MikMod_free(nextwav);nextwav=NULL;
521 MikMod_free(wh);wh=NULL;
522 _mm_errno = MMERR_LOADING_SAMPLEINFO;
523 return 0;
524 }
525
526 for(u=0;u<XMNOTECNT;u++)
527 d->samplenumber[u]=pth.what[u]+of.numsmp;
528 d->volfade = pth.volfade;
529
530 #if defined __STDC__ || defined _MSC_VER || defined MPW_C
531 #define XM_ProcessEnvelope(name) \
532 for (u = 0; u < (XMENVCNT >> 1); u++) { \
533 d-> name##env[u].pos = pth. name##env[u << 1]; \
534 d-> name##env[u].val = pth. name##env[(u << 1)+ 1]; \
535 } \
536 if (pth. name##flg&1) d-> name##flg|=EF_ON; \
537 if (pth. name##flg&2) d-> name##flg|=EF_SUSTAIN; \
538 if (pth. name##flg&4) d-> name##flg|=EF_LOOP; \
539 d-> name##susbeg=d-> name##susend=pth. name##sus; \
540 d-> name##beg=pth. name##beg; \
541 d-> name##end=pth. name##end; \
542 d-> name##pts=pth. name##pts; \
543 \
544 /* scale envelope */ \
545 for (p=0;p<XMENVCNT/2;p++) \
546 d-> name##env[p].val<<=2; \
547 \
548 if ((d-> name##flg&EF_ON)&&(d-> name##pts<2)) \
549 d-> name##flg&=~EF_ON
550 #else
551 #define XM_ProcessEnvelope(name) \
552 for (u = 0; u < (XMENVCNT >> 1); u++) { \
553 d-> name/**/env[u].pos = pth. name/**/env[u << 1]; \
554 d-> name/**/env[u].val = pth. name/**/env[(u << 1)+ 1]; \
555 } \
556 if (pth. name/**/flg&1) d-> name/**/flg|=EF_ON; \
557 if (pth. name/**/flg&2) d-> name/**/flg|=EF_SUSTAIN; \
558 if (pth. name/**/flg&4) d-> name/**/flg|=EF_LOOP; \
559 d-> name/**/susbeg=d-> name/**/susend= \
560 pth. name/**/sus; \
561 d-> name/**/beg=pth. name/**/beg; \
562 d-> name/**/end=pth. name/**/end; \
563 d-> name/**/pts=pth. name/**/pts; \
564 \
565 /* scale envelope */ \
566 for (p=0;p<XMENVCNT/2;p++) \
567 d-> name/**/env[p].val<<=2; \
568 \
569 if ((d-> name/**/flg&EF_ON)&&(d-> name/**/pts<2)) \
570 d-> name/**/flg&=~EF_ON
571 #endif
572
573 XM_ProcessEnvelope(vol);
574 XM_ProcessEnvelope(pan);
575 #undef XM_ProcessEnvelope
576
577 if (d->volflg & EF_ON)
578 FixEnvelope(d->volenv, d->volpts);
579 if (d->panflg & EF_ON)
580 FixEnvelope(d->panenv, d->panpts);
581
582 /* Samples are stored outside the instrument struct now, so we
583 have to load them all into a temp area, count the of.numsmp
584 along the way and then do an AllocSamples() and move
585 everything over */
586 if(mh->version>0x0103) next = 0;
587 for(u=0;u<ih.numsmp;u++,s++) {
588 /* XM sample header is 40 bytes: make sure we won't hit EOF */
589 /* Note: last instrument is at the end of file in version 0x0104 */
590 if(_mm_ftell(modreader)+40>filend) {
591 MikMod_free(nextwav);MikMod_free(wh);
592 nextwav=NULL;wh=NULL;
593 _mm_errno = MMERR_LOADING_SAMPLEINFO;
594 return 0;
595 }
596 /* Allocate more room for sample information if necessary */
597 if(of.numsmp+u==wavcnt) {
598 wavcnt+=XM_SMPINCR;
599 if(!(nextwav=(ULONG*)MikMod_realloc(nextwav,wavcnt*sizeof(ULONG)))){
600 MikMod_free(wh);wh=NULL;
601 _mm_errno = MMERR_OUT_OF_MEMORY;
602 return 0;
603 }
604 if(!(wh=(XMWAVHEADER*)MikMod_realloc(wh,wavcnt*sizeof(XMWAVHEADER)))) {
605 MikMod_free(nextwav);nextwav=NULL;
606 _mm_errno = MMERR_OUT_OF_MEMORY;
607 return 0;
608 }
609 s=wh+(wavcnt-XM_SMPINCR);
610 }
611
612 s->length =_mm_read_I_ULONG (modreader);
613 s->loopstart =_mm_read_I_ULONG (modreader);
614 s->looplength =_mm_read_I_ULONG (modreader);
615 s->volume =_mm_read_UBYTE (modreader);
616 s->finetune =_mm_read_SBYTE (modreader);
617 s->type =_mm_read_UBYTE (modreader);
618 s->panning =_mm_read_UBYTE (modreader);
619 s->relnote =_mm_read_SBYTE (modreader);
620 s->vibtype = pth.vibflg;
621 s->vibsweep = pth.vibsweep;
622 s->vibdepth = pth.vibdepth*4;
623 s->vibrate = pth.vibrate;
624 s->reserved =_mm_read_UBYTE (modreader);
625 _mm_read_string(s->samplename, 22, modreader);
626
627 nextwav[of.numsmp+u]=next;
628 next+=s->length;
629 }
630
631 if(mh->version>0x0103) {
632 for(u=0;u<ih.numsmp;u++)
633 nextwav[of.numsmp++]+=_mm_ftell(modreader);
634 _mm_fseek(modreader,next,SEEK_CUR);
635 } else
636 of.numsmp+=ih.numsmp;
637 } else {
638 /* read the remainder of the header */
639 ck = _mm_ftell(modreader);
640 if ((headend<0) || (filend<headend) || (headend<ck)) {
641 break;
642 }
643 for(u=headend-_mm_ftell(modreader);u;u--) {
644 _mm_skip_BYTE(modreader);
645 }
646
647 /* last instrument is at the end of file in version 0x0104 */
648 if(_mm_eof(modreader) && (mh->version<0x0104 || t<of.numins-1)) {
649 MikMod_free(nextwav);MikMod_free(wh);
650 nextwav=NULL;wh=NULL;
651 _mm_errno = MMERR_LOADING_SAMPLEINFO;
652 return 0;
653 }
654 }
655 }
656 }
657
658 /* sanity check */
659 if(!of.numsmp) {
660 MikMod_free(nextwav);nextwav=NULL;
661 MikMod_free(wh);wh=NULL;
662 _mm_errno = MMERR_LOADING_SAMPLEINFO;
663 return 0;
664 }
665
666 return 1;
667 }
668
XM_Load(BOOL curious)669 static BOOL XM_Load(BOOL curious)
670 {
671 INSTRUMENT *d;
672 SAMPLE *q;
673 int t,u;
674 BOOL dummypat=0;
675 char tracker[21],modtype[60];
676
677 /* try to read module header */
678 _mm_read_string(mh->id,17,modreader);
679 _mm_read_string(mh->songname,21,modreader);
680 _mm_read_string(mh->trackername,20,modreader);
681 mh->version =_mm_read_I_UWORD(modreader);
682 if(mh->version < 0x102 || mh->version > 0x104)
683 goto bad_xm;
684 mh->headersize =_mm_read_I_ULONG(modreader);
685 mh->songlength =_mm_read_I_UWORD(modreader);
686 mh->restart =_mm_read_I_UWORD(modreader);
687 mh->numchn =_mm_read_I_UWORD(modreader);
688 mh->numpat =_mm_read_I_UWORD(modreader);
689 mh->numins =_mm_read_I_UWORD(modreader);
690 mh->flags =_mm_read_I_UWORD(modreader);
691 mh->tempo =_mm_read_I_UWORD(modreader);
692 mh->bpm =_mm_read_I_UWORD(modreader);
693 if(mh->numchn > 64) goto bad_xm;
694 if(mh->tempo > 32 || mh->bpm < 32 || mh->bpm > 255)
695 goto bad_xm;
696 if(mh->songlength > 256 || mh->headersize < 20 || mh->headersize > 20+256)
697 goto bad_xm;
698 if(mh->numpat > 256 || mh->numins > 255 || mh->restart > 255)
699 goto bad_xm;
700 /* _mm_read_UBYTES(mh->orders,256,modreader);*/
701 /* _mm_read_UBYTES(mh->orders,mh->headersize-20,modreader);*/
702 _mm_read_UBYTES(mh->orders,mh->songlength,modreader);
703 if(_mm_fseek(modreader, mh->headersize+60, SEEK_SET) || _mm_eof(modreader))
704 goto bad_hdr;
705
706 /* set module variables */
707 of.initspeed = mh->tempo;
708 of.inittempo = mh->bpm;
709 strncpy(tracker,mh->trackername,20);tracker[20]=0;
710 for(t=20;(t>=0)&&(tracker[t]<=' ');t--) tracker[t]=0;
711
712 /* some modules have the tracker name empty */
713 if (!tracker[0])
714 strcpy(tracker,"Unknown tracker");
715
716 #ifdef HAVE_SNPRINTF
717 snprintf(modtype,60,"%s (XM format %d.%02d)",
718 tracker,mh->version>>8,mh->version&0xff);
719 #else
720 sprintf(modtype,"%s (XM format %d.%02d)",
721 tracker,mh->version>>8,mh->version&0xff);
722 #endif
723 of.modtype = MikMod_strdup(modtype);
724 of.numchn = mh->numchn;
725 of.numpat = mh->numpat;
726 of.numtrk = (UWORD)of.numpat*of.numchn; /* get number of channels */
727 of.songname = DupStr(mh->songname,20,1);
728 of.numpos = mh->songlength; /* copy the songlength */
729 of.reppos = mh->restart<mh->songlength?mh->restart:0;
730 of.numins = mh->numins;
731 of.flags |= UF_XMPERIODS | UF_INST | UF_NOWRAP | UF_FT2QUIRKS | UF_PANNING;
732 if(mh->flags&1) of.flags |= UF_LINEAR;
733 of.bpmlimit = 32;
734
735 memset(of.chanvol,64,of.numchn); /* store channel volumes */
736
737 if(!AllocPositions(of.numpos+1)) return 0;
738 for(t=0;t<of.numpos;t++)
739 of.positions[t]=mh->orders[t];
740
741 /* We have to check for any pattern numbers in the order list greater than
742 the number of patterns total. If one or more is found, we set it equal to
743 the pattern total and make a dummy pattern to workaround the problem */
744 for(t=0;t<of.numpos;t++) {
745 if(of.positions[t]>=of.numpat) {
746 of.positions[t]=of.numpat;
747 dummypat=1;
748 }
749 }
750 if(dummypat) {
751 of.numpat++;of.numtrk+=of.numchn;
752 }
753
754 if(mh->version<0x0104) {
755 if(!LoadInstruments()) return 0;
756 if(!LoadPatterns(dummypat)) return 0;
757 for(t=0;t<of.numsmp;t++)
758 nextwav[t]+=_mm_ftell(modreader);
759 } else {
760 if(!LoadPatterns(dummypat)) return 0;
761 if(!LoadInstruments()) return 0;
762 }
763
764 if(!AllocSamples()) {
765 MikMod_free(nextwav);MikMod_free(wh);
766 nextwav=NULL;wh=NULL;
767 return 0;
768 }
769 q = of.samples;
770 s = wh;
771 for(u=0;u<of.numsmp;u++,q++,s++) {
772 q->samplename = DupStr(s->samplename,22,1);
773 q->length = s->length;
774 q->loopstart = s->loopstart;
775 q->loopend = s->loopstart+s->looplength;
776 q->volume = s->volume;
777 q->speed = s->finetune+128;
778 q->panning = s->panning;
779 q->seekpos = nextwav[u];
780 q->vibtype = s->vibtype;
781 q->vibsweep = s->vibsweep;
782 q->vibdepth = s->vibdepth;
783 q->vibrate = s->vibrate;
784
785 if(s->type & 0x10) {
786 q->length >>= 1;
787 q->loopstart >>= 1;
788 q->loopend >>= 1;
789 }
790
791 q->flags|=SF_OWNPAN|SF_DELTA|SF_SIGNED;
792 if(s->type&0x3) q->flags|=SF_LOOP;
793 if(s->type&0x2) q->flags|=SF_BIDI;
794 if(s->type&0x10) q->flags|=SF_16BITS;
795 }
796
797 d=of.instruments;
798 s=wh;
799 for(u=0;u<of.numins;u++,d++)
800 for(t=0;t<XMNOTECNT;t++) {
801 if (d->samplenumber[t]>=of.numsmp)
802 d->samplenote[t]=255;
803 else {
804 int note=t+s[d->samplenumber[t]].relnote;
805 d->samplenote[t]=(note<0)?0:note;
806 }
807 }
808
809 MikMod_free(wh);MikMod_free(nextwav);
810 wh=NULL;nextwav=NULL;
811 return 1;
812
813 bad_hdr: _mm_errno = MMERR_LOADING_HEADER; return 0;
814 bad_xm: _mm_errno = MMERR_NOT_A_MODULE; return 0;
815 }
816
XM_LoadTitle(void)817 static CHAR *XM_LoadTitle(void)
818 {
819 CHAR str[21];
820
821 _mm_fseek(modreader,17,SEEK_SET);
822 if(!_mm_read_UBYTES(str, 21, modreader)) return NULL;
823
824 return(DupStr(str,21,1));
825 }
826
827 /*========== Loader information */
828
829 MIKMODAPI MLOADER load_xm={
830 NULL,
831 "XM",
832 "XM (FastTracker 2)",
833 XM_Init,
834 XM_Test,
835 XM_Load,
836 XM_Cleanup,
837 XM_LoadTitle
838 };
839
840 /* ex:set ts=4: */
841