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