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