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

  1. //
  2. // GOATTRACKER v2 packer/relocator
  3. //
  4.  
  5. #define GRELOC_C
  6.  
  7. #include "goattrk2.h"
  8. #include "membuf.h"
  9. #include "parse.h"
  10.  
  11. char *playeroptname[] =
  12. {
  13.   "Buffered SID-writes",
  14.   "Sound effect support",
  15.   "Volume change support",
  16.   "Store author-info",
  17.   "Use zeropage ghostregs",
  18.   "Disable optimization",
  19.   "Full SID buffering"
  20. };
  21.  
  22. char *tableleftname[] = {
  23.   "mt_wavetbl",
  24.   "mt_pulsetimetbl",
  25.   "mt_filttimetbl",
  26.   "mt_speedlefttbl"};
  27.  
  28. char *tablerightname[] = {
  29.   "mt_notetbl",
  30.   "mt_pulsespdtbl",
  31.   "mt_filtspdtbl",
  32.   "mt_speedrighttbl"};
  33.  
  34. unsigned char chnused[MAX_CHN];
  35. unsigned char pattused[MAX_PATT];
  36. unsigned char pattmap[MAX_PATT];
  37. unsigned char instrused[MAX_INSTR];
  38. unsigned char instrmap[MAX_INSTR];
  39. unsigned char tableused[MAX_TABLES][MAX_TABLELEN+1];
  40. unsigned char tablemap[MAX_TABLES][MAX_TABLELEN+1];
  41. int pattoffset[MAX_PATT];
  42. int pattsize[MAX_PATT];
  43. int songoffset[MAX_SONGS][MAX_CHN];
  44. int songsize[MAX_SONGS][MAX_CHN];
  45. int tableerror;
  46. int channels;
  47. int fixedparams;
  48. int simplepulse;
  49. int firstnote;
  50. int lastnote;
  51. int patternlastnote;
  52. int nofilter;
  53. int nofiltermod;
  54. int nopulse;
  55. int nopulsemod;
  56. int nowavedelay;
  57. int norepeat;
  58. int notrans;
  59. int noportamento;
  60. int notoneporta;
  61. int novib;
  62. int noinsvib;
  63. int nosetad;
  64. int nosetsr;
  65. int nosetwave;
  66. int nosetwaveptr;
  67. int nosetpulseptr;
  68. int nosetfiltptr;
  69. int nosetfiltcutoff;
  70. int nosetfiltctrl;
  71. int nosetmastervol;
  72. int nofunktempo;
  73. int noglobaltempo;
  74. int nochanneltempo;
  75. int nogate;
  76. int noeffects;
  77. int nowavecmd;
  78. int nofirstwavecmd;
  79. int nocalculatedspeed;
  80. int nonormalspeed;
  81. int nozerospeed;
  82.  
  83. struct membuf src = STATIC_MEMBUF_INIT;
  84. struct membuf dest = STATIC_MEMBUF_INIT;
  85.  
  86. #ifdef GT2RELOC
  87. #ifdef __WIN32__
  88. extern FILE *STDOUT, *STDERR;
  89. #else
  90. #define STDOUT stdout
  91. #define STDERR stderr
  92. #endif
  93. extern char packedsongname[MAX_PATHNAME];
  94. #define clearscreen()
  95. #define fliptoscreen()
  96. #define waitkeynoupdate()
  97. #define printtextc(x, y, b) fputs(b, STDERR)
  98. #define printmainscreen()
  99. #endif
  100.  
  101. void relocator(void)
  102. {
  103. #ifndef GT2RELOC
  104.   char packedsongname[MAX_FILENAME];
  105.   char packedfilter[MAX_FILENAME];
  106. #endif
  107.   unsigned char *packeddata = NULL;
  108.   char *playername = "player.s";
  109.  
  110.   int tableerrortype = TYPE_NONE;
  111.   int tableerrorcause = CAUSE_NONE;
  112.   int tableerrorsource1 = 0;
  113.   int tableerrorsource2 = 0;
  114.   int patterns = 0;
  115.   int songs = 0;
  116.   int instruments = 0;
  117.   int numlegato = 0;
  118.   int numnohr = 0;
  119.   int numnormal = 0;
  120.   int freenormal;
  121.   int freenohr;
  122.   int freelegato;
  123.   int transuprange = 0;
  124.   int transdownrange = 0;
  125.   int pattdatasize = 0;
  126.   int patttblsize = 0;
  127.   int songdatasize = 0;
  128.   int songtblsize = 0;
  129.   int instrsize = 0;
  130.   int wavetblsize = 0;
  131.   int pulsetblsize = 0;
  132.   int filttblsize = 0;
  133.   int speedtblsize = 0;
  134.   int playersize = 0;
  135.   int packedsize = 0;
  136.  
  137.   FILE *songhandle = NULL;
  138.   int selectdone;
  139.   int opt = 0;
  140.   unsigned char speedcode[] = {0xa2,0x00,0x8e,0x04,0xdc,0xa2,0x00,0x8e,0x05,0xdc};
  141.  
  142.   int c,d,e;
  143.  
  144.   unsigned char patttemp[512];
  145.   unsigned char *songwork = NULL;
  146.   unsigned char *pattwork = NULL;
  147.   unsigned char *instrwork = NULL;
  148.  
  149.   channels = 3;
  150.   fixedparams = 1;
  151.   simplepulse = 1;
  152.   firstnote = MAX_NOTES-1;
  153.   lastnote = 0;
  154.   patternlastnote = 0;
  155.   noeffects = 1;
  156.   nogate = 1;
  157.   nofilter = 1;
  158.   nofiltermod = 1;
  159.   nopulse = 1;
  160.   nopulsemod = 1;
  161.   nowavedelay = 1;
  162.   nowavecmd = 1;
  163.   norepeat = 1;
  164.   notrans = 1;
  165.   noportamento = 1;
  166.   notoneporta = 1;
  167.   novib = 1;
  168.   noinsvib = 1;
  169.   nosetad = 1;
  170.   nosetsr = 1;
  171.   nosetwave = 1;
  172.   nosetwaveptr = 1;
  173.   nosetpulseptr = 1;
  174.   nosetfiltptr = 1;
  175.   nosetfiltcutoff = 1;
  176.   nosetfiltctrl = 1;
  177.   nosetmastervol = 1;
  178.   nofunktempo = 1;
  179.   noglobaltempo = 1;
  180.   nochanneltempo = 1;
  181.   nofirstwavecmd = 1;
  182.   nocalculatedspeed = 1;
  183.   nonormalspeed = 1;
  184.   nozerospeed = 1;
  185.  
  186.   stopsong();
  187.  
  188.   memset(pattused, 0, sizeof pattused);
  189.   memset(instrused, 0, sizeof instrused);
  190.   memset(chnused, 0, sizeof chnused);
  191.   memset(tableused, 0, sizeof tableused);
  192.   memset(tablemap, 0, sizeof tablemap);
  193.   tableerror = 0;
  194.  
  195.   membuf_free(&src);
  196.   membuf_free(&dest);
  197.  
  198.   // Process song-orderlists
  199.   countpatternlengths();
  200.   // Calculate amount of songs with nonzero length
  201.   for (c = 0; c < MAX_SONGS; c++)
  202.   {
  203.     if ((songlen[c][0]) &&
  204.         (songlen[c][1]) &&
  205.         (songlen[c][2]))
  206.     {
  207.       // See which patterns are used in this song
  208.       for (d = 0; d < MAX_CHN; d++)
  209.       {
  210.         songdatasize += songlen[c][d]+2;
  211.         for (e = 0; e < songlen[c][d]; e++)
  212.         {
  213.           if (songorder[c][d][e] < REPEAT)
  214.           {
  215.             int f;
  216.             int num = songorder[c][d][e];
  217.  
  218.             pattused[num] = 1;
  219.             for (f = 0; f < pattlen[num]; f++)
  220.             {
  221.               if ((pattern[num][f*4] != REST) || (pattern[num][f*4+1]) || (pattern[num][f*4+2]))
  222.                 chnused[d] = 1;
  223.             }
  224.           }
  225.           else
  226.           {
  227.             if (songorder[c][d][e] >= TRANSDOWN)
  228.             {
  229.               notrans = 0;
  230.               if (songorder[c][d][e] < TRANSUP)
  231.               {
  232.                 int newtransdownrange = -(songorder[c][d][e] - TRANSUP);
  233.                 if (newtransdownrange > transdownrange) transdownrange = newtransdownrange;
  234.               }
  235.               else
  236.               {
  237.                 int newtransuprange = songorder[c][d][e] - TRANSUP;
  238.                 if (newtransuprange > transuprange) transuprange = newtransuprange;
  239.               }
  240.             }
  241.             else norepeat = 0;
  242.           }
  243.         }
  244.         if (songorder[c][d][songlen[c][d]+1] >= songlen[c][d])
  245.         {
  246.           sprintf(textbuffer, "ILLEGAL SONG RESTART POSITION! (SUBTUNE %02X, CHANNEL %d)", c, d+1);
  247.           clearscreen();
  248.           printtextc(MAX_ROWS/2, 15, textbuffer);
  249.           fliptoscreen();
  250.           waitkeynoupdate();
  251.           goto PRCLEANUP;
  252.         }
  253.       }
  254.       songs++;
  255.     }
  256.   }
  257.  
  258.   // Optimize amount of used channels
  259.   if (!chnused[2])
  260.     channels = 2;
  261.   if ((!chnused[1]) && (!chnused[2]))
  262.     channels = 1;
  263.  
  264.   if (!songs)
  265.   {
  266.     clearscreen();
  267.     printtextc(MAX_ROWS/2, CTITLE, "NO SONGS, NO DATA TO SAVE!");
  268.     fliptoscreen();
  269.     waitkeynoupdate();
  270.     goto PRCLEANUP;
  271.   }
  272.  
  273.   // Build the pattern-mapping
  274.   // Instrument 1 is always used
  275.   instrused[1] = 1;
  276.   for (c = 0; c < MAX_PATT; c++)
  277.   {
  278.     if (pattused[c])
  279.     {
  280.       pattmap[c] = patterns;
  281.       patterns++;
  282.  
  283.       // See which instruments/tablecommands are used
  284.       for (d = 0; d < pattlen[c]; d++)
  285.       {
  286.         tableerror = 0;
  287.  
  288.         if ((pattern[c][d*4] == KEYOFF) || (pattern[c][d*4] == KEYON))
  289.           nogate = 0;
  290.         if (pattern[c][d*4+1])
  291.           instrused[pattern[c][d*4+1]] = 1;
  292.         if (pattern[c][d*4+2])
  293.           noeffects = 0;
  294.         if ((pattern[c][d*4+2] >= CMD_SETWAVEPTR) && (pattern[c][d*4+2] <= CMD_SETFILTERPTR))
  295.           exectable(pattern[c][d*4+2] - CMD_SETWAVEPTR, pattern[c][d*4+3]);
  296.         if ((pattern[c][d*4+2] >= CMD_PORTAUP) && (pattern[c][d*4+2] <= CMD_VIBRATO))
  297.         {
  298.           exectable(STBL, pattern[c][d*4+3]);
  299.           calcspeedtest(pattern[c][d*4+3]);
  300.         }
  301.         if (pattern[c][d*4+2] == CMD_FUNKTEMPO)
  302.           exectable(STBL, pattern[c][d*4+3]);
  303.         if (pattern[c][d*4+2] == CMD_FUNKTEMPO)
  304.         {
  305.           nofunktempo = 0;
  306.           noglobaltempo = 0;
  307.         }
  308.         if ((pattern[c][d*4+2] == CMD_SETTEMPO) && ((pattern[c][d*4+3] & 0x7f) < 3)) nofunktempo = 0;
  309.  
  310.         // See, which are the highest/lowest notes used
  311.         if ((pattern[c][d*4] >= FIRSTNOTE) && (pattern[c][d*4] <= LASTNOTE))
  312.         {
  313.           int newfirstnote = pattern[c][d*4] - FIRSTNOTE - transdownrange;
  314.           int newlastnote = pattern[c][d*4] - FIRSTNOTE + transuprange;
  315.           if (newfirstnote < 0) newfirstnote = 0;
  316.           if (newlastnote > MAX_NOTES-1) newlastnote = MAX_NOTES-1;
  317.  
  318.           if (newfirstnote < firstnote) firstnote = newfirstnote;
  319.           if (newlastnote > lastnote)
  320.           {
  321.             patternlastnote = newlastnote;
  322.             lastnote = newlastnote;
  323.           }
  324.           if (newfirstnote > lastnote)
  325.           {
  326.             patternlastnote = newfirstnote;
  327.             lastnote = newfirstnote;
  328.           }
  329.         }
  330.         if ((tableerror) && (!tableerrortype))
  331.         {
  332.           tableerrortype = tableerror;
  333.           tableerrorcause = CAUSE_PATTERN;
  334.           tableerrorsource1 = c;
  335.           tableerrorsource2 = d;
  336.         }
  337.       }
  338.     }
  339.   }
  340.  
  341.   // Count amount of normal, nohr, and legato instruments
  342.   // Also see if special first wave parameters are used
  343.   for (c = 0; c < MAX_INSTR; c++)
  344.   {
  345.     if (instrused[c])
  346.     {
  347.       if (instr[c].gatetimer & 0x40) numlegato++;
  348.       else
  349.       {
  350.         if (instr[c].gatetimer & 0x80) numnohr++;
  351.         else numnormal++;
  352.       }
  353.       if ((!instr[c].firstwave) || (instr[c].firstwave >= 0xfe))
  354.         nofirstwavecmd = 0;
  355.     }
  356.   }
  357.   freenormal = 1;
  358.   freenohr = freenormal + numnormal;
  359.   freelegato = freenohr + numnohr;
  360.  
  361.   // Build the instrument-mapping
  362.   for (c = 0; c < MAX_INSTR; c++)
  363.   {
  364.     if (instrused[c])
  365.     {
  366.       if (instr[c].gatetimer & 0x40) instrmap[c] = freelegato++;
  367.       else
  368.       {
  369.         if (instr[c].gatetimer & 0x80) instrmap[c] = freenohr++;
  370.         else instrmap[c] = freenormal++;
  371.       }
  372.       instruments++;
  373.       for (d = 0; d < MAX_TABLES; d++)
  374.       {
  375.         tableerror = 0;
  376.         exectable(d, instr[c].ptr[d]);
  377.         if (d == STBL) calcspeedtest(instr[c].ptr[d]);
  378.         if ((tableerror) && (!tableerrortype))
  379.         {
  380.           tableerrortype = tableerror;
  381.           tableerrorcause = CAUSE_INSTRUMENT;
  382.           tableerrorsource1 = c;
  383.           tableerrorsource2 = d;
  384.         }
  385.       }
  386.     }
  387.   }
  388.  
  389.   // Execute tableprograms invoked from wavetable commands
  390.   for (c = 0; c < MAX_TABLELEN; c++)
  391.   {
  392.     if (tableused[WTBL][c+1])
  393.     {
  394.       if ((ltable[WTBL][c] >= WAVECMD) && (ltable[WTBL][c] <= WAVELASTCMD))
  395.       {
  396.         d = -1;
  397.         tableerror = 0;
  398.  
  399.         switch(ltable[WTBL][c] - WAVECMD)
  400.         {
  401.           case CMD_PORTAUP:
  402.           case CMD_PORTADOWN:
  403.           case CMD_TONEPORTA:
  404.           case CMD_VIBRATO:
  405.           d = STBL;
  406.           calcspeedtest(rtable[WTBL][c]);
  407.           break;
  408.  
  409.           case CMD_SETPULSEPTR:
  410.           d = PTBL;
  411.           nopulse = 0;
  412.            break;
  413.            
  414.            case CMD_SETFILTERPTR:
  415.            d = FTBL;
  416.           nofilter = 0;
  417.           break;
  418.  
  419.           case CMD_DONOTHING:
  420.           case CMD_SETWAVEPTR:
  421.           case CMD_FUNKTEMPO:
  422.           sprintf(textbuffer, "ILLEGAL WAVETABLE COMMAND (ROW %02X, COMMAND %X)", c+1, ltable[WTBL][c] - WAVECMD);
  423.           clearscreen();
  424.           printtextc(MAX_ROWS/2, 15, textbuffer);
  425.           fliptoscreen();
  426.           waitkeynoupdate();
  427.           goto PRCLEANUP;
  428.         }
  429.  
  430.         if (d != -1) exectable(d, rtable[WTBL][c]);
  431.  
  432.         if ((tableerror) && (!tableerrortype))
  433.         {
  434.           tableerrortype = tableerror;
  435.           tableerrorcause = CAUSE_WAVECMD;
  436.           tableerrorsource1 = c+1;
  437.           tableerrorsource2 = d;
  438.         }
  439.       }
  440.     }
  441.   }
  442.  
  443.   // Build the table-mapping
  444.   for (c = 0; c < MAX_TABLES; c++)
  445.   {
  446.     int e = 1;
  447.     for (d = 0; d < MAX_TABLELEN; d++)
  448.     {
  449.       if (tableused[c][d+1])
  450.       {
  451.         tablemap[c][d+1] = e;
  452.         e++;
  453.       }
  454.     }
  455.   }
  456.  
  457.   // Check for table errors
  458.   if (tableerrorcause)
  459.   {
  460.     clearscreen();
  461.     switch(tableerrortype)
  462.     {
  463.       case TYPE_JUMP:
  464.       sprintf(textbuffer, "TABLE POINTER POINTS TO A JUMP! ");
  465.       break;
  466.  
  467.       case TYPE_OVERFLOW:
  468.       sprintf(textbuffer, "TABLE EXECUTION OVERFLOWS! ");
  469.       break;
  470.     }
  471.     switch (tableerrorcause)
  472.     {
  473.       case CAUSE_PATTERN:
  474.       sprintf(textbuffer + strlen(textbuffer), "(PATTERN %02X, ROW %02d)", tableerrorsource1, tableerrorsource2);
  475.       break;
  476.  
  477.       case CAUSE_WAVECMD:
  478.       sprintf(textbuffer + strlen(textbuffer), "WAVETABLE CMD (ROW %02X, ", tableerrorsource1);
  479.       goto TABLETYPE;
  480.  
  481.       case CAUSE_INSTRUMENT:
  482.       sprintf(textbuffer + strlen(textbuffer), "(INSTRUMENT %02X, ", tableerrorsource1);
  483.       TABLETYPE:
  484.       switch (tableerrorsource2)
  485.       {
  486.         case WTBL:
  487.         strcat(textbuffer, "WAVE");
  488.         break;
  489.  
  490.         case PTBL:
  491.         strcat(textbuffer, "PULSE");
  492.         break;
  493.  
  494.         case FTBL:
  495.         strcat(textbuffer, "FILTER");
  496.         break;
  497.       }
  498.       strcat(textbuffer, ")");
  499.       break;
  500.     }
  501.     printtextc(MAX_ROWS/2, 15, textbuffer);
  502.  
  503.     fliptoscreen();
  504.     waitkeynoupdate();
  505.     goto PRCLEANUP;
  506.   }
  507.  
  508.   // Find duplicate ranges in tables
  509.   for (c = 0; c < MAX_TABLES; c++)
  510.     findtableduplicates(c);
  511.  
  512.   // Select playroutine options
  513. #ifndef GT2RELOC
  514.   clearscreen();
  515.   printblankc(0, 0, 15+16, MAX_COLUMNS);
  516.   if (!strlen(loadedsongfilename))
  517.     sprintf(textbuffer, "%s Packer/Relocator", programname);
  518.   else
  519.     sprintf(textbuffer, "%s Packer/Relocator - %s", programname, loadedsongfilename);
  520.   textbuffer[MAX_COLUMNS] = 0;
  521.   printtext(0, 0, 15+16, textbuffer);
  522.   printtext(1, 2, CTITLE, "SELECT PLAYROUTINE OPTIONS: (CURSORS=MOVE/CHANGE, ENTER=ACCEPT, ESC=CANCEL)");
  523.   selectdone = 0;
  524.   while (!selectdone)
  525.   {
  526.     for (c = 0; c < MAX_OPTIONS; c++)
  527.     {
  528.       int color = CNORMAL;
  529.       if (opt == c) color = CEDIT;
  530.  
  531.       printtext(1, 3+c, color, playeroptname[c]);
  532.       if (playerversion & (PLAYER_BUFFERED << c))
  533.         printtext(24, 3+c, color, "Yes");
  534.       else
  535.         printtext(24, 3+c, color, "No ");
  536.     }
  537.     fliptoscreen();
  538.     waitkeynoupdate();
  539.  
  540.     if (win_quitted)
  541.     {
  542.       exitprogram = 1;
  543.       goto PRCLEANUP;
  544.     }
  545.  
  546.     switch(rawkey)
  547.     {
  548.       case KEY_LEFT:
  549.       case KEY_RIGHT:
  550.       case KEY_SPACE:
  551.       playerversion ^= (PLAYER_BUFFERED << opt);
  552.       if (opt)
  553.       {
  554.         if ((playerversion & PLAYER_SOUNDEFFECTS) || (playerversion & PLAYER_ZPGHOSTREGS) || (playerversion & PLAYER_FULLBUFFERED))
  555.           playerversion |= PLAYER_BUFFERED;
  556.       }
  557.       else
  558.       {
  559.         if (!(playerversion & PLAYER_BUFFERED))
  560.         {
  561.           playerversion &= ~PLAYER_SOUNDEFFECTS;
  562.           playerversion &= ~PLAYER_ZPGHOSTREGS;
  563.           playerversion &= ~PLAYER_FULLBUFFERED;
  564.         }
  565.       }
  566.       break;
  567.  
  568.       case KEY_UP:
  569.       opt--;
  570.       if (opt < 0) opt = MAX_OPTIONS-1;
  571.       break;
  572.  
  573.       case KEY_DOWN:
  574.       opt++;
  575.       if (opt >= MAX_OPTIONS) opt = 0;
  576.       break;
  577.  
  578.       case KEY_ESC:
  579.       selectdone = -1;
  580.       break;
  581.  
  582.       case KEY_ENTER:
  583.       selectdone = 1;
  584.       break;
  585.     }
  586.   }
  587.   if (selectdone == -1) goto PRCLEANUP;
  588. #endif
  589.  
  590.   // Disable optimizations if necessary
  591.   if (playerversion & PLAYER_NOOPTIMIZATION)
  592.   {
  593.     fixedparams = 0;
  594.     if (!numlegato) numlegato++;
  595.  
  596.     simplepulse = 0;
  597.     firstnote = 0;
  598.     lastnote = MAX_NOTES-1;
  599.     nogate = 0;
  600.     noeffects = 0;
  601.     nofilter = 0;
  602.     nofiltermod = 0;
  603.     nopulse = 0;
  604.     nopulsemod = 0;
  605.     nowavedelay = 0;
  606.     nowavecmd = 0;
  607.     norepeat = 0;
  608.     notrans = 0;
  609.     noportamento = 0;
  610.     notoneporta = 0;
  611.     novib = 0;
  612.     noinsvib = 0;
  613.     nosetad = 0;
  614.     nosetsr = 0;
  615.     nosetwave = 0;
  616.     nosetwaveptr = 0;
  617.     nosetpulseptr = 0;
  618.     nosetfiltptr = 0;
  619.     nosetfiltcutoff = 0;
  620.     nosetfiltctrl = 0;
  621.     nosetmastervol = 0;
  622.     nofunktempo = 0;
  623.     noglobaltempo = 0;
  624.     nochanneltempo = 0;
  625.     nofirstwavecmd = 0;
  626.     nocalculatedspeed = 0;
  627.     nonormalspeed = 0;
  628.     nozerospeed = 0;
  629.   }
  630.  
  631.   // Make sure buffering is used if it is needed
  632.   if ((playerversion & PLAYER_SOUNDEFFECTS) || (playerversion & PLAYER_ZPGHOSTREGS) || (playerversion & PLAYER_FULLBUFFERED))
  633.     playerversion |= PLAYER_BUFFERED;
  634.  
  635.   // Sound effect or ghostreg players always use full 3 channels
  636.   if ((playerversion & PLAYER_SOUNDEFFECTS) || (playerversion & PLAYER_FULLBUFFERED) || (playerversion & PLAYER_ZPGHOSTREGS))
  637.     channels = 3;
  638.  
  639.   // Allocate memory for song-orderlists
  640.   songtblsize = songs*6;
  641.   songwork = malloc(songdatasize);
  642.   if (!songwork)
  643.   {
  644.     clearscreen();
  645.     printtextc(MAX_ROWS/2, CTITLE, "OUT OF MEMORY IN PACKER/RELOCATOR!");
  646.     fliptoscreen();
  647.     waitkeynoupdate();
  648.     goto PRCLEANUP;
  649.   }
  650.  
  651.   // Generate songorderlists & songtable
  652.   songdatasize = 0;
  653.   for (c = 0; c < songs; c++)
  654.   {
  655.     if ((songlen[c][0]) &&
  656.         (songlen[c][1]) &&
  657.         (songlen[c][2]))
  658.     {
  659.       for (d = 0; d < MAX_CHN; d++)
  660.       {
  661.         songoffset[c][d] = songdatasize;
  662.         songsize[c][d] = songlen[c][d] + 2;
  663.  
  664.         for (e = 0; e < songlen[c][d]; e++)
  665.         {
  666.           // Pattern
  667.           if (songorder[c][d][e] < REPEAT)
  668.             songwork[songdatasize++] = pattmap[songorder[c][d][e]];
  669.           else
  670.           {
  671.             // Transpose
  672.             if (songorder[c][d][e] >= TRANSDOWN)
  673.             {
  674.               songwork[songdatasize++] = songorder[c][d][e];
  675.             }
  676.             // Repeat sequence: must be swapped
  677.             else
  678.             {
  679.               // See that repeat amount is more than 1
  680.               if (songorder[c][d][e] > REPEAT)
  681.               {
  682.                 // Insanity check that a pattern indeed follows
  683.                 if (songorder[c][d][e+1] < REPEAT)
  684.                 {
  685.                   songwork[songdatasize++] = pattmap[songorder[c][d][e+1]];
  686.                   songwork[songdatasize++] = songorder[c][d][e];
  687.                   e++;
  688.                 }
  689.                 else
  690.                   songwork[songdatasize++] = songorder[c][d][e];
  691.               }
  692.             }
  693.           }
  694.         }
  695.         // Endmark & repeat position
  696.         songwork[songdatasize++] = songorder[c][d][e++];
  697.         songwork[songdatasize++] = songorder[c][d][e++];
  698.       }
  699.     }
  700.     else
  701.     {
  702.       for (d = 0; d < MAX_CHN; d++)
  703.       {
  704.         songoffset[c][d] = songdatasize;
  705.         songsize[c][d] = 0;
  706.       }
  707.     }
  708.   }
  709.  
  710.   // Calculate total size of patterns
  711.   for (c = 0; c < MAX_PATT; c++)
  712.   {
  713.     if (pattused[c])
  714.     {
  715.       int result = packpattern(patttemp, pattern[c], pattlen[c]);
  716.  
  717.       if (result < 0)
  718.       {
  719.         clearscreen();
  720.         sprintf(textbuffer, "PATTERN %02X IS TOO COMPLEX (OVER 256 BYTES PACKED)!", c);
  721.         printtextc(MAX_ROWS/2, 15, textbuffer);
  722.         fliptoscreen();
  723.         waitkeynoupdate();
  724.         goto PRCLEANUP;
  725.       }
  726.       pattdatasize += result;
  727.     }
  728.   }
  729.  
  730.   patttblsize = patterns*2;
  731.   pattwork = malloc(pattdatasize);
  732.   if (!pattwork)
  733.   {
  734.     clearscreen();
  735.     printtextc(MAX_ROWS/2, CTITLE, "OUT OF MEMORY IN PACKER/RELOCATOR!");
  736.     fliptoscreen();
  737.     waitkeynoupdate();
  738.     goto PRCLEANUP;
  739.   }
  740.  
  741.   // This time pack the patterns for real
  742.   pattdatasize = 0;
  743.   d = 0;
  744.   for (c = 0; c < MAX_PATT; c++)
  745.   {
  746.     if (pattused[c])
  747.     {
  748.       pattoffset[d] = pattdatasize;
  749.       pattsize[d] = packpattern(&pattwork[pattdatasize], pattern[c], pattlen[c]);
  750.       pattdatasize += pattsize[d];
  751.       d++;
  752.     }
  753.   }
  754.  
  755.   // Then process instruments
  756.   instrsize = instruments*9;
  757.   instrwork = malloc(instrsize);
  758.   if (!instrwork)
  759.   {
  760.     clearscreen();
  761.     printtextc(MAX_ROWS/2, CTITLE, "OUT OF MEMORY IN PACKER/RELOCATOR!");
  762.     fliptoscreen();
  763.     waitkeynoupdate();
  764.     goto PRCLEANUP;
  765.   }
  766.  
  767.   for (c = 1; c < MAX_INSTR; c++)
  768.   {
  769.     if (instrused[c])
  770.     {
  771.       d = instrmap[c] - 1;
  772.       instrwork[d] = instr[c].ad;
  773.       instrwork[d+instruments] = instr[c].sr;
  774.       instrwork[d+instruments*2] = tablemap[WTBL][instr[c].ptr[WTBL]];
  775.       instrwork[d+instruments*3] = tablemap[PTBL][instr[c].ptr[PTBL]];
  776.       instrwork[d+instruments*4] = tablemap[FTBL][instr[c].ptr[FTBL]];
  777.       if (instr[c].vibdelay)
  778.       {
  779.         instrwork[d+instruments*5] = tablemap[STBL][instr[c].ptr[STBL]];
  780.         instrwork[d+instruments*6] = instr[c].vibdelay - 1;
  781.       }
  782.       else
  783.       {
  784.         instrwork[d+instruments*5] = 0;
  785.         instrwork[d+instruments*6] = 0;
  786.       }
  787.       instrwork[d+instruments*7] = instr[c].gatetimer & 0x3f;
  788.       instrwork[d+instruments*8] = instr[c].firstwave;
  789.  
  790.       if (instr[c].ptr[STBL])
  791.       {
  792.         novib = 0;
  793.         noinsvib = 0;
  794.       }
  795.       if (instr[c].ptr[PTBL])
  796.         nopulse = 0;
  797.       if (instr[c].ptr[FTBL])
  798.         nofilter = 0;
  799.  
  800.       // See if all instruments use same gatetimer & firstwave parameters
  801.       if ((instr[c].gatetimer != instr[1].gatetimer) ||
  802.           (instr[c].firstwave != instr[1].firstwave))
  803.         fixedparams = 0;
  804.       // or if special firstwave commands are in use
  805.       if ((!instr[c].firstwave) || (instr[c].firstwave >= 0xfe))
  806.         fixedparams = 0;
  807.     }
  808.   }
  809.  
  810.   // Disable sameparam optimization for multispeed stability
  811.   if (multiplier > 1)
  812.   {
  813.     fixedparams = 0;
  814.     numlegato++;
  815.     numnohr++;
  816.   }
  817.  
  818.   if (fixedparams) instrsize -= instruments*2;
  819.   if (noinsvib) instrsize -= instruments*2;
  820.   if (nopulse) instrsize -= instruments;
  821.   if (nofilter) instrsize -= instruments;
  822.  
  823.   // Process tables
  824.   for (c = 0; c < MAX_TABLELEN; c++)
  825.   {
  826.     if (tableused[WTBL][c+1])
  827.     {
  828.       wavetblsize += 2;
  829.       if ((ltable[WTBL][c] >= WAVEDELAY) && (ltable[WTBL][c] <= WAVELASTDELAY)) nowavedelay = 0;
  830.       if ((ltable[WTBL][c] >= WAVECMD) && (ltable[WTBL][c] <= WAVELASTCMD))
  831.       {
  832.         nowavecmd = 0;
  833.         noeffects = 0;
  834.         switch (ltable[WTBL][c] - WAVECMD)
  835.         {
  836.           case CMD_PORTAUP:
  837.           case CMD_PORTADOWN:
  838.           noportamento = 0;
  839.           break;
  840.  
  841.           case CMD_TONEPORTA:
  842.           notoneporta = 0;
  843.           break;
  844.  
  845.           case CMD_VIBRATO:
  846.           novib = 0;
  847.           break;
  848.  
  849.           case CMD_SETAD:
  850.           nosetad = 0;
  851.           break;
  852.  
  853.           case CMD_SETSR:
  854.           nosetsr = 0;
  855.           break;
  856.  
  857.           case CMD_SETWAVE:
  858.           nosetwave = 0;
  859.           break;
  860.  
  861.           case CMD_SETPULSEPTR:
  862.           nosetpulseptr = 0;
  863.           break;
  864.  
  865.           case CMD_SETFILTERPTR:
  866.           nosetfiltptr = 0;
  867.           break;
  868.  
  869.           case CMD_SETFILTERCUTOFF:
  870.           nosetfiltcutoff = 0;
  871.           break;
  872.  
  873.           case CMD_SETFILTERCTRL:
  874.           nosetfiltctrl = 0;
  875.           break;
  876.  
  877.           case CMD_SETMASTERVOL:
  878.           nosetmastervol = 0;
  879.           break;
  880.         }
  881.       }
  882.       if (ltable[WTBL][c] < WAVECMD)
  883.       {
  884.         if (rtable[WTBL][c] <= 0x80)
  885.         {
  886.           int newlastnote = rtable[WTBL][c] + patternlastnote;
  887.           if (newlastnote > MAX_NOTES - 1) newlastnote = MAX_NOTES - 1;
  888.           if (rtable[WTBL][c] >= 0x20) firstnote = 0;
  889.            if (newlastnote > lastnote) lastnote = newlastnote;
  890.         }
  891.         else
  892.         {
  893.           int newfirstnote = rtable[WTBL][c] & 0x7f;
  894.           int newlastnote = rtable[WTBL][c] & 0x7f;
  895.           if (newlastnote > MAX_NOTES - 1) newlastnote = MAX_NOTES - 1;
  896.           if (newfirstnote < firstnote) firstnote = newfirstnote;
  897.           if (newlastnote > lastnote) lastnote = newlastnote;
  898.         }
  899.       }
  900.     }
  901.   }
  902.   for (c = 0; c < MAX_TABLELEN; c++)
  903.   {
  904.     if (tableused[PTBL][c+1])
  905.     {
  906.       pulsetblsize += 2;
  907.       if ((ltable[PTBL][c] >= 0x80) && (ltable[PTBL][c] != 0xff))
  908.       {
  909.         if (rtable[PTBL][c] & 0xf) simplepulse = 0;
  910.       }
  911.       if (ltable[PTBL][c] < 0x80)
  912.       {
  913.         nopulsemod = 0;
  914.         if (rtable[PTBL][c] & 0xf) simplepulse = 0;
  915.       }
  916.     }
  917.   }
  918.   for (c = 0; c < MAX_TABLELEN; c++)
  919.   {
  920.     if (tableused[FTBL][c+1])
  921.     {
  922.       filttblsize += 2;
  923.       if (ltable[FTBL][c] < 0x80) nofiltermod = 0;
  924.     }
  925.   }
  926.   for (c = 0; c < MAX_TABLELEN; c++)
  927.   {
  928.     if (tableused[STBL][c+1]) speedtblsize += 2;
  929.   }
  930.   // Zero entry of speedtable
  931.   if ((!novib) || (!nofunktempo) || (!noportamento) || (!notoneporta))
  932.     speedtblsize += 2;
  933.  
  934.   if (nopulse) pulsetblsize = 0;
  935.   if (nofilter) filttblsize = 0;
  936.  
  937. #ifdef GT2RELOC
  938.   fprintf(STDOUT, "Player address:   $%04X\n", playeradr);
  939.   fprintf(STDOUT, "Zeropage address: $%04X\n", zeropageadr);
  940. #else
  941.   sprintf(textbuffer, "SELECT START ADDRESS: (CURSORS=MOVE, ENTER=ACCEPT, ESC=CANCEL)");
  942.   printtext(1, 11, 15, textbuffer);
  943.  
  944.   selectdone = 0;
  945.   while (!selectdone)
  946.   {
  947.     sprintf(textbuffer, "$%04X", playeradr);
  948.     printtext(1, 12, 10, textbuffer);
  949.  
  950.     fliptoscreen();
  951.     waitkeynoupdate();
  952.  
  953.     if (win_quitted)
  954.     {
  955.       exitprogram = 1;
  956.       goto PRCLEANUP;
  957.     }
  958.  
  959.     switch(rawkey)
  960.     {
  961.       case KEY_LEFT:
  962.       playeradr -= 0x0400;
  963.       playeradr &= 0xff00;
  964.       break;
  965.  
  966.       case KEY_UP:
  967.       playeradr += 0x0100;
  968.       playeradr &= 0xff00;
  969.       break;
  970.  
  971.       case KEY_RIGHT:
  972.       playeradr += 0x0400;
  973.       playeradr &= 0xff00;
  974.       break;
  975.  
  976.       case KEY_DOWN:
  977.       playeradr -= 0x0100;
  978.       playeradr &= 0xff00;
  979.       break;
  980.  
  981.       case KEY_ESC:
  982.       selectdone = -1;
  983.       break;
  984.  
  985.       case KEY_ENTER:
  986.       selectdone = 1;
  987.       break;
  988.     }
  989.   }
  990.  
  991.   if (selectdone == -1) goto PRCLEANUP;
  992.  
  993.   sprintf(textbuffer, "SELECT ZEROPAGE ADDRESS: (CURSORS=MOVE, ENTER=ACCEPT, ESC=CANCEL)");
  994.   printtext(1, 14, 15, textbuffer);
  995.  
  996.   selectdone = 0;
  997.   while (!selectdone)
  998.   {
  999.     if (playerversion & PLAYER_ZPGHOSTREGS)
  1000.     {
  1001.       if (zeropageadr < 0x02) zeropageadr = 0xe5;
  1002.       if (zeropageadr > 0xe5) zeropageadr = 0x02;
  1003.     }
  1004.     else
  1005.     {
  1006.       if (zeropageadr < 0x02) zeropageadr = 0xfe;
  1007.       if (zeropageadr > 0xfe) zeropageadr = 0x02;
  1008.     }
  1009.  
  1010.     if (!(playerversion & PLAYER_ZPGHOSTREGS))
  1011.     {
  1012.       if (zeropageadr < 0x90)
  1013.         sprintf(textbuffer, "$%02X-$%02X (Used by BASIC interpreter)    ", zeropageadr, zeropageadr+1);
  1014.       if ((zeropageadr >= 0x90) && (zeropageadr < 0xfb))
  1015.         sprintf(textbuffer, "$%02X-$%02X (Used by KERNAL routines)      ", zeropageadr, zeropageadr+1);
  1016.       if ((zeropageadr >= 0xfb) && (zeropageadr < 0xfe))
  1017.         sprintf(textbuffer, "$%02X-$%02X (Unused)                       ", zeropageadr, zeropageadr+1);
  1018.       if (zeropageadr >= 0xfe)
  1019.         sprintf(textbuffer, "$%02X-$%02X ($FF used by BASIC interpreter)", zeropageadr, zeropageadr+1);
  1020.     }
  1021.     else
  1022.     {
  1023.       sprintf(textbuffer, "$%02X-$%02X (ghostregs start at %02X)", zeropageadr, zeropageadr+26, zeropageadr);
  1024.     }
  1025.  
  1026.     printtext(1, 15, 10, textbuffer);
  1027.  
  1028.     fliptoscreen();
  1029.     waitkeynoupdate();
  1030.  
  1031.     if (win_quitted)
  1032.     {
  1033.       exitprogram = 1;
  1034.       goto PRCLEANUP;
  1035.     }
  1036.  
  1037.     switch(rawkey)
  1038.     {
  1039.       case KEY_LEFT:
  1040.       zeropageadr -= 0x10;
  1041.       break;
  1042.  
  1043.       case KEY_UP:
  1044.       zeropageadr++;
  1045.       break;
  1046.  
  1047.       case KEY_RIGHT:
  1048.       zeropageadr += 0x10;
  1049.       break;
  1050.  
  1051.       case KEY_DOWN:
  1052.       zeropageadr--;
  1053.       break;
  1054.  
  1055.       case KEY_ESC:
  1056.       selectdone = -1;
  1057.       break;
  1058.  
  1059.       case KEY_ENTER:
  1060.       selectdone = 1;
  1061.       break;
  1062.     }
  1063.   }
  1064.  
  1065.   if (selectdone == -1) goto PRCLEANUP;
  1066. #endif
  1067.  
  1068.   // Validate frequencytable parameters
  1069.   if (lastnote < firstnote)
  1070.     lastnote = firstnote;
  1071.   if (firstnote < 0) firstnote = 0;
  1072.   if (!nocalculatedspeed)
  1073.     lastnote++; // Calculated speeds need the next frequency value
  1074.   if (lastnote > MAX_NOTES-1) lastnote = MAX_NOTES-1;
  1075.   // For sound effect support, always use the full table
  1076.   if (playerversion & PLAYER_SOUNDEFFECTS)
  1077.   {
  1078.     firstnote = 0;
  1079.     lastnote = MAX_NOTES-1;
  1080.   }
  1081.  
  1082.   // Insert baseaddresses
  1083.   insertdefine("base", playeradr);
  1084.   insertdefine("zpbase", zeropageadr);
  1085.   insertdefine("SIDBASE", sidaddress);
  1086.  
  1087.   // Insert conditionals
  1088.   insertdefine("SOUNDSUPPORT", (playerversion & PLAYER_SOUNDEFFECTS) ? 1 : 0);
  1089.   insertdefine("VOLSUPPORT", (playerversion & PLAYER_VOLUME) ? 1 : 0);
  1090.   insertdefine("BUFFEREDWRITES", (playerversion & PLAYER_BUFFERED) ? 1 : 0);
  1091.   insertdefine("GHOSTREGS", (playerversion & (PLAYER_ZPGHOSTREGS|PLAYER_FULLBUFFERED)) ? 1 : 0);
  1092.   insertdefine("ZPGHOSTREGS", (playerversion & PLAYER_ZPGHOSTREGS) ? 1 : 0);
  1093.   insertdefine("FIXEDPARAMS", fixedparams);
  1094.   insertdefine("SIMPLEPULSE", simplepulse);
  1095.   insertdefine("PULSEOPTIMIZATION", optimizepulse);
  1096.   insertdefine("REALTIMEOPTIMIZATION", optimizerealtime);
  1097.   insertdefine("NOAUTHORINFO", (playerversion & PLAYER_AUTHORINFO) ? 0 : 1);
  1098.   insertdefine("NOEFFECTS", noeffects);
  1099.   insertdefine("NOGATE", nogate);
  1100.   insertdefine("NOFILTER", nofilter);
  1101.   insertdefine("NOFILTERMOD", nofiltermod);
  1102.   insertdefine("NOPULSE", nopulse);
  1103.   insertdefine("NOPULSEMOD", nopulsemod);
  1104.   insertdefine("NOWAVEDELAY", nowavedelay);
  1105.   insertdefine("NOWAVECMD", nowavecmd);
  1106.   insertdefine("NOREPEAT", norepeat);
  1107.   insertdefine("NOTRANS", notrans);
  1108.   insertdefine("NOPORTAMENTO", noportamento);
  1109.   insertdefine("NOTONEPORTA", notoneporta);
  1110.   insertdefine("NOVIB", novib);
  1111.   insertdefine("NOINSTRVIB", noinsvib);
  1112.   insertdefine("NOSETAD", nosetad);
  1113.   insertdefine("NOSETSR", nosetsr);
  1114.   insertdefine("NOSETWAVE", nosetwave);
  1115.   insertdefine("NOSETWAVEPTR", nosetwaveptr);
  1116.   insertdefine("NOSETPULSEPTR", nosetpulseptr);
  1117.   insertdefine("NOSETFILTPTR", nosetfiltptr);
  1118.   insertdefine("NOSETFILTCTRL", nosetfiltctrl);
  1119.   insertdefine("NOSETFILTCUTOFF", nosetfiltcutoff);
  1120.   insertdefine("NOSETMASTERVOL", nosetmastervol);
  1121.   insertdefine("NOFUNKTEMPO", nofunktempo);
  1122.   insertdefine("NOGLOBALTEMPO", noglobaltempo);
  1123.   insertdefine("NOCHANNELTEMPO", nochanneltempo);
  1124.   insertdefine("NOFIRSTWAVECMD", nofirstwavecmd);
  1125.   insertdefine("NOCALCULATEDSPEED", nocalculatedspeed);
  1126.   insertdefine("NONORMALSPEED", nonormalspeed);
  1127.   insertdefine("NOZEROSPEED", nozerospeed);
  1128.  
  1129.   // Insert parameters
  1130.   insertdefine("NUMCHANNELS", channels);
  1131.   insertdefine("NUMSONGS", songs);
  1132.   insertdefine("FIRSTNOTE", firstnote);
  1133.   insertdefine("FIRSTNOHRINSTR", numnormal + 1);
  1134.   insertdefine("FIRSTLEGATOINSTR", numnormal + numnohr + 1);
  1135.   insertdefine("NUMHRINSTR", numnormal);
  1136.   insertdefine("NUMNOHRINSTR", numnohr);
  1137.   insertdefine("NUMLEGATOINSTR", numlegato);
  1138.   insertdefine("ADPARAM", adparam >> 8);
  1139.   insertdefine("SRPARAM", adparam & 0xff);
  1140.   if ((instr[MAX_INSTR-1].ad >= 2) && (!(instr[MAX_INSTR-1].ptr[WTBL])))
  1141.     insertdefine("DEFAULTTEMPO", instr[MAX_INSTR-1].ad - 1);
  1142.   else
  1143.     insertdefine("DEFAULTTEMPO", multiplier ? (multiplier*6-1) : 5);
  1144.  
  1145.   // Fixed firstwave & gatetimer
  1146.   if (fixedparams)
  1147.   {
  1148.     insertdefine("FIRSTWAVEPARAM", instr[1].firstwave);
  1149.     insertdefine("GATETIMERPARAM", instr[1].gatetimer & 0x3f);
  1150.   }
  1151.  
  1152.   // Insert source code of player
  1153.   if (adparam >= 0xf000)
  1154.     playername = "altplayer.s";
  1155.  
  1156.   if (!insertfile(playername))
  1157.   {
  1158.     clearscreen();
  1159.     printtextc(MAX_ROWS/2, CTITLE, "COULD NOT OPEN PLAYROUTINE!");
  1160.     fliptoscreen();
  1161.     waitkeynoupdate();
  1162.     goto PRCLEANUP;
  1163.   }
  1164.   
  1165.   // Modify ghostregs to not be zeropage if needed
  1166.   if ((playerversion & PLAYER_FULLBUFFERED) && (playerversion & PLAYER_ZPGHOSTREGS) == 0)
  1167.   {
  1168.     int bufsize = membuf_get_size(&src);
  1169.     char* bufdata = (char*)membuf_get(&src);
  1170.     int c;
  1171.     for (c = 0; c < bufsize; c++)
  1172.     {
  1173.       if (bufdata[c] == '<')
  1174.       {
  1175.         if (memcmp(bufdata + c + 1, "ghost", 5) == 0)
  1176.           bufdata[c] = ' ';
  1177.       }
  1178.     }
  1179.   }
  1180.  
  1181.   // Insert frequencytable
  1182.   insertlabel("mt_freqtbllo");
  1183.   insertbytes(&freqtbllo[firstnote], lastnote-firstnote+1);
  1184.   insertlabel("mt_freqtblhi");
  1185.   insertbytes(&freqtblhi[firstnote], lastnote-firstnote+1);
  1186.  
  1187.   // Insert songtable
  1188.   insertlabel("mt_songtbllo");
  1189.   for (c = 0; c < songs*3; c++)
  1190.   {
  1191.     sprintf(textbuffer, "mt_song%d", c);
  1192.     insertaddrlo(textbuffer);
  1193.   }
  1194.   insertlabel("mt_songtblhi");
  1195.   for (c = 0; c < songs*3; c++)
  1196.   {
  1197.     sprintf(textbuffer, "mt_song%d", c);
  1198.     insertaddrhi(textbuffer);
  1199.   }
  1200.  
  1201.   // Insert patterntable
  1202.   insertlabel("mt_patttbllo");
  1203.   for (c = 0; c < patterns; c++)
  1204.   {
  1205.     sprintf(textbuffer, "mt_patt%d", c);
  1206.     insertaddrlo(textbuffer);
  1207.   }
  1208.   insertlabel("mt_patttblhi");
  1209.   for (c = 0; c < patterns; c++)
  1210.   {
  1211.     sprintf(textbuffer, "mt_patt%d", c);
  1212.     insertaddrhi(textbuffer);
  1213.   }
  1214.  
  1215.   // Insert instruments
  1216.   insertlabel("mt_insad");
  1217.   insertbytes(&instrwork[0], instruments);
  1218.   insertlabel("mt_inssr");
  1219.   insertbytes(&instrwork[instruments], instruments);
  1220.   insertlabel("mt_inswaveptr");
  1221.   insertbytes(&instrwork[instruments*2], instruments);
  1222.   if (!nopulse)
  1223.   {
  1224.     insertlabel("mt_inspulseptr");
  1225.     insertbytes(&instrwork[instruments*3], instruments);
  1226.   }
  1227.   if (!nofilter)
  1228.   {
  1229.     insertlabel("mt_insfiltptr");
  1230.     insertbytes(&instrwork[instruments*4], instruments);
  1231.   }
  1232.   if (!noinsvib)
  1233.   {
  1234.     insertlabel("mt_insvibparam");
  1235.     insertbytes(&instrwork[instruments*5], instruments);
  1236.     insertlabel("mt_insvibdelay");
  1237.     insertbytes(&instrwork[instruments*6], instruments);
  1238.   }
  1239.   if (!fixedparams)
  1240.   {
  1241.     insertlabel("mt_insgatetimer");
  1242.     insertbytes(&instrwork[instruments*7], instruments);
  1243.     insertlabel("mt_insfirstwave");
  1244.     insertbytes(&instrwork[instruments*8], instruments);
  1245.   }
  1246.  
  1247.   // Insert tables
  1248.   for (c = 0; c < MAX_TABLES; c++)
  1249.   {
  1250.     if ((c == PTBL) && (nopulse)) goto SKIPTABLE;
  1251.     if ((c == FTBL) && (nofilter)) goto SKIPTABLE;
  1252.  
  1253.     // Write table left side
  1254.     // Extra zero for speedtable
  1255.     if ((c == STBL) && ((!novib) || (!nofunktempo) || (!noportamento) || (!notoneporta))) insertbyte(0);
  1256.     // Table label
  1257.     insertlabel(tableleftname[c]);
  1258.  
  1259.     // Table data
  1260.     for (d = 0; d < MAX_TABLELEN; d++)
  1261.     {
  1262.       if (tableused[c][d+1])
  1263.       {
  1264.         switch (c)
  1265.         {
  1266.           // In wavetable, convert waveform values for the playroutine
  1267.           case WTBL:
  1268.           {
  1269.             unsigned char wave = ltable[c][d];
  1270.             if ((ltable[c][d] >= WAVESILENT) && (ltable[c][d] <= WAVELASTSILENT)) wave &= 0xf;
  1271.             if ((ltable[c][d] > WAVELASTDELAY) && (ltable[c][d] <= WAVELASTSILENT) && (!nowavedelay)) wave += 0x10;
  1272.             insertbyte(wave);
  1273.           }
  1274.           break;
  1275.  
  1276.           case PTBL:
  1277.           if ((simplepulse) && (ltable[c][d] != 0xff) && (ltable[c][d] > 0x80))
  1278.             insertbyte(0x80);
  1279.           else
  1280.             insertbyte(ltable[c][d]);
  1281.           break;
  1282.  
  1283.           // In filtertable, modify passband bits
  1284.           case FTBL:
  1285.           if ((ltable[c][d] != 0xff) && (ltable[c][d] > 0x80))
  1286.             insertbyte(((ltable[c][d] & 0x70) >> 1) | 0x80);
  1287.           else
  1288.             insertbyte(ltable[c][d]);
  1289.           break;
  1290.  
  1291.           default:
  1292.           insertbyte(ltable[c][d]);
  1293.           break;
  1294.         }
  1295.       }
  1296.     }
  1297.  
  1298.     // Write table right side, remapping jumps as necessary
  1299.     // Extra zero for speedtable
  1300.     if ((c == STBL) && ((!novib) || (!nofunktempo) || (!noportamento) || (!notoneporta))) insertbyte(0);
  1301.     // Table label
  1302.     insertlabel(tablerightname[c]);
  1303.  
  1304.     for (d = 0; d < MAX_TABLELEN; d++)
  1305.     {
  1306.       if (tableused[c][d+1])
  1307.       {
  1308.         if ((ltable[c][d] != 0xff) || (c == STBL))
  1309.         {
  1310.           switch(c)
  1311.           {
  1312.             case WTBL:
  1313.             if ((ltable[c][d] >= WAVECMD) && (ltable[c][d] <= WAVELASTCMD))
  1314.             {
  1315.               // Remap table-referencing commands
  1316.               switch (ltable[c][d] - WAVECMD)
  1317.               {
  1318.                 case CMD_PORTAUP:
  1319.                 case CMD_PORTADOWN:
  1320.                 case CMD_TONEPORTA:
  1321.                 case CMD_VIBRATO:
  1322.                 insertbyte(tablemap[STBL][rtable[c][d]]);
  1323.                 break;
  1324.  
  1325.                 case CMD_SETPULSEPTR:
  1326.                 insertbyte(tablemap[PTBL][rtable[c][d]]);
  1327.                 break;
  1328.  
  1329.                 case CMD_SETFILTERPTR:
  1330.                 insertbyte(tablemap[FTBL][rtable[c][d]]);
  1331.                 break;
  1332.  
  1333.                 default:
  1334.                 insertbyte(rtable[c][d]);
  1335.                 break;
  1336.               }
  1337.             }
  1338.             else
  1339.             {
  1340.               // For normal notes, reverse all right side high bits
  1341.               insertbyte(rtable[c][d] ^ 0x80);
  1342.             }
  1343.             break;
  1344.  
  1345.             case PTBL:
  1346.             if (simplepulse)
  1347.             {
  1348.               if (ltable[c][d] >= 0x80)
  1349.                 insertbyte((ltable[c][d] & 0x0f) | (rtable[c][d] & 0xf0));
  1350.               else
  1351.               {
  1352.                 int pulsespeed = rtable[c][d] >> 4;
  1353.                 if (rtable[c][d] & 0x80)
  1354.                 {
  1355.                   pulsespeed |= 0xf0;
  1356.                   pulsespeed--;
  1357.                 }
  1358.                 pulsespeed = swapnybbles(pulsespeed);
  1359.                 insertbyte(pulsespeed);
  1360.               }
  1361.             }
  1362.             else
  1363.               insertbyte(rtable[c][d]);
  1364.             break;
  1365.  
  1366.             default:
  1367.             insertbyte(rtable[c][d]);
  1368.             break;
  1369.           }
  1370.         }
  1371.         else
  1372.           insertbyte(tablemap[c][rtable[c][d]]);
  1373.       }
  1374.     }
  1375.  
  1376.     SKIPTABLE: ;
  1377.   }
  1378.  
  1379.   // Insert orderlists
  1380.   for (c = 0; c < songs; c++)
  1381.   {
  1382.     for (d = 0; d < MAX_CHN; d++)
  1383.     {
  1384.       sprintf(textbuffer, "mt_song%d", c*3+d);
  1385.       insertlabel(textbuffer);
  1386.       insertbytes(&songwork[songoffset[c][d]], songsize[c][d]);
  1387.     }
  1388.   }
  1389.  
  1390.   // Insert patterns
  1391.   for (c = 0; c < patterns; c++)
  1392.   {
  1393.     sprintf(textbuffer, "mt_patt%d", c);
  1394.     insertlabel(textbuffer);
  1395.     insertbytes(&pattwork[pattoffset[c]], pattsize[c]);
  1396.   }
  1397.  
  1398.   /* {
  1399.     FILE *handle = fopen("debug.s", "wb");
  1400.     fwrite(membuf_get(&src), membuf_memlen(&src), 1, handle);
  1401.     fclose(handle);
  1402.   } */
  1403.  
  1404.   // Assemble; on error fail in a rude way (the parser does so too)
  1405.   if (assemble(&src, &dest)) exit(1);
  1406.  
  1407.   packeddata = membuf_get(&dest);
  1408.   packedsize = membuf_memlen(&dest);
  1409.   playersize = packedsize - songtblsize - songdatasize - patttblsize - pattdatasize - instrsize - wavetblsize - pulsetblsize - filttblsize - speedtblsize;
  1410.  
  1411.   // Copy author info
  1412.   if (playerversion & PLAYER_AUTHORINFO)
  1413.   {
  1414.     for (c = 0; c < 32; c++)
  1415.     {
  1416.       packeddata[32+c] = authorname[c];
  1417.       // Convert 0 to space
  1418.       if (packeddata[32+c] == 0) packeddata[32+c] = 0x20;
  1419.     }
  1420.   }
  1421.  
  1422.   // Print results
  1423. #ifdef GT2RELOC
  1424.   fprintf(STDOUT, "packing results:\n");
  1425.   fprintf(STDOUT, "Playroutine:     %d bytes\n", playersize);
  1426.   fprintf(STDOUT, "Songtable:       %d bytes\n", songtblsize);
  1427.   fprintf(STDOUT, "Song-orderlists: %d bytes\n", songdatasize);
  1428.   fprintf(STDOUT, "Patterntable:    %d bytes\n", patttblsize);
  1429.   fprintf(STDOUT, "Patterns:        %d bytes\n", pattdatasize);
  1430.   fprintf(STDOUT, "Instruments:     %d bytes\n", instrsize);
  1431.   fprintf(STDOUT, "Tables:          %d bytes\n", wavetblsize+pulsetblsize+filttblsize+speedtblsize);
  1432.   fprintf(STDOUT, "Total size:      %d bytes\n", packedsize);
  1433.  
  1434.   songhandle = fopen(packedsongname, "wb");
  1435.   if (!songhandle) 
  1436.   {
  1437.       fprintf(STDERR, "error: could not open output file '%s'.\n", packedsongname);
  1438.       goto PRCLEANUP;
  1439.   }
  1440.  
  1441. #else
  1442.   clearscreen();
  1443.   printblankc(0, 0, 15+16, MAX_COLUMNS);
  1444.   if (!strlen(loadedsongfilename))
  1445.     sprintf(textbuffer, "%s Packer/Relocator", programname);
  1446.   else
  1447.     sprintf(textbuffer, "%s Packer/Relocator - %s", programname, loadedsongfilename);
  1448.   textbuffer[80] = 0;
  1449.   printtext(0, 0, 15+16, textbuffer);
  1450.  
  1451.   sprintf(textbuffer, "PACKING RESULTS:");
  1452.   printtext(1, 2, 15, textbuffer);
  1453.  
  1454.   sprintf(textbuffer, "Playroutine:     %d bytes", playersize);
  1455.   printtext(1, 3, 7, textbuffer);
  1456.   sprintf(textbuffer, "Songtable:       %d bytes", songtblsize);
  1457.   printtext(1, 4, 7, textbuffer);
  1458.   sprintf(textbuffer, "Song-orderlists: %d bytes", songdatasize);
  1459.   printtext(1, 5, 7, textbuffer);
  1460.   sprintf(textbuffer, "Patterntable:    %d bytes", patttblsize);
  1461.   printtext(1, 6, 7, textbuffer);
  1462.   sprintf(textbuffer, "Patterns:        %d bytes", pattdatasize);
  1463.   printtext(1, 7, 7, textbuffer);
  1464.   sprintf(textbuffer, "Instruments:     %d bytes", instrsize);
  1465.   printtext(1, 8, 7, textbuffer);
  1466.   sprintf(textbuffer, "Tables:          %d bytes", wavetblsize+pulsetblsize+filttblsize+speedtblsize);
  1467.   printtext(1, 9, 7, textbuffer);
  1468.   sprintf(textbuffer, "Total size:      %d bytes", packedsize);
  1469.   printtext(1, 11, 7, textbuffer);
  1470.   fliptoscreen();
  1471.  
  1472.  
  1473.   // Now ask for fileformat
  1474.   printtext(1, 13, CTITLE, "SELECT FORMAT TO SAVE IN: (CURSORS=MOVE, ENTER=ACCEPT, ESC=CANCEL)");
  1475.  
  1476.   selectdone = 0;
  1477.  
  1478.   while (!selectdone)
  1479.   {
  1480.     switch(fileformat)
  1481.     {
  1482.       case FORMAT_SID:
  1483.       printtext(1, 14, CEDIT, "SID - SIDPlay music file format          ");
  1484.       strcpy(packedfilter, "*.sid");
  1485.       break;
  1486.  
  1487.       case FORMAT_PRG:
  1488.       printtext(1, 14, CEDIT, "PRG - C64 native format                  ");
  1489.       strcpy(packedfilter, "*.prg");
  1490.       break;
  1491.  
  1492.       case FORMAT_BIN:
  1493.       printtext(1, 14, CEDIT, "BIN - Raw binary format (no startaddress)");
  1494.       strcpy(packedfilter, "*.bin");
  1495.       break;
  1496.     }
  1497.  
  1498.     fliptoscreen();
  1499.     waitkeynoupdate();
  1500.  
  1501.     if (win_quitted)
  1502.     {
  1503.       exitprogram = 1;
  1504.       goto PRCLEANUP;
  1505.     }
  1506.  
  1507.     switch(rawkey)
  1508.     {
  1509.       case KEY_LEFT:
  1510.       case KEY_DOWN:
  1511.       fileformat--;
  1512.       if (fileformat < FORMAT_SID) fileformat = FORMAT_BIN;
  1513.       break;
  1514.  
  1515.       case KEY_RIGHT:
  1516.       case KEY_UP:
  1517.       fileformat++;
  1518.       if (fileformat > FORMAT_BIN) fileformat = FORMAT_SID;
  1519.       break;
  1520.  
  1521.       case KEY_ESC:
  1522.       selectdone = -1;
  1523.       break;
  1524.  
  1525.       case KEY_ENTER:
  1526.       selectdone = 1;
  1527.       break;
  1528.     }
  1529.   }
  1530.   if (selectdone == -1) goto PRCLEANUP;
  1531.  
  1532.   // By default, copy loaded song name up to the extension
  1533.   memset(packedsongname, 0, sizeof packedsongname);
  1534.   for (c = 0; c < strlen(loadedsongfilename); c++)
  1535.   {
  1536.     if (loadedsongfilename[c] == '.') break;
  1537.     packedsongname[c] = loadedsongfilename[c];
  1538.   }
  1539.   switch (fileformat)
  1540.   {
  1541.     case FORMAT_PRG:
  1542.     strcat(packedsongname, ".prg");
  1543.     break;
  1544.  
  1545.     case FORMAT_BIN:
  1546.     strcat(packedsongname, ".bin");
  1547.     break;
  1548.  
  1549.     case FORMAT_SID:
  1550.     strcat(packedsongname, ".sid");
  1551.     break;
  1552.   }
  1553.  
  1554.   // Now ask for filename, retry if unsuccessful
  1555.   while (!songhandle)
  1556.   {
  1557.     if (!fileselector(packedsongname, packedpath, packedfilter, "Save Music+Playroutine", 3))
  1558.       goto PRCLEANUP;
  1559.  
  1560.     if (strlen(packedsongname) < MAX_FILENAME-4)
  1561.     {
  1562.       int extfound = 0;
  1563.       for (c = strlen(packedsongname)-1; c >= 0; c--)
  1564.       {
  1565.         if (packedsongname[c] == '.') extfound = 1;
  1566.       }
  1567.       if (!extfound)
  1568.       {
  1569.         switch (fileformat)
  1570.         {
  1571.           case FORMAT_PRG:
  1572.           strcat(packedsongname, ".prg");
  1573.           break;
  1574.  
  1575.           case FORMAT_BIN:
  1576.           strcat(packedsongname, ".bin");
  1577.           break;
  1578.  
  1579.           case FORMAT_SID:
  1580.           strcat(packedsongname, ".sid");
  1581.           break;
  1582.         }
  1583.       }
  1584.     }
  1585.     songhandle = fopen(packedsongname, "wb");
  1586.   }
  1587. #endif
  1588.  
  1589.   if (fileformat == FORMAT_PRG)
  1590.   {
  1591.     fwritele16(songhandle, playeradr);
  1592.   }
  1593.   if (fileformat == FORMAT_SID)
  1594.   {
  1595.     unsigned char ident[] = {'P', 'S', 'I', 'D', 0x00, 0x02, 0x00, 0x7c};
  1596.     unsigned char byte;
  1597.     // Identification
  1598.     fwrite(ident, sizeof ident, 1, songhandle);
  1599.  
  1600.     // Load address
  1601.     byte = 0x00;
  1602.     fwrite8(songhandle, byte);
  1603.     fwrite8(songhandle, byte);
  1604.  
  1605.     // Init address
  1606.     if ((multiplier > 1) || (!multiplier))
  1607.     {
  1608.       unsigned speedvalue;
  1609.       byte = (playeradr-10) >> 8;
  1610.       fwrite8(songhandle, byte);
  1611.       byte = (playeradr-10) & 0xff;
  1612.       fwrite8(songhandle, byte);
  1613.  
  1614.       if (multiplier)
  1615.       {
  1616.         if (ntsc) speedvalue = 0x42c6/multiplier;
  1617.         else speedvalue = 0x4cc7/multiplier;
  1618.       }
  1619.       else
  1620.       {
  1621.         if (ntsc) speedvalue = 0x42c6*2;
  1622.         else speedvalue = 0x4cc7*2;
  1623.       }
  1624.       speedcode[1] = speedvalue & 0xff;
  1625.       speedcode[6] = speedvalue >> 8;
  1626.     }
  1627.     else
  1628.     {
  1629.       byte = (playeradr) >> 8;
  1630.       fwrite8(songhandle, byte);
  1631.       byte = (playeradr) & 0xff;
  1632.       fwrite8(songhandle, byte);
  1633.     }
  1634.  
  1635.     // Play address
  1636.     byte = (playeradr+3) >> 8;
  1637.     fwrite8(songhandle, byte);
  1638.     byte = (playeradr+3) & 0xff;
  1639.     fwrite8(songhandle, byte);
  1640.  
  1641.     // Number of subtunes
  1642.     byte = 0x00;
  1643.     fwrite8(songhandle, byte);
  1644.     byte = songs;
  1645.     fwrite8(songhandle, byte);
  1646.  
  1647.     // Default subtune
  1648.     byte = 0x00;
  1649.     fwrite8(songhandle, byte);
  1650.     byte = 0x01;
  1651.     fwrite8(songhandle, byte);
  1652.  
  1653.     // Song speed bits
  1654.     byte = 0x00;
  1655.     if ((ntsc) || (multiplier > 1) || (!multiplier)) byte = 0xff;
  1656.     fwrite8(songhandle, byte);
  1657.     fwrite8(songhandle, byte);
  1658.     fwrite8(songhandle, byte);
  1659.     fwrite8(songhandle, byte);
  1660.  
  1661.     // Songname etc.
  1662.     fwrite(songname, sizeof songname, 1, songhandle);
  1663.     fwrite(authorname, sizeof authorname, 1, songhandle);
  1664.     fwrite(copyrightname, sizeof copyrightname, 1, songhandle);
  1665.  
  1666.     // Flags
  1667.     byte = 0x00;
  1668.     fwrite8(songhandle, byte);
  1669.     if (ntsc) byte = 8;
  1670.       else byte = 4;
  1671.     if (sidmodel) byte |= 32;
  1672.       else byte |= 16;
  1673.     fwrite8(songhandle, byte);
  1674.  
  1675.     // Reserved longword
  1676.     byte = 0x00;
  1677.     fwrite8(songhandle, byte);
  1678.     fwrite8(songhandle, byte);
  1679.     fwrite8(songhandle, byte);
  1680.     fwrite8(songhandle, byte);
  1681.  
  1682.     // Load address
  1683.     if ((multiplier > 1) || (!multiplier))
  1684.     {
  1685.       byte = (playeradr-10) & 0xff;
  1686.       fwrite8(songhandle, byte);
  1687.       byte = (playeradr-10) >> 8;
  1688.       fwrite8(songhandle, byte);
  1689.     }
  1690.     else
  1691.     {
  1692.       byte = (playeradr) & 0xff;
  1693.       fwrite8(songhandle, byte);
  1694.       byte = (playeradr) >> 8;
  1695.       fwrite8(songhandle, byte);
  1696.     }
  1697.     if ((multiplier > 1) || (!multiplier)) fwrite(speedcode, 10, 1, songhandle);
  1698.   }
  1699.  
  1700.   fwrite(packeddata, packedsize, 1, songhandle);
  1701.   fclose(songhandle);
  1702.  
  1703.   PRCLEANUP:
  1704.   membuf_free(&src);
  1705.   membuf_free(&dest);
  1706.  
  1707.   if (pattwork) free(pattwork);
  1708.   if (songwork) free(songwork);
  1709.   if (instrwork) free(instrwork);
  1710.   printmainscreen();
  1711.   key = 0;
  1712.   rawkey = 0;
  1713. }
  1714.  
  1715. int packpattern(unsigned char *dest, unsigned char *src, int rows)
  1716. {
  1717.   unsigned char temp1[MAX_PATTROWS*4];
  1718.   unsigned char temp2[512];
  1719.   unsigned char instr = 0;
  1720.   int command = -1;
  1721.   int databyte = -1;
  1722.   int destsizeim = 0;
  1723.   int destsize = 0;
  1724.   int c, d;
  1725.  
  1726.   // First optimize instrument changes
  1727.   for (c = 0; c < rows; c++)
  1728.   {
  1729.     if ((c) && (src[c*4+1]) && (src[c*4+1] == instr))
  1730.     {
  1731.       temp1[c*4] = src[c*4];
  1732.       temp1[c*4+1] = 0;
  1733.       temp1[c*4+2] = src[c*4+2];
  1734.       temp1[c*4+3] = src[c*4+3];
  1735.     }
  1736.     else
  1737.     {
  1738.       temp1[c*4] = src[c*4];
  1739.       temp1[c*4+1] = src[c*4+1];
  1740.       temp1[c*4+2] = src[c*4+2];
  1741.       temp1[c*4+3] = src[c*4+3];
  1742.       if (src[c*4+1])
  1743.         instr = src[c*4+1];
  1744.     }
  1745.  
  1746.     switch(temp1[c*4+2])
  1747.     {
  1748.       // Remap speedtable commands
  1749.       case CMD_PORTAUP:
  1750.       case CMD_PORTADOWN:
  1751.       noportamento = 0;
  1752.       temp1[c*4+3] = tablemap[STBL][temp1[c*4+3]];
  1753.       break;
  1754.  
  1755.       case CMD_TONEPORTA:
  1756.       notoneporta = 0;
  1757.       temp1[c*4+3] = tablemap[STBL][temp1[c*4+3]];
  1758.       break;
  1759.  
  1760.       case CMD_VIBRATO:
  1761.       novib = 0;
  1762.       temp1[c*4+3] = tablemap[STBL][temp1[c*4+3]];
  1763.       break;
  1764.  
  1765.       case CMD_SETAD:
  1766.       nosetad = 0;
  1767.       break;
  1768.  
  1769.       case CMD_SETSR:
  1770.       nosetsr = 0;
  1771.       break;
  1772.  
  1773.       case CMD_SETWAVE:
  1774.       nosetwave = 0;
  1775.       break;
  1776.  
  1777.       // Remap table commands
  1778.       case CMD_SETWAVEPTR:
  1779.       nosetwaveptr = 0;
  1780.       temp1[c*4+3] = tablemap[WTBL][temp1[c*4+3]];
  1781.       break;
  1782.  
  1783.       case CMD_SETPULSEPTR:
  1784.       nosetpulseptr = 0;
  1785.       nopulse = 0;
  1786.       temp1[c*4+3] = tablemap[PTBL][temp1[c*4+3]];
  1787.       break;
  1788.  
  1789.       case CMD_SETFILTERPTR:
  1790.       nosetfiltptr = 0;
  1791.       nofilter = 0;
  1792.       temp1[c*4+3] = tablemap[FTBL][temp1[c*4+3]];
  1793.       break;
  1794.  
  1795.       case CMD_SETFILTERCTRL:
  1796.       nosetfiltctrl = 0;
  1797.       nofilter = 0;
  1798.       break;
  1799.  
  1800.       case CMD_SETFILTERCUTOFF:
  1801.       nosetfiltcutoff = 0;
  1802.       nofilter = 0;
  1803.       break;
  1804.  
  1805.       case CMD_SETMASTERVOL:
  1806.       nosetmastervol = 0;
  1807.       // If no authorinfo being saved, erase timingmarks (not supported)
  1808.       if (!(playerversion & PLAYER_AUTHORINFO))
  1809.       {
  1810.         if (temp1[c*4+3] > 0x0f)
  1811.         {
  1812.           temp1[c*4+2] = 0;
  1813.           temp1[c*4+3] = 0;
  1814.         }
  1815.       }
  1816.       break;
  1817.  
  1818.       case CMD_FUNKTEMPO:
  1819.       nofunktempo = 0;
  1820.       temp1[c*4+3] = tablemap[STBL][temp1[c*4+3]];
  1821.       break;
  1822.  
  1823.       case CMD_SETTEMPO:
  1824.       if (temp1[c*4+3] >= 0x80) nochanneltempo = 0;
  1825.       else noglobaltempo = 0;
  1826.       // Decrease databyte of all tempo commands for the playroutine
  1827.       // Do not touch funktempo
  1828.       if ((temp1[c*4+3] & 0x7f) >= 3)
  1829.         temp1[c*4+3]--;
  1830.       break;
  1831.  
  1832.     }
  1833.   }
  1834.  
  1835.   if (noeffects)
  1836.   {
  1837.     command = 0;
  1838.     databyte = 0;
  1839.   }
  1840.  
  1841.   // Write in playroutine format
  1842.   for (c = 0; c < rows; c++)
  1843.   {
  1844.     // Instrument change with mapping
  1845.     if (temp1[c*4+1])
  1846.     {
  1847.       temp2[destsizeim++] = instrmap[INSTRCHG+temp1[c*4+1]];
  1848.     }
  1849.     // Rest+FX
  1850.     if (temp1[c*4] == REST)
  1851.     {
  1852.       if ((temp1[c*4+2] != command) || (temp1[c*4+3] != databyte))
  1853.       {
  1854.         command = temp1[c*4+2];
  1855.         databyte = temp1[c*4+3];
  1856.         temp2[destsizeim++] = FXONLY+command;
  1857.         if (command)
  1858.           temp2[destsizeim++] = databyte;
  1859.       }
  1860.       else
  1861.         temp2[destsizeim++] = REST;
  1862.     }
  1863.     else
  1864.     {
  1865.       // Normal note
  1866.       if ((temp1[c*4+2] != command) || (temp1[c*4+3] != databyte))
  1867.       {
  1868.         command = temp1[c*4+2];
  1869.         databyte = temp1[c*4+3];
  1870.         temp2[destsizeim++] = FX+command;
  1871.         if (command)
  1872.           temp2[destsizeim++] = databyte;
  1873.       }
  1874.       temp2[destsizeim++] = temp1[c*4];
  1875.     }
  1876.   }
  1877.  
  1878.   // Final step: optimize long singlebyte rests with "packed rest"
  1879.   for (c = 0; c < destsizeim;)
  1880.   {
  1881.     int packok = 1;
  1882.  
  1883.     // Never pack first row or sequencer goes crazy
  1884.     if (!c) packok = 0;
  1885.     
  1886.     // There must be no instrument or command changes on the row to be packed
  1887.     if (temp2[c] < FX)
  1888.     {
  1889.       dest[destsize++] = temp2[c++];
  1890.       packok = 0;
  1891.     }
  1892.     if ((temp2[c] >= FXONLY) && (temp2[c] < FIRSTNOTE))
  1893.     {
  1894.       int fxnum = temp2[c] - FXONLY;
  1895.       dest[destsize++] = temp2[c++];
  1896.       if (fxnum) dest[destsize++] = temp2[c++];
  1897.       packok = 0;
  1898.       goto NEXTROW;
  1899.     }
  1900.     if (temp2[c] < FXONLY)
  1901.      {
  1902.       int fxnum = temp2[c] - FX;
  1903.       dest[destsize++] = temp2[c++];
  1904.       if (fxnum) dest[destsize++] = temp2[c++];
  1905.       packok = 0;
  1906.     }
  1907.  
  1908.     if (temp2[c] != REST) packok = 0;
  1909.  
  1910.     if (!packok)
  1911.       dest[destsize++] = temp2[c++];
  1912.     else
  1913.     {
  1914.       for (d = c; d < destsizeim; )
  1915.       {
  1916.         if (temp2[d] == REST)
  1917.         {
  1918.           d++;
  1919.           if (d-c == 64) break;
  1920.         }
  1921.         else break;
  1922.       }
  1923.       d -= c;
  1924.       if (d > 1)
  1925.       {
  1926.         dest[destsize++] = -d;
  1927.         c += d;
  1928.       }
  1929.       else
  1930.         dest[destsize++] = temp2[c++];
  1931.     }
  1932.     NEXTROW: {}
  1933.   }
  1934.   // See if pattern too big
  1935.   if (destsize > 256) return -1;
  1936.  
  1937.   // If less than 256 bytes, insert endmark
  1938.   if (destsize < 256)
  1939.   dest[destsize++] = 0x00;
  1940.  
  1941.   return destsize;
  1942. }
  1943.  
  1944. int testoverlap(int area1start, int area1size, int area2start, int area2size)
  1945. {
  1946.   int area1last = area1start+area1size-1;
  1947.   int area2last = area2start+area2size-1;
  1948.  
  1949.   if (area1start == area2start) return 1;
  1950.  
  1951.   if (area1start < area2start)
  1952.   {
  1953.     if (area1last < area2start) return 0;
  1954.     else return 1;
  1955.   }
  1956.   else
  1957.   {
  1958.     if (area2last < area1start) return 0;
  1959.     else return 1;
  1960.   }
  1961. }
  1962.  
  1963. unsigned char swapnybbles(unsigned char n)
  1964. {
  1965.   unsigned char highnybble = n >> 4;
  1966.   unsigned char lownybble = n & 0xf;
  1967.  
  1968.   return (lownybble << 4) | highnybble;
  1969. }
  1970.  
  1971. int insertfile(char *name)
  1972. {
  1973.   int size;
  1974.   int handle = io_open(name);
  1975.   if (handle == -1) return 0;
  1976.  
  1977.   size = io_lseek(handle, 0, SEEK_END);
  1978.   io_lseek(handle, 0, SEEK_SET);
  1979.   while (size--)
  1980.   {
  1981.     membuf_append_char(&src, io_read8(handle));
  1982.   }
  1983.   io_close(handle);
  1984.   return 1;
  1985. }
  1986.  
  1987. void inserttext(const char *text)
  1988. {
  1989.   membuf_append(&src, text, strlen(text));
  1990. }
  1991.  
  1992. void insertdefine(const char *name, int value)
  1993. {
  1994.   char insertbuffer[80];
  1995.  
  1996.   sprintf(insertbuffer, "%-16s = %d\n", name, value);
  1997.   inserttext(insertbuffer);
  1998. }
  1999.  
  2000. void insertlabel(const char *name)
  2001. {
  2002.   char insertbuffer[80];
  2003.  
  2004.   sprintf(insertbuffer, "%s:\n", name);
  2005.   inserttext(insertbuffer);
  2006. }
  2007.  
  2008. void insertbytes(const unsigned char *bytes, int size)
  2009. {
  2010.   char insertbuffer[80];
  2011.   int row = 0;
  2012.  
  2013.   while (size--)
  2014.   {
  2015.     if (!row)
  2016.     {
  2017.       inserttext("                .BYTE (");
  2018.       sprintf(insertbuffer, "$%02x", *bytes);
  2019.       inserttext(insertbuffer);
  2020.       bytes++;
  2021.       row++;
  2022.     }
  2023.     else
  2024.     {
  2025.       sprintf(insertbuffer, ",$%02x", *bytes);
  2026.       inserttext(insertbuffer);
  2027.       bytes++;
  2028.       row++;
  2029.       if (row == MAX_BYTES_PER_ROW)
  2030.       {
  2031.         inserttext(")\n");
  2032.         row = 0;
  2033.       }
  2034.     }
  2035.   }
  2036.   if (row) inserttext(")\n");
  2037. }
  2038.  
  2039. void insertbyte(unsigned char byte)
  2040. {
  2041.   char insertbuffer[80];
  2042.  
  2043.   sprintf(insertbuffer, "                .BYTE ($%02x)\n", byte);
  2044.   inserttext(insertbuffer);
  2045. }
  2046.  
  2047. void insertaddrlo(const char *name)
  2048. {
  2049.   char insertbuffer[80];
  2050.  
  2051.   sprintf(insertbuffer, "                .BYTE (%s %% 256)\n", name);
  2052.   inserttext(insertbuffer);
  2053. }
  2054.  
  2055. void insertaddrhi(const char *name)
  2056. {
  2057.   char insertbuffer[80];
  2058.  
  2059.   sprintf(insertbuffer, "                .BYTE (%s / 256)\n", name);
  2060.   inserttext(insertbuffer);
  2061. }
  2062.  
  2063. void findtableduplicates(int num)
  2064. {
  2065.   int c,d,e;
  2066.  
  2067.   if (num == STBL)
  2068.   {
  2069.     for (c = 1; c <= MAX_TABLELEN; c++)
  2070.     {
  2071.       if (tableused[num][c])
  2072.       {
  2073.         for (d = c+1; d <= MAX_TABLELEN; d++)
  2074.         {
  2075.           if (tableused[num][d])
  2076.           {
  2077.             if ((ltable[num][d-1] == ltable[num][c-1]) && (rtable[num][d-1] == rtable[num][c-1]))
  2078.             {
  2079.               // Duplicate found, remove and map to the original
  2080.               tableused[num][d] = 0;
  2081.               for (e = d; e <= MAX_TABLELEN; e++)
  2082.                 if (tableused[num][e]) tablemap[num][e]--;
  2083.               tablemap[num][d] = tablemap[num][c];
  2084.             }
  2085.           }
  2086.         }
  2087.       }
  2088.     }
  2089.   }
  2090.   else
  2091.   {
  2092.     for (c = 1; c <= MAX_TABLELEN; c++)
  2093.     {
  2094.       if (isusedandselfcontained(num, c))
  2095.       {
  2096.         for (d = c + gettablepartlen(num, c - 1); d <= MAX_TABLELEN; )
  2097.         {
  2098.           int len = gettablepartlen(num, d - 1);
  2099.  
  2100.           if (isusedandselfcontained(num, d))
  2101.           {
  2102.             for (e = 0; e < len; e++)
  2103.             {
  2104.               if (e < len-1)
  2105.               {
  2106.                 // Is table data the same?
  2107.                 if ((ltable[num][d+e-1] != ltable[num][c+e-1]) || (rtable[num][d+e-1] != rtable[num][c+e-1]))
  2108.                   break;
  2109.               }
  2110.               else
  2111.               {
  2112.                 // Do both parts have a jump in the end?
  2113.                 if (ltable[num][d+e-1] != ltable[num][c+e-1])
  2114.                   break;
  2115.                 // Do both parts end?
  2116.                 if (rtable[num][d+e-1] == 0)
  2117.                 {
  2118.                   if (rtable[num][c+e-1] != 0)
  2119.                     break;
  2120.                 }
  2121.                 else
  2122.                 {
  2123.                   // Do both parts loop in the same way?
  2124.                   if ((rtable[num][d+e-1] - d) != (rtable[num][c+e-1] - c))
  2125.                     break;
  2126.                 }
  2127.               }
  2128.             }
  2129.             if (e == len)
  2130.             {
  2131.               // Duplicate found, remove and map to the original
  2132.               for (e = 0; e < len; e++)
  2133.                 tableused[num][d+e] = 0;
  2134.               for (e = d; e < MAX_TABLELEN; e++)
  2135.                 if (tableused[num][e]) tablemap[num][e] -= len;
  2136.               for (e = 0; e < len; e++)
  2137.                 tablemap[num][d+e] = tablemap[num][c+e];
  2138.             }
  2139.           }
  2140.           d += len;
  2141.         }
  2142.       }
  2143.     }
  2144.   }
  2145. }
  2146.  
  2147. int isusedandselfcontained(int num, int start)
  2148. {
  2149.   int len = gettablepartlen(num, start - 1);
  2150.   int end = start + len - 1;
  2151.   int c;
  2152.  
  2153.   // Don't use jumps only
  2154.   if (len == 1) return 0;
  2155.  
  2156.   // Check that whole table is used
  2157.   for (c = start; c <= end; c++)
  2158.   {
  2159.     if (tableused[num][c] == 0) return 0;
  2160.   }
  2161.   // Check for jump to outside
  2162.   if (rtable[num][end-1] != 0)
  2163.   {
  2164.     if ((rtable[num][end-1] < start) || (rtable[num][end-1] > end)) return 0;
  2165.   }
  2166.   // Check for jump from outside
  2167.   for (c = 1; c < start; c++)
  2168.     if ((tableused[num][c]) && (ltable[num][c-1] == 0xff) && (rtable[num][c-1] >= start) && (rtable[num][c-1] <= end)) return 0;
  2169.   for (c = end+1; c <= MAX_TABLELEN; c++)
  2170.     if ((tableused[num][c]) && (ltable[num][c-1] == 0xff) && (rtable[num][c-1] >= start) && (rtable[num][c-1] <= end)) return 0;
  2171.  
  2172.   // OK!
  2173.   return 1;
  2174. }
  2175.  
  2176. void calcspeedtest(unsigned char pos)
  2177. {
  2178.   if (!pos) 
  2179.   {
  2180.     nozerospeed = 0;
  2181.     return;
  2182.   }
  2183.  
  2184.   if (ltable[STBL][pos-1] >= 0x80) nocalculatedspeed = 0;
  2185.   else nonormalspeed = 0;
  2186. }
  2187.  
  2188.  
  2189.