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