home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1999 February / PCO_0299.ISO / filesbbs / linux / mikmod-3.000 / mikmod-3 / mikmod-3.1.2 / loaders / load_xm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-12-07  |  17.6 KB  |  666 lines

  1. /*    MikMod sound library
  2.     (c) 1998 Miodrag Vallat and others - see file AUTHORS for complete list
  3.  
  4.     This library is free software; you can redistribute it and/or modify
  5.     it under the terms of the GNU Library General Public License as
  6.     published by the Free Software Foundation; either version 2 of
  7.     the License, or (at your option) any later version.
  8.  
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU Library General Public License for more details.
  13.  
  14.     You should have received a copy of the GNU Library General Public
  15.     License along with this library; if not, write to the Free Software
  16.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18.  
  19. /*==============================================================================
  20.  
  21.   $Id: load_xm.c,v 1.18 1998/12/07 06:00:24 miod Exp $
  22.  
  23.   Fasttracker (XM) module loader
  24.  
  25. ==============================================================================*/
  26.  
  27. #ifdef HAVE_CONFIG_H
  28. #include "config.h"
  29. #endif
  30.  
  31. #include <string.h>
  32.  
  33. #include <mikmod_internals.h>
  34.  
  35. /*========== Module structure */
  36.  
  37. typedef struct XMHEADER {
  38.     CHAR  id[17];          /* ID text: 'Extended module: ' */
  39.     CHAR  songname[21];    /* Module name */
  40.     CHAR  trackername[20]; /* Tracker name */
  41.     UWORD version;         /* Version number */
  42.     ULONG headersize;      /* Header size */
  43.     UWORD songlength;      /* Song length (in patten order table) */
  44.     UWORD restart;         /* Restart position */
  45.     UWORD numchn;          /* Number of channels (2,4,6,8,10,...,32) */
  46.     UWORD numpat;          /* Number of patterns (max 256) */
  47.     UWORD numins;          /* Number of instruments (max 128) */
  48.     UWORD flags;       
  49.     UWORD tempo;           /* Default tempo */
  50.     UWORD bpm;             /* Default BPM */
  51.     UBYTE orders[256];     /* Pattern order table  */
  52. } XMHEADER;
  53.  
  54. typedef struct XMINSTHEADER {
  55.     ULONG size;     /* Instrument size */
  56.     CHAR  name[22]; /* Instrument name */
  57.     UBYTE type;     /* Instrument type (always 0) */
  58.     UWORD numsmp;   /* Number of samples in instrument */
  59.     ULONG ssize;
  60. } XMINSTHEADER;
  61.  
  62. #define XMENVCNT 24
  63. #define XMNOTECNT 8*OCTAVE
  64. typedef struct XMPATCHHEADER {
  65.     UBYTE what[XMNOTECNT];  /*  Sample number for all notes */
  66.     UWORD volenv[XMENVCNT]; /*  Points for volume envelope */
  67.     UWORD panenv[XMENVCNT]; /*  Points for panning envelope */
  68.     UBYTE volpts;      /*  Number of volume points */
  69.     UBYTE panpts;      /*  Number of panning points */
  70.     UBYTE volsus;      /*  Volume sustain point */
  71.     UBYTE volbeg;      /*  Volume loop start point */
  72.     UBYTE volend;      /*  Volume loop end point */
  73.     UBYTE pansus;      /*  Panning sustain point */
  74.     UBYTE panbeg;      /*  Panning loop start point */
  75.     UBYTE panend;      /*  Panning loop end point */
  76.     UBYTE volflg;      /*  Volume type: bit 0: On; 1: Sustain; 2: Loop */
  77.     UBYTE panflg;      /*  Panning type: bit 0: On; 1: Sustain; 2: Loop */
  78.     UBYTE vibflg;      /*  Vibrato type */
  79.     UBYTE vibsweep;    /*  Vibrato sweep */
  80.     UBYTE vibdepth;    /*  Vibrato depth */
  81.     UBYTE vibrate;     /*  Vibrato rate */
  82.     UWORD volfade;     /*  Volume fadeout */
  83.     UWORD reserved[11];
  84. } XMPATCHHEADER;
  85.  
  86. typedef struct XMWAVHEADER {
  87.     ULONG length;         /* Sample length */
  88.     ULONG loopstart;      /* Sample loop start */
  89.     ULONG looplength;     /* Sample loop length */
  90.     UBYTE volume;         /* Volume  */
  91.     SBYTE finetune;       /* Finetune (signed byte -128..+127) */
  92.     UBYTE type;           /* Loop type */
  93.     UBYTE panning;        /* Panning (0-255) */
  94.     SBYTE relnote;        /* Relative note number (signed byte) */
  95.     UBYTE reserved;       /* Reserved */
  96.     CHAR  samplename[22]; /* Sample name */
  97.     UBYTE vibtype;        /* Vibrato type */
  98.     UBYTE vibsweep;       /* Vibrato sweep */
  99.     UBYTE vibdepth;       /* Vibrato depth */
  100.     UBYTE vibrate;        /* Vibrato rate */
  101. } XMWAVHEADER;
  102.  
  103. typedef struct XMPATHEADER {
  104.     ULONG size;     /* Pattern header length  */
  105.     UBYTE packing;  /* Packing type (always 0) */
  106.     UWORD numrows;  /* Number of rows in pattern (1..256) */
  107.     UWORD packsize; /* Packed patterndata size */
  108. } XMPATHEADER;
  109.  
  110. typedef struct XMNOTE {
  111.     UBYTE note,ins,vol,eff,dat;
  112. } XMNOTE;
  113.  
  114. /*========== Loader variables */
  115.  
  116. static    XMNOTE *xmpat = NULL;
  117. static    XMHEADER *mh = NULL;
  118.  
  119. /*========== Loader code */
  120.  
  121. BOOL XM_Test(void)
  122. {
  123.     UBYTE id[38];
  124.  
  125.     if(!_mm_read_UBYTES(id,38,modfp)) return 0;
  126.     if(memcmp(id,"Extended Module: ",17)) return 0;
  127.     if(id[37]==0x1a) return 1;
  128.     return 0;
  129. }
  130.  
  131. BOOL XM_Init(void)
  132. {
  133.     if(!(mh=(XMHEADER *)_mm_malloc(sizeof(XMHEADER)))) return 0;
  134.     return 1;
  135. }
  136.  
  137. void XM_Cleanup(void)
  138. {
  139.     if(mh) free(mh);
  140.     mh = NULL;
  141. }
  142.  
  143. void XM_ReadNote(XMNOTE* n)
  144. {
  145.     UBYTE cmp;
  146.  
  147.     memset(n,0,sizeof(XMNOTE));
  148.     cmp=_mm_read_UBYTE(modfp);
  149.  
  150.     if(cmp&0x80) {
  151.         if(cmp&1)  n->note = _mm_read_UBYTE(modfp);
  152.         if(cmp&2)  n->ins  = _mm_read_UBYTE(modfp);
  153.         if(cmp&4)  n->vol  = _mm_read_UBYTE(modfp);
  154.         if(cmp&8)  n->eff  = _mm_read_UBYTE(modfp);
  155.         if(cmp&16) n->dat  = _mm_read_UBYTE(modfp);
  156.     } else {
  157.         n->note = cmp;
  158.         n->ins  = _mm_read_UBYTE(modfp);
  159.         n->vol  = _mm_read_UBYTE(modfp);
  160.         n->eff  = _mm_read_UBYTE(modfp);
  161.         n->dat  = _mm_read_UBYTE(modfp);
  162.     }
  163. }
  164.  
  165. UBYTE* XM_Convert(XMNOTE* xmtrack,UWORD rows)
  166. {
  167.     int t;
  168.     UBYTE note,ins,vol,eff,dat;
  169.  
  170.     UniReset();
  171.     for(t=0;t<rows;t++) {
  172.         note = xmtrack->note;
  173.         ins  = xmtrack->ins;
  174.         vol  = xmtrack->vol;
  175.         eff  = xmtrack->eff;
  176.         dat  = xmtrack->dat;
  177.  
  178.         if(note) {
  179.             if(note==8*OCTAVE+1) {
  180.                 UniWrite(UNI_KEYFADE);
  181.                 UniWrite(0);
  182.             } else
  183.                 UniNote(note-1);
  184.         }
  185.         if(ins) UniInstrument(ins-1);
  186.  
  187.         switch(vol>>4) {
  188.             case 0x6: /* volslide down */
  189.                 if(vol&0xf) {
  190.                     UniWrite(UNI_XMEFFECTA);
  191.                     UniWrite(vol&0xf);
  192.                 }
  193.                 break;
  194.             case 0x7: /* volslide up */
  195.                 if(vol&0xf) {
  196.                     UniWrite(UNI_XMEFFECTA);
  197.                     UniWrite(vol<<4);
  198.                 }
  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) {
  221.                     UniWrite(UNI_XMEFFECTP);
  222.                     UniWrite(vol&0xf);
  223.                 }
  224.                 break;
  225.             case 0xe: /* panning slide right (only slide when data not zero) */
  226.                 if(vol&0xf) {
  227.                     UniWrite(UNI_XMEFFECTP);
  228.                     UniWrite(vol<<4);
  229.                 }
  230.                 break;
  231.             case 0xf: /* tone porta */
  232.                 UniPTEffect(0x3,vol<<4);
  233.                 break;
  234.             default:
  235.                 if((vol>=0x10)&&(vol<=0x50))
  236.                     UniPTEffect(0xc,vol-0x10);
  237.         }
  238.  
  239.         switch(eff) {
  240.             case 0x4: /* Effect 4: Vibrato */
  241.                 UniWrite(UNI_XMEFFECT4);
  242.                 UniWrite(dat);
  243.                 break;
  244.             case 0xa:
  245.                 UniWrite(UNI_XMEFFECTA);
  246.                 UniWrite(dat);
  247.                 break;
  248.             case 0xe: /* Extended effects */
  249.                 switch(dat>>4) {
  250.                     case 0x1: /* XM fine porta up */
  251.                         UniWrite(UNI_XMEFFECTE1);
  252.                         UniWrite(dat&0xf);
  253.                         break;
  254.                     case 0x2: /* XM fine porta down */
  255.                         UniWrite(UNI_XMEFFECTE2);
  256.                         UniWrite(dat&0xf);
  257.                         break;
  258.                     case 0xa: /* XM fine volume up */
  259.                         UniWrite(UNI_XMEFFECTEA);
  260.                         UniWrite(dat&0xf);
  261.                         break;
  262.                     case 0xb: /* XM fine volume down */
  263.                         UniWrite(UNI_XMEFFECTEB);
  264.                         UniWrite(dat&0xf);
  265.                         break;
  266.                     default:
  267.                         UniPTEffect(0x0e,dat);
  268.                 }
  269.                 break;
  270.             case 'G'-55: /* G - set global volume */
  271.                 UniWrite(UNI_XMEFFECTG);
  272.                 UniWrite(dat>64?64:dat);
  273.                 break;
  274.             case 'H'-55: /* H - global volume slide */
  275.                 UniWrite(UNI_XMEFFECTH);
  276.                 UniWrite(dat);
  277.                 break;
  278.             case 'K'-55: /* K - keyOff and KeyFade */
  279.                 UniWrite(UNI_KEYFADE);
  280.                 UniWrite(dat);
  281.                 break;
  282.             case 'L'-55: /* L - set envelope position */
  283.                 UniWrite(UNI_XMEFFECTL);
  284.                 UniWrite(dat);
  285.                 break;
  286.             case 'P'-55: /* P - panning slide */
  287.                 UniWrite(UNI_XMEFFECTP);
  288.                 UniWrite(dat);
  289.                 break;
  290.             case 'R'-55: /* R - multi retrig note */
  291.                 UniWrite(UNI_S3MEFFECTQ);
  292.                 UniWrite(dat);
  293.                 break;
  294.             case 'T'-55: /* T - Tremor */
  295.                 UniWrite(UNI_S3MEFFECTI);
  296.                 UniWrite(dat);
  297.                 break;
  298.             case 'X'-55:
  299.                 switch(dat>>4) {
  300.                     case 1: /* X1 - Extra Fine Porta up */
  301.                         UniWrite(UNI_XMEFFECTX1);
  302.                         UniWrite(dat&0xf);
  303.                         break;
  304.                     case 2: /* X2 - Extra Fine Porta down */
  305.                         UniWrite(UNI_XMEFFECTX2);
  306.                         UniWrite(dat&0xf);
  307.                         break;
  308.                 }
  309.                 break;
  310.             default:
  311.                 if(!(eff>>4)) {
  312.                     /* Convert pattern jump from Dec to Hex */
  313.                     if(eff==0xd)
  314.                         dat=(((dat&0xf0)>>4)*10)+(dat&0xf);
  315.                     /* finetune conversion to Lxx */
  316.                     if(eff==5)
  317.                         S3MIT_ProcessCmd(0xc,dat,1);
  318.                     else
  319.                         UniPTEffect(eff,dat);
  320.                 }
  321.                 break;
  322.         }
  323.         UniNewline();
  324.         xmtrack++;
  325.     }
  326.     return UniDup();
  327. }
  328.  
  329. BOOL XM_Load(BOOL curious)
  330. {
  331. #define XM_SMPINCR 64
  332.     INSTRUMENT *d;
  333.     SAMPLE *q;
  334.     XMWAVHEADER *wh=NULL,*s=NULL;
  335.     int t,u,v,p,numtrk;
  336.     long next;
  337.     ULONG *nextwav=NULL;
  338.     UWORD wavcnt=0;
  339.     BOOL dummypat=0;
  340.  
  341.     /* try to read module header */
  342.     _mm_read_string(mh->id,17,modfp);
  343.     _mm_read_string(mh->songname,21,modfp);
  344.     _mm_read_string(mh->trackername,20,modfp);
  345.     mh->version     =_mm_read_I_UWORD(modfp);
  346.     if((mh->version<0x100)||(mh->version>0x104)) {
  347.         _mm_errno=MMERR_NOT_A_MODULE;
  348.         return 0;
  349.     }
  350.     mh->headersize  =_mm_read_I_ULONG(modfp);
  351.     mh->songlength  =_mm_read_I_UWORD(modfp);
  352.     mh->restart     =_mm_read_I_UWORD(modfp);
  353.     mh->numchn      =_mm_read_I_UWORD(modfp);
  354.     mh->numpat      =_mm_read_I_UWORD(modfp);
  355.     mh->numins      =_mm_read_I_UWORD(modfp);
  356.     mh->flags       =_mm_read_I_UWORD(modfp);
  357.     mh->tempo       =_mm_read_I_UWORD(modfp);
  358.     mh->bpm         =_mm_read_I_UWORD(modfp);
  359.     if(!mh->bpm) {
  360.         _mm_errno=MMERR_NOT_A_MODULE;
  361.         return 0;
  362.     }
  363.     _mm_read_UBYTES(mh->orders,256,modfp);
  364.  
  365.     if(feof(modfp)) {
  366.         _mm_errno = MMERR_LOADING_HEADER;
  367.         return 0;
  368.     }
  369.  
  370.     /* set module variables */
  371.     of.initspeed = mh->tempo;         
  372.     of.inittempo = mh->bpm;
  373.     of.modtype   = DupStr(mh->trackername,20);
  374.     of.numchn    = mh->numchn;
  375.     of.numpat    = mh->numpat;
  376.     of.numtrk    = (UWORD)of.numpat*of.numchn;   /* get number of channels */
  377.     of.songname  = DupStr(mh->songname,20);
  378.     of.numpos    = mh->songlength;               /* copy the songlength */
  379.     of.reppos    = mh->restart<mh->songlength?mh->restart:0;
  380.     of.numins    = mh->numins;
  381.     of.flags |= UF_XMPERIODS | UF_INST;
  382.     if(mh->flags&1) of.flags |= UF_LINEAR;
  383.  
  384.     memset(of.chanvol,64,of.numchn);             /* store channel volumes */
  385.  
  386.     if(!AllocPositions(of.numpos+1)) return 0;
  387.     for(t=0;t<of.numpos;t++)
  388.         of.positions[t]=mh->orders[t];
  389.  
  390.     /* We have to check for any pattern numbers in the order list greater than
  391.        the number of patterns total. If one or more is found, we set it equal to
  392.        the pattern total and make a dummy pattern to workaround the problem */
  393.     for(t=0;t<of.numpos;t++) {
  394.         if(of.positions[t]>=of.numpat) {
  395.             of.positions[t]=of.numpat;
  396.             dummypat=1;
  397.         }
  398.     }
  399.     if(dummypat) {
  400.         of.numpat++;of.numtrk+=of.numchn;
  401.     }
  402.  
  403.     if(!AllocTracks()) return 0;
  404.     if(!AllocPatterns()) return 0;
  405.     numtrk=0;
  406.     for(t=0;t<mh->numpat;t++) {
  407.         XMPATHEADER ph;
  408.  
  409.         ph.size     =_mm_read_I_ULONG(modfp);
  410.         ph.packing  =_mm_read_UBYTE(modfp);
  411.         if(ph.packing) {
  412.             _mm_errno=MMERR_LOADING_PATTERN;
  413.             return 0;
  414.         }
  415.         ph.numrows  =_mm_read_I_UWORD(modfp);
  416.         ph.packsize =_mm_read_I_UWORD(modfp);
  417.  
  418.         of.pattrows[t]=ph.numrows;
  419.  
  420.         if(ph.numrows) {
  421.             if(!(xmpat=(XMNOTE*)_mm_calloc(ph.numrows*of.numchn,sizeof(XMNOTE))))
  422.                 return 0;
  423.  
  424.             /* when packsize is 0, don't try to load a pattern.. it's empty. */
  425.             if(ph.packsize) 
  426.                 for(u=0;u<ph.numrows;u++) 
  427.                     for(v=0;v<of.numchn;v++)
  428.                         XM_ReadNote(&xmpat[(v*ph.numrows)+u]);
  429.  
  430.             if(feof(modfp)) {
  431.                 free(xmpat);
  432.                 _mm_errno=MMERR_LOADING_PATTERN;
  433.                 return 0;
  434.             }
  435.  
  436.             for(v=0;v<of.numchn;v++)
  437.                 of.tracks[numtrk++]=XM_Convert(&xmpat[v*ph.numrows],ph.numrows);
  438.  
  439.             free(xmpat);
  440.         } else {
  441.             for(v=0;v<of.numchn;v++)
  442.                 of.tracks[numtrk++]=XM_Convert(NULL,ph.numrows);
  443.         }
  444.     }
  445.  
  446.     if(dummypat) {
  447.         of.pattrows[t]=64;
  448.         if(!(xmpat=(XMNOTE*)_mm_calloc(64*of.numchn,sizeof(XMNOTE)))) return 0;
  449.         for(v=0;v<of.numchn;v++)
  450.             of.tracks[numtrk++]=XM_Convert(&xmpat[v*64],64);
  451.         free(xmpat);
  452.     }
  453.  
  454.     if(!AllocInstruments()) return 0;
  455.     d=of.instruments;
  456.  
  457.     for(t=0;t<of.numins;t++) {
  458.         XMINSTHEADER ih;
  459.         int headend;
  460.  
  461.         memset(d->samplenumber,255,INSTNOTES);
  462.  
  463.         /* read instrument header */
  464.         headend     = _mm_ftell(modfp);
  465.         ih.size     = _mm_read_I_ULONG(modfp);
  466.         headend    += ih.size;
  467.         _mm_read_string(ih.name, 22, modfp);
  468.         ih.type     = _mm_read_UBYTE(modfp);
  469.         ih.numsmp   = _mm_read_I_UWORD(modfp);
  470.         d->insname  = DupStr(ih.name,22);
  471.  
  472.         if((SWORD)ih.size>29) {
  473.             ih.ssize    = _mm_read_I_ULONG(modfp);
  474.             if(((SWORD)ih.numsmp>0)&&(ih.numsmp<=XMNOTECNT)) {
  475.                 XMPATCHHEADER pth;
  476.  
  477.                 _mm_read_UBYTES (pth.what,XMNOTECNT,modfp);
  478.                 _mm_read_I_UWORDS (pth.volenv, XMENVCNT, modfp);
  479.                 _mm_read_I_UWORDS (pth.panenv, XMENVCNT, modfp);
  480.                 pth.volpts      =  _mm_read_UBYTE(modfp);
  481.                 pth.panpts      =  _mm_read_UBYTE(modfp);
  482.                 pth.volsus      =  _mm_read_UBYTE(modfp);
  483.                 pth.volbeg      =  _mm_read_UBYTE(modfp);
  484.                 pth.volend      =  _mm_read_UBYTE(modfp);
  485.                 pth.pansus      =  _mm_read_UBYTE(modfp);
  486.                 pth.panbeg      =  _mm_read_UBYTE(modfp);
  487.                 pth.panend      =  _mm_read_UBYTE(modfp);
  488.                 pth.volflg      =  _mm_read_UBYTE(modfp);
  489.                 pth.panflg      =  _mm_read_UBYTE(modfp);
  490.                 pth.vibflg      =  _mm_read_UBYTE(modfp);
  491.                 pth.vibsweep    =  _mm_read_UBYTE(modfp);
  492.                 pth.vibdepth    =  _mm_read_UBYTE(modfp);
  493.                 pth.vibrate     =  _mm_read_UBYTE(modfp);
  494.                 pth.volfade     =  _mm_read_I_UWORD(modfp);
  495.  
  496.                 /* read the remainder of the header */
  497.                 for(u=headend-_mm_ftell(modfp);u;u--) _mm_read_UBYTE(modfp);
  498.  
  499.                 if(feof(modfp)) {
  500.                     free(nextwav);free(wh);
  501.                     _mm_errno = MMERR_LOADING_SAMPLEINFO;
  502.                     return 0;
  503.                 }
  504.  
  505.                 for(u=0;u<XMNOTECNT;u++)
  506.                     d->samplenumber[u]=pth.what[u]+of.numsmp;
  507.                 d->volfade = pth.volfade;
  508.                 memcpy(d->volenv,pth.volenv,XMENVCNT);
  509.                 if(pth.volflg & 1)  d->volflg |= EF_ON;
  510.                 if(pth.volflg & 2)  d->volflg |= EF_SUSTAIN;
  511.                 if(pth.volflg & 4)  d->volflg |= EF_LOOP;
  512.                 d->volsusbeg = d->volsusend = pth.volsus;
  513.                 d->volbeg    = pth.volbeg;
  514.                 d->volend    = pth.volend;
  515.                 d->volpts    = pth.volpts;
  516.  
  517.                 /* scale volume envelope: */
  518.                 for(p=0;p<XMENVCNT/2;p++)
  519.                     d->volenv[p].val<<=2;
  520.  
  521.                 if((d->volflg & EF_ON)&&(d->volpts<2))
  522.                     d->volflg &= ~EF_ON;
  523.  
  524.                 memcpy(d->panenv,pth.panenv,XMENVCNT);
  525.                 d->panflg    = pth.panflg;
  526.                 d->pansusbeg = d->pansusend = pth.pansus;
  527.                 d->panbeg    = pth.panbeg;
  528.                 d->panend    = pth.panend;
  529.                 d->panpts    = pth.panpts;
  530.  
  531.                 /* scale panning envelope: */
  532.                 for(p=0;p<XMENVCNT/2;p++)
  533.                     d->panenv[p].val<<=2;
  534.                 if((d->panflg & EF_ON) && (d->panpts<2))
  535.                     d->panflg &= ~EF_ON;
  536.                 next = 0;
  537.  
  538.                 /* Samples are stored outside the instrument struct now, so we
  539.                    have to load them all into a temp area, count the of.numsmp
  540.                    along the way and then do an AllocSamples() and move
  541.                    everything over */
  542.                 for(u=0; u<ih.numsmp;u++,s++) {
  543.                     /* Allocate more room for sample information if necessary */
  544.                     if(of.numsmp+u==wavcnt) {
  545.                         wavcnt+=XM_SMPINCR;
  546.                         if(!(nextwav=realloc(nextwav,wavcnt*sizeof(ULONG)))){
  547.                             free(wh);
  548.                             _mm_errno = MMERR_OUT_OF_MEMORY;
  549.                             return 0;
  550.                         }
  551.                         if(!(wh=realloc(wh,wavcnt*sizeof(XMWAVHEADER)))) {
  552.                             free(nextwav);
  553.                             _mm_errno = MMERR_OUT_OF_MEMORY;
  554.                             return 0;
  555.                         }
  556.                         s=wh+(wavcnt-XM_SMPINCR);
  557.                     }
  558.  
  559.                     s->length       =_mm_read_I_ULONG (modfp);
  560.                     s->loopstart    =_mm_read_I_ULONG (modfp);
  561.                     s->looplength   =_mm_read_I_ULONG (modfp);
  562.                     s->volume       =_mm_read_UBYTE (modfp);
  563.                     s->finetune     =_mm_read_SBYTE (modfp);
  564.                     s->type         =_mm_read_UBYTE (modfp);
  565.                     s->panning      =_mm_read_UBYTE (modfp);
  566.                     s->relnote      =_mm_read_SBYTE (modfp);
  567.                     s->vibtype      = pth.vibflg;
  568.                     s->vibsweep     = pth.vibsweep;
  569.                     s->vibdepth     = pth.vibdepth*4;
  570.                     s->vibrate      = pth.vibrate;
  571.                     s->reserved     =_mm_read_UBYTE (modfp);
  572.                     _mm_read_string(s->samplename, 22, modfp);
  573.  
  574.                     nextwav[of.numsmp+u]=next;
  575.                     next+=s->length;
  576.  
  577.                     if(feof(modfp)) {
  578.                         free(nextwav);free(wh);
  579.                         _mm_errno = MMERR_LOADING_SAMPLEINFO;
  580.                         return 0;
  581.                     }
  582.                 }
  583.  
  584.                 for(u=0;u<ih.numsmp;u++)
  585.                     nextwav[of.numsmp++]+=_mm_ftell(modfp);
  586.                 _mm_fseek(modfp,next,SEEK_CUR);
  587.             }
  588.         }
  589.         d++;
  590.     }
  591.  
  592.     /* sanity check */
  593.     if(!of.numsmp) {
  594.         free(nextwav);free(wh);
  595.         _mm_errno = MMERR_LOADING_SAMPLEINFO;
  596.         return 0;
  597.     }
  598.  
  599.     if(!AllocSamples()) {
  600.         free(nextwav);free(wh);
  601.         return 0;
  602.     }
  603.     q = of.samples;
  604.     s = wh;
  605.     for(u=0;u<of.numsmp;u++,q++,s++) {
  606.         q->samplename   = DupStr(s->samplename,22);
  607.         q->length       = s->length;
  608.         q->loopstart    = s->loopstart;
  609.         q->loopend      = s->loopstart+s->looplength;
  610.         q->volume       = s->volume;
  611.         q->speed        = s->finetune+128;
  612.         q->panning      = s->panning;
  613.         q->seekpos      = nextwav[u];
  614.         q->vibtype      = s->vibtype;
  615.         q->vibsweep     = s->vibsweep;
  616.         q->vibdepth     = s->vibdepth;
  617.         q->vibrate      = s->vibrate;
  618.  
  619.         if(s->type & 0x10) {
  620.             q->length    >>= 1;
  621.             q->loopstart >>= 1;
  622.             q->loopend   >>= 1;
  623.         }
  624.  
  625.         q->flags|=SF_OWNPAN;
  626.         if(s->type&0x3) q->flags|=SF_LOOP;
  627.         if(s->type&0x2) q->flags|=SF_BIDI;
  628.         if(s->type&0x10) q->flags|=SF_16BITS;
  629.         q->flags|=SF_DELTA|SF_SIGNED;
  630.     }
  631.  
  632.     d = of.instruments;
  633.     s = wh;
  634.     for(u=0;u<of.numins;u++,d++) {
  635.         for(t=0;t<XMNOTECNT;t++)
  636.             d->samplenote[t]=(d->samplenumber[t]>=of.numsmp)?
  637.               255:(t+s[d->samplenumber[t]].relnote);
  638.     }
  639.  
  640.     free(wh);free(nextwav);
  641.     return 1;
  642. }
  643.  
  644. CHAR *XM_LoadTitle(void)
  645. {
  646.     CHAR s[21];
  647.  
  648.     _mm_fseek(modfp,17,SEEK_SET);
  649.     if(!fread(s,21,1,modfp)) return NULL;
  650.  
  651.     return(DupStr(s,21));
  652. }
  653.  
  654. /*========== Loader information */
  655.  
  656. MLOADER load_xm={
  657.     NULL,
  658.     "XM",
  659.     "XM loader v1.0",
  660.     XM_Init,
  661.     XM_Test,
  662.     XM_Load,
  663.     XM_Cleanup,
  664.     XM_LoadTitle
  665. };
  666.