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