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