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