summaryrefslogtreecommitdiff
path: root/apps/plugins/mikmod/load_xm.c
diff options
context:
space:
mode:
authorFrank Gevaerts <frank@gevaerts.be>2010-12-12 15:03:30 +0000
committerFrank Gevaerts <frank@gevaerts.be>2010-12-12 15:03:30 +0000
commit26f2bfde03420edad4de1f22cb3d515dc063b20d (patch)
tree4a8c4abaf4795f38da70a4657c1a0fb3ba9debeb /apps/plugins/mikmod/load_xm.c
parentd192bdf11e06e50645ecb5726658d4b691480a9a (diff)
downloadrockbox-26f2bfde03420edad4de1f22cb3d515dc063b20d.tar.gz
rockbox-26f2bfde03420edad4de1f22cb3d515dc063b20d.zip
Add MikMod plugin, ported by Jason Yu, with some minor work by Craig Mann and William Peters (FS#8806)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28810 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/mikmod/load_xm.c')
-rw-r--r--apps/plugins/mikmod/load_xm.c829
1 files changed, 829 insertions, 0 deletions
diff --git a/apps/plugins/mikmod/load_xm.c b/apps/plugins/mikmod/load_xm.c
new file mode 100644
index 0000000000..54a95aa2e6
--- /dev/null
+++ b/apps/plugins/mikmod/load_xm.c
@@ -0,0 +1,829 @@
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: load_xm.c,v 1.5 2008/02/29 18:49:03 denis111 Exp $
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
46extern int fprintf(FILE *, const char *, ...);
47#endif
48
49/*========== Module structure */
50
51typedef 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
68typedef 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)
78typedef 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
99typedef 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
116typedef 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
123typedef struct XMNOTE {
124 UBYTE note,ins,vol,eff,dat;
125} XMNOTE;
126
127/*========== Loader variables */
128
129static XMNOTE *xmpat=NULL;
130static XMHEADER *mh=NULL;
131
132/* increment unit for sample array MikMod_reallocation */
133#define XM_SMPINCR 64
134static ULONG *nextwav=NULL;
135static XMWAVHEADER *wh=NULL,*s=NULL;
136
137/*========== Loader code */
138
139int 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
149int XM_Init(void)
150{
151 if(!(mh=(XMHEADER *)MikMod_malloc(sizeof(XMHEADER)))) return 0;
152 return 1;
153}
154
155void XM_Cleanup(void)
156{
157 MikMod_free(mh);
158}
159
160static int XM_ReadNote(XMNOTE* n)
161{
162 UBYTE cmp,result=1;
163
164 memset(n,0,sizeof(XMNOTE));
165 cmp=_mm_read_UBYTE(modreader);
166
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;
180 }
181 return result;
182}
183
184static UBYTE* XM_Convert(XMNOTE* xmtrack,UWORD rows)
185{
186 int t;
187 UBYTE note,ins,vol,eff,dat;
188
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;
196
197 if(note) {
198 if(note>XMNOTECNT)
199 UniEffect(UNI_KEYFADE,0);
200 else
201 UniNote(note-1);
202 }
203 if(ins) UniInstrument(ins-1);
204
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;
212
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);
243 }
244
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);
271 }
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;
302 }
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);
315 }
316 break;
317 }
318 UniNewline();
319 xmtrack++;
320 }
321 return UniDup();
322}
323
324static int LoadPatterns(int dummypat)
325{
326 int t,u,v,numtrk;
327
328 if(!AllocTracks()) return 0;
329 if(!AllocPatterns()) return 0;
330
331 numtrk=0;
332 for(t=0;t<mh->numpat;t++) {
333 XMPATHEADER ph;
334
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;
339 }
340 ph.packing =_mm_read_UBYTE(modreader);
341 if(ph.packing) {
342 _mm_errno=MMERR_LOADING_PATTERN;
343 return 0;
344 }
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);
350
351 ph.size-=(mh->version==0x0102?8:9);
352 if(ph.size)
353 _mm_fseek(modreader,ph.size,SEEK_CUR);
354
355 of.pattrows[t]=ph.numrows;
356
357 if(ph.numrows) {
358 if(!(xmpat=(XMNOTE*)MikMod_calloc(ph.numrows*of.numchn,sizeof(XMNOTE))))
359 return 0;
360
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;
366
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;
372 }
373 }
374
375 if(ph.packsize) {
376 _mm_fseek(modreader,ph.packsize,SEEK_CUR);
377 }
378
379 if(_mm_eof(modreader)) {
380 MikMod_free(xmpat);xmpat=NULL;
381 _mm_errno=MMERR_LOADING_PATTERN;
382 return 0;
383 }
384
385 for(v=0;v<of.numchn;v++)
386 of.tracks[numtrk++]=XM_Convert(&xmpat[v*ph.numrows],ph.numrows);
387
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);
392 }
393 }
394
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;
401 }
402
403 return 1;
404}
405
406static void FixEnvelope(ENVPT *cur, int pts)
407{
408 int u, old, tmp;
409 ENVPT *prev;
410
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. */
414
415 prev = cur++;
416 old = prev->pos;
417
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;
438 }
439 } else
440 old = cur->pos;
441 }
442}
443
444static int LoadInstruments(void)
445{
446 int t,u, ck;
447 INSTRUMENT *d;
448 ULONG next=0;
449 UWORD wavcnt=0;
450
451 if(!AllocInstruments()) return 0;
452 d=of.instruments;
453 for(t=0;t<of.numins;t++,d++) {
454 XMINSTHEADER ih;
455 long headend;
456
457 memset(d->samplenumber,0xff,INSTNOTES*sizeof(UWORD));
458
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;
468 }
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);
473
474 d->insname = DupStr(ih.name,22,1);
475
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;
481
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);
500
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--) _mm_read_UBYTE(modreader);
504
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;
510
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;
516 }
517
518 for(u=0;u<XMNOTECNT;u++)
519 d->samplenumber[u]=pth.what[u]+of.numsmp;
520 d->volfade = pth.volfade;
521
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]; \
527 } \
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; \
535 \
536 /* scale envelope */ \
537 for (p=0;p<XMENVCNT/2;p++) \
538 d-> name##env[p].val<<=2; \
539 \
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]; \
547 } \
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; \
556 \
557 /* scale envelope */ \
558 for (p=0;p<XMENVCNT/2;p++) \
559 d-> name/**/env[p].val<<=2; \
560 \
561 if ((d-> name/**/flg&EF_ON)&&(d-> name/**/pts<2)) \
562 d-> name/**/flg&=~EF_ON
563#endif
564
565 XM_ProcessEnvelope(vol);
566 XM_ProcessEnvelope(pan);
567#undef XM_ProcessEnvelope
568
569 if (d->volflg & EF_ON)
570 FixEnvelope(d->volenv, d->volpts);
571 if (d->panflg & EF_ON)
572 FixEnvelope(d->panenv, d->panpts);
573
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;
587 }
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;
592 }
593 s=wh+(wavcnt-XM_SMPINCR);
594 }
595
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);
610
611 nextwav[of.numsmp+u]=next;
612 next+=s->length;
613
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;
619 }
620 }
621
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;
635 }
636 _mm_fseek(modreader,ck,SEEK_SET);
637 for(u=headend-_mm_ftell(modreader);u;u--) _mm_read_UBYTE(modreader);
638
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;
644 }
645 }
646 }
647 }
648
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;
655 }
656
657 return 1;
658}
659
660int XM_Load(int curious)
661{
662 INSTRUMENT *d;
663 SAMPLE *q;
664 int t,u;
665 int dummypat=0;
666 char tracker[21],modtype[60];
667
668 /* try to read module header */
669 _mm_read_string(mh->id,17,modreader);
670 _mm_read_string(mh->songname,21,modreader);
671 _mm_read_string(mh->trackername,20,modreader);
672 mh->version =_mm_read_I_UWORD(modreader);
673 if((mh->version<0x102)||(mh->version>0x104)) {
674 _mm_errno=MMERR_NOT_A_MODULE;
675 return 0;
676 }
677 mh->headersize =_mm_read_I_ULONG(modreader);
678 mh->songlength =_mm_read_I_UWORD(modreader);
679 mh->restart =_mm_read_I_UWORD(modreader);
680 mh->numchn =_mm_read_I_UWORD(modreader);
681 mh->numpat =_mm_read_I_UWORD(modreader);
682 mh->numins =_mm_read_I_UWORD(modreader);
683 mh->flags =_mm_read_I_UWORD(modreader);
684 mh->tempo =_mm_read_I_UWORD(modreader);
685 mh->bpm =_mm_read_I_UWORD(modreader);
686 if(!mh->bpm) {
687 _mm_errno=MMERR_NOT_A_MODULE;
688 return 0;
689 }
690 _mm_read_UBYTES(mh->orders,mh->headersize-20,modreader);
691
692 if(_mm_eof(modreader)) {
693 _mm_errno = MMERR_LOADING_HEADER;
694 return 0;
695 }
696
697 /* set module variables */
698 of.initspeed = mh->tempo;
699 of.inittempo = mh->bpm;
700 strncpy(tracker,mh->trackername,20);tracker[20]=0;
701 for(t=20;(tracker[t]<=' ')&&(t>=0);t--) tracker[t]=0;
702
703 /* some modules have the tracker name empty */
704 if (!tracker[0])
705 strcpy(tracker,"Unknown tracker");
706
707#ifdef HAVE_SNPRINTF
708 snprintf(modtype,60,"%s (XM format %d.%02d)",
709 tracker,mh->version>>8,mh->version&0xff);
710#else
711 sprintf(modtype,"%s (XM format %d.%02d)",
712 tracker,mh->version>>8,mh->version&0xff);
713#endif
714 of.modtype = StrDup(modtype);
715 of.numchn = mh->numchn;
716 of.numpat = mh->numpat;
717 of.numtrk = (UWORD)of.numpat*of.numchn; /* get number of channels */
718 of.songname = DupStr(mh->songname,20,1);
719 of.numpos = mh->songlength; /* copy the songlength */
720 of.reppos = mh->restart<mh->songlength?mh->restart:0;
721 of.numins = mh->numins;
722 of.flags |= UF_XMPERIODS | UF_INST | UF_NOWRAP | UF_FT2QUIRKS |
723 UF_PANNING;
724 if(mh->flags&1) of.flags |= UF_LINEAR;
725 of.bpmlimit = 32;
726
727 memset(of.chanvol,64,of.numchn); /* store channel volumes */
728
729 if(!AllocPositions(of.numpos+1)) return 0;
730 for(t=0;t<of.numpos;t++)
731 of.positions[t]=mh->orders[t];
732
733 /* We have to check for any pattern numbers in the order list greater than
734 the number of patterns total. If one or more is found, we set it equal to
735 the pattern total and make a dummy pattern to workaround the problem */
736 for(t=0;t<of.numpos;t++) {
737 if(of.positions[t]>=of.numpat) {
738 of.positions[t]=of.numpat;
739 dummypat=1;
740 }
741 }
742 if(dummypat) {
743 of.numpat++;of.numtrk+=of.numchn;
744 }
745
746 if(mh->version<0x0104) {
747 if(!LoadInstruments()) return 0;
748 if(!LoadPatterns(dummypat)) return 0;
749 for(t=0;t<of.numsmp;t++)
750 nextwav[t]+=_mm_ftell(modreader);
751 } else {
752 if(!LoadPatterns(dummypat)) return 0;
753 if(!LoadInstruments()) return 0;
754 }
755
756 if(!AllocSamples()) {
757 MikMod_free(nextwav);MikMod_free(wh);
758 nextwav=NULL;wh=NULL;
759 return 0;
760 }
761 q = of.samples;
762 s = wh;
763 for(u=0;u<of.numsmp;u++,q++,s++) {
764 q->samplename = DupStr(s->samplename,22,1);
765 q->length = s->length;
766 q->loopstart = s->loopstart;
767 q->loopend = s->loopstart+s->looplength;
768 q->volume = s->volume;
769 q->speed = s->finetune+128;
770 q->panning = s->panning;
771 q->seekpos = nextwav[u];
772 q->vibtype = s->vibtype;
773 q->vibsweep = s->vibsweep;
774 q->vibdepth = s->vibdepth;
775 q->vibrate = s->vibrate;
776
777 if(s->type & 0x10) {
778 q->length >>= 1;
779 q->loopstart >>= 1;
780 q->loopend >>= 1;
781 }
782
783 q->flags|=SF_OWNPAN|SF_DELTA|SF_SIGNED;
784 if(s->type&0x3) q->flags|=SF_LOOP;
785 if(s->type&0x2) q->flags|=SF_BIDI;
786 if(s->type&0x10) q->flags|=SF_16BITS;
787 }
788
789 d=of.instruments;
790 s=wh;
791 for(u=0;u<of.numins;u++,d++)
792 for(t=0;t<XMNOTECNT;t++) {
793 if (d->samplenumber[t]>=of.numsmp)
794 d->samplenote[t]=255;
795 else {
796 int note=t+s[d->samplenumber[t]].relnote;
797 d->samplenote[t]=(note<0)?0:note;
798 }
799 }
800
801 MikMod_free(wh);MikMod_free(nextwav);
802 wh=NULL;nextwav=NULL;
803 return 1;
804}
805
806CHAR *XM_LoadTitle(void)
807{
808 CHAR s[21];
809
810 _mm_fseek(modreader,17,SEEK_SET);
811 if(!_mm_read_UBYTES(s,21,modreader)) return NULL;
812
813 return(DupStr(s,21,1));
814}
815
816/*========== Loader information */
817
818MIKMODAPI MLOADER load_xm={
819 NULL,
820 "XM",
821 "XM (FastTracker 2)",
822 XM_Init,
823 XM_Test,
824 XM_Load,
825 XM_Cleanup,
826 XM_LoadTitle
827};
828
829/* ex:set ts=4: */