Category : Printer Utilities
Archive   : SPS20.ZIP
Filename : SPS.8

Output of file : SPS.8 contained in archive : SPS20.ZIP
;SPS.COM is a TSR program to do a selective print screen. It prints
;the characters within a box defined by the cursor position. When
;started, if P is pressed, the whole screen is printed, and if Esc
;is pressed, the print screen is aborted.

Colormem equ 0B800h ;Color video mem for page 1
Monomem equ 0B000h ;Mon video mem for page 1
Timer equ 8 ;Timer int #
Enterkey equ 28 ;Define scan codes
Home equ 71
Endkey equ 79
Esc equ 1
Lfarrow equ 75
Rtarrow equ 77
Uparrow equ 72
Dnarrow equ 80
Pgup equ 73
Pgdn equ 81
Cntrl equ 29 ;Scan code for control key
Cntnot equ Cntrl+128 ;Scan code fpr control key release
Lshrel equ 42+128 ;Scan code for left shift release
Rshrel equ 54+128 ; " " " right " "
Video equ 10h ;Bios video interrupt
DOS equ 21h ;DOS interrupt
Getvec equ 35h ;Get int vector DOS service
Setvec equ 25h ;Set int vector DOS service
Setcur equ 2 ;Set cursor pos video service
Getcur equ 3 ;Get cursor pos video service
Promptpos equ 25*160-36 ;5th char from end of screen

jmp Initialize ;Install the program as int 5 (PrtScn)

Oldoff5 dw ? ;Save old int 5 offset and segment here
Oldseg5 dw ?
Oldoff8 dw ?
Oldseg8 dw ?
Oldoff9 dw ? ;Save old keyboard int here
Oldseg9 dw ?
Vidmem dw ? ;Current video mem segment
Curpos dw ? ;Cursor position at start
Curtyp dw ? ;Cursor type
Stloc dw 0 ;Start row:col of print box
Endloc dw 184fh ;End row:col of print box
Timeval db ?
Vpage db ? ;Current video page
Endflg db 0 ;1=> start row:col set
Prtflg db 0 ;1=> screen has been printed
Cntflg db 0 ;1=> Cntrl being pressed
Row db ? ;Rows to print
Col db ? ;Columns to print
Buffer: dw 18 dup(?) ;Put original prompt data here
Msg1: db 'Speptp psptpaprptp pppopspiptpipopnp'
Msg2: db 'Speptp pepnpdp pppopspiptpipopnp p p'
Msg3: db 'Pprpipnptpeprp pnpoptp prpepapdpyp p'
Rowbuf: db 83 dup(?) ;Buffer for a screen row of chars

Newint5: push bp,ax,bx,cx,dx,si,di,ds,es ;Save all for calling pgm
mov bp,sp
mov ds,cs ;Set both for this code
mov es,cs
mov cx,Colormem ;Assume color display
mov ah,15 ;Get current video mode
int Video
mov Vpage,bh ;Save video page
cmp al,2 ;Color?
je A1 ;Yes
cmp al,3 ;Color?
je A1 ;Yes
cmp al,7 ;Mono?
je A0 ;Yes
mov sp,bp
pop es,ds,di,si,dx,cx,bx,ax,bp ;Restore all for calling pgm
cs jmp far d[Oldint5] ;and do a graphics print screen

;Come here if 80 col text mode.
A0: mov cx,Monomem ;Yes, set for Mono
A1: mov bl,0 ;bx=page offset
add cx,bx ;Video segment
mov Vidmem,cx ;Save it

;Save old and install new Keyboard int 9 and Timer int 8 to this code.
push ds
mov ax,0 ;Set ds=0 (int area)
mov ds,ax
cli ;Disable interrupts
mov ax,[32]
mov bx,[34]
mov cx,[36]
mov dx,[38]
mov cs:Oldoff8,ax
mov cs:Oldseg8,bx
mov cs:Oldoff9,cx ;to storage
mov cs:Oldseg9,dx
mov w[32],Newint8
mov w[34],cs
mov w[36],Newint9
mov w[38],cs
sti ;Enable ints
pop ds

;Initialize variables.
mov Stloc,0 ;Start of screen
mov Endloc,184Fh ;End of screen
mov Endflg,0 ;Clear flags
mov Prtflg,0
mov Cntflg,0

;Get current Cursor position and type.
mov ah,Getcur ;Get cursor row:col
mov bh,Vpage
int Video
mov Curpos,dx ;Save it
mov Curtyp,cx ;Save cursor type

;Move cursor to top of screen.
xor dx,dx ;Top of screen
call Poscur
mov cx,0607h ;Set new cursor
mov ah,1
int Video

;Get last 18 bytes from screen.
push ds
mov ax,Vidmem ;Set ds=Vidmem
mov ds,ax
mov si,Promptpos ;ds:si=prompt pos
mov di,Buffer ;es:di=buffer
mov cx,18 ;Get 18 words
rep movsw ;to buffer
pop ds

