page 66,132 ; This file was modified by Ben Diss (CIS 71270,341) to fix the ALT key ; bug and to provide the following inmprovements: ; ; 1. The hot key to increase or decrease intensity is CTRL-ALT plus the ; arrow key. ; 2. The replaced ISRs are now called at the beginning of all ISRs ; rather than JMPed to at the end. This eliminates some problems with a ; few clone systems. ; 3. Hot-key blanking has been added via SHIFT-SHIFT. ; 4. Hot-key disabling has been added via CTRL-ALT-D and re-enabling via ; CTRL-ALT-E. ; 5. Mouse support has been added, so that any use of the mouse will ; reset the time-out blanker. ; 6. The version number has been changed to 1.01 to relect the changes. ; ; Although I have used this program on my system since it was published, ; I cannot promise that it will work on yours, as I have not done any ; in-depth testing. This program is provided "as-is" without any ; warrenty of any kind. The original version was written for PC ; Magazine and is Copyright 1989, Ziff Communications Co. I hereby ; release all claims to rights for the modifications I have made. ; ; --- Ben ; ;------------------------------------------------------------------------- ; On 1-17-90, version 1.02: ; ; I rewrote the mouse routines so that all mouse drivers will be ;supported on all types of systems. The old method only worked for ;serial mouses. Also, when no mouse driver was loaded with certain ;programs that did use a mouse, the system would go into orbit. ; ; The method used now, polls the mouse driver twice a second for any ;change in the status. I did it this way to reduce the overhead of the ;polling routine. The side effect is that it is almost impossible to ;detect the press of a button using this method. ; ;---------------------------------------------------------------------------- ; On 1-18-90, version 1.02: ; ; Commented out the interval timer for the mouse polling routine. I ;found no difference with and without the delay using a number of ;benchmark programs. To retore them, simply delete the comments in from ;of those lines. ; ;---------------------------------------------------------------------------- ; On 1-20-90, version 1.03: ; ; WHOOPS! I forgot to bypass the INT 33 monitoring routine when there ;is no mouse driver installed. ; ;============================================================================ ; DIMMER.COM allows VGA users to interactively brighten or dim the screen. ; Syntax is: ; ; DIMMER [/U] [/V[+|-]] [/D mmm [+|-]xx] [[+|-]xx] ; ; where /U = Uninstall the program ; /D = Adjust intensity by xx after mmm minutes of inactivity ; xx = Numeric code from -63 to +63 representing relative ; amount by which to adjust the intensity ; /V = Reset delay timer on call to BIOS video interrupt. The ; default is V-. ; ; COMMAND LINE INTENSITY CONTROL ; ; DIMMER /D 1 -63 causes the screen to blank after 1 minute of ; inactivity. DIMMER /D 0 cancels any time delay previously entered. ; DIMMER -20 causes the screen to immediately dim 20 intensity levels. ; DIMMER 0 restores the screen intensity to what it was when DIMMER ; was installed. In all cases, DIMMER becomes RAM-resident so that ; intensity levels can also be adjusted interactively. ; DIMMER /D 1 -63 /V causes the screen to blank after 1 minute of ; inactivity. If a program calls any BIOS video routines, the ; screen is reset to its original brightness. ; ; INTERACTIVE INTENSITY CONTROL ; ; With DIMMER installed, Ctrl-Alt-UpArrow increases the display intensity ; by 1 level, Ctrl-Alt-DnArrow decreases the intensity by 1 level, and ; Ctrl-Alt-Home restores the screen intensity to what it was when DIMMER ; was installed. ;============================================================================ code segment assume cs:code org 2Ch env_segment dw ? ;Address of environment block org 80h command_tail dw ? ;Address of command tail org 100h main: jmp initialize ;Go to initialization code program db "Dimmer 1.03 " copyright db "(c) 1989 Ziff Communications Co.",13,10 authors db "PC Magazine ",254," Doug Boling and Jeff Prosise" db "$",1Ah dimmer_val db 0 ;Relative dimmer value delaydimval db 0 ;Delayed dimmer value wait_time dw -1 ;Delay until screen blank dim_counter dw -1 ;Number of minutes to delay second_cnt dw 1092 ;Timer ticks per minute restorebyvid db 0 ;1 = delay reset by video call vid_function dw 0 ;Saved video function int08h dd ? ;Int 8 vector (Timer) int09h dd ? ;Int 9 vector (Keyboard) int10h dd ? ;Int 10 vector (Video) INT33H dd ? ;Int 33 vector (Mouse) MOUSE_INST db ? ;0 if no mouse , -1 if present MOUSE_BUZY DB 0 ;0=not buzy, -1=buzy ;============================================================================ ; RESET_DELAY reset the delay counter ;============================================================================ RSHIFT = 000000001B ; Right Shift Key is Depressed LSHIFT = 000000010B ; Left Shift Key is Depressed CTRL = 000000100B ; Ctrl Key is Depressed ALT = 000001000B ; Alt Key is Depressed KEYS_UP DB 1 ;0=keys not up since blank SAVE_WAIT DW ? ;saves the wait_time reset_delay proc near CMP CS:[KEYS_UP],1 ;keys released since last JNE done_reset ; forced blank? mov cs:[second_cnt],1092 ;Reset delay counters mov ax,cs:[wait_time] xchg cs:[dim_counter],ax or ax,ax ;If counter was 0, reset the jne done_reset ; screen intensity mov ah,cs:[dimmer_val] call adj_palette_2 done_reset: ret reset_delay endp ;============================================================================ ; MOUSEINT monitors the mouse driver for activity ;============================================================================ EVEN ; word align to assist prefetch que MOUSEINT PROC NEAR MOV MOUSE_BUZY,-1 ; mouse driver is now buzy PUSHF ; push flags CALL INT33H ; call the driver MOV MOUSE_BUZY,0 ; mouse is now free IRET ; return MOUSEINT ENDP ;============================================================================ ; CHECK_MOUSE polls the mouse driver to check for movement ;============================================================================ MOUSE_BX DW ? MOUSE_CX DW ? MOUSE_DX DW ? EVEN ; word align to assist prefetch que CHECK_MOUSE PROC NEAR PUSH BX ; save registers PUSH CX PUSH DX MOV AX,3 ; Get mouse position and status PUSHF ; push the flags and CALL INT33H ; call the mouse driver CMP BX,MOUSE_BX ; if button status has changed JNE MOUSE_MOVED ; then reset the delay CMP CX,MOUSE_CX ; if the horiz position has changed JNE MOUSE_MOVED ; then reset the delay CMP DX,MOUSE_DX ; if the vert position has changed JNE MOUSE_MOVED ; then reset the delay JMP SHORT SAVE_MOUSE ; else just save the status MOUSE_MOVED: CALL RESET_DELAY ; reset the delay counter and restore ; the screen if necessary SAVE_MOUSE: MOV MOUSE_BX,BX ; save the mouse driver status MOV MOUSE_CX,CX MOV MOUSE_DX,DX POP DX ; restore the registers POP CX POP BX RET CHECK_MOUSE ENDP ;============================================================================ ; TIMERINT services the BIOS timer interrupt. ;============================================================================ ;COUNTER DB 9 ; mouse polling interval counter EVEN ; word align to assist prefetch que timerint proc far pushf ;Push flags call int08h ;Call BIOS timer routine sti ;Enable interrupts push ax ;Save AX CMP MOUSE_INST,-1 ; if mouse not installed JNE TIMER_1 ; then skip mouse check ; ; Check the mouse driver only once per second. This saves CPU time, but ; also makes detecting a button press very unlikely. ; ; DEC COUNTER ; decrement the interval timer ; JNZ TIMER_1 ; if not zero, then skip mouse check ; MOV COUNTER,9 ; reset the interval timer CMP MOUSE_BUZY,-1 ; if the mouse driver is buzy JE TIMER_1 ; then skip the mouse check CALL CHECK_MOUSE ; else check for mouse movement TIMER_1: mov ax,cs:[dim_counter] ;Get delay counter cmp ax,0FFFFh ;See if timer enabled je timer_exit ;Exit if not enabled or ax,ax ;Exit if timer at 0 to je timer_exit ; prevent rollover. dec cs:[second_cnt] ;Decrement seconds and exit jnz timer_exit ; if not zero mov word ptr cs:[second_cnt],1092 dec ax ;Decrement minute counter mov cs:[dim_counter],ax ;Update delay counter or ax,ax ;Exit if timer hasn't jne timer_exit ; reached zero mov ah,cs:[delaydimval] ;Get dimmer value call adj_palette_2 ;Modify color registers timer_exit: pop ax ;Restore AX and exit iret timerint endp ;============================================================================ ; KBINT services the keyboard interrupt. ;============================================================================ EVEN ; word align to assist prefetch que kbint proc far PUSHF CALL INT09H ;BIOS keyboard handler sti ;Enable interrupts push ax ;Save AX call reset_delay ; reset the delay counter MOV AH,2 ;Get keyboard shift status INT 16H and al,0Fh ;Mask upper 4 bits cmp al,ALT+CTRL ;Check for Alt key je alt_found ;Continue if Alt is pressed CMP AL,LSHIFT+RSHIFT ;Check for our hot-key JNE kbint0a MOV AH,CS:[DELAYDIMVAL] ;else get dimmer value CALL ADJ_PALETTE_2 ;Modify color registers MOV CS:[DIM_COUNTER],0 ;Set counter dimmed screen MOV CS:[KEYS_UP],0 ;Set key_up to 'not yet' JMP SHORT kbint_done kbint0a: CMP AL,0 JNE KBINT_DONE MOV CS:[KEYS_UP],1 kbint_done: POP AX IRET alt_found: in al,60h CMP AL,20H ;Check for 'D' to disable JNE kbint0b MOV AX,CS:[WAIT_TIME] MOV CS:[SAVE_WAIT],AX ;Save the wait_time MOV CS:[DIM_COUNTER],0FFFFH ;Disable dim_counter MOV CS:[WAIT_TIME],0FFFFH ;DIsable wait_time MOV AX,0E07H INT 10H JMP SHORT kbint4 kbint0b: CMP AL,12H ;Check for 'E' to enable JNE kbint0c MOV AX,CS:[SAVE_WAIT] MOV CS:[WAIT_TIME],AX MOV CS:[DIM_COUNTER],AX MOV CS:[SECOND_CNT],1092 ;Reset delay counters MOV AX,0E07H INT 10H MOV AX,0E07H INT 10H JMP SHORT kbint4 kbint0c: cmp al,72 ;Check for UpArrow jne kbint1 cmp cs:[dimmer_val],63 ;Increment color registers jge kbint3 ; by 1 if dimmer value inc cs:[dimmer_val] ; isn't maxed out jmp short kbint3 kbint1: cmp al,80 ;Check for DnArrow jne kbint2 cmp cs:[dimmer_val],-63 ;Decrement color registers jle kbint3 ; by 1 if dimmer value dec cs:[dimmer_val] ; isn't zeroed out jmp short kbint3 kbint2: cmp al,71 ;Reset color registers if jne kbint_done ; Alt-Home was pressed mov cs:[dimmer_val],0 kbint3: mov ah,cs:[dimmer_val] ;Get dimmer value call adj_palette_2 ;Modify color registers kbint4: MOV AH,1 INT 16H JZ KBINT_EXIT MOV AH,0 INT 16H JMP SHORT kbint4 KBINT_EXIT: pop ax ;Restore AX and exit iret kbint endp ;============================================================================ ; VIDEOINT services the BIOS video interrupt. ;============================================================================ EVEN ; word align to assist prefetch que videoint proc far mov cs:[vid_function],ax ;Save function number pushf ;Push flags call int10h ;Call video BIOS routine sti ;Enable interrupts push ax ;Save AX cmp cs:[restorebyvid],0 ;If video checking enabled, je video_1 ; check delay counter. cmp word ptr cs:[dim_counter],0 jne video_1 ;Restore color register mov ah,cs:[dimmer_val] ; values if timed delay call adj_palette_2 ; has dimmed the screen mov cs:[second_cnt],1092 ;Reset delay counters mov ax,cs:[wait_time] mov cs:[dim_counter],ax video_1: mov ax,cs:[vid_function] ;See what function was called or ah,ah ;Check for mode change je refresh_palette cmp ah,11h ;Check for mode reset je refresh_palette cmp ax,1010h ;Check for changes to the je refresh_buffer ; VGA color registers cmp ax,1012h ; made thru the video je refresh_buffer ; BIOS cmp ax,101Bh jne video_exit refresh_buffer: call get_palette ;Reload register array jmp short video_exit refresh_palette: mov ah,cs:[dimmer_val] ;Get dimmer adjust value call adj_palette_2 ;Modify palette video_exit: pop ax ;Restore AX and exit iret videoint endp ;---------------------------------------------------------------------------- ; ADJ_PALETTE_1 adjusts the VGA color registers to their original values ; plus the current dimmer value. ; Entry: AH - Dimmer value ; DS - Segment where color register values are stored ;---------------------------------------------------------------------------- adj_palette_1 proc near cld ;Clear direction flag push cx ;Save registers push dx push si mov si,offset end_res ;Point SI to buffer ; containing original values mov dx,03C8h ;Write address register xor al,al ;Set beginning address cli ;Disable interrupts out dx,al mov cx,256 * 3 ;256 color registers mov dx,03C9h ;Write data register adj_loop1: lodsb ;Get color value call mod64_add ;Add dimmer value out dx,al ;Write data to color register loop adj_loop1 ;Loop until done sti ;Enable interrupts pop si ;Restore registers and exit pop dx pop cx ret adj_palette_1 endp ;---------------------------------------------------------------------------- ; ADJ_PALETTE_2 adjusts the VGA color registers to their original values ; plus the current dimmer value. ; Entry: AH - Dimmer value ;---------------------------------------------------------------------------- adj_palette_2 proc near push ds ;Save DS push cs ;Point DS to code segment pop ds call adj_palette_1 ;Modify color registers pop ds ;Restore DS and exit ret adj_palette_2 endp ;---------------------------------------------------------------------------- ; MOD64_ADD adds AH to AL using modulo 64 math. ;---------------------------------------------------------------------------- mod64_add proc near or al,al ;If 0, don't brighten je mod2 add al,ah cmp al,0 ;See if underflow jg mod1 mov al,0 ;If so, set at minimum jmp short mod2 mod1: cmp al,63 ;See if overflow jbe mod2 mov al,63 ;If so, set at maximum mod2: ret mod64_add endp ;---------------------------------------------------------------------------- ; GET_PALETTE buffers the current values of the VGA color registers. ;---------------------------------------------------------------------------- get_palette proc near cld ;Clear direction flag push ax ;Save registers push cx push dx push di push es mov cx,cs ;Point ES to the code segment mov es,cx mov di,offset end_res ;Point DI to save buffer mov dx,03C7h ;Read address register xor al,al ;Begin with register 0 cli ;Disable interrupts out dx,al mov cx,256 * 3 ;256 color registers mov dx,03C9h ;Read data register getp_loop1: in al,dx ;Get color register value and al,3Fh ;Mask off the upper 2 bits stosb ;Store it loop getp_loop1 ;Loop until done sti ;Enable interrupts pop es ;Restore registers and exit pop di pop dx pop cx pop ax ret get_palette endp ;---------------------------------------------------------------------------- ; FINAL_INSTALL is the last of the resident code. ;---------------------------------------------------------------------------- final_install: assume ds:code call get_palette ;Get color register values mov ah,dimmer_val ;Adjust color registers and call adj_palette_2 ; terminate mov dx,(offset end_res-offset code+768+15) SHR 4 mov ax,3100h int 21h end_res = $ ;End of resident code ;============================================================================ ; Start of non-resident section. ;============================================================================ alrdy_installed db 0 ;Installed flag other_seg dw 0 ;Segment of installed code change_flag db 0 ;Set if dimmer or delay ; value is modified infomsg1 db "Program uninstalled$" errmsg1 db "Program not installed$" errmsg2 db "Syntax: DIMMER [/U] [/V[+|-]] [/D mmm [+|-]xx]" db " [[+|-]xx]$" errmsg3 db "Can",39,"t uninstall$" errmsg4 db "VGA required$" errmsg5 db "Intensity value must be between -63 and +63$" errmsg6 db "Invalid delay value$" errmsg7 db "Program already installed$" errmsg8 db "Invalid intensity value$" initialize proc near assume cs:code,ds:code ; ;See if a copy of DIMMER is already resident in memory. ; cld ;Clear direction flag mov word ptr [main],0 ;Initialize fingerprint xor bx,bx ;Zero BX for start mov ax,cs ;Keep CS value in AX find_copy: inc bx ;Increment search segment mov es,bx cmp ax,bx ;Not installed if current je find_copy1 ; segment is found mov si,offset main ;Search this segment for ASCII mov di,si ; fingerprint. mov cx,16 repe cmpsb jne find_copy ;Loop back if not found inc alrdy_installed ;Set installed flag find_copy1: mov other_seg,es ;Save segment value ; ;Check to see if a mouse is present ; MOV AX,0 ; check for mouse driver INT 33H MOV MOUSE_INST,AH ;0=no mouse, -1=mouse installed ; ;Verify that a VGA is installed. ; mov ax,1A00h ;BIOS read display function int 10h mov dx,offset errmsg4 cmp al,1Ah ;See if VGA present jne disp_error ;Exit on error if no VGA ; ;Parse the command line for switches. ; mov si,offset command_tail+1 ;Point SI to command parse_line_loop: ; tail in PSP lodsb ;Scan command line for / or a cmp al,32 ; number. Continue scanning je parse_line_loop ; until a carriage return is cmp al,13 ; found. je parse_line_end cmp al,"/" ;Is this a / character? jne check_numeric ;No, then check for numeric lodsb ;Get next character or al,20h ;Convert to lower case cmp al,"u" ;Check for uninstall switch je uninstall_found cmp al,"d" ;Check for delay switch je delay_found cmp al,"v" ;Check for reset delay by je vidflag_found ; video call switch. parse_line_error: mov dx,offset errmsg2 ;Syntax error jmp short disp_error ;Display message and exit ; ;Read the dimmer value from the command line if entry is numeric. ; check_numeric: cmp al,"-" ;Convert ASCII number into je numeric_start ; binary. Check for leading cmp al,"+" ; sign. je numeric_start cmp al,"0" jb parse_line_error cmp al,"9" ja parse_line_error dec si numeric_start: or change_flag,1 ;Set bit 0 in change flag call setdim ;Read and set dimmer value jmp short chk_err_and_loop ;Check for error return ; ;Read the time delay and dimmer values from the command line. ; vidflag_found: call setvidflag ;Modify the state of video flg jmp short chk_err_and_loop ;Check for error return delay_found: or change_flag,2 ;Set bit 1 in change flag call setdelay ;Read and set delay value chk_err_and_loop: jc disp_error jmp short parse_line_loop ; ;Uninstall the program from memory. ; uninstall_found: mov dx,offset errmsg1 ;Make sure program is cmp alrdy_installed,0 ; installed and signal je disp_error ; error if it is not call remove ;Remove program from memory mov dx,offset errmsg3 jc disp_error ;Error if can't remove mov dx,offset infomsg1 ;Acknowledge if removed call print_string exit: mov ax,4C00h ;Exit with RC = 0 int 21h ; ;Process new dimmer and/or delay values now if DIMMER is already resident. ; parse_line_end: cmp alrdy_installed,0 ;Program already installed? je install ;No, then install it cmp change_flag,0 ;Changes to resident copy? jne check_dimmer_change ;Yes, then process them mov dx,offset errmsg7 disp_error: call print_string ;No, then display error mov ax,4C01h ; message and exit int 21h ; with RC = 1 check_dimmer_change: test change_flag,1 ;Adjust color registers if jz check_delay_change ; dimmer value was changed push ds mov ds,other_seg ;Point DS to installed assume ds:nothing ; segment mov ah,ds:[dimmer_val] call adj_palette_1 pop ds assume ds:code jmp exit ;Terminate check_delay_change: test change_flag,2 ;Exit now if delay value jnz exit ; was modified ; ;Install a copy of DIMMER. ; install: mov ax,3508h ;Hook into interrupt 8 int 21h mov word ptr int08h,bx mov word ptr int08h[2],es mov ax,2508h mov dx,offset timerint int 21h mov ax,3509h ;Hook into interrupt 9 int 21h mov word ptr int09h,bx mov word ptr int09h[2],es mov ax,2509h mov dx,offset kbint int 21h mov ax,3510h ;Hook into interrupt 10h int 21h mov word ptr int10h,bx mov word ptr int10h[2],es mov ax,2510h mov dx,offset videoint int 21h CMP MOUSE_INST,-1 ; if mouse not installed JNE INIT_1 ; then skip mouse install mov ax,3533h ;Hook into interrupt 33h int 21h mov word ptr int33h,bx mov word ptr int33h[2],es mov ax,2533h mov dx,offset MOUSEINT int 21h INIT_1: mov dx,offset program ;Display copyright notice call print_string ; and jump to final jmp final_install ; install code initialize endp ;----------------------------------------------------------------------------- ; PRINT_STRING displays a DOS "$"-delimited text string with leading and ; trailing CRLFs. ; Entry: DS:DX - String address ;----------------------------------------------------------------------------- crlf db 13,10,"$" print_string proc near push dx ;Save entry-level value of DX mov ah,9 ;Print leading CRLF mov dx,offset crlf int 21h mov ah,9 ;Print text string pop dx int 21h mov ah,9 ;Print trailing CRLF mov dx,offset crlf int 21h ret ;Exit to caller print_string endp ;----------------------------------------------------------------------------- ; SETVIDFLAG modifies the video reset flag. ; Entry: DS:SI - Address of optional sign value. ;----------------------------------------------------------------------------- setvidflag proc near mov al,1 ;Assume video flag enable cmp byte ptr [si],"-" ;Check for video flag disable jne setvidflag_1 dec al setvidflag_1: mov es,other_seg ;Point ES to installed seg mov es:[restorebyvid],al ;Set/Reset video flag clc ret setvidflag endp ;----------------------------------------------------------------------------- ; SETDIM sets the dimmer value. ; Entry: DS:SI - Address of first digit ; Exit: CF set on error (DX points to error message text) ;----------------------------------------------------------------------------- setdim proc near mov di,si ;Copy command line pointer call asc2bin ;Convert ASCII to binary mov dx,offset errmsg8 ;Exit on error jc setdim_error cmp byte ptr [di-1],"-" ;Negate value if negative jne setdim_1 neg ax setdim_1: mov dx,offset errmsg5 cmp ax,63 ;Error if value is less than jg setdim_error ; -63 or greater than +63 cmp ax,-63 jl setdim_error mov es,other_seg ;Point ES to installed seg mov es:[dimmer_val],al ;Record dimmer value clc setdim_exit: ret setdim_error: stc jmp short setdim_exit setdim endp ;----------------------------------------------------------------------------- ; SETDELAY sets the delay counter. ; Entry: DS:SI - Address of first character past /D switch ; Exit: CF set on error (DX points to error message text) ;----------------------------------------------------------------------------- setdelay proc near setdelay_l1: lodsb cmp al,32 ;Skip spaces je setdelay_l1 mov dx,offset errmsg2 ;Error if no delay value cmp al,13 ; was specified je setdelay_error dec si ;Back up to first character call asc2bin ;Convert ASCII to binary mov dx,offset errmsg6 ;Exit on error jc setdelay_error mov bx,0FFFFh ;If delay value 0, disable or ax,ax ; delay counter with FFFFh je delay_2 mov bx,ax ;Save delay value setdelay_l2: lodsb ;Get next character cmp al,32 ;Skip spaces je setdelay_l2 mov dx,offset errmsg2 ;Error if no delay value cmp al,13 ; was specified je setdelay_error mov di,si ;Copy pointer to number cmp al,"-" ;Check for leading sign je setdelay_1 ; identifier cmp al,"+" je setdelay_1 dec si ;Back up to first character setdelay_1: push bx ;Save delay value call asc2bin ;ASCII --> binary pop bx ;Retrieve delay value mov dx,offset errmsg8 ;Exit on error jc setdelay_error cmp byte ptr [di-1],"-" ;Negate value if negative jne delay_1 neg ax delay_1: mov dx,offset errmsg5 ;Check to see if the value cmp ax,63 ; is out of range jg setdelay_error cmp ax,-63 jl setdelay_error delay_2: mov es,other_seg ;Load new delay and dimmer mov es:[delaydimval],al ; values into the mov es:[wait_time],bx ; program MOV ES:[SAVE_WAIT],BX mov es:[dim_counter],bx mov es:[second_cnt],1092 clc setdelay_exit: ret setdelay_error: stc jmp short setdelay_exit setdelay endp ;----------------------------------------------------------------------------- ; REMOVE removes a resident copy of the program from memory. ; Exit: CF set on error ;----------------------------------------------------------------------------- remove_error: stc jmp remove_exit1 remove proc near cmp alrdy_installed,0 ;See if installed je remove_error ;No, error mov ax,3508h ;Get timer vector int 21h mov ax,es ;Check to make sure timer cmp ax,other_seg ; vector not modified jne remove_error mov ax,3509h ;Get keyboard vector int 21h mov ax,es ;Check to make sure keyboard cmp ax,other_seg ; vector not modified jne remove_error mov ax,3510h ;Get video vector int 21h mov ax,es ;Check to make sure video cmp ax,other_seg ; vector not modified jne remove_error CMP MOUSE_INST,-1 ; if mouse not installed JNE REMOVE_1 ; then skip mouse segment check mov ax,3533h ;Get mouse vector int 21h mov ax,es ;Check to make sure video cmp ax,other_seg ; vector not modified jne remove_error REMOVE_1: push ds lds dx,es:[int08h] ;Get old interrupt 8 vector mov ax,2508h ;Set interrupt int 21h lds dx,es:[int09h] ;Get old interrupt 9 vector mov ax,2509h ;Set interrupt int 21h lds dx,es:[int10h] ;Get old interrupt 10 vector mov ax,2510h ;Set interrupt int 21h CMP MOUSE_INST,-1 ; if mouse not installed JNE REMOVE_2 ; then skip mouse remove lds dx,es:[int33h] ;Get old interrupt 33 vector mov ax,2533h ;Set interrupt int 21h REMOVE_2: pop ds mov cx,es:[env_segment] mov ah,49h ;Free PSP block int 21h mov es,cx ;Free environment block mov ah,49h int 21h remove_exit: clc remove_exit1: ret remove endp ;----------------------------------------------------------------------------- ; ASC2BIN Converts an ASCII number pointed to by SI to a hex value. ; Entry: SI = pointer to ASCII number ; Exit: AX = binary value ; CF set on error ;----------------------------------------------------------------------------- ten dw 10 asc2bin proc near xor ax,ax ;Clear accumulator xor bx,bx ;Clear BX asc_loop: mov bl,[si] ;Get ASCII character cmp bl,13 ;Done if carriage return or je asc_exit ; space encountered cmp bl,32 je asc_exit inc si sub bl,"0" ;ASCII --> binary jb asc_error ;Error if binary value is cmp bl,9 ; less than 0 or greater ja asc_error ; than 9 mul ten ;Multiply accumulator by 10 add ax,bx ;Add last digit to sum jmp short asc_loop ;Loop until done asc_exit: clc asc_exit1: ret asc_error: stc jmp short asc_exit1 asc2bin endp code ends end main