~and471/ubuntu/maverick/frozen-bubble/fix-599809

« back to all changes in this revision

Viewing changes to SDL_mixer_patched/mikmod/load_xm.c

  • Committer: Bazaar Package Importer
  • Author(s): Josselin Mouette
  • Date: 2004-07-08 17:22:16 UTC
  • mfrom: (2.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20040708172216-4e9erxuhsq7djmnd
Tags: 1.0.0-6
c_stuff/lib/FBLE.pm: fix to deal with new SDL_perl (closes: #257749).

Show diffs side-by-side

added added

removed removed

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