home *** CD-ROM | disk | FTP | other *** search
/ Inter.Net 55-1 / Inter.Net 55-1.iso / beos / PPBeDevKit.ZIP / PLAYERPR.TAR / PlayerPRO / Source / Import-Export / XM.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-12-26  |  31.0 KB  |  1,328 lines

  1. /********************                        ***********************/
  2. //
  3. //    Player PRO 5.0 - DRIVER SOURCE CODE -
  4. //
  5. //    Library Version 5.0
  6. //
  7. //    To use with MAD Library for Mac: Symantec, CodeWarrior and MPW
  8. //
  9. //    Antoine ROSSET
  10. //    16 Tranchees
  11. //    1206 GENEVA
  12. //    SWITZERLAND
  13. //
  14. //    COPYRIGHT ANTOINE ROSSET 1996, 1997, 1998
  15. //
  16. //    Thank you for your interest in PlayerPRO !
  17. //
  18. //    FAX:                (+41 22) 346 11 97
  19. //    PHONE:             (+41 79) 203 74 62
  20. //    Internet:     RossetAntoine@bluewin.ch
  21. //
  22. /********************                        ***********************/
  23.  
  24.  
  25. #include "RDriver.h"
  26. #include "XM.h"
  27. #include "FileUtils.h"
  28.  
  29. #ifdef _MAC_H
  30. #if defined(powerc) || defined(__powerc)
  31. enum {
  32.         PlayerPROPlug = kCStackBased
  33.         | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
  34.         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof( OSType)))
  35.         | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof( Ptr)))
  36.         | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof( MADMusic*)))
  37.         | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof( PPInfoRec*)))
  38.         | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof( MADDriverSettings*)))
  39. };
  40.  
  41. ProcInfoType __procinfo = PlayerPROPlug;
  42. #else
  43. #include <A4Stuff.h>
  44. #endif
  45. #endif
  46.  
  47. Ptr MADPlugNewPtr( long size, MADDriverSettings* init);
  48.  
  49. /**************************************************************************
  50. **************************************************************************/
  51.  
  52. #define HEADERSIZE     276
  53. #define PHSIZE        9
  54. #define IHSIZE        263
  55. #define IHSIZESMALL    33
  56. #define IHSSIZE        40
  57.  
  58. static XMHEADER     *mh;
  59. static Ptr            theXMRead, theXMMax;
  60.  
  61. #define READXMFILE(dst, size)    {BlockMove( theXMRead, dst, size);    theXMRead += (long) size;}
  62. #define WRITEXMFILE(src, size)    {BlockMove( src, theXMRead, size);    theXMRead += (long) size;}
  63.  
  64. Cmd* GetMADCommand( register short PosX, register short    TrackIdX, register PatData*    tempMusicPat)
  65. {
  66.     if( PosX < 0) PosX = 0;
  67.     else if( PosX >= tempMusicPat->header.size) PosX = tempMusicPat->header.size -1;
  68.         
  69.     return( & (tempMusicPat->Cmds[ (tempMusicPat->header.size * TrackIdX) + PosX]));
  70. }
  71.  
  72. void pStrcpy(register unsigned char *s1, register unsigned char *s2)
  73. {
  74.     register short len, i;
  75.     
  76.     len = *s2;
  77.     for ( i = 0; i <= len; i++) s1[ i] = s2[ i];
  78. }
  79.  
  80. Ptr MADPlugNewPtr( long size, MADDriverSettings* init)
  81. {
  82.     if( init->sysMemory) return NewPtrSys( size);
  83.     else return NewPtr( size);
  84. }
  85.  
  86. Ptr MADPlugNewPtrClear( long size, MADDriverSettings* init)
  87. {
  88.     if( init->sysMemory) return NewPtrSysClear( size);
  89.     else return NewPtrClear( size);
  90. }
  91.  
  92. Boolean XM_Init( MADDriverSettings *init)
  93. {
  94.     mh = (XMHEADER*) MADPlugNewPtr( sizeof(XMHEADER), init);
  95.     if( mh == 0L) return false;
  96.     else return true;
  97. }
  98.  
  99.  
  100. void XM_Cleanup(void)
  101. {
  102.     if( mh != 0L) DisposePtr( (Ptr) mh);
  103. }
  104.  
  105. void XM_WriteNote( Cmd *cmd)
  106. {
  107.     UBYTE    cmp;
  108.     long    r;
  109.     
  110.     cmp = 0;
  111.     if( cmd->note)     cmp += 1;
  112.     if( cmd->ins)     cmp += 2;
  113.     if( cmd->vol)     cmp += 4;
  114.     if( cmd->cmd)     cmp += 8;
  115.     if( cmd->arg)     cmp += 16;
  116.     
  117.     if( cmp == 31)        // all bytes used -> no compression
  118.     {
  119.         WRITEXMFILE( &cmd->note, 1);
  120.         WRITEXMFILE( &cmd->ins, 1);
  121.         WRITEXMFILE( &cmd->vol, 1);
  122.         WRITEXMFILE( &cmd->cmd, 1);
  123.         WRITEXMFILE( &cmd->arg, 1);
  124.     }
  125.     else
  126.     {
  127.         UBYTE    ccmp = cmp + 0x80;
  128.     
  129.         WRITEXMFILE( &ccmp, 1);
  130.         
  131.         r = cmp & 1L;    if( r)     WRITEXMFILE( &cmd->note, 1);
  132.         r = cmp & 2L;    if( r)     WRITEXMFILE( &cmd->ins, 1);
  133.         r = cmp & 4L;     if( r)     WRITEXMFILE( &cmd->vol, 1);
  134.         r = cmp & 8L;    if( r)     WRITEXMFILE( &cmd->cmd, 1);
  135.         r = cmp & 16L;    if( r)     WRITEXMFILE( &cmd->arg, 1);
  136.         
  137.         
  138.     }
  139. }
  140.  
  141. void XM_ReadNote(XMNOTE *n)
  142. {
  143.     UBYTE    cmp;
  144.     long    r;
  145.  
  146.     READXMFILE( &cmp, 1);
  147.  
  148.     r = cmp & 0x80;
  149.     if( r)
  150.     {
  151.         r = cmp & 1L;    if( r)     READXMFILE( &n->note, 1)    else n->note     = 0xFF;
  152.         r = cmp & 2L;    if( r)     READXMFILE( &n->ins, 1)        else n->ins     = 0;
  153.         r = cmp & 4L;     if( r)     READXMFILE( &n->vol, 1)        else n->vol     = 0xFF;
  154.         r = cmp & 8L;    if( r)     READXMFILE( &n->eff, 1)        else n->eff     = 0xFF;
  155.         r = cmp & 16L;    if( r)     READXMFILE( &n->dat, 1)        else n->dat     = 0xFF;
  156.     }
  157.     else
  158.     {
  159.         n->note    =    cmp;
  160.         READXMFILE( &n->ins, 1);
  161.         READXMFILE( &n->vol, 1);
  162.         READXMFILE( &n->eff, 1);
  163.         READXMFILE( &n->dat, 1);
  164.     }
  165. }
  166.  
  167. void XM_Convert2MAD(XMNOTE *xmtrack, Cmd        *aCmd)
  168. {
  169.     UBYTE     note,ins,vol,eff,dat;
  170.  
  171.         note    =    xmtrack->note;
  172.         if( note == 0 || note == 0xFF) note = 0xFF;
  173.         else note--;
  174.         
  175.         ins        =    xmtrack->ins;
  176.         vol        =    xmtrack->vol;
  177.         eff        =    xmtrack->eff;
  178.         dat        =    xmtrack->dat;
  179.  
  180.         aCmd->ins        = ins;
  181.         aCmd->note        = note;
  182.         aCmd->vol        = vol;
  183.         if( note == 96)                        // KEY OFF
  184.         {
  185.             aCmd->note        = 0xFE;
  186.         }
  187.         
  188.         if( eff <= 0x0F)
  189.         {
  190.             aCmd->cmd        = eff;    
  191.             aCmd->arg        = dat;    if( aCmd->arg == 0xFF) aCmd->arg = 0;
  192.         }
  193.         else
  194.         {
  195.             aCmd->cmd        = 0;
  196.             aCmd->arg        = 0;
  197.         }
  198.         
  199.         switch(eff)
  200.         {
  201.  
  202.             case 'G'-55:                    // G - set global volume
  203.             break;
  204.  
  205.             case 'H'-55:                    // H - global volume slide
  206.             break;
  207.  
  208.             case 'K'-55:                    // K - keyoff
  209.                 aCmd->ins        = 00;
  210.                 aCmd->note        = 0xFE;
  211.             break;
  212.  
  213.             case 'L'-55:                    // L - set envelope position
  214.             break;
  215.  
  216.             case 'P'-55:                    // P - panning slide
  217.             break;
  218.  
  219.             case 'R'-55:                    // R - multi retrig note
  220.             break;
  221.  
  222.             case 'T'-55:
  223.             break;
  224.  
  225.             case 'X'-55:
  226.                 if((dat>>4)==1)
  227.                 {                            // X1 extra fine porta up
  228.  
  229.  
  230.                 }
  231.                 else
  232.                 {                            // X2 extra fine porta down
  233.  
  234.                 }
  235.                 break;
  236.  
  237.             default:
  238.             break;
  239.         }
  240. }
  241.  
  242. void XM_Convert2XM( Cmd        *aCmd)
  243. {
  244.     if( aCmd->note == 0xFE) aCmd->note        = 96 + 1;    // KEY OFF
  245.     else if( aCmd->note == 0xFF) aCmd->note        = 0;
  246.     else aCmd->note++;
  247.     
  248.     if( aCmd->vol == 0xFF)    aCmd->vol = 0;
  249.     if( aCmd->cmd == 0xFF)    aCmd->cmd = 0;
  250. }
  251.  
  252. OSErr XMReadPattern( MADMusic *theMAD, MADDriverSettings *init)
  253. {
  254.     int            t, u, v, i;
  255.  
  256.     /*****************/
  257.     /** PATTERNS **/
  258.     /*****************/
  259.  
  260.     for( i = 0; i < MAXPATTERN; i++) theMAD->partition[ i] = 0L;
  261.  
  262.     for(t=0;t<mh->numpat;t++)
  263.     {
  264.         short                PatternSize;
  265.         XMPATHEADER         ph;
  266.         XMNOTE                xmpat;
  267.         Cmd                    *aCmd;
  268.         Ptr                    theXMReadCopy;
  269.         
  270.         theXMReadCopy = theXMRead;
  271.         READXMFILE( &ph.size,         4);            INT32( &ph.size);
  272.         READXMFILE( &ph.packing,     1);
  273.         READXMFILE( &ph.numrows,     2);            INT16( &ph.numrows);
  274.         READXMFILE( &ph.packsize,     2);        INT16( &ph.packsize);
  275.         theXMRead = theXMReadCopy + ph.size;
  276.         
  277.         /*
  278.             Gr8.. when packsize is 0, don't try to load a pattern.. it's empty.
  279.             This bug was discovered thanks to Khyron's module..
  280.         */
  281.  
  282.         if( ph.packsize > 0)
  283.         {
  284.             PatternSize = ph.numrows;
  285.             theMAD->partition[ t] = (PatData*) MADPlugNewPtrClear( sizeof( PatHeader) + theMAD->header->numChn * PatternSize * sizeof( Cmd), init);
  286.             if( theMAD->partition[ t] == 0L) return MADNeedMemory;
  287.  
  288.             theMAD->partition[ t]->header.size = PatternSize;
  289.  
  290.             for( u = 0 ; u < PatternSize ; u++)
  291.             {
  292.                 for( v = 0 ; v < theMAD->header->numChn ; v++)
  293.                 {
  294.                     XM_ReadNote( &xmpat);
  295.  
  296.                     aCmd = GetMADCommand(  u,  v, theMAD->partition[ t]);
  297.                     
  298.                     XM_Convert2MAD( &xmpat, aCmd);
  299.                 }
  300.             }
  301.         }
  302.         else
  303.         {
  304.             Cmd            nullCmd;
  305.             
  306.             nullCmd.ins        = 0;
  307.             nullCmd.note    = 0xFF;
  308.             nullCmd.cmd        = 0;
  309.             nullCmd.arg        = 0;
  310.             nullCmd.vol        = 0xFF;
  311.             nullCmd.unused    = 0;
  312.             
  313.             PatternSize = 1;
  314.             theMAD->partition[ t] = (PatData*) MADPlugNewPtrClear( sizeof( PatHeader) + theMAD->header->numChn * PatternSize * sizeof( Cmd), init);
  315.             if( theMAD->partition[ t] == 0L) return MADNeedMemory;
  316.             
  317.             theMAD->partition[ t]->header.size = PatternSize;
  318.             
  319.             for( u = 0 ; u < PatternSize ; u++)
  320.             {
  321.                 for( v = 0 ; v < theMAD->header->numChn ; v++)
  322.                 {
  323.                     aCmd = GetMADCommand(  u,  v, theMAD->partition[ t]);
  324.                     *aCmd = nullCmd;
  325.                 }
  326.             }
  327.         }
  328.     }
  329.     
  330.     return noErr;
  331. }
  332.  
  333. OSErr XMReadInstruments( MADMusic *theMAD, MADDriverSettings *init)
  334. {
  335.     int            t, u, i, x;
  336.     long        inOutCount = 0;
  337.  
  338.     /*****************/
  339.     /** INSTRUMENTS **/
  340.     /*****************/
  341.     
  342.     theMAD->fid = ( InstrData*) MADPlugNewPtrClear( sizeof( InstrData) * (long) MAXINSTRU, init);
  343.     if( !theMAD->fid) return MADNeedMemory;
  344.     
  345.     theMAD->sample = ( sData**) MADPlugNewPtrClear( sizeof( sData*) * (long) MAXINSTRU * (long) MAXSAMPLE, init);
  346.     if( !theMAD->sample) return MADNeedMemory;
  347.     
  348.     for( i = 0; i < MAXINSTRU; i++) theMAD->fid[ i].firstSample = i * MAXSAMPLE;
  349.     
  350.     for(i  = 0 ; i < MAXINSTRU; i++)
  351.     {
  352.         for( x = 0; x < MAXSAMPLE; x++) theMAD->sample[ i*MAXSAMPLE + x] = 0L;
  353.  
  354.         theMAD->fid[i].numSamples    = 0;
  355.     }
  356.     
  357.     for( t = 0; t < mh->numins; t++)
  358.     {
  359.         XMINSTHEADER     ih;
  360.         InstrData        *curIns = &theMAD->fid[ t];
  361.         Ptr                theXMReadCopy;
  362.  
  363.         theXMReadCopy = theXMRead;
  364.         READXMFILE( &ih.size,    4);        INT32( &ih.size);
  365.         READXMFILE( &ih.name,    22);
  366.         READXMFILE( &ih.type,    1);
  367.         READXMFILE( &ih.numsmp,    2);    INT16( &ih.numsmp);
  368.     //    READXMFILE( &ih.ssize,    4);        INT32( &ih.ssize);
  369.         
  370.  
  371.         for( x = 0; x < 22; x++) curIns->name[ x] = ih.name[x];
  372.         curIns->numSamples    = ih.numsmp;
  373.  
  374.         if(ih.numsmp > 0)
  375.         {
  376.             XMPATCHHEADER    pth;
  377.  
  378.             READXMFILE( &ih.ssize,    4);            INT32( &ih.ssize);
  379.             READXMFILE( &pth.what,        96);
  380.             READXMFILE( &pth.volenv,    48);
  381.             READXMFILE( &pth.panenv,    48);
  382.             READXMFILE( &pth.volpts,    1);
  383.             READXMFILE( &pth.panpts,    1);
  384.             READXMFILE( &pth.volsus,    1);
  385.             READXMFILE( &pth.volbeg,    1);
  386.             READXMFILE( &pth.volend,    1);
  387.             READXMFILE( &pth.pansus,    1);
  388.             READXMFILE( &pth.panbeg,    1);
  389.             READXMFILE( &pth.panend,    1);
  390.             READXMFILE( &pth.volflg,    1);
  391.             READXMFILE( &pth.panflg,    1);
  392.             READXMFILE( &pth.vibflg,    1);
  393.             READXMFILE( &pth.vibsweep,    1);
  394.             READXMFILE( &pth.vibdepth,    1);
  395.             READXMFILE( &pth.vibrate,    1);
  396.             READXMFILE( &pth.volfade,    2);        INT16( &pth.volfade);
  397.             READXMFILE( &pth.reserved,    22);
  398.             
  399.             
  400.             
  401.             BlockMove( pth.what,     curIns->what,         96);
  402.             
  403.             // Volume Env
  404.             
  405.             BlockMove( pth.volenv,     curIns->volEnv,     48);
  406.             for( x = 0; x < 12; x++)
  407.             {
  408.                 INT16( &curIns->volEnv[ x].pos);    // 
  409.                 INT16( &curIns->volEnv[ x].val);    // 00...64
  410.             }
  411.             
  412.             curIns->volSize    = pth.volpts;
  413.             curIns->volType    = pth.volflg;
  414.             curIns->volSus    = pth.volsus;
  415.             curIns->volBeg    = pth.volbeg;
  416.             curIns->volEnd    = pth.volend;
  417.             
  418.             if( curIns->volBeg >= curIns->volSize) curIns->volBeg = curIns->volSize-1;
  419.             if( curIns->volEnd >= curIns->volSize) curIns->volEnd = curIns->volSize-1;
  420.             
  421.             curIns->volFade    = pth.volfade;
  422.             
  423.             // Panning Env
  424.             
  425.             BlockMove( pth.panenv,     curIns->pannEnv,     48);
  426.             
  427.             for( x = 0; x < 12; x++)
  428.             {
  429.                 INT16( &curIns->pannEnv[ x].pos);    // 
  430.                 INT16( &curIns->pannEnv[ x].val);    // 00...64
  431.             }
  432.             
  433.             curIns->pannSize    = pth.panpts;
  434.             curIns->pannType    = pth.panflg;
  435.             curIns->pannSus    = pth.pansus;
  436.             curIns->pannBeg    = pth.panbeg;
  437.             curIns->pannEnd    = pth.panend;
  438.             
  439.             if( curIns->pannBeg >= curIns->pannSize) curIns->pannBeg = curIns->pannSize-1;
  440.             if( curIns->pannEnd >= curIns->pannSize) curIns->pannEnd = curIns->pannSize-1;
  441.             
  442.         //    curIns->panFade    = pth.panfade;
  443.         }
  444.         theXMRead = theXMReadCopy + ih.size;
  445.         
  446.         /** Read samples */
  447.         
  448.         for( u = 0 ; u < ih.numsmp ; u++)
  449.         {
  450.             XMWAVHEADER        wh;
  451.             
  452.             theXMReadCopy = theXMRead;
  453.             READXMFILE( &wh.length,            4);            INT32( &wh.length);
  454.             READXMFILE( &wh.loopstart,        4);        INT32( &wh.loopstart);
  455.             READXMFILE( &wh.looplength,        4);        INT32( &wh.looplength);
  456.             READXMFILE( &wh.volume,            1);
  457.             READXMFILE( &wh.finetune,        1);
  458.             READXMFILE( &wh.type,            1);
  459.             READXMFILE( &wh.panning,        1);
  460.             READXMFILE( &wh.relnote,        1);
  461.             READXMFILE( &wh.reserved,        1);
  462.             READXMFILE( &wh.samplename,        22);
  463.             theXMRead = theXMReadCopy + ih.ssize;
  464.             
  465.             {
  466.                 sData    *curData;
  467.                 long     finetune[ 16] = 
  468.                 {
  469.                     7895,    7941,    7985,    8046,    8107,    8169,    8232,    8280,
  470.                     8363,    8413,    8463,    8529,    8581,    8651,    8723,    8757
  471.                 };
  472.                 
  473.                 curData = theMAD->sample[ t*MAXSAMPLE + u] = (sData*) MADPlugNewPtrClear( sizeof( sData), init);
  474.                 
  475.                 curData->size        = wh.length;
  476.                 curData->loopBeg     = wh.loopstart;
  477.                 curData->loopSize     = wh.looplength;
  478.                 
  479.                 curData->vol        = wh.volume;
  480.                 curData->c2spd        = finetune[ (wh.finetune + 128)/16];
  481.                 curData->loopType    = 0;
  482.                 curData->amp        = 8;
  483.                 
  484.                 if( wh.type & 0x10)        // 16 Bits
  485.                 {
  486.                     curData->amp = 16;
  487.                 }
  488.                 if( wh.type & 0x2)        // Ping Pong
  489.                 {
  490.                     curData->loopType = ePingPongLoop;
  491.                 }
  492.                 
  493.                 if( !(wh.type & 0x3))
  494.                 {
  495.                     curData->loopBeg = 0;
  496.                     curData->loopSize = 0;
  497.                 }
  498.                 
  499.             //    curData->panning    = wh.panning;
  500.                 curData->relNote    = wh.relnote;
  501.                 for( x = 0; x < 22; x++) curData->name[ x] = wh.samplename[ x];
  502.             }
  503.         }
  504.  
  505.         /** Read samples data **/
  506.         
  507.         for( u = 0 ; u < curIns->numSamples ; u++)
  508.         {
  509.             sData    *curData = theMAD->sample[ t*MAXSAMPLE + u];
  510.             
  511.             curData->data         = MADPlugNewPtr( curData->size, init);
  512.             if( curData->data == 0L) return MADNeedMemory;
  513.             
  514.             if( curData->data != 0L)
  515.             {
  516.                 READXMFILE( curData->data, curData->size);
  517.                 
  518.                 if( curData->amp == 16)
  519.                 {
  520.                     short    *tt;
  521.                     long    tL;
  522.                     
  523.                     tt = (short*) curData->data;
  524.  
  525.                     for( tL = 0; tL < curData->size/2; tL++)
  526.                     {
  527.                         INT16( (Ptr) (tt + tL));
  528.                     }
  529.                     
  530.                     {
  531.                     /* Delta to Real */
  532.                     long    oldV, newV;
  533.                     long    xL;
  534.                     
  535.                     oldV = 0;
  536.                     
  537.                     for( xL = 0; xL < curData->size/2; xL++)
  538.                     {
  539.                         newV = tt[ xL] + oldV;
  540.                         tt[ xL] = newV;
  541.                         oldV = newV;
  542.                     }
  543.                     }
  544.                 }
  545.                 else
  546.                 {
  547.                     /* Delta to Real */
  548.                     long    oldV, newV;
  549.                     long    xL;
  550.                     
  551.                     oldV = 0;
  552.  
  553.                     for( xL = 0; xL < curData->size; xL++)
  554.                     {
  555.                         newV = curData->data[ xL] + oldV;
  556.                         curData->data[ xL] = newV;
  557.                         oldV = newV;
  558.                     }
  559.                 }
  560.             }
  561.             else return MADNeedMemory;
  562.         }
  563.     }
  564.     return noErr;
  565. }
  566.  
  567. OSErr XM_Load( Ptr    theXM, long XMSize, MADMusic *theMAD, MADDriverSettings *init)
  568. {
  569.     int            i;
  570.     long        inOutCount, x;
  571.  
  572.     theXMRead = theXM;
  573.  
  574.     /********************/
  575.     /** READ XM HEADER **/
  576.     /********************/
  577.     
  578.     READXMFILE( mh, sizeof(XMHEADER));
  579.     /* BigEndian <-> LittleEndian */
  580.  
  581.     INT16( &mh->version);
  582.     INT32( &mh->headersize);
  583.     INT16( &mh->songlength);
  584.     INT16( &mh->restart);
  585.     INT16( &mh->numchn);
  586.     INT16( &mh->numpat);
  587.     INT16( &mh->numins);        if( mh->numins > MAXINSTRU) { mh->numins = MAXINSTRU;    }
  588.     INT16( &mh->flags);
  589.     INT16( &mh->bpm);
  590.     INT16( &mh->tempo);
  591.  
  592.     /********************/
  593.     /** MAD ALLOCATION **/
  594.     /********************/
  595.     
  596.     inOutCount = sizeof( MADSpec);
  597.     theMAD->header = (MADSpec*) MADPlugNewPtrClear( inOutCount, init);    
  598.     if( theMAD->header == 0L) return MADNeedMemory;
  599.     
  600.     theMAD->header->MAD = 'MADI';
  601.     
  602.     for(i=0; i<20; i++)
  603.     {
  604.         theMAD->header->name[ i] = mh->songname[ i];
  605.         if( theMAD->header->name[ i] == 0) i = 21;
  606.     }
  607.     
  608.     theMAD->header->speed            =     mh->tempo;
  609.     theMAD->header->tempo            =    mh->bpm;
  610.     theMAD->header->numChn            =    mh->numchn;
  611.     theMAD->header->numPat            =    mh->numpat;
  612.     theMAD->header->numPointers        =    mh->songlength;
  613.     
  614.     if( theMAD->header->numPointers > 128) theMAD->header->numPointers = 128;
  615.     
  616.     MADstrcpy( theMAD->header->infos, (Ptr) "Converted by PlayerPRO XM Plug (⌐Antoine ROSSET <rossetantoine@bluewin.ch>)");
  617.     
  618.     for( i = 0; i < mh->songlength; i++)
  619.     {
  620.         theMAD->header->oPointers[ i] = mh->orders[ i];
  621.         if( theMAD->header->oPointers[ i] >= theMAD->header->numPat)
  622.             theMAD->header->oPointers[ i] = theMAD->header->numPat-1;
  623.     }
  624.     
  625.     x = 1;
  626.     for( i = 0; i < MAXTRACK; i++)
  627.     {
  628.         if( x > 0) theMAD->header->chanPan[ i] = MAX_PANNING/4;
  629.         else theMAD->header->chanPan[ i] = MAX_PANNING - MAX_PANNING/4;
  630.         x--;
  631.         
  632.         if( x == -2) x = 2;
  633.         
  634.         theMAD->header->chanVol[ i] = MAX_VOLUME;
  635.     }
  636.  
  637.     theMAD->header->generalVol        = 64;
  638.     theMAD->header->generalSpeed    = 80;
  639.     theMAD->header->generalPitch    = 80;
  640.  
  641.     switch( mh->version)
  642.     {
  643.         case 0x104:
  644.             XMReadPattern( theMAD, init);
  645.             XMReadInstruments( theMAD, init);
  646.         break;
  647.         
  648.     /*    case 0x103:
  649.             XMReadInstruments( theMAD);
  650.             XMReadPattern( theMAD);
  651.         break;*/
  652.         
  653.         default:
  654.             return MADFileNotSupportedByThisPlug;
  655.         break;
  656.     }
  657.     return noErr;
  658. }
  659.  
  660. long ConvertSampleC4SPDXM( Ptr src, long srcSize, short amp, long srcC4SPD, Ptr dst, long dstC4SPD)
  661. {
  662.     short    *src16 = (short*) src, *dst16 = (short*) dst;
  663.     Ptr        src8 = src, dst8 = dst;
  664.     long    x;
  665.     
  666.     if( amp == 8)
  667.     {
  668.         for( x = 0; x < srcSize; x++)
  669.         {
  670.             dst8[ (x * dstC4SPD) / srcC4SPD] = src8[ x];
  671.         }
  672.     }
  673.     else
  674.     {
  675.         for( x = 0; x < srcSize/2; x++)
  676.         {
  677.             dst16[ (x * dstC4SPD) / srcC4SPD] = src16[ x];
  678.         }
  679.     }
  680.     
  681.     return (srcSize * dstC4SPD) / srcC4SPD;
  682. }
  683.  
  684. long XMGetPeriod( short note, long c2spd)
  685. {
  686.     unsigned long     period, n,o, mytab[ 12] = {        1712L*16L,1616L*16L,1524L*16L,1440L*16L,1356L*16L,1280L*16L,
  687.                                                     1208L*16L,1140L*16L,1076L*16L,1016L*16L,960L*16L,907L*16L };
  688.     
  689.     n = note%12;        o = note/12;
  690.     
  691.     period = (( 8363UL * ( mytab[ n]) ) >> o ) / c2spd;
  692.     
  693.     if( period == 0L) period = 7242;
  694.     
  695.     return period;
  696. }
  697.  
  698.  
  699. Ptr    ConvertMad2XM( MADMusic *theMAD, MADDriverSettings *init, long *sndSize)
  700. {
  701.     int            u, i;
  702.     long        PatternSize, InstruSize, NumberInstru;
  703.     Ptr            finalXMPtr;
  704.     
  705.     /********************************/
  706.     /*             MAD INFORMATIONS    */
  707.     /********************************/
  708.     InstruSize         = 0;
  709.     PatternSize     = 0;
  710.     
  711.     NumberInstru = MAXINSTRU;
  712.     
  713.     for( i = 0; i < MAXINSTRU ; i++)
  714.     {
  715.         InstruSize += sizeof( XMINSTHEADER) + sizeof( XMPATCHHEADER);
  716.         
  717.         for( u = 0; u < theMAD->fid[ i].numSamples; u++)
  718.         {
  719.             InstruSize            += sizeof( XMWAVHEADER) + theMAD->sample[ i*MAXSAMPLE + u]->size;
  720.         }
  721.         
  722.         if( theMAD->fid[ i].numSamples > 0 || theMAD->fid[ i].name[ 0] != 0)
  723.         {
  724.             NumberInstru = i + 1;
  725.         }
  726.     }
  727.     
  728.     for( i = 0; i < theMAD->header->numPat;i++)
  729.     {
  730.         PatternSize += sizeof( XMNOTE) * theMAD->header->numChn * theMAD->partition[ i]->header.size;
  731.         PatternSize += sizeof( XMPATHEADER);
  732.     }
  733.     /********************************/
  734.     
  735.     *sndSize =                         sizeof(XMHEADER) +
  736.                                                 InstruSize +
  737.                                                 PatternSize;
  738.     
  739.     theXMRead = finalXMPtr = MADPlugNewPtr( *sndSize, init);
  740.     theXMMax = theXMRead + *sndSize;
  741.     if( theXMRead == 0L) return 0L;
  742.     
  743.     /********************/
  744.     /** WRITE XM HEADER */
  745.     /********************/
  746.     
  747.     
  748.     
  749.     MADstrcpy( mh->id, (Ptr) "Extended Module: ");
  750.     MADstrcpy( mh->trackername, (Ptr) "FastTracker v2.00   ");
  751.     mh->version            = 0x104;                                                    INT16( &mh->version);
  752.     mh->headersize        = HEADERSIZE;                                                INT32( &mh->headersize);
  753.     mh->songlength         = theMAD->header->numPointers;    INT16( &mh->songlength);
  754.     mh->restart         = 0;                                                            INT16( &mh->restart);
  755.     mh->numchn             = theMAD->header->numChn;                    INT16( &mh->numchn);
  756.     mh->numpat             = theMAD->header->numPat;                    INT16( &mh->numpat);
  757.     mh->numins             = NumberInstru;                                        INT16( &mh->numins);
  758.     mh->flags             = 0;                                                            INT16( &mh->flags);
  759.     mh->bpm             = theMAD->header->tempo;                        INT16( &mh->bpm);
  760.     mh->tempo             = theMAD->header->speed;                    INT16( &mh->tempo);
  761.     
  762.     for(i=0; i<21; i++) mh->songname[ i] = ' ';
  763.     for(i=0; i<21; i++)
  764.     {
  765.         mh->songname[ i] = theMAD->header->name[ i];
  766.         if( theMAD->header->name[ i] == 0) i = 21;
  767.     }
  768.     mh->songname[ 20] = 0x1a;
  769.     
  770.     for( i = 0; i < 256; i++) mh->orders[ i] = 0;
  771.     for( i = 0; i < theMAD->header->numPointers; i++) mh->orders[ i] = theMAD->header->oPointers[ i];
  772.     
  773.     WRITEXMFILE( mh, sizeof(XMHEADER));
  774.     
  775.     /*****************/
  776.     /** PATTERNS    **/
  777.     /*****************/
  778.     
  779.     {
  780.     int            t, u, v;
  781.     
  782.     for(t=0;t<theMAD->header->numPat;t++)
  783.     {
  784.         short                PatternSize;
  785.         XMPATHEADER         ph;
  786.         Ptr                    packingCopy, cc;
  787.         
  788.         ph.size = PHSIZE;                        INT32( &ph.size);            WRITEXMFILE( &ph.size,    4);
  789.         ph.packing = 0;                            WRITEXMFILE( &ph.packing,    1);
  790.         ph.numrows = theMAD->partition[ t]->header.size;    INT16( &ph.numrows);        WRITEXMFILE( &ph.numrows,    2);
  791.         
  792.         packingCopy = theXMRead;
  793.         ph.packsize = 1;                                    INT16( &ph.packsize);        WRITEXMFILE( &ph.packsize,    2);
  794.         
  795.         cc = theXMRead;
  796.         for( u = 0 ; u < theMAD->partition[ t]->header.size ; u++)
  797.         {
  798.             for( v = 0 ; v < theMAD->header->numChn ; v++)
  799.             {
  800.                 Cmd        *aCmd;
  801.                 Cmd        bCmd;
  802.                 
  803.                 aCmd = GetMADCommand(  u,  v, theMAD->partition[ t]);
  804.                 
  805.                 bCmd = *aCmd;
  806.                 
  807.                 XM_Convert2XM( &bCmd);
  808.                 
  809.                 XM_WriteNote( &bCmd);
  810.             }
  811.         }
  812.         
  813.         PatternSize = theXMRead - cc;
  814.         
  815.         cc = theXMRead;
  816.         theXMRead = packingCopy;
  817.         ph.packsize = PatternSize;                        INT16( &ph.packsize);        WRITEXMFILE( &ph.packsize,    2);
  818.         theXMRead = cc;
  819.     }
  820.     }
  821.     
  822.     /*****************/
  823.     /** INSTRUMENTS **/
  824.     /*****************/
  825.  
  826.     {
  827.     int            t, u, x;
  828.     long        inOutCount = 0;
  829.     
  830.     for( t = 0; t < NumberInstru; t++)
  831.     {
  832.         XMINSTHEADER     ih;
  833.         long            ihsizecopy, ihssizecopy;
  834.         
  835.         InstrData        *curIns = &theMAD->fid[ t];
  836.         Ptr                theXMReadCopy;
  837.  
  838.         theXMReadCopy = theXMRead;
  839.         
  840.         //************************//
  841.         // Instrument header size //
  842.         
  843.         if( curIns->numSamples > 0) ih.size = IHSIZE;
  844.         else ih.size = IHSIZESMALL;
  845.         
  846.         ihsizecopy = ih.size;
  847.         INT32( &ih.size);
  848.         WRITEXMFILE( &ih.size,    4);
  849.         
  850.         //************************//
  851.         
  852.         for( x = 0; x < 22; x++)             ih.name[x] = curIns->name[ x];            WRITEXMFILE( &ih.name,    22);
  853.         ih.type = 0;                                                                WRITEXMFILE( &ih.type,    1);
  854.         ih.numsmp = curIns->numSamples;            INT16( &ih.numsmp);                    WRITEXMFILE( &ih.numsmp,    2);
  855.         
  856.         ih.ssize = IHSSIZE;
  857.         ihssizecopy = ih.ssize;
  858.         INT32( &ih.ssize);
  859.         
  860.         if( curIns->numSamples > 0)
  861.         {
  862.             XMPATCHHEADER    pth;
  863.             
  864.             for( x = 0; x < sizeof( pth); x++) ((char*) &pth)[ x] = 0;
  865.             
  866.             BlockMove( curIns->what, pth.what, 96);
  867.             BlockMove( curIns->volEnv, pth.volenv, 48);
  868.             for( x = 0; x < 24; x++) INT16( &pth.volenv[ x]);
  869.             
  870.             pth.volpts = curIns->volSize;
  871.             pth.volflg = curIns->volType;
  872.             pth.volsus = curIns->volSus;
  873.             pth.volbeg = curIns->volBeg;
  874.             pth.volend = curIns->volEnd;
  875.             pth.volfade = curIns->volFade;
  876.             
  877.             BlockMove( curIns->pannEnv, pth.panenv, 48);
  878.             
  879.             WRITEXMFILE( &ih.ssize,        4);
  880.             WRITEXMFILE( &pth.what,        96);
  881.             WRITEXMFILE( &pth.volenv,    48);
  882.             WRITEXMFILE( &pth.panenv,    48);
  883.             WRITEXMFILE( &pth.volpts,    1);
  884.             WRITEXMFILE( &pth.panpts,    1);
  885.             WRITEXMFILE( &pth.volsus,    1);
  886.             WRITEXMFILE( &pth.volbeg,    1);
  887.             WRITEXMFILE( &pth.volend,    1);
  888.             WRITEXMFILE( &pth.pansus,    1);
  889.             WRITEXMFILE( &pth.panbeg,    1);
  890.             WRITEXMFILE( &pth.panend,    1);
  891.             WRITEXMFILE( &pth.volflg,    1);
  892.             WRITEXMFILE( &pth.panflg,    1);
  893.             WRITEXMFILE( &pth.vibflg,    1);
  894.             WRITEXMFILE( &pth.vibsweep,    1);
  895.             WRITEXMFILE( &pth.vibdepth,    1);
  896.             WRITEXMFILE( &pth.vibrate,    1);
  897.             INT16( &pth.volfade);        WRITEXMFILE( &pth.volfade,    2);
  898.             WRITEXMFILE( &pth.reserved,    22);
  899.         }
  900.         theXMRead = theXMReadCopy + ihsizecopy;
  901.         
  902.         /** WRITE samples */
  903.         
  904.         for( u = 0 ; u < curIns->numSamples ; u++)
  905.         {
  906.             XMWAVHEADER        wh;
  907.             sData            *curData;
  908.             short            modifc2spd = 0;
  909.             long            copyc2spd;
  910.             
  911.             long     finetune[ 16] = 
  912.             {
  913.                 7895,    7941,    7985,    8046,    8107,    8169,    8232,    8280,
  914.                 8363,    8413,    8463,    8529,    8581,    8651,    8723,    8757
  915.             };
  916.             
  917.             curData = theMAD->sample[ t*MAXSAMPLE + u];
  918.             
  919.             wh.volume        = curData->vol;
  920.             
  921.             copyc2spd = curData->c2spd;
  922.             
  923.             if( curData->c2spd > 8757 || curData->c2spd < 7895)
  924.             {
  925.                 #define BASECALC    45
  926.                 
  927.                 wh.finetune = 0;            // <- 8363 Hz
  928.                 
  929.                 while( XMGetPeriod( BASECALC, curData->c2spd) < XMGetPeriod( BASECALC + modifc2spd, 8363))
  930.                 {
  931.                     modifc2spd++;
  932.                 }
  933.                 
  934.                 curData->c2spd = 8363;
  935.             }
  936.             
  937.             
  938.             {
  939.                 wh.length         = curData->size;
  940.                 wh.loopstart    = curData->loopBeg;
  941.                 wh.looplength    = curData->loopSize;
  942.                 
  943.                 if( curData->stereo)
  944.                 {
  945.                     wh.length /= 2;
  946.                     wh.loopstart /= 2;
  947.                     wh.looplength /= 2;
  948.                 }
  949.                 
  950.                 wh.finetune = -128;
  951.                 if( curData->c2spd > 8757) wh.finetune = 127;
  952.                 else
  953.                 {
  954.                     while( finetune[ (wh.finetune + 128)/16] < curData->c2spd)
  955.                     {
  956.                         wh.finetune += 16;
  957.                     }
  958.                 }
  959.             }
  960.             
  961.             curData->c2spd = copyc2spd;
  962.             
  963.             wh.type = 0;
  964.             if( curData->amp == 16) wh.type += 0x10;
  965.             if( curData->loopSize > 0) wh.type += 0x3;
  966.             if( curData->loopType == ePingPongLoop) wh.type += 0x2;
  967.             
  968.             wh.panning = 128;    //curData->panning;
  969.             wh.relnote = curData->relNote + modifc2spd;
  970.             for( x = 0; x < 22; x++) wh.samplename[ x] = curData->name[ x];
  971.             
  972.             theXMReadCopy = theXMRead;
  973.             INT32( &wh.length);        WRITEXMFILE( &wh.length,        4);
  974.             INT32( &wh.loopstart);    WRITEXMFILE( &wh.loopstart,        4);
  975.             INT32( &wh.looplength);    WRITEXMFILE( &wh.looplength,    4);
  976.             WRITEXMFILE( &wh.volume,        1);
  977.             WRITEXMFILE( &wh.finetune,        1);
  978.             WRITEXMFILE( &wh.type,            1);
  979.             wh.panning        = 128;                            WRITEXMFILE( &wh.panning,        1);
  980.             WRITEXMFILE( &wh.relnote,        1);
  981.             WRITEXMFILE( &wh.reserved,        1);
  982.             WRITEXMFILE( &wh.samplename,        22);
  983.             theXMRead = theXMReadCopy + ihssizecopy;
  984.         }
  985.         
  986.         /** WRITE samples data **/
  987.         
  988.         for( u = 0 ; u < curIns->numSamples ; u++)
  989.         {
  990.             sData    *curData = theMAD->sample[ t*MAXSAMPLE + u];
  991.             Ptr        theXMReadCopy = theXMRead;
  992.             long    curSize;
  993.             
  994.             WRITEXMFILE( curData->data, curData->size);
  995.             curSize = curData->size;
  996.             
  997.             if( curData->stereo)
  998.             {
  999.                 if( curData->amp == 8)
  1000.                 {
  1001.                     for( x = 0 ; x < curSize; x+=2)
  1002.                     {
  1003.                         theXMReadCopy[ x / 2] = ((long) theXMReadCopy[ x] + (long) theXMReadCopy[ x + 1]) / 2L;
  1004.                     }
  1005.                 }
  1006.                 else
  1007.                 {
  1008.                     short *short16out = (short*) theXMReadCopy, *short16in = (short*) theXMReadCopy;
  1009.                     
  1010.                     for( x = 0 ; x < curSize/2; x+=2)
  1011.                     {
  1012.                         short16out[ x / 2] = ((long) short16in[ x] + (long) short16in[ x + 1]) / 2L;
  1013.                     }
  1014.                 }
  1015.                 
  1016.                 curSize /= 2;
  1017.                 theXMRead -= curSize;
  1018.             }
  1019.             
  1020.             if( curData->amp == 16)
  1021.             {
  1022.                 short    *tt = (short*) theXMReadCopy;
  1023.                 long    tL;
  1024.                 
  1025.                 /* Real to Delta */
  1026.                 long    oldV, newV;
  1027.                 long    xL;
  1028.                 
  1029.                 oldV = 0;
  1030.                 
  1031.                 for( xL = 0; xL < curSize/2; xL++)
  1032.                 {
  1033.                     newV = tt[ xL];
  1034.                     tt[ xL] -= oldV;
  1035.                     oldV = newV;
  1036.                 }
  1037.                 
  1038.                 for( tL = 0; tL < curSize/2; tL++)
  1039.                 {
  1040.                     INT16( (Ptr) (tt + tL));
  1041.                 }
  1042.             }
  1043.             else
  1044.             {
  1045.                 /* Real to Delta */
  1046.                 long    oldV, newV;
  1047.                 long    xL;
  1048.             //    Byte    *tempByte = (Byte*) theXMReadCopy;
  1049.                 
  1050.                 oldV = 0;
  1051.                 
  1052.                 for( xL = 0; xL < curSize; xL++)
  1053.                 {
  1054.                     newV = theXMReadCopy[ xL];
  1055.                     theXMReadCopy[ xL] -= oldV;
  1056.                     oldV = newV;
  1057.                 }
  1058.             }
  1059.         }
  1060.     }
  1061.     }
  1062.     
  1063.     *sndSize = theXMRead - finalXMPtr;
  1064.     
  1065.     return finalXMPtr;
  1066. }
  1067.  
  1068. Boolean compMem( Ptr a, Ptr b, long s)
  1069. {
  1070. long     i;
  1071.  
  1072.     for( i = 0; i < s; i++)
  1073.     {
  1074.         if( a[ i] != b[ i]) return false;
  1075.     }
  1076.     
  1077.     return true;
  1078. }
  1079.  
  1080. OSErr TestXMFile( Ptr AlienFile)
  1081. {
  1082.     if( compMem( AlienFile, "Extended Module: ", 17))
  1083.     {
  1084.         theXMRead = AlienFile;
  1085.     
  1086.         /********************/
  1087.         /** READ XM HEADER **/
  1088.         /********************/
  1089.         
  1090.         READXMFILE( mh, sizeof(XMHEADER));
  1091.         /* BigEndian <-> LittleEndian */
  1092.     
  1093.         INT16( &mh->version);
  1094.         INT16( &mh->songlength);
  1095.         INT16( &mh->numchn);
  1096.         INT16( &mh->numpat);
  1097.         INT16( &mh->numins);
  1098.     
  1099.         switch( mh->version)
  1100.         {
  1101.             case 0x104:
  1102.             break;
  1103.             
  1104.             default:
  1105.                 return MADFileNotSupportedByThisPlug;
  1106.             break;
  1107.         }
  1108.         return noErr;
  1109.     }
  1110.     return MADFileNotSupportedByThisPlug;
  1111. }
  1112.  
  1113. OSErr ExtractXMInfo( PPInfoRec *info, Ptr AlienFile)
  1114. {
  1115.     short    i;
  1116.     
  1117.  
  1118.     theXMRead = AlienFile;
  1119.  
  1120.     /********************/
  1121.     /** READ XM HEADER **/
  1122.     /********************/
  1123.     
  1124.     READXMFILE( mh, sizeof(XMHEADER));
  1125.     /* BigEndian <-> LittleEndian */
  1126.  
  1127.     INT16( &mh->version);
  1128.     INT16( &mh->songlength);
  1129.     INT16( &mh->numchn);
  1130.     INT16( &mh->numpat);
  1131.     INT16( &mh->numins);
  1132.     INT16( &mh->flags);
  1133.  
  1134.     switch( mh->version)
  1135.     {
  1136.         case 0x104:
  1137.         break;
  1138.         
  1139.         default:
  1140.             return MADFileNotSupportedByThisPlug;
  1141.         break;
  1142.     }
  1143.     
  1144.     /*** Signature ***/
  1145.     
  1146.     info->signature = 'XM  ';
  1147.     
  1148.     /*** Internal name ***/
  1149.     
  1150.     for(i=0; i<21; i++)
  1151.     {
  1152.         info->internalFileName[ i] = mh->songname[ i];
  1153.         if( info->internalFileName[ i] == 0 || info->internalFileName[ i] == 0x1a)
  1154.         {
  1155.             info->internalFileName[ i] = 0;
  1156.             i = 21;
  1157.         }
  1158.     }
  1159.  
  1160.     /*** Total Patterns ***/
  1161.     
  1162.     info->totalPatterns = mh->numpat;
  1163.     
  1164.     /*** Partition Length ***/
  1165.     
  1166.     info->partitionLength = mh->songlength;
  1167.     
  1168.     /*** Total Instruments ***/
  1169.     
  1170.     info->totalInstruments = mh->numins;
  1171.     
  1172.     /*** Total Tracks ***/
  1173.     
  1174.     info->totalTracks = mh->numchn;
  1175.     
  1176.     if( mh->flags&1) MADstrcpy( info->formatDescription, "XM Linear Plug");
  1177.     else MADstrcpy( info->formatDescription, "XM Log Plug");
  1178.  
  1179.     return noErr;
  1180. }
  1181.  
  1182. #ifndef _MAC_H
  1183.  
  1184. extern "C" EXP OSErr FillPlug( PlugInfo *p);
  1185. extern "C" EXP OSErr mainPLUG( OSType order, Ptr AlienFileName, MADMusic *MadFile, PPInfoRec *info, MADDriverSettings *init);
  1186.  
  1187. EXP OSErr FillPlug( PlugInfo *p)        // Function USED IN DLL - For PC & BeOS
  1188. {
  1189.     MADstrcpy( p->type,         ".XM");
  1190.     MADstrcpy( p->MenuName,     "XM Files");
  1191.     p->mode    =    'EXIM';
  1192.     
  1193.     return noErr;
  1194. }
  1195. #endif
  1196.  
  1197. #ifdef _MAC_H
  1198. EXP OSErr main( OSType order, Ptr AlienFileName, MADMusic *MadFile, PPInfoRec *info, MADDriverSettings *init)
  1199. #else
  1200. OSErr mainPLUG( OSType order, Ptr AlienFileName, MADMusic *MadFile, PPInfoRec *info, MADDriverSettings *init)
  1201. #endif
  1202. {
  1203.     OSErr            myErr;
  1204.     Ptr                AlienFile;
  1205.     long            sndSize;
  1206.     UNFILE        iFileRefI;
  1207.     
  1208.     #ifdef _MAC_H
  1209.     #ifndef powerc
  1210.         long    oldA4 = SetCurrentA4();             //this call is necessary for strings in 68k code resources
  1211.     #endif
  1212.     #endif
  1213.     
  1214.     myErr = noErr;
  1215.     
  1216.     if( !XM_Init( init)) return MADNeedMemory;
  1217.     
  1218.     switch( order)
  1219.     {
  1220.         case 'EXPL':
  1221.             AlienFile = ConvertMad2XM( MadFile, init, &sndSize);
  1222.             
  1223.             if( AlienFile != 0L)
  1224.             {
  1225.                 iFileCreate( AlienFileName, 'XM  ');
  1226.                 iFileRefI = iFileOpen( AlienFileName);
  1227.                 if( iFileRefI)
  1228.                 {
  1229.                     iWrite( sndSize, AlienFile, iFileRefI);
  1230.                     iClose( iFileRefI);
  1231.                 }
  1232.                 DisposePtr( AlienFile);    AlienFile = 0L;
  1233.             }
  1234.             else myErr = MADNeedMemory;
  1235.         break;
  1236.         
  1237.         case 'IMPL':
  1238.             iFileRefI = iFileOpen( AlienFileName);
  1239.             if( iFileRefI)
  1240.             {
  1241.                 sndSize = iGetEOF( iFileRefI);
  1242.                 
  1243.                 // ** MEMORY Test Start
  1244.                 AlienFile = MADPlugNewPtr( sndSize * 2L, init);
  1245.                 if( AlienFile == 0L) myErr = MADNeedMemory;
  1246.                 // ** MEMORY Test End
  1247.                 
  1248.                 else
  1249.                 {
  1250.                     DisposePtr( AlienFile);
  1251.                     
  1252.                     AlienFile = MADPlugNewPtr( sndSize, init);
  1253.                     if( AlienFile == 0L) myErr = MADNeedMemory;
  1254.                     else
  1255.                     {
  1256.                         iRead( sndSize, AlienFile, iFileRefI);
  1257.                         
  1258.                         myErr = TestXMFile( AlienFile);
  1259.                         if( myErr == noErr)
  1260.                         {
  1261.                             myErr = XM_Load( AlienFile,  sndSize, MadFile, init);
  1262.                         }
  1263.                     }
  1264.                     DisposePtr( AlienFile);    AlienFile = 0L;
  1265.                 }
  1266.                 iClose( iFileRefI);
  1267.             }
  1268.         break;
  1269.         
  1270.         case 'TEST':
  1271.             iFileRefI = iFileOpen( AlienFileName);
  1272.             if( iFileRefI)
  1273.             {
  1274.                 sndSize = 1024L;
  1275.                 
  1276.                 AlienFile = MADPlugNewPtr( sndSize, init);
  1277.                 if( AlienFile == 0L) myErr = MADNeedMemory;
  1278.                 else
  1279.                 {
  1280.                     myErr = iRead( sndSize, AlienFile, iFileRefI);
  1281.                     
  1282.                     myErr = TestXMFile( AlienFile);
  1283.                     
  1284.                     DisposePtr( AlienFile);    AlienFile = 0L;
  1285.                 }
  1286.                 iClose( iFileRefI);
  1287.             }
  1288.         break;
  1289.  
  1290.         case 'INFO':
  1291.             iFileRefI = iFileOpen( AlienFileName);
  1292.             if( iFileRefI)
  1293.             {
  1294.                 info->fileSize = iGetEOF( iFileRefI);
  1295.             
  1296.                 sndSize = 5000L;    // Read only 5000 first bytes for optimisation
  1297.                 
  1298.                 AlienFile = MADPlugNewPtr( sndSize, init);
  1299.                 if( AlienFile == 0L) myErr = MADNeedMemory;
  1300.                 else
  1301.                 {
  1302.                     myErr = iRead( sndSize, AlienFile, iFileRefI);
  1303.                     if( myErr == noErr)
  1304.                     {
  1305.                         myErr = TestXMFile( AlienFile);
  1306.                         if( !myErr) myErr = ExtractXMInfo( info, AlienFile);
  1307.                     }
  1308.                     DisposePtr( AlienFile);    AlienFile = 0L;
  1309.                 }
  1310.                 iClose( iFileRefI);
  1311.             }
  1312.         break;
  1313.         
  1314.         default:
  1315.             myErr = MADOrderNotImplemented;
  1316.         break;
  1317.     }
  1318.  
  1319.     XM_Cleanup();
  1320.  
  1321.     #ifdef _MAC_H
  1322.     #ifndef powerc
  1323.         SetA4( oldA4);
  1324.     #endif
  1325.     #endif
  1326.  
  1327.     return myErr;
  1328. }