home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 24 / CD_ASCQ_24_0995.iso / dos / prg / dsik205 / dsik.dat / EXAMPLES / M2DSM.C < prev    next >
C/C++ Source or Header  |  1995-04-10  |  22KB  |  645 lines

  1. /****************************************************************************
  2. *
  3. *                   Digital Sound Interface Kit (DSIK)
  4. *                            Version 2.00
  5. *
  6. *                           by Carlos Hasan
  7. *
  8. * Filename:     m2dsm.c
  9. * Version:      Revision 1.1
  10. *
  11. * Language:     WATCOM C
  12. * Environment:  IBM PC (DOS/4GW)
  13. *
  14. * Description:  Standalone music module converter.
  15. *
  16. * Revision History:
  17. * ----------------
  18. *
  19. * Revision 1.1  94/12/28  18:40:45  chv
  20. * New unused tracks removal routine.
  21. *
  22. * Revision 1.0  94/10/01  18:47:07  chv
  23. * Initial revision
  24. *
  25. ****************************************************************************/
  26.  
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <io.h>
  30. #include <fcntl.h>
  31. #include <malloc.h>
  32. #include <string.h>
  33. #include <sys\stat.h>
  34. #include "audio.h"
  35. #include "import.h"
  36.  
  37.  
  38.  
  39. /****************************************************************************
  40. *
  41. * Functions:    dGetDriverFlags, dMemAlloc and dMemFree
  42. *
  43. * Description:  Fake sound system functions used to load modules in memory.
  44. *
  45. ****************************************************************************/
  46.  
  47. int dGetDriverFlags(void)
  48. {
  49.     return AF_8BITS | AF_MONO | AF_NODRAM;
  50. }
  51.  
  52. long dMemAlloc(Sample *SampPtr)
  53. {
  54.     return (long)SampPtr;
  55. }
  56.  
  57. void dMemFree(Sample *SampPtr)
  58. {
  59. }
  60.  
  61.  
  62. /****************************************************************************
  63. *
  64. * Function:     dSaveModule
  65. * Parameters:   Filename    - DOS file name
  66. *               Module      - Music module
  67. *
  68. * Returns:      Music module or NULL if error.
  69. *
  70. ****************************************************************************/
  71.  
  72. DSM *dSaveModule(char *Filename, DSM *Module)
  73. {
  74.     int Handle,I;
  75.     RiffHeader Header;
  76.     RiffBlock Block;
  77.  
  78.     if ((Handle = open(Filename,O_CREAT|O_WRONLY|O_BINARY,S_IRWXU)) < 0)
  79.         return NULL;
  80.  
  81.     Header.ID = ID_RIFF;
  82.     Header.Length = sizeof(Header.Type) + sizeof(Block) + sizeof(Song);
  83.     Header.Type = ID_DSMF;
  84.     for (I = 0; I < Module->Header.NumPatterns; I++)
  85.         Header.Length += sizeof(Block) + Module->Patterns[I]->Length;
  86.     for (I = 0; I < Module->Header.NumSamples; I++)
  87.         Header.Length += sizeof(Block) + sizeof(Sample) + Module->Samples[I]->Length;
  88.     if (write(Handle,&Header,sizeof(Header)) != sizeof(Header)) {
  89.         close(Handle);
  90.         return NULL;
  91.     }
  92.  
  93.     Block.ID = ID_SONG;
  94.     Block.Length = sizeof(Song);
  95.     if (write(Handle,&Block,sizeof(Block)) != sizeof(Block)) {
  96.         close(Handle);
  97.         return NULL;
  98.     }
  99.     if (write(Handle,&Module->Header,Block.Length) != Block.Length) {
  100.         close(Handle);
  101.         return NULL;
  102.     }
  103.  
  104.     for (I = 0; I < Module->Header.NumPatterns; I++) {
  105.         Block.ID = ID_PATT;
  106.         Block.Length = Module->Patterns[I]->Length;
  107.         if (write(Handle,&Block,sizeof(Block)) != sizeof(Block)) {
  108.             close(Handle);
  109.             return NULL;
  110.         }
  111.         if (write(Handle,Module->Patterns[I],Block.Length) != Block.Length) {
  112.             close(Handle);
  113.             return NULL;
  114.         }
  115.     }
  116.  
  117.     for (I = 0; I < Module->Header.NumSamples; I++) {
  118.         Block.ID = ID_INST;
  119.         Block.Length = sizeof(Sample) + Module->Samples[I]->Length;
  120.         if (write(Handle,&Block,sizeof(Block)) != sizeof(Block)) {
  121.             close(Handle);
  122.             return NULL;
  123.         }
  124.         if (write(Handle,Module->Samples[I],sizeof(Sample)) != sizeof(Sample)) {
  125.             close(Handle);
  126.             return NULL;
  127.         }
  128.         if (write(Handle,Module->Samples[I]->DataPtr,Module->Samples[I]->Length) != Module->Samples[I]->Length) {
  129.             close(Handle);
  130.             return NULL;
  131.         }
  132.     }
  133.  
  134.     close(Handle);
  135.     return Module;
  136. }
  137.  
  138. /****************************************************************************
  139. *
  140. * Function:     dSaveSample
  141. * Parameters:   Filename    - DOS file name
  142. *               SampPtr     - sample structure
  143. *
  144. * Returns:      Sample structure or NULL if error.
  145. *
  146. ****************************************************************************/
  147.  
  148. Sample *dSaveSample(char *Filename, Sample *SampPtr)
  149. {
  150.     int Handle;
  151.  
  152.     if ((Handle = open(Filename,O_CREAT|O_WRONLY|O_BINARY,S_IRWXU)) < 0)
  153.         return NULL;
  154.     if (write(Handle,SampPtr->DataPtr,SampPtr->Length) != SampPtr->Length) {
  155.         close(Handle);
  156.         return NULL;
  157.     }
  158.     close(Handle);
  159.     return SampPtr;
  160. }
  161.  
  162. /****************************************************************************
  163. *
  164. * Function:     dDumpModule
  165. * Parameters:   Module - Music module
  166. *
  167. * Description:  Dump module information on screen.
  168. *
  169. ****************************************************************************/
  170.  
  171. void dDumpModule(DSM *Module)
  172. {
  173.     int I;
  174.  
  175.     printf( "\nRIFF/DSMF Module File:\n"
  176.             "\n"
  177.             "Module name            \"%s\"\n"
  178.             "Order list length      %d\n"
  179.             "Number of patterns     %d\n"
  180.             "Number of samples      %d\n"
  181.             "Number of tracks       %d\n"
  182.             "Global/Master volume   %d/%d\n"
  183.             "Initial speed/tempo    %d/%d\n",
  184.             Module->Header.ModuleName,
  185.             Module->Header.NumOrders,
  186.             Module->Header.NumPatterns,
  187.             Module->Header.NumSamples,
  188.             Module->Header.NumTracks,
  189.             Module->Header.GlobalVolume,
  190.             Module->Header.MasterVolume,
  191.             Module->Header.InitTempo,
  192.             Module->Header.InitBPM);
  193.  
  194.     printf( "\n"
  195.             "Instrument table:\n"
  196.             "\n");
  197.     for (I = 0; I < Module->Header.NumSamples; I++) {
  198.         printf( "Sample %d:\n"
  199.                 "    Instrument name          \"%s\"\n"
  200.                 "    Middle-c frequency       %d Hz\n"
  201.                 "    Default volume           %d\n"
  202.                 "    Sample length            %ld\n"
  203.                 "    Loop start/end points    %ld/%ld\n"
  204.                 "    Bit flags                0x%02x ( %s%s%s%s%s )\n\n",
  205.                 I+1,
  206.                 Module->Samples[I]->SampleName,
  207.                 Module->Samples[I]->Rate,
  208.                 Module->Samples[I]->Volume,
  209.                 Module->Samples[I]->Length,
  210.                 Module->Samples[I]->LoopStart,
  211.                 Module->Samples[I]->LoopEnd,
  212.                 Module->Samples[I]->Flags,
  213.                 Module->Samples[I]->Flags & SF_16BITS ? "16-BIT" : "8-BIT",
  214.                 Module->Samples[I]->Flags & SF_SIGNED ? " SIGNED" : " UNSIGNED",
  215.                 Module->Samples[I]->Flags & SF_DELTA ? " DELTA" : "",
  216.                 Module->Samples[I]->Flags & SF_LOOPED ? " LOOPED" : "",
  217.                 Module->Samples[I]->Flags & SF_LIBRARY ? " LIBRARY" : "");
  218.     }
  219.     printf("\n");
  220. }
  221.  
  222. /****************************************************************************
  223. *
  224. * Function:     dOptPattern
  225. * Parameters:   Patt    - pattern pointer
  226. *               TrkUsed - tracks used array
  227. *               SmpUsed - samples used array
  228. *               Hdr     - module header
  229. *
  230. * Description:  Optimize and check music pattern.
  231. *
  232. ****************************************************************************/
  233.  
  234. void dOptPattern(Pattern *Patt, int *TrkUsed, int *SmpUsed, Song *Hdr)
  235. {
  236.     unsigned char *ptr,*endptr;
  237.     unsigned row,track,flags,sample;
  238.  
  239.     if (!Patt) {
  240.         printf("FATAL ERROR: null pattern address!\n");
  241.         exit(EXIT_FAILURE);
  242.     }
  243.     ptr = Patt->Data;
  244.     endptr = ((char*)Patt)+Patt->Length;
  245.     for (row = 0; row < 64; row++) {
  246.         while ((flags = *ptr++) != 0) {
  247.             if (ptr >= endptr) {
  248.                 printf("FATAL ERROR: pattern is corrupted!\n");
  249.                 exit(EXIT_FAILURE);
  250.             }
  251.             track = flags & 0x0F;
  252.             TrkUsed[track] = 1;
  253.             if (flags & 0x80) {
  254.                 if (*ptr > 96) {
  255.                     printf("WARNING: invalid note index (%d).\n",*ptr);
  256.                     *ptr = 0;
  257.                 }
  258.                 ptr++;
  259.             }
  260.             if (flags & 0x40) {
  261.                 if ((sample = *ptr) > Hdr->NumSamples) {
  262.                     printf("WARNING: invalid sample reference (%d).\n",sample);
  263.                     *ptr = 0;
  264.                 }
  265.                 else SmpUsed[sample] = 1;
  266.                 ptr++;
  267.             }
  268.             if (flags & 0x20) {
  269.                 if (*ptr > 64) {
  270.                     printf("WARNING: invalid volume level (%d).\n",*ptr);
  271.                     *ptr = 64;
  272.                 }
  273.                 ptr++;
  274.             }
  275.             if (flags & 0x10) {
  276.                 if (*ptr >= 16) {
  277.                     printf("WARNING: invalid protracker command (%1x%02x).\n",ptr[0],ptr[1]);
  278.                     *ptr++ = 0;
  279.                     *ptr++ = 0;
  280.                 }
  281.                 else ptr += 2;
  282.             }
  283.         }
  284.     }
  285. }
  286.  
  287. /****************************************************************************
  288. *
  289. * Function:     dMapPattern
  290. * Parameters:   Patt    - pattern pointer
  291. *               TrkMap  - tracks remap table
  292. *
  293. * Description:  Remap tracks in a pattern sheet.
  294. *
  295. ****************************************************************************/
  296.  
  297. void dMapPattern(Pattern *Patt, int *TrkMap)
  298. {
  299.     unsigned char *ptr;
  300.     unsigned row,flags;
  301.  
  302.     ptr = Patt->Data;
  303.     for (row = 0; row < 64; row++) {
  304.         while ((flags = *ptr) != 0) {
  305.             *ptr++ = (flags & 0xF0) | (TrkMap[flags & 0x0F] & 0x0F);
  306.             if (flags & 0x80) ptr++;
  307.             if (flags & 0x40) ptr++;
  308.             if (flags & 0x20) ptr++;
  309.             if (flags & 0x10) ptr += 2;
  310.         }
  311.     }
  312. }
  313.  
  314. /****************************************************************************
  315. *
  316. * Function:     dOptSample
  317. * Parameters:   SampPtr - sample structure
  318. *               Packed  - delta packed sample flag
  319. *
  320. * Description:  Optimize and check sample structures.
  321. *
  322. ****************************************************************************/
  323.  
  324. void dOptSample(Sample *SampPtr, int Packed)
  325. {
  326.     long count;
  327.     signed char *ptr,oldsample,newsample;
  328.  
  329.     if (!SampPtr->Length) {
  330.         /* clear sample information if there is no data */
  331.         SampPtr->Flags = 0;
  332.         SampPtr->Volume = 0;
  333.         SampPtr->LoopStart = SampPtr->LoopEnd = 0;
  334.         SampPtr->Rate = 0;
  335.     }
  336.     if (SampPtr->Length && !(SampPtr->Flags & SF_SIGNED)) {
  337.         /* the sound system likes signed samples :-) */
  338.         count = SampPtr->Length;
  339.         ptr = (signed char *)SampPtr->DataPtr;
  340.         while (count--) *ptr++ ^= 0x80;
  341.         SampPtr->Flags |= SF_SIGNED;
  342.     }
  343.     if (SampPtr->Length && Packed) {
  344.         count = SampPtr->Length;
  345.         ptr = (signed char *)SampPtr->DataPtr;
  346.         oldsample = 0;
  347.         while (count--) {
  348.             newsample = *ptr;
  349.             *ptr++ -= oldsample;
  350.             oldsample = newsample;
  351.         }
  352.         SampPtr->Flags |= SF_DELTA;
  353.     }
  354.     if (SampPtr->Volume > 64) {
  355.         printf("WARNING: invalid sample default volume (%d).\n", SampPtr->Volume);
  356.         SampPtr->Volume = 64;
  357.     }
  358.     if (SampPtr->Flags & SF_LOOPED) {
  359.         if (SampPtr->LoopEnd > SampPtr->Length) {
  360.             printf("WARNING: invalid sample loop end point.\n");
  361.             SampPtr->LoopEnd = SampPtr->Length;
  362.         }
  363.         if (SampPtr->LoopStart > SampPtr->LoopEnd) {
  364.             printf("WARNING: invalid sample loop start point.\n");
  365.             SampPtr->LoopStart = SampPtr->LoopEnd;
  366.         }
  367.     }
  368.     else {
  369.         SampPtr->LoopStart = SampPtr->LoopEnd = 0;
  370.     }
  371.     if ((SampPtr->Rate < 4000) && (SampPtr->Length)) {
  372.         printf("WARNING: invalid sample frequency.\n");
  373.         SampPtr->Rate = MIDCFREQ;
  374.     }
  375. }
  376.  
  377. /****************************************************************************
  378. *
  379. * Function:     dOptModule
  380. * Parameters:   Module - Music module
  381. *               Packed - samples delta packed flag
  382. *               ReMap  - track remap flag
  383. *
  384. * Description:  Optimize and check music module.
  385. *
  386. ****************************************************************************/
  387.  
  388. void dOptModule(DSM *Module, int Packed, int Remap)
  389. {
  390.     static int PtnUsed[MAXORDERS],PtnMap[MAXORDERS];
  391.     static int TrkUsed[MAXTRACKS],TrkMap[MAXTRACKS];
  392.     static int SmpUsed[MAXSAMPLES+1];
  393.     int I,J;
  394.  
  395.     /* check out the module header */
  396.     if (strlen(Module->Header.ModuleName) >= sizeof(Module->Header.ModuleName)) {
  397.         printf("FATAL ERROR: module header is corrupted!\n");
  398.         exit(EXIT_FAILURE);
  399.     }
  400.     if (Module->Header.NumOrders == 0 || Module->Header.NumOrders > MAXORDERS) {
  401.         printf("FATAL ERROR: invalid orderlist length!\n");
  402.         exit(EXIT_FAILURE);
  403.     }
  404.     if (Module->Header.NumSamples > MAXSAMPLES) {
  405.         printf("FATAL ERROR: too many samples!\n");
  406.         exit(EXIT_FAILURE);
  407.     }
  408.     if (Module->Header.NumPatterns > MAXORDERS) {
  409.         printf("FATAL ERROR: too many patterns!\n");
  410.         exit(EXIT_FAILURE);
  411.     }
  412.     if (Module->Header.NumTracks == 0 || Module->Header.NumTracks > MAXTRACKS) {
  413.         printf("FATAL ERROR: invalid number of tracks!\n");
  414.         exit(EXIT_FAILURE);
  415.     }
  416.     if (Module->Header.GlobalVolume > 64 || Module->Header.MasterVolume < 16) {
  417.         printf("FATAL ERROR: invalid global/master volume!\n");
  418.         exit(EXIT_FAILURE);
  419.     }
  420.     if (Module->Header.InitTempo >= 32 || Module->Header.InitBPM < 32) {
  421.         printf("FATAL ERROR: invalid speed/tempo!\n");
  422.         exit(EXIT_FAILURE);
  423.     }
  424.  
  425.     /* search used and unused patterns */
  426.     memset(PtnUsed,0,sizeof(PtnUsed));
  427.     for (I = 0; I < Module->Header.NumOrders; I++) {
  428.         if ((J = Module->Header.Orders[I]) < Module->Header.NumPatterns)
  429.             PtnUsed[J] = 1;
  430.         else if (J != 0xFF) {
  431.             printf("WARNING: invalid pattern reference (%d).\n",J);
  432.         }
  433.     }
  434.  
  435.     /* build the pattern remap table and update the order list */
  436.     for (I = J = 0; I < MAXORDERS; I++)
  437.         PtnMap[I] = PtnUsed[I] ? J++ : 0xFF;
  438.     for (I = 0; I < MAXORDERS; I++) {
  439.         if (I < Module->Header.NumOrders) {
  440.             if ((J = Module->Header.Orders[I]) < Module->Header.NumPatterns) {
  441.                 Module->Header.Orders[I] = PtnMap[J];
  442.             }
  443.             else {
  444.                 Module->Header.Orders[I] = 0xFF;
  445.             }
  446.         }
  447.         else {
  448.             Module->Header.Orders[I] = 0xFF;
  449.         }
  450.     }
  451.  
  452.     /* free unused patterns and remap pattern array */
  453.     for (I = 0; I < Module->Header.NumPatterns; I++) {
  454.         if (PtnUsed[I]) {
  455.             Module->Patterns[PtnMap[I]] = Module->Patterns[I];
  456.         }
  457.         else {
  458.             free(Module->Patterns[I]);
  459.             Module->Patterns[I] = NULL;
  460.         }
  461.     }
  462.  
  463.     /* update number of patterns field */
  464.     for (I = 0; I < Module->Header.NumPatterns; I++)
  465.         if (!Module->Patterns[I]) break;
  466.     if (I == 0) {
  467.         printf("FATAL ERROR: no patterns in module!\n");
  468.         exit(EXIT_FAILURE);
  469.     }
  470.     if (I < Module->Header.NumPatterns) {
  471.         printf("WARNING: removing %d unused pattern(s).\n", Module->Header.NumPatterns-I);
  472.         Module->Header.NumPatterns = I;
  473.     }
  474.  
  475.     /* update order list length */
  476.     for (I = J = 0; I < Module->Header.NumOrders; I++)
  477.         if (Module->Header.Orders[I] != 0xFF) J = I+1;
  478.     if (J < Module->Header.NumOrders) {
  479.         printf("WARNING: removing %d unused order(s).\n",Module->Header.NumOrders-J);
  480.         Module->Header.NumOrders = J;
  481.     }
  482.  
  483.     /* optimize and check sample structures */
  484.     for (I = 0; I < Module->Header.NumSamples; I++) {
  485.         dOptSample(Module->Samples[I],Packed);
  486.     }
  487.  
  488.     /* optimize and check patterns and search used/unused samples */
  489.     memset(TrkUsed,0,sizeof(TrkUsed));
  490.     memset(SmpUsed,0,sizeof(SmpUsed));
  491.     for (I = 0; I < Module->Header.NumPatterns; I++) {
  492.         dOptPattern(Module->Patterns[I],TrkUsed,SmpUsed,&Module->Header);
  493.     }
  494.  
  495.     /* remove unused samples */
  496.     for (I = J = 0; I < Module->Header.NumSamples; I++) {
  497.         if (!SmpUsed[I+1] && Module->Samples[I]->Length) {
  498.             if (Module->Samples[I]->DataPtr) free(Module->Samples[I]->DataPtr);
  499.             Module->Samples[I]->DataPtr = NULL;
  500.             Module->Samples[I]->Flags = 0;
  501.             Module->Samples[I]->Volume = 0;
  502.             Module->Samples[I]->Length = 0;
  503.             Module->Samples[I]->LoopStart = Module->Samples[I]->LoopEnd = 0;
  504.             Module->Samples[I]->Rate = 0;
  505.             J++;
  506.         }
  507.     }
  508.     if (J) {
  509.         printf("WARNING: removing %d unused sample(s).\n",J);
  510.     }
  511.  
  512.     /* remove unused tracks */
  513.     if (Remap) {
  514.         for (I = J = 0; I < MAXTRACKS; I++)
  515.             TrkMap[I] = TrkUsed[I] ? J++ : 0xFF;
  516.         if (Module->Header.NumTracks != J)
  517.             printf("WARNING: removing %d unused track(s).\n", Module->Header.NumTracks-J);
  518.         Module->Header.NumTracks = J;
  519.         for (I = 0; I < MAXTRACKS; I++) {
  520.             if (TrkMap[I] != 0xFF)
  521.                 Module->Header.ChanMap[TrkMap[I]] =
  522.                             Module->Header.ChanMap[I];
  523.         }
  524.         for (I = Module->Header.NumTracks; I < MAXTRACKS; I++)
  525.             Module->Header.ChanMap[I] = 0xFF;
  526.         for (I = 0; I < Module->Header.NumPatterns; I++)
  527.             dMapPattern(Module->Patterns[I],TrkMap);
  528.     }
  529. }
  530.  
  531.  
  532.  
  533. int main(int argc, char *argv[])
  534. {
  535.     DSM *module;
  536.     Sample *sample;
  537.     char path[_MAX_PATH],drive[_MAX_DRIVE];
  538.     char dir[_MAX_DIR],name[_MAX_FNAME],ext[_MAX_EXT];
  539.     int verbose,looped,packed,remap,form,i;
  540.  
  541.     printf("M2DSM Version 2.01  Copyright (C) 1995 Carlos Hasan\n");
  542.  
  543.     verbose = looped = packed = remap = 0;
  544.     strcpy(path,"");
  545.     for (i = 1; i < argc; i++) {
  546.         if (!strcmp(argv[i],"-v")) verbose = 1;
  547.         else if (!strcmp(argv[i],"-l")) looped = 1;
  548.         else if (!strcmp(argv[i],"-p")) packed = 1;
  549.         else if (!strcmp(argv[i],"-t")) remap = 1;
  550.         else if (!strlen(path)) strcpy(path,argv[i]);
  551.     }
  552.  
  553.     if (strlen(path) == 0) {
  554.         printf( "use: M2DSM [options] file[.mod|.s3m|.mtm|.669|.stm|.wav|.voc|.iff|.raw]\n"
  555.                 "options:\n"
  556.                 "   -v  verbose mode\n"
  557.                 "   -l  enable looping on modules\n"
  558.                 "   -p  delta pack sample data\n"
  559.                 "   -t  remove unused tracks\n"
  560.                 "M2DSM convert MOD, S3M, MTM, 669, STM and DSM to RIFF/DSMF module files\n"
  561.                 "and WAV, VOC, IFF and RAW to 8-bit signed RAW sample files.\n");
  562.         exit(EXIT_FAILURE);
  563.     }
  564.  
  565.     strupr(path);
  566.     _splitpath(path,drive,dir,name,ext);
  567.     if (*ext == 0) strcpy(ext,".MOD");
  568.     _makepath(path, drive, dir, name, ext);
  569.  
  570.     if (!strcmp(ext,".DSM")) form = FORM_DSM;
  571.     else if (!strcmp(ext,".MOD")) form = FORM_MOD;
  572.     else if (!strcmp(ext,".S3M")) form = FORM_S3M;
  573.     else if (!strcmp(ext,".MTM")) form = FORM_MTM;
  574.     else if (!strcmp(ext,".669")) form = FORM_669;
  575.     else if (!strcmp(ext,".STM")) form = FORM_STM;
  576.     else if (!strcmp(ext,".WAV")) form = FORM_WAV;
  577.     else if (!strcmp(ext,".VOC")) form = FORM_VOC;
  578.     else if (!strcmp(ext,".IFF")) form = FORM_IFF;
  579.     else {
  580.         printf("FATAL ERROR: unknown module/sample file format (%s).\n",path);
  581.         exit(EXIT_FAILURE);
  582.     }
  583.  
  584.     if (form < FORM_WAV) {
  585.         printf("Loading %s module file: %s\n",
  586.             form == FORM_DSM ? "RIFF/DSMF" :
  587.             form == FORM_MOD ? "Protracker/Fastracker" :
  588.             form == FORM_S3M ? "Scream Tracker 3.0" :
  589.             form == FORM_MTM ? "Multitracker 1.0" :
  590.             form == FORM_669 ? "Composer 669" :
  591.             form == FORM_STM ? "Scream Tracker 2.0" : "", path);
  592.  
  593.         if (!(module = dImportModule(path,form))) {
  594.             printf("FATAL ERROR (%03d): cannot load %s module file: %s.\n",
  595.                 dError, path, dErrorMsg[dError]);
  596.             exit(EXIT_FAILURE);
  597.         }
  598.  
  599.         /* optimze and check module */
  600.         dOptModule(module,packed,remap);
  601.         if (looped) {
  602.             if ((module->Header.ReStart < module->Header.NumOrders) &&
  603.                 (module->Header.ReStart != 0))
  604.                 printf("WARNING: restart position modified.\n");
  605.             module->Header.ReStart = 0;
  606.         }
  607.  
  608.         strupr(path);
  609.         _makepath(path, "", "", name, ".DSM");
  610.  
  611.         printf("Saving RIFF/DSMF module file: %s\n",path);
  612.         if (!dSaveModule(path,module)) {
  613.             printf("FATAL ERROR: cannot create/write file: %s\n",path);
  614.             exit(EXIT_FAILURE);
  615.         }
  616.  
  617.         if (verbose) dDumpModule(module);
  618.     }
  619.     else {
  620.         printf("Loading %s sample file: %s\n",
  621.             form == FORM_WAV ? "Microsoft WAVE" :
  622.             form == FORM_VOC ? "Creative Labs Voice" :
  623.             form == FORM_IFF ? "Amiga IFF/8SVX" : "", path);
  624.  
  625.         if (!(sample = dImportSample(path,form))) {
  626.             printf("FATAL ERROR (%03d): cannot load %s sample file: %s.\n",
  627.                 dError, path, dErrorMsg[dError]);
  628.             exit(EXIT_FAILURE);
  629.         }
  630.  
  631.         /* optimze and check sample */
  632.         dOptSample(sample,packed);
  633.  
  634.         strupr(path);
  635.         _makepath(path, "", "", name, ".RAW");
  636.  
  637.         printf("Saving 8-bit signed RAW sample file: %s\n",path);
  638.         if (!dSaveSample(path,sample)) {
  639.             printf("FATAL ERROR: cannot create/write file: %s\n",path);
  640.             exit(EXIT_FAILURE);
  641.         }
  642.     }
  643.     return EXIT_SUCCESS;
  644. }
  645.