home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / goattracker_2.71_stereo.zip / src / gplay.c < prev    next >
C/C++ Source or Header  |  2008-05-17  |  33KB  |  1,182 lines

  1. //
  2. // GOATTRACKER v2 playroutine
  3. //
  4.  
  5. #define GPLAY_C
  6.  
  7. #include "goattrk2.h"
  8.  
  9. unsigned char freqtbllo[] = {
  10.   0x17,0x27,0x39,0x4b,0x5f,0x74,0x8a,0xa1,0xba,0xd4,0xf0,0x0e,
  11.   0x2d,0x4e,0x71,0x96,0xbe,0xe8,0x14,0x43,0x74,0xa9,0xe1,0x1c,
  12.   0x5a,0x9c,0xe2,0x2d,0x7c,0xcf,0x28,0x85,0xe8,0x52,0xc1,0x37,
  13.   0xb4,0x39,0xc5,0x5a,0xf7,0x9e,0x4f,0x0a,0xd1,0xa3,0x82,0x6e,
  14.   0x68,0x71,0x8a,0xb3,0xee,0x3c,0x9e,0x15,0xa2,0x46,0x04,0xdc,
  15.   0xd0,0xe2,0x14,0x67,0xdd,0x79,0x3c,0x29,0x44,0x8d,0x08,0xb8,
  16.   0xa1,0xc5,0x28,0xcd,0xba,0xf1,0x78,0x53,0x87,0x1a,0x10,0x71,
  17.   0x42,0x89,0x4f,0x9b,0x74,0xe2,0xf0,0xa6,0x0e,0x33,0x20,0xff,
  18.   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  19.   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  20.   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  21.   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
  22.  
  23. unsigned char freqtblhi[] = {
  24.   0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,
  25.   0x02,0x02,0x02,0x02,0x02,0x02,0x03,0x03,0x03,0x03,0x03,0x04,
  26.   0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x06,0x06,0x07,0x07,0x08,
  27.   0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0c,0x0d,0x0d,0x0e,0x0f,0x10,
  28.   0x11,0x12,0x13,0x14,0x15,0x17,0x18,0x1a,0x1b,0x1d,0x1f,0x20,
  29.   0x22,0x24,0x27,0x29,0x2b,0x2e,0x31,0x34,0x37,0x3a,0x3e,0x41,
  30.   0x45,0x49,0x4e,0x52,0x57,0x5c,0x62,0x68,0x6e,0x75,0x7c,0x83,
  31.   0x8b,0x93,0x9c,0xa5,0xaf,0xb9,0xc4,0xd0,0xdd,0xea,0xf8,0xff,
  32.   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  33.   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  34.   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  35.   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
  36.  
  37. CHN chn[MAX_CHN];
  38. unsigned char filterctrl = 0;
  39. unsigned char filtertype = 0;
  40. unsigned char filtercutoff = 0;
  41. unsigned char filtertime = 0;
  42. unsigned char filterptr = 0;
  43. unsigned char filter2ctrl = 0;
  44. unsigned char filter2type = 0;
  45. unsigned char filter2cutoff = 0;
  46. unsigned char filter2time = 0;
  47. unsigned char filter2ptr = 0;
  48. unsigned char funktable[2];
  49. unsigned char masterfader = 0x0f;
  50. int psnum = 0;
  51. int songinit = 0;
  52. int lastsonginit = 0;
  53. int startpattpos = 0;
  54.  
  55. void sequencer(int c, CHN *cptr);
  56.  
  57. void initchannels(void)
  58. {
  59.   int c;
  60.   CHN *cptr = &chn[0];
  61.  
  62.   memset(chn, 0, sizeof chn);
  63.  
  64.   for (c = 0; c < MAX_CHN; c++)
  65.   {
  66.       chn[c].trans = 0;
  67.       chn[c].instr = 1;
  68.     if (multiplier)
  69.       cptr->tempo = 6*multiplier-1;
  70.     else
  71.       cptr->tempo = 6-1;
  72.     cptr++;
  73.   }
  74.  
  75.   if (multiplier)
  76.   {
  77.     funktable[0] = 9*multiplier-1;
  78.     funktable[1] = 6*multiplier-1;
  79.   }
  80.   else
  81.   {
  82.     funktable[0] = 9-1;
  83.     funktable[1] = 6-1;
  84.   }
  85. }
  86.  
  87. void initsong(int num, int mode)
  88. {
  89.   sound_suspend();
  90.   songinit = PLAY_STOPPED;
  91.   psnum = num;
  92.   songinit = mode;
  93.   startpattpos = 0;
  94.   sound_flush();
  95. }
  96.  
  97. void initsongpos(int num, int mode, int pattpos)
  98. {
  99.   sound_suspend();
  100.   songinit = PLAY_STOPPED;
  101.   psnum = num;
  102.   songinit = mode;
  103.   startpattpos = pattpos;
  104.   sound_flush();
  105. }
  106.  
  107. void stopsong(void)
  108. {
  109.   sound_suspend();
  110.   songinit = PLAY_STOP;
  111.   sound_flush();
  112. }
  113.  
  114. void rewindsong(void)
  115. {
  116.   if (lastsonginit == PLAY_BEGINNING) lastsonginit = PLAY_POS;
  117.   initsong(psnum, lastsonginit);
  118. }
  119.  
  120. void playtestnote(int note, int ins, int chnnum)
  121. {
  122.   if (note == KEYON) return;
  123.   if ((note == REST) || (note == KEYOFF))
  124.   {
  125.     releasenote(chnnum);
  126.     return;
  127.   }
  128.  
  129.   if (!(instr[ins].gatetimer & 0x40))
  130.   {
  131.     chn[chnnum].gate = 0xfe; // Keyoff
  132.     if (!(instr[ins].gatetimer & 0x80))
  133.     {
  134.       if (chnnum < 3)
  135.       {
  136.         sidreg[0x5+chnnum*7] = adparam>>8; // Hardrestart
  137.         sidreg[0x6+chnnum*7] = adparam&0xff;
  138.       }
  139.       else
  140.       {
  141.         sidreg2[0x5+(chnnum-3)*7] = adparam>>8; // Hardrestart
  142.         sidreg2[0x6+(chnnum-3)*7] = adparam&0xff;
  143.       }
  144.     }
  145.   }
  146.  
  147.   chn[chnnum].instr = ins;
  148.   chn[chnnum].newnote = note;
  149.   if (songinit == PLAY_STOPPED)
  150.   {
  151.     chn[chnnum].tick = (instr[ins].gatetimer & 0x3f)+1;
  152.     chn[chnnum].gatetimer = instr[ins].gatetimer & 0x3f;
  153.   }
  154. }
  155.  
  156. void releasenote(int chnnum)
  157. {
  158.   chn[chnnum].gate = 0xfe;
  159. }
  160.  
  161. void mutechannel(int chnnum)
  162. {
  163.   chn[chnnum].mute ^= 1;
  164. }
  165.  
  166. int isplaying(void)
  167. {
  168.   return (songinit != PLAY_STOPPED);
  169. }
  170.  
  171. void playroutine(void)
  172. {
  173.   INSTR *iptr;
  174.   CHN *cptr = &chn[0];
  175.   int c;
  176.  
  177.   if (songinit == PLAY_STOP)
  178.     followplay = 0;
  179.  
  180.   if ((songinit > 0) && (songinit < PLAY_STOPPED))
  181.   {
  182.     lastsonginit = songinit;
  183.  
  184.     filterctrl = 0;
  185.     filterptr = 0;
  186.     filter2ctrl = 0;
  187.     filter2ptr = 0;
  188.  
  189.     resettime();
  190.  
  191.     if ((songinit == 0x02) || (songinit == 0x03))
  192.     {
  193.       for (c = 0; c< MAX_CHN; c++)
  194.       {
  195.         if (espos[c] >= songlen[psnum][c])
  196.           songinit = 0x01;
  197.       }
  198.     }
  199.  
  200.     for (c = 0; c < MAX_CHN; c++)
  201.     {
  202.       cptr->songptr = 0;
  203.       cptr->command = 0;
  204.       cptr->cmddata = 0;
  205.       cptr->newcommand = 0;
  206.       cptr->newcmddata = 0;
  207.       cptr->advance = 1;
  208.       cptr->wave = 0;
  209.       cptr->ptr[WTBL] = 0;
  210.       cptr->newnote = 0;
  211.       cptr->repeat = 0;
  212.       if (multiplier)
  213.         cptr->tick = 6*multiplier-1;
  214.       else
  215.         cptr->tick = 6-1;
  216.       cptr->gatetimer = instr[1].gatetimer & 0x3f;
  217.       cptr->pattptr = 0x7fffffff;
  218.       if (cptr->tempo < 2) cptr->tempo = 0;
  219.  
  220.       switch (songinit)
  221.       {
  222.         case PLAY_BEGINNING:
  223.         if (multiplier)
  224.         {
  225.           funktable[0] = 9*multiplier-1;
  226.           funktable[1] = 6*multiplier-1;
  227.           cptr->tempo = 6*multiplier-1;
  228.         }
  229.         else
  230.         {
  231.           funktable[0] = 9-1;
  232.           funktable[1] = 6-1;
  233.           cptr->tempo = 6-1;
  234.         }
  235.         if ((instr[MAX_INSTR-1].ad >= 2) && (!(instr[MAX_INSTR-1].ptr[WTBL])))
  236.           cptr->tempo = instr[MAX_INSTR-1].ad - 1;
  237.         cptr->trans = 0;
  238.         cptr->instr = 1;
  239.         sequencer(c, cptr);
  240.         break;
  241.  
  242.         case PLAY_PATTERN:
  243.         cptr->advance = 0;
  244.         cptr->pattptr = startpattpos * 4;
  245.         cptr->pattnum = epnum[c];
  246.         if (cptr->pattptr >= (pattlen[cptr->pattnum] * 4))
  247.           cptr->pattptr = 0;
  248.         break;
  249.  
  250.         case PLAY_POS:
  251.         cptr->songptr = espos[c];
  252.         sequencer(c, cptr);
  253.         break;
  254.       }
  255.       cptr++;
  256.     }
  257.     if (songinit != PLAY_STOP)
  258.       songinit = 0;
  259.     else
  260.       songinit = PLAY_STOPPED;
  261.     if ((!songlen[psnum][0]) || (!songlen[psnum][1]) || (!songlen[psnum][2]) ||
  262.         (!songlen[psnum][3]) || (!songlen[psnum][4]) || (!songlen[psnum][5]))
  263.       songinit = PLAY_STOPPED; // Zero length song
  264.  
  265.     startpattpos = 0;
  266.   }
  267.   else
  268.   {
  269.     if (filterptr)
  270.     {
  271.       // Filter jump
  272.       if (ltable[FTBL][filterptr-1] == 0xff)
  273.       {
  274.         filterptr = rtable[FTBL][filterptr-1];
  275.         if (!filterptr) goto FILTERSTOP;
  276.       }
  277.  
  278.       if (!filtertime)
  279.       {
  280.         // Filter set
  281.         if (ltable[FTBL][filterptr-1] >= 0x80)
  282.         {
  283.           filtertype = ltable[FTBL][filterptr-1] & 0x70;
  284.           filterctrl = rtable[FTBL][filterptr-1];
  285.           filterptr++;
  286.           // Can be combined with cutoff set
  287.           if (ltable[FTBL][filterptr-1] == 0x00)
  288.           {
  289.             filtercutoff = rtable[FTBL][filterptr-1];
  290.             filterptr++;
  291.           }
  292.         }
  293.         else
  294.         {
  295.           // New modulation step
  296.           if (ltable[FTBL][filterptr-1])
  297.             filtertime = ltable[FTBL][filterptr-1];
  298.           else
  299.           {
  300.             // Cutoff set
  301.             filtercutoff = rtable[FTBL][filterptr-1];
  302.             filterptr++;
  303.           }
  304.         }
  305.       }
  306.       // Filter modulation
  307.       if (filtertime)
  308.       {
  309.         filtercutoff += rtable[FTBL][filterptr-1];
  310.         filtertime--;
  311.         if (!filtertime) filterptr++;
  312.       }
  313.     }
  314.     FILTERSTOP:
  315.     sidreg[0x15] = 0x00;
  316.     sidreg[0x16] = filtercutoff;
  317.     sidreg[0x17] = filterctrl;
  318.     sidreg[0x18] = filtertype | masterfader;
  319.  
  320.     if (filter2ptr)
  321.     {
  322.       // Filter jump
  323.       if (ltable[FTBL][filter2ptr-1] == 0xff)
  324.       {
  325.         filter2ptr = rtable[FTBL][filter2ptr-1];
  326.         if (!filter2ptr) goto FILTER2STOP;
  327.       }
  328.  
  329.       if (!filter2time)
  330.       {
  331.         // Filter set
  332.         if (ltable[FTBL][filter2ptr-1] >= 0x80)
  333.         {
  334.           filter2type = ltable[FTBL][filter2ptr-1] & 0x70;
  335.           filter2ctrl = rtable[FTBL][filter2ptr-1];
  336.           filter2ptr++;
  337.           // Can be combined with cutoff set
  338.           if (ltable[FTBL][filter2ptr-1] == 0x00)
  339.           {
  340.             filter2cutoff = rtable[FTBL][filter2ptr-1];
  341.             filter2ptr++;
  342.           }
  343.         }
  344.         else
  345.         {
  346.           // New modulation step
  347.           if (ltable[FTBL][filter2ptr-1])
  348.             filter2time = ltable[FTBL][filter2ptr-1];
  349.           else
  350.           {
  351.             // Cutoff set
  352.             filter2cutoff = rtable[FTBL][filter2ptr-1];
  353.             filter2ptr++;
  354.           }
  355.         }
  356.       }
  357.       // Filter modulation
  358.       if (filter2time)
  359.       {
  360.         filter2cutoff += rtable[FTBL][filter2ptr-1];
  361.         filter2time--;
  362.         if (!filter2time) filter2ptr++;
  363.       }
  364.     }
  365.  
  366.     FILTER2STOP:
  367.     sidreg2[0x15] = 0x00;
  368.     sidreg2[0x16] = filter2cutoff;
  369.     sidreg2[0x17] = filter2ctrl;
  370.     sidreg2[0x18] = filter2type | masterfader;
  371.  
  372.     for (c = 0; c < MAX_CHN; c++)
  373.     {
  374.       iptr = &instr[cptr->instr];
  375.  
  376.       // Reset tempo in jammode
  377.       if ((songinit == PLAY_STOPPED) && (cptr->tempo < 2))
  378.       {
  379.         if (multiplier)
  380.           cptr->tempo = 6*multiplier-1;
  381.         else
  382.           cptr->tempo = 6-1;
  383.       }
  384.  
  385.       // Decrease tick
  386.       cptr->tick--;
  387.       if (!cptr->tick) goto TICK0;
  388.  
  389.       // Tick N
  390.       // Reload counter
  391.       if (cptr->tick >= 0x80)
  392.       {
  393.         if (cptr->tempo >= 2)
  394.           cptr->tick = cptr->tempo;
  395.         else
  396.         {
  397.           // Set funktempo, switch between 2 values
  398.           cptr->tick = funktable[cptr->tempo];
  399.           cptr->tempo ^= 1;
  400.         }
  401.         // Check for illegally high gatetimer and stop the song in this case
  402.         if (chn->gatetimer > cptr->tick)
  403.           stopsong();
  404.       }
  405.       goto WAVEEXEC;
  406.  
  407.       // Tick 0
  408.       TICK0:
  409.       // Advance in sequencer
  410.       sequencer(c, cptr);
  411.  
  412.       // Get gatetimer compare-value
  413.       cptr->gatetimer = iptr->gatetimer & 0x3f;
  414.  
  415.       // New note init
  416.       if (cptr->newnote)
  417.       {
  418.         cptr->note = cptr->newnote-FIRSTNOTE;
  419.         cptr->command = 0;
  420.         cptr->vibdelay = iptr->vibdelay;
  421.         cptr->cmddata = iptr->ptr[STBL];
  422.         if (cptr->newcommand != CMD_TONEPORTA)
  423.         {
  424.           if (iptr->firstwave)
  425.           {
  426.             if (iptr->firstwave >= 0xfe) cptr->gate = iptr->firstwave;
  427.             else
  428.             {
  429.               cptr->wave = iptr->firstwave;
  430.               cptr->gate = 0xff;
  431.             }
  432.           }
  433.  
  434.  
  435.           cptr->ptr[WTBL] = iptr->ptr[WTBL];
  436.  
  437.           if (cptr->ptr[WTBL])
  438.           {
  439.             // Stop the song in case of jumping into a jump
  440.             if (ltable[WTBL][cptr->ptr[WTBL]-1] == 0xff)
  441.               stopsong();
  442.           }
  443.           if (iptr->ptr[PTBL])
  444.           {
  445.             cptr->ptr[PTBL] = iptr->ptr[PTBL];
  446.             cptr->pulsetime = 0;
  447.             if (cptr->ptr[PTBL])
  448.             {
  449.               // Stop the song in case of jumping into a jump
  450.               if (ltable[PTBL][cptr->ptr[PTBL]-1] == 0xff)
  451.                 stopsong();
  452.             }
  453.           }
  454.           if (iptr->ptr[FTBL])
  455.           {
  456.             if (c < 3)
  457.             {
  458.               filterptr = iptr->ptr[FTBL];
  459.               filtertime = 0;
  460.               if (filterptr)
  461.               {
  462.                 // Stop the song in case of jumping into a jump
  463.                 if (ltable[FTBL][filterptr-1] == 0xff)
  464.                   stopsong();
  465.               }
  466.             }
  467.             else
  468.             {
  469.               filter2ptr = iptr->ptr[FTBL];
  470.               filter2time = 0;
  471.               if (filter2ptr)
  472.               {
  473.                 // Stop the song in case of jumping into a jump
  474.                 if (ltable[FTBL][filter2ptr-1] == 0xff)
  475.                   stopsong();
  476.               }
  477.             }
  478.           }
  479.           if (c < 3)
  480.           {
  481.             sidreg[0x5+7*c] = iptr->ad;
  482.             sidreg[0x6+7*c] = iptr->sr;
  483.           }
  484.           else
  485.           {
  486.             sidreg2[0x5+7*(c-3)] = iptr->ad;
  487.             sidreg2[0x6+7*(c-3)] = iptr->sr;
  488.           }
  489.         }
  490.       }
  491.  
  492.       // Tick 0 effects
  493.  
  494.       switch (cptr->newcommand)
  495.       {
  496.         case CMD_DONOTHING:
  497.         cptr->command = 0;
  498.         cptr->cmddata = iptr->ptr[STBL];
  499.         break;
  500.  
  501.         case CMD_PORTAUP:
  502.         case CMD_PORTADOWN:
  503.         cptr->vibtime = 0;
  504.         cptr->command = cptr->newcommand;
  505.         cptr->cmddata = cptr->newcmddata;
  506.         break;
  507.  
  508.         case CMD_TONEPORTA:
  509.         case CMD_VIBRATO:
  510.         cptr->command = cptr->newcommand;
  511.         cptr->cmddata = cptr->newcmddata;
  512.         break;
  513.  
  514.         case CMD_SETAD:
  515.         if (c < 3)
  516.           sidreg[0x5+7*c] = cptr->newcmddata;
  517.         else
  518.           sidreg2[0x5+7*(c-3)] = cptr->newcmddata;
  519.         break;
  520.  
  521.         case CMD_SETSR:
  522.         if (c < 3)
  523.           sidreg[0x6+7*c] = cptr->newcmddata;
  524.         else
  525.           sidreg2[0x6+7*(c-3)] = cptr->newcmddata;
  526.         break;
  527.  
  528.         case CMD_SETWAVE:
  529.         cptr->wave = cptr->newcmddata;
  530.         break;
  531.  
  532.         case CMD_SETWAVEPTR:
  533.         cptr->ptr[WTBL] = cptr->newcmddata;
  534.         cptr->wavetime = 0;
  535.         if (cptr->ptr[WTBL])
  536.         {
  537.           // Stop the song in case of jumping into a jump
  538.           if (ltable[WTBL][cptr->ptr[WTBL]-1] == 0xff)
  539.             stopsong();
  540.         }
  541.         break;
  542.  
  543.         case CMD_SETPULSEPTR:
  544.         cptr->ptr[PTBL] = cptr->newcmddata;
  545.         cptr->pulsetime = 0;
  546.         if (cptr->ptr[PTBL])
  547.         {
  548.           // Stop the song in case of jumping into a jump
  549.           if (ltable[PTBL][cptr->ptr[PTBL]-1] == 0xff)
  550.             stopsong();
  551.         }
  552.         break;
  553.  
  554.         case CMD_SETFILTERPTR:
  555.         if (c < 3)
  556.         {
  557.           filterptr = cptr->newcmddata;
  558.           filtertime = 0;
  559.           if (filterptr)
  560.           {
  561.             // Stop the song in case of jumping into a jump
  562.             if (ltable[FTBL][filterptr-1] == 0xff)
  563.               stopsong();
  564.           }
  565.         }
  566.         else
  567.         {
  568.           filter2ptr = cptr->newcmddata;
  569.           filter2time = 0;
  570.           if (filter2ptr)
  571.           {
  572.             // Stop the song in case of jumping into a jump
  573.             if (ltable[FTBL][filter2ptr-1] == 0xff)
  574.               stopsong();
  575.           }
  576.         }
  577.         break;
  578.  
  579.         case CMD_SETFILTERCTRL:
  580.         if (c < 3)
  581.         {
  582.           filterctrl = cptr->newcmddata;
  583.           if (!filterctrl) filterptr = 0;
  584.         }
  585.         else
  586.         {
  587.           filter2ctrl = cptr->newcmddata;
  588.           if (!filter2ctrl) filter2ptr = 0;
  589.         }
  590.         break;
  591.  
  592.         case CMD_SETFILTERCUTOFF:
  593.         if (c < 3)
  594.           filtercutoff = cptr->newcmddata;
  595.         else
  596.           filter2cutoff = cptr->newcmddata;
  597.         break;
  598.  
  599.         case CMD_SETMASTERVOL:
  600.         if (cptr->newcmddata < 0x10)
  601.           masterfader = cptr->newcmddata;
  602.         break;
  603.  
  604.         case CMD_FUNKTEMPO:
  605.         if (cptr->newcmddata)
  606.         {
  607.           funktable[0] = ltable[STBL][cptr->newcmddata-1]-1;
  608.           funktable[1] = rtable[STBL][cptr->newcmddata-1]-1;
  609.         }
  610.         {
  611.           int d;
  612.           for (d = 0; d < MAX_CHN; d++)
  613.             chn[d].tempo = 0;
  614.         }
  615.         break;
  616.  
  617.         case CMD_SETTEMPO:
  618.         {
  619.           unsigned char newtempo = cptr->newcmddata & 0x7f;
  620.  
  621.           if (newtempo >= 3) newtempo--;
  622.           if (cptr->newcmddata >= 0x80)
  623.             cptr->tempo = newtempo;
  624.           else
  625.           {
  626.             int d;
  627.             for (d = 0; d < MAX_CHN; d++)
  628.               chn[d].tempo = newtempo;
  629.           }
  630.         }
  631.         break;
  632.       }
  633.       if (cptr->newnote)
  634.       {
  635.         cptr->newnote = 0;
  636.         if (cptr->newcommand != CMD_TONEPORTA) goto NEXTCHN;
  637.       }
  638.  
  639.       WAVEEXEC:
  640.       if (cptr->ptr[WTBL])
  641.       {
  642.         unsigned char wave = ltable[WTBL][cptr->ptr[WTBL]-1];
  643.         unsigned char note = rtable[WTBL][cptr->ptr[WTBL]-1];
  644.  
  645.         if (wave > WAVELASTDELAY)
  646.         {
  647.             // Normal waveform values
  648.             if (wave < WAVESILENT) cptr->wave = wave;
  649.           // Values without waveform selected
  650.           if ((wave >= WAVESILENT) && (wave <= WAVELASTSILENT)) cptr->wave = wave & 0xf;
  651.           // Command execution from wavetable
  652.           if ((wave >= WAVECMD) && (wave <= WAVELASTCMD))
  653.           {
  654.               unsigned char param = rtable[WTBL][cptr->ptr[WTBL]-1];
  655.               switch (wave & 0xf)
  656.               {
  657.                   case CMD_DONOTHING:
  658.                   case CMD_SETWAVEPTR:
  659.                   case CMD_FUNKTEMPO:
  660.                   stopsong();
  661.                   break;
  662.  
  663.               case CMD_PORTAUP:
  664.               {
  665.                 unsigned short speed = 0;
  666.                 if (param)
  667.                 {
  668.                   speed = (ltable[STBL][param-1] << 8) | rtable[STBL][param-1];
  669.                 }
  670.                 if (speed >= 0x8000)
  671.                 {
  672.                   speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8);
  673.                   speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8);
  674.                   speed >>= rtable[STBL][param-1];
  675.                 }                
  676.                 cptr->freq += speed;
  677.               }
  678.               break;
  679.  
  680.               case CMD_PORTADOWN:
  681.               {
  682.                 unsigned short speed = 0;
  683.                 if (param)
  684.                 {
  685.                   speed = (ltable[STBL][param-1] << 8) | rtable[STBL][param-1];
  686.                 }
  687.                 if (speed >= 0x8000)
  688.                 {
  689.                   speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8);
  690.                   speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8);
  691.                   speed >>= rtable[STBL][param-1];
  692.                 }
  693.                 cptr->freq -= speed;
  694.               }
  695.               break;
  696.  
  697.               case CMD_TONEPORTA:
  698.               {
  699.                 unsigned short targetfreq = freqtbllo[cptr->note] | (freqtblhi[cptr->note] << 8);
  700.                 unsigned short speed = 0;
  701.  
  702.                 if (!param)
  703.                 {
  704.                   cptr->freq = targetfreq;
  705.                   cptr->vibtime = 0;
  706.                 }
  707.                 else
  708.                 {
  709.                   speed = (ltable[STBL][param-1] << 8) | rtable[STBL][param-1];
  710.                   if (speed >= 0x8000)
  711.                   {
  712.                     speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8);
  713.                     speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8);
  714.                     speed >>= rtable[STBL][param-1];
  715.                   }
  716.                   if (cptr->freq < targetfreq)
  717.                   {
  718.                     cptr->freq += speed;
  719.                     if (cptr->freq > targetfreq)
  720.                     {
  721.                       cptr->freq = targetfreq;
  722.                       cptr->vibtime = 0;
  723.                     }
  724.                   }
  725.                   if (cptr->freq > targetfreq)
  726.                   {
  727.                     cptr->freq -= speed;
  728.                     if (cptr->freq < targetfreq)
  729.                     {
  730.                       cptr->freq = targetfreq;
  731.                       cptr->vibtime = 0;
  732.                     }
  733.                   }
  734.                 }
  735.               }
  736.               break;
  737.  
  738.               case CMD_VIBRATO:
  739.               {
  740.                 unsigned short speed = 0;
  741.                 unsigned char cmpvalue = 0;
  742.  
  743.                 if (param)
  744.                 {
  745.                   cmpvalue = ltable[STBL][param-1];
  746.                   speed = rtable[STBL][param-1];
  747.                 }
  748.                 if (cmpvalue >= 0x80)
  749.                 {
  750.                   cmpvalue &= 0x7f;
  751.                   speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8);
  752.                   speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8);
  753.                   speed >>= rtable[STBL][param-1];
  754.                 }
  755.  
  756.                 if ((cptr->vibtime < 0x80) && (cptr->vibtime > cmpvalue))
  757.                   cptr->vibtime ^= 0xff;
  758.                 cptr->vibtime += 0x02;
  759.                 if (cptr->vibtime & 0x01)
  760.                   cptr->freq -= speed;
  761.                 else
  762.                   cptr->freq += speed;
  763.               }
  764.               break;
  765.  
  766.               case CMD_SETAD:
  767.               if (c < 3)
  768.                 sidreg[0x5+7*c] = param;
  769.               else
  770.                 sidreg2[0x5+7*(c-3)] = param;
  771.               break;
  772.  
  773.               case CMD_SETSR:
  774.               if (c < 3)
  775.                 sidreg[0x6+7*c] = param;
  776.               else
  777.                 sidreg2[0x6+7*(c-3)] = param;
  778.               break;
  779.  
  780.               case CMD_SETWAVE:
  781.               cptr->wave = param;
  782.               break;
  783.  
  784.               case CMD_SETPULSEPTR:
  785.               cptr->ptr[PTBL] = param;
  786.               cptr->pulsetime = 0;
  787.               if (cptr->ptr[PTBL])
  788.               {
  789.                 // Stop the song in case of jumping into a jump
  790.                 if (ltable[PTBL][cptr->ptr[PTBL]-1] == 0xff)
  791.                   stopsong();
  792.               }
  793.               break;
  794.  
  795.               case CMD_SETFILTERPTR:
  796.               if (c < 3)
  797.               {
  798.                 filterptr = param;
  799.                 filtertime = 0;
  800.                 if (filterptr)
  801.                 {
  802.                   // Stop the song in case of jumping into a jump
  803.                   if (ltable[FTBL][filterptr-1] == 0xff)
  804.                   stopsong();
  805.                 }
  806.               }
  807.               else
  808.               {
  809.                 filter2ptr = param;
  810.                 filter2time = 0;
  811.                 if (filter2ptr)
  812.                 {
  813.                   // Stop the song in case of jumping into a jump
  814.                   if (ltable[FTBL][filter2ptr-1] == 0xff)
  815.                   stopsong();
  816.                 }
  817.               }
  818.               break;
  819.  
  820.               case CMD_SETFILTERCTRL:
  821.               if (c < 3)
  822.               {
  823.                 filterctrl = param;
  824.                 if (!filterctrl) filterptr = 0;
  825.               }
  826.               else
  827.               {
  828.                 filter2ctrl = param;
  829.                 if (!filter2ctrl) filter2ptr = 0;
  830.               }
  831.               break;
  832.  
  833.               case CMD_SETFILTERCUTOFF:
  834.               if (c < 3)
  835.                 filtercutoff = param;
  836.               else
  837.                 filter2cutoff = param;
  838.               break;
  839.  
  840.               case CMD_SETMASTERVOL:
  841.               if (cptr->newcmddata < 0x10)
  842.                 masterfader = param;
  843.               break;
  844.             }
  845.           }
  846.         }
  847.         else
  848.         {
  849.           // Wavetable delay
  850.           if (cptr->wavetime != wave)
  851.           {
  852.             cptr->wavetime++;
  853.             goto TICKNEFFECTS;
  854.           }
  855.         }
  856.  
  857.         cptr->wavetime = 0;
  858.         cptr->ptr[WTBL]++;
  859.         // Wavetable jump
  860.         if (ltable[WTBL][cptr->ptr[WTBL]-1] == 0xff)
  861.         {
  862.           cptr->ptr[WTBL] = rtable[WTBL][cptr->ptr[WTBL]-1];
  863.         }
  864.  
  865.         if ((wave >= WAVECMD) && (wave <= WAVELASTCMD))
  866.           goto PULSEEXEC;
  867.  
  868.         if (note != 0x80)
  869.         {
  870.           if (note < 0x80)
  871.             note += cptr->note;
  872.           note &= 0x7f;
  873.           cptr->freq = freqtbllo[note] | (freqtblhi[note]<<8);
  874.           cptr->vibtime = 0;
  875.           cptr->lastnote = note;
  876.           goto PULSEEXEC;
  877.         }
  878.       }
  879.  
  880.       // Tick N command
  881.       TICKNEFFECTS:
  882.       if ((!optimizerealtime) || (cptr->tick))
  883.       {
  884.         switch(cptr->command)
  885.         {
  886.           case CMD_PORTAUP:
  887.           {
  888.             unsigned short speed = 0;
  889.             if (cptr->cmddata)
  890.             {
  891.               speed = (ltable[STBL][cptr->cmddata-1] << 8) | rtable[STBL][cptr->cmddata-1];
  892.             }
  893.             if (speed >= 0x8000)
  894.             {
  895.               speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8);
  896.               speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8);
  897.               speed >>= rtable[STBL][cptr->cmddata-1];
  898.             }
  899.             cptr->freq += speed;
  900.           }
  901.           break;
  902.  
  903.           case CMD_PORTADOWN:
  904.           {
  905.             unsigned short speed = 0;
  906.             if (cptr->cmddata)
  907.             {
  908.               speed = (ltable[STBL][cptr->cmddata-1] << 8) | rtable[STBL][cptr->cmddata-1];
  909.             }
  910.             if (speed >= 0x8000)
  911.             {
  912.               speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8);
  913.               speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8);
  914.               speed >>= rtable[STBL][cptr->cmddata-1];
  915.             }
  916.             cptr->freq -= speed;
  917.           }
  918.           break;
  919.  
  920.           case CMD_DONOTHING:
  921.           if ((!cptr->cmddata) || (!cptr->vibdelay))
  922.             break;
  923.           if (cptr->vibdelay > 1)
  924.           {
  925.             cptr->vibdelay--;
  926.             break;
  927.           }
  928.           case CMD_VIBRATO:
  929.           {
  930.             unsigned short speed = 0;
  931.             unsigned char cmpvalue = 0;
  932.  
  933.             if (cptr->cmddata)
  934.             {
  935.               cmpvalue = ltable[STBL][cptr->cmddata-1];
  936.               speed = rtable[STBL][cptr->cmddata-1];
  937.             }
  938.             if (cmpvalue >= 0x80)
  939.             {
  940.               cmpvalue &= 0x7f;
  941.               speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8);
  942.               speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8);
  943.               speed >>= rtable[STBL][cptr->cmddata-1];
  944.             }
  945.  
  946.             if ((cptr->vibtime < 0x80) && (cptr->vibtime > cmpvalue))
  947.               cptr->vibtime ^= 0xff;
  948.             cptr->vibtime += 0x02;
  949.             if (cptr->vibtime & 0x01)
  950.               cptr->freq -= speed;
  951.             else
  952.               cptr->freq += speed;
  953.           }
  954.           break;
  955.  
  956.           case CMD_TONEPORTA:
  957.           {
  958.             unsigned short targetfreq = freqtbllo[cptr->note] | (freqtblhi[cptr->note] << 8);
  959.             unsigned short speed = 0;
  960.  
  961.             if (!cptr->cmddata)
  962.             {
  963.               cptr->freq = targetfreq;
  964.               cptr->vibtime = 0;
  965.             }
  966.             else
  967.             {
  968.               speed = (ltable[STBL][cptr->cmddata-1] << 8) | rtable[STBL][cptr->cmddata-1];
  969.               if (speed >= 0x8000)
  970.               {
  971.                 speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8);
  972.                 speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8);
  973.                 speed >>= rtable[STBL][cptr->cmddata-1];
  974.               }
  975.               if (cptr->freq < targetfreq)
  976.               {
  977.                 cptr->freq += speed;
  978.                 if (cptr->freq > targetfreq)
  979.                 {
  980.                   cptr->freq = targetfreq;
  981.                   cptr->vibtime = 0;
  982.                 }
  983.               }
  984.               if (cptr->freq > targetfreq)
  985.               {
  986.                 cptr->freq -= speed;
  987.                 if (cptr->freq < targetfreq)
  988.                 {
  989.                   cptr->freq = targetfreq;
  990.                   cptr->vibtime = 0;
  991.                 }
  992.               }
  993.             }
  994.           }
  995.           break;
  996.         }
  997.       }
  998.  
  999.       PULSEEXEC:
  1000.       if (optimizepulse)
  1001.       {
  1002.         if ((songinit != 0x80) && (cptr->tick == cptr->gatetimer)) goto GETNEWNOTES;
  1003.       }
  1004.  
  1005.       if (cptr->ptr[PTBL])
  1006.       {
  1007.         // Skip pulse when sequencer has been executed
  1008.         if (optimizepulse)
  1009.         {
  1010.             if ((!cptr->tick) && (!cptr->pattptr)) goto NEXTCHN;
  1011.         }
  1012.  
  1013.         // Pulsetable jump
  1014.         if (ltable[PTBL][cptr->ptr[PTBL]-1] == 0xff)
  1015.         {
  1016.           cptr->ptr[PTBL] = rtable[PTBL][cptr->ptr[PTBL]-1];
  1017.           if (!cptr->ptr[PTBL]) goto PULSEEXEC;
  1018.         }
  1019.  
  1020.         if (!cptr->pulsetime)
  1021.         {
  1022.           // Set pulse
  1023.           if (ltable[PTBL][cptr->ptr[PTBL]-1] >= 0x80)
  1024.           {
  1025.             cptr->pulse = (ltable[PTBL][cptr->ptr[PTBL]-1] & 0xf) << 8;
  1026.             cptr->pulse |= rtable[PTBL][cptr->ptr[PTBL]-1];
  1027.             cptr->ptr[PTBL]++;
  1028.           }
  1029.           else
  1030.           {
  1031.             cptr->pulsetime = ltable[PTBL][cptr->ptr[PTBL]-1];
  1032.           }
  1033.         }
  1034.         // Pulse modulation
  1035.         if (cptr->pulsetime)
  1036.         {
  1037.           unsigned char speed = rtable[PTBL][cptr->ptr[PTBL]-1];
  1038.           if (speed < 0x80)
  1039.           {
  1040.             cptr->pulse += speed;
  1041.             cptr->pulse &= 0xfff;
  1042.           }
  1043.           else
  1044.           {
  1045.             cptr->pulse += speed;
  1046.             cptr->pulse -= 0x100;
  1047.             cptr->pulse &= 0xfff;
  1048.           }
  1049.           cptr->pulsetime--;
  1050.           if (!cptr->pulsetime) cptr->ptr[PTBL]++;
  1051.         }
  1052.       }
  1053.       if ((songinit == 0x80) || (cptr->tick != cptr->gatetimer)) goto NEXTCHN;
  1054.  
  1055.       // New notes processing
  1056.       GETNEWNOTES:
  1057.       {
  1058.         unsigned char newnote;
  1059.  
  1060.         newnote = pattern[cptr->pattnum][cptr->pattptr];
  1061.         if (pattern[cptr->pattnum][cptr->pattptr+1])
  1062.           cptr->instr = pattern[cptr->pattnum][cptr->pattptr+1];
  1063.         cptr->newcommand = pattern[cptr->pattnum][cptr->pattptr+2];
  1064.         cptr->newcmddata = pattern[cptr->pattnum][cptr->pattptr+3];
  1065.         cptr->pattptr += 4;
  1066.         if (pattern[cptr->pattnum][cptr->pattptr] == ENDPATT)
  1067.           cptr->pattptr = 0x7fffffff;
  1068.  
  1069.         if (newnote == KEYOFF)
  1070.           cptr->gate = 0xfe;
  1071.         if (newnote == KEYON)
  1072.           cptr->gate = 0xff;
  1073.         if (newnote <= LASTNOTE)
  1074.         {
  1075.           cptr->newnote = newnote+cptr->trans;
  1076.           if ((cptr->newcommand) != CMD_TONEPORTA)
  1077.           {
  1078.             if (!(instr[cptr->instr].gatetimer & 0x40))
  1079.             {
  1080.               cptr->gate = 0xfe;
  1081.               if (!(instr[cptr->instr].gatetimer & 0x80))
  1082.               {
  1083.                 if (c < 3)
  1084.                 {
  1085.                   sidreg[0x5+7*c] = adparam>>8;
  1086.                   sidreg[0x6+7*c] = adparam&0xff;
  1087.                 }
  1088.                 else
  1089.                 {
  1090.                   sidreg2[0x5+7*(c-3)] = adparam>>8;
  1091.                   sidreg2[0x6+7*(c-3)] = adparam&0xff;
  1092.                 }
  1093.               }
  1094.             }
  1095.           }
  1096.         }
  1097.       }
  1098.       NEXTCHN:
  1099.       if (cptr->mute)
  1100.       {
  1101.         if (c < 3)
  1102.           sidreg[0x4+7*c] = cptr->wave = 0x08;
  1103.         else
  1104.           sidreg2[0x4+7*(c-3)] = cptr->wave = 0x08;
  1105.       }
  1106.       else
  1107.       {
  1108.         if (c < 3)
  1109.         {
  1110.           sidreg[0x0+7*c] = cptr->freq & 0xff;
  1111.           sidreg[0x1+7*c] = cptr->freq >> 8;
  1112.           sidreg[0x2+7*c] = cptr->pulse & 0xfe;
  1113.           sidreg[0x3+7*c] = cptr->pulse >> 8;
  1114.           sidreg[0x4+7*c] = cptr->wave & cptr->gate;
  1115.         }
  1116.         else
  1117.         {
  1118.           sidreg2[0x0+7*(c-3)] = cptr->freq & 0xff;
  1119.           sidreg2[0x1+7*(c-3)] = cptr->freq >> 8;
  1120.           sidreg2[0x2+7*(c-3)] = cptr->pulse & 0xfe;
  1121.           sidreg2[0x3+7*(c-3)] = cptr->pulse >> 8;
  1122.           sidreg2[0x4+7*(c-3)] = cptr->wave & cptr->gate;
  1123.         }
  1124.       }
  1125.       cptr++;
  1126.     }
  1127.   }
  1128.   if (songinit != 0x80) incrementtime();
  1129. }
  1130.  
  1131. void sequencer(int c, CHN *cptr)
  1132. {
  1133.   if ((songinit != 0x80) && (cptr->pattptr == 0x7fffffff))
  1134.   {
  1135.     cptr->pattptr = startpattpos * 4;
  1136.     if (!cptr->advance) goto SEQDONE;
  1137.     // Song loop
  1138.     if (songorder[psnum][c][cptr->songptr] == LOOPSONG)
  1139.     {
  1140.       cptr->songptr = songorder[psnum][c][cptr->songptr+1];
  1141.       if (cptr->songptr >= songlen[psnum][c])
  1142.       {
  1143.         stopsong();
  1144.         cptr->songptr = 0;
  1145.         goto SEQDONE;
  1146.       }
  1147.     }
  1148.     // Transpose
  1149.     if ((songorder[psnum][c][cptr->songptr] >= TRANSDOWN) && (songorder[psnum][c][cptr->songptr] < LOOPSONG))
  1150.     {
  1151.       cptr->trans = songorder[psnum][c][cptr->songptr]-TRANSUP;
  1152.       cptr->songptr++;
  1153.     }
  1154.     // Repeat
  1155.     if ((songorder[psnum][c][cptr->songptr] >= REPEAT) && (songorder[psnum][c][cptr->songptr] < TRANSDOWN))
  1156.     {
  1157.       cptr->repeat = songorder[psnum][c][cptr->songptr]-REPEAT;
  1158.       cptr->songptr++;
  1159.     }
  1160.     // Pattern number
  1161.     cptr->pattnum = songorder[psnum][c][cptr->songptr];
  1162.     if (cptr->repeat)
  1163.       cptr->repeat--;
  1164.     else
  1165.       cptr->songptr++;
  1166.  
  1167.     // Check for illegal pattern now
  1168.     if (cptr->pattnum >= MAX_PATT)
  1169.     {
  1170.       stopsong();
  1171.       cptr->pattnum = 0;
  1172.     }
  1173.     if (cptr->pattptr >= (pattlen[cptr->pattnum] * 4))
  1174.       cptr->pattptr = 0;
  1175.       
  1176.     // Check for playback endpos
  1177.     if ((lastsonginit != PLAY_BEGINNING) && (esend[c] > 0) && (esend[c] > espos[c]) && (cptr->songptr > esend[c]) && (espos[c] < songlen[psnum][c]))
  1178.       cptr->songptr = espos[c];
  1179.   }
  1180.   SEQDONE: {}
  1181. }
  1182.