[Back to SOUND SWAG index]  [Back to Main SWAG index]  [Original]

{
If you want absolute silence (no ticks and very short beeps you get with the
timer interrupt approach), and you are running QEMM 7.03 or higher, you can
use this.If anyone is interested, I have also some sources with the same
routines to capture IO access under QEMM.
===
{ NoSound, PC Speaker sound killer for QEMM 7.03+, Arne de Bruijn, 19960405. }
{ Released to the Public Domain. }
{ Run it to install, run with /U to remove it. }
{$G+}
uses dos;
{ Resident part }
{ Only code segment will be preserved, so necessary variables are stored here
}procedure QPI_CS; assembler; asm db 0,0,0; end;
procedure OldTrap_CS; assembler; asm end;
procedure OldIOTrap_CS; assembler; asm db 0,0,0; end;

procedure MyTrap; far; assembler; { Called when something accesses port $61 }
asm
 test cl,4      { Is the program writing to port $61? }
 jne @IsWrite   { Yes, jump to @IsWrite }
 push bx
 mov bx,ax
 mov ax,1a05h   { Pass port read to QEMM, to execute it }
 call dword ptr cs:[QPI_CS]
 mov ax,bx
 pop bx
 retf
@IsWrite:
 and al,not 2   { Clear speaker bits, so it's always off }
 push bx
 mov bx,ax
 mov ax,1a05h   { Pass port write to QEMM, to execute it }
 call dword ptr cs:[QPI_CS]
 mov ax,bx
 pop bx
end;

procedure End_Of_TSR_Label; assembler; asm end;

type
 TPtr=record Ofs,Seg:word; end;
const
 QPI:pointer=NIL;
function GetQemmApi(var QPI:pointer):boolean; assembler;
asm
 mov ah,3fh
 mov cx,'QE'
 mov dx,'MM'
 int 67h
 mov al,0
 test ah,ah
 jnz @NoQemm
 mov ax,di
 mov dx,es
 cld
 les di,QPI
 stosw
 mov ax,dx
 stosw
 mov al,1
@NoQemm:
end;

procedure QPI_SetIOCallback(IOCallback:pointer); assembler;
asm
 mov ax,1a07h
 les di,IOCallback
 call [QPI]
end;

function QPI_GetPortTrap(PortNo:word):boolean; assembler;
asm
 mov ax,1a08h
 mov dx,PortNo
 call [QPI]
 mov al,bl
end;

procedure QPI_SetPortTrap(PortNo:word); assembler;
asm
 mov ax,1a09h
 mov dx,PortNo
 call [QPI]
end;

procedure QPI_ClearPortTrap(PortNo:word); assembler;
asm
 mov ax,1a0ah
 mov dx,PortNo
 call [QPI]
end;

function QPI_GetVersion(var Version:word):boolean; assembler;
asm
 mov ax,word ptr [QPI]
 or ax,word ptr [QPI+2]
 jz @NoQemm
 mov ah,3
 call [QPI]
 jc @NoQemm
 les di,Version
 stosw
 mov al,1
 db 0a9h { Skip following instruction (2 bytes) }
@NoQemm:
 mov al,0
end;

procedure QPI_GetIOCallback(var IOCallBack:pointer); assembler;
asm
 mov ax,1a06h
 call [QPI]
 mov ax,di
 mov dx,es
 cld
 les di,IOCallBack
 stosw
 mov ax,dx
 stosw
end;

var
 W:word;
 OldIOTrap:pointer;
 S:string[2];
begin
 if not GetQemmApi(QPI) then
  begin WriteLn('QEMM not installed!'); Halt(1); end;
 pointer((@QPI_CS)^):=QPI;
 if not QPI_GetVersion(W) then
  begin WriteLn('QPI_GetVersion error!'); Halt(1); end;
 if W<$0703 then
  begin WriteLn('Need QEMM 7.03+'); Halt(1); end;
 QPI_GetIOCallback(OldIOTrap); { Get current IO trap function }
 if word(OldIOTrap)=Ofs(MyTrap) then { Ours? }
  begin
   S:=ParamStr(1); S[2]:=Upcase(S[2]);
   if S<>'/U' then
    WriteLn('NoSound already installed! Use /U to unload.')
   else
    begin
     { Restore port trap state }
     if not boolean(ptr(TPtr(OldIOTrap).Seg,ofs(OldTrap_CS))^) then
      QPI_ClearPortTrap($61);
     QPI_SetIOCallback(pointer(ptr(TPtr(OldIOTrap).Seg,ofs(OldIOTrap_CS))^));
     W:=TPtr(OldIOTrap).Seg-$10;  { TSR PSP segment (just under code segment)
}     asm
      mov ah,49h         { DOS function 'Free memory block' }
      mov es,W           { Get TSR PSP segment }
      push es            { Save it }
      mov es,es:[2ch]    { Get TSR environment segment }
      int 21h            { Free it }
      mov ah,49h         { Again 'Free memory block' }
      pop es             { Restore TSR PSP segment }
      int 21h            { Free it }
     end;
     WriteLn('NoSound removed.');
    end;
   Halt(0);
  end;
 QPI_SetIOCallback(@MyTrap);
 pointer((@OldIOTrap_CS)^):=OldIOTrap;
 boolean((@OldTrap_CS)^):=QPI_GetPortTrap($61);
 QPI_SetPortTrap($61);
 WriteLn('NoSound installed.');
 swapvectors;
 asm
  mov ax,3100h   { DOS function 'Terminate and stay resident' }
  mov dx,offset End_Of_Tsr_Label+15+256  { Calculate resident size }
  shr dx,4       { Scale down to paragraphs }
  int 21h        { Go TSR }
 end;
end.

[Back to SOUND SWAG index]  [Back to Main SWAG index]  [Original]