home *** CD-ROM | disk | FTP | other *** search
- TITLE BUFFY.ASM
- PAGE 60,132
- ;
- ;
- ;
- ;
- ;
- ;
- ;
- ;
- ;
- ;
- ;
- ;
- ;----------------------------------------------------------------------------
- PUBLIC initialize
- max_value = 36
-
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ;
- ; This data is used by both interupt service routines (ISR's)
- ;
- ;----------------------------------------------------------------------------
-
- BUFFY_DATA SEGMENT PARA PUBLIC 'DATA'
- db "Unique StringXYZ"
- psp_pointer dw (?)
- isr_2f_seg dw (?)
- int_2f_id db (?)
- error_code db (?)
- counter dw (?)
- screen_buffer dw (?)
- org_screen dw 80 * 25 dup (?)
- display_lines label word
-
- db " WW WW EEEEEEE LL CCCCCC OOOOO MMM MMM EEEEEEE "
- db " WW WW EE LL CC OO OO MM M M MM EE "
- db " WW W WW EEEE LL CC OO OO MM M MM EEEE "
- db " WW W W WW EE LL CC OO OO MM MM EE "
- db " WWW WWW EEEEEEE LLLLLLL CCCCCC OOOOO MM MM EEEEEEE "
- db " "
- db " TTTTTTTTT OOOOO "
- db " TT OO OO "
- db " TT OO OO "
- db " TT OO OO "
- db " TT OOOOO "
- db " "
- db " BBBBBB UU UU FFFFFFF FFFFFFF YY YY '' SSSSSS "
- db " BB BB UU UU FF FF YY YY '' SS S "
- db " BB BB UU UU FFFFF FFFFF YY SS "
- db " BB BB UU UU FF FF YY S SS "
- db " BBBBBB UUUUU FF FF YY SSSSSS "
- db " "
- db " WW WW OOOOO RRRRRR LL DDDDDD "
- db " WW WW OO OO RR RR LL DD DD "
- db " WW W WW OO OO RRRRRR LL DD DD "
- db " WW W W WW OO OO RR RR LL DD DD "
- db " WWW WWW OOOOO RR RR LLLLLLL DDDDDD "
- db " "
- db " Press any key to return to reality "
-
- screen_length = $ - display_lines
-
-
- BUFFY_DATA ENDS
-
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
-
- MULTIPLEX_RTN SEGMENT PARA PUBLIC 'CODE'
- ASSUME CS:MULTIPLEX_RTN, DS:NOTHING, ES:NOTHING
- int_2f_rtn PROC FAR
- push bx
- push ds
-
- ;----------------------------------------------------------------------------
- ; Check to see if the multiplex id is ours.
- ; If it is, set ES to point to our copy of BUFFY_DATA, AL=FF and return.
- ; If not, restore registers and call next interupt vector in line.
- ;----------------------------------------------------------------------------
- mov bx,BUFFY_DATA
- mov ds,bx
- ASSUME DS:BUFFY_DATA, ES:NOTHING
- cmp ah,int_2f_id
- jne exit_multiplex_rtn
-
- mov es,bx
- pop ds
- pop bx
- mov al,0FFh
- iret
-
- exit_multiplex_rtn:
- pop ds
- pop bx
- ASSUME DS:NOTHING, ES:NOTHING
- jmp DWORD PTR cs:next_int_2f
-
- next_int_2f dd (?)
-
- int_2f_rtn ENDP
- MULTIPLEX_RTN ENDS
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
-
- KEYB_INTR_RTN SEGMENT PARA PUBLIC 'CODE'
- ASSUME CS:KEYB_INTR_RTN, DS:NOTHING, ES:NOTHING
- keyb_isr PROC FAR
- push ax
- push ds
- pushf
-
- mov ax,BUFFY_DATA
- mov ds,ax
- ASSUME DS:BUFFY_DATA, ES:NOTHING
-
- cmp counter,max_value
- jng exit_keyb_rtn
- call NEAR PTR restore_screen
-
- exit_keyb_rtn:
- mov counter,0
- popf
- pop ds
- pop ax
- ASSUME DS:NOTHING, ES:NOTHING
-
- jmp DWORD PTR cs:org_keyb_vector
-
- keyb_isr ENDP
- ;----------------------------------------------------------------------------
- ; Copy the screen into the screen buffer.
- ;----------------------------------------------------------------------------
-
- restore_screen PROC NEAR
- ASSUME DS:BUFFY_DATA
- push cx
- push si
- push di
- push es
-
- ;----------------------------------------------------------------------------
- ; Set the destination pointer (ES:DI) to B000:screen_buffer
- ;----------------------------------------------------------------------------
- mov di,0B000h
- mov es,di
- mov di,screen_buffer
-
- ;----------------------------------------------------------------------------
- ; Set the source pointer (DS:SI) to BUFFY_DATA:org_screen
- ;----------------------------------------------------------------------------
- mov si,OFFSET org_screen
-
- ;----------------------------------------------------------------------------
- ; Copy the original screen back onto the display.
- ;----------------------------------------------------------------------------
- mov cx,80 * 25
- cld
- rep movsw
-
- pop es
- pop di
- pop si
- pop cx
-
- ret
-
- restore_screen ENDP
-
- org_keyb_vector dd (?)
- KEYB_INTR_RTN ENDS
-
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
-
- CLK_INTR_RTN SEGMENT PARA PUBLIC 'CODE'
- ASSUME CS:CLK_INTR_RTN, DS:NOTHING, ES:NOTHING
- clk_isr PROC FAR
- push ax
- push ds
- pushf
-
- mov ax,BUFFY_DATA
- mov ds,ax
- ASSUME DS:BUFFY_DATA, ES:NOTHING
-
- ;----------------------------------------------------------------------------
- ; Check the counter value.
- ; If the counter > max_value the screen has already been swapped.
- ; If the counter = max_value then try to swap the screen.
- ; If the counter < max_value then increment the counter.
- ;----------------------------------------------------------------------------
- cmp counter,max_value
- je attempt_swap
- jl increment_and_exit ; Still counting up to screen swap.
- jg no_action ; Screen has already been swapped.
-
- increment_and_exit:
- inc counter
-
- no_action:
- popf
- pop ds
- pop ax
- ASSUME DS:NOTHING, ES:NOTHING
-
- jmp DWORD PTR cs:org_clk_vector
-
- ;----------------------------------------------------------------------------
- ; At this point the counter = max_value.
- ; Check the video mode to make sure that it is one of 2,3 or 7.
- ; If it is then save the screen buffer start position and
- ; swap the screen and increment the counter variable.
- ;----------------------------------------------------------------------------
- ASSUME DS:BUFFY_DATA, ES:NOTHING
- attempt_swap:
- call NEAR PTR get_current_video_mode ; Returns BIOS video mode in AL
- mov screen_buffer,0000
- cmp al,7
- je swap_screen ; can swap in mode 7
- mov screen_buffer,8000h
- cmp al,3
- je swap_screen ; can swap in mode 3
- cmp al,2
- je swap_screen ; can swap in mode 2
- jmp SHORT no_action
-
- swap_screen:
- call NEAR PTR screen_save
- call NEAR PTR screen_clear
- call NEAR PTR buffy_screen
-
- jmp SHORT increment_and_exit
-
- clk_isr ENDP
-
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ;
- ; Return the BIOS video mode in the AL register.
- ;
- ;----------------------------------------------------------------------------
-
- get_current_video_mode PROC NEAR
- ASSUME DS:NOTHING, ES:NOTHING
-
- push ds
- mov ax,40h
- mov ds,ax
- mov al,ds:[49h] ; get display mode variable.
- pop ds
-
- ret
-
- get_current_video_mode ENDP
-
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ; Copy the screen into the screen buffer.
- ;----------------------------------------------------------------------------
- screen_save PROC NEAR
- ASSUME DS:NOTHING, ES:NOTHING
- push ax
- push cx
- push di
- push si
- push ds
- push es
- pushf
-
- ;----------------------------------------------------------------------------
- ; Set up DS to point to B000 and ES to point to BUFFY_DATA
- ;----------------------------------------------------------------------------
- mov ax,0B000h
- mov ds,ax
- mov ax,BUFFY_DATA
- mov es,ax
- ASSUME DS:NOTHING, ES:BUFFY_DATA
-
- ;----------------------------------------------------------------------------
- ; Set up SI to point to start of screen buffer, DI to <org_screen>
- ;----------------------------------------------------------------------------
- mov si,es:screen_buffer
- mov di,OFFSET BUFFY_DATA:org_screen
-
- ;----------------------------------------------------------------------------
- ; Copy display screen (DS:SI) to screen save buffer (BUFFY_DATA:org_screen)
- ;----------------------------------------------------------------------------
- mov cx,80 * 25
- cld
- rep movsw
-
- popf
- pop es
- pop ds
- pop si
- pop di
- pop cx
- pop ax
-
- ret
-
- screen_save ENDP
-
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ;
- ; Clear the screen. Use attribute 7 (normal) and character 'space'.
- ;
- ;----------------------------------------------------------------------------
-
- screen_clear PROC NEAR
- ASSUME DS:NOTHING, ES:NOTHING
-
- push ax
- push cx
- push di
- push es
- pushf
-
- mov ax,BUFFY_DATA
- mov es,ax
- ASSUME DS:NOTHING, ES:BUFFY_DATA
- mov di,es:screen_buffer
-
- mov ax,0B000h
- mov es,ax
- ASSUME DS:NOTHING, ES:NOTHING
- mov cx,80 * 25
- mov ax,720h
- cld
- rep stosw
-
- popf
- pop es
- pop di
- pop cx
- pop ax
-
- ret
-
- screen_clear ENDP
-
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
-
- buffy_screen PROC NEAR
- ASSUME DS:NOTHING, ES:NOTHING
-
- push ax
- push cx
- push di
- push si
- push ds
- push es
- pushf
-
- mov ax,BUFFY_DATA
- mov ds,ax
- ASSUME DS:BUFFY_DATA, ES:NOTHING
-
- mov di,screen_buffer ; Offset of screen buffer.
- mov si,OFFSET display_lines ; BX points to current display item
-
- mov ax,0B000h ; Segment of screen buffer.
- mov es,ax
-
- mov ah,07 ; This is the characters attribute
- mov cx,screen_length
- next_character:
- lodsb
- stosw
- loop next_character
-
- exit_buffy_screen:
- popf
- pop es
- pop ds
- pop si
- pop di
- pop cx
- pop ax
-
- ret
-
- buffy_screen ENDP
-
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ; Data area in same segment.
- ;----------------------------------------------------------------------------
-
- org_clk_vector dd (?)
- CLK_INTR_RTN ENDS
-
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
-
- BUFFY_CODE SEGMENT PARA PUBLIC 'CODE'
-
- ASSUME CS:BUFFY_CODE, DS:NOTHING, ES:NOTHING
-
- initialize PROC FAR
-
- mov ax,BUFFY_DATA
- mov ds,ax
- ASSUME DS:BUFFY_DATA, ES:NOTHING
-
- ;----------------------------------------------------------------------------
- ; Save the PSP in the BUFFY_DATA segment for possible use later.
- ;----------------------------------------------------------------------------
- mov psp_pointer,es ; Save the segment of the PSP.
- mov counter,0 ; Set the counter to 0
- mov error_code,0 ; Set the error code to 0
-
- ;----------------------------------------------------------------------------
- ; Get the original multiplex interupt vector and save it in a memory
- ; variable in the MULTIPLEX_RTN segment.
- ;----------------------------------------------------------------------------
-
- mov ah,35h ; Get the interupt 2Fhex vector
- mov al,2Fh ; returned in ES:BX
- int 21h
-
- mov ax,MULTIPLEX_RTN ; Store original vector
- mov ds,ax
- ASSUME DS:MULTIPLEX_RTN, ES:NOTHING
-
- mov WORD PTR next_int_2f[2], es
- mov WORD PTR next_int_2f[0], bx
-
- ;----------------------------------------------------------------------------
- ; Get the original keyboard interupt vector and save it in a memory
- ; variable in the KEYB_INTR_RTN segment.
- ;----------------------------------------------------------------------------
-
- mov ah,35h ; Get the interupt 9 vector
- mov al,09h ; returned in ES:BX
- int 21h
-
- mov ax,KEYB_INTR_RTN ; Store original vector
- mov ds,ax
- ASSUME DS:KEYB_INTR_RTN, ES:NOTHING
-
- mov WORD PTR org_keyb_vector[2], es
- mov WORD PTR org_keyb_vector[0], bx
-
- ;----------------------------------------------------------------------------
- ; Get the original clock (1Chex) interupt vector and save it in a memory
- ; variable in the CLK_INTR_RTN segment.
- ;----------------------------------------------------------------------------
- mov ah,35h ; Get the interupt 1Chex vector
- mov al,1Ch ; returned in ES:BX
- int 21h
-
- mov ax,CLK_INTR_RTN ; Store original vector
- mov ds,ax
- ASSUME DS:CLK_INTR_RTN, ES:NOTHING
-
- mov WORD PTR org_clk_vector[2], es
- mov WORD PTR org_clk_vector[0], bx
-
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ; call NEAR PTR debug_proc
-
-
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
-
- ;----------------------------------------------------------------------------
- ; Check to see if a copy is already installed.
- ; If a copy is already installed, check for a command line option to
- ; uninstall it "/U", otherwise print error message and exit.
- ; If no copy is currently running then install this copy.
- ;----------------------------------------------------------------------------
- mov ax,BUFFY_DATA
- mov ds,ax
- ASSUME DS:BUFFY_DATA, ES:NOTHING
-
- call NEAR PTR check_for_existing_copy
- jnc install_buffy
-
- call NEAR PTR check_for_uninstall
- jnc @F
- push ds
- push cs
- pop ds
- mov dx,OFFSET CS:msg_already_installed
- mov ah,9
- int 21h
- pop ds
- jmp SHORT exit_with_error
-
- @@: call NEAR PTR uninstall
- mov error_code,0
- jmp SHORT exit_no_error
-
- ;----------------------------------------------------------------------------
- ; After uninstalling or issuing error message, exit without installing.
- ;----------------------------------------------------------------------------
- exit_with_error:
- mov error_code,1
-
- exit_no_error:
- mov ah,4Ch
- mov al,error_code
- int 21h
-
-
- install_buffy:
- call NEAR PTR set_int_2f_id
-
- ;----------------------------------------------------------------------------
- ; Set the keyboard interupt vector to the new routine
- ;----------------------------------------------------------------------------
- mov ax,KEYB_INTR_RTN
- mov ds,ax
- ASSUME DS:KEYB_INTR_RTN, ES:NOTHING
-
- mov dx,OFFSET KEYB_INTR_RTN:keyb_isr
- mov ah,25h ; Set the interupt 9 vector
- mov al,09h ; set to DS:DX
- int 21h
-
- ;----------------------------------------------------------------------------
- ; Set the clock interupt vector to the new routine
- ;----------------------------------------------------------------------------
- mov ax,CLK_INTR_RTN
- mov ds,ax
- ASSUME DS:CLK_INTR_RTN, ES:NOTHING
-
- mov dx,OFFSET CLK_INTR_RTN:clk_isr
- mov ah,25h ; Set the interupt 1Chex vector
- mov al,1Ch ; set to DS:DX
- int 21h
-
- ;----------------------------------------------------------------------------
- ; Set the multiplex interupt vector to the new routine
- ;----------------------------------------------------------------------------
- mov ax,MULTIPLEX_RTN
- mov ds,ax
- ASSUME DS:MULTIPLEX_RTN, ES:NOTHING
-
- mov dx,OFFSET MULTIPLEX_RTN:int_2f_rtn
- mov ah,25h ; Set the interupt 2Fhex vector
- mov al,2Fh ; set to DS:DX
- int 21h
-
- ;----------------------------------------------------------------------------
- ; Release environment block.
- ;----------------------------------------------------------------------------
- mov ax,BUFFY_DATA ; Make data segment addressable
- mov ds,ax
- ASSUME DS:BUFFY_DATA, ES:NOTHING
-
- mov ax,psp_pointer ; Load pointer to PSP into DS
- mov ds,ax
- ASSUME DS:NOTHING, ES:NOTHING
-
- mov es,ds:[2Ch] ; Get segment of Environment from PSP
-
- mov ah,49h ; Release segment of Environment.
- int 21h
-
- ;----------------------------------------------------------------------------
- ; Terminate and stay resident, leaving enough memory to hold the
- ; interupt service routines and the screen buffers.
- ;----------------------------------------------------------------------------
- mov ax,BUFFY_DATA
- mov ds,ax
- ASSUME DS:BUFFY_DATA
-
- mov dx,BUFFY_CODE
- sub dx,ax
- add dx,16
- mov ah,31h
- mov al,error_code
- int 21h
-
- initialize ENDP
-
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- debug_proc PROC NEAR
-
- push ax
- push ds
-
- mov ax,BUFFY_DATA
- mov ds,ax
- call NEAR PTR uninstall
-
- pop ds
- pop ax
- ret
-
- debug_proc ENDP
-
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
-
- check_for_existing_copy PROC NEAR
- ASSUME DS:BUFFY_DATA, ES:NOTHING
-
- push ax
- push cx
- push di
- push si
- push es
-
- mov ah,80h
-
- next_check:
- xor al,al
- int 2fh
-
- cmp al,0FFh
- je check_16_bytes
- or al,al
- je could_not_find
- failed_check:
- inc ah
- jnz next_check
- jmp SHORT could_not_find
-
- check_16_bytes:
- xor si,si
- xor di,di
- cld
- mov cx,16
- repe cmpsb
- jne failed_check
-
- mov isr_2f_seg,es
- stc
- jmp SHORT exit_check
-
- could_not_find:
- clc
-
- exit_check:
- pop es
- pop si
- pop di
- pop cx
- pop ax
- ret
-
- check_for_existing_copy ENDP
-
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
-
- check_for_uninstall PROC NEAR
- ASSUME DS:BUFFY_DATA, ES:NOTHING
- push ds
-
- mov ds,psp_pointer
- ASSUME DS:NOTHING, ES:NOTHING
-
- or BYTE PTR ds:[80h],0
- je error_exit_check_for_uninstall
-
- check_parameter_value:
- cmp BYTE PTR ds:[82h], '/'
- jne error_exit_check_for_uninstall
- cmp BYTE PTR ds:[83h], 'U'
- jne error_exit_check_for_uninstall
- clc
- jmp SHORT exit_check_for_uninstall
-
- error_exit_check_for_uninstall:
- stc
-
- exit_check_for_uninstall:
- pop ds
-
- ret
-
- check_for_uninstall ENDP
-
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
-
- uninstall PROC NEAR
-
- push ax
- push bx
- push dx
- push si
- push ds
- push es
-
- ;----------------------------------------------------------------------------
- ; Switch active PSP to the copy of BUFFY that was found.
- ; 1) Unlink all interupt vectors from found copy of BUFFY.
- ; 2) get current PSP address from DOS
- ; 3) get PSP from found copy of BUFFY
- ; 4) call DOS 'Set psp' with found copy
- ; 5) release memory starting at found copy of PSP
- ; 6) reset to current PSP
- ;----------------------------------------------------------------------------
-
- ;----------------------------------------------------------------------------
- ; Set DS to point to the found copy of BUFFY_DATA
- ; We can let the assembler think that we are still pointing to the current
- ; copy of BUFFY_DATA because the assembler just uses this for segment
- ; overrides and offset calculations (both of which will be the same).
- ;----------------------------------------------------------------------------
- mov ax,BUFFY_DATA
- mov ds,ax
- ASSUME DS:BUFFY_DATA, ES:NOTHING
-
- mov ax,isr_2f_seg
- mov es,ax
- ASSUME DS:NOTHING, ES:BUFFY_DATA
-
- ;----------------------------------------------------------------------------
- ; ES now points to found copy of BUFFY_DATA.
- ; Calculate the position of the original int 2F vector and reset the
- ; vector via DOS.
- ;----------------------------------------------------------------------------
- mov ax,MULTIPLEX_RTN
- sub ax,BUFFY_DATA
- mov bx,es
- add ax,bx
- mov ds,ax
- ASSUME DS:MULTIPLEX_RTN, ES:BUFFY_DATA
-
- ;----------------------------------------------------------------------------
- ; DS now points to the found copy of MULTIPLEX_RTN.
- ; ES points to the found copy of BUFFY_DATA,
- ; Save a copy of the segment address of the original int_2f_isr
- ; Get the current vector from DOS
- ; Compare the current vector with the address of found copy,
- ; If they are the same they can be unlinked
- ; otherwise they cannot be unlinked (chain would be cut)
- ;----------------------------------------------------------------------------
- mov si,es
-
- mov ah,35h ; Get vector to current int 2F handler
- mov al,2Fh
- int 21h ; Returns ES:BX
-
- mov ax,ds
- mov bx,es
- sub ax,bx ; Compare found segment with INT 2F segment
- jz @F
- jmp could_not_unlink
-
- @@: mov es,si ; Restore segment of BUFFY_DATA
- mov dx,WORD PTR next_int_2f[0]
- mov ds,WORD PTR next_int_2f[2]
- ASSUME DS:NOTHING, ES:BUFFY_DATA
-
- mov ah,25h ; Reset int 2F vector to previous vector
- mov al,2Fh
- int 21h
-
- ;----------------------------------------------------------------------------
- ; ES now points to found copy of BUFFY_DATA.
- ; Calculate the position of the original int 9 vector and reset the
- ; vector via DOS.
- ;----------------------------------------------------------------------------
- mov ax,KEYB_INTR_RTN
- sub ax,BUFFY_DATA
- mov bx,es
- add ax,bx
- mov ds,ax
- ASSUME DS:KEYB_INTR_RTN, ES:BUFFY_DATA
-
- ;----------------------------------------------------------------------------
- ; DS now points to the found copy of KEYB_INTR_RTN
- ; ES points to the found copy of BUFFY_DATA,
- ; Save a copy of the segment address of the original keyb_isr
- ; Get the current vector from DOS
- ; Compare the current vector with the address of found copy,
- ; If they are the same they can be unlinked
- ; otherwise they cannot be unlinked (chain would be cut)
- ;----------------------------------------------------------------------------
- mov si,es
-
- mov ah,35h ; Get vector to current int 9 handler
- mov al,9
- int 21h ; Returns ES:BX
-
- mov ax,ds
- mov bx,es
- sub ax,bx ; Compare found segment with int 9 segment
- jz @F
- jmp could_not_unlink
-
- @@: mov es,si ; Restore segment of BUFFY_DATA
- mov dx,WORD PTR org_keyb_vector[0]
- mov ds,WORD PTR org_keyb_vector[2]
- ASSUME DS:NOTHING, ES:BUFFY_DATA
-
- mov ah,25h ; Reset int 9 vector to previous vector
- mov al,9 ; Vector in DS:DX
- int 21h
-
- ;----------------------------------------------------------------------------
- ; ES now points to found copy of BUFFY_DATA.
- ; Calculate the position of the original int 1C vector and reset the
- ; vector via DOS.
- ;----------------------------------------------------------------------------
- mov ax,CLK_INTR_RTN
- sub ax,BUFFY_DATA
- mov bx,es
- add ax,bx
- mov ds,ax
- ASSUME DS:CLK_INTR_RTN, ES:BUFFY_DATA
-
- ;----------------------------------------------------------------------------
- ; DS now points to the found copy of CLK_INTR_RTN
- ; ES points to the found copy of BUFFY_DATA,
- ; Save a copy of the segment address of the original clk_isr
- ; Get the current vector from DOS
- ; Compare the current vector with the address of found copy,
- ; If they are the same they can be unlinked
- ; otherwise they cannot be unlinked (chain would be cut)
- ;----------------------------------------------------------------------------
- mov si,es
-
- mov ah,35h ; Get vector to current int 1C handler
- mov al,1Ch
- int 21h ; Returns ES:BX
-
- mov ax,ds
- mov bx,es
- sub ax,bx ; Compare found segment with int 1C segment
- jz @F
- jmp could_not_unlink
-
- @@: mov es,si ; Restore segment of BUFFY_DATA
- mov dx,WORD PTR org_clk_vector[0]
- mov ds,WORD PTR org_clk_vector[2]
- ASSUME DS:NOTHING, ES:BUFFY_DATA
-
- mov ah,25h ; Reset int 1C vector to previous vector
- mov al,1Ch ; Vector in DS:DX
- int 21h
-
- ;----------------------------------------------------------------------------
- ; The interupt service routines have now been unlinked.
- ; Now we get our PSP and save it.
- ; Get the found copies PSP and make it active.
- ;----------------------------------------------------------------------------
-
- mov ah,51h ; Get our PSP
- int 21h ; Returned in BX
-
- push bx ; Save this so we can reset later.
-
- mov bx,psp_pointer ; Set found PSP to be active
- mov ah,50h
- int 21h
-
- ;----------------------------------------------------------------------------
- ; Release the memory originally consumed by the found copy of BUFFY.
- ;----------------------------------------------------------------------------
- mov es,psp_pointer
- mov ah,49h
- int 21h
-
- jnc @F
- mov ax,cs
- mov ds,ax
- mov dx,OFFSET cs:msg_memory_failure
- int 21h
- add sp,2
- stc
- jmp SHORT exit_uninstall
-
- ;----------------------------------------------------------------------------
- ; Reset PSP back to current process.
- ;----------------------------------------------------------------------------
- @@: pop bx
- mov ah,50h
- int 21h
- jmp SHORT exit_uninstall
-
- could_not_unlink:
- mov ax,cs
- mov ds,ax
- mov dx,OFFSET cs:msg_interupt_taken
- int 21h
- stc
-
- exit_uninstall:
- pop es
- pop ds
- pop si
- pop dx
- pop bx
- pop ax
-
- ret
-
- uninstall ENDP
-
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
-
- set_int_2f_id PROC NEAR
- ASSUME DS:BUFFY_DATA, ES:NOTHING
-
- push ax
-
- mov ah,80h
- xor al,al
-
- set_check:
- int 2fh
- or al,al
- je set_2f_id
- inc ah
- jnz set_check
- stc
- jmp exit_set_2f_id
-
- set_2f_id:
- mov int_2f_id,ah
- clc
-
- exit_set_2f_id:
- pop ax
- ret
-
- set_int_2f_id ENDP
-
- msg_already_installed db 13,10,'TSR is already installed',13,10,'$'
- msg_interupt_taken db 13,10,'Could not uninstall',13,10,'$'
- msg_memory_failure db 13,10,'Memory deallocation failure - Reboot',13,10,'$'
- BUFFY_CODE ENDS
-
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
- ;----------------------------------------------------------------------------
-
- STACK SEGMENT STACK 'STACK'
-
- db 64 dup ('stack...')
-
- STACK ENDS
-
- END initialize
-
-