home *** CD-ROM | disk | FTP | other *** search
- page 60,132
- ; SNIPPER is a resident utility which allows cutting out a portion
- ; of the screen. The selected portion may be printed, written
- ; to disk or entered in the keyboard buffer. Activate SNIPPER by
- ; pressing ALT-W, then position the cursor in the upper left corner of
- ; the window using the arrow keys. Press CR to fix the first corner,
- ; then expand the window with arrow keys. Finally, type "P" to print,
- ; "F" for disk file, "G" to retrieve or CR for a help menu. Press ESC
- ; any time to exit SNIPPER. When installing SNIPPER, use the optional
- ; parameters to expand it's internal buffer for displays (such as the
- ; EGA) containing more than the standard 25 rows and 80 columns.
- ; SNIPPER [rows,columns]
-
- ;------------------------------------;
- ; BIOS_SEG IS THE ROM-BIOS DATA AREA ;
- ;------------------------------------;
- BIOS_SEG SEGMENT AT 0040H
- ORG 004AH
- CRT_COLS DB ? ;CURRENT NUMBER OF COLUMNS
- ORG 0050H
- CURSOR_POSN DW 8 DUP(?) ;CURRENT CURSOR LOCATION
- ORG 0062H
- ACTIVE_PAGE DB ? ;ACTIVE PAGE FOR CGA AND EGA
- ORG 0084H
- ROWS DB ? ;LAST ROW NUMBER FOR EGA
- BIOS_SEG ENDS
-
- CSEG SEGMENT
- ASSUME CS:CSEG,DS:NOTHING
- ORG 0100H ;BEGINNING FOR .COM PROGRAMS
- START: JMP INIT ;INITIALIZATION CODE IS AT END
-
- ;--------------------------------;
- ; DATA AREA USED BY THIS PROGRAM ;
- ;--------------------------------;
- HOTKEY EQU 11H ;SCAN CODE FOR "W" KEY
- SHIFT_MASK EQU 00001000B ;MASK FOR ALT KEY
- ;
- COPYRIGHT DB "SNIPPER 1.1 (c) 1987 Ziff Communications Co."
- DB 13,10,"Hotkey is ALT-W",13,10,"$",1AH
- PROGRAMMER DB "Tom Kihlken"
- INSTALLED_MSG DB "Already Installed",13,10,"$"
- BAD_DOS_MSG DB "Requires DOS 2.0+",13,10,"$"
- OLDINT09 DD ? ;OLD KEYBOARD BREAK INTERRUPT VECTOR
- OLDINT13 DD ? ;OLD BIOS DISK IO INTERRUPT VECTOR
- OLDINT16 DD ? ;OLD KEYBOARD INTERRUPT VECTOR
- OLDINT21 DD ? ;OLD DOS FUNCTION INTERRUPT VECTOR
- ERR_STAT DB ? ;ERROR STATUS DURING FILE OUTPUT
- FILE_PROMPT DB "Enter Filename: "
- FILENAME DB "SCREEN.CUT" ;THE DEFAULT FILENAME
- DB 15 DUP (0) ;LEAVE ROOM FOR DRIVE AND PATH
- BUFF_NEXT DW BUFF_START ;POINTER TO NEXT KEY IN BUFFER
- BUFF_LAST DW BUFF_START ;POINTER TO LAST KEY IN BUFFER
- BUFF_START EQU OFFSET INIT
- BUFF_SIZE EQU 25*(80+2) ;ROOM FOR 25 ROWS OF 80 COLUMNS
- BUFF_END DW BUFF_START+BUFF_SIZE
- TOP_LEFT LABEL WORD ;FIRST CORNER OF WINDOW
- LEFT_SIDE DB 0 ;COLUMN NUMBER OF LEFT SIDE
- TOP_ROW DB 0 ;ROW NUMBER OF TOP SIDE
- BOT_RIGHT LABEL WORD ;SECOND CORNER OF WINDOW
- RIGHT_SIDE DB ? ;COLUMN NUMBER OR RIGHT SIDE
- BOT_ROW DB ? ;ROW NUMBER OF BOTTOM
- SEND_CHAR DW ? ;POINTER TO CHARACTER HANDLER
- SEND_KEYS DB 0 ;IF=1, USE KEYSTROKES FROM BUFFER
- WRIT_FILE DB 0 ;IF=1, NEED TO WRITE TO DISK
- BUSY_FLAGS DB 0 ;BIT MASKED AS FOLLOWS:
- ; 1 - DOS IS ACTIVE
- ; 2 - BIOS IO IS ACTIVE
- ; 4 - SNIPPER IS ACTIVE
- DOS_STAT DB 0 ;CURRENT DOS FUNCTION
-
- HELP_MENU DB 201,10 DUP(205),187
- DB 186," F - File ",186
- DB 186," P - Print",186
- DB 186," S - Save ",186
- DB 186," G - Get ",186
- DB 186,"Esc- Quit ",186
- DB 200,10 DUP(205),188
-
- ;------------------------------------------------------------------;
- ; SNIPPER BUILDS THE WINDOW AND ACCEPTS COMMANDS FROM THE KEYBOARD ;
- ;------------------------------------------------------------------;
- SNIPPER PROC NEAR
- ASSUME DS:CSEG, ES:BIOS_SEG
- XOR BX,BX ;BX IS INCREMENT FOR ROW/COLUMN
- GET_KB_KEY1:
- MOV DX,TOP_LEFT ;GET LOCATION OF FIRST CORNER
- ADD DH,BH ;ADD IN THE ROW INCREMENT
- ADD DL,BL ;ADD IN THE COLUMN INCREMENT
- CMP DL,0 ;AT LEFT EDGE OF SCREEN?
- JGE NOT_LEFT_EDGE
- MOV DL,CRT_COLS ;JUMP TO THE RIGHT EDGE
- DEC DL
- NOT_LEFT_EDGE:
- CMP DL,CRT_COLS ;AT RIGHT EDGE OF SCREEN YET?
- JB NOT_RIGHT_EDGE ;IF NOT, KEEP MOVING RIGHT
- XOR DL,DL ;IF YES, WRAP TO LEFT EDGE
- NOT_RIGHT_EDGE:
- CMP DH,0 ;AT TOP OF SCREEN YET?
- JGE NOT_AT_TOP
- MOV DH,ROWS ;JUMP DOWN TO THE BOTTOM
- NOT_AT_TOP:
- CMP DH,ROWS ;AT BOTTOM OF SCREEN?
- JLE NOT_AT_BOTTOM
- XOR DH,DH ;JUMP BACK TO THE TOP
- NOT_AT_BOTTOM:
- MOV TOP_LEFT,DX ;SAVE NEW CORNER LOCATION
- CALL REV_VIDEO ;CHANGE IT TO REVERSE VIDEO
- XOR AH,AH ;BIOS KEYBOARD INPUT
- INT 16H ;GET A KEYSTROKE
- PUSH AX
- CALL REV_VIDEO ;PUT ATTRIBUTE BACK TO NORMAL
- POP AX
- CMP AH,1 ;IS IT ESCAPE?
- JNE NOT_ESC
- RET ;JUST RETURN TO EXIT
- NOT_ESC:
- MOV BX,0FF00H ;INCREMENT TO SUBTRACT ONE ROW
- CMP AH,48H ;IS IT UP ARROW?
- JE GET_KB_KEY1
- MOV BX,0100H ;INCREMENT TO ADD ONE ROW
- CMP AH,50H ;IS IT DOWN ARROW?
- JE GET_KB_KEY1
- MOV BX,0001H ;INCREMENT TO ADD ONE COLUMN
- CMP AH,4DH ;IS IT RIGHT ARROW?
- JE GET_KB_KEY1
- MOV BX,00FFH ;INCREMENT TO SUBTRACT ONE COLUMN
- CMP AH,4BH ;IS IT LEFT ARROW?
- JE GET_KB_KEY1
- XOR BX,BX
- CMP AL,13 ;IS IT A CARRIAGE RETURN?
- JNE NOT_CR
- MOV DX,TOP_LEFT ;A CARRIAGE RETURN WAS PRESSED
- MOV BOT_RIGHT,DX ;INITIALIZE THE SECOND CORNER
- CALL REV_VIDEO ;CHANGE IT BACK TO REVERSE VIDEO
- JMP SHORT GET_KB_KEY2
- NOT_CR:
- CMP AH,22H ;IS IT THE "G" KEY
- JE TYPE_BUFF ;IF YES, THAN GET THE WINDOW
- JMP GET_KB_KEY1 ;JUST GET ANOTHER KEY
- TYPE_BUFF:
- MOV SEND_KEYS,1 ;SIGNAL TO SEND THE KEYS
- RET
- GET_KB_KEY2:
- XOR AH,AH
- INT 16H ;GET A KEYSTROKE
- GOT_KEY2: MOV DX,BOT_RIGHT
- CMP AH,48H ;IS IT UP ARROW?
- JE SUB_ROW ;SUBTRACT A ROW FROM WINDOW
- CMP AH,50H ;IS IT DOWN ARROW?
- JE ADD_ROW ;ADD A ROW TO THE WINDOW
- CMP AH,4DH ;IS IT RIGHT ARROW?
- JE ADD_COL ;ADD A COLUMN TO THE WINDOW
- CMP AH,4BH ;IS IT LEFT ARROW?
- JE SUB_COL ;SUBTRACT A COLUMN FROM WINDOW
- JMP NOT_ARROW_KEY
- SUB_COL:
- DEC DL ;SUBTRACT A COLUMN
- CMP DL,LEFT_SIDE ;DONT ERASE IT COMPLETELY
- JL GET_KB_KEY2
- MOV RIGHT_SIDE,DL ;SAVE NEW RIGHT SIDE COLUMN
- INC DL
- JMP SHORT COL_LOOP
- ADD_COL:
- INC DL ;ADD A COLUMN
- CMP DL,CRT_COLS ;AT RIGHT EDGE OF SCREEN?
- JAE GET_KB_KEY2 ;STOP WHEN SCREEN IS FILLED
- MOV RIGHT_SIDE,DL ;SAVE NEW RIGHT SIDE COLUMN
- COL_LOOP:
- CALL REV_VIDEO ;REVERSE THIS CHARACTER
- DEC DH ;MOVE TO NEXT ROW
- CMP DH,TOP_ROW ;AT TOP ROW YET?
- JGE COL_LOOP ;LOOP UNTIL AT TOP ROW
- JMP GET_KB_KEY2
- SUB_ROW:
- DEC DH
- CMP DH,TOP_ROW ;AT TOP OF WINDOW?
- JL GET_KB_KEY2 ;DONT ERASE IT COMPLETELY
- MOV BOT_ROW,DH
- INC DH
- JMP SHORT ROW_LOOP
- ADD_ROW:
- INC DH
- CMP DH,ROWS ;AT BOTTOM OF SCREEN?
- JG GET_KB_KEY2 ;STOP WHEN SCREEN IS FILLED
- MOV BOT_ROW,DH
- ROW_LOOP:
- CALL REV_VIDEO ;REVERSE THIS CHARACTER
- DEC DL ;MOVE TO NEXT COLUMN
- CMP DL,LEFT_SIDE ;AT LEFT EDGE YET?
- JGE ROW_LOOP ;CONTINUE UNTIL AT LEFT EDGE
- JMP GET_KB_KEY2
- NOT_ARROW_KEY:
- CMP AH,19H ;WAS IT THE "P" KEY?
- JNE NOT_P
- MOV SEND_CHAR,OFFSET PRINT_CHAR
- JMP READ_WINDOW
- NOT_P:
- MOV BUFF_NEXT,BUFF_START
- MOV BUFF_LAST,BUFF_START
- MOV SEND_CHAR,OFFSET BUFF_CHAR
-
- CMP AH,1FH ;WAS IT THE "S" KEY?
- JNE NOT_S
- MOV SEND_CHAR,OFFSET BUFF_CHAR
- JMP READ_WINDOW
- NOT_S:
- CMP AH,22H ;IS IT THE "G" KEY
- JNE NOT_G
- MOV SEND_KEYS,1
- JMP READ_WINDOW
- NOT_G:
- CMP AH,21H ;IS IT THE "F" KEY
- JNE NOT_F
- MOV WRIT_FILE,0
- CALL GET_FILENAME
- CMP WRIT_FILE,-1 ;WAS ESCAPE REQUESTED?
- JE ERASE_BOX
- CALL READ_WINDOW
- MOV WRIT_FILE,1
- TEST BUSY_FLAGS,00000011B ;IS INT21 OR INT13 BUSY?
- JNZ RETURN ;IF YES, WAIT TILL LATER
- CALL WRITE_TO_FILE ;IF NOT, DO IT NOW
- RETURN:
- RET
- NOT_F:
- CMP AH,1 ;IS IT ESCAPE?
- JE ERASE_BOX ;IF YES, ERASE BOX AND EXIT
- CMP AL,13 ;IS IT A CARRIAGE RETURN?
- JE DISPLAY_HELP ;IF YES, DISPLAY HELP
- JMP GET_KB_KEY2 ;OTHERWISE JUST GET ANOTHER KEY
- ERASE_BOX:
- MOV SEND_CHAR,OFFSET RETURN
- JMP READ_WINDOW
- DISPLAY_HELP:
- CALL EXCHANGE_HELP ;PUT UP THE HELP MENU
- XOR AH,AH
- INT 16H ;GET ANOTHER KEYSTROKE
- PUSH AX ;SAVE THE KEYSTROKE
- CALL EXCHANGE_HELP ;PULL DOWN THE HELP MENU
- POP AX ;GET BACK THE KEYSTROKE
- JMP GOT_KEY2
- ;*********************************************************************
- REV_VIDEO:
- CALL READ_CHAR ;READ CHARACTER AND ATTRIBUTE
- MOV BL,AH ;SAVE ATTRIBUTE IN BL
- AND BL,10001000B ;GET BLINK AND INTENSITY BITS
- AND AH,01110111B ;NOW LOOK ONLY AT COLOR BITS
- MOV CL,4 ;ROTATE FOUR COUNTS
- ROR AH,CL ;ROTATE FOREGROUND AND BACKGROUND
- OR BL,AH ;PUT BACK BLINK AND INTENSITY BITS
- CALL DISPLAY_CHAR ;WRITE CHARACTER AND ATTRIBUTE
- RET
- ;*********************************************************************
- READ_WINDOW:
- MOV DX,TOP_LEFT ;GET LOCATION OF FIRST CORNER
- READ_LOOP:
- CALL REV_VIDEO ;PUT ATTRIBUTE BACK TO NORMAL
- CALL READ_CHAR ;READ THE CHARACTER
- CALL SEND_CHAR ;CALL TO THE POINTER
- INC DL ;NEXT CHAR IN ROW
- CMP DL,RIGHT_SIDE ;AT THE RIGHT BORDER YET?
- JLE READ_LOOP ;DO ALL CHARACTERS IN THIS ROW
- CALL CR_LF ;SEND CR-LF AFTER EACH ROW
- INC DH ;MOVE TO NEXT ROW
- MOV DL,LEFT_SIDE ;BACK TO LEFT EDGE
- CMP DH,BOT_ROW ;AT THE BOTTOM BORDER YET?
- JLE READ_LOOP ;READ ENTIRE WINDOW
- RET
- ;*********************************************************************
- CR_LF:
- MOV AL,13
- CALL SEND_CHAR ;SEND A CARRIAGE RETURN
- MOV AL,10
- CALL SEND_CHAR ;SEND A LINE FEED
- RET
- ;*********************************************************************
- DISPLAY_CHAR:
- PUSH BX ;SAVE THE ATTRIBUTE
- CALL GET_CURS_ADDR ;GET ADDRESS OF BIOS CURSOR
- MOV ES:[BX],DX ;TELL BIOS WHERE THE CURSOR IS
- POP BX ;GET BACK THE ATTRIBUTE
- MOV BH,ACTIVE_PAGE ;GET ACTIVE PAGE
- PUSH CX ;SAVE THE LOOP COUNT
- MOV CX,1 ;WRITE 1 CHARACTER
- MOV AH,9 ;WRITE CHARACTER AND ATTRIBUTE
- INT 10H
- POP CX ;RECOVER LOOP COUNT
- RET ;DONE WRITING THE CHARACTER
- ;*********************************************************************
- READ_CHAR:
- CALL GET_CURS_ADDR ;GET ADDRESS OF BIOS CURSOR
- MOV ES:[BX],DX ;TELL BIOS WHERE THE CURSOR IS
- MOV BH,ACTIVE_PAGE ;GET ACTIVE PAGE
- MOV AH,8 ;BIOS FUNCTION TO READ CHARACTER
- INT 10H ;READ THE CHARACTER/ATTRIBUTE
- RET
- ;*********************************************************************
- PRINT_CHAR:
- PUSH DX
- XOR AH,AH ;USE FUNCTION 0
- XOR DX,DX ;PRINTER NUMBER 0
- INT 17H ;BIOS PRINT CHARACTER FUNCTION
- ROR AH,1 ;LOOK AT BIT ZERO
- JNC PRINT_OK ;DID A TIMEOUT OCCUR?
- MOV SEND_CHAR,OFFSET RETURN
- PRINT_OK:
- POP DX
- RET ;DONE PRINTING CHARACTER
- ;*********************************************************************
- BUFF_CHAR:
- MOV BX,BUFF_LAST ;GET LOCATION OF LAST CHARACTER
- MOV [BX],AL ;PUT THE CHARACTER IN BUFFER
- INC BX ;ADVANCE THE POINTER
- MOV BUFF_LAST,BX ;CHECK FOR BUFFER FULL
- CMP BX,BUFF_END ;IS THE BUFFER FULL YET?
- JNE BUFF_OK ;IF NOT, KEEP GOING
- MOV SEND_CHAR,OFFSET RETURN
- BUFF_OK:
- RET ;NOW ITS IN THE BUFFER
- ;*********************************************************************
- GET_CURS_ADDR:
- MOV BL,ACTIVE_PAGE ;GET THE CURRENT PAGE NUMBER
- XOR BH,BH ;CONVERT TO A WORD OFFSET
- SHL BX,1 ;TIMES TWO FOR A WORD
- ADD BX,OFFSET CURSOR_POSN ;ADD IN BASE ADDRESS
- RET
- ;*********************************************************************
- EXCHANGE_HELP:
- XOR DX,DX ;START AT TOP LEFT CORNER
- LEA SI,HELP_MENU
- EXCHANGE_LOOP:
- CMP DL,12 ;AT LAST COLUMN IN THIS ROW YET?
- JL SWAP_CHAR
- XOR DL,DL ;BACK TO FIRST COLUMN
- INC DH ;DO THE NEXT ROW
- CMP DH,7 ;AT LAST ROW YET?
- JL SWAP_CHAR ;QUIT WHEN LAST ROW IS DONE
- RET
- SWAP_CHAR:
- CALL READ_CHAR ;READ CHARACTER AT THIS POSITION
- XCHG AL,CS:[SI] ;SWAP WITH THE HELP TEXT
- MOV BL,AH ;ATTRIBUTE IS THE SAME
- CALL DISPLAY_CHAR ;PUT NEW CHARACTER ON SCREEN
- INC DL ;POINT TO NEXT POSITION
- INC SI
- JMP EXCHANGE_LOOP
- ;*********************************************************************
- GET_FILENAME:
- LEA SI,FILE_PROMPT ;POINT TO THE PROMPT FOR SOURCE
- XOR DI,DI ;USE THE PSP FOR BUFFER
- XOR DX,DX ;PUT PROMPT AT TOP LEFT CORNER
- MOV CX,40 ;USE MAX OF 40 CHARACTERS
- DISPLAY_PROMPT:
- PUSH CX ;SAVE LOOP COUNT
- CALL READ_CHAR ;GET CHARACTER ON THIS LINE
- MOV CS:[DI],AX ;STORE IT IN THE PSP
- INC DI ;ADD TWO FOR NEXT CHARACTER
- INC DI
- MOV AL,CS:[SI] ;GET NEXT PROMPT CHARACTER
- INC SI ;NEXT CHARACTER IN PROMPT
- MOV BL,47H ;ATTRIBUTE FOR PROMPT
- CALL DISPLAY_CHAR ;PUT UP THE PROMPT CHARACTER
- INC DL ;POINT TO NEXT COLUMN
- POP CX ;GET BACK LOOP COUNT
- LOOP DISPLAY_PROMPT ;ENTIRE PROMPT AND FILENAME
- FIND_LAST_LETTER:
- DEC SI ;BACKUP TO LAST LETTER
- DEC DL ;BACKUP TO LAST COLUMN
- CMP BYTE PTR [SI],0 ;IS THIS A LETTER?
- JE FIND_LAST_LETTER;BACKUP UNTILL A LETTER IS FOUND
- INC DL ;PUT BLINKING BOX AT LAST LETTER
- READ_KB:
- MOV AL,219 ;ASCII FOR BOX CHARACTER
- MOV BL,47H+80H ;MAKE IT A BLINKING BOX CHARACTER
- CALL DISPLAY_CHAR ;WRITE THE BLINKING BOX
- ;
- XOR AH,AH ;FUNCTIO 0 TO GET NEXT KEY
- INT 16H ;BIOS KEYBOARD INPUT
- CMP AL,13 ;IS IT A CARRIAGE RETURN?
- JE ERASE_PROMPT
- CMP AL,8 ;IS IT A BACKSPACE?
- JE BACK_SPACE
- CMP AH,1 ;IS IT ESCAPE?
- JE ESC_RET
- CMP AL,"." ;IS IT A VALID LETTER?
- JL READ_KB
- CMP AL,"z" ;IS IT A VALID LETTER?
- JG READ_KB
- CMP DL,39 ;ONLY ALLOW 40 CHARACTERS
- JGE READ_KB
- TTY_KEY:
- MOV BL,47H ;ATTRIBUTE FOR FILENAME
- CALL DISPLAY_CHAR ;WRITE THE LETTER
- INC DL ;MOVE TO NEXT COLUMN
- JMP READ_KB ;GET ANOTHER KEYSTROKE
- BACK_SPACE:
- CMP DL,16 ;AT BEGINNING OF LINE?
- JLE READ_KB ;IF YES, CAN'T BACKUP FROM HERE
- MOV AL,0 ;WRITE A NORMAL BLANK (ASCII 0)
- MOV BL,47H ;ATTRIBUTE FOR FILENAME
- CALL DISPLAY_CHAR ;WRITE THE LETTER
- DEC DL ;BACKUP THE CURSOR
- JMP READ_KB ;THEN GET THE NEXT KEY
- ESC_RET:
- MOV WRIT_FILE,-1 ;INDICATE ESCAPE IS REQUESTED
- ERASE_PROMPT:
- XOR AL,AL ;GET RID OF THE CURSOR
- CALL DISPLAY_CHAR ;WRITE THE LETTER
- LEA DI,FILE_PROMPT ;COPY TO FILENAME
- XOR SI,SI ;COPY FROM PSP
- XOR DX,DX ;PROMPT IS AT ROW ZERO
- MOV CX,40 ;COPY ALL 40 CHARACTERS
- ERASE_LOOP:
- CALL READ_CHAR ;GET CHARACTER ON THIS LINE
- MOV CS:[DI],AL ;PUT IN BACK IN MEMORY
- INC DI
- MOV AX,CS:[SI] ;GET THE ORIGINAL CHARACTER BACK
- MOV BL,AH ;PUT ATTRIBUTE INTO BL
- INC SI
- INC SI
- CALL DISPLAY_CHAR ;WRITE ORIGINAL CHARACTER
- INC DL ;MOVE TO NEXT COLUMN
- LOOP ERASE_LOOP ;ERASE THE ENTIRE PROMPT
- RET
- SNIPPER ENDP
-
- ;---------------------------------------------------------------------;
- ; THIS COPIES THE BUFFER CONTENTS TO A FILE. IT SHOULD ONLY BE CALLED ;
- ; WHEN DOS IS IN A STABLE AND REENTRANT CONDITION. ;
- ;---------------------------------------------------------------------;
- WRITE_TO_FILE PROC NEAR
- ASSUME DS:NOTHING, ES:NOTHING
-
- MOV WRIT_FILE,0 ;TURN OFF REQUEST FLAG
- PUSH AX ;MUST PRESERVE ALL REGISTERS
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH DS
- PUSH ES
- PUSH CS
- POP DS
- ASSUME DS:CSEG ;DS POINTS TO OUR CODE SEGMENT
- MOV AX,3524H ;GET DOS CRITICAL ERROR VECTOR
- INT 21H ;DOS FUNCTION TO GET VECTOR
- PUSH BX ;SAVE OLD VECTOR ON STACK
- PUSH ES
-
- ; REPLACE THE DOS SEVERE ERROR INTERRUPT WITH OUR OWN ROUTINE.
-
- MOV DX,OFFSET NEWINT24
- MOV AX,2524H ;SETUP TO CHANGE INT 24h VECTOR
- INT 21H ;CHANGE DOS SEVERE ERROR VECTOR
- MOV DX,OFFSET FILENAME ;POINT TO FILENAME
-
- ; FIRST TRY TO OPEN THE FILE. IF DOS RETURNS WITH THE CARRY FLAG SET,
- ; THE FILE DIDN'T EXIST AND WE MUST CREATE IT. ONCE THE FILE IS OPENED,
- ; ADVANCE THE FILE POINTER TO THE END OF FILE TO APPEND.
-
- MOV AX,3D02H ;DOS FUNCTION TO OPEN FILE
- INT 21H ;DOS WILL RETURN WITH CARRY FLAG
- JC FILE_NOT_FOUND ;SET IF FILE DOESN'T EXIST.
- MOV BX,AX ;KEEP HANDLE IN BX ALSO
- XOR CX,CX ;MOVE DOS FILE POINTER TO THE
- XOR DX,DX ;END OF THE FILE. THIS LETS US
- MOV AX,4202H ;APPEND THIS TO AN EXISTING FILE
- INT 21H ;DOS FUNCTION TO MOVE POINTER
- JNC WRITE_FILE ;IF NO ERROR, CONTINUE TO WRITE
- DOS_ERROR:
- CMP ERR_STAT,0 ;DID A SEVERE ERROR OCCUR?
- JNE REP_VECTOR ;IF SEVERE ERROR, JUST QUIT
- JMP SHORT CLOSE_FILE;JUST CLOSE THE FILE
-
- FILE_NOT_FOUND: CMP ERR_STAT,0 ;DID A SEVERE ERROR OCCUR?
- JNE REP_VECTOR ;IF SEVERE ERROR, JUST QUIT
- MOV CX,0020H ;ATTRIBUTE FOR NEW FILE
- MOV AH,3CH ;CREATE FILE FOR WRITING
- INT 21H ;DOS FUNCTION TO CREATE FILE
- JC DOS_ERROR ;ON ANY ERROR, TAKE JUMP
- MOV BX,AX ;SAVE HANDLE IN BX
- WRITE_FILE: MOV DX,BUFF_START ;POINT TO BUFFER
- MOV CX,BUFF_LAST ;GET BUFFER POINTER
- SUB CX,DX ;NUMBER OF CHARS IN BUFFER
- MOV AH,40H ;DOS WRITE TO A DEVICE FUNCTION
- INT 21H ;WRITE TO THE FILE
- CLOSE_FILE:
- MOV AH,3EH ;DOS FUNCTION TO CLOSE THE FILE
- INT 21H
- REP_VECTOR:
- POP DS ;GET INT 24H VECTOR FROM STACK
- POP DX
- MOV AX,2524H ;RESTORE CRITICAL ERROR VECTOR
- INT 21H ;DOS FUNCTION TO CHANGE VECTOR
- POP ES ;FINALLY RESTORE ALL REGISTERS
- POP DS
- POP DX
- POP CX
- POP BX
- POP AX
- RET ;FINISHED WRITING TO DISK
- WRITE_TO_FILE ENDP
- ;---------------------------------------------------------------------;
- ; INTERRUPT 09 ROUTINE. WATCH FOR TRIGGER KEY TO POP UP.
- ;---------------------------------------------------------------------;
- NEWINT09 PROC FAR
- ASSUME DS:NOTHING, ES:NOTHING
- STI ;ALLOW OTHER INTERRUPTS
- PUSH AX ;MUST SAVE PROCESSOR STATE
- IN AL,60H ;GET THE SCAN CODE
- CMP AL,HOTKEY ;IS IT THE HOT KEY?
- JE TRIGGER ;IF YES, CHECK THE MASK
- INT09_EXIT: POP AX ;RESTORE THE PROCESSOR STATE
- JMP OLDINT09 ;CONTINUE WITH ROM ROUTINE
-
- TRIGGER: MOV AH,2 ;GET KEYBOARD STATUS
- INT 16H ;BIOS KEYBOARD SERVICE
-
- AND AL,0FH ;Take lo er four bits
- CMP AL,SHIFT_MASK ;IS ALT KEY DOWN?
- JNZ INT09_EXIT ;IF NOT, IGNORE IT
- TEST BUSY_FLAGS,00000100B ;IS SNIPPER ALREADY ACTIVE?
- JNZ INT09_EXIT ;IF ACTIVE, THEN EXIT
- OR BUSY_FLAGS,00000100B ;ITS ACTIVE NOW
- PUSHF
- CALL OLDINT09 ;LET ROM PROCESS THE KEY
- PUSH BX ;MUST PRESERVE ALL REGISTERS
- PUSH CX
- PUSH DX
- PUSH BP
- PUSH SI
- PUSH DI
- PUSH DS
- PUSH ES
- PUSH CS
- POP DS ;SET DS TO CSEG
- MOV AX,BIOS_SEG ;ES POINTS TO BIOS DATA AREA
- MOV ES,AX
- ASSUME DS:CSEG, ES:BIOS_SEG
- CALL GET_CURS_ADDR ;CURSOR ADDRESS FOR THIS PAGE
- PUSH ES:[BX] ;SAVE THE CURSOR LOCATION
- CALL SNIPPER ;DO THE WINDOW
- CALL GET_CURS_ADDR ;CURS0R ADDRESS FOR THIS PAGE
- POP ES:[BX] ;GET BACK CURSOR POSITION
- AND BUSY_FLAGS,11111011B ;SNIPPER IS NOT ACTIVE
- POP ES ;RESTORE ALL REGISTERS
- POP DS
- POP DI
- POP SI
- POP BP
- POP DX
- POP CX
- POP BX
- POP AX
- IRET ;NOW WERE ALL DONE
- NEWINT09 ENDP
- ;---------------------------------------------------------------------;
- ; INTERRUPT 13 ROUTINE. SET BIOS BUST BIT ;
- ;---------------------------------------------------------------------;
- NEWINT13 PROC FAR
- ASSUME DS:NOTHING, ES:NOTHING
-
- OR BUSY_FLAGS,00000010B ;SET BIOS BUSY BIT
- PUSHF
- CALL OLDINT13 ;DO THE BIOS FUNCTION
- PUSHF ;SAVE RESULT FLAGS
- AND BUSY_FLAGS,11111101B ;CLEAR BIOS BUSY BIT
- POPF ;GET BACK RESULT FLAGS
- STI ;MUST RETURN WITH INTERUPTS ON
- RET 2 ;RETURN BIOS RESULT FLAGS
-
- NEWINT13 ENDP
- ;---------------------------------------------------------------------;
- ; INTERRUPT 16 ROUTINE. INSERT KEYSTROKES FROM BUFFER ;
- ;---------------------------------------------------------------------;
- NEWINT16 PROC FAR
- ASSUME DS:NOTHING, ES:NOTHING
- PUSH BX
- CMP SEND_KEYS,1 ;SENDING KEYS FROM BUFFER?
- JE INSERT_KEY ;IF YES, THEN GET NEXT ONE
- CMP WRIT_FILE,1 ;ANYTHING TO WRITE TO DISK?
- JE CHECK_DOS_STAT ;IF YES, THIS IS THE TIME
- BIOS_KB:
- POP BX
- JMP OLDINT16 ;JUST DO NORMAL KB ROUTINE
- CHECK_DOS_STAT:
- CMP DOS_STAT,0AH ;DOING READ STRING?
- JE BEGIN_NOW ;IF YES, ITS SAFE TO BEGIN
- CMP DOS_STAT,8 ;DOING KEYBOARD INPUT?
- JNE BIOS_KB ;IF YES, ITS SAFE TO BEGIN
- BEGIN_NOW:
- STI ;GET INTERRUPTS BACK ON
- CALL WRITE_TO_FILE ;EMPTY THE BUFFER
- JMP BIOS_KB ;CONTINUE WITH BIOS ROUTINE
- INSERT_KEY:
- STI ;INTERRUPTS BACK ON
- MOV BX,BUFF_NEXT ;GET ADDRESS OF NEXT BYTE
- CMP BX,BUFF_LAST ;AT END OF BUFFER YET?
- JL GET_A_KEY ;IF NOT, GET THE NEXT ONE
- MOV SEND_KEYS,0 ;WHEN DONE, TURN OFF SEND SWITCH
- GET_A_KEY:
- MOV AL,CS:[BX] ;GET THE NEXT KEY CODE
- CMP AL,10 ;IS IT A LINE FEED?
- JNE NOT_LF ;DONT RETURN THE LINE FEEDS
- INC BUFF_NEXT ;SKIP TO NEXT KEY
- JMP INSERT_KEY
- NOT_LF:
- CMP AH,1 ;REQUEST FOR STATUS ONLY?
- JE RETURN_STATUS ;IF YES, RETURN STATUS ONLY
- CMP AH,0 ;REQUEST TO GET THE NEXT KEY
- JNE BIOS_KB ;IF NOT, IGNORE THIS FUNCTION
- INC BX ;REMOVE THIS KEY FROM OUR BUFFER
- MOV BUFF_NEXT,BX ;SAVE THE POINTER TO NEXT KEY
- RETURN_STATUS:
- OR BL,1 ;CLEAR ZERO FLAG TO INDICATE A
- POP BX ;KEY IS AVAILIABLE
- RET 2 ;RETURN WITH THESE FLAGS
- NEWINT16 ENDP
- ;---------------------------------------------------------------------;
- ; INTERRUPT 21 ROUTINE. THIS ROUTINE IS USED TO MONITOR DOS FUNCTION ;
- ; CALLS. IF THE BUFFER NEEDS TO BE FLUSHED, IT WIL BE DONE HERE. ;
- ;---------------------------------------------------------------------;
- NEWINT21 PROC FAR
- ASSUME DS:NOTHING, ES:NOTHING
-
- PUSHF ;SAVE ENTRY FLAGS
-
- STI ;ALLOW INTERRUPTS
- CMP AH,4BH ;IF EXEC
- JNE NOT_EXEC
- POPF
- JMP CS:OLDINT21 ;GO DIRECT
- NOT_EXEC:
- OR AH,AH ;DOING FUNCTION ZERO?
- JNE NOT_ZERO
- MOV AH,4CH ;IF YES, CHANGE IT TO A 4CH
- NOT_ZERO:
- OR BUSY_FLAGS,00000001B ;SET DOS BUSY BIT
- MOV DOS_STAT,AH
- POPF ;RESTORE ORIGINAL FLAGS
- PUSHF ;SIMULATE AN INTERRUPT
- CALL CS:OLDINT21 ;DO THE DOS FUNCTION
- PUSHF ;SAVE THE RESULT FLAGS
- AND BUSY_FLAGS,11111110B ;CLEAR DOS BUSY BIT
- CMP WRIT_FILE,1 ;ANYTHING TO WRITE TO DISK?
- JNE NO_WRITE ;IF NOT JUST RETURN
- CALL WRITE_TO_FILE ;SAFE TO ACCESS DISK NOW
- NO_WRITE:
- POPF ;RECOVER DOS RESULT FLAGS
- STI
- RET 2 ;RETURN WITH DOS RESULT FLAGS
- NEWINT21 ENDP
-
- ;---------------------------------------------------------------------;
- ; NEW INTERRUPT 24H (CRITICAL DOS ERROR). THIS INTERRUPT IS ONLY IN ;
- ; EFFECT ONLY DURING A WRITE SCREEN. IT IS REQUIRED TO SUPPRESS THE ;
- ; 'ABORT, RETRY, IGNORE' MESSAGE. ALL FATAL DISK ERRORS ARE IGNORED. ;
- ;---------------------------------------------------------------------;
- NEWINT24 PROC FAR
- ASSUME CS:CSEG, DS:NOTHING, ES:NOTHING
- STI ;TURN INTERRUPTS BACK ON
- INC ERR_STAT ;SET THE ERROR FLAG
- XOR AL,AL ;TELLS DOS TO IGNORE THE ERROR
- IRET ;THATS ALL WE DO HERE
- NEWINT24 ENDP
-
- ;--------------------------------------------------------------------;
- ; HERE IS THE CODE USED TO INITIALIZE SNIPPER. ;
- ;--------------------------------------------------------------------;
- ASSUME CS:CSEG, DS:CSEG, ES:CSEG
- INIT:
- LEA DX,COPYRIGHT
- MOV AH,9 ;DOS DISPLAY STRING SERVICE
- INT 21H ;DISPLAY TITLE MESSAGE
- ; SEARCH FOR AN PREVIOUSLY INSTALLED COPY OF SNIPPER
- NOT BYTE PTR START ;MODIFY TO AVOID FASLE MATCH
- XOR BX,BX ;START SEARCH AT SEGMENT ZERO
- MOV AX,CS ;COMPARE TO THIS CODE SEGMENT
- NEXT_SEGMENT:
- INC BX ;LOOK AT NEXT SEGMENT
- CMP AX,BX ;UNTIL REACHING THIS CODE SEG
- MOV ES,BX
- JE NOT_INSTALLED
- LEA SI,START ;SETUP TO COMPARE STRINGS
- MOV DI,SI
- MOV CX,16 ;16 BYTES MUST MATCH
- REP CMPSB ;COMPARE DS:SI TO ES:DI
- OR CX,CX ;DID THE STRINGS MATCH?
- JNZ NEXT_SEGMENT ;IF NO MATCH, TRY NEXT SEGMENT
- LEA DX,INSTALLED_MSG
- JMP SHORT ERR_EXIT
- NOT_INSTALLED:
- MOV AH,30H
- INT 21H ;GET DOS VERSION NUMBER
- CMP AL,2 ;IS IT HIGHER THAN 2.0?
- JAE VER_OK ;IF YES, PROCEED
- LEA DX,BAD_DOS_MSG
- ERR_EXIT: MOV AH,9 ;DOS DISPLAY STRING SERVICE
- INT 21H ;DISPLAY ERRER MESSAGE
- RET ;RETURN TO DOS
- VER_OK:
- INC SI ;POINT TO FIRST PARAMETER
- MOV SI,81H ;POINT TO PARAMETER AREA
- CALL GET_PARAM ;GET FIRST PARAMETER (ROWS)
- PUSH AX ;SAVE THE ROW COUNT
- CALL GET_PARAM ;GET SECOND PARAMETER (COLUMNS)
- ADD AX,2 ;ADD SPACE FOR CR AND LF
- POP BX ;GET BACK FIRST PARAMETER
- MUL BX ;PRODUCT OF ROWS AND COLUMNS
- OR AX,AX ;WAS ANYTHING ENTERED?
- JZ NO_PARAMS ;IF NOT, USE DEFAULT VALUE
- CMP AX,10000 ;MAXIMUM BUFFER IS 10000 BYTES
- JLE SIZE_IS_OK
- MOV AX,10000
- SIZE_IS_OK:
- ADD AX,BUFF_START
- MOV BUFF_END,AX ;SET THE NEW BUFFER SIZE
- NO_PARAMS:
- MOV AX,BIOS_SEG ;LOOK AT BIOS DATA AREA
- MOV ES,AX
- ASSUME ES:BIOS_SEG
- CMP ROWS,0 ;IS NUMBER OF ROWS ENTERED HERE
- JNE MUST_BE_EGA ;IF YES, AN EGA MAY BE PRESENT
- MOV ROWS,24 ;IF NOT EGA, MUST BE 24 ROWS
- MUST_BE_EGA:
- ASSUME ES:NOTHING
- MOV AX,3509H ;GET KEYBOARD BREAK VECTOR
- INT 21H
- MOV WORD PTR [OLDINT09], BX ;SAVE SEGMENT
- MOV WORD PTR [OLDINT09+2],ES ;SAVE OFFSET
- MOV DX, OFFSET NEWINT09
- MOV AX, 2509H
- INT 21H ;DOS FUNCTION TO CHANGE VECTOR
-
- MOV AX,3513H ;GET BIOS DISK INTERRUPT VECTOR
- INT 21H
- MOV WORD PTR [OLDINT13], BX ;SAVE SEGMENT
- MOV WORD PTR [OLDINT13+2],ES ;SAVE OFFSET
- MOV DX, OFFSET NEWINT13
- MOV AX, 2513H
- INT 21H ;DOS FUNCTION TO CHANGE VECTOR
-
- MOV AX,3516H ;GET KEYBOARD INPUT VECTOR
- INT 21H
- MOV WORD PTR [OLDINT16], BX ;SAVE SEGMENT
- MOV WORD PTR [OLDINT16+2],ES ;SAVE OFFSET
- MOV DX, OFFSET NEWINT16
- MOV AX, 2516H
- INT 21H ;DOS FUNCTION TO CHANGE VECTOR
-
- MOV AX,3521H ;GET DOS FUNCTION VECTOR
- INT 21H
- MOV WORD PTR [OLDINT21], BX
- MOV WORD PTR [OLDINT21+2],ES
- MOV DX, OFFSET NEWINT21
- MOV AX, 2521H
- INT 21H ;DOS FUNCTION TO CHANGE VECTOR
-
- ;--------------------------------------------------------------------;
- ; DEALLOCATE OUR COPY OF THE ENVIORNMENT. ;
- ; EXIT USING INT 27H. LEAVE CODE AND SPACE FOR BUFFER RESIDENT. ;
- ;--------------------------------------------------------------------;
-
- MOV AX,DS:[002CH] ;GET SEGMENT OF ENVIORNMENT
- MOV ES,AX ;PUT IT INTO ES
- MOV AH,49H ;RELEASE ALLOCATED MEMORY
- INT 21H
- MOV DX,BUFF_END ;LEAVE THIS MUCH RESIDENT
- INT 27H ;TEMINATE AND STAY RESIDENT
- ;---------------------------------------------------------;
- ; GET_PARAM RETRIEVES AN INTEGER FROM THE COMMAND LINE. ;
- ;---------------------------------------------------------;
- GET_PARAM: XOR AX,AX ;CLEAR AX FOR TOTAL
- GET_DIGIT: MOV BL,[SI] ;GET CHARACTER INTO BL
- CMP BL,0DH ;IS IT THE LAST ONE?
- JE DONE
- INC SI ;POINT TO NEXT CHARACTER
- CMP BL,"," ;IS IT THE DELIMITER?
- JE DONE
- SUB BL,30H ;CONVERT ASCII TO INTEGER
- JC GET_DIGIT ;IS IT A VALID DIGIT
- CMP BL,9
- JA GET_DIGIT ;IF NOT VALID, JUST SKIP IT
- MOV BH,10 ;TIMES 10 FOR NEXT DIGIT
- MUL BH ;MULTIPLY SUM AND ADD THIS DIGIT
- ADD AL,BL ;ADD DIGIT TO SUM
- JMP GET_DIGIT ;READ ALL CHARACTERS ON LINE
- DONE: RET
- CSEG ENDS
- END START
-