home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / goattracker_2.70_stereo.zip / src / ss2stereo.c < prev   
C/C++ Source or Header  |  2008-04-01  |  14KB  |  549 lines

  1. /*
  2.  * GoatTracker V2.xx pattern splitter
  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. char ident[4];
  16. unsigned char ltable[4][MAX_TABLELEN*2];
  17. unsigned char rtable[4][MAX_TABLELEN*2];
  18. unsigned char songorder[MAX_SONGS][MAX_CHN][MAX_SONGLEN+2];
  19. unsigned char destsongorder[MAX_SONGS][MAX_CHN][MAX_SONGLEN+2];
  20. unsigned char ordermaptbl[MAX_SONGLEN+2];
  21. unsigned char pattern[MAX_PATT][MAX_PATTROWS*4+4];
  22. unsigned char destpattern[MAX_PATT+1][MAX_PATTROWS*4+4];
  23. unsigned char songname[MAX_STR];
  24. unsigned char authorname[MAX_STR];
  25. unsigned char copyrightname[MAX_STR];
  26. int pattlen[MAX_PATT];
  27. int songlen[MAX_SONGS][MAX_CHN];
  28. int destpattlen[MAX_PATT+1];
  29. int destsonglen[MAX_SONGS][MAX_CHN];
  30. int destpattsplits[MAX_PATT+1];
  31. int patternmaptable[MAX_PATT][MAX_SPLITS];
  32. int tables = 0;
  33.  
  34. int dp;
  35. int highestusedpattern = 0;
  36. int highestusedinstr = 0;
  37. int targetlen = 16;
  38.  
  39. int wavelen = 0, pulselen = 0, filtlen = 0;
  40.  
  41. int main(int argc, char **argv);
  42. int loadsong(char *name);
  43. int savesong(char *name);
  44. int processsong(void);
  45. void countpatternlengths(void);
  46. void countdestpatternlengths(void);
  47. void clearsong(void);
  48. int gettablelen(int num);
  49.  
  50. int main(int argc, char **argv)
  51. {
  52.   if (argc < 3)
  53.   {
  54.     printf("Usage: SS2STEREO <source> <destination> [length]\n\n"
  55.            "Splits patterns of the song into smaller patterns with [length] rows,\n"
  56.            "searching for possible duplicates and probably making the song take less\n"
  57.            "memory. For safety reasons source & destination cannot be same, because\n"
  58.            "a splitted song is harder to edit. Always keep the original!\n\n"
  59.            "Default length is 16.\n");
  60.     return 1;
  61.   }
  62.   if (!strcmp(argv[1], argv[2]))
  63.   {
  64.     printf("ERROR: Source and destination are not allowed to be the same.");
  65.     return 1;
  66.   }
  67.  
  68.   if (argc >= 4)
  69.   {
  70.     sscanf(argv[3], "%u", &targetlen);
  71.     if (targetlen < 1) targetlen = 1;
  72.     if (targetlen > MAX_PATTROWS) targetlen = MAX_PATTROWS;
  73.   }
  74.  
  75.   if (!loadsong(argv[1]))
  76.   {
  77.     printf("ERROR: Couldn't load source song.");
  78.     return 1;
  79.   }
  80.   if (!processsong())
  81.   {
  82.     return 1;
  83.   }
  84.   if (!savesong(argv[2]))
  85.   {
  86.     printf("ERROR: Couldn't save destination song.");
  87.     return 1;
  88.   }
  89.   return 0;
  90. }
  91.  
  92. int processsong(void)
  93. {
  94.   int c,d,e;
  95.   int splitsize;
  96.   int songs;
  97.   int dsl;
  98.  
  99.   dp = 0; // Destination patterns
  100.  
  101.   for (c = 0; c <= highestusedpattern; c++)
  102.   {
  103.     destpattsplits[c] = 0;
  104.     splitsize = targetlen;
  105.     while (pattlen[c] / splitsize > MAX_SPLITS) splitsize *= 2;
  106.     if (pattlen[c] <= splitsize) splitsize = pattlen[c];
  107.  
  108.     d = 0;
  109.     while (d < pattlen[c])
  110.     {
  111.       int remain = pattlen[c] - d;
  112.       int splitfound = 0;
  113.  
  114.       // Check existing patterns for matches
  115.       for (e = 0; e < dp; e++)
  116.       {
  117.         if ((destpattlen[e] <= remain) && (destpattlen[e] >= splitsize) && (!memcmp(&pattern[c][d*4], destpattern[e], destpattlen[e]*4)))
  118.         {
  119.           patternmaptable[c][destpattsplits[c]] = e;
  120.           destpattsplits[c]++;
  121.           d += destpattlen[e];
  122.           splitfound = 1;
  123.           break;
  124.         }
  125.       }
  126.       if (!splitfound)
  127.       {
  128.         // If less than 2 splits left, do in one part
  129.         if (remain < splitsize * 2)
  130.         {
  131.           memcpy(destpattern[dp], &pattern[c][d*4], remain*4);
  132.           destpattern[dp][remain*4] = ENDPATT;
  133.           destpattern[dp][remain*4+1] = 0;
  134.           destpattern[dp][remain*4+2] = 0;
  135.           destpattern[dp][remain*4+3] = 0;
  136.           destpattlen[dp] = remain;
  137.           patternmaptable[c][destpattsplits[c]] = dp;
  138.           destpattsplits[c]++;
  139.           d += remain;
  140.           dp++;
  141.         }
  142.         else
  143.         {
  144.           memcpy(destpattern[dp], &pattern[c][d*4], splitsize*4);
  145.           destpattern[dp][splitsize*4] = ENDPATT;
  146.           destpattern[dp][splitsize*4+1] = 0;
  147.           destpattern[dp][splitsize*4+2] = 0;
  148.           destpattern[dp][splitsize*4+3] = 0;
  149.           destpattlen[dp] = splitsize;
  150.           patternmaptable[c][destpattsplits[c]] = dp;
  151.           destpattsplits[c]++;
  152.           d += splitsize;
  153.           dp++;
  154.         }
  155.       }
  156.       // This should never happen 
  157.       if (destpattsplits[c] >= MAX_SPLITS)
  158.       {
  159.         printf("ERROR: Internal error, too many splits!");
  160.         return 0;
  161.       }
  162.       // This might happen :-) 
  163.       if (dp > MAX_PATT)
  164.       {
  165.         printf("ERROR: 255 patterns exceeded!");
  166.         return 0;
  167.       }
  168.     }
  169.   }
  170.  
  171.   // Now convert all songs 
  172.   // Determine amount of songs to be processed
  173.   c = 0;
  174.   for (;;)
  175.   {
  176.     if (c == MAX_SONGS) break;
  177.     if ((!songlen[c][0])||
  178.        (!songlen[c][1])||
  179.        (!songlen[c][2])) break;
  180.     c++;
  181.   }
  182.   songs = c;
  183.  
  184.   for (c = 0; c < songs; c++)
  185.   {
  186.     for (d = 0; d < MAX_CHN; d++)
  187.     {
  188.       dsl = 0;
  189.       for (e = 0; e <= songlen[c][d]+1; e++)
  190.       {
  191.         int pattnum = songorder[c][d][e];
  192.  
  193.         ordermaptbl[e] = dsl;
  194.         if (e < songlen[c][d])
  195.         {
  196.           if (pattnum < MAX_PATT)
  197.           {
  198.             int f;
  199.             for (f = 0; f < destpattsplits[pattnum]; f++)
  200.             {
  201.               destsongorder[c][d][dsl] = patternmaptable[pattnum][f];
  202.               dsl++;
  203.               if (dsl > MAX_SONGLEN)
  204.               {
  205.                 printf("ERROR: Orderlist-length of 254 exceeded!");
  206.                 return 0;
  207.               }
  208.             }
  209.           }
  210.           else
  211.           {
  212.             destsongorder[c][d][dsl] = pattnum;
  213.             dsl++;
  214.             if (dsl > MAX_SONGLEN)
  215.             {
  216.               printf("ERROR: Orderlist-length of 254 exceeded!");
  217.               return 0;
  218.             }
  219.           }
  220.         }
  221.         else
  222.         {
  223.           if (pattnum == LOOPSONG)
  224.           {
  225.             destsongorder[c][d][dsl] = pattnum;
  226.           }
  227.           else
  228.           {
  229.             // Map old orderlist position to new 
  230.             destsongorder[c][d][dsl] = ordermaptbl[pattnum];
  231.           }
  232.           dsl++;
  233.         }
  234.       }
  235.     }
  236.   }
  237.   // Everything ok! 
  238.   countdestpatternlengths();
  239.   {
  240.     int destpatttbl = 0, destpatt = 0, destsong = 0;
  241.     int srcpatttbl = 0, srcpatt = 0, srcsong = 0;
  242.  
  243.     for (c = 0; c < MAX_SONGS; c++)
  244.     {
  245.       if ((songlen[c][0]) && (songlen[c][1]) && (songlen[c][2]))
  246.       {
  247.         for (d = 0; d < MAX_CHN; d++)
  248.         {
  249.           srcsong += songlen[c][d]+1;
  250.           destsong += destsonglen[c][d]+1;
  251.         }
  252.       }
  253.     }
  254.     for (c = 0; c < highestusedpattern; c++)
  255.     {
  256.       srcpatt += pattlen[c]*4 + 4;
  257.       srcpatttbl += 2;
  258.     }
  259.     for (c = 0; c < dp; c++)
  260.     {
  261.       destpatt += destpattlen[c]*4 + 4;
  262.       destpatttbl += 2;
  263.     }
  264.     printf("Processing complete. Results:\n\n"
  265.            "       Songdata Patterns Patt.Tbl Total\n"
  266.            "Before %-8d %-8d %-8d %-8d\n"
  267.            "After  %-8d %-8d %-8d %-8d\n",
  268.            srcsong,srcpatt,srcpatttbl,srcsong+srcpatt+srcpatttbl,
  269.            destsong,destpatt,destpatttbl,destsong+destpatt+destpatttbl);
  270.   }
  271.   return 1;
  272. }
  273.  
  274. int loadsong(char *name)
  275. {
  276.   int c;
  277.  
  278.   FILE *srchandle = fopen(name, "rb");
  279.   if (srchandle)
  280.   {
  281.     fread(ident, 4, 1, srchandle);
  282.     if (!memcmp(ident, "GTS2", 4)) tables = 3;
  283.     if (!memcmp(ident, "GTS3", 4)) tables = 4;
  284.     if (!memcmp(ident, "GTS4", 4)) tables = 4;
  285.     if (!memcmp(ident, "GTS5", 4)) tables = 4;
  286.  
  287.     if (tables)
  288.     {
  289.       int d;
  290.       unsigned char length;
  291.       unsigned char amount;
  292.       int loadbytes;
  293.       clearsong();
  294.  
  295.       // Read infotexts
  296.       fread(songname, sizeof songname, 1, srchandle);
  297.       fread(authorname, sizeof authorname, 1, srchandle);
  298.       fread(copyrightname, sizeof copyrightname, 1, srchandle);
  299.  
  300.       // Read songorderlists
  301.       amount = fread8(srchandle);
  302.       for (d = 0; d < amount; d++)
  303.       {
  304.         for (c = 0; c < MAX_CHN; c++)
  305.         {
  306.           length = fread8(srchandle);
  307.           loadbytes = length;
  308.           loadbytes++;
  309.           fread(songorder[d][c], loadbytes, 1, srchandle);
  310.         }
  311.       }
  312.       // Read instruments
  313.       highestusedinstr = fread8(srchandle);
  314.       for (c = 1; c <= highestusedinstr; c++)
  315.       {
  316.         instr[c].ad = fread8(srchandle);
  317.         instr[c].sr = fread8(srchandle);
  318.         instr[c].ptr[WTBL] = fread8(srchandle);
  319.         instr[c].ptr[PTBL] = fread8(srchandle);
  320.         instr[c].ptr[FTBL] = fread8(srchandle);
  321.         instr[c].ptr[STBL] = fread8(srchandle);
  322.         instr[c].vibdelay = fread8(srchandle);
  323.         instr[c].gatetimer = fread8(srchandle);
  324.         instr[c].firstwave = fread8(srchandle);
  325.         fread(&instr[c].name, MAX_INSTRNAMELEN, 1, srchandle);
  326.       }
  327.       // Read tables
  328.       for (c = 0; c < tables; c++)
  329.       {
  330.         loadbytes = fread8(srchandle);
  331.         fread(ltable[c], loadbytes, 1, srchandle);
  332.         fread(rtable[c], loadbytes, 1, srchandle);
  333.       }
  334.       // Read patterns
  335.       amount = fread8(srchandle);
  336.       for (c = 0; c < amount; c++)
  337.       {
  338.         length = fread8(srchandle);
  339.         fread(pattern[c], length*4, 1, srchandle);
  340.       }
  341.       countpatternlengths();
  342.       fclose(srchandle);
  343.       return 1;
  344.     }
  345.     fclose(srchandle);
  346.   }
  347.   return 0;
  348. }
  349.  
  350. int savesong(char *name)
  351. {
  352.   FILE *handle;
  353.   int c;
  354.  
  355.   handle = fopen(name, "wb");
  356.   if (handle)
  357.   {
  358.     int d;
  359.     unsigned char length;
  360.     unsigned char amount;
  361.     int writebytes;
  362.     fwrite(ident, 4, 1, handle);
  363.  
  364.     countdestpatternlengths();
  365.  
  366.     // Write infotexts
  367.     fwrite(songname, sizeof songname, 1, handle);
  368.     fwrite(authorname, sizeof authorname, 1, handle);
  369.     fwrite(copyrightname, sizeof copyrightname, 1, handle);
  370.  
  371.     // Determine amount of songs to be saved
  372.     c = 0;
  373.     for (;;)
  374.     {
  375.       if (c == MAX_SONGS) break;
  376.       if ((!destsonglen[c][0])||
  377.          (!destsonglen[c][1])||
  378.          (!destsonglen[c][2])) break;
  379.       c++;
  380.     }
  381.     amount = c;
  382.  
  383.     fwrite8(handle, amount);
  384.     // Write songorderlists
  385.     for (d = 0; d < amount; d++)
  386.     {
  387.       for (c = 0; c < MAX_CHN; c++)
  388.       {
  389.         length = destsonglen[d][c]+1;
  390.         fwrite8(handle, length);
  391.         writebytes = length;
  392.         writebytes++;
  393.         fwrite(destsongorder[d][c], writebytes, 1, handle);
  394.       }
  395.     }
  396.     // Write instruments
  397.     fwrite8(handle, highestusedinstr);
  398.     for (c = 1; c <= highestusedinstr; c++)
  399.     {
  400.       fwrite8(handle, instr[c].ad);
  401.       fwrite8(handle, instr[c].sr);
  402.       fwrite8(handle, instr[c].ptr[WTBL]);
  403.       fwrite8(handle, instr[c].ptr[PTBL]);
  404.       fwrite8(handle, instr[c].ptr[FTBL]);
  405.       fwrite8(handle, instr[c].ptr[STBL]);
  406.       fwrite8(handle, instr[c].vibdelay);
  407.       fwrite8(handle, instr[c].gatetimer);
  408.       fwrite8(handle, instr[c].firstwave);
  409.       fwrite(&instr[c].name, MAX_INSTRNAMELEN, 1, handle);
  410.     }
  411.     // Write tables
  412.     for (c = 0; c < tables; c++)
  413.     {
  414.       writebytes = gettablelen(c);
  415.       fwrite8(handle, writebytes);
  416.       fwrite(ltable[c], writebytes, 1, handle);
  417.       fwrite(rtable[c], writebytes, 1, handle);
  418.     }
  419.     // Write patterns
  420.     amount = dp;
  421.     fwrite8(handle, amount);
  422.     for (c = 0; c < amount; c++)
  423.     {
  424.       length = destpattlen[c]+1;
  425.       fwrite8(handle, length);
  426.       fwrite(destpattern[c], length*4, 1, handle);
  427.     }
  428.  
  429.     fclose(handle);
  430.     return 1;
  431.   }
  432.   return 0;
  433. }
  434.  
  435. void countpatternlengths(void)
  436. {
  437.   int c, d, e;
  438.  
  439.   highestusedpattern = 0;
  440.   for (c = 0; c < MAX_PATT; c++)
  441.   {
  442.     for (d = 0; d <= MAX_PATTROWS; d++)
  443.     {
  444.       if (pattern[c][d*4] == ENDPATT) break;
  445.     }
  446.     pattlen[c] = d;
  447.   }
  448.   for (e = 0; e < MAX_SONGS; e++)
  449.   {
  450.     for (c = 0; c < MAX_CHN; c++)
  451.     {
  452.       for (d = 0; d < MAX_SONGLEN; d++)
  453.       {
  454.         if (songorder[e][c][d] >= LOOPSONG) break;
  455.         if (songorder[e][c][d] < MAX_PATT)
  456.         {
  457.           if (songorder[e][c][d] > highestusedpattern)
  458.             highestusedpattern = songorder[e][c][d];
  459.         }
  460.       }
  461.       songlen[e][c] = d;
  462.     }
  463.   }
  464. }
  465.  
  466. void countdestpatternlengths(void)
  467. {
  468.   int c, d, e;
  469.  
  470.   for (c = 0; c < MAX_PATT; c++)
  471.   {
  472.     for (d = 0; d <= MAX_PATTROWS; d++)
  473.     {
  474.       if (destpattern[c][d*4] == ENDPATT) break;
  475.     }
  476.     destpattlen[c] = d;
  477.   }
  478.   for (e = 0; e < MAX_SONGS; e++)
  479.   {
  480.     for (c = 0; c < MAX_CHN; c++)
  481.     {
  482.       for (d = 0; d < MAX_SONGLEN; d++)
  483.       {
  484.         if (destsongorder[e][c][d] >= LOOPSONG) break;
  485.       }
  486.       destsonglen[e][c] = d;
  487.     }
  488.   }
  489. }
  490.  
  491. void clearsong(void)
  492. {
  493.   int c;
  494.  
  495.   for (c = 0; c < MAX_CHN; c++)
  496.   {
  497.     int d;
  498.     for (d = 0; d < MAX_SONGS; d++)
  499.     {
  500.       destsonglen[d][c] = 0;
  501.       destsongorder[d][c][0] = LOOPSONG;
  502.  
  503.       memset(&songorder[d][c][0], 0, MAX_SONGLEN);
  504.       if (!d)
  505.       {
  506.         songorder[d][c][0] = c;
  507.         songorder[d][c][1] = LOOPSONG;
  508.         songorder[d][c][2] = 0;
  509.       }
  510.       else
  511.       {
  512.         songorder[d][c][0] = LOOPSONG;
  513.         songorder[d][c][1] = 0;
  514.       }
  515.     }
  516.   }
  517.   memset(songname, 0, sizeof songname);
  518.   memset(authorname, 0, sizeof authorname);
  519.   memset(copyrightname, 0, sizeof copyrightname);
  520.  
  521.   for (c = 0; c < MAX_PATT; c++)
  522.   {
  523.     int d;
  524.     memset(&pattern[c][0], 0, MAX_PATTROWS*4);
  525.     for (d = 0; d < MAX_PATTROWS; d++) pattern[c][d*4] = REST;
  526.     for (d = MAX_PATTROWS; d <= MAX_PATTROWS; d++) pattern[c][d*4] = ENDPATT;
  527.   }
  528.   for (c = 0; c < MAX_INSTR; c++)
  529.   {
  530.     memset(&instr[c], 0, sizeof(INSTR));
  531.   }
  532.   memset(ltable, 0, sizeof ltable);
  533.   memset(rtable, 0, sizeof rtable);
  534.   countpatternlengths();
  535. }
  536.  
  537.  
  538. int gettablelen(int num)
  539. {
  540.   int c;
  541.  
  542.   for (c = MAX_TABLELEN-1; c >= 0; c--)
  543.   {
  544.     if (ltable[num][c] | rtable[num][c]) break;
  545.   }
  546.   return c+1;
  547. }
  548.  
  549.