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