home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / goattracker_2.73.zip / src / betaconv.c < prev    next >
C/C++ Source or Header  |  2014-07-23  |  9KB  |  359 lines

  1. /*
  2.  * GoatTracker V2.0 beta songconvertor
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <ctype.h>
  9. #include "bme_end.h"
  10. #include "gcommon.h"
  11.  
  12. #define MAX_SPLITS 16
  13.  
  14. INSTR instr[MAX_INSTR];
  15. unsigned char ltable[3][MAX_TABLELEN*2];
  16. unsigned char rtable[3][MAX_TABLELEN*2];
  17. unsigned char songorder[MAX_SONGS][MAX_CHN][MAX_SONGLEN+2];
  18. unsigned char pattern[MAX_PATT][MAX_PATTROWS*4+4];
  19. unsigned char songname[MAX_STR];
  20. unsigned char authorname[MAX_STR];
  21. unsigned char copyrightname[MAX_STR];
  22. int pattlen[MAX_PATT];
  23. int songlen[MAX_SONGS][MAX_CHN];
  24.  
  25. int highestusedpattern = 0;
  26. int highestusedinstr = 0;
  27.  
  28. int wavelen = 0, pulselen = 0, filtlen = 0;
  29.  
  30. int vibdepth = 0, pulse = 0;
  31.  
  32. int loadsong(char *name);
  33. int savesong(char *name);
  34. void countpatternlengths(void);
  35. void clearsong(void);
  36. int gettablelen(int num);
  37.  
  38. int main(int argc, char **argv)
  39. {
  40.   if (argc < 3)
  41.   {
  42.     printf("Usage: BETACONV <source> <destination> [vibdepth] [pulse]\n"
  43.            "[vibdepth] decides whether to halve vibdepth (1=yes 0=no), default 0\n"
  44.            "[pulse] decides whether to halve pulse speed (1=yes 0=no), default 0\n\n"
  45.            "Converts GT2 early beta (47 instr.) song to GT2 current format (63 instr.)\n"
  46.            "Optionally, halves vibrato depths and pulse speeds.\n");
  47.     return EXIT_FAILURE;
  48.   }
  49.  
  50.   if (argc >= 4)
  51.   {
  52.     sscanf(argv[3], "%u", &vibdepth);
  53.   }
  54.  
  55.   if (argc >= 5)
  56.   {
  57.     sscanf(argv[4], "%u", &pulse);
  58.   }
  59.  
  60.   if (!loadsong(argv[1]))
  61.   {
  62.     printf("ERROR: Couldn't load source song.");
  63.     return EXIT_FAILURE;
  64.   }
  65.   if (!savesong(argv[2]))
  66.   {
  67.     printf("ERROR: Couldn't save destination song.");
  68.     return EXIT_FAILURE;
  69.   }
  70.   return EXIT_SUCCESS;
  71. }
  72.  
  73. int loadsong(char *name)
  74. {
  75.   char ident[4];
  76.   int c;
  77.  
  78.   FILE *srchandle = fopen(name, "rb");
  79.   if (srchandle)
  80.   {
  81.     fread(ident, 4, 1, srchandle);
  82.     if (!memcmp(ident, "GTS2", 4))
  83.     {
  84.       int d;
  85.       unsigned char length;
  86.       unsigned char amount;
  87.       int loadbytes;
  88.       clearsong();
  89.  
  90.       // Read infotexts
  91.       fread(songname, sizeof songname, 1, srchandle);
  92.       fread(authorname, sizeof authorname, 1, srchandle);
  93.       fread(copyrightname, sizeof copyrightname, 1, srchandle);
  94.  
  95.       // Read songorderlists
  96.       amount = fread8(srchandle);
  97.       for (d = 0; d < amount; d++)
  98.       {
  99.         for (c = 0; c < MAX_CHN; c++)
  100.         {
  101.           length = fread8(srchandle);
  102.           loadbytes = length;
  103.           loadbytes++;
  104.           fread(songorder[d][c], loadbytes, 1, srchandle);
  105.         }
  106.       }
  107.       // Read instruments
  108.       for (c = 1; c <= 47; c++)
  109.       {
  110.         instr[c].ad = fread8(srchandle);
  111.         instr[c].sr = fread8(srchandle);
  112.         instr[c].ptr[WTBL] = fread8(srchandle);
  113.         instr[c].ptr[PTBL] = fread8(srchandle);
  114.         instr[c].ptr[FTBL] = fread8(srchandle);
  115.         instr[c].vibdelay = fread8(srchandle);
  116.         instr[c].ptr[STBL] = fread8(srchandle);
  117.         if (vibdepth)
  118.           instr[c].ptr[STBL] = (instr[c].ptr[STBL] & 0xf0) | ((instr[c].ptr[STBL] & 0x0f) >> 1);
  119.         instr[c].gatetimer = fread8(srchandle);
  120.         instr[c].firstwave = fread8(srchandle);
  121.         fread(&instr[c].name, MAX_INSTRNAMELEN, 1, srchandle);
  122.       }
  123.       // Read tables
  124.       for (c = 0; c < 3; c++)
  125.       {
  126.         loadbytes = fread8(srchandle);
  127.         fread(ltable[c], loadbytes, 1, srchandle);
  128.         fread(rtable[c], loadbytes, 1, srchandle);
  129.         if ((c == PTBL) && (pulse))
  130.         {
  131.           for (d = 0; d < loadbytes; d++)
  132.           {
  133.             if ((ltable[PTBL][d]) && (ltable[PTBL][d] < 0x80))
  134.             {
  135.               // Halve positive pulsespeed
  136.               if (rtable[PTBL][d] < 0x80)
  137.               {
  138.                 rtable[PTBL][d] >>= 1;
  139.               }
  140.               else
  141.               {
  142.                 rtable[PTBL][d] >>= 1;
  143.                 rtable[PTBL][d] |= 0x80;
  144.               }
  145.             }
  146.           }
  147.         }
  148.       }
  149.       // Read patterns
  150.       amount = fread8(srchandle);
  151.       for (c = 0; c < amount; c++)
  152.       {
  153.         length = fread8(srchandle);
  154.         fread(pattern[c], length*4, 1, srchandle);
  155.         for (d = 0; d < length; d++)
  156.         {
  157.           // Convert notes in patterns to new format
  158.           if (pattern[c][d*4] == 0xb0) pattern[c][d*4] = REST;
  159.           if ((pattern[c][d*4] >= 0x50) && (pattern[c][d*4] <= 0xaf))
  160.           {
  161.             pattern[c][d*4] += 0x10;
  162.             if (pattern[c][d*4] > REST) pattern[c][d*4] = REST;
  163.           }
  164.  
  165.           // Halve vibrato depth
  166.           if ((vibdepth) && (pattern[c][d*4+2] == 0x4))
  167.             pattern[c][d*4+3] = (pattern[c][d*4+3] & 0xf0) | ((pattern[c][d*4+3] & 0x0f) >> 1);
  168.         }
  169.       }
  170.       countpatternlengths();
  171.       for (c = 1; c < MAX_INSTR; c++)
  172.       {
  173.         if ((instr[c].ad) || (instr[c].sr) || (instr[c].ptr[0]) || (instr[c].ptr[1]) ||
  174.             (instr[c].ptr[2]) || (instr[c].vibdelay) || (instr[c].ptr[STBL]))
  175.         {
  176.           if (c > highestusedinstr) highestusedinstr = c;
  177.         }
  178.       }
  179.       fclose(srchandle);
  180.       return 1;
  181.     }
  182.     fclose(srchandle);
  183.   }
  184.   return 0;
  185. }
  186.  
  187. int savesong(char *name)
  188. {
  189.   char ident[] = {'G', 'T', 'S', '2'};
  190.   FILE *handle;
  191.   int c;
  192.  
  193.   handle = fopen(name, "wb");
  194.   if (handle)
  195.   {
  196.     int d;
  197.     unsigned char length;
  198.     unsigned char amount;
  199.     int writebytes;
  200.     fwrite(ident, 4, 1, handle);
  201.  
  202.     // Write infotexts
  203.     fwrite(songname, sizeof songname, 1, handle);
  204.     fwrite(authorname, sizeof authorname, 1, handle);
  205.     fwrite(copyrightname, sizeof copyrightname, 1, handle);
  206.  
  207.     // Determine amount of songs to be saved
  208.     c = 0;
  209.     for (;;)
  210.     {
  211.       if (c == MAX_SONGS) break;
  212.       if ((!songlen[c][0])||
  213.         (!songlen[c][1])||
  214.         (!songlen[c][2])) break;
  215.       c++;
  216.     }
  217.     amount = c;
  218.  
  219.     fwrite8(handle, amount);
  220.     // Write songorderlists
  221.     for (d = 0; d < amount; d++)
  222.     {
  223.       for (c = 0; c < MAX_CHN; c++)
  224.       {
  225.         length = songlen[d][c]+1;
  226.         fwrite8(handle, length);
  227.         writebytes = length;
  228.         writebytes++;
  229.         fwrite(songorder[d][c], writebytes, 1, handle);
  230.       }
  231.     }
  232.     // Write instruments
  233.     fwrite8(handle, highestusedinstr);
  234.     for (c = 1; c <= highestusedinstr; c++)
  235.     {
  236.       fwrite8(handle, instr[c].ad);
  237.       fwrite8(handle, instr[c].sr);
  238.       fwrite8(handle, instr[c].ptr[WTBL]);
  239.       fwrite8(handle, instr[c].ptr[PTBL]);
  240.       fwrite8(handle, instr[c].ptr[FTBL]);
  241.       fwrite8(handle, instr[c].vibdelay);
  242.       fwrite8(handle, instr[c].ptr[STBL]);
  243.       fwrite8(handle, instr[c].gatetimer);
  244.       fwrite8(handle, instr[c].firstwave);
  245.       fwrite(&instr[c].name, MAX_INSTRNAMELEN, 1, handle);
  246.     }
  247.     // Write tables
  248.     for (c = 0; c < 3; c++)
  249.     {
  250.       writebytes = gettablelen(c);
  251.       fwrite8(handle, writebytes);
  252.       fwrite(ltable[c], writebytes, 1, handle);
  253.       fwrite(rtable[c], writebytes, 1, handle);
  254.     }
  255.     // Write patterns
  256.     amount = highestusedpattern + 1;
  257.     fwrite8(handle, amount);
  258.     for (c = 0; c < amount; c++)
  259.     {
  260.       length = pattlen[c]+1;
  261.       fwrite8(handle, length);
  262.       fwrite(pattern[c], length*4, 1, handle);
  263.     }
  264.  
  265.     fclose(handle);
  266.     return 1;
  267.   }
  268.   return 0;
  269. }
  270.  
  271. void countpatternlengths(void)
  272. {
  273.   int c, d, e;
  274.  
  275.   highestusedpattern = 0;
  276.   highestusedinstr = 0;
  277.   for (c = 0; c < MAX_PATT; c++)
  278.   {
  279.     for (d = 0; d <= MAX_PATTROWS; d++)
  280.     {
  281.       if (pattern[c][d*4] == ENDPATT) break;
  282.       if ((pattern[c][d*4] != REST) || (pattern[c][d*4+1]) || (pattern[c][d*4+2]) || (pattern[c][d*4+3]))
  283.         highestusedpattern = c;
  284.       if (pattern[c][d*4+1] > highestusedinstr) highestusedinstr = pattern[c][d*4+1];
  285.     }
  286.     pattlen[c] = d;
  287.   }
  288.   for (e = 0; e < MAX_SONGS; e++)
  289.   {
  290.     for (c = 0; c < MAX_CHN; c++)
  291.     {
  292.       for (d = 0; d < MAX_SONGLEN; d++)
  293.       {
  294.         if (songorder[e][c][d] >= LOOPSONG) break;
  295.         if (songorder[e][c][d] < MAX_PATT)
  296.         {
  297.           if (songorder[e][c][d] > highestusedpattern)
  298.             highestusedpattern = songorder[e][c][d];
  299.         }
  300.       }
  301.       songlen[e][c] = d;
  302.     }
  303.   }
  304. }
  305.  
  306. void clearsong(void)
  307. {
  308.   int c;
  309.  
  310.   for (c = 0; c < MAX_CHN; c++)
  311.   {
  312.     int d;
  313.     for (d = 0; d < MAX_SONGS; d++)
  314.     {
  315.       memset(&songorder[d][c][0], 0, MAX_SONGLEN);
  316.       if (!d)
  317.       {
  318.         songorder[d][c][0] = c;
  319.         songorder[d][c][1] = LOOPSONG;
  320.         songorder[d][c][2] = 0;
  321.       }
  322.       else
  323.       {
  324.         songorder[d][c][0] = LOOPSONG;
  325.         songorder[d][c][1] = 0;
  326.       }
  327.     }
  328.   }
  329.   memset(songname, 0, sizeof songname);
  330.   memset(authorname, 0, sizeof authorname);
  331.   memset(copyrightname, 0, sizeof copyrightname);
  332.  
  333.   for (c = 0; c < MAX_PATT; c++)
  334.   {
  335.     int d;
  336.     memset(&pattern[c][0], 0, MAX_PATTROWS*4);
  337.     for (d = 0; d < MAX_PATTROWS; d++) pattern[c][d*4] = REST;
  338.     for (d = MAX_PATTROWS; d <= MAX_PATTROWS; d++) pattern[c][d*4] = ENDPATT;
  339.   }
  340.   for (c = 0; c < MAX_INSTR; c++)
  341.   {
  342.     memset(&instr[c], 0, sizeof(INSTR));
  343.   }
  344.   memset(ltable, 0, sizeof ltable);
  345.   memset(rtable, 0, sizeof rtable);
  346.   countpatternlengths();
  347. }
  348.  
  349. int gettablelen(int num)
  350. {
  351.   int c;
  352.  
  353.   for (c = MAX_TABLELEN-1; c >= 0; c--)
  354.   {
  355.     if (ltable[num][c] | rtable[num][c]) break;
  356.    }
  357.    return c+1;
  358. }
  359.