;=====================================================================
; CLICK.COM clicks the PC's speaker each time a key is pressed.
; Assemble and link with:
;
;       MASM CLICK;
;       LINK CLICK;
;       EXE2BIN CLICK CLICK.EXE
;
; Copyright (c) 1990 Ziff-Davis Publishing Company
;=====================================================================

code    segment para public 'code'
        assume  cs:code
        org     100h

begin:  jmp     init                    ;Jump to initialization code

intvec  dd      ?                       ;Old interrupt 09H vector

;---------------------------------------------------------------------
; KBINT intercepts interrupt 09H and calls CLICK when a key is pressed.
;---------------------------------------------------------------------
kbint   proc    far
        pushf                           ;Save flags
        push    ax                      ;Save AX
        in      al,60h                  ;Read scan code
        test    al,80h                  ;Check for break code
        jnz     exit                    ;Exit on break
        call    click                   ;Click on make code
exit:   pop     ax                      ;Restore AX
        popf                            ;Restore flags
        jmp     intvec                  ;Jump to BIOS handler
kbint   endp

;---------------------------------------------------------------------
; CLICK programs the speaker to produce a short click.
;---------------------------------------------------------------------
click   proc    near
        sti                             ;Interrupts on
        mov     al,0B6h                 ;Program timer 2 to generate
        out     43h,al                  ;  pulses
        jmp     short $+2
        mov     al,0                    ;Send low byte of the 16-bit
        out     42h,al                  ;  value that will determine
        jmp     short $+2               ;  the pulse frequency
        mov     al,6                    ;Then send the high byte
        out     42h,al
        jmp     short $+2
        in      al,61h                  ;Speaker on
        jmp     short $+2
        or      al,3
        out     61h,al
        push    cx                      ;Save CX
        mov     cx,1000h                ;Timing delay
here:   loop    here
        pop     cx                      ;Restore CX
        in      al,61h                  ;Speaker off
        jmp     short $+2
        and     al,0FCh
        out     61h,al
        ret                             ;Return to caller
click   endp

;*********************************************************************
; End of resident code -- start of initialization code.  Everything from
; here on is discarded when the program becomes memory-resident.
;*********************************************************************

init    proc    near
        assume  cs:code,ds:code
        mov     ax,3509h                ;Get the current interrupt
        int     21h                     ;  09H vector and store it
        mov     word ptr intvec,bx
        mov     word ptr intvec[2],es
        mov     ax,2509h                ;Point interrupt 09H to
        mov     dx,offset kbint         ;  the KBINT routine
        int     21h
        mov     dx,offset init          ;Use interrupt 27H to
        int     27h                     ;  terminate and stay
init    endp                            ;  resident

code    ends
        end     begin
