home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / far096.zip / FARTRAK.CPP < prev    next >
C/C++ Source or Header  |  1994-04-30  |  16KB  |  520 lines

  1. // Piece of code from FARTRAK.CPP
  2. // This should allow you to use FARs in your own programs
  3. // By Daniel Potter/Digital Infinity
  4. // Code for F2R's to be released soon
  5.  
  6. word OverFlow=0,OCount=0,PlayTempo=CurTempo,PlayOrder=CurOrder;
  7. int  TempoBend=0;
  8. int  mTempo[16];
  9. long PitchWheel[16]={0},DestPitch[16]={0},Increment[16]={0},PresPitch[16]={0};
  10. int  VolWheel[16]={0},DestVol[16]={0},VIncrement[16]={0},PresVol[16]={0};
  11. long RetLeft[16]={0},RetSpc[16]={0},CurSpc[16]={0},RetSmp[16]={0},RetVol[16]={0xF};
  12. int  OfftCnt[16]={0},RetCnt[16]={0};
  13. int  VibOn[16]={0};
  14. int  VibPtr[16]={0},VibInc[16]={0};
  15. int  CurFreqs[16]={0};
  16. int  CurVols[16]={15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15};
  17. int  SinTable[16][128]={0};
  18. int  VibAmp=4;
  19. int  CurChSmp[16]={0};
  20. Flag near VolRamps=TRUE;
  21. Flag near TempoType=1;
  22.  
  23. void UdTempo() {
  24.   if (TempoType)
  25.     UpdateTempo(mTempo[PlayTempo]+TempoBend);
  26.   else
  27.     UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
  28.   return;
  29. }
  30.  
  31. void CalcTempo() {
  32.   word q;
  33.   double t,f=1,y,amp;
  34.  
  35.   mTempo[0]=256;
  36.   for (q=1;q<16;q++) mTempo[q]=128/q;
  37.  
  38.   for (amp=0;amp<16;amp++)
  39.     for (t=0;t<1;t+=(1.0/128)) {
  40.       y=sin(2*3.1415*f*t)*amp;
  41.       SinTable[amp][t*128]=y;
  42.     }
  43. }
  44.  
  45. extern "C" void IRQHook() {
  46.   pokeb(TSeg,132*2,peekb(TSeg,132*2)^128);
  47. }
  48.  
  49. byte Bars[16]={0};
  50. extern Flag BarsOff;
  51.  
  52. void UpdateBars();
  53. void KillBars() {
  54.   memset(Bars,0,16);
  55.   if (!BarsOff) {
  56.     DrawF(94,5,0xe,0xf,"ÇÇääêêîîÉÉööÿÿ££ááññ¿¿¼¼░░┤┤╕╕╝╝");
  57.     DrawF(94,6,0xd,0xc,"üüààëëììææòòÖÖ¥¥ííÑÑ⌐⌐¡¡▒▒╡╡╣╣╜╜");
  58.     DrawF(94,7,0xd,0xc,"ééååèèÄÄÆÆûûÜÜ₧₧ó󪪬¬««▓▓╢╢║║╛╛");
  59.     DrawF(94,8,0xd,0xc,"ââççïïÅÅôôùù¢¢ƒƒúúºº½½»»││╖╖╗╗┐┐");
  60.  
  61.     DrawF(94,4,0xb,0x9," 0 1 2 3 4 5 6 7 8 9 A B C D E F");
  62.     UpdateBars();
  63.   }
  64. }
  65.  
  66. void ASMUpd(word,word);
  67. void UpdateBars() {
  68.   if (!BarsOff) ASMUpd(FP_SEG(Bars),FP_OFF(Bars));
  69. }
  70.  
  71. word fsize;
  72. word fs;
  73.  
  74. void UpdateTops();
  75. extern Flag Locked,UDBars=FALSE,IsStolen;
  76. void interrupt (*OldInt8)(...);
  77. void interrupt Int8(...) {
  78.   word c,ov,m,q;
  79.   long fp,sp,t,ch;
  80.   byte fekt;
  81.  
  82.   if (!TempoType) {
  83.     if ((OCount%8)) goto oo;
  84.   }
  85.   for (ch=0;ch<16;ch++) {
  86.     if (!(OCount%2)) {
  87.       if (Bars[ch]<(PlayTempo)) Bars[ch]=0;
  88.       if (Bars[ch]) Bars[ch]-=PlayTempo;
  89.       UpdateBars();
  90.     }
  91.     if (VibOn[ch]) {
  92.       VibPtr[ch]+=VibInc[ch];              // Update vibrato table cntr
  93.       if (VibPtr[ch]>=128)                 // Reset counter
  94.         VibPtr[ch]=0;
  95.       if (!Increment[ch])                  // Note port doing it for us?
  96.         Music.SetFreq(ch,CurFreqs[ch]+PitchWheel[ch]+SinTable[VibAmp][VibPtr[ch]]);
  97.     }
  98.     if (Increment[ch]) {                   // Deal with note port
  99.       t=(CurFreqs[ch]+PitchWheel[ch]);
  100.       if (Increment[ch]<0) {
  101.         if (t<=DestPitch[ch]) {
  102.           Increment[ch]=0;
  103.           PresPitch[ch]=0;
  104.           CurFreqs[ch]=DestPitch[ch];
  105.           DestPitch[ch]=0;
  106.         }
  107.         else
  108.           PresPitch[ch]+=Increment[ch];
  109.       }
  110.       else {
  111.         if (t>=DestPitch[ch]) {
  112.           Increment[ch]=0;
  113.           PresPitch[ch]=0;
  114.           CurFreqs[ch]=DestPitch[ch];
  115.           DestPitch[ch]=0;
  116.         }
  117.         else
  118.           PresPitch[ch]+=Increment[ch];
  119.       }
  120.     }
  121.     PitchWheel[ch]=PresPitch[ch]/256;
  122.     Music.SetFreq(ch,CurFreqs[ch]+PitchWheel[ch]+SinTable[VibAmp][VibPtr[ch]]);
  123.  
  124.     if (VIncrement[ch]) {                   // Deal with vol port
  125.       t=(CurVols[ch]*4)+VolWheel[ch];
  126.       if (VIncrement[ch]<0) {
  127.         if (t<=DestVol[ch]) {
  128.           VIncrement[ch]=0;
  129.           PresVol[ch]=0;
  130.           CurVols[ch]=DestVol[ch]/4;
  131.           DestVol[ch]=0;
  132.         }
  133.         else
  134.           PresVol[ch]+=VIncrement[ch];
  135.       }
  136.       else {
  137.         if (t>=DestVol[ch]) {
  138.           VIncrement[ch]=0;
  139.           PresVol[ch]=0;
  140.           CurVols[ch]=DestVol[ch]/4;
  141.           DestPitch[ch]=0;
  142.         }
  143.         else
  144.           PresVol[ch]+=VIncrement[ch];
  145.       }
  146.       VolWheel[ch]=PresVol[ch];
  147.       if ( ((CurVols[ch]*4)+VolWheel[ch])< 0) {
  148.         VIncrement[ch]=0;
  149.         PresVol[ch]=0;
  150.         CurVols[ch]=DestVol[ch]/4;
  151.         DestVol[ch]=0;
  152.         Music.SetVol(ch,VolTab[0]);
  153.       }
  154.       else
  155.         Music.SetVol(ch,VolTab[(CurVols[ch]*4)+VolWheel[ch]]);
  156.  
  157.     }
  158.  
  159.         if (RetLeft[ch] && ChanOn[ch]) {               // Deal with retrigger
  160.       CurSpc[ch]+=2;
  161.       if (CurSpc[ch]>=RetSpc[ch]) {
  162.         if (!OfftCnt[ch]) goto DoNote1;            // No note offset (retrig)
  163.         if (OfftCnt[ch]==RetCnt[ch]) goto DoNote1; // Time for output of note
  164.         goto NoNote1;
  165.         DoNote1:
  166.           q=RetSmp[ch];
  167.           m=Sample[q].LoopMode;
  168.           CurVols[ch]=RetVol[ch]-1;
  169.           CurChSmp[ch]=q;
  170.           if (m&(1<<2))
  171.             Music.PlaySample(Sample[q].Seg/2,
  172.                              Sample[q].Off/2,
  173.                              Sample[q].Rep/2,
  174.                              Sample[q].RepEnd/2,
  175.                              ch,m);
  176.           else
  177.             Music.PlaySample(Sample[q].Seg,
  178.                              Sample[q].Off,
  179.                              Sample[q].Rep,
  180.                              Sample[q].RepEnd,
  181.                              ch,m);
  182.           Music.SetVol(ch,VolTab[(CurVols[ch]*4)+VolWheel[ch]]);
  183.           RetLeft[ch]--;
  184.           CurSpc[ch]=0;
  185.         NoNote1:
  186.           RetCnt[ch]++;
  187.       }
  188.     }
  189.   }
  190.  
  191. oo:
  192.   if (OCount--) {
  193.     outportb(0x20,0x20);
  194.     return;
  195.   }
  196.   OCount=OverFlow;
  197.  
  198.   ov=CurVoice;
  199.   for (c=0;c<16;c++) {
  200.     CurVoice=c;
  201.     OfftCnt[CurVoice]=0; RetCnt[CurVoice]=0; RetLeft[CurVoice]=0;
  202. //    if (Bars[CurVoice]<(PlayTempo*2)) Bars[CurVoice]=0;
  203. //    if (Bars[CurVoice]) Bars[CurVoice]-=PlayTempo*2;
  204.     fekt=Pattern[CurSpot+3]&0xF0;
  205.     if (Pattern[CurSpot] && ChanOn[CurVoice] && fekt!=0x30) {
  206.       q=Pattern[CurSpot+1];
  207.       m=Sample[q].LoopMode;
  208.       if (Sample[Pattern[CurSpot+1]].SType&1) m|=(1<<2);
  209.       CurFreqs[CurVoice]=Freqs[Pattern[CurSpot]-1];
  210.       Music.SetFreq(CurVoice,CurFreqs[CurVoice]);
  211.       CurChSmp[CurVoice]=q;
  212.       if (m&(1<<2))
  213.         Music.PlaySample(Sample[q].Seg/2,
  214.                          Sample[q].Off/2,
  215.                          Sample[q].Rep/2,
  216.                          Sample[q].RepEnd/2,
  217.                          CurVoice,m);
  218.       else
  219.         Music.PlaySample(Sample[q].Seg,
  220.                          Sample[q].Off,
  221.                          Sample[q].Rep,
  222.                          Sample[q].RepEnd,
  223.                          CurVoice,m);
  224.       PresPitch[CurVoice]=0;
  225.       DestPitch[CurVoice]=0; Increment[CurVoice]=0;
  226.       Bars[CurVoice]=(Pattern[CurSpot+2]*fs)/16;
  227.     }
  228.     Music.SetBalance(CurVoice,CurBalance[CurVoice]);
  229.     if (Pattern[CurSpot+2] && ChanOn[CurVoice] && fekt!=0xa0) {
  230.       PresVol[CurVoice]=0; VolWheel[CurVoice]=0;
  231.       DestVol[CurVoice]=0; VIncrement[CurVoice]=0;
  232.  
  233.       CurVols[CurVoice]=(Pattern[CurSpot+2]-1);
  234.       Music.SetVol(CurVoice,VolTab[(CurVols[CurVoice]*4)]);
  235.       Bars[CurVoice]=(Pattern[CurSpot+2]*fs)/16;
  236.     }
  237.     if (Pattern[CurSpot+3]) {
  238.       switch(Pattern[CurSpot+3]&0xF0) {
  239.         case 0xf0:  // Modify tempo
  240.           CurTempo=Pattern[CurSpot+3]&0xF;
  241.           PlayTempo=CurTempo;
  242.           if (TempoType)
  243.             UpdateTempo(mTempo[PlayTempo]+TempoBend);
  244.           else
  245.             UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
  246.           break;
  247.         case 0xe0:  // Fine tempo up/cancel
  248.           if (Pattern[CurSpot+3]&0xF) {
  249.             TempoBend+=Pattern[CurSpot+3]&0xF;
  250.             if ((TempoBend+mTempo[PlayTempo])>=100)
  251.               TempoBend=100;
  252.           }
  253.           else
  254.             TempoBend=0;
  255.           if (TempoType)
  256.             UpdateTempo(mTempo[PlayTempo]+TempoBend);
  257.           else
  258.             UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
  259.           break;
  260.         case 0xd0:  // Fine tempo down/cancel
  261.           if (Pattern[CurSpot+3]&0xF) {
  262.             TempoBend-=Pattern[CurSpot+3]&0xF;
  263.             if ((TempoBend+mTempo[PlayTempo])<=0)
  264.               TempoBend=0;
  265.           }
  266.           else
  267.             TempoBend=0;
  268.           if (TempoType)
  269.             UpdateTempo(mTempo[PlayTempo]+TempoBend);
  270.           else
  271.             UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
  272.           break;
  273.         case 0xb0:  // Set Balance
  274.           CurBalance[CurVoice]=Pattern[CurSpot+3]&0xF;
  275.           Music.SetBalance(CurVoice,CurBalance[CurVoice]);
  276.           if (Tracking)
  277.             UpdatePanning();
  278.           break;
  279.         case 0x10:  // raise pitch
  280.           PresPitch[CurVoice]+=((Pattern[CurSpot+3]&0xF)*4)*256;
  281.           PitchWheel[CurVoice]=PresPitch[CurVoice]/256;
  282.           DestPitch[CurVoice]=0; Increment[CurVoice]=0;
  283.           Music.SetFreq(ch,CurFreqs[ch]+PitchWheel[ch]+SinTable[VibAmp][VibPtr[ch]]);
  284.           break;
  285.         case 0x20:  // lower pitch
  286.           PresPitch[CurVoice]-=((Pattern[CurSpot+3]&0xF)*4)*256;
  287.           PitchWheel[CurVoice]=PresPitch[CurVoice]/256;
  288.           DestPitch[CurVoice]=0; Increment[CurVoice]=0;
  289.           Music.SetFreq(ch,CurFreqs[ch]+PitchWheel[ch]+SinTable[VibAmp][VibPtr[ch]]);
  290.           break;
  291.         case 0x30:  // Port to note
  292.           if (Pattern[CurSpot]) {
  293.             t=0;
  294.             fp=CurFreqs[CurVoice]+PitchWheel[CurVoice];
  295.             sp=Freqs[Pattern[CurSpot]-1];
  296.             DestPitch[CurVoice]=sp;
  297.             if (fp>sp) {t=sp;sp=fp;fp=t;}
  298.             if (Pattern[CurSpot+3]&0xF)
  299.               Increment[CurVoice]=((sp-fp)*256)/((Pattern[CurSpot+3]&0xF)*
  300.                 (mTempo[PlayTempo]+TempoBend));
  301.             else
  302.               Increment[CurVoice]=((sp-fp)*256)/(1*
  303.                 (mTempo[PlayTempo]+TempoBend));
  304.             Increment[CurVoice]*=8;
  305.             if (t) Increment[CurVoice]=-Increment[CurVoice];
  306.           }
  307.           break;
  308.         case 0xC0:  // Note Offset
  309.           OfftCnt[CurVoice]=Pattern[CurSpot+3]&0xF;
  310.             RetLeft[CurVoice]=0xE;
  311.             if (TempoType)
  312.               RetSpc[CurVoice]=((mTempo[PlayTempo]+TempoBend)/(RetLeft[CurVoice]+1))/4;
  313.             else
  314.               RetSpc[CurVoice]=((mTempo[PlayTempo]+TempoBend)/(RetLeft[CurVoice]+1))/2;
  315.             RetSmp[CurVoice]=Pattern[CurSpot+1];
  316.             RetVol[CurVoice]=Pattern[CurSpot+2];
  317.             CurSpc[CurVoice]=0;
  318.           break;
  319.         case 0x40:  // Retrigger
  320.           if (Pattern[CurSpot]) {
  321.             RetLeft[CurVoice]=(Pattern[CurSpot+3]&0xF)-1;
  322.             if (TempoType)
  323.               RetSpc[CurVoice]=((mTempo[PlayTempo]+TempoBend)/(RetLeft[CurVoice]+1))/4;
  324.             else
  325.               RetSpc[CurVoice]=((mTempo[PlayTempo]+TempoBend)/(RetLeft[CurVoice]+1))/2;
  326.             RetSmp[CurVoice]=Pattern[CurSpot+1];
  327.             RetVol[CurVoice]=Pattern[CurSpot+2];
  328.             CurSpc[CurVoice]=0;
  329.           }
  330.           break;
  331.         case 0x50:  // Set vibrato amplitude
  332.           VibAmp=Pattern[CurSpot+3]&0xF;
  333.           break;
  334.         case 0x60:  // Vibrato Control
  335.           if (!VibOn[CurVoice]) {
  336.             VibOn[CurVoice]=1;
  337.             VibInc[CurVoice]=(Pattern[CurSpot+3]&0xF)*6;
  338.             VibPtr[CurVoice]=0;
  339.           }
  340.           else
  341.             VibInc[CurVoice]=(Pattern[CurSpot+3]&0xF)*6;
  342.           break;
  343.         case 0x90:  // Sustained vibrato control
  344.           if (Pattern[CurSpot+3]&0xF) {   // On
  345.             if (!VibOn[CurVoice]) {
  346.               VibOn[CurVoice]=2;
  347.               VibInc[CurVoice]=(Pattern[CurSpot+3]&0xF)*6;
  348.               VibPtr[CurVoice]=0;
  349.             }
  350.             else
  351.               VibInc[CurVoice]=(Pattern[CurSpot+3]&0xF)*6;
  352.           }
  353.           else {                          // Off
  354.             VibPtr[CurVoice]=0;
  355.             VibInc[CurVoice]=0;
  356.             VibOn[CurVoice]=FALSE;
  357.           }
  358.           break;
  359.         case 0x70:  // VolSldUp
  360.           q=Pattern[CurSpot+3]&0xF;
  361.           CurVols[CurVoice]+=q;
  362.           if (CurVols[CurVoice]>0xF) CurVols[CurVoice]=0xF;
  363.           Music.SetVol(CurVoice,VolTab[(CurVols[CurVoice]*4)+VolWheel[CurVoice]]);
  364.           Bars[CurVoice]=((CurVols[CurVoice]+1)*fs)/16;
  365.           break;
  366.         case 0x80:  // VolSldDn
  367.           q=Pattern[CurSpot+3]&0xF;
  368.           CurVols[CurVoice]-=q;
  369.           if (CurVols[CurVoice]<0) CurVols[CurVoice]=0;
  370.           Music.SetVol(CurVoice,VolTab[(CurVols[CurVoice]*4)+VolWheel[CurVoice]]);
  371.           Bars[CurVoice]=((CurVols[CurVoice]+1)*fs)/16;
  372.           break;
  373.         case 0xA0:  // Port to Vol
  374.           if (Pattern[CurSpot+2]) {
  375.             t=0;
  376.             fp=(CurVols[CurVoice]*4)+VolWheel[CurVoice];
  377.             sp=(Pattern[CurSpot+2]*4)-1;
  378.             DestVol[CurVoice]=sp;
  379.             if (fp>sp) {t=sp;sp=fp;fp=t;}
  380.             if (Pattern[CurSpot+3]&0xF)
  381.               VIncrement[CurVoice]=((sp-fp)*16)/((Pattern[CurSpot+3]&0xF)*
  382.                 (mTempo[PlayTempo]+TempoBend));
  383.             else
  384.               VIncrement[CurVoice]=((sp-fp)*16)/(1*
  385.                 (mTempo[PlayTempo]+TempoBend));
  386.             if (t) VIncrement[CurVoice]=-VIncrement[CurVoice];
  387.           }
  388.           break;
  389.         case 0x00: // Global funct
  390.           switch(Pattern[CurSpot+3]&0xF) {
  391.             case 1: // Ramp off
  392.             case 2: // Ramp on
  393.               VolRamps=(Pattern[CurSpot+3]&0xF)-1;
  394.               break;
  395.             case 3:
  396.               q=CurChSmp[CurVoice];
  397.               Music.SetLoops(Sample[q].Seg,Sample[q].Off,Sample[q].Len,
  398.                 Sample[q].LoopMode&0xF7,CurVoice);
  399.               break;
  400.             case 4: // 669 tempos
  401.             case 5: // far tempos
  402.               TempoType=(Pattern[CurSpot+3]&0xF)-4;
  403.               if (TempoType)
  404.                 UpdateTempo(mTempo[PlayTempo]+TempoBend);
  405.               else
  406.                 UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
  407.               break;
  408.           }
  409.           break;
  410.       }
  411.     }
  412.     if (VibOn[CurVoice]==1 && (Pattern[CurSpot+3]&0xF0)!=0x60) {
  413.       VibPtr[CurVoice]=0;
  414.       VibInc[CurVoice]=0;
  415.       VibOn[CurVoice]=FALSE;
  416.     }
  417.     if (Bars[CurVoice]>=fs) Bars[CurVoice]=fs-1;
  418.     if (Bars[CurVoice]<1) Bars[CurVoice]=1;
  419.   }
  420.   CurVoice=ov;
  421.   if (CurRow<=BreakLoc) {
  422.     if (CurRow-CurTop==31) {
  423.       if (Tracking) {
  424.         CurRow++;
  425.         CurTop=CurRow;
  426.         TrakUpdate=TRUE;
  427.       }
  428.       else
  429.         CurRow++;
  430.     }
  431.     else
  432.       if (Tracking) {
  433.         MoveCurs(CurVoice,CurRow+1);
  434.         UDBars=TRUE;;
  435.       }
  436.       else
  437.         CurRow++;
  438.   }
  439.   else {
  440.     if (PatLock) {
  441.       if (Tracking) {
  442.         TrakUpdate=TRUE;
  443.         CurRow=0; CurTop=0;
  444.       }
  445.       else
  446.         CurRow=0;
  447.     }
  448.     else {
  449.       PutAwayPat(CurPattern);
  450.       if (Order[CurOrder+1]==0xFF)
  451.         CurOrder=LoopTo;
  452.       else
  453.         CurOrder++;
  454.       CurPattern=Order[CurOrder];
  455.       GetPat(CurPattern);
  456.       if (Tracking) {
  457.         CurTop=0;
  458.         CurRow=0;
  459.         TrakUpdate=TRUE;
  460.       }
  461.       else
  462.         CurRow=0;
  463.     }
  464.   }
  465.  
  466.   outportb(0x20,0x20);
  467. }
  468.  
  469. void StartMusic() {
  470.   fs=fsize*4;
  471.   StopMusic();
  472.   KillBars();
  473.   memset(&PitchWheel[0],0,sizeof(PitchWheel));
  474.   memset(&VibOn[0],0,sizeof(VibOn));
  475.   memset(&VibPtr[0],0,sizeof(VibPtr));
  476.   memset(&VibInc[0],0,sizeof(VibInc));
  477.   memset(&RetLeft[0],0,sizeof(RetLeft));
  478.   PlayTempo=CurTempo;
  479.   UpdateChans();
  480.   UpdateOrder();
  481.   OldInt8=getvect(8);
  482.   setvect(8,Int8);
  483.   if (TempoType)
  484.     UpdateTempo(mTempo[PlayTempo]+TempoBend);
  485.   else
  486.     UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
  487.   OCount=OverFlow;
  488.   Playing=YES;
  489.  
  490.   if (!Tracking) {
  491.     DrawF(0,42,11,9," Playing song.. Press any key except D to stop playback - Press D to shell to DOS                                                   ");
  492.     do {
  493.       GetCh();
  494.       if (LKHit=='D') {
  495.         DosShell();
  496.         LKHit='D';
  497.       }
  498.     } while (LKHit=='D');
  499.     StopMusic();
  500.     UpdateStat();
  501.     UpdateChans();
  502.   }
  503. }
  504.  
  505. void StopMusic() {
  506.   word q;
  507.  
  508.   if (Playing) {
  509.     setvect(8,OldInt8);
  510.     outportb(0x43,0x34);
  511.     outportb(0x40,0);
  512.     outportb(0x40,0);
  513.     if (Tracking) UpdateChans();
  514.     KillBars();
  515.   }
  516.   for (q=0;q<16;q++) Music.StopSample(q);
  517.   Playing=NO;
  518. }
  519.  
  520.