;---------------------------------
; Here's some code I wrote a while ago to change the beep.  This is
; ready to assemble - all I've done is removed the custom bell routine.
; Feel free to plagiarize.        Mitch Ames

.radix  16

cr      equ     0Dh
lf      equ     0Ah

code    segment
assume  cs:code,ds:code,es:code,ss:code

org     0100

start:  jmp     init

int_10: cmp     ax,0E07                 ;write bell?
        je      beep
        jmp     dword ptr cs:org_10     ;if not, back to the BIOS

beep:   ; insert your routine here preserving regs
        ; (or nothing if you just want to kill the bell
        pop     cx
        pop     bx
        pop     ax
        iret

end_tsr_code    equ     $

org_10  dd      ?

; Install TSR hooking into interrupt 10

init:   mov     si,81                   ;point to command line
parse:  lodsb
        and     al,not 20               ;upper case
        cmp     al,"U"
        je      unload                  ;if "u", unload
        cmp     al,cr                   ;if no params, load TSR
        jne     parse

        mov     ax,3510                 ;save current interrupt vector
        int     21
        mov     word ptr org_10,bx
        mov     word ptr org_10+2,es
        mov     dx,offset int_10        ;point vector to new routine
        mov     ax,2510
        int     21
        mov     dx,offset loaded        ;display message
        mov     ah,9
        int     21
        mov     ax,3100                 ;terminate and stay resident
        mov     dx,(init-start+10F)/10  ;number of paragraphs to reserve
        int     21

; Unload TSR hooked into interrupt 10

unload: mov     ax,3510                 ;get interrupt vector
        int     21
        mov     di,bx                   ;point ES:DI to interrupt routine
        mov     si,offset int_10        ;point DS:SI to this program's TSR code
        mov     cx,end_tsr_code-int_10  ;length of code
        repe    cmpsb                   ;compare them
        jne     fail                    ;quit if they're not the same
        push    ds                      ;save program DS
        lds     dx,es:org_10            ;restore original interrupt
        mov     ax,2510
        int     21
        pop     ds                      ;restore program DS
        push    es                      ;save TSR program segment
        mov     bx,es                   ;and copy to BX
        mov     ax,es:2C                ;get TSR's environment segment to AX
        push    ax                      ;save it
        dec     ax                      ;get memory control block's segment
        mov     es,ax                   ;to ES
        cmp     bx,es:[1]               ;check that environment block is still
                                        ;owned by TSR program block
        jne     fail                    ;quit if not
        pop     es                      ;restore TSR's environment segment
        mov     ah,49                   ;release memory
        int     21
        jc      fail                    ;quit if it fails
        pop     es                      ;restore TSR program segment
        mov     ah,49                   ;release memory
        int     21
        mov     dx,offset removed       ;message if successful
        mov     al,0                    ;exit code = 0
        jnc     quit                    ;quit if succeeded
fail:   mov     dx,offset not_rem       ;message if failed
        mov     al,1                    ;exit code = 1

quit:   push    ax                      ;save exit code
        mov     ah,9                    ;write message in DS:DX
        int     21
        pop     ax                      ;restore exit code
        mov     ah,4C                   ;terminate with exit code
        int     21


loaded  db      "New bell routine loaded.",cr,lf,"$"
removed db      "Bell routine unloaded.",cr,lf,"$"
not_rem db      "Can't unload.",cr,lf,"$"

code    ends
end     start
