home *** CD-ROM | disk | FTP | other *** search
- {$R-,V-,A+}
- UNIT NONALIZA;
-
- INTERFACE
-
- USES DOS;
-
- FUNCTION AdLib_Test:Boolean;
- FUNCTION Load_Music(Filename:String):Byte;
- PROCEDURE Start_Music;
- PROCEDURE Pause_Music;
- PROCEDURE Continue_Music;
- PROCEDURE Stop_Music;
-
- IMPLEMENTATION
-
- CONST
-
- AdLib_Port=$388;
-
- Notes :Array[1..12] Of Word=
- ($157,$16B,$181,$198,$1B0,$1CA,$1EA,$202,$220,$241,$263,$287);
-
- DecOp :Array[1..18] Of Byte=
- (0,1,2,3,4,5,8,9,10,11,12,13,16,17,18,19,20,21);
-
- DecOp9:Array[1..9] Of Byte=
- (1,2,3,7,8,9,13,14,15);
-
- TYPE
-
- SBIFormat =RECORD
- Sound_Params,Level,Attack_Rate,
- Release_Rate,Wave_Form :Array[0..1] Of Byte;
- Feedback :Byte;
- END;
-
- NoteFormat=RECORD
- Inst_Num,Sound_Num,Note_Num,Octa_Num:Byte;
- Duration_Num:Word;
- END;
-
- Mus =^Data;
- Data =Array[1..65018] Of Byte;
-
- VAR
- Load,
- Start,
- Pause,
- Continue,
- Stop :Boolean;
- I :Byte;
- Freq :Word;
- Int08,
- OldInt08 :Pointer;
- Activate_Music :Boolean;
- File1 :File;
- Filename :String;
- L_Inst :Array[1..64] Of SBIFormat;
- L_Note :Array[1..9] Of NoteFormat;
- Max_Vol :Array[1..9,0..2] Of Byte;
- Len_VoiceH,
- Len_VoiceL :Byte;
- Len_Voice,
- Csr_Gene :Word;
- Csr_Beg,
- Csr_End :Array[1..9] Of Word;
- Csr_Voice :Array[1..9] Of LongInt;
- Music :Mus;
- N_Inst,N_Sound,
- N_Note,N_Octa :Byte;
- N_Duration :Word;
- Nber_Inst,
- Nber_Voice,
- Nber_Tick :Byte;
- Busy,AdLib_OK :Boolean;
- Name_Inst :Array[1..64] Of String[8];
- Nothing :Array[1..100] Of Byte;
- Cptr :Byte;
- Regs :Registers;
-
-
- PROCEDURE Write_FM(Reg,Val:Byte);
- BEGIN
- ASM
- mov dx, 388h
- mov al, Reg
- out dx, al
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- inc dx
- mov al, Val
- out dx, al
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- in al, dx
- END;
- END;
-
-
- FUNCTION Read_FM:Byte;
- BEGIN
- ASM
- mov dx, 388h
- in al, dx
- mov @result, al
- END;
- END;
-
-
- FUNCTION AdLib_Test:Boolean;
- VAR
- Res1,Res2,I:Byte;
- BEGIN
- Write_FM($01,$00);
- Write_FM($04,$60);
- Write_FM($04,$80);
- Res1:=Read_FM;
- Write_FM($02,$FF);
- Write_FM($04,$21);
- FOR I:=0 TO 200 DO;
- Res2:=Read_FM;
- Write_FM($04,$60);
- Write_FM($04,$80);
- IF (((Res1 AND $E0)=0) AND ((Res2 AND $E0)=$C0))
- THEN AdLib_Test:=True
- ELSE AdLib_Test:=False;
- END;
-
-
- PROCEDURE Initialization_9voices;
- BEGIN
- Write_FM($08,$00);
- Write_FM($01,$20);
- Write_FM($BD,$DF);
- END;
-
-
- PROCEDURE Stop_Note(Voice:Byte);
- VAR
- Reg:Byte;
- BEGIN
- Reg:=$B0+Voice-1;
- Write_FM(Reg,0);
- END;
-
-
- PROCEDURE Play_Note(Voice:Byte;Code:Word;Octave:Byte);
- VAR
- Reg,Aux:Byte;
- BEGIN
- Reg:=$A0+Voice-1;
- Write_FM(Reg,Notes[Code] And $FF);
- Reg:=$B0+Voice-1;
- Aux:=(Notes[Code] SHR 8) OR (Octave SHL 2) OR $20;
- Write_FM(Reg,Aux);
- END;
-
-
- PROCEDURE Volume(Voice,Vol:Byte);
- VAR
- Reg :Byte;
- KSL,
- TL :Byte;
- BEGIN
- KSL:=Max_Vol[Voice,1] AND 192;
- TL :=63-Vol;
- Reg:=$40+DecOp[DecOp9[Voice]+3];
- Write_FM(Reg,KSL OR TL);
- IF Max_Vol[Voice,2]=1
- THEN BEGIN
- KSL:=Max_Vol[Voice,0] AND 192;
- TL :=63-Vol;
- Reg:=$40+DecOp[DecOp9[Voice]];
- Write_FM(Reg,KSL OR TL);
- END
- ELSE Write_FM($40+DecOp[DecOp9[Voice]],Max_Vol[Voice,0]);
- END;
-
-
- PROCEDURE Change_Instrument(Voice:Byte; VAR Instrument:SBIFormat);
- VAR
- Operator:Byte;
- BEGIN
- Operator:=DecOP[DecOP9[Voice]];
- Write_FM(Operator+$20,Instrument.Sound_Params[0]);
- Max_Vol[Voice,0]:=Instrument.Level[0];
- Write_FM(Operator+$60,Instrument.Attack_Rate[0]);
- Write_FM(Operator+$80,Instrument.Release_Rate[0]);
- Write_FM(Operator+$E0,Instrument.Wave_Form[0]);
- Write_FM(Voice-1+$C0,Instrument.Feedback);
- Max_Vol[Voice,2]:=Instrument.Feedback AND 1;
- Operator:=DecOP[DecOP9[Voice]+3];
- Write_FM(Operator+$20,Instrument.Sound_Params[1]);
- Max_Vol[Voice,1]:=Instrument.Level[1];
- Write_FM(Operator+$60,Instrument.Attack_Rate[1]);
- Write_FM(Operator+$80,Instrument.Release_Rate[1]);
- Write_FM(Operator+$E0,Instrument.Wave_Form[1]);
- END;
-
-
- FUNCTION Load_Music(Filename:String):Byte;
- VAR
- I :Byte;
- ChAux :String[4];
- BEGIN
- IF ((Load=False) OR (AdLib_OK=False)) {Chargement impossible}
- THEN BEGIN
- Load_Music:=1;
- Exit;
- END;
- {$I-}
- New(Music); {Pas assez de mémoire}
- {$I+}
- IF IOResult<>0
- THEN BEGIN
- Load_Music:=2;
- Exit;
- END;
- Assign(File1,Filename);
- {$I-}
- Reset(File1,1);
- {$I+}
- IF IOResult<>0
- THEN BEGIN
- Dispose(Music);
- Load_Music:=3; {Module non trouvé}
- Exit;
- END;
- IF FileSize(File1)<129
- THEN BEGIN
- Dispose(Music);
- Close(File1);
- Load_Music:=4; {Taille du module incorrecte}
- Exit;
- END;
- BlockRead(File1,Nothing[1],100);
- IF ((Nothing[1]<>70) OR (Nothing[2]<>77) OR
- (Nothing[3]<>57) OR (Nothing[4]<>64))
- THEN BEGIN
- Dispose(Music);
- Close(File1);
- Load_Music:=5; {Signature FM9 non trouvée}
- Exit;
- END;
- BlockRead(File1,Nber_Inst,1);
- BlockRead(File1,Nber_Voice,1);
- BlockRead(File1,Nber_Tick,1);
- FOR I:=1 TO Nber_Inst DO
- BEGIN
- {$I-}
- BlockRead(File1,Name_Inst[I][1],8);
- BlockRead(File1,L_Inst[I],11);
- {$I+}
- IF IOResult<>0
- THEN BEGIN
- Dispose(Music);
- Close(File1);
- Load_Music:=6; {Erreur dans instrument}
- Exit;
- END;
- END;
- Csr_Gene:=1;
- FOR I:=1 TO Nber_Voice DO
- BEGIN
- {$I-}
- BlockRead(File1,Len_VoiceH,1);
- BlockRead(File1,Len_VoiceL,1);
- {$I+}
- IF IOResult<>0
- THEN BEGIN
- Dispose(Music);
- Close(File1);
- Load_Music:=7; {Erreur dans taille voix}
- Exit;
- END;
- Len_Voice:=Len_VoiceH*256+Len_VoiceL;
- {$I-}
- BlockRead(File1,Music^[Csr_Gene],Len_Voice);
- {$I+}
- IF IOResult<>0
- THEN BEGIN
- Dispose(Music);
- Close(File1);
- Load_Music:=8; {Erreur dans événement}
- Exit;
- END;
- Csr_Beg[I]:=Csr_Gene;
- Csr_End[I]:=Len_Voice+Csr_Gene-1;
- Csr_Gene :=Csr_End[I]+1;
- END;
- Close(File1);
- Load_Music:=0;
- Load :=False;
- Start :=True;
- Pause :=False;
- Continue :=False;
- Stop :=False;
- FOR I:=1 TO Nber_Voice DO
- BEGIN
- Csr_Voice[I]:=Csr_Beg[I]-5;
- L_Note[I].Inst_Num :=0;
- L_Note[I].Sound_Num :=64;
- L_Note[I].Note_Num :=15;
- L_Note[I].Octa_Num :=9;
- L_Note[I].Duration_Num:=1;
- END;
- END;
-
-
- {LE DRIVER JOUANT JUSQU'A 9 VOIX DE MUSIQUE FM EN TACHE DE FOND EN ETANT
- APPELE PAR LE TIMER "FREQ" FOIS PAR SECONDE...}
- PROCEDURE Driver_FM9;Interrupt; { DRIVER }
- VAR
- I:Byte;
- BEGIN
- Dec(Cptr);
- IF Cptr=0
- THEN BEGIN
- Intr(103,Regs);
- Cptr:=Nber_Tick Div 18;
- END
- ELSE Port[$20]:=$20;
- IF ((Activate_Music=True) AND (Busy=False))
- THEN BEGIN
- Busy:=True;
- FOR I:=1 TO Nber_Voice DO
- BEGIN
- Dec(L_Note[I].Duration_Num);
- IF L_Note[I].Duration_Num<1
- THEN BEGIN
- Inc(Csr_Voice[I],5);
- IF Csr_Voice[I]>Csr_End[I]
- THEN Csr_Voice[I]:=Csr_Beg[I];
- N_Inst :=Music^[Csr_Voice[I]];
- N_Sound :=Music^[Csr_Voice[I]+1];
- N_Note :=Music^[Csr_Voice[I]+2] AND 15;
- N_Octa :=Music^[Csr_Voice[I]+2] SHR 4;
- N_Duration:=Music^[Csr_Voice[I]+3]*256+
- Music^[Csr_Voice[I]+4];
- Stop_Note(I);
- IF N_Inst<>L_Note[I].Inst_Num
- THEN BEGIN
- L_Note[I].Inst_Num:=N_Inst;
- L_Note[I].Sound_Num:=N_Sound;
- Change_Instrument(I,L_Inst[N_Inst]);
- Volume(I,N_Sound);
- END;
- IF N_Sound<>L_Note[I].Sound_Num
- THEN BEGIN
- L_Note[I].Sound_Num:=N_Sound;
- Volume(I,N_Sound);
- END;
- L_Note[I].Duration_Num:=N_Duration;
- IF N_Note<>13
- THEN Play_Note(I,N_Note,N_Octa);
- END;
- END;
- END;
- Busy:=False;
- END; { DRIVER }
-
-
- PROCEDURE Load_FM9_Driver;
- BEGIN
- Freq:=1193180 Div Nber_Tick;
- Cptr:=1;
- InLine($FA);
- Port[$43]:=$34;
- Port[$40]:=Lo(Freq);
- Port[$40]:=Hi(Freq);
- GetIntVec($08,OldInt08);
- Int08:=Ptr(Seg(Driver_FM9),Ofs(Driver_FM9));
- SetIntVec(103,OldInt08);
- SetIntVec($08,Int08);
- Inline($FB);
- END;
-
-
- PROCEDURE Unload_FM9_Driver;
- BEGIN
- IF Stop=True
- THEN BEGIN
- InLine($FA);
- Port[$43]:=$34;
- Port[$40]:=0;
- Port[$40]:=0;
- GetIntVec(103,OldInt08);
- SetIntVec($08,OldInt08);
- InLine($FB);
- END;
- Dispose(Music);
- Stop:=False;
- END;
-
-
- PROCEDURE Start_Music;
- BEGIN
- IF ((AdLib_OK=True) AND (Start=True))
- THEN BEGIN
- Load :=False;
- Start :=False;
- Pause :=True;
- Continue:=False;
- Stop :=True;
- Initialization_9voices;
- Load_FM9_Driver;
- Activate_Music:=True;
- END;
- END;
-
-
- PROCEDURE Stop_Music;
- VAR
- I:Byte;
- BEGIN
- IF AdLib_OK=True
- THEN BEGIN
- Activate_Music:=False;
- IF Stop=True
- THEN BEGIN
- FOR I:=1 TO Nber_Voice DO
- BEGIN
- Volume(I,0);
- Stop_Note(I);
- END;
- Unload_FM9_Driver;
- END;
- Start :=False;
- Pause :=False;
- Continue:=False;
- Load :=True;
- END;
- END;
-
-
- PROCEDURE Pause_Music;
- VAR
- I:Byte;
- BEGIN
- IF ((Adlib_OK=True) AND (Pause=True))
- THEN BEGIN
- Activate_Music:=False;
- Load :=False;
- Start :=False;
- Pause :=False;
- Continue :=True;
- Stop :=True;
- FOR I:=1 TO Nber_Voice DO
- Stop_Note(I);
- END;
- END;
-
-
- PROCEDURE Continue_Music;
- BEGIN
- IF ((Adlib_OK=True) AND (Continue=True))
- THEN BEGIN
- Activate_Music:=True;
- Load :=False;
- Start :=False;
- Pause :=True;
- Continue :=False;
- Stop :=True;
- END;
- END;
-
-
-
- BEGIN
- AdLib_OK :=False;
- Activate_Music:=False;
- Busy :=False;
- Load :=True;
- Start :=False;
- Pause :=False;
- Continue :=False;
- Stop :=False;
- IF AdLib_Test=True
- THEN AdLib_OK:=True;
- END.
-