        page 60,132
        title PRTSCRN -- Print the Screen via Interrupt 5 (Shift-PrtScrn)
;******************************************************************************
;
;                               I N T   5
;
;     This is a modification of IBM's Interrupt 5 logic.  It does the same
;     print screen, but if the character to be printed is in the range
;     x'00' to x'19' or x'80' to x'99', then a blank is passed instead.
;
;     As with IBM's Interrupt 5 logic, the cursor position is saved 
;     and restored upon completion.  The routine runs with
;     interrupts enabled.  If a subsequent 'Print Screen' key is depressed
;     during the time this routine is printing it will be ignored.
;
;     Address 50:0 contains the Print Screen status:
;
;        50:0     = 0      Either Print Screen has not been called or upon
;                          return from a call this indicates a successful
;                          operation.
;                 = 1      Print Screen is in progress.
;                 = 255    Error encountered during printing.
;
;	Author	Robert S. Russell
;		Bootstrap Creations
;		1902 Pomar Way
;		Walnut Creek, California 94598
;
;*******************************************************************************

;------------------------------
;      print status byte
;------------------------------
scrnstat        segment at 0h
        dd      5 dup(?)                ; skip int 0-4
int5of  dw      1 dup(?)                ; int vector for int 5 (offset)
int5cs  dw      1 dup(?)                ; int vector for int 5 (code seg)
        org     500h
status_byte     db      1 dup(?)        ; 1 = print in progress
                                        ; 0 = print not in progress
                                        ; 255 = error during print
scrnstat        ends
        page
code    segment public  'code'
        assume  cs:code,ds:scrnstat,ss:code
        org     100h
prtscrn:
	jmp	set_vector		; put initialization code at bottom
					; so it can be freed after use.

print_screen    proc    near
        sti                             ; enable interrupts
        push    ds                      ; save regs used
        push    ax
        push    bx
        push    cx                      ; will be used for cursor limits
        push    dx                      ; will hold current cursor position
        mov     ax,scrnstat             ; a..data segment
        mov     ds,ax                   ; set data segment
        cmp     status_byte,1           ; is print already in progress?
        jz      exit                    ; yes, let's get out of here
        mov     status_byte,1           ; indicate print now in progress
        mov     ah,15                   ; get the current screen mode
        int     10h                     ;       [al] = mode
                                        ;       [ah] = # of cols/line
                                        ;       [bh] = visual page
;-------------------------------------------------------------------------------
;       at this point the columns/line are in ax and the page, if
;       color, is in bh.  al contains the current video mode
;-------------------------------------------------------------------------------
        mov     cl,ah                   ; will use cx register to
        mov     ch,25                   ;  control row and columns.
        call    crlf                    ; send a cr/lf sequence
        push    cx                      ; save screen bounds
        mov     ah,3                    ; get cursor position
        int     10h                     ; and save it
        pop     cx                      ; recall screen bounds
        push    dx                      ; recall [bh] = visual page
        xor     dx,dx                   ; will set cursor position to [0,0]
;-------------------------------------------------------------------------------
;       the loop from printloop up to loop_end is the loop to read each cursor
;       position from the screen and print the character there.
;-------------------------------------------------------------------------------
printloop:
        mov     ah,2                    ; indicate new cursor position
        int     10h                     ; set cursor position 
        mov     ah,8                    ; indicate read the character there
        int     10h                     ; character now in [al]
        cmp     al,20h                  ; is char "unprintable"?
        jb      blankit                 ; yes, so blank it out
        cmp     al,9fh                  ; printable with hi order bit set?
        ja      printit                 ; yes, so print it
        cmp     al,80h                  ; printable with hi order bit cleared?
        jb      printit                 ; yes, so print it
blankit:
        mov     al,20h                  ; change char to blank
printit:
        push    dx                      ; save cursor position
        xor     dx,dx                   ; use printer 1
        xor     ah,ah                   ; request print the char in [al]
        int     17h                     ; print the char
        pop     dx                      ; restore cursor position
        test    ah,25h                  ; check for printer error
        jnz     print_err               ; quit if error detected
        inc     dl                      ; move to next column
        cmp     cl,dl                   ; is this the end of the line?
        jne     printloop               ; no, so proceed.
        xor     dl,dl                   ; return to col 0 (new line)
        mov     ah,dl                   ; [ah] = 0
        push    dx                      ; save new cursor position
        call    crlf                    ; do cr/lf
        pop     dx                      ; restore cursor position
        inc     dh                      ; skip to next line
        cmp     ch,dh                   ; done?
        jnz     printloop               ; no, continue
loop_end:
        pop     dx                      ; get cursor position
        mov     ah,2                    ; specify cursor set request
        int     10h                     ; restore beginning cursor position
        mov     status_byte,0           ; indicate print screen not in progress
        jmp     short exit              ; and get out of here
print_err:
        pop     dx                      ; get cursor position
        mov     ah,2                    ; request cursor position set
        int     10h                     ; restore cursor position
err20:
        mov     status_byte,0ffh        ; indicate error
exit:
        pop     dx                      ; restore all the regs
        pop     cx
        pop     bx
        pop     ax
        pop     ds
        iret
print_screen    endp

;***** carriage return, line feed subroutine ***********************************

crlf    proc    near
        xor     dx,dx                   ; select printer 0
        xor     ah,ah                   ; send initial cr/lf to printer
        mov     al,10                   ; = lf
        int     17h                     ; print the line feed
        xor     ah,ah                   ; clear ah
        mov     al,13                   ; = cr
        int     17h                     ; print the carriage return
        ret
crlf    endp
end_print_screen:                       ;end of resident routine
set_vector:
        push    ds
        xor     ax,ax
        push    ax
        mov     ax,scrnstat             ; set ds to point to int vector table
        mov     ds,ax                   ;
        cli                             ; disable interrupts so that interrupt
                                        ; address doesn't get garbled
        lea     ax,print_screen         ; address of print_screen routine
        mov     int5of,ax               ; store it in int 5 vector
        mov     int5cs,cs               ; and save paragraph address
        lea     dx,end_print_screen     ; end of resident interrupt routine
        sti                             ; allow interrupt
        pop     ax
        pop     ds
        int     27h                     ; terminate but stay resident
code    ends
        end     prtscrn
