home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Large Pack of OldSkool DOS MOD Trackers
/
far096.zip
/
FARTRAK.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-30
|
16KB
|
520 lines
// Piece of code from FARTRAK.CPP
// This should allow you to use FARs in your own programs
// By Daniel Potter/Digital Infinity
// Code for F2R's to be released soon
word OverFlow=0,OCount=0,PlayTempo=CurTempo,PlayOrder=CurOrder;
int TempoBend=0;
int mTempo[16];
long PitchWheel[16]={0},DestPitch[16]={0},Increment[16]={0},PresPitch[16]={0};
int VolWheel[16]={0},DestVol[16]={0},VIncrement[16]={0},PresVol[16]={0};
long RetLeft[16]={0},RetSpc[16]={0},CurSpc[16]={0},RetSmp[16]={0},RetVol[16]={0xF};
int OfftCnt[16]={0},RetCnt[16]={0};
int VibOn[16]={0};
int VibPtr[16]={0},VibInc[16]={0};
int CurFreqs[16]={0};
int CurVols[16]={15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15};
int SinTable[16][128]={0};
int VibAmp=4;
int CurChSmp[16]={0};
Flag near VolRamps=TRUE;
Flag near TempoType=1;
void UdTempo() {
if (TempoType)
UpdateTempo(mTempo[PlayTempo]+TempoBend);
else
UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
return;
}
void CalcTempo() {
word q;
double t,f=1,y,amp;
mTempo[0]=256;
for (q=1;q<16;q++) mTempo[q]=128/q;
for (amp=0;amp<16;amp++)
for (t=0;t<1;t+=(1.0/128)) {
y=sin(2*3.1415*f*t)*amp;
SinTable[amp][t*128]=y;
}
}
extern "C" void IRQHook() {
pokeb(TSeg,132*2,peekb(TSeg,132*2)^128);
}
byte Bars[16]={0};
extern Flag BarsOff;
void UpdateBars();
void KillBars() {
memset(Bars,0,16);
if (!BarsOff) {
DrawF(94,5,0xe,0xf,"ÇÇääêêîîÉÉööÿÿ££ááññ¿¿¼¼░░┤┤╕╕╝╝");
DrawF(94,6,0xd,0xc,"üüààëëììææòòÖÖ¥¥ííÑÑ⌐⌐¡¡▒▒╡╡╣╣╜╜");
DrawF(94,7,0xd,0xc,"ééååèèÄÄÆÆûûÜÜ₧₧ó󪪬¬««▓▓╢╢║║╛╛");
DrawF(94,8,0xd,0xc,"ââççïïÅÅôôùù¢¢ƒƒúúºº½½»»││╖╖╗╗┐┐");
DrawF(94,4,0xb,0x9," 0 1 2 3 4 5 6 7 8 9 A B C D E F");
UpdateBars();
}
}
void ASMUpd(word,word);
void UpdateBars() {
if (!BarsOff) ASMUpd(FP_SEG(Bars),FP_OFF(Bars));
}
word fsize;
word fs;
void UpdateTops();
extern Flag Locked,UDBars=FALSE,IsStolen;
void interrupt (*OldInt8)(...);
void interrupt Int8(...) {
word c,ov,m,q;
long fp,sp,t,ch;
byte fekt;
if (!TempoType) {
if ((OCount%8)) goto oo;
}
for (ch=0;ch<16;ch++) {
if (!(OCount%2)) {
if (Bars[ch]<(PlayTempo)) Bars[ch]=0;
if (Bars[ch]) Bars[ch]-=PlayTempo;
UpdateBars();
}
if (VibOn[ch]) {
VibPtr[ch]+=VibInc[ch]; // Update vibrato table cntr
if (VibPtr[ch]>=128) // Reset counter
VibPtr[ch]=0;
if (!Increment[ch]) // Note port doing it for us?
Music.SetFreq(ch,CurFreqs[ch]+PitchWheel[ch]+SinTable[VibAmp][VibPtr[ch]]);
}
if (Increment[ch]) { // Deal with note port
t=(CurFreqs[ch]+PitchWheel[ch]);
if (Increment[ch]<0) {
if (t<=DestPitch[ch]) {
Increment[ch]=0;
PresPitch[ch]=0;
CurFreqs[ch]=DestPitch[ch];
DestPitch[ch]=0;
}
else
PresPitch[ch]+=Increment[ch];
}
else {
if (t>=DestPitch[ch]) {
Increment[ch]=0;
PresPitch[ch]=0;
CurFreqs[ch]=DestPitch[ch];
DestPitch[ch]=0;
}
else
PresPitch[ch]+=Increment[ch];
}
}
PitchWheel[ch]=PresPitch[ch]/256;
Music.SetFreq(ch,CurFreqs[ch]+PitchWheel[ch]+SinTable[VibAmp][VibPtr[ch]]);
if (VIncrement[ch]) { // Deal with vol port
t=(CurVols[ch]*4)+VolWheel[ch];
if (VIncrement[ch]<0) {
if (t<=DestVol[ch]) {
VIncrement[ch]=0;
PresVol[ch]=0;
CurVols[ch]=DestVol[ch]/4;
DestVol[ch]=0;
}
else
PresVol[ch]+=VIncrement[ch];
}
else {
if (t>=DestVol[ch]) {
VIncrement[ch]=0;
PresVol[ch]=0;
CurVols[ch]=DestVol[ch]/4;
DestPitch[ch]=0;
}
else
PresVol[ch]+=VIncrement[ch];
}
VolWheel[ch]=PresVol[ch];
if ( ((CurVols[ch]*4)+VolWheel[ch])< 0) {
VIncrement[ch]=0;
PresVol[ch]=0;
CurVols[ch]=DestVol[ch]/4;
DestVol[ch]=0;
Music.SetVol(ch,VolTab[0]);
}
else
Music.SetVol(ch,VolTab[(CurVols[ch]*4)+VolWheel[ch]]);
}
if (RetLeft[ch] && ChanOn[ch]) { // Deal with retrigger
CurSpc[ch]+=2;
if (CurSpc[ch]>=RetSpc[ch]) {
if (!OfftCnt[ch]) goto DoNote1; // No note offset (retrig)
if (OfftCnt[ch]==RetCnt[ch]) goto DoNote1; // Time for output of note
goto NoNote1;
DoNote1:
q=RetSmp[ch];
m=Sample[q].LoopMode;
CurVols[ch]=RetVol[ch]-1;
CurChSmp[ch]=q;
if (m&(1<<2))
Music.PlaySample(Sample[q].Seg/2,
Sample[q].Off/2,
Sample[q].Rep/2,
Sample[q].RepEnd/2,
ch,m);
else
Music.PlaySample(Sample[q].Seg,
Sample[q].Off,
Sample[q].Rep,
Sample[q].RepEnd,
ch,m);
Music.SetVol(ch,VolTab[(CurVols[ch]*4)+VolWheel[ch]]);
RetLeft[ch]--;
CurSpc[ch]=0;
NoNote1:
RetCnt[ch]++;
}
}
}
oo:
if (OCount--) {
outportb(0x20,0x20);
return;
}
OCount=OverFlow;
ov=CurVoice;
for (c=0;c<16;c++) {
CurVoice=c;
OfftCnt[CurVoice]=0; RetCnt[CurVoice]=0; RetLeft[CurVoice]=0;
// if (Bars[CurVoice]<(PlayTempo*2)) Bars[CurVoice]=0;
// if (Bars[CurVoice]) Bars[CurVoice]-=PlayTempo*2;
fekt=Pattern[CurSpot+3]&0xF0;
if (Pattern[CurSpot] && ChanOn[CurVoice] && fekt!=0x30) {
q=Pattern[CurSpot+1];
m=Sample[q].LoopMode;
if (Sample[Pattern[CurSpot+1]].SType&1) m|=(1<<2);
CurFreqs[CurVoice]=Freqs[Pattern[CurSpot]-1];
Music.SetFreq(CurVoice,CurFreqs[CurVoice]);
CurChSmp[CurVoice]=q;
if (m&(1<<2))
Music.PlaySample(Sample[q].Seg/2,
Sample[q].Off/2,
Sample[q].Rep/2,
Sample[q].RepEnd/2,
CurVoice,m);
else
Music.PlaySample(Sample[q].Seg,
Sample[q].Off,
Sample[q].Rep,
Sample[q].RepEnd,
CurVoice,m);
PresPitch[CurVoice]=0;
DestPitch[CurVoice]=0; Increment[CurVoice]=0;
Bars[CurVoice]=(Pattern[CurSpot+2]*fs)/16;
}
Music.SetBalance(CurVoice,CurBalance[CurVoice]);
if (Pattern[CurSpot+2] && ChanOn[CurVoice] && fekt!=0xa0) {
PresVol[CurVoice]=0; VolWheel[CurVoice]=0;
DestVol[CurVoice]=0; VIncrement[CurVoice]=0;
CurVols[CurVoice]=(Pattern[CurSpot+2]-1);
Music.SetVol(CurVoice,VolTab[(CurVols[CurVoice]*4)]);
Bars[CurVoice]=(Pattern[CurSpot+2]*fs)/16;
}
if (Pattern[CurSpot+3]) {
switch(Pattern[CurSpot+3]&0xF0) {
case 0xf0: // Modify tempo
CurTempo=Pattern[CurSpot+3]&0xF;
PlayTempo=CurTempo;
if (TempoType)
UpdateTempo(mTempo[PlayTempo]+TempoBend);
else
UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
break;
case 0xe0: // Fine tempo up/cancel
if (Pattern[CurSpot+3]&0xF) {
TempoBend+=Pattern[CurSpot+3]&0xF;
if ((TempoBend+mTempo[PlayTempo])>=100)
TempoBend=100;
}
else
TempoBend=0;
if (TempoType)
UpdateTempo(mTempo[PlayTempo]+TempoBend);
else
UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
break;
case 0xd0: // Fine tempo down/cancel
if (Pattern[CurSpot+3]&0xF) {
TempoBend-=Pattern[CurSpot+3]&0xF;
if ((TempoBend+mTempo[PlayTempo])<=0)
TempoBend=0;
}
else
TempoBend=0;
if (TempoType)
UpdateTempo(mTempo[PlayTempo]+TempoBend);
else
UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
break;
case 0xb0: // Set Balance
CurBalance[CurVoice]=Pattern[CurSpot+3]&0xF;
Music.SetBalance(CurVoice,CurBalance[CurVoice]);
if (Tracking)
UpdatePanning();
break;
case 0x10: // raise pitch
PresPitch[CurVoice]+=((Pattern[CurSpot+3]&0xF)*4)*256;
PitchWheel[CurVoice]=PresPitch[CurVoice]/256;
DestPitch[CurVoice]=0; Increment[CurVoice]=0;
Music.SetFreq(ch,CurFreqs[ch]+PitchWheel[ch]+SinTable[VibAmp][VibPtr[ch]]);
break;
case 0x20: // lower pitch
PresPitch[CurVoice]-=((Pattern[CurSpot+3]&0xF)*4)*256;
PitchWheel[CurVoice]=PresPitch[CurVoice]/256;
DestPitch[CurVoice]=0; Increment[CurVoice]=0;
Music.SetFreq(ch,CurFreqs[ch]+PitchWheel[ch]+SinTable[VibAmp][VibPtr[ch]]);
break;
case 0x30: // Port to note
if (Pattern[CurSpot]) {
t=0;
fp=CurFreqs[CurVoice]+PitchWheel[CurVoice];
sp=Freqs[Pattern[CurSpot]-1];
DestPitch[CurVoice]=sp;
if (fp>sp) {t=sp;sp=fp;fp=t;}
if (Pattern[CurSpot+3]&0xF)
Increment[CurVoice]=((sp-fp)*256)/((Pattern[CurSpot+3]&0xF)*
(mTempo[PlayTempo]+TempoBend));
else
Increment[CurVoice]=((sp-fp)*256)/(1*
(mTempo[PlayTempo]+TempoBend));
Increment[CurVoice]*=8;
if (t) Increment[CurVoice]=-Increment[CurVoice];
}
break;
case 0xC0: // Note Offset
OfftCnt[CurVoice]=Pattern[CurSpot+3]&0xF;
RetLeft[CurVoice]=0xE;
if (TempoType)
RetSpc[CurVoice]=((mTempo[PlayTempo]+TempoBend)/(RetLeft[CurVoice]+1))/4;
else
RetSpc[CurVoice]=((mTempo[PlayTempo]+TempoBend)/(RetLeft[CurVoice]+1))/2;
RetSmp[CurVoice]=Pattern[CurSpot+1];
RetVol[CurVoice]=Pattern[CurSpot+2];
CurSpc[CurVoice]=0;
break;
case 0x40: // Retrigger
if (Pattern[CurSpot]) {
RetLeft[CurVoice]=(Pattern[CurSpot+3]&0xF)-1;
if (TempoType)
RetSpc[CurVoice]=((mTempo[PlayTempo]+TempoBend)/(RetLeft[CurVoice]+1))/4;
else
RetSpc[CurVoice]=((mTempo[PlayTempo]+TempoBend)/(RetLeft[CurVoice]+1))/2;
RetSmp[CurVoice]=Pattern[CurSpot+1];
RetVol[CurVoice]=Pattern[CurSpot+2];
CurSpc[CurVoice]=0;
}
break;
case 0x50: // Set vibrato amplitude
VibAmp=Pattern[CurSpot+3]&0xF;
break;
case 0x60: // Vibrato Control
if (!VibOn[CurVoice]) {
VibOn[CurVoice]=1;
VibInc[CurVoice]=(Pattern[CurSpot+3]&0xF)*6;
VibPtr[CurVoice]=0;
}
else
VibInc[CurVoice]=(Pattern[CurSpot+3]&0xF)*6;
break;
case 0x90: // Sustained vibrato control
if (Pattern[CurSpot+3]&0xF) { // On
if (!VibOn[CurVoice]) {
VibOn[CurVoice]=2;
VibInc[CurVoice]=(Pattern[CurSpot+3]&0xF)*6;
VibPtr[CurVoice]=0;
}
else
VibInc[CurVoice]=(Pattern[CurSpot+3]&0xF)*6;
}
else { // Off
VibPtr[CurVoice]=0;
VibInc[CurVoice]=0;
VibOn[CurVoice]=FALSE;
}
break;
case 0x70: // VolSldUp
q=Pattern[CurSpot+3]&0xF;
CurVols[CurVoice]+=q;
if (CurVols[CurVoice]>0xF) CurVols[CurVoice]=0xF;
Music.SetVol(CurVoice,VolTab[(CurVols[CurVoice]*4)+VolWheel[CurVoice]]);
Bars[CurVoice]=((CurVols[CurVoice]+1)*fs)/16;
break;
case 0x80: // VolSldDn
q=Pattern[CurSpot+3]&0xF;
CurVols[CurVoice]-=q;
if (CurVols[CurVoice]<0) CurVols[CurVoice]=0;
Music.SetVol(CurVoice,VolTab[(CurVols[CurVoice]*4)+VolWheel[CurVoice]]);
Bars[CurVoice]=((CurVols[CurVoice]+1)*fs)/16;
break;
case 0xA0: // Port to Vol
if (Pattern[CurSpot+2]) {
t=0;
fp=(CurVols[CurVoice]*4)+VolWheel[CurVoice];
sp=(Pattern[CurSpot+2]*4)-1;
DestVol[CurVoice]=sp;
if (fp>sp) {t=sp;sp=fp;fp=t;}
if (Pattern[CurSpot+3]&0xF)
VIncrement[CurVoice]=((sp-fp)*16)/((Pattern[CurSpot+3]&0xF)*
(mTempo[PlayTempo]+TempoBend));
else
VIncrement[CurVoice]=((sp-fp)*16)/(1*
(mTempo[PlayTempo]+TempoBend));
if (t) VIncrement[CurVoice]=-VIncrement[CurVoice];
}
break;
case 0x00: // Global funct
switch(Pattern[CurSpot+3]&0xF) {
case 1: // Ramp off
case 2: // Ramp on
VolRamps=(Pattern[CurSpot+3]&0xF)-1;
break;
case 3:
q=CurChSmp[CurVoice];
Music.SetLoops(Sample[q].Seg,Sample[q].Off,Sample[q].Len,
Sample[q].LoopMode&0xF7,CurVoice);
break;
case 4: // 669 tempos
case 5: // far tempos
TempoType=(Pattern[CurSpot+3]&0xF)-4;
if (TempoType)
UpdateTempo(mTempo[PlayTempo]+TempoBend);
else
UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
break;
}
break;
}
}
if (VibOn[CurVoice]==1 && (Pattern[CurSpot+3]&0xF0)!=0x60) {
VibPtr[CurVoice]=0;
VibInc[CurVoice]=0;
VibOn[CurVoice]=FALSE;
}
if (Bars[CurVoice]>=fs) Bars[CurVoice]=fs-1;
if (Bars[CurVoice]<1) Bars[CurVoice]=1;
}
CurVoice=ov;
if (CurRow<=BreakLoc) {
if (CurRow-CurTop==31) {
if (Tracking) {
CurRow++;
CurTop=CurRow;
TrakUpdate=TRUE;
}
else
CurRow++;
}
else
if (Tracking) {
MoveCurs(CurVoice,CurRow+1);
UDBars=TRUE;;
}
else
CurRow++;
}
else {
if (PatLock) {
if (Tracking) {
TrakUpdate=TRUE;
CurRow=0; CurTop=0;
}
else
CurRow=0;
}
else {
PutAwayPat(CurPattern);
if (Order[CurOrder+1]==0xFF)
CurOrder=LoopTo;
else
CurOrder++;
CurPattern=Order[CurOrder];
GetPat(CurPattern);
if (Tracking) {
CurTop=0;
CurRow=0;
TrakUpdate=TRUE;
}
else
CurRow=0;
}
}
outportb(0x20,0x20);
}
void StartMusic() {
fs=fsize*4;
StopMusic();
KillBars();
memset(&PitchWheel[0],0,sizeof(PitchWheel));
memset(&VibOn[0],0,sizeof(VibOn));
memset(&VibPtr[0],0,sizeof(VibPtr));
memset(&VibInc[0],0,sizeof(VibInc));
memset(&RetLeft[0],0,sizeof(RetLeft));
PlayTempo=CurTempo;
UpdateChans();
UpdateOrder();
OldInt8=getvect(8);
setvect(8,Int8);
if (TempoType)
UpdateTempo(mTempo[PlayTempo]+TempoBend);
else
UpdateTempo(mTempo[PlayTempo]+(TempoBend*2));
OCount=OverFlow;
Playing=YES;
if (!Tracking) {
DrawF(0,42,11,9," Playing song.. Press any key except D to stop playback - Press D to shell to DOS ");
do {
GetCh();
if (LKHit=='D') {
DosShell();
LKHit='D';
}
} while (LKHit=='D');
StopMusic();
UpdateStat();
UpdateChans();
}
}
void StopMusic() {
word q;
if (Playing) {
setvect(8,OldInt8);
outportb(0x43,0x34);
outportb(0x40,0);
outportb(0x40,0);
if (Tracking) UpdateChans();
KillBars();
}
for (q=0;q<16;q++) Music.StopSample(q);
Playing=NO;
}