;Display prompt.
mov si,Msg1 ;Print 'start' prompt
call Prompt

;Hang up computer and wait for keyboard input.
Waithere: jmp Waithere ;Wait for keyboard int

cs cmp Timeval,0
je X1
cs dec Timeval
X1: cs jmp far d[Oldint8]

;This is the new Keyboard int 9 routine. Does not pass keys on to
;other programs, so they never know keys were pressed.
Newint9: sti
push ax ;Save reg
in al,60h ;Get scan code
cmp Prtflg,0 ;Is screen being printed?
jne B0 ;Yes, clear keyboard and return from int
cmp al,Lshrel ;Left shift release?
je A2 ;Yes
cmp al,Rshrel ;Right shift release?
jne A3 ;No
A2: pop ax
cs jmp far d[Oldint9] ;Yes, send to BIOS
;No, process the key command.
A3: cmp al,Home ;Home?
jne C1 ;No
xor dx,dx ;Set for start of screen
B1: call Poscur ;Set cursor there
;Reset keyboard and sen End Of Interrupt
B0: call Resetkbd ;Reset keyboard
pop ax
iret ;Send back to Wait line

C1: cmp al,Endkey ;End key?
jne C2 ;No
mov dx,184Fh ;Set for end of screen
jmp B1

C2: cmp al,Uparrow ;Up arrow?
jne C3 ;No
cmp dh,0 ;On top line?
je B0 ;Yes
dec dh ;Dec row
jmp B1

C3: cmp al,Dnarrow ;Down arrow?
jne C4 ;No
cmp dh,24 ;On bottom row?
je B0 ;Yes
inc dh ;Inc row
jmp B1

C4: cmp al,Lfarrow ;Left arrow?
jne C5 ;No
cmp cs:Cntflg,0 ;Cntrl left arrow?
je C4A ;No
mov dl,0 ;Set for 1st col
jmp B1
C4A: cmp dl,0 ;At 1st col?
je B0 ;Yes
dec dl ;Dec col
jmp B1

C5: cmp al,Rtarrow ;Right arrow?
jne C6 ;No
cmp cs:Cntflg,0 ;Cntrl right arrow?
je C5A ;No
mov dl,79 ;Set for last col
jmp B1
C5A: cmp dl,79 ;At last col?
je B0 ;Yes
inc dl ;Inc col
jmp B1

C6: cmp al,Cntrl ;Control pressed?
jne C7 ;No
inc Cntflg ;Yes, set flag
jmp B0

C7: cmp al,Cntnot ;Cntrl key released?
jne C8 ;No
mov Cntflg,0 ;Clear flag
jmp B0

C8: cmp al,Esc ;Escape?
jne C9 ;No
jmp Exit ;Yes, exit

C9: cmp al,25 ;Was a P?
je Check ;Yes, print whole screen

cmp al,Pgup ;Page up?
jne D1 ;No
mov dh,0 ;Set to top row
jmp B1

D1: cmp al,Pgdn ;Page down
jne D3 ;No
mov dh,24 ;Set to last row
D2: jmp B1

D3: cmp al,Enterkey ;Enter?
jne D2 ;No, ignore the key and wait for another
cmp Endflg,0 ;1st selection?
jne D4 ;No
mov Stloc,dx ;Save start box location
inc Endflg ;=> start saved
mov si,Msg2 ;Print End prompt
call Prompt
jmp B0 ;Get next command
D4: mov Endloc,dx ;Save end location

Check: mov si,Buffer ;ds:si=buffer
call Prompt ;Put original data back on screen
inc Prtflg ;Indicate printing has started
mov ax,Stloc ;Get box start
mov cx,Endloc ;Get box end
sub ch,ah ;Rows OK?
jc Exit ;No
sub cl,al ;Cols OK?
jc Exit ;No, exit
add cx,0101h ;ah=rows, al=columns to do
mov Row,ch ;Save them
mov Col,cl

;Compute start offset.
mov cl,al ;Save column
mov ch,80 ;Chars/row
xchg al,ah ;Get row to al
mul ch ;ax=char offset to start of row
mov ch,0 ;cx=column
add ax,cx ;ax=char offset of start location
shl ax,1 ;Byte offset since 2 bytes/char
mov si,ax ;Save it

;Get a row of data to the buffer.
E0: push ds
mov ax,Vidmem ;Set ds=video mem
mov ds,ax
mov es,cs ;Set es this segment
E1: mov cl,cs:Col ;Get cols to do
mov ch,0 ;cx=cols to do
mov di,Rowbuf ;es:di point to screen row buffer
push si,di,cx ;Save pointers and count
E2: lodsw ;Get char & attr from screen
stosb ;Save char in row buffer
loop E2 ;Do for all chars on row
mov ax,0A0Dh ;Add a cr-lf
;Ckeck for and replace (with a space) any control chars.
pop cx,di ;Get cols and buffer pointer
E3: mov al,cs:[di] ;Get a char from buffer
cmp al,20h ;Control char?
jb E4 ;Yes
cmp al,0FFh ;Bad char?
jb E5 ;No
E4: mov cs:b[di],20h ;Replace with a space
E5: inc di ;Point to next char
loop E3 ;Check all
;Now send chars in buffer to printer.
call Printer
pop si ;Get start of row
add si,160 ;Next row
dec cs:Row ;Done all rows?
jne E1 ;No
pop ds

;Now exit.
Exit: mov si,Buffer ;Put old screen data back
call Prompt
mov dx,cs:Curpos ;Restore Cursor
call Poscur
mov cx,cs:Curtyp
mov ah,1
int Video
;Set old keyboard and timer interrupts back.
mov ax,0 ;Set ds=0 (int area)
mov ds,ax
cli ;Disable interrupts
mov ax,cs:Oldoff8 ;Set old int 8
mov bx,cs:Oldseg8
mov cx,cs:Oldoff9 ;Set old int 9
mov dx,cs:Oldseg9
mov [32],ax
mov [34],bx
mov [36],cx
mov [38],dx
sti ;Enable ints
call Resetkbd ;Reset the keyboard
mov sp,bp
pop es,ds,di,si,dx,cx,bx,ax,bp ;Restore all for calling pgm
iret ;Return from interrupt

;Subroutines ---------------------------------------------------------
Poscur: mov ah,Setcur ;Set cursor video service
mov bh,Vpage ;Current video page
int Video ;Set cursor pos

Prompt: push ax,cx,es,di
mov ax,Vidmem ;Set es=Video segment
mov es,ax
mov di,Promptpos ;es:di=prompt pos
mov cx,18 ;18 words to move
rep movsw ;Move them to video mem
pop di,es,cx,ax

Getkey: mov ah,0 ;Wait for key Keyboard service
int 16h ;Do it

Resetkbd: in al,61h ;Get current control value
mov ah,al ;Save it in ah
or al,80h ;Set msb
out 61h,al ;Send it to control port
mov al,ah ;Get original value
out 61h,al ;Send it to control port
cli ;Disable ints
mov al,20h ;Send EOI value to 8259
out 20h,al
sti ;Enable ints

;Print the row of chars in the row buffer.
Printer: push ds
xor dx,dx ;Select LPT1
mov ds,cs ;Set ds this code
mov Timeval,36 ;Set a 2 second wait
G1: call Getstat ;Get printer status
cmp ah,90h ;OK?
je G3 ;Yes
cmp Timeval,0 ;Timed out?
jne G1 ;No
call PNR ;Print 'Printer not ready' prompt
mov Timeval,180 ;Set a 10 second wait
G2: call Getstat ;Get printer status
cmp ah,90h ;OK now?
je G8 ;Yes
cmp Timeval,0 ;Timed out?
jne G2 ;No
jmp Exit ;Yes, give up
G8: call PIB ;Put old screen back
G3: mov si,Rowbuf ;ds:si points to row buffer
mov cl,Col ;cx=Columns
mov ch,0
add cl,2 ;Add 2 for cr-lf at end
G4: lodsb ;Get a char from buffer
mov ah,0 ;Send char service
int 17h ;no, send to printer
test ah,10h ;Still selected?
je G7 ;No
loop G4 ;Yes, print next char
pop ds
G7: push si,cx ;Save position and count
mov Timeval,180 ;Set a 10 second timeout
call PNR ;Print 'Printer not ready'
G5: call Getstat ;Get printer status
test ah,10 ;Selected?
jne G6 ;Yes
cmp Timeval,0 ;Timed out?
jne G5 ;No
jmp Exit ;Yes, give up
G6: call PIB ;Put old screen back
pop cx,si ;Get old position and count
jmp G4 ;and continue printing

Getstat: mov ah,2
int 17h

PNR: push si
mov si,Msg3
PNR1: call Prompt
pop si

PIB: push si
mov si,Buffer
jmp PNR1

;Come here to install the program. ------------------------------------
Initialize: jmp short Init1
Msg4: db 13,10,'Selective Print Screen ver. 2.0 by Bob Montgomery'
db ' installed.',13,10,'$'
Init1: mov ah,Getvec
mov al,5
int DOS
mov [Oldoff5],bx
mov [Oldseg5],es
mov ah,Setvec
mov al,5
mov dx,Newint5
int DOS
mov dx,Msg4
mov ah,9
int DOS
mov dx,Initialize
int 27h

  3 Responses to “Category : Printer Utilities
Archive   : SPS20.ZIP
Filename : SPS.8

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: