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