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