unit Sound;
{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q-,R-,S+,T-,V+,X+,Y+}
{$M 16384,0,655360}
{$G+}
{$M 4096,0,65500}
interface

Function InitSoundSystem(Base : Word) : boolean;
Procedure SpeakerOn;
Procedure SpeakerOff;
Procedure DMAStop;
Procedure DMAContinue;
Procedure PlaySample(Sample:Pointer;Size:Word;Freq:Word;DMACh:Byte);
Procedure WriteDSP(Data : Byte);
Function ReadDSP : Byte;

const _init=$2;

implementation
Const DmaChannel : Array [0..3,1..3] of Byte =
  (($87,$0,$1),($83,$2,$3),($81,$2,$3),($82,$6,$7));
Var   Reset, ReadData, WriteData, DataAvailable : Word;
      Offset, Page: Word;
Function InitSoundSystem;
Begin
{ InitSoundSystem := 1;{}
 Base := Base * $10;
 Reset := Base + $206;
 ReadData := Base + $20A;
 WriteData := Base + $20C;
 DataAvailable := Base + $20E;
 Port[Reset] := 1;
 Port[Reset] := 0;
 InitSoundSystem:=(Port[DataAvailable] And $80 = $80) And (Port[ReadData] = $AA);
End;

Procedure WriteDSP(Data : Byte);
Begin
 While Port[WriteData] And $80 <> 0 Do;
 Port[WriteData] := Data;
End;

Function ReadDSP : Byte;
Begin
 While Port[DataAvailable] And $80 = 0 Do;
 ReadDSP := Port[ReadData];
End;

Procedure SpeakerOn;
Begin
 WriteDSP($D1);
End;

Procedure SpeakerOff;
Begin
 WriteDSP($D3);
End;

Procedure DMAStop;
Begin
 WriteDSP($D0);
End;

Procedure DMAContinue;
Begin
 WriteDSP($D4);
End;

Procedure PlaySample;
Begin
 SpeakerOn;
 Dec(Size);
 Offset := Seg(Sample^) Shl 4 + Ofs(Sample^);
 Page := (Seg(Sample^) + Ofs(Sample^) Shr 4) Shr 12;
 Port[$0A] := $4 + DMACh;
 Port[$0C] := 0; {Clear the internal DMA flip-flop}
 Port[$0B] := $48 + DMACh;
 Port[DMAChannel[1,2]] := Lo(Offset);
 Port[DMAChannel[1,2]] := Hi(Offset);
 Port[DMAChannel[1,1]] := Page;
 Port[DMAChannel[1,3]] := Lo(Size);
 Port[DMAChannel[1,3]] := Hi(Size);
 Port[$0A] := DMACh;
 WriteDSP($40);
 WriteDSP(256 - 1000000 Div Freq);
 WriteDSP($14);
 WriteDSP(Lo(Size));
 WriteDSP(Hi(Size));
End;

end.