Bump version numbers for 3.13
[maemo-rb.git] / apps / plugins / mikmod / load_xm.c
blobffbd6dff4d9b8e3e2c8e12d69099cbbca4833263
1 /* MikMod sound library
2 (c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
3 AUTHORS for complete list.
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.
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.
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.
21 /*==============================================================================
23 $Id: load_xm.c,v 1.5 2008/02/29 18:49:03 denis111 Exp $
25 Fasttracker (XM) module loader
27 ==============================================================================*/
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
37 #include <stdio.h>
38 #ifdef HAVE_MEMORY_H
39 #include <memory.h>
40 #endif
41 #include <string.h>
43 #include "mikmod_internals.h"
45 #ifdef SUNOS
46 extern int fprintf(FILE *, const char *, ...);
47 #endif
49 /*========== Module structure */
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;
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;
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;
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;
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;
123 typedef struct XMNOTE {
124 UBYTE note,ins,vol,eff,dat;
125 } XMNOTE;
127 /*========== Loader variables */
129 static XMNOTE *xmpat=NULL;
130 static XMHEADER *mh=NULL;
132 /* increment unit for sample array MikMod_reallocation */
133 #define XM_SMPINCR 64
134 static ULONG *nextwav=NULL;
135 static XMWAVHEADER *wh=NULL,*s=NULL;
137 /*========== Loader code */
139 static int XM_Test(void)
141 UBYTE id[38];
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;
149 static int XM_Init(void)
151 if(!(mh=(XMHEADER *)MikMod_malloc(sizeof(XMHEADER)))) return 0;
152 return 1;
155 static void XM_Cleanup(void)
157 MikMod_free(mh);
160 static int XM_ReadNote(XMNOTE* n)
162 UBYTE cmp,result=1;
164 memset(n,0,sizeof(XMNOTE));
165 cmp=_mm_read_UBYTE(modreader);
167 if(cmp&0x80) {
168 if(cmp&1) { result++;n->note = _mm_read_UBYTE(modreader); }
169 if(cmp&2) { result++;n->ins = _mm_read_UBYTE(modreader); }
170 if(cmp&4) { result++;n->vol = _mm_read_UBYTE(modreader); }
171 if(cmp&8) { result++;n->eff = _mm_read_UBYTE(modreader); }
172 if(cmp&16) { result++;n->dat = _mm_read_UBYTE(modreader); }
173 } else {
174 n->note = cmp;
175 n->ins = _mm_read_UBYTE(modreader);
176 n->vol = _mm_read_UBYTE(modreader);
177 n->eff = _mm_read_UBYTE(modreader);
178 n->dat = _mm_read_UBYTE(modreader);
179 result += 4;
181 return result;
184 static UBYTE* XM_Convert(XMNOTE* xmtrack,UWORD rows)
186 int t;
187 UBYTE note,ins,vol,eff,dat;
189 UniReset();
190 for(t=0;t<rows;t++) {
191 note = xmtrack->note;
192 ins = xmtrack->ins;
193 vol = xmtrack->vol;
194 eff = xmtrack->eff;
195 dat = xmtrack->dat;
197 if(note) {
198 if(note>XMNOTECNT)
199 UniEffect(UNI_KEYFADE,0);
200 else
201 UniNote(note-1);
203 if(ins) UniInstrument(ins-1);
205 switch(vol>>4) {
206 case 0x6: /* volslide down */
207 if(vol&0xf) UniEffect(UNI_XMEFFECTA,vol&0xf);
208 break;
209 case 0x7: /* volslide up */
210 if(vol&0xf) UniEffect(UNI_XMEFFECTA,vol<<4);
211 break;
213 /* volume-row fine volume slide is compatible with protracker
214 EBx and EAx effects i.e. a zero nibble means DO NOT SLIDE, as
215 opposed to 'take the last sliding value'. */
216 case 0x8: /* finevol down */
217 UniPTEffect(0xe,0xb0|(vol&0xf));
218 break;
219 case 0x9: /* finevol up */
220 UniPTEffect(0xe,0xa0|(vol&0xf));
221 break;
222 case 0xa: /* set vibrato speed */
223 UniEffect(UNI_XMEFFECT4,vol<<4);
224 break;
225 case 0xb: /* vibrato */
226 UniEffect(UNI_XMEFFECT4,vol&0xf);
227 break;
228 case 0xc: /* set panning */
229 UniPTEffect(0x8,vol<<4);
230 break;
231 case 0xd: /* panning slide left (only slide when data not zero) */
232 if(vol&0xf) UniEffect(UNI_XMEFFECTP,vol&0xf);
233 break;
234 case 0xe: /* panning slide right (only slide when data not zero) */
235 if(vol&0xf) UniEffect(UNI_XMEFFECTP,vol<<4);
236 break;
237 case 0xf: /* tone porta */
238 UniPTEffect(0x3,vol<<4);
239 break;
240 default:
241 if((vol>=0x10)&&(vol<=0x50))
242 UniPTEffect(0xc,vol-0x10);
245 switch(eff) {
246 case 0x4:
247 UniEffect(UNI_XMEFFECT4,dat);
248 break;
249 case 0x6:
250 UniEffect(UNI_XMEFFECT6,dat);
251 break;
252 case 0xa:
253 UniEffect(UNI_XMEFFECTA,dat);
254 break;
255 case 0xe: /* Extended effects */
256 switch(dat>>4) {
257 case 0x1: /* XM fine porta up */
258 UniEffect(UNI_XMEFFECTE1,dat&0xf);
259 break;
260 case 0x2: /* XM fine porta down */
261 UniEffect(UNI_XMEFFECTE2,dat&0xf);
262 break;
263 case 0xa: /* XM fine volume up */
264 UniEffect(UNI_XMEFFECTEA,dat&0xf);
265 break;
266 case 0xb: /* XM fine volume down */
267 UniEffect(UNI_XMEFFECTEB,dat&0xf);
268 break;
269 default:
270 UniPTEffect(eff,dat);
272 break;
273 case 'G'-55: /* G - set global volume */
274 UniEffect(UNI_XMEFFECTG,dat>64?128:dat<<1);
275 break;
276 case 'H'-55: /* H - global volume slide */
277 UniEffect(UNI_XMEFFECTH,dat);
278 break;
279 case 'K'-55: /* K - keyOff and KeyFade */
280 UniEffect(UNI_KEYFADE,dat);
281 break;
282 case 'L'-55: /* L - set envelope position */
283 UniEffect(UNI_XMEFFECTL,dat);
284 break;
285 case 'P'-55: /* P - panning slide */
286 UniEffect(UNI_XMEFFECTP,dat);
287 break;
288 case 'R'-55: /* R - multi retrig note */
289 UniEffect(UNI_S3MEFFECTQ,dat);
290 break;
291 case 'T'-55: /* T - Tremor */
292 UniEffect(UNI_S3MEFFECTI,dat);
293 break;
294 case 'X'-55:
295 switch(dat>>4) {
296 case 1: /* X1 - Extra Fine Porta up */
297 UniEffect(UNI_XMEFFECTX1,dat&0xf);
298 break;
299 case 2: /* X2 - Extra Fine Porta down */
300 UniEffect(UNI_XMEFFECTX2,dat&0xf);
301 break;
303 break;
304 default:
305 if(eff<=0xf) {
306 /* the pattern jump destination is written in decimal,
307 but it seems some poor tracker software writes them
308 in hexadecimal... (sigh) */
309 if (eff==0xd)
310 /* don't change anything if we're sure it's in hexa */
311 if ((((dat&0xf0)>>4)<=9)&&((dat&0xf)<=9))
312 /* otherwise, convert from dec to hex */
313 dat=(((dat&0xf0)>>4)*10)+(dat&0xf);
314 UniPTEffect(eff,dat);
316 break;
318 UniNewline();
319 xmtrack++;
321 return UniDup();
324 static int LoadPatterns(int dummypat)
326 int t,u,v,numtrk;
328 if(!AllocTracks()) return 0;
329 if(!AllocPatterns()) return 0;
331 numtrk=0;
332 for(t=0;t<mh->numpat;t++) {
333 XMPATHEADER ph;
335 ph.size =_mm_read_I_ULONG(modreader);
336 if (ph.size<(mh->version==0x0102?8:9)) {
337 _mm_errno=MMERR_LOADING_PATTERN;
338 return 0;
340 ph.packing =_mm_read_UBYTE(modreader);
341 if(ph.packing) {
342 _mm_errno=MMERR_LOADING_PATTERN;
343 return 0;
345 if(mh->version==0x0102)
346 ph.numrows =_mm_read_UBYTE(modreader)+1;
347 else
348 ph.numrows =_mm_read_I_UWORD(modreader);
349 ph.packsize =_mm_read_I_UWORD(modreader);
351 ph.size-=(mh->version==0x0102?8:9);
352 if(ph.size)
353 _mm_fseek(modreader,ph.size,SEEK_CUR);
355 of.pattrows[t]=ph.numrows;
357 if(ph.numrows) {
358 if(!(xmpat=(XMNOTE*)MikMod_calloc(ph.numrows*of.numchn,sizeof(XMNOTE))))
359 return 0;
361 /* when packsize is 0, don't try to load a pattern.. it's empty. */
362 if(ph.packsize)
363 for(u=0;u<ph.numrows;u++)
364 for(v=0;v<of.numchn;v++) {
365 if(!ph.packsize) break;
367 ph.packsize-=XM_ReadNote(&xmpat[(v*ph.numrows)+u]);
368 if(ph.packsize<0) {
369 MikMod_free(xmpat);xmpat=NULL;
370 _mm_errno=MMERR_LOADING_PATTERN;
371 return 0;
375 if(ph.packsize) {
376 _mm_fseek(modreader,ph.packsize,SEEK_CUR);
379 if(_mm_eof(modreader)) {
380 MikMod_free(xmpat);xmpat=NULL;
381 _mm_errno=MMERR_LOADING_PATTERN;
382 return 0;
385 for(v=0;v<of.numchn;v++)
386 of.tracks[numtrk++]=XM_Convert(&xmpat[v*ph.numrows],ph.numrows);
388 MikMod_free(xmpat);xmpat=NULL;
389 } else {
390 for(v=0;v<of.numchn;v++)
391 of.tracks[numtrk++]=XM_Convert(NULL,ph.numrows);
395 if(dummypat) {
396 of.pattrows[t]=64;
397 if(!(xmpat=(XMNOTE*)MikMod_calloc(64*of.numchn,sizeof(XMNOTE)))) return 0;
398 for(v=0;v<of.numchn;v++)
399 of.tracks[numtrk++]=XM_Convert(&xmpat[v*64],64);
400 MikMod_free(xmpat);xmpat=NULL;
403 return 1;
406 static void FixEnvelope(ENVPT *cur, int pts)
408 int u, old, tmp;
409 ENVPT *prev;
411 /* Some broken XM editing program will only save the low byte
412 of the position value. Try to compensate by adding the
413 missing high byte. */
415 prev = cur++;
416 old = prev->pos;
418 for (u = 1; u < pts; u++, prev++, cur++) {
419 if (cur->pos < prev->pos) {
420 if (cur->pos < 0x100) {
421 if (cur->pos > old) /* same hex century */
422 tmp = cur->pos + (prev->pos - old);
423 else
424 tmp = cur->pos | ((prev->pos + 0x100) & 0xff00);
425 old = cur->pos;
426 cur->pos = tmp;
427 #ifdef MIKMOD_DEBUG
428 fprintf(stderr, "\rbroken envelope position(%d/%d), %d %d -> %d\n",
429 u, pts, prev->pos, old, cur->pos);
430 #endif
431 } else {
432 #ifdef MIKMOD_DEBUG
433 /* different brokenness style... fix unknown */
434 fprintf(stderr, "\rbroken envelope position(%d/%d), %d %d\n",
435 u, pts, old, cur->pos);
436 #endif
437 old = cur->pos;
439 } else
440 old = cur->pos;
444 static int LoadInstruments(void)
446 int t,u, ck;
447 INSTRUMENT *d;
448 ULONG next=0;
449 UWORD wavcnt=0;
451 if(!AllocInstruments()) return 0;
452 d=of.instruments;
453 for(t=0;t<of.numins;t++,d++) {
454 XMINSTHEADER ih;
455 long headend;
457 memset(d->samplenumber,0xff,INSTNOTES*sizeof(UWORD));
459 /* read instrument header */
460 headend = _mm_ftell(modreader);
461 ih.size = _mm_read_I_ULONG(modreader);
462 headend += ih.size;
463 ck = _mm_ftell(modreader);
464 _mm_fseek(modreader,0,SEEK_END);
465 if ((headend<0) || (_mm_ftell(modreader)<headend) || (headend<ck)) {
466 _mm_fseek(modreader,ck,SEEK_SET);
467 break;
469 _mm_fseek(modreader,ck,SEEK_SET);
470 _mm_read_string(ih.name, 22, modreader);
471 ih.type = _mm_read_UBYTE(modreader);
472 ih.numsmp = _mm_read_I_UWORD(modreader);
474 d->insname = DupStr(ih.name,22,1);
476 if((SWORD)ih.size>29) {
477 ih.ssize = _mm_read_I_ULONG(modreader);
478 if(((SWORD)ih.numsmp>0)&&(ih.numsmp<=XMNOTECNT)) {
479 XMPATCHHEADER pth;
480 int p;
482 _mm_read_UBYTES (pth.what,XMNOTECNT,modreader);
483 _mm_read_I_UWORDS (pth.volenv, XMENVCNT, modreader);
484 _mm_read_I_UWORDS (pth.panenv, XMENVCNT, modreader);
485 pth.volpts = _mm_read_UBYTE(modreader);
486 pth.panpts = _mm_read_UBYTE(modreader);
487 pth.volsus = _mm_read_UBYTE(modreader);
488 pth.volbeg = _mm_read_UBYTE(modreader);
489 pth.volend = _mm_read_UBYTE(modreader);
490 pth.pansus = _mm_read_UBYTE(modreader);
491 pth.panbeg = _mm_read_UBYTE(modreader);
492 pth.panend = _mm_read_UBYTE(modreader);
493 pth.volflg = _mm_read_UBYTE(modreader);
494 pth.panflg = _mm_read_UBYTE(modreader);
495 pth.vibflg = _mm_read_UBYTE(modreader);
496 pth.vibsweep = _mm_read_UBYTE(modreader);
497 pth.vibdepth = _mm_read_UBYTE(modreader);
498 pth.vibrate = _mm_read_UBYTE(modreader);
499 pth.volfade = _mm_read_I_UWORD(modreader);
501 /* read the remainder of the header
502 (2 bytes for 1.03, 22 for 1.04) */
503 if (headend>=_mm_ftell(modreader)) for(u=headend-_mm_ftell(modreader);u;u--) (void)_mm_read_UBYTE(modreader);
505 /* we can't trust the envelope point count here, as some
506 modules have incorrect values (K_OSPACE.XM reports 32 volume
507 points, for example). */
508 if(pth.volpts>XMENVCNT/2) pth.volpts=XMENVCNT/2;
509 if(pth.panpts>XMENVCNT/2) pth.panpts=XMENVCNT/2;
511 if((_mm_eof(modreader))||(pth.volpts>XMENVCNT/2)||(pth.panpts>XMENVCNT/2)) {
512 if(nextwav) { MikMod_free(nextwav);nextwav=NULL; }
513 if(wh) { MikMod_free(wh);wh=NULL; }
514 _mm_errno = MMERR_LOADING_SAMPLEINFO;
515 return 0;
518 for(u=0;u<XMNOTECNT;u++)
519 d->samplenumber[u]=pth.what[u]+of.numsmp;
520 d->volfade = pth.volfade;
522 #if defined __STDC__ || defined _MSC_VER || defined MPW_C
523 #define XM_ProcessEnvelope(name) \
524 for (u = 0; u < (XMENVCNT >> 1); u++) { \
525 d-> name##env[u].pos = pth. name##env[u << 1]; \
526 d-> name##env[u].val = pth. name##env[(u << 1)+ 1]; \
528 if (pth. name##flg&1) d-> name##flg|=EF_ON; \
529 if (pth. name##flg&2) d-> name##flg|=EF_SUSTAIN; \
530 if (pth. name##flg&4) d-> name##flg|=EF_LOOP; \
531 d-> name##susbeg=d-> name##susend=pth. name##sus; \
532 d-> name##beg=pth. name##beg; \
533 d-> name##end=pth. name##end; \
534 d-> name##pts=pth. name##pts; \
536 /* scale envelope */ \
537 for (p=0;p<XMENVCNT/2;p++) \
538 d-> name##env[p].val<<=2; \
540 if ((d-> name##flg&EF_ON)&&(d-> name##pts<2)) \
541 d-> name##flg&=~EF_ON
542 #else
543 #define XM_ProcessEnvelope(name) \
544 for (u = 0; u < (XMENVCNT >> 1); u++) { \
545 d-> name/**/env[u].pos = pth. name/**/env[u << 1]; \
546 d-> name/**/env[u].val = pth. name/**/env[(u << 1)+ 1]; \
548 if (pth. name/**/flg&1) d-> name/**/flg|=EF_ON; \
549 if (pth. name/**/flg&2) d-> name/**/flg|=EF_SUSTAIN; \
550 if (pth. name/**/flg&4) d-> name/**/flg|=EF_LOOP; \
551 d-> name/**/susbeg=d-> name/**/susend= \
552 pth. name/**/sus; \
553 d-> name/**/beg=pth. name/**/beg; \
554 d-> name/**/end=pth. name/**/end; \
555 d-> name/**/pts=pth. name/**/pts; \
557 /* scale envelope */ \
558 for (p=0;p<XMENVCNT/2;p++) \
559 d-> name/**/env[p].val<<=2; \
561 if ((d-> name/**/flg&EF_ON)&&(d-> name/**/pts<2)) \
562 d-> name/**/flg&=~EF_ON
563 #endif
565 XM_ProcessEnvelope(vol);
566 XM_ProcessEnvelope(pan);
567 #undef XM_ProcessEnvelope
569 if (d->volflg & EF_ON)
570 FixEnvelope(d->volenv, d->volpts);
571 if (d->panflg & EF_ON)
572 FixEnvelope(d->panenv, d->panpts);
574 /* Samples are stored outside the instrument struct now, so we
575 have to load them all into a temp area, count the of.numsmp
576 along the way and then do an AllocSamples() and move
577 everything over */
578 if(mh->version>0x0103) next = 0;
579 for(u=0;u<ih.numsmp;u++,s++) {
580 /* Allocate more room for sample information if necessary */
581 if(of.numsmp+u==wavcnt) {
582 wavcnt+=XM_SMPINCR;
583 if(!(nextwav=MikMod_realloc(nextwav,wavcnt*sizeof(ULONG)))){
584 if(wh) { MikMod_free(wh);wh=NULL; }
585 _mm_errno = MMERR_OUT_OF_MEMORY;
586 return 0;
588 if(!(wh=MikMod_realloc(wh,wavcnt*sizeof(XMWAVHEADER)))) {
589 MikMod_free(nextwav);nextwav=NULL;
590 _mm_errno = MMERR_OUT_OF_MEMORY;
591 return 0;
593 s=wh+(wavcnt-XM_SMPINCR);
596 s->length =_mm_read_I_ULONG (modreader);
597 s->loopstart =_mm_read_I_ULONG (modreader);
598 s->looplength =_mm_read_I_ULONG (modreader);
599 s->volume =_mm_read_UBYTE (modreader);
600 s->finetune =_mm_read_SBYTE (modreader);
601 s->type =_mm_read_UBYTE (modreader);
602 s->panning =_mm_read_UBYTE (modreader);
603 s->relnote =_mm_read_SBYTE (modreader);
604 s->vibtype = pth.vibflg;
605 s->vibsweep = pth.vibsweep;
606 s->vibdepth = pth.vibdepth*4;
607 s->vibrate = pth.vibrate;
608 s->reserved =_mm_read_UBYTE (modreader);
609 _mm_read_string(s->samplename, 22, modreader);
611 nextwav[of.numsmp+u]=next;
612 next+=s->length;
614 if(_mm_eof(modreader)) {
615 MikMod_free(nextwav);MikMod_free(wh);
616 nextwav=NULL;wh=NULL;
617 _mm_errno = MMERR_LOADING_SAMPLEINFO;
618 return 0;
622 if(mh->version>0x0103) {
623 for(u=0;u<ih.numsmp;u++)
624 nextwav[of.numsmp++]+=_mm_ftell(modreader);
625 _mm_fseek(modreader,next,SEEK_CUR);
626 } else
627 of.numsmp+=ih.numsmp;
628 } else {
629 /* read the remainder of the header */
630 ck = _mm_ftell(modreader);
631 _mm_fseek(modreader,0,SEEK_END);
632 if ((headend<0) || (_mm_ftell(modreader)<headend) || (headend<ck)) {
633 _mm_fseek(modreader,ck,SEEK_SET);
634 break;
636 _mm_fseek(modreader,ck,SEEK_SET);
637 for(u=headend-_mm_ftell(modreader);u;u--) (void)_mm_read_UBYTE(modreader);
639 if(_mm_eof(modreader)) {
640 MikMod_free(nextwav);MikMod_free(wh);
641 nextwav=NULL;wh=NULL;
642 _mm_errno = MMERR_LOADING_SAMPLEINFO;
643 return 0;
649 /* sanity check */
650 if(!of.numsmp) {
651 if(nextwav) { MikMod_free(nextwav);nextwav=NULL; }
652 if(wh) { MikMod_free(wh);wh=NULL; }
653 _mm_errno = MMERR_LOADING_SAMPLEINFO;
654 return 0;
657 return 1;
660 static int XM_Load(int curious)
662 INSTRUMENT *d;
663 SAMPLE *q;
664 int t,u;
665 int dummypat=0;
666 char tracker[21],modtype[60];
667 (void)curious;
669 /* try to read module header */
670 _mm_read_string(mh->id,17,modreader);
671 _mm_read_string(mh->songname,21,modreader);
672 _mm_read_string(mh->trackername,20,modreader);
673 mh->version =_mm_read_I_UWORD(modreader);
674 if((mh->version<0x102)||(mh->version>0x104)) {
675 _mm_errno=MMERR_NOT_A_MODULE;
676 return 0;
678 mh->headersize =_mm_read_I_ULONG(modreader);
679 mh->songlength =_mm_read_I_UWORD(modreader);
680 mh->restart =_mm_read_I_UWORD(modreader);
681 mh->numchn =_mm_read_I_UWORD(modreader);
682 mh->numpat =_mm_read_I_UWORD(modreader);
683 mh->numins =_mm_read_I_UWORD(modreader);
684 mh->flags =_mm_read_I_UWORD(modreader);
685 mh->tempo =_mm_read_I_UWORD(modreader);
686 mh->bpm =_mm_read_I_UWORD(modreader);
687 if(!mh->bpm) {
688 _mm_errno=MMERR_NOT_A_MODULE;
689 return 0;
691 _mm_read_UBYTES(mh->orders,mh->headersize-20,modreader);
693 if(_mm_eof(modreader)) {
694 _mm_errno = MMERR_LOADING_HEADER;
695 return 0;
698 /* set module variables */
699 of.initspeed = mh->tempo;
700 of.inittempo = mh->bpm;
701 strncpy(tracker,mh->trackername,20);tracker[20]=0;
702 for(t=20;(tracker[t]<=' ')&&(t>=0);t--) tracker[t]=0;
704 /* some modules have the tracker name empty */
705 if (!tracker[0])
706 strcpy(tracker,"Unknown tracker");
708 #ifdef HAVE_SNPRINTF
709 snprintf(modtype,60,"%s (XM format %d.%02d)",
710 tracker,mh->version>>8,mh->version&0xff);
711 #else
712 sprintf(modtype,"%s (XM format %d.%02d)",
713 tracker,mh->version>>8,mh->version&0xff);
714 #endif
715 of.modtype = StrDup(modtype);
716 of.numchn = mh->numchn;
717 of.numpat = mh->numpat;
718 of.numtrk = (UWORD)of.numpat*of.numchn; /* get number of channels */
719 of.songname = DupStr(mh->songname,20,1);
720 of.numpos = mh->songlength; /* copy the songlength */
721 of.reppos = mh->restart<mh->songlength?mh->restart:0;
722 of.numins = mh->numins;
723 of.flags |= UF_XMPERIODS | UF_INST | UF_NOWRAP | UF_FT2QUIRKS |
724 UF_PANNING;
725 if(mh->flags&1) of.flags |= UF_LINEAR;
726 of.bpmlimit = 32;
728 memset(of.chanvol,64,of.numchn); /* store channel volumes */
730 if(!AllocPositions(of.numpos+1)) return 0;
731 for(t=0;t<of.numpos;t++)
732 of.positions[t]=mh->orders[t];
734 /* We have to check for any pattern numbers in the order list greater than
735 the number of patterns total. If one or more is found, we set it equal to
736 the pattern total and make a dummy pattern to workaround the problem */
737 for(t=0;t<of.numpos;t++) {
738 if(of.positions[t]>=of.numpat) {
739 of.positions[t]=of.numpat;
740 dummypat=1;
743 if(dummypat) {
744 of.numpat++;of.numtrk+=of.numchn;
747 if(mh->version<0x0104) {
748 if(!LoadInstruments()) return 0;
749 if(!LoadPatterns(dummypat)) return 0;
750 for(t=0;t<of.numsmp;t++)
751 nextwav[t]+=_mm_ftell(modreader);
752 } else {
753 if(!LoadPatterns(dummypat)) return 0;
754 if(!LoadInstruments()) return 0;
757 if(!AllocSamples()) {
758 MikMod_free(nextwav);MikMod_free(wh);
759 nextwav=NULL;wh=NULL;
760 return 0;
762 q = of.samples;
763 s = wh;
764 for(u=0;u<of.numsmp;u++,q++,s++) {
765 q->samplename = DupStr(s->samplename,22,1);
766 q->length = s->length;
767 q->loopstart = s->loopstart;
768 q->loopend = s->loopstart+s->looplength;
769 q->volume = s->volume;
770 q->speed = s->finetune+128;
771 q->panning = s->panning;
772 q->seekpos = nextwav[u];
773 q->vibtype = s->vibtype;
774 q->vibsweep = s->vibsweep;
775 q->vibdepth = s->vibdepth;
776 q->vibrate = s->vibrate;
778 if(s->type & 0x10) {
779 q->length >>= 1;
780 q->loopstart >>= 1;
781 q->loopend >>= 1;
784 q->flags|=SF_OWNPAN|SF_DELTA|SF_SIGNED;
785 if(s->type&0x3) q->flags|=SF_LOOP;
786 if(s->type&0x2) q->flags|=SF_BIDI;
787 if(s->type&0x10) q->flags|=SF_16BITS;
790 d=of.instruments;
791 s=wh;
792 for(u=0;u<of.numins;u++,d++)
793 for(t=0;t<XMNOTECNT;t++) {
794 if (d->samplenumber[t]>=of.numsmp)
795 d->samplenote[t]=255;
796 else {
797 int note=t+s[d->samplenumber[t]].relnote;
798 d->samplenote[t]=(note<0)?0:note;
802 MikMod_free(wh);MikMod_free(nextwav);
803 wh=NULL;nextwav=NULL;
804 return 1;
807 static CHAR *XM_LoadTitle(void)
809 CHAR s[21];
811 _mm_fseek(modreader,17,SEEK_SET);
812 if(!_mm_read_UBYTES(s,21,modreader)) return NULL;
814 return(DupStr(s,21,1));
817 /*========== Loader information */
819 MIKMODAPI MLOADER load_xm={
820 NULL,
821 "XM",
822 "XM (FastTracker 2)",
823 XM_Init,
824 XM_Test,
825 XM_Load,
826 XM_Cleanup,
827 XM_LoadTitle
830 /* ex:set ts=4: */