home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 August / macformat-027.iso / mac / Shareware City / Developers / PlayerPRO 4.4.1 Dev.Kit / Import⁄Export / Mod.c < prev    next >
Encoding:
Text File  |  1995-04-04  |  19.8 KB  |  684 lines  |  [TEXT/MPCC]

  1. /********************                        ***********************/
  2. //
  3. //    Player PRO 4.4x -- MOD to MADx & MADx to MOD
  4. //
  5. //    Version 1.0    - 12.3.95 ANR
  6. //
  7. //    To use with CodeWarrior 68K or PPC
  8. //
  9. //    Antoine ROSSET
  10. //    16 Tranchees
  11. //    1206 GENEVA
  12. //    SWITZERLAND
  13. //    
  14. //    FAX:            (+41 22) 346 11 97
  15. //    Compuserve:        100277,164
  16. //    Internet:         rosset@dial.eunet.ch
  17. //
  18. /********************                        ***********************/
  19.  
  20. #include "MOD.h"
  21. #include "MAD.h"
  22. #include "RDriver.h"
  23. #include "PPInOut.h"
  24.  
  25. #if defined(powerc) || defined(__powerc)
  26. enum {
  27.         PlayerPROPlug = kCStackBased
  28.         | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
  29.         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof( OSType)))
  30.         | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof( Ptr*)))
  31.         | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof( MADPartition*)))
  32.         | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof( PPInfoRec*)))
  33.         | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof( short**)))
  34. };
  35.  
  36. ProcInfoType __procinfo = PlayerPROPlug;
  37. #else
  38. #include <A4Stuff.h>
  39. #endif
  40.  
  41. void AnalyseSignatureMOD( long temp, short *maxInstru, long *PatternSize, short *tracksNo, MODDef* aMOD)
  42. {
  43.     long         test, i;
  44.     Boolean        result;
  45.  
  46.     *maxInstru = 31;
  47.  
  48.     switch( temp)
  49.     {
  50.         case 'FLT4':    *PatternSize = sizeof( struct MODCom) * 64L * 4L;    *tracksNo = 4;    break;
  51.         case 'FLT8':    *PatternSize = sizeof( struct MODCom) * 64L * 4L;    *tracksNo = 4;    break;
  52.         case 'M.K.':    *PatternSize = sizeof( struct MODCom) * 64L * 4L;    *tracksNo = 4;    break;
  53.         case '5CHN':    *PatternSize = sizeof( struct MODCom) * 64L * 5L;    *tracksNo = 5;    break;
  54.         case '6CHN':    *PatternSize = sizeof( struct MODCom) * 64L * 6L;    *tracksNo = 6;    break;
  55.         case '7CHN':    *PatternSize = sizeof( struct MODCom) * 64L * 7L;    *tracksNo = 7;    break;
  56.         case '8CHN':    *PatternSize = sizeof( struct MODCom) * 64L * 8L;    *tracksNo = 8;    break;
  57.         case '9CHN':    *PatternSize = sizeof( struct MODCom) * 64L * 9L;    *tracksNo = 9;    break;
  58.         case '10CH':    *PatternSize = sizeof( struct MODCom) * 64L * 10L;    *tracksNo = 10;    break;
  59.         case '11CH':    *PatternSize = sizeof( struct MODCom) * 64L * 11L;    *tracksNo = 11;    break;
  60.         case '12CH':    *PatternSize = sizeof( struct MODCom) * 64L * 12L;    *tracksNo = 12;    break;
  61.         case '13CH':    *PatternSize = sizeof( struct MODCom) * 64L * 13L;    *tracksNo = 13;    break;
  62.         case '14CH':    *PatternSize = sizeof( struct MODCom) * 64L * 14L;    *tracksNo = 14;    break;
  63.         case '15CH':    *PatternSize = sizeof( struct MODCom) * 64L * 15L;    *tracksNo = 15;    break;
  64.         case '16CH':    *PatternSize = sizeof( struct MODCom) * 64L * 16L;    *tracksNo = 16;    break;
  65.         case '17CH':    *PatternSize = sizeof( struct MODCom) * 64L * 17L;    *tracksNo = 17;    break;
  66.         case '18CH':    *PatternSize = sizeof( struct MODCom) * 64L * 18L;    *tracksNo = 18;    break;
  67.         case '19CH':    *PatternSize = sizeof( struct MODCom) * 64L * 19L;    *tracksNo = 19;    break;
  68.         case '20CH':    *PatternSize = sizeof( struct MODCom) * 64L * 20L;    *tracksNo = 20;    break;
  69.         case '21CH':    *PatternSize = sizeof( struct MODCom) * 64L * 21L;    *tracksNo = 21;    break;
  70.         case '22CH':    *PatternSize = sizeof( struct MODCom) * 64L * 22L;    *tracksNo = 22;    break;
  71.         case '23CH':    *PatternSize = sizeof( struct MODCom) * 64L * 23L;    *tracksNo = 23;    break;
  72.         case '24CH':    *PatternSize = sizeof( struct MODCom) * 64L * 24L;    *tracksNo = 24;    break;
  73.         case '25CH':    *PatternSize = sizeof( struct MODCom) * 64L * 25L;    *tracksNo = 25;    break;
  74.         case '26CH':    *PatternSize = sizeof( struct MODCom) * 64L * 26L;    *tracksNo = 26;    break;
  75.         case '27CH':    *PatternSize = sizeof( struct MODCom) * 64L * 27L;    *tracksNo = 27;    break;
  76.         case '28CH':    *PatternSize = sizeof( struct MODCom) * 64L * 28L;    *tracksNo = 28;    break;
  77.         case '29CH':    *PatternSize = sizeof( struct MODCom) * 64L * 29L;    *tracksNo = 29;    break;
  78.         case '30CH':    *PatternSize = sizeof( struct MODCom) * 64L * 30L;    *tracksNo = 30;    break;
  79.         case '31CH':    *PatternSize = sizeof( struct MODCom) * 64L * 31L;    *tracksNo = 31;    break;
  80.         case '32CH':    *PatternSize = sizeof( struct MODCom) * 64L * 32L;    *tracksNo = 32;    break;
  81.         
  82.         default:
  83.             *PatternSize     = sizeof( struct MODCom) * 64L * 4L;            *tracksNo = 4;
  84.             
  85.             result = true;
  86.             test = 0;
  87.             for( i = 0; i < 15; i++)
  88.             {
  89.                 test += aMOD->fid[i].numWords;
  90.                 if( aMOD->fid[i].fineTune > 0x0F) result = false;
  91.             }
  92.             if( test == 0) result = false;
  93.                         
  94.             if( result) *maxInstru         = 15;
  95.             else *maxInstru             = 0;
  96.         break;
  97.     }
  98. }
  99.  
  100. short FoundNote( short Period, short *MADpitchTable)
  101. {
  102. short    NCount = 1;
  103.     
  104.     while( NCount < NUMBER_NOTES+1)
  105.     {
  106.         if( Period >= MADpitchTable[ NCount]) return( NCount);
  107.         NCount++;
  108.     }
  109.     
  110.     return 0;
  111. }
  112.  
  113. struct Command* GetMADCommand( register short PosX, register short    TrackIdX, register    struct MusicPattern*    tempMusicPat)
  114. {
  115.     if( PosX < 0) PosX = 0;
  116.     else if( PosX >= tempMusicPat->header.PatternSize) PosX = tempMusicPat->header.PatternSize -1;
  117.         
  118.     return( & (tempMusicPat->Commands[ (tempMusicPat->header.PatternSize * TrackIdX) + PosX]));
  119. }
  120.  
  121. struct MODCom* GetMODCommand( short position, short whichTracks, short whichPattern, short maxTracks, Ptr PatPtr)
  122. {
  123.     struct MODCom*    myMODCom;
  124.     
  125.     myMODCom =    (struct MODCom*) (PatPtr +
  126.                 whichPattern * 64L * sizeof( struct MODCom) * maxTracks +
  127.                 position * sizeof( struct MODCom) * maxTracks +
  128.                 whichTracks * sizeof( struct MODCom));
  129.     
  130.     return myMODCom;
  131. }
  132.  
  133. OSErr PPConvertMod2Mad( Ptr aMOD,long MODSize, MADPartition    *theMAD, short *MADpitchTable)
  134. {
  135.     short             i, PatMax, x, tracksNo, z, maxInstru;
  136.     long             sndSize, OffSetToSample, MPatSize, temp, inOutCount;
  137.     Ptr                MaxPtr;
  138.     OSErr            theErr;
  139.     Ptr                theInstrument[ 64], destPtr;
  140.     
  141.     /**** Variables for MAD File *****/
  142.     struct Command        *aCmd;
  143.  
  144.     /**** Variables for MOD File *****/
  145.     MODDef                 *theMOD;
  146.     struct MODPat        *PatInt;
  147.     MODDef                *MODInt;
  148.     struct MODCom        *theCommand;
  149.     /********************************/
  150.     
  151.     theMOD = ((MODDef*) aMOD);
  152.     MaxPtr = (Ptr)((long) theMOD + MODSize);
  153.  
  154.     temp = *((long*)(aMOD + 0x438));        // Signature...
  155.  
  156.     AnalyseSignatureMOD( temp, &maxInstru, &MPatSize, &tracksNo, theMOD);
  157.     
  158.     if( maxInstru == 0)
  159.     {
  160.         return fileNotSupportedByThisPlug;    // This file is NOT a Mod file !!!!!! This should NEVER happen !
  161.     }
  162.     else if( maxInstru == 15)                // Old Mods format with 15 instruments
  163.     {
  164.         MODInt = (MODDef*) ( (Ptr) theMOD - (Ptr) 0x1E0);
  165.         PatInt = (struct MODPat*) ((Ptr) MODInt->patterns - (Ptr) 0x4);
  166.  
  167.         PatMax = 0;
  168.         for(i=0; i<64; i++)
  169.         {
  170.             if( MODInt->oPointers[i] < 0) MODInt->oPointers[i] = 0;
  171.             if( MODInt->oPointers[i] > 128) MODInt->oPointers[i] = 0;
  172.         
  173.             if( MODInt->oPointers[i] >= PatMax)    PatMax = MODInt->oPointers[i];
  174.         }
  175.         PatMax++;
  176.         
  177.         OffSetToSample = (long) 0x258 + PatMax * MPatSize;
  178.     }
  179.     else                                    // Mods format with 32 instruments
  180.     {
  181.         MODInt    = theMOD;
  182.         PatInt    = MODInt->patterns;
  183.     
  184.         PatMax = 0;
  185.         for(i=0; i<128; i++)
  186.         {
  187.             if( MODInt->oPointers[i] < 0) MODInt->oPointers[i] = 0;
  188.             if( MODInt->oPointers[i] > 128) MODInt->oPointers[i] = 0;
  189.             
  190.             if( MODInt->oPointers[i] >= PatMax) PatMax = MODInt->oPointers[i];
  191.         }
  192.         PatMax++;
  193.         
  194.         OffSetToSample = (long) 0x43c + PatMax * MPatSize;
  195.     }
  196.     
  197.     for( i = 0; i < maxInstru ; i++)
  198.     {
  199.         theInstrument[i] = (Ptr) ((long) theMOD + (long) OffSetToSample);
  200.  
  201.         sndSize = ((long) theMOD->fid[i].numWords) * 2L;
  202.     
  203.         if( theInstrument[i] + sndSize > MaxPtr)
  204.         {
  205.             theMOD->fid[i].numWords = MaxPtr - theInstrument[i];
  206.             theMOD->fid[i].numWords /= 2L;
  207.             
  208.             if( theMOD->fid[i].numWords < 0) theMOD->fid[i].numWords = 0;
  209.                     
  210.             sndSize = ((long) theMOD->fid[i].numWords) * 2L;
  211.         }
  212.         
  213.         OffSetToSample += sndSize;
  214.  
  215.         if( theMOD->fid[i].loopWords > 2 && sndSize > 0)
  216.         {
  217.             if( (long) theMOD->fid[i].loopWord +
  218.                 (long) theMOD->fid[i].loopWords > 
  219.                 (long) theMOD->fid[i].numWords)
  220.             {
  221.                 theMOD->fid[ i].loopWords =    (long) theMOD->fid[i].numWords -
  222.                                             (long) theMOD->fid[i].loopWord;
  223.         
  224.                 if( (long) theMOD->fid[i].loopWord +
  225.                 (long) theMOD->fid[i].loopWords > 
  226.                 (long) theMOD->fid[i].numWords)
  227.                 {
  228.                     theMOD->fid[i].loopWord = 0;
  229.                     theMOD->fid[i].loopWords = 0;
  230.                 }
  231.             }
  232.         }
  233.         else
  234.         {
  235.             theMOD->fid[i].loopWord = 0;
  236.             theMOD->fid[i].loopWords = 0;
  237.         }
  238.     }
  239.     
  240.     /***************************************************************/
  241.     /******** MOD is ready to be converted into MAD File ***********/
  242.     /***************************************************************/
  243.     
  244.     inOutCount = sizeof( MADSpec);
  245.     theMAD->header = (MADSpec*) NewPtrClear( inOutCount);    
  246.     if( theMAD->header == 0L) DebugStr("\pHeader: I NEED MEMORY !!! NOW !");
  247.     
  248.     theMAD->header->MADIdentification = 'MADG';
  249.     
  250.     for(i=0; i<22; i++) theMAD->header->NameSignature[i] = theMOD->NameSignature[i];
  251.     
  252.     theMAD->header->PatMax = PatMax;
  253.     theMAD->header->numPointers = MODInt->numPointers;
  254.     
  255.     for(i=0; i<128; i++) theMAD->header->oPointers[ i] = MODInt->oPointers[ i];
  256.     
  257.     theMAD->header->Tracks = tracksNo;
  258.  
  259.     for(i = 0; i < maxInstru; i++)
  260.     {
  261.         for( x = 0; x < 22; x++) theMAD->header->fid[i].Filename[x] = theMOD->fid[i].Filename[x];
  262.         theMAD->header->fid[i].insSize        = theMOD->fid[i].numWords * 2L;
  263.         theMAD->header->fid[i].fineTune        = theMOD->fid[i].fineTune;
  264.         theMAD->header->fid[i].volume         = theMOD->fid[i].volume;
  265.         theMAD->header->fid[i].freq         = 1;
  266.         theMAD->header->fid[i].amplitude    = 8;
  267.         theMAD->header->fid[i].loopStart     = theMOD->fid[i].loopWord*2L;
  268.         theMAD->header->fid[i].loopLenght     = theMOD->fid[i].loopWords*2L;
  269.         
  270.         if( theMAD->header->fid[ i].insSize > 0)
  271.         {
  272.             theMAD->instrument[ i] = NewPtr( theMAD->header->fid[i].insSize);
  273.             if( theMAD->instrument[ i] == 0L) DebugStr("\pInstruments: I NEED MEMORY !!! NOW !");
  274.             
  275.             BlockMove( theInstrument[i], theMAD->instrument[i], theMAD->header->fid[i].insSize);
  276.         }
  277.         else theMAD->instrument[i] = 0L;
  278.     }
  279.     
  280.     for( i = maxInstru; i < MAXINSTRU ; i++)
  281.     {
  282.         theMAD->instrument[i]                 = 0L;
  283.         theMAD->header->fid[i].volume         = 64;
  284.         theMAD->header->fid[i].freq         = 1;
  285.         theMAD->header->fid[i].amplitude    = 8;
  286.     }
  287.     
  288.     for(i=0; i<theMAD->header->PatMax; i++)
  289.     {
  290.         theMAD->partition[ i] = (struct    MusicPattern*) NewPtrClear( sizeof( struct MusicPattern) + theMAD->header->Tracks * 64L * sizeof( struct Command));
  291.         if( theMAD->partition[ i] == 0L) DebugStr("\pPatterns: I NEED MEMORY !!! NOW !");
  292.         
  293.         theMAD->partition[ i]->header.PatternSize         = 64L;
  294.         theMAD->partition[ i]->header.CompressionMode     = 'NONE';
  295.         
  296.         for( x = 0; x < 20; x++) theMAD->partition[ i]->header.PatternName[ x] = 0;
  297.         
  298.         theMAD->partition[ i]->header.PatBytes = 0L;        theMAD->partition[ i]->header.unused2 = 0L;
  299.     
  300.         MaxPtr = (Ptr) theMAD->partition[ i];
  301.         MaxPtr += sizeof( struct MusicPattern) + theMAD->header->Tracks * 64L * sizeof( struct Command);
  302.  
  303.         for(x=0; x<64; x++)
  304.         {
  305.             for(z=0; z<theMAD->header->Tracks; z++)
  306.             {
  307.                 aCmd = GetMADCommand(  x,  z, theMAD->partition[ i]);
  308.                 if( (Ptr) aCmd + sizeof( struct Command) > MaxPtr) DebugStr("\pConversion ERROR");
  309.                 
  310.                 theCommand     = GetMODCommand(    x,
  311.                                                 z,
  312.                                                 i,
  313.                                                 theMAD->header->Tracks,
  314.                                                 (Ptr) PatInt);
  315.                 
  316.                 aCmd->InstrumentNo = (theCommand->InstrLoNibble & 0x0F) + (theCommand->InstrHiNibble << 4);
  317.                 aCmd->AmigaPeriod = FoundNote( theCommand->AmigaPeriod, MADpitchTable);
  318.                 aCmd->EffectCmd = theCommand->EffectCmd & 0x0F;
  319.                 aCmd->EffectArg = theCommand->EffectArg & 0x00FF;
  320.             }
  321.         }
  322.     }
  323.     for( i = theMAD->header->PatMax; i < MAXPATTERN ; i++) theMAD->partition[ i] = 0L;
  324.  
  325.     return noErr;
  326. }
  327.  
  328. Ptr PPConvertMad2Mod( MADPartition *theMAD)
  329. {
  330.     short                 i, x, z, maxInstru;
  331.     long                 sndSize, OffSetToSample, temp, InstruSize, *alpha;
  332.     Ptr                    MaxPtr;
  333.     OSErr                theErr;
  334.     Ptr                    theInstrument[ 64], destPtr;
  335.     Boolean                CheckGoodMod;
  336.     Str255                tempStr;
  337.     char                redut[4];
  338.     short                MODTuning[ 65] =
  339.                         {    0,
  340.                             1712,1616,1525,1440,1357,1281,1209,1141,1077,1017, 961, 907,
  341.                             856,808,762,720,678,640,604,570,538,508,480,453,
  342.                             428,404,381,360,339,320,302,285,269,254,240,226,
  343.                             214,202,190,180,170,160,151,143,135,127,120,113,
  344.                             107,101, 95, 90, 85, 80, 76, 71, 67, 64, 60, 57 };
  345.                             
  346.     /**** Variables for MAD file ****/
  347.     
  348.     struct Command        *aCmd;
  349.  
  350.     /**** Variables for MOD file ****/
  351.     
  352.     MODDef                 *theMOD;
  353.     struct MODCom        *theCommand;
  354.     /********************************/
  355.  
  356.     maxInstru = 31;
  357.     
  358.     OffSetToSample = theMAD->header->PatMax * theMAD->header->Tracks * 64L * sizeof( struct Command);
  359.     OffSetToSample += sizeof( MADSpec);
  360.     
  361.     InstruSize = 0;
  362.     for( i = 0; i < maxInstru ; i++)
  363.     {
  364.         theInstrument[i] = theMAD->instrument[i];
  365.         OffSetToSample += theMAD->header->fid[i].insSize;
  366.         InstruSize += theMAD->header->fid[i].insSize;
  367.     }
  368.     
  369.     /******** MAD is ready to be converted **********/
  370.     /******** Copy information in the MOD file    ***/
  371.     
  372.     theMOD = (MODDef*) NewPtr( 0x43c + InstruSize + theMAD->header->Tracks * 64L * theMAD->header->PatMax * sizeof( struct MODCom));
  373.     if( theMOD == 0L) return 0L;
  374.     
  375.     theMOD->longFmtSignature = 'M.K.';
  376.     if( theMAD->header->Tracks > 4)
  377.     {
  378.         NumToString( theMAD->header->Tracks, tempStr);
  379.         if( tempStr[ 0] == 2)
  380.         {
  381.             redut[0] = tempStr[1];
  382.             redut[1] = tempStr[2];
  383.             redut[2] = 'C';
  384.             redut[3] = 'H';
  385.         }
  386.         else if( tempStr[ 0] == 1)
  387.         {
  388.             redut[0] = tempStr[1];
  389.             redut[1] = 'C';
  390.             redut[2] = 'H';
  391.             redut[3] = 'N';
  392.         }
  393.         
  394.         alpha = (long*) redut;
  395.         
  396.         theMOD->longFmtSignature = *alpha;
  397.     }
  398.     
  399.     MaxPtr = (Ptr) theMOD + GetPtrSize( (Ptr) theMOD);
  400.     
  401.     for(i=0; i<20; i++) theMOD->NameSignature[i] = theMAD->header->NameSignature[i];
  402.     
  403.     CheckGoodMod = false;
  404.     theMOD->numPointers = theMAD->header->numPointers;
  405.     for(i=0; i<128; i++)
  406.     {
  407.         theMOD->oPointers[ i] = theMAD->header->oPointers[ i];
  408.         if( theMOD->oPointers[ i] == theMAD->header->PatMax - 1) CheckGoodMod = true;
  409.     }
  410.     if( !CheckGoodMod) theMOD->oPointers[ theMOD->numPointers + 1] = theMAD->header->PatMax - 1;
  411.     
  412.     for(i=0; i<maxInstru; i++)
  413.     {
  414.         for( x = 0; x < 22; x++) theMOD->fid[i].Filename[x] = theMAD->header->fid[i].Filename[x];
  415.         
  416.         if( theMAD->header->fid[i].insSize/2L > 0xFFFFUL) theMOD->fid[i].numWords = 0xFFFFUL;
  417.         else theMOD->fid[i].numWords = (short) (theMAD->header->fid[i].insSize / 2L);
  418.         
  419.         theMOD->fid[i].fineTune = theMAD->header->fid[i].fineTune;
  420.         theMOD->fid[i].volume = theMAD->header->fid[i].volume;
  421.         theMOD->fid[i].loopWord = theMAD->header->fid[i].loopStart / 2L;
  422.         theMOD->fid[i].loopWords = theMAD->header->fid[i].loopLenght / 2L;
  423.     }
  424.     
  425.     InstruSize = 0L;
  426.     
  427.     OffSetToSample = (long) 0x43c + theMAD->header->PatMax * sizeof( struct MODCom) * 64L * theMAD->header->Tracks;
  428.     
  429.     for(i=0; i<maxInstru; i++)
  430.     {
  431.         destPtr = (Ptr) ((long) theMOD + (long) OffSetToSample + (long) InstruSize);
  432.     
  433.         if( destPtr  + (long) (theMOD->fid[i].numWords) * 2L <= MaxPtr) BlockMove( theInstrument[i], destPtr, (long) (theMOD->fid[i].numWords) * 2L);
  434.         else DebugStr("\pInstrument Error");
  435.         
  436.         InstruSize += (long) (theMOD->fid[i].numWords) * 2L;
  437.     }
  438.     
  439.     for(i=0; i<theMAD->header->PatMax; i++)
  440.     {
  441.         for(x=0; x < 64; x++)
  442.         {
  443.             for(z=0; z < theMAD->header->Tracks; z++)
  444.             {
  445.                 aCmd         = GetMADCommand(     x,
  446.                                                 z,
  447.                                                 theMAD->partition[ i]);
  448.                 
  449.                 theCommand     = GetMODCommand(    x,
  450.                                                 z,
  451.                                                 i,
  452.                                                 theMAD->header->Tracks,
  453.                                                 (Ptr) theMOD->patterns);
  454.                                                 
  455.                 if( (Ptr) theCommand > MaxPtr) DebugStr("\pCommand Error");
  456.                 
  457.                 theCommand->InstrLoNibble = (aCmd->InstrumentNo & 0x0F);
  458.                 theCommand->InstrHiNibble = (aCmd->InstrumentNo >> 4);
  459.                 if( aCmd->AmigaPeriod > 0) theCommand->AmigaPeriod = MODTuning[ aCmd->AmigaPeriod - 1];
  460.                 else theCommand->AmigaPeriod = 0;
  461.                 theCommand->EffectCmd = aCmd->EffectCmd;
  462.                 theCommand->EffectArg = aCmd->EffectArg;
  463.             }
  464.         }
  465.     }
  466.     
  467.     return( (Ptr) theMOD);
  468. }
  469.  
  470. OSErr ExtractMODInfo( PPInfoRec *info, Ptr AlienFile)
  471. {
  472.     MODDef    *myMOD = ( MODDef*) AlienFile;
  473.     long    PatternSize;
  474.     short    i;
  475.     short    maxInstru;
  476.     short    tracksNo;
  477.     
  478.     /*** Signature ***/
  479.     
  480.     info->signature = myMOD->longFmtSignature;
  481.     
  482.     /*** Internal name ***/
  483.     
  484.     myMOD->NameSignature[ 19] = '\0';
  485.     pStrcpy( info->internalFileName, CtoPstr( myMOD->NameSignature));
  486.  
  487.     /*** Check MOD Type ***/
  488.     
  489.     AnalyseSignatureMOD( info->signature, &maxInstru, &PatternSize, &info->totalTracks, myMOD);
  490.     if( maxInstru == 0)
  491.     {
  492.         return fileNotSupportedByThisPlug;
  493.     }
  494.     else if( maxInstru == 15)    // Old mod format
  495.     {
  496.         info->signature = '----';
  497.         myMOD = (MODDef*) ((Ptr) myMOD - (Ptr) 0x1E0);
  498.     }
  499.     
  500.     /*** Total Patterns ***/
  501.     
  502.     info->totalPatterns = 0;
  503.     for( i = 0; i < 128; i++)
  504.     {
  505.         if( myMOD->oPointers[ i] >= info->totalPatterns)    info->totalPatterns = myMOD->oPointers[ i];
  506.     }
  507.     info->totalPatterns++;
  508.     
  509.     /*** Partition Length ***/
  510.     
  511.     info->partitionLength = myMOD->numPointers;
  512.     
  513.     /*** Total Instruments ***/
  514.     
  515.     for( i = 0, info->totalInstruments = 0; i < maxInstru ; i++)
  516.     {
  517.         if( myMOD->fid[ i].numWords > 5) info->totalInstruments++;
  518.     }
  519.     
  520.     pStrcpy( info->formatDescription, "\pMOD Plug");
  521.  
  522.     return noErr;
  523. }
  524.  
  525. OSErr TestMODFile( Ptr AlienFile)
  526. {
  527.     short    maxInstru;
  528.     long    PatternSize;
  529.     short    tracksNo;
  530.     
  531.     AnalyseSignatureMOD( *((long*)(AlienFile + 0x438)), &maxInstru, &PatternSize, &tracksNo, (MODDef*) AlienFile);
  532.     
  533.     if( maxInstru == 0) return fileNotSupportedByThisPlug;
  534.     else return noErr;
  535. }
  536.  
  537. void pStrcpy(register unsigned char *s1, register unsigned char *s2)
  538. {
  539.     register short len, i;
  540.     
  541.     len = *s2;
  542.     for ( i = 0; i <= len; i++) s1[ i] = s2[ i];
  543. }
  544.  
  545. /*****************/
  546. /* MAIN FUNCTION */
  547. /*****************/
  548.  
  549. OSErr main( OSType order, FSSpec *AlienFileFSSpec, MADPartition *MadFile, PPInfoRec *info, short *MADpitchTable)
  550. {
  551.     OSErr    myErr;
  552.     Ptr        AlienFile;
  553.     short    vRefNum, iFileRefI;
  554.     long    dirID, sndSize;
  555.     
  556. #ifndef powerc
  557.     long    oldA4 = SetCurrentA4();             //this call is necessary for strings in 68k code resources
  558. #endif
  559.  
  560.     HGetVol( 0L, &vRefNum, &dirID);
  561.     HSetVol( 0L, AlienFileFSSpec->vRefNum, AlienFileFSSpec->parID);
  562.  
  563.     myErr = noErr;
  564.  
  565.     switch( order)
  566.     {
  567.         case 'IMPL':
  568.             myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  569.             if( myErr == noErr)
  570.             {
  571.                 GetEOF( iFileRefI, &sndSize);
  572.             
  573.                 // ** MEMORY Test Start
  574.                 AlienFile = NewPtr( sndSize * 2L);
  575.                 if( AlienFile == 0L) myErr = needMoreMemory;
  576.                 // ** MEMORY Test End
  577.                 
  578.                 else
  579.                 {
  580.                     DisposPtr( AlienFile);
  581.                     
  582.                     AlienFile = NewPtr( sndSize);
  583.                     myErr = FSRead( iFileRefI, &sndSize, AlienFile);
  584.                     if( myErr == noErr)
  585.                     {
  586.                         myErr = TestMODFile( AlienFile);
  587.                         if( myErr == noErr)
  588.                         {
  589.                             myErr = PPConvertMod2Mad( AlienFile, GetPtrSize( AlienFile), MadFile, MADpitchTable);
  590.                         }
  591.                     }
  592.                     DisposPtr( AlienFile);    AlienFile = 0L;
  593.                 }
  594.                 FSClose( iFileRefI);
  595.             }
  596.         break;
  597.         
  598.         case 'TEST':
  599.             myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  600.             if( myErr == noErr)
  601.             {
  602.                 sndSize = 5000L;    // Read only 5000 first bytes for optimisation
  603.                 
  604.                 AlienFile = NewPtr( sndSize);
  605.                 if( AlienFile == 0L) myErr = needMoreMemory;
  606.                 else
  607.                 {
  608.                     myErr = FSRead( iFileRefI, &sndSize, AlienFile);
  609.                     myErr = TestMODFile( AlienFile);
  610.                     
  611.                     DisposPtr( AlienFile);    AlienFile = 0L;
  612.                 }
  613.                 FSClose( iFileRefI);
  614.             }
  615.         break;
  616.         
  617.         case 'EXPL':
  618.             AlienFile = PPConvertMad2Mod( MadFile);
  619.             
  620.             if( AlienFile != 0L)
  621.             {
  622.                 myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  623.                 if( myErr == fnfErr)
  624.                 {
  625.                     myErr = Create( AlienFileFSSpec->name, 0, 'SNPL', 'STrk');
  626.                     myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  627.                 }
  628.                 
  629.                 if( myErr == noErr)
  630.                 {
  631.                     FInfo    fndrInfo;
  632.                 
  633.                     sndSize = GetPtrSize( AlienFile);
  634.                     myErr = SetEOF( iFileRefI, sndSize);
  635.                     if( myErr == noErr)
  636.                     {
  637.                         myErr = FSWrite( iFileRefI, &sndSize, AlienFile);
  638.                     }
  639.                     FSClose( iFileRefI);
  640.                     
  641.                     GetFInfo( AlienFileFSSpec->name, 0, &fndrInfo);
  642.                     fndrInfo.fdCreator    = 'SNPL';
  643.                     fndrInfo.fdType        = 'STrk';
  644.                     SetFInfo( AlienFileFSSpec->name, 0, &fndrInfo);
  645.                 }
  646.                 DisposPtr( AlienFile);    AlienFile = 0L;
  647.             }
  648.         break;
  649.  
  650.         case 'INFO':
  651.             myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  652.             if( myErr == noErr)
  653.             {
  654.                 GetEOF( iFileRefI, &info->fileSize);
  655.             
  656.                 sndSize = 5000L;    // Read only 5000 first bytes for optimisation
  657.                 
  658.                 AlienFile = NewPtr( sndSize);
  659.                 if( AlienFile == 0L) myErr = needMoreMemory;
  660.                 else
  661.                 {
  662.                     myErr = FSRead( iFileRefI, &sndSize, AlienFile);
  663.                     if( myErr == noErr)
  664.                     {
  665.                         myErr = ExtractMODInfo( info, AlienFile);
  666.                     }
  667.                     DisposPtr( AlienFile);    AlienFile = 0L;
  668.                 }
  669.                 FSClose( iFileRefI);
  670.             }
  671.         break;
  672.         
  673.         default:
  674.             myErr = orderNotImplemented;
  675.         break;
  676.     }
  677.  
  678.     HSetVol( 0L, vRefNum, dirID);
  679.  
  680.     #ifndef powerc
  681.         SetA4( oldA4);
  682.     #endif
  683.     return myErr;
  684. }