[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]