home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 24 / CD_ASCQ_24_0995.iso / dos / prg / dsik205 / dsik.dat / SOURCE / IMPORT.C < prev    next >
C/C++ Source or Header  |  1995-04-10  |  59KB  |  1,828 lines

  1. /****************************************************************************
  2. *
  3. *                   Digital Sound Interface Kit (DSIK)
  4. *                            Version 2.00
  5. *
  6. *                           by Carlos Hasan
  7. *
  8. * Filename:     import.c
  9. * Version:      Revision 1.5
  10. *
  11. * Language:     WATCOM C
  12. * Environment:  IBM PC (DOS/4GW)
  13. *
  14. * Description:  Import routines for module and sample files.
  15. *
  16. * Revision History:
  17. * ----------------
  18. *
  19. * Revision 1.5  94/12/31  10:47:44  chv
  20. * Minor changes.
  21. *
  22. * Revision 1.4  94/12/26  11:37:34  chv
  23. * Fixed bug in the MTM pattern loader (notes were transposed one halfnote).
  24. *
  25. * Revision 1.3  94/11/17  16:58:20  chv
  26. * Added Composer 669 and Scream Tracker 2.0 import routines
  27. *
  28. * Revision 1.2  94/11/08  15:10:42  chv
  29. * Added Amiga IFF/8SVX sample file import routines
  30. *
  31. * Revision 1.1  94/10/26  13:12:43  chv
  32. * Added Multitracker MTM modules import routines
  33. *
  34. * Revision 1.0  94/10/03  12:50:22  chv
  35. * Initial revision
  36. *
  37. ****************************************************************************/
  38.  
  39. #include <io.h>
  40. #include <fcntl.h>
  41. #include <malloc.h>
  42. #include <string.h>
  43. #include <sys\stat.h>
  44. #include "audio.h"
  45. #include "import.h"
  46.  
  47.  
  48. /******************* SOUND/SAMPLE FILES IMPORT ROUTINES ********************/
  49.  
  50. /*----------------- RAW Sample Files Import Routines ----------------------*/
  51.  
  52. /****************************************************************************
  53. *
  54. * Function:     LoadSample
  55. * Parameters:   Handle      - DOS file handle
  56. *               Length      - sample length
  57. *               Flags       - sample format
  58. *
  59. * Returns:      Sample address or NULL when an error has occurred
  60. *               while loading the file.
  61. *
  62. * Description:  Load 8-bit signed/unsigned mono samples from disk.
  63. *
  64. ****************************************************************************/
  65.  
  66. static Sample *LoadSample(int Handle, long Length, int Flags)
  67. {
  68.     Sample *SampPtr;
  69.     void *DataPtr;
  70.  
  71.     if (!(SampPtr = (Sample*)calloc(1,sizeof(Sample)))) {
  72.         dError = ERR_NOMEM;
  73.         return NULL;
  74.     }
  75.     SampPtr->Flags = Flags;
  76.     SampPtr->Volume = 64;
  77.     SampPtr->Length = SampPtr->LoopStart = SampPtr->LoopEnd = Length;
  78.     SampPtr->DataPtr = NULL;
  79.     SampPtr->Rate = MIDCFREQ;
  80.     if (!SampPtr->Length) {
  81.         return SampPtr;
  82.     }
  83.     if (!(SampPtr->DataPtr = DataPtr = malloc(Length))) {
  84.         dError = ERR_NOMEM;
  85.         free(SampPtr);
  86.         return NULL;
  87.     }
  88.     if (read(Handle,DataPtr,Length) != Length) {
  89.         dError = ERR_FILEIO;
  90.         free(DataPtr);
  91.         free(SampPtr);
  92.         return NULL;
  93.     }
  94.     if (!dMemAlloc(SampPtr)) {
  95.         dError = ERR_NODRAM;
  96.         free(DataPtr);
  97.         free(SampPtr);
  98.         return NULL;
  99.     }
  100.     if (dGetDriverFlags() & AF_DRAM) {
  101.         free(DataPtr);
  102.     }
  103.     return SampPtr;
  104. }
  105.  
  106.  
  107. /*---------------- Creative Labs' Voice Import Routines -------------------*/
  108.  
  109. /****************************************************************************
  110. *
  111. * Function:     VOCLoadSample
  112. * Parameters:   Handle      - DOS file handle
  113. *               Length      - file length
  114. *
  115. * Returns:      Sample address or NULL when an error has occurred
  116. *               while loading the file.
  117. *
  118. * Description:  Load Creative Labs' Voice 8-bit mono samples from disk.
  119. *
  120. ****************************************************************************/
  121.  
  122. static Sample *VOCLoadSample(int Handle, long Length)
  123. {
  124.     Sample *SampPtr;
  125.     VocHeader VocHdr;
  126.     VocBlock VocBlk;
  127.     VocData VocDta;
  128.     VocExtInfo VocExt;
  129.     long Size;
  130.  
  131.     /* read VOC header */
  132.     if (read(Handle,&VocHdr,sizeof(VocHdr)) != sizeof(VocHdr)) {
  133.         dError = ERR_FILEIO;
  134.         return NULL;
  135.     }
  136.     if (memcmp(VocHdr.Magic,VOC_HDR,sizeof(VocHdr.Magic))) {
  137.         dError = ERR_FORMAT;
  138.         return NULL;
  139.     }
  140.  
  141.     /* seek VOC data block */
  142.     if (lseek(Handle,VocHdr.BlockPos-sizeof(VocHdr),SEEK_CUR) < 0) {
  143.         dError = ERR_FILEIO;
  144.         return NULL;
  145.     }
  146.     do {
  147.         if (read(Handle,&VocBlk,sizeof(VocBlk)) != sizeof(VocBlk)) {
  148.             dError = ERR_FILEIO;
  149.             return NULL;
  150.         }
  151.         Size = *((long*)VocBlk.Size) & 0xFFFFFF;
  152.         if (VocBlk.Type == VOC_DATA) {
  153.             if (read(Handle,&VocDta,sizeof(VocDta)) != sizeof(VocDta)) {
  154.                 dError = ERR_FILEIO;
  155.                 return NULL;
  156.             }
  157.             if (VocDta.Format != VOC_FMT_8BITS) {
  158.                 dError = ERR_FORMAT;
  159.                 return NULL;
  160.             }
  161.             Size -= sizeof(VocDta);
  162.         }
  163.         else if (VocBlk.Type == VOC_EXTINFO) {
  164.             if (read(Handle,&VocExt,sizeof(VocExt)) != sizeof(VocExt)) {
  165.                 dError = ERR_FILEIO;
  166.                 return NULL;
  167.             }
  168.             if (VocExt.Mode != VOC_MODE_MONO) {
  169.                 dError = ERR_FORMAT;
  170.                 return NULL;
  171.             }
  172.         }
  173.         else {
  174.             if (lseek(Handle,Size,SEEK_CUR) < 0) {
  175.                 dError = ERR_FILEIO;
  176.                 return NULL;
  177.             }
  178.         }
  179.     } while (VocBlk.Type != VOC_DATA);
  180.  
  181.     /* load VOC PCM samples */
  182.     if (!(SampPtr = LoadSample(Handle,Size,SF_8BITS|SF_UNSIGNED)))
  183.         return NULL;
  184.     SampPtr->Volume = 64;
  185.     SampPtr->Rate = (word)(1000000L/(256-VocDta.TimeConst));
  186.  
  187.     return SampPtr;
  188. }
  189.  
  190.  
  191. /*------------- Amiga IFF/8SVX sample format Import Routines --------------*/
  192.  
  193. /****************************************************************************
  194. *
  195. * Function:     IFFLoadSample
  196. * Parameters:   Handle      - DOS file handle
  197. *               Length      - file length
  198. *
  199. * Returns:      Sample address or NULL when an error has occurred
  200. *               while loading the file.
  201. *
  202. * Description:  Load 8-bit mono signed IFF sample files.
  203. *
  204. ****************************************************************************/
  205.  
  206. static Sample *IFFLoadSample(int Handle, long Length)
  207. {
  208.     Sample *SampPtr;
  209.     IffHeader Header;
  210.     IffBlock Block;
  211.     IffVHdr VHdr;
  212.     IffChan Chan;
  213.  
  214.     /* read IFF/8SVX header */
  215.     if (read(Handle,&Header,sizeof(Header)) != sizeof(Header)) {
  216.         dError = ERR_FILEIO;
  217.         return NULL;
  218.     }
  219.     if (Header.ID != IFF_FORM || Header.Type != IFF_8SVX) {
  220.         dError = ERR_FORMAT;
  221.         return NULL;
  222.     }
  223.  
  224.     /* seek IFF/8SVX BODY chunk */
  225.     SampPtr = NULL;
  226.     VHdr.Rate = MIDCFREQ;
  227.     Header.Length = LSWAP(Header.Length);
  228.     if (Header.Length & 1) Header.Length++;
  229.     Header.Length -= sizeof(Header.Type);
  230.     while (Header.Length) {
  231.         if (read(Handle,&Block,sizeof(Block)) != sizeof(Block)) {
  232.             dError = ERR_FILEIO;
  233.             return NULL;
  234.         }
  235.         Block.Length = LSWAP(Block.Length);
  236.         if (Block.Length & 1) Block.Length++;
  237.         Header.Length -= sizeof(Block) + Block.Length;
  238.         if (Block.ID == IFF_VHDR) {
  239.             if (Block.Length != sizeof(VHdr)) {
  240.                 dError = ERR_FORMAT;
  241.                 return NULL;
  242.             }
  243.             if (read(Handle,&VHdr,sizeof(VHdr)) != sizeof(VHdr)) {
  244.                 dError = ERR_FILEIO;
  245.                 return NULL;
  246.             }
  247.             VHdr.Rate = WSWAP(VHdr.Rate);
  248.             if (VHdr.Format != 0) {
  249.                 dError = ERR_FORMAT;
  250.                 return NULL;
  251.             }
  252.         }
  253.         else if (Block.ID == IFF_CHAN) {
  254.             if (Block.Length != sizeof(Chan)) {
  255.                 dError = ERR_FORMAT;
  256.                 return NULL;
  257.             }
  258.             if (read(Handle,&Chan,sizeof(Chan)) != sizeof(Chan)) {
  259.                 dError = ERR_FILEIO;
  260.                 return NULL;
  261.             }
  262.             Chan.Channels = LSWAP(Chan.Channels);
  263.             Chan.Channels = (Chan.Channels & 0x01) +
  264.                 ((Chan.Channels & 0x02) >> 1) +
  265.                 ((Chan.Channels & 0x04) >> 2) +
  266.                 ((Chan.Channels & 0x08) >> 3);
  267.             if (Chan.Channels != 1) {
  268.                 dError = ERR_FORMAT;
  269.                 return NULL;
  270.             }
  271.         }
  272.         else if (Block.ID == IFF_BODY) {
  273.             if (!(SampPtr = LoadSample(Handle,Block.Length,SF_8BITS|SF_SIGNED)))
  274.                 return NULL;
  275.             SampPtr->Volume = 64;
  276.             SampPtr->Rate = VHdr.Rate;
  277.             break;
  278.         }
  279.         else if (lseek(Handle,Block.Length,SEEK_CUR) < 0) {
  280.             dError = ERR_FILEIO;
  281.             return NULL;
  282.         }
  283.     }
  284.  
  285.     if (!SampPtr) dError = ERR_FORMAT;
  286.     return SampPtr;
  287. }
  288.  
  289. /*------------ Amiga 8-bit RAW Sample Files Import Routines ---------------*/
  290.  
  291. /****************************************************************************
  292. *
  293. * Function:     RAWLoadSample
  294. * Parameters:   Handle      - DOS file handle
  295. *               Length      - sample length
  296. *
  297. * Returns:      Sample address or NULL when an error has occurred
  298. *               while loading the file.
  299. *
  300. * Description:  Load 8-bit signed/unsigned mono samples from disk.
  301. *
  302. ****************************************************************************/
  303.  
  304. static Sample *RAWLoadSample(int Handle, long Length)
  305. {
  306.     return LoadSample(Handle,Length,SF_8BITS|SF_SIGNED);
  307. }
  308.  
  309.  
  310. /******************* MUSIC MODULE FILES IMPORT ROUTINES ********************/
  311.  
  312. /*--------------- Protracker/Fastracker Import Routines -------------------*/
  313.  
  314. static word PeriodTable[96] = {
  315.     6848,6464,6096,5760,5424,5120,4832,4560,4304,4064,3840,3624,
  316.     3424,3232,3048,2880,2712,2560,2416,2280,2152,2032,1920,1812,
  317.     1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906,
  318.     856,808,762,720,678,640,604,570,538,508,480,453,
  319.     428,404,381,360,339,320,302,285,269,254,240,226,
  320.     214,202,190,180,170,160,151,143,135,127,120,113,
  321.     107,101,95,90,85,80,75,71,67,63,60,56,
  322.     53,50,47,45,42,40,37,35,33,31,30,28 };
  323.  
  324. static word RateTable[16] = {
  325.     8363,8424,8485,8546,8608,8670,8733,8797,
  326.     7894,7951,8008,8066,8125,8184,8243,8303 };
  327.  
  328. /****************************************************************************
  329. *
  330. * Function:     MODLoadPattern
  331. * Parameters:   Handle      - file handle
  332. *               NumTracks   - number of tracks
  333. *
  334. * Returns:      Pattern structure or NULL if error.
  335. *
  336. * Description:  Used to load MOD patterns.
  337. *
  338. ****************************************************************************/
  339.  
  340. static Pattern *MODLoadPattern(int Handle, int NumTracks)
  341. {
  342.     Pattern *DPatt;
  343.     byte *SPatt;
  344.     byte *S,*D;
  345.     byte Row,Track,Flags,Note,Inst,Effect,Param;
  346.     word Period;
  347.  
  348.     if (!(DPatt = (Pattern*)malloc(2+(1+5*NumTracks)*64))) {
  349.         dError = ERR_NOMEM;
  350.         return NULL;
  351.     }
  352.     if (!(SPatt = (byte*)malloc(NumTracks<<8))) {
  353.         dError = ERR_NOMEM;
  354.         free(DPatt);
  355.         return NULL;
  356.     }
  357.     if (read(Handle,SPatt,NumTracks<<8) != (NumTracks<<8)) {
  358.         dError = ERR_FILEIO;
  359.         free(SPatt);
  360.         free(DPatt);
  361.         return NULL;
  362.     }
  363.     S = SPatt;
  364.     D = DPatt->Data;
  365.     for (Row = 0; Row < 64; Row++) {
  366.         for (Track = 0; Track < NumTracks; Track++) {
  367.             Period = (((word)S[0] & 0x0F) << 8) | ((word)S[1]);
  368.             Inst = (S[0] & 0xF0) | ((S[2] & 0xF0)>>4);
  369.             Effect = S[2] & 0x0F;
  370.             Param = S[3];
  371.             S += 4;
  372.             for (Note = 0; Note < 96; Note++)
  373.                 if (Period >= PeriodTable[Note]) break;
  374.             if (Note >= 96) Note = 0; else Note++;
  375.             Flags = 0;
  376.             if (Note) Flags |= 0x80;
  377.             if (Inst) Flags |= 0x40;
  378.             if (Effect | Param) Flags |= 0x10;
  379.             if (Flags) {
  380.                 *D++ = Flags | (Track & 0x0F);
  381.                 if (Note) *D++ = Note;
  382.                 if (Inst) *D++ = Inst;
  383.                 if (Effect | Param) {
  384.                     *D++ = Effect;
  385.                     *D++ = Param;
  386.                 }
  387.             }
  388.         }
  389.         *D++ = 0;
  390.     }
  391.     free(SPatt);
  392.     DPatt->Length = D-(byte*)DPatt;
  393.     return (Pattern*)realloc(DPatt,DPatt->Length);
  394. }
  395.  
  396. /****************************************************************************
  397. *
  398. * Function:     MODLoadSample
  399. * Parameters:   Handle  - file handle
  400. *               Instr   - MOD sample structure
  401. *
  402. * Returns:      Sample structure or NULL if error.
  403. *
  404. * Description:  Used to load MOD samples.
  405. *
  406. ****************************************************************************/
  407.  
  408. static Sample *MODLoadSample(int Handle, MODSample *Instr)
  409. {
  410.     Sample *SampPtr;
  411.  
  412.     Instr->Length = WSWAP(Instr->Length) << 1;
  413.     Instr->LoopStart = WSWAP(Instr->LoopStart) << 1;
  414.     Instr->LoopLength = WSWAP(Instr->LoopLength) << 1;
  415.     if (!(SampPtr = LoadSample(Handle,Instr->Length,SF_8BITS|SF_SIGNED)))
  416.         return NULL;
  417.     strncpy(SampPtr->SampleName,Instr->SampleName,sizeof(Instr->SampleName));
  418.     SampPtr->Volume = Instr->Volume;
  419.     SampPtr->Rate = RateTable[Instr->Finetune & 0x0F];
  420.     if (Instr->LoopLength > 2) {
  421.         SampPtr->Flags |= SF_LOOPED;
  422.         SampPtr->LoopStart = SampPtr->LoopEnd = Instr->LoopStart;
  423.         SampPtr->LoopEnd += Instr->LoopLength;
  424.         if (SampPtr->LoopEnd >= SampPtr->Length)
  425.             SampPtr->LoopEnd = SampPtr->Length;
  426.         if (SampPtr->LoopStart >= SampPtr->LoopEnd)
  427.             SampPtr->LoopStart = SampPtr->LoopEnd;
  428.     }
  429.     return SampPtr;
  430. }
  431.  
  432. /****************************************************************************
  433. *
  434. * Function:     MODLoadModule
  435. * Parameters:   Handle      - DOS file handle
  436. *               Length      - file length
  437. *
  438. * Returns:      Music module address or NULL when an error has occurred
  439. *               while loading the file.
  440. *
  441. * Description:  Load Protracker/Fastracker (MOD) music modules from disk.
  442. *
  443. ****************************************************************************/
  444.  
  445. static DSM *MODLoadModule(int Handle, long Length)
  446. {
  447.     DSM *Module;
  448.     MODSong Header;
  449.     int Index;
  450.  
  451.     if (!(Module = (DSM*)calloc(1,sizeof(DSM)))) {
  452.         dError = ERR_NOMEM;
  453.         return NULL;
  454.     }
  455.     if (read(Handle,&Header,sizeof(Header)) != sizeof(Header)) {
  456.         dError = ERR_FILEIO;
  457.         dFreeModule(Module);
  458.         return NULL;
  459.     }
  460.     if (Header.Magic == MOD_MK || Header.Magic == MOD_FLT4) {
  461.         Module->Header.NumTracks = 4;
  462.     }
  463.     else if (Header.Magic == MOD_6CHN) {
  464.         Module->Header.NumTracks = 6;
  465.     }
  466.     else if (Header.Magic == MOD_8CHN || Header.Magic == MOD_FLT8) {
  467.         Module->Header.NumTracks = 8;
  468.     }
  469.     else {
  470.         dError = ERR_FORMAT;
  471.         dFreeModule(Module);
  472.         return NULL;
  473.     }
  474.  
  475.     /* fill the SONG structure */
  476.     strncpy(Module->Header.ModuleName,Header.SongName,sizeof(Header.SongName));
  477.     Module->Header.OrderPos = 0;
  478.     Module->Header.ReStart = Header.ReStart;
  479.     Module->Header.NumOrders = Header.NumOrders;
  480.     Module->Header.NumSamples = 31;
  481.     Module->Header.NumPatterns = 0;
  482.     Module->Header.GlobalVolume = 64;
  483.     Module->Header.MasterVolume = 768/Module->Header.NumTracks;
  484.     Module->Header.InitTempo = 6;
  485.     Module->Header.InitBPM = 125;
  486.     for (Index = 0; Index < 128; Index++) {
  487.         Module->Header.Orders[Index] = Header.Orders[Index];
  488.         if (Module->Header.NumPatterns < Header.Orders[Index])
  489.             Module->Header.NumPatterns = Header.Orders[Index];
  490.     }
  491.     (Module->Header.NumPatterns)++;
  492.     for (Index = 0; Index < Module->Header.NumTracks; Index++) {
  493.         Module->Header.ChanMap[Index] = ((Index & 3) == 0 ||
  494.                 (Index & 3) == 3) ? PAN_LEFT : PAN_RIGHT;
  495.     }
  496.  
  497.     /* allocate sample and pattern pointer tables */
  498.     if (!(Module->Samples = (Sample**)calloc(Module->Header.NumSamples,sizeof(Sample *)))) {
  499.         dError = ERR_NOMEM;
  500.         dFreeModule(Module);
  501.         return NULL;
  502.     }
  503.     if (!(Module->Patterns = (Pattern**)calloc(Module->Header.NumPatterns,sizeof(Pattern *)))) {
  504.         dError = ERR_NOMEM;
  505.         dFreeModule(Module);
  506.         return NULL;
  507.     }
  508.  
  509.     /* fill the PATT structures */
  510.     for (Index = 0; Index < Module->Header.NumPatterns; Index++) {
  511.         if (!(Module->Patterns[Index] =
  512.                 MODLoadPattern(Handle,Module->Header.NumTracks))) {
  513.             dFreeModule(Module);
  514.             return NULL;
  515.         }
  516.     }
  517.  
  518.     /* fill the INST structures */
  519.     for (Index = 0; Index < Module->Header.NumSamples; Index++) {
  520.         if (!(Module->Samples[Index] =
  521.                 MODLoadSample(Handle,&Header.Samples[Index]))) {
  522.             dFreeModule(Module);
  523.             return NULL;
  524.         }
  525.     }
  526.  
  527.     return Module;
  528. }
  529.  
  530. /*----------------- Scream Tracker 3.0 Import Routines --------------------*/
  531.  
  532. /****************************************************************************
  533. *
  534. * Function:     S3MLoadPattern
  535. * Parameters:   Handle  - file handle
  536. *               SeekPos - pattern relative file position
  537. *               ChanMap - 32 channels remap table
  538. *
  539. * Returns:      Pattern structure or NULL if error.
  540. *
  541. * Description:  Used to load S3M patterns.
  542. *
  543. ****************************************************************************/
  544.  
  545. static Pattern *S3MLoadPattern(int Handle, long SeekPos, byte *ChanMap)
  546. {
  547.     Pattern *DPatt;
  548.     byte *SPatt;
  549.     byte TrackParam[MAXTRACKS];
  550.     byte *S,*D,*MaxD;
  551.     word Length;
  552.     byte Row,Flags,Track,Note,Inst,Volume,Effect,Param,PattLoop;
  553.  
  554.     if (!(DPatt = (Pattern*)malloc(70+2+(1+6*MAXTRACKS)*64))) {
  555.         dError = ERR_NOMEM;
  556.         return NULL;
  557.     }
  558.     if (lseek(Handle,SeekPos,SEEK_SET) < 0) {
  559.         dError = ERR_FILEIO;
  560.         free(DPatt);
  561.         return NULL;
  562.     }
  563.     if (read(Handle,&Length,sizeof(Length)) != sizeof(Length)) {
  564.         dError = ERR_FILEIO;
  565.         free(DPatt);
  566.         return NULL;
  567.     }
  568.     if (!(SPatt = (byte*)malloc(Length -= 2))) {
  569.         dError = ERR_NOMEM;
  570.         free(DPatt);
  571.         return NULL;
  572.     }
  573.     if (read(Handle,SPatt,Length) != Length) {
  574.         dError = ERR_FILEIO;
  575.         free(SPatt);
  576.         free(DPatt);
  577.         return NULL;
  578.     }
  579.     for (Track = PattLoop = 0; Track < MAXTRACKS; Track++) {
  580.         TrackParam[Track] = 0;
  581.     }
  582.     S = SPatt;
  583.     D = DPatt->Data;
  584.     MaxD = D+2+(1+6*MAXTRACKS)*64;
  585.     for (Row = 0; Row < 64; Row++) {
  586.         while (D < MaxD) {
  587.             if (!(Flags = *S++)) break;
  588.             Note = 255;
  589.             Inst = 0;
  590.             Volume = 255;
  591.             Effect = 0;
  592.             Param = 0;
  593.             Track = ChanMap[Flags & 0x1F];
  594.             if (Flags & 0x20) {
  595.                 Note = *S++;
  596.                 Inst = *S++;
  597.             }
  598.             if (Flags & 0x40) {
  599.                 Volume = *S++;
  600.             }
  601.             if (Flags & 0x80) {
  602.                 Effect = *S++;
  603.                 Param = *S++;
  604.             }
  605.             if (Track >= MAXTRACKS) continue;
  606.             if (Note == 0xFE) {
  607.                 Note = Volume = 0;
  608.             }
  609.             else if (Note == 0xFF) {
  610.                 Note = 0;
  611.             }
  612.             else {
  613.                 Note = (Note & 0x0F) + 12*(Note >> 4);
  614.                 if (Note >= 96) Note = 95; else Note++;
  615.             }
  616.             if (Param) TrackParam[Track] = Param;
  617.             Effect += 64;
  618.             if ((Param == 0) && (((Effect >= 'D') && (Effect <= 'G')) ||
  619.                 (Effect == 'K') || (Effect == 'L') || (Effect == 'Q'))) {
  620.                 Param = TrackParam[Track];
  621.             }
  622.             switch (Effect) {
  623.             case 'A':
  624.                 if (Param <= 0x1F) Effect = 0x0F;
  625.                 else Effect = Param = 0;
  626.                 break;
  627.             case 'B':
  628.                 Effect = 0x0B;
  629.                 break;
  630.             case 'C':
  631.                 Effect = 0x0D;
  632.                 break;
  633.             case 'D':
  634.                 if ((Param & 0xF0) == 0x00) {
  635.                     Effect = 0x0A;
  636.                     Param &= 0x0F;
  637.                 }
  638.                 else if ((Param & 0x0F) == 0x00) {
  639.                     Effect = 0x0A;
  640.                     Param &= 0xF0;
  641.                 }
  642.                 else if ((Param & 0xF0) == 0xF0) {
  643.                     Effect = 0x0E;
  644.                     Param = 0xB0 | (Param & 0x0F);
  645.                 }
  646.                 else if ((Param & 0x0F) == 0x0F) {
  647.                     Effect = 0x0E;
  648.                     Param = 0xA0 | (Param >> 4);
  649.                 }
  650.                 else Effect = Param = 0;
  651.                 break;
  652.             case 'E':
  653.                 if ((Param & 0xF0) == 0xF0) {
  654.                     Effect = 0x0E;
  655.                     Param = 0x20 | (Param & 0x0F);
  656.                 }
  657.                 else if ((Param & 0xF0) == 0xE0) {
  658.                     Effect = 0x0E;
  659.                     Param = 0x20 | ((Param & 0x0F) >> 2);
  660.                 }
  661.                 else {
  662.                     Effect = 0x02;
  663.                 }
  664.                 break;
  665.             case 'F':
  666.                 if ((Param & 0xF0) == 0xF0) {
  667.                     Effect = 0x0E;
  668.                     Param = 0x10 | (Param & 0x0F);
  669.                 }
  670.                 else if ((Param & 0xF0) == 0xE0) {
  671.                     Effect = 0x0E;
  672.                     Param = 0x10 | ((Param & 0x0F) >> 2);
  673.                 }
  674.                 else {
  675.                     Effect = 0x01;
  676.                 }
  677.                 break;
  678.             case 'G':
  679.                 Effect = 0x03;
  680.                 break;
  681.             case 'H':
  682.                 Effect = 0x04;
  683.                 break;
  684.             case 'I':
  685.                 Effect = 0x0E;
  686.                 Param = 0x90 | (Param & 0x0F); /* emu tremor with retrig */
  687.                 break;
  688.             case 'J':
  689.                 Effect = 0x00;
  690.                 break;
  691.             case 'K':
  692.                 Effect = 0x06;
  693.                 break;
  694.             case 'L':
  695.                 Effect = 0x05;
  696.                 break;
  697.             case 'O':
  698.                 Effect = 0x09;
  699.                 break;
  700.             case 'Q':
  701.                 Effect = 0x0A;  /* emu retrigvol with volslide */
  702.                 if ((Param >> 4) >= 8)
  703.                     Param = (((Param >> 4)/(Param & 0x0F))+1) << 4;
  704.                 else
  705.                     Param = (((Param >> 4)/(Param & 0x0F))+1);
  706.                 break;
  707.             case 'R':
  708.                 Effect = 0x07;
  709.                 break;
  710.             case 'S':
  711.                 switch (Param & 0xF0) {
  712.                 case 0x00:
  713.                     Effect = 0x0E;
  714.                     Param = 0x00 | (Param & 0x0F);
  715.                     break;
  716.                 case 0x10:
  717.                     Effect = 0x0E;
  718.                     Param = 0x30 | (Param & 0x0F);
  719.                     break;
  720.                 case 0x20:
  721.                     Effect = 0x0E;
  722.                     Param = 0x50 | (Param & 0x0F);
  723.                     break;
  724.                 case 0x30:
  725.                     Effect = 0x0E;
  726.                     Param = 0x70 | (Param & 0x0F);
  727.                     break;
  728.                 case 0x40:
  729.                     Effect = 0x0E;
  730.                     Param = 0x40 | (Param & 0x0F);
  731.                     break;
  732.                 case 0x80:
  733.                     Effect = 0x0E;
  734.                     Param = 0x80 | (Param & 0x0F);
  735.                     break;
  736.                 case 0xA0:
  737.                     Effect = 0x08;
  738.                     switch (Param & 0x0F) {
  739.                     case 0x00:
  740.                     case 0x02:
  741.                         Param = PAN_LEFT;
  742.                         break;
  743.                     case 0x01:
  744.                     case 0x03:
  745.                         Param = PAN_RIGHT;
  746.                         break;
  747.                     case 0x04:
  748.                         Param = (PAN_LEFT + PAN_MIDDLE)/2;
  749.                         break;
  750.                     case 0x05:
  751.                         Param = (PAN_MIDDLE + PAN_RIGHT)/2;
  752.                         break;
  753.                     case 0x06:
  754.                     case 0x07:
  755.                         Param = PAN_MIDDLE;
  756.                         break;
  757.                     default:
  758.                         Effect = Param = 0;
  759.                         break;
  760.                     }
  761.                     break;
  762.                 case 0xB0:
  763.                     if ((Param & 0x0F) == 0x00)
  764.                         Param = PattLoop;
  765.                     else {
  766.                         PattLoop = Param & 0x0F;
  767.                         Param = 0xB0;
  768.                     }
  769.                     Effect = 0x0E;
  770.                     Param = 0x60 | (Param & 0x0F);
  771.                     break;
  772.                 case 0xC0:
  773.                     Effect = 0x0E;
  774.                     Param = 0xC0 | (Param & 0x0F);
  775.                     break;
  776.                 case 0xD0:
  777.                     Effect = 0x0E;
  778.                     Param = 0xD0 | (Param & 0x0F);
  779.                     break;
  780.                 case 0xE0:
  781.                     Effect = 0x0E;
  782.                     Param = 0xE0 | (Param & 0x0F);
  783.                     break;
  784.                 default:
  785.                     Effect = Param = 0;
  786.                     break;
  787.                 }
  788.                 break;
  789.             case 'T':
  790.                 if (Param >= 0x20) Effect = 0x0F;
  791.                 else Effect = Param = 0;
  792.                 break;
  793.             case 'X':
  794.                 Effect = 0x08;
  795.                 break;
  796.             case 'Z':
  797.                 Effect = 0x0B;
  798.                 Param = 0x80 | Param;
  799.                 break;
  800.             default:
  801.                 Effect = Param = 0;
  802.                 break;
  803.             }
  804.             Flags = 0;
  805.             if (Note) Flags |= 0x80;
  806.             if (Inst) Flags |= 0x40;
  807.             if (Volume <= 64) Flags |= 0x20;
  808.             if (Effect | Param) Flags |= 0x10;
  809.             if (Flags) {
  810.                 *D++ = (Flags | (Track & 0x0F));
  811.                 if (Note) *D++ = Note;
  812.                 if (Inst) *D++ = Inst;
  813.                 if (Volume <= 64) *D++ = Volume;
  814.                 if (Effect | Param) {
  815.                     *D++ = Effect;
  816.                     *D++ = Param;
  817.                 }
  818.             }
  819.         }
  820.         *D++ = 0x00;
  821.     }
  822.     free(SPatt);
  823.     DPatt->Length = D-(byte*)DPatt;
  824.     return (Pattern*)realloc(DPatt,DPatt->Length);
  825. }
  826.  
  827. /****************************************************************************
  828. *
  829. * Function:     S3MLoadSample
  830. * Parameters:   Handle  - file handle
  831. *               SeekPos - sample relative file position
  832. *
  833. * Returns:      Sample structure or NULL if error.
  834. *
  835. * Description:  Used to load S3M samples.
  836. *
  837. ****************************************************************************/
  838.  
  839. static Sample *S3MLoadSample(int Handle, long SeekPos)
  840. {
  841.     S3MSample Instr;
  842.     Sample *SampPtr;
  843.  
  844.     if (lseek(Handle,SeekPos,SEEK_SET) < 0) {
  845.         dError = ERR_FILEIO;
  846.         return NULL;
  847.     }
  848.     if (read(Handle,&Instr,sizeof(Instr)) != sizeof(Instr)) {
  849.         dError = ERR_FILEIO;
  850.         return NULL;
  851.     }
  852.     if (Instr.Type == 1 && Instr.Magic != S3M_SCRS) {
  853.         dError = ERR_FORMAT;
  854.         return NULL;
  855.     }
  856.     if (Instr.Type != 1) {
  857.         Instr.Type = Instr.Volume = Instr.Flags = Instr.Rate = 0;
  858.         Instr.DataPtr = Instr.Length = Instr.LoopStart = Instr.LoopEnd = 0;
  859.     }
  860.     else if (lseek(Handle,(dword)Instr.DataPtr<<4,SEEK_SET) < 0) {
  861.         dError = ERR_FILEIO;
  862.         return NULL;
  863.     }
  864.     if (!(SampPtr = LoadSample(Handle,Instr.Length,SF_8BITS|SF_UNSIGNED)))
  865.         return NULL;
  866.     strcpy(SampPtr->SampleName,Instr.SampleName);
  867.     strcpy(SampPtr->FileName,Instr.FileName);
  868.     SampPtr->Volume = Instr.Volume;
  869.     SampPtr->Rate = Instr.Rate;
  870.     if (Instr.Flags) {
  871.         SampPtr->Flags |= SF_LOOPED;
  872.         SampPtr->LoopStart = Instr.LoopStart;
  873.         SampPtr->LoopEnd = Instr.LoopEnd;
  874.     }
  875.     return SampPtr;
  876. }
  877.  
  878. /****************************************************************************
  879. *
  880. * Function:     S3MLoadModule
  881. * Parameters:   Handle      - DOS file handle
  882. *               Length      - file length
  883. *
  884. * Returns:      Music module address or NULL when an error has occurred
  885. *               while loading the file.
  886. *
  887. * Description:  Load Scream Tracker 3.0 (S3M) music modules from disk.
  888. *
  889. ****************************************************************************/
  890.  
  891. static DSM *S3MLoadModule(int Handle, long Length)
  892. {
  893.     DSM *Module;
  894.     S3MSong Header;
  895.     word SampTab[MAXSAMPLES],PattTab[MAXORDERS];
  896.     byte ChanMap[32],PanMap[32],PanPos;
  897.     int Index;
  898.  
  899.     if (!(Module = (DSM*)calloc(1,sizeof(DSM)))) {
  900.         dError = ERR_NOMEM;
  901.         return NULL;
  902.     }
  903.     if (read(Handle,&Header,sizeof(Header)) != sizeof(Header)) {
  904.         dError = ERR_FILEIO;
  905.         dFreeModule(Module);
  906.         return NULL;
  907.     }
  908.     if (Header.Magic != S3M_SCRM || Header.NumOrders > MAXORDERS ||
  909.         Header.NumPatterns > MAXORDERS || Header.NumSamples > MAXSAMPLES) {
  910.         dError = ERR_FORMAT;
  911.         dFreeModule(Module);
  912.         return NULL;
  913.     }
  914.     if (read(Handle,Module->Header.Orders,Header.NumOrders) != Header.NumOrders) {
  915.         dError = ERR_FILEIO;
  916.         dFreeModule(Module);
  917.         return NULL;
  918.     }
  919.     if (read(Handle,SampTab,2*Header.NumSamples) != 2*Header.NumSamples) {
  920.         dError = ERR_FILEIO;
  921.         dFreeModule(Module);
  922.         return NULL;
  923.     }
  924.     if (read(Handle,PattTab,2*Header.NumPatterns) != 2*Header.NumPatterns) {
  925.         dError = ERR_FILEIO;
  926.         dFreeModule(Module);
  927.         return NULL;
  928.     }
  929.     if (Header.DefPan == 0xFC) {
  930.         if (read(Handle,PanMap,sizeof(PanMap)) != sizeof(PanMap)) {
  931.             dError = ERR_FILEIO;
  932.             dFreeModule(Module);
  933.             return NULL;
  934.         }
  935.     }
  936.  
  937.     /* fill the SONG structure */
  938.     strcpy(Module->Header.ModuleName,Header.SongName);
  939.     Module->Header.OrderPos = 0;
  940.     Module->Header.ReStart = MAXORDERS-1;
  941.     Module->Header.NumOrders = Header.NumOrders;
  942.     Module->Header.NumSamples = Header.NumSamples;
  943.     Module->Header.NumPatterns = Header.NumPatterns;
  944.     Module->Header.GlobalVolume = 64;
  945.     Module->Header.MasterVolume = 2*(Header.MasterVolume & 0x7F);
  946.     Module->Header.InitTempo = Header.Tempo;
  947.     Module->Header.InitBPM = Header.BPM;
  948.     Module->Header.NumTracks = 0;
  949.     for (Index = 0; Index < 32; Index++) {
  950.         Header.ChanMap[Index] &= 0x7F;
  951.         ChanMap[Index] = 0xFF;
  952.         if (Module->Header.NumTracks >= MAXTRACKS) continue;
  953.         else if (Header.ChanMap[Index] <= 15) {
  954.             PanPos = (Header.ChanMap[Index] <= 7) ? PAN_LEFT : PAN_RIGHT;
  955.             if ((Header.DefPan == 0xFC) && (PanMap[Index] & 0x20))
  956.                 PanPos = (PanMap[Index] & 0x0F) << 3;
  957.             Module->Header.ChanMap[Module->Header.NumTracks] = PanPos;
  958.             ChanMap[Index] = (Module->Header.NumTracks)++;
  959.         }
  960.     }
  961.     for (Index = 0; Index < Module->Header.NumOrders; Index++)
  962.         if (Module->Header.Orders[Index] == 0xFF) break;
  963.     Module->Header.NumOrders = Index;
  964.  
  965.     /* allocate sample and pattern pointer tables */
  966.     if (!(Module->Samples = (Sample**)calloc(Module->Header.NumSamples,sizeof(Sample *)))) {
  967.         dError = ERR_NOMEM;
  968.         dFreeModule(Module);
  969.         return NULL;
  970.     }
  971.     if (!(Module->Patterns = (Pattern**)calloc(Module->Header.NumPatterns,sizeof(Pattern *)))) {
  972.         dError = ERR_NOMEM;
  973.         dFreeModule(Module);
  974.         return NULL;
  975.     }
  976.  
  977.     /* fill the PATT structures */
  978.     for (Index = 0; Index < Header.NumPatterns; Index++) {
  979.         if (!(Module->Patterns[Index] = S3MLoadPattern(Handle,
  980.                 (dword)PattTab[Index]<<4,ChanMap))) {
  981.             dFreeModule(Module);
  982.             return NULL;
  983.         }
  984.     }
  985.  
  986.     /* fill the INST structures */
  987.     for (Index = 0; Index < Header.NumSamples; Index++) {
  988.         if (!(Module->Samples[Index] = S3MLoadSample(Handle,
  989.                 (dword)SampTab[Index]<<4))) {
  990.             dFreeModule(Module);
  991.             return NULL;
  992.         }
  993.     }
  994.     return Module;
  995. }
  996.  
  997. /*----------------- Multitracker 1.0 Import Routines ----------------------*/
  998.  
  999. /****************************************************************************
  1000. *
  1001. * Function:     MTMLoadPattern
  1002. * Parameters:   Seq     - track sequence
  1003. *               Tracks  - track structures
  1004. *
  1005. * Returns:      Pattern structure or NULL if error.
  1006. *
  1007. * Description:  Used to build patterns from MTM track sequences.
  1008. *
  1009. ****************************************************************************/
  1010.  
  1011. static Pattern *MTMLoadPattern(word *Seq, MTMTrack *Tracks)
  1012. {
  1013.     Pattern *DPatt;
  1014.     byte *S,*D;
  1015.     byte Row,Track,Flags,Note,Inst,Effect,Param;
  1016.  
  1017.     if (!(DPatt = (Pattern*)malloc(2+(1+5*MAXTRACKS)*64))) {
  1018.         dError = ERR_NOMEM;
  1019.         return NULL;
  1020.     }
  1021.     D = DPatt->Data;
  1022.     for (Row = 0; Row < 64; Row++) {
  1023.         for (Track = 0; Track < MAXTRACKS; Track++) {
  1024.             if (Seq[Track]) {
  1025.                 S = &Tracks[Seq[Track]-1].Data[3*Row];
  1026.                 Note = (S[0] >> 2) & 0x3F;
  1027.                 Inst = ((S[0] & 0x03)<<4) + ((S[1]>>4) & 0x0F);
  1028.                 Effect = (S[1] & 0x0F);
  1029.                 Param = S[2];
  1030.                 Flags = 0;
  1031.                 if (Note) {
  1032.                     Flags |= 0x80;
  1033.                     Note += 12*2+1;
  1034.                 }
  1035.                 if (Inst) Flags |= 0x40;
  1036.                 if (Effect | Param) Flags |= 0x10;
  1037.                 if (Flags) {
  1038.                     *D++ = Flags | (Track & 0x0F);
  1039.                     if (Note) *D++ = Note;
  1040.                     if (Inst) *D++ = Inst;
  1041.                     if (Effect | Param) {
  1042.                         *D++ = Effect;
  1043.                         *D++ = Param;
  1044.                     }
  1045.                 }
  1046.             }
  1047.         }
  1048.         *D++ = 0;
  1049.     }
  1050.     DPatt->Length = D-(byte*)DPatt;
  1051.     return (Pattern*)realloc(DPatt,DPatt->Length);
  1052. }
  1053.  
  1054. /****************************************************************************
  1055. *
  1056. * Function:     MTMLoadSample
  1057. * Parameters:   Handle  - file handle
  1058. *               Instr   - MTM sample structure
  1059. *
  1060. * Returns:      Sample structure or NULL if error.
  1061. *
  1062. * Description:  Used to load MTM samples.
  1063. *
  1064. ****************************************************************************/
  1065.  
  1066. static Sample *MTMLoadSample(int Handle, MTMSample *Instr)
  1067. {
  1068.     Sample *SampPtr;
  1069.  
  1070.     if (!(SampPtr = LoadSample(Handle,Instr->Length,SF_8BITS|SF_UNSIGNED)))
  1071.         return NULL;
  1072.     strncpy(SampPtr->SampleName,Instr->SampleName,sizeof(Instr->SampleName));
  1073.     SampPtr->Volume = Instr->Volume;
  1074.     SampPtr->Rate = RateTable[Instr->Finetune & 0x0F];
  1075.     if (Instr->LoopEnd - Instr->LoopStart > 2) {
  1076.         SampPtr->Flags |= SF_LOOPED;
  1077.         SampPtr->LoopStart = Instr->LoopStart;
  1078.         SampPtr->LoopEnd = Instr->LoopEnd;
  1079.     }
  1080.     return SampPtr;
  1081. }
  1082.  
  1083. /****************************************************************************
  1084. *
  1085. * Function:     MTMLoadModule
  1086. * Parameters:   Handle      - DOS file handle
  1087. *               Length      - file length
  1088. *
  1089. * Returns:      Music module address or NULL when an error has occurred
  1090. *               while loading the file.
  1091. *
  1092. * Description:  Load Multitracker 1.0 (MTM) music modules from disk.
  1093. *
  1094. ****************************************************************************/
  1095.  
  1096. static DSM *MTMLoadModule(int Handle, long Length)
  1097. {
  1098.     DSM *Module;
  1099.     MTMSong Header;
  1100.     MTMSample *Samples;
  1101.     MTMTrack *Tracks;
  1102.     word TrackSeq[32];
  1103.     int Index;
  1104.  
  1105.     /* open MTM module file */
  1106.     if (!(Module = (DSM*)calloc(1,sizeof(DSM)))) {
  1107.         dError = ERR_NOMEM;
  1108.         return NULL;
  1109.     }
  1110.  
  1111.     /* load MTM header */
  1112.     if (read(Handle,&Header,sizeof(Header)) != sizeof(Header)) {
  1113.         dError = ERR_FILEIO;
  1114.         dFreeModule(Module);
  1115.         return NULL;
  1116.     }
  1117.     if (((Header.Magic & MTM_MASK) != MTM_MAGIC) ||
  1118.             (Header.NumChans > MAXTRACKS) ||
  1119.             (Header.NumSamples > MAXSAMPLES) ||
  1120.             (Header.BeatsPerTrack != 64)) {
  1121.         dError = ERR_FORMAT;
  1122.         dFreeModule(Module);
  1123.         return NULL;
  1124.     }
  1125.  
  1126.     /* fill the SONG structure */
  1127.     strncpy(Module->Header.ModuleName,Header.SongName,sizeof(Header.SongName));
  1128.     Module->Header.OrderPos = 0;
  1129.     Module->Header.ReStart = MAXORDERS-1;
  1130.     Module->Header.NumOrders = Header.LastOrder+1;
  1131.     Module->Header.NumSamples = Header.NumSamples;
  1132.     Module->Header.NumPatterns = Header.LastPattern+1;
  1133.     Module->Header.NumTracks = Header.NumChans;
  1134.     Module->Header.GlobalVolume = 64;
  1135.     Module->Header.MasterVolume = 768/Module->Header.NumTracks;
  1136.     Module->Header.InitTempo = 6;
  1137.     Module->Header.InitBPM = 125;
  1138.     for (Index = 0; Index < MAXTRACKS; Index++)
  1139.         Module->Header.ChanMap[Index] = Header.PanPos[Index] << 3;
  1140.  
  1141.     /* allocate sample and pattern pointer tables */
  1142.     if (!(Module->Samples = (Sample**)calloc(Module->Header.NumSamples,sizeof(Sample *)))) {
  1143.         dError = ERR_NOMEM;
  1144.         dFreeModule(Module);
  1145.         return NULL;
  1146.     }
  1147.     if (!(Module->Patterns = (Pattern**)calloc(Module->Header.NumPatterns,sizeof(Pattern *)))) {
  1148.         dError = ERR_NOMEM;
  1149.         dFreeModule(Module);
  1150.         return NULL;
  1151.     }
  1152.  
  1153.     /* allocate MTM sample and track structures */
  1154.     if (!(Samples = (MTMSample*)calloc(Module->Header.NumSamples,sizeof(MTMSample)))) {
  1155.         dError = ERR_NOMEM;
  1156.         dFreeModule(Module);
  1157.         return NULL;
  1158.     }
  1159.     if (!(Tracks = (MTMTrack*)calloc(Header.NumTracks,sizeof(MTMTrack)))) {
  1160.         dError = ERR_NOMEM;
  1161.         free(Samples);
  1162.         dFreeModule(Module);
  1163.         return NULL;
  1164.     }
  1165.  
  1166.     /* load MTM sample structures */
  1167.     if (read(Handle,Samples,Module->Header.NumSamples*sizeof(MTMSample)) != Module->Header.NumSamples*sizeof(MTMSample)) {
  1168.         dError = ERR_FILEIO;
  1169.         free(Tracks);
  1170.         free(Samples);
  1171.         dFreeModule(Module);
  1172.         return NULL;
  1173.     }
  1174.  
  1175.     /* load the SONG order list */
  1176.     if (read(Handle,Module->Header.Orders,128) != 128) {
  1177.         dError = ERR_FILEIO;
  1178.         free(Tracks);
  1179.         free(Samples);
  1180.         dFreeModule(Module);
  1181.         return NULL;
  1182.     }
  1183.  
  1184.     /* load MTM tracks */
  1185.     if (read(Handle,Tracks,Header.NumTracks*sizeof(MTMTrack)) != Header.NumTracks*sizeof(MTMTrack)) {
  1186.         dError = ERR_FILEIO;
  1187.         free(Tracks);
  1188.         free(Samples);
  1189.         dFreeModule(Module);
  1190.         return NULL;
  1191.     }
  1192.  
  1193.     /* fill PATT structures */
  1194.     for (Index = 0; Index < Module->Header.NumPatterns; Index++) {
  1195.         if (read(Handle,TrackSeq,sizeof(TrackSeq)) != sizeof(TrackSeq)) {
  1196.             dError = ERR_FILEIO;
  1197.             free(Tracks);
  1198.             free(Samples);
  1199.             dFreeModule(Module);
  1200.             return NULL;
  1201.         }
  1202.         if (!(Module->Patterns[Index] = MTMLoadPattern(TrackSeq,Tracks))) {
  1203.             free(Tracks);
  1204.             free(Samples);
  1205.             dFreeModule(Module);
  1206.             return NULL;
  1207.         }
  1208.     }
  1209.     free(Tracks);
  1210.  
  1211.     /* skip MTM comments data */
  1212.     if (lseek(Handle,Header.CommentLength,SEEK_CUR) < 0) {
  1213.         dError = ERR_FILEIO;
  1214.         free(Samples);
  1215.         dFreeModule(Module);
  1216.         return NULL;
  1217.     }
  1218.  
  1219.     /* fill INST structures */
  1220.     for (Index = 0; Index < Module->Header.NumSamples; Index++) {
  1221.         if (!(Module->Samples[Index] = MTMLoadSample(Handle,&Samples[Index]))) {
  1222.             free(Samples);
  1223.             dFreeModule(Module);
  1224.             return NULL;
  1225.         }
  1226.     }
  1227.     free(Samples);
  1228.  
  1229.     return Module;
  1230. }
  1231.  
  1232. /*------------------- Composer 669 Import Routines ------------------------*/
  1233.  
  1234. /****************************************************************************
  1235. *
  1236. * Function:     GG9LoadPattern
  1237. * Parameters:   Handle      - file handle
  1238. *               Tempo       - initial tempo value
  1239. *               BreakRow    - number of rows
  1240. *
  1241. * Returns:      Pattern structure or NULL if error.
  1242. *
  1243. * Description:  Used to load 669 patterns.
  1244. *
  1245. ****************************************************************************/
  1246.  
  1247. static Pattern *GG9LoadPattern(int Handle, int Tempo, int BreakRow)
  1248. {
  1249.     static byte VolTable[16] = {
  1250.         0x00,0x06,0x0B,0x10,0x14,0x18,0x1C,0x20,
  1251.         0x24,0x28,0x2C,0x30,0x34,0x38,0x3C,0x40 };
  1252.     Pattern *DPatt;
  1253.     byte *SPatt,*S,*D;
  1254.     byte Row,Track,Flags,Note,Inst,Volume,Effect,Param;
  1255.     int InsertTempo, InsertBreak;
  1256.  
  1257.     if (!(DPatt = (Pattern*)malloc(2+(1+6*8)*64))) {
  1258.         dError = ERR_NOMEM;
  1259.         return NULL;
  1260.     }
  1261.     if (!(SPatt = (byte*)malloc(3*8*64))) {
  1262.         dError = ERR_NOMEM;
  1263.         free(DPatt);
  1264.         return NULL;
  1265.     }
  1266.     if (read(Handle,SPatt,3*8*64) != 3*8*64) {
  1267.         dError = ERR_FILEIO;
  1268.         free(SPatt);
  1269.         free(DPatt);
  1270.         return NULL;
  1271.     }
  1272.     S = SPatt;
  1273.     D = DPatt->Data;
  1274.     for (Row = 0; Row < 64; Row++) {
  1275.         InsertTempo = (Row == 0);
  1276.         InsertBreak = ((Row == BreakRow) && (Row != 63));
  1277.         for (Track = 0; Track < 8; Track++) {
  1278.             Note = (S[0] >> 2);
  1279.             Inst = ((S[0] & 0x03) << 4) | (S[1] >> 4);
  1280.             Volume = VolTable[S[1] & 0x0F];
  1281.             Effect = (S[2] >> 4);
  1282.             Param = (S[2] & 0x0F);
  1283.             if (S[0] == 0xFE) {
  1284.                 Note = Inst = 0;
  1285.             }
  1286.             else if (S[0] == 0xFF) {
  1287.                 Note = Inst = 0;
  1288.                 Volume = 255;
  1289.             }
  1290.             else {
  1291.                 Note++;
  1292.                 Inst++;
  1293.             }
  1294.             S += 3;
  1295.             switch (Effect) {
  1296.                 case 0x0:
  1297.                     Effect = 0x01;
  1298.                     break;
  1299.                 case 0x1:
  1300.                     Effect = 0x02;
  1301.                     break;
  1302.                 case 0x2:
  1303.                     Effect = 0x03;
  1304.                     break;
  1305.                 case 0x3:
  1306.                     Effect = 0x0E;
  1307.                     Param = 0x21;
  1308.                     break;
  1309.                 case 0x4:
  1310.                     Effect = 0x04;
  1311.                     Param = (Param << 4) + 1;
  1312.                     break;
  1313.                 case 0x5:
  1314.                     Effect = 0x0F;
  1315.                     break;
  1316.                 default:
  1317.                     Effect = Param = 0;
  1318.                     break;
  1319.             }
  1320.             if (InsertTempo && (!(Effect | Param) || (Track == 7))) {
  1321.                 Effect = 0x0F;
  1322.                 Param = Tempo;
  1323.                 InsertTempo = 0;
  1324.             }
  1325.             if (InsertBreak && (!(Effect | Param) || (Track == 7))) {
  1326.                 Effect = 0x0D;
  1327.                 Param = 0x00;
  1328.                 InsertBreak = 0;
  1329.             }
  1330.             Flags = 0;
  1331.             if (Note) {
  1332.                 Note += 12*2;
  1333.                 Flags |= 0x80;
  1334.             }
  1335.             if (Inst) Flags |= 0x40;
  1336.             if (Volume <= 64) Flags |= 0x20;
  1337.             if (Effect | Param) Flags |= 0x10;
  1338.             if (Flags) {
  1339.                 *D++ = Flags | (Track & 0x0F);
  1340.                 if (Note) *D++ = Note;
  1341.                 if (Inst) *D++ = Inst;
  1342.                 if (Volume <= 64) *D++ = Volume;
  1343.                 if (Effect | Param) {
  1344.                     *D++ = Effect;
  1345.                     *D++ = Param;
  1346.                 }
  1347.             }
  1348.         }
  1349.         *D++ = 0x00;
  1350.     }
  1351.     free(SPatt);
  1352.     DPatt->Length = D-(byte*)DPatt;
  1353.     return (Pattern*)realloc(DPatt,DPatt->Length);
  1354. }
  1355.  
  1356. /****************************************************************************
  1357. *
  1358. * Function:     GG9LoadSample
  1359. * Parameters:   Handle  - file handle
  1360. *               Instr   - 669 sample structure
  1361. *
  1362. * Returns:      Sample structure or NULL if error.
  1363. *
  1364. * Description:  Used to load 669 samples.
  1365. *
  1366. ****************************************************************************/
  1367.  
  1368. static Sample *GG9LoadSample(int Handle, GG9Sample *Instr)
  1369. {
  1370.     Sample *SampPtr;
  1371.  
  1372.     if (!(SampPtr = LoadSample(Handle,Instr->Length,SF_8BITS|SF_UNSIGNED)))
  1373.         return NULL;
  1374.     strncpy(SampPtr->SampleName,Instr->FileName,sizeof(Instr->FileName));
  1375.     SampPtr->Volume = 64;
  1376.     SampPtr->Rate = MIDCFREQ;
  1377.     if (Instr->LoopEnd <= Instr->Length) {
  1378.         SampPtr->Flags |= SF_LOOPED;
  1379.         SampPtr->LoopStart = Instr->LoopStart;
  1380.         SampPtr->LoopEnd = Instr->LoopEnd;
  1381.     }
  1382.     return SampPtr;
  1383. }
  1384.  
  1385. /****************************************************************************
  1386. *
  1387. * Function:     GG9LoadModule
  1388. * Parameters:   Handle      - DOS file handle
  1389. *               Length      - file length
  1390. *
  1391. * Returns:      Music module address or NULL when an error has occurred
  1392. *               while loading the file.
  1393. *
  1394. * Description:  Load Composer 669 music modules from disk.
  1395. *
  1396. ****************************************************************************/
  1397.  
  1398. static DSM *GG9LoadModule(int Handle, long Length)
  1399. {
  1400.     DSM *Module;
  1401.     GG9Song Header;
  1402.     GG9Sample Samples[64];
  1403.     int Index;
  1404.  
  1405.     if (!(Module = (DSM*)calloc(1,sizeof(DSM)))) {
  1406.         dError = ERR_NOMEM;
  1407.         return NULL;
  1408.     }
  1409.     if (read(Handle,&Header,sizeof(Header)) != sizeof(Header)) {
  1410.         dError = ERR_FILEIO;
  1411.         dFreeModule(Module);
  1412.         return NULL;
  1413.     }
  1414.     if (Header.Magic != GG9_MAGIC || Header.NumSamples > 64) {
  1415.         dError = ERR_FORMAT;
  1416.         dFreeModule(Module);
  1417.         return NULL;
  1418.     }
  1419.     if (read(Handle,Samples,sizeof(GG9Sample)*Header.NumSamples) != sizeof(GG9Sample)*Header.NumSamples) {
  1420.         dError = ERR_FILEIO;
  1421.         dFreeModule(Module);
  1422.         return NULL;
  1423.     }
  1424.  
  1425.     /* fill SONG structure */
  1426.     strncpy(Module->Header.ModuleName,Header.SongName,sizeof(Module->Header.ModuleName)-1);
  1427.     Module->Header.OrderPos = 0;
  1428.     Module->Header.ReStart = Header.ReStart;
  1429.     Module->Header.NumSamples = Header.NumSamples;
  1430.     Module->Header.NumPatterns = Header.NumPatterns;
  1431.     Module->Header.NumTracks = 8;
  1432.     Module->Header.GlobalVolume = 64;
  1433.     Module->Header.MasterVolume = 768/8;
  1434.     Module->Header.InitTempo = 4;
  1435.     Module->Header.InitBPM = 80;
  1436.     for (Index = 0; Index < 8; Index++) {
  1437.         Module->Header.ChanMap[Index] = (Index & 1) ? PAN_RIGHT : PAN_LEFT;
  1438.     }
  1439.     for (Index = 0; Index < 128; Index++) {
  1440.         if (Header.Orders[Index] >= 128) break;
  1441.         Module->Header.Orders[Index] = Header.Orders[Index];
  1442.         (Module->Header.NumOrders)++;
  1443.     }
  1444.  
  1445.     /* allocate sample and pattern pointer tables */
  1446.     if (!(Module->Samples = (Sample**)calloc(Module->Header.NumSamples,sizeof(Sample *)))) {
  1447.         dError = ERR_NOMEM;
  1448.         dFreeModule(Module);
  1449.         return NULL;
  1450.     }
  1451.     if (!(Module->Patterns = (Pattern**)calloc(Module->Header.NumPatterns,sizeof(Pattern *)))) {
  1452.         dError = ERR_NOMEM;
  1453.         dFreeModule(Module);
  1454.         return NULL;
  1455.     }
  1456.  
  1457.     /* load PATT structures */
  1458.     for (Index = 0; Index < Module->Header.NumPatterns; Index++) {
  1459.         if (!(Module->Patterns[Index] = GG9LoadPattern(Handle,
  1460.                 Header.Tempos[Index],Header.Breaks[Index]))) {
  1461.             dFreeModule(Module);
  1462.             return NULL;
  1463.         }
  1464.     }
  1465.  
  1466.     /* load INST structures */
  1467.     for (Index = 0; Index < Module->Header.NumSamples; Index++) {
  1468.         if (!(Module->Samples[Index] = GG9LoadSample(Handle,&Samples[Index]))) {
  1469.             dFreeModule(Module);
  1470.             return NULL;
  1471.         }
  1472.     }
  1473.     return Module;
  1474. }
  1475.  
  1476. /*-------------------- Scream Tracker 2.0 import routines -----------------*/
  1477.  
  1478. /****************************************************************************
  1479. *
  1480. * Function:     STMLoadPattern
  1481. * Parameters:   Handle  - file handle
  1482. *
  1483. * Returns:      Pattern structure or NULL if error.
  1484. *
  1485. * Description:  Used to load STM patterns.
  1486. *
  1487. ****************************************************************************/
  1488.  
  1489. static Pattern *STMLoadPattern(int Handle)
  1490. {
  1491.     Pattern *DPatt;
  1492.     byte *SPatt,*S,*D;
  1493.     byte Row,Track,Flags,Note,Inst,Volume,Effect,Param;
  1494.  
  1495.     if (!(DPatt = (Pattern*)malloc(2+(1+6*4)*64))) {
  1496.         dError = ERR_NOMEM;
  1497.         return NULL;
  1498.     }
  1499.     if (!(SPatt = (byte*)malloc(4*4*64))) {
  1500.         dError = ERR_NOMEM;
  1501.         free(DPatt);
  1502.         return NULL;
  1503.     }
  1504.     if (read(Handle,SPatt,4*4*64) != 4*4*64) {
  1505.         dError = ERR_FILEIO;
  1506.         free(SPatt);
  1507.         free(DPatt);
  1508.         return NULL;
  1509.     }
  1510.     S = SPatt;
  1511.     D = DPatt->Data;
  1512.     for (Row = 0; Row < 64; Row++) {
  1513.         for (Track = 0; Track < 4; Track++) {
  1514.             Note = S[0];
  1515.             Inst = S[1] >> 3;
  1516.             Volume = (S[1] & 0x07) | ((S[2] & 0xF0) >> 1);
  1517.             Effect = 64 + (S[2] & 0x0F);
  1518.             Param = S[3];
  1519.             S += 4;
  1520.             if (Note >= 251) continue;
  1521.             Note = (Note & 0x0F) + 12*(Note >> 4);
  1522.             switch (Effect) {
  1523.                 case 'A':
  1524.                     Effect = 0x0F;
  1525.                     Param >>= 4;
  1526.                     break;
  1527.                 case 'B':
  1528.                     Effect = 0x0B;
  1529.                     break;
  1530.                 case 'C':
  1531.                     Effect = 0x0D;
  1532.                     break;
  1533.                 case 'D':
  1534.                     if ((Param & 0xF0) == 0x00) {
  1535.                         Effect = 0x0A;
  1536.                         Param &= 0x0F;
  1537.                     }
  1538.                     else if ((Param & 0x0F) == 0x00) {
  1539.                         Effect = 0x0A;
  1540.                         Param &= 0xF0;
  1541.                     }
  1542.                     else {
  1543.                         Effect = Param = 0;
  1544.                     }
  1545.                     break;
  1546.                 case 'E':
  1547.                     Effect = 0x02;
  1548.                     break;
  1549.                 case 'F':
  1550.                     Effect = 0x01;
  1551.                     break;
  1552.                 case 'G':
  1553.                     Effect = 0x03;
  1554.                     break;
  1555.                 case 'H':
  1556.                     Effect = 0x04;
  1557.                     break;
  1558.                 case 'I':
  1559.                     Effect = 0x0E;      /* emu tremor with retrig */
  1560.                     Param = 0x90 | (Param & 0x0F);
  1561.                     break;
  1562.                 case 'J':
  1563.                     Effect = 0x00;
  1564.                     break;
  1565.                 default:
  1566.                     Effect = Param = 0;
  1567.                     break;
  1568.             }
  1569.             Flags = 0;
  1570.             if (Note) {
  1571.                 Note += 2*12;
  1572.                 Flags |= 0x80;
  1573.             }
  1574.             if (Inst) Flags |= 0x40;
  1575.             if (Volume <= 64) Flags |= 0x20;
  1576.             if (Effect | Param) Flags |= 0x10;
  1577.             if (Flags) {
  1578.                 *D++ = Flags | (Track & 0x0F);
  1579.                 if (Note) *D++ = Note;
  1580.                 if (Inst) *D++ = Inst;
  1581.                 if (Volume <= 64) *D++ = Volume;
  1582.                 if (Effect | Param) {
  1583.                     *D++ = Effect;
  1584.                     *D++ = Param;
  1585.                 }
  1586.             }
  1587.         }
  1588.         *D++ = 0x00;
  1589.     }
  1590.     free(SPatt);
  1591.     DPatt->Length = D-(byte*)DPatt;
  1592.     return (Pattern*)realloc(DPatt,DPatt->Length);
  1593. }
  1594.  
  1595. /****************************************************************************
  1596. *
  1597. * Function:     STMLoadSample
  1598. * Parameters:   Handle  - file handle
  1599. *               Instr   - STM sample structure
  1600. *
  1601. * Returns:      Sample structure or NULL if error.
  1602. *
  1603. * Description:  Used to load STM samples.
  1604. *
  1605. ****************************************************************************/
  1606.  
  1607. static Sample *STMLoadSample(int Handle, STMSample *Instr)
  1608. {
  1609.     Sample *SampPtr;
  1610.  
  1611.     if (!(SampPtr = LoadSample(Handle,Instr->Length,SF_8BITS|SF_SIGNED)))
  1612.         return NULL;
  1613.     strncpy(SampPtr->SampleName,Instr->FileName,sizeof(Instr->FileName));
  1614.     SampPtr->Volume = Instr->Volume;
  1615.     SampPtr->Rate = Instr->Rate;
  1616.     if (Instr->LoopEnd <= Instr->Length) {
  1617.         SampPtr->Flags |= SF_LOOPED;
  1618.         SampPtr->LoopStart = Instr->LoopStart;
  1619.         SampPtr->LoopEnd = Instr->LoopEnd;
  1620.     }
  1621.     return SampPtr;
  1622. }
  1623.  
  1624. /****************************************************************************
  1625. *
  1626. * Function:     STMLoadModule
  1627. * Parameters:   Handle      - DOS file handle
  1628. *               Length      - file length
  1629. *
  1630. * Returns:      Music module address or NULL when an error has occurred
  1631. *               while loading the file.
  1632. *
  1633. * Description:  Load Scream Tracker 2.0 (STM) music modules from disk.
  1634. *
  1635. ****************************************************************************/
  1636.  
  1637. static DSM *STMLoadModule(int Handle, long Length)
  1638. {
  1639.     DSM *Module;
  1640.     STMSong Header;
  1641.     int Index;
  1642.  
  1643.     if (!(Module = (DSM*)calloc(1,sizeof(DSM)))) {
  1644.         dError = ERR_NOMEM;
  1645.         return NULL;
  1646.     }
  1647.     if (read(Handle,&Header,sizeof(Header)) != sizeof(Header)) {
  1648.         dError = ERR_FILEIO;
  1649.         dFreeModule(Module);
  1650.         return NULL;
  1651.     }
  1652.     if (memcmp(Header.Tracker,STM_TRACKER,sizeof(Header.Tracker))) {
  1653.         dError = ERR_FORMAT;
  1654.         dFreeModule(Module);
  1655.         return NULL;
  1656.     }
  1657.  
  1658.     /* fill SONG structure */
  1659.     strncpy(Module->Header.ModuleName,Header.SongName,sizeof(Header.SongName));
  1660.     Module->Header.OrderPos = 0;
  1661.     Module->Header.ReStart = MAXORDERS-1;
  1662.     Module->Header.NumSamples = 31;
  1663.     Module->Header.NumPatterns = Header.NumPatterns;
  1664.     Module->Header.NumTracks = 4;
  1665.     Module->Header.GlobalVolume = 64;
  1666.     Module->Header.MasterVolume = 768/4;
  1667.     Module->Header.InitTempo = Header.InitTempo >> 4;
  1668.     Module->Header.InitBPM = 125;
  1669.     for (Index = 0; Index < 128; Index++) {
  1670.         if (Header.Orders[Index] >= 99) break;
  1671.         Module->Header.Orders[Index] = Header.Orders[Index];
  1672.         (Module->Header.NumOrders)++;
  1673.     }
  1674.     for (Index = 0; Index < 4; Index++) {
  1675.         Module->Header.ChanMap[Index] = (Index & 1) ? PAN_RIGHT : PAN_LEFT;
  1676.     }
  1677.  
  1678.     /* allocate sample and pattern pointer tables */
  1679.     if (!(Module->Samples = (Sample**)calloc(Module->Header.NumSamples,sizeof(Sample *)))) {
  1680.         dError = ERR_NOMEM;
  1681.         dFreeModule(Module);
  1682.         return NULL;
  1683.     }
  1684.     if (!(Module->Patterns = (Pattern**)calloc(Module->Header.NumPatterns,sizeof(Pattern *)))) {
  1685.         dError = ERR_NOMEM;
  1686.         dFreeModule(Module);
  1687.         return NULL;
  1688.     }
  1689.  
  1690.     /* load PATT structures */
  1691.     for (Index = 0; Index < Module->Header.NumPatterns; Index++) {
  1692.         if (!(Module->Patterns[Index] = STMLoadPattern(Handle))) {
  1693.             dFreeModule(Module);
  1694.             return NULL;
  1695.         }
  1696.     }
  1697.  
  1698.     /* load INST structures */
  1699.     for (Index = 0; Index < Module->Header.NumSamples; Index++) {
  1700.         if (!(Module->Samples[Index] = STMLoadSample(Handle,&Header.Samples[Index]))) {
  1701.             dFreeModule(Module);
  1702.             return NULL;
  1703.         }
  1704.     }
  1705.     return Module;
  1706. }
  1707.  
  1708.  
  1709. /*------------------- Module/Sample Import Routines -----------------------*/
  1710.  
  1711. /****************************************************************************
  1712. *
  1713. * Function:     dImportModuleFile
  1714. * Parameters:   Handle  - DOS file handle
  1715. *               Length  - Module length
  1716. *               Form    - Module format
  1717. *
  1718. * Returns:      Music module address or NULL when an error has occurred
  1719. *               while loading the file.
  1720. *
  1721. * Description:  Load multichannel music modules from disk.
  1722. *
  1723. ****************************************************************************/
  1724.  
  1725. DSM *dImportModuleFile(int Handle, long Length, int Form)
  1726. {
  1727.     return (Form == FORM_DSM) ? dLoadModuleFile(Handle,Length) :
  1728.         (Form == FORM_MOD) ? MODLoadModule(Handle,Length) :
  1729.         (Form == FORM_S3M) ? S3MLoadModule(Handle,Length) :
  1730.         (Form == FORM_MTM) ? MTMLoadModule(Handle,Length) :
  1731.         (Form == FORM_669) ? GG9LoadModule(Handle,Length) :
  1732.         (Form == FORM_STM) ? STMLoadModule(Handle,Length) :
  1733.         NULL;
  1734. }
  1735.  
  1736.  
  1737. /****************************************************************************
  1738. *
  1739. * Function:     dImportSampleFile
  1740. * Parameters:   Filename    - Sample filename
  1741. *               Length      - Sample length
  1742. *               Form        - Sample format
  1743. *
  1744. * Returns:      Sample address or NULL when an error has occurred
  1745. *               while loading the file.
  1746. *
  1747. * Description:  Load 8-bit mono digital samples from disk.
  1748. *
  1749. ****************************************************************************/
  1750.  
  1751. Sample *dImportSampleFile(int Handle, long Length, int Form)
  1752. {
  1753.     return (Form == FORM_WAV) ? dLoadSampleFile(Handle,Length) :
  1754.         (Form == FORM_VOC) ? VOCLoadSample(Handle,Length) :
  1755.         (Form == FORM_IFF) ? IFFLoadSample(Handle,Length) :
  1756.         (Form == FORM_RAW) ? RAWLoadSample(Handle,Length) :
  1757.         NULL;
  1758. }
  1759.  
  1760.  
  1761. /****************************************************************************
  1762. *
  1763. * Function:     dImportModule
  1764. * Parameters:   Filename    - Module filename
  1765. *               Form        - Module format
  1766. *
  1767. * Returns:      Music module address or NULL when an error has occurred
  1768. *               while loading the file.
  1769. *
  1770. * Description:  Load multichannel music modules from disk.
  1771. *
  1772. ****************************************************************************/
  1773.  
  1774. DSM *dImportModule(char *Filename, int Form)
  1775. {
  1776.     int Handle;
  1777.     DSM *Module;
  1778.     long Length;
  1779.  
  1780.     if ((Handle = open(Filename,O_RDONLY|O_BINARY)) < 0) {
  1781.         dError = ERR_NOFILE;
  1782.         return NULL;
  1783.     }
  1784.     if ((Length = filelength(Handle)) < 0) {
  1785.         dError = ERR_FILEIO;
  1786.         close(Handle);
  1787.         return NULL;
  1788.     }
  1789.     Module = dImportModuleFile(Handle,Length,Form);
  1790.     close(Handle);
  1791.     return Module;
  1792. }
  1793.  
  1794.  
  1795. /****************************************************************************
  1796. *
  1797. * Function:     dImportSample
  1798. * Parameters:   Filename    - Sample filename
  1799. *               Form        - Sample format
  1800. *
  1801. * Returns:      Sample address or NULL when an error has occurred
  1802. *               while loading the file.
  1803. *
  1804. * Description:  Load 8-bit mono digital samples from disk.
  1805. *
  1806. ****************************************************************************/
  1807.  
  1808. Sample *dImportSample(char *Filename, int Form)
  1809. {
  1810.     int Handle;
  1811.     Sample *SampPtr;
  1812.     long Length;
  1813.  
  1814.     if ((Handle = open(Filename,O_RDONLY|O_BINARY)) < 0) {
  1815.         dError = ERR_NOFILE;
  1816.         return NULL;
  1817.     }
  1818.     if ((Length = filelength(Handle)) < 0) {
  1819.         dError = ERR_FILEIO;
  1820.         close(Handle);
  1821.         return NULL;
  1822.     }
  1823.     SampPtr = dImportSampleFile(Handle,Length,Form);
  1824.     close(Handle);
  1825.     return SampPtr;
  1826. }
  1827.  
  1828.