Вы находитесь на странице: 1из 8

; EGRPRTSC - Graphics mode printscreen for EGA/TTL Monochrome to EPSON FX-80

;
; (c) 1986 KGRhoads - all rights reserved except as herein noted.
;
; PERMISSION IS GRANTED FOR NON-COMMERCIAL DISTRIBUTION OF SOURCE AND BINARY
; VERSIONS OF THIS PROGRAM. You are free to give away copies; but I am not
; allowing anyone to sell my programs for their profit.
;
; USAGE: this is resident program that "borrows" the PrtSc interrupt (INT 5)
; It is loaded once (usually in an AUTOEXEC.BAT), and does nothing unless
; the PrtSc function is invoked. When PrtSc is signalled, the program checks
; via BIOS INT 10H to see if the video mode is 0fH (15), which is the EGA
; graphics mode for TTL monochrome monitors. If that is the mode, it does
; a pixel by pixel dump to printer number 0, using the 80 dpi graphics mode
; of the EPSON FX-80. If the video mode is not 15, it calls the previous
; PrtSc routine.
;

code_seg segment
assume cs:code_seg,ds:code_seg,es:code_seg
org 0100h
;
entry_point proc near
jmp init
;
initstring db 27d,'@'
init_string db 27d,'#',27d,'A',8,27d,'O',10d,10d,13d
init_s_end db 13d
gr_codes db 27d,'*',4,128d,2
post_codes db 13d,0,10d,13d,0,0
def_mode db 27d,'0',27d,'!',8d,10d,13d
;
oldprtsc label dword
offprtsc dw 0
segprtsc dw 0
count dw 0
assume cs:code_seg,ds:nothing,es:abs_0
;
; PrtSc invoked -- test if already in progress before proceeding
prtsctst label near
; save registers
push es
push ax
; set up absolute 0 addressing in es
mov ax,0
mov es,ax
; get PrtSc indicator byte: 0=READY 1=GOING -1=ERROR
mov al,es:[indic]
cmp al,1 ;is one already going?
je tst_exit ;yes - exit
jmp isit_gr
;over all exit point turn off PrtSc indic, restore registers and leave
exit: mov dx,0
mov cx,11d
mov si,offset post_codes
call send_pr_string ;extra blank line at end
; then set print mode to 6 lines/inch; pica; emphasized & another blank line
cli ;disable interrupts
mov ax,0
mov es,ax
mov es:[indic],0
bye: pop di
pop si
pop ds
; exit for second test - is not graphics mode, call BIOS PrtSc
gr_exit: pop dx
pop cx
pop bx
; exit for first test - found PrtSc already going
tst_exit: pop ax
pop es
sti ;enable interrupts
iret
;
isit_gr label near
; NO PrtSc currently going - check which shift key
; if left shift key continue, if right shift key ignore
mov ah,2
int 16h
and al,2
jz tst_exit
; - check video mode
push bx ;save more registers
push cx
push dx
mov ah,0fh ;BIOS video - inquire
int 10h
cmp al,0fh ;vid mode in al, 0f=ega/mono graphics
jne do_ord ;not graphics - do ordinary
jmp do_gr ;is graphics - do that
;
do_ord: pushf ;simulate interrupt w/pushf long call
call dword ptr cs:[oldprtsc]
jmp gr_exit ; then leave
;
; set PrtSc indicator to in progress
do_gr: mov es:[indic],1
push ds ;save more registers
push si
push di
assume cs:code_seg,ds:code_seg,es:seg_a000
push cs ;set up addressing
pop ds ;ds for local data
mov ax,0a000h ;es for EGA video memory
mov es,ax
;
; ega/monochrome graphics PrtSc here
;
;first - set up prefix and postfix strings
mov ax,word ptr ds:[gr_codes]
mov word ptr ds:[pre],ax
mov ax,word ptr ds:[gr_codes+2]
mov word ptr ds:[pre+2],ax
mov al,byte ptr ds:[gr_codes+5]
mov byte ptr ds:[pre+5],al
;
mov ax,word ptr ds:[post_codes]
mov word ptr ds:[post],ax
mov ax,word ptr ds:[post_codes+2]
mov word ptr ds:[post+2],ax
mov al,byte ptr ds:[post_codes+5]
mov byte ptr ds:[post+5],al
;
;next - is there a printer? reset and test
mov dx,0
mov ah,1
int 17h
mov al,ah ;copy status
xor al,0b0h ;?no printer attached
jne pr_tst2
jmp error ;no printer
pr_tst2: mov al,ah
xor al,88h ;? printer not turned on
jne pr_tst3
jmp error ;printer not on
pr_tst3: mov al,ah
and al,20h ;?out of paper
je pr_init
jmp error ;out of paper
;
; next initialize printer settings
pr_init: mov dx,0 ;use printer 0
mov si,offset init_string ;prep printer init
mov cx,((offset init_s_end)-(offset init_string)-1)
call send_pr_string ;two blank lines before
;
; this is where the actual screen dumping starts
;
mov di,0 ;start at beginning of buffer
mov cx,43 ;43 and fraction lines on screen
mov count,cx
dump_loop: mov dx,0 ;using printer #0
call print_line ;convert and print a line
dec count ;did a line
jnz dump_loop ;still more left
mov si,offset buffer
call do_a_line ;get last (partial) line
mov si,offset buffer
mov al,0fch ;and mask out nonsense
mov cx,640d ;over all 640 bytes
last_loop: and ds:[si],al
inc si
dec cx
jnz last_loop ;loop if not done masking
call in_p_l
; mov si,offset pre
; mov cx,650d
; mov dx,0
; call send_pr_string
jmp exit ;when done go to exit
;
; if error set PrtSc error indicator
error: cli ;disable interrupts
mov ax,0
mov es,ax
assume cs:code_seg,ds:code_seg,es:abs_0
mov es:[indic],0ffh
jmp bye
assume cs:code_seg,ds:code_seg,es:seg_a000
;
send_pr_byte proc near
; byte in al, printer number (0 ..) in dx
push ax ;save byte to be printed
push cx ;save caller's cx
mov cx,0200h ;set retry count if minor errors
p_b_loop: mov ah,2 ; get printer status
int 17h
xor ah,90h ;reverse busy/not selected
and ah,0b9h ;remove ack. and unused
jz send_pr ;ok? -> send byte
mov al,ah ;get massaged status
test al,30h ;? out of paper/printer not selected
jnz p_b_err ;exit - error
test al,80h ;? printer busy
jnz p_b_loop ;try again w/o dec count
dec cx ;any other - dec count/try again
jz send_pr ; if count out - try send
jmp p_b_loop
send_pr: pop cx ;restore caller's cx
pop ax ;get byte back to al
mov ah,0 ;send byte fn code
int 17h ;do it
ret
p_b_err: pop cx ;fix stack - pop cx
pop ax ; pop ax
pop ax ; pop ip
jmp error ; error exit
send_pr_byte endp
;
send_pr_string proc near
;ds:[si] -> string, cx=length, dx = printer number ( 0)
send_pr_loop: mov al,byte ptr ds:[si]
push cx ;save char count
call send_pr_byte ;send a char
and ah,20h ;test for paper out
jz next_byte ;not out - do next
pop ax ;paper is out - error
pop ax
jmp error
next_byte: pop cx ;restore char count
inc si ;bump pointer upto next char
dec cx ;decrement counter
jnz send_pr_loop ;done?
ret ;yes
send_pr_string endp
;
; video ram is bit mapped by rows; printer needs data mapped by columns
; this routine rotates a bit from each of 8 video ram locations into a
; byte for the printer
do_a_byte proc near ;convert from screen buffer
stc ;one byte of printer data
mov al,0ffh ;reverses screen as it works
mov ds:[si],al
rcl byte ptr es:[di],1
jnc d_b_1
and byte ptr es:[di],0feh
stc
d_b_1: rcl byte ptr ds:[si],1
rcl byte ptr es:[di+80d],1
jnc d_b_2
and byte ptr es:[di+80d],0feh
stc
d_b_2: rcl byte ptr ds:[si],1
rcl byte ptr es:[di+160d],1
jnc d_b_3
and byte ptr es:[di+160d],0feh
stc
d_b_3: rcl byte ptr ds:[si],1
rcl byte ptr es:[di+240d],1
jnc d_b_4
and byte ptr es:[di+240d],0feh
stc
d_b_4: rcl byte ptr ds:[si],1
rcl byte ptr es:[di+320d],1
jnc d_b_5
and byte ptr es:[di+320d],0feh
stc
d_b_5: rcl byte ptr ds:[si],1
rcl byte ptr es:[di+400d],1
jnc d_b_6
and byte ptr es:[di+400d],0feh
stc
d_b_6: rcl byte ptr ds:[si],1
rcl byte ptr es:[di+480d],1
jnc d_b_7
and byte ptr es:[di+480d],0feh
stc
d_b_7: rcl byte ptr ds:[si],1
rcl byte ptr es:[di+560d],1
jnc d_b_8
and byte ptr es:[di+560d],0feh
stc
d_b_8: rcl byte ptr ds:[si],1
ret
do_a_byte endp
;
do_8_bytes proc near
; turns 8 bytes in a column in the video ram into the equivalent 8 bytes
; in a row in the printer buffer
mov cl,8
do_8_loop: call do_a_byte
inc si
dec cl
jnz do_8_loop
ret
do_8_bytes endp
;
;converts one printer line's worth of data, from 8 pixel cols by 640 pixel
;rows on screen, routines called by this reverse screen as they process -
;so this reverses it back when done - THUS THE AREA OF SCREEN BEING SENT TO
;THE PRINTER "FLASHES" BRIEFLY
do_a_line proc near
mov ch,80d
do_line_loop: call do_8_bytes
inc di
dec ch
jnz do_line_loop
sub di,80d
mov cx,640d
reset_line_loop: not byte ptr es:[di]
inc di
dec cx
jnz reset_line_loop
ret
do_a_line endp
;
;this routine calls do_a_line above to convert 1 line of data
;looks through the data to see if only a partial line is needed
;and then calls send_pr_string to print it out
print_line proc near
mov si,offset buffer ;point si at pr buffer
call do_a_line ;and convert 1 line
in_p_l: mov si,(offset post)-1 ;start at end of line
mov cx,640d ;set count = line length
p_l_loop: cmp byte ptr ds:[si],0 ;?nothing to print
jnz p_l_doit ;is something - go print
dec si ;still nothing, step back
dec cx ;decrement length
jnz p_l_loop ;?len>0 - yes loop back
jmp new_line ;no - no data on line
p_l_doit: mov ax,cx ;printer wants byte count in form
mov dx,0 ;remainder,quotient after div 256
mov bx,256d ;so we do div to get them
div bx
mov quot,al ;and plug into prefix string
mov rem,dl
mov dx,0
mov si,offset pre
add cx,5d
call send_pr_string ;then send prefix and data to printer
new_line: mov si,offset post ;then send line feed/carriage return
mov cx,4d
call send_pr_string
ret
print_line endp
;
; the print buffer
pre label byte ;prefix string here, set graphic mode
db 27d,'*',4 ;80 dots/inch mode
rem db 128d ;data count/256 remainder
quot db 2 ;data count/256 quotient
buffer label byte ;full screen has 640 pixels
db 640d dup (0) ;sending 8 cols of pixels at a time
post label byte
db 13d,0,10d,13d,0,0
;
;
; initialization code - borrow INT 5 vector & save old vector
assume cs:code_seg,ds:code_seg,es:code_seg
INIT label near
;set up absolute 0 segment addressing via es
mov ax,0
mov es,ax
mov ax,word ptr es:[16h]
cmp ax,0f000h
jne not_bios
; replace IBM BIOS PrtSc with EGA BIOS PrtSc, unless already done
mov ax,1200h
mov bx,20h
int 10h
not_bios label near
; get and save offset portion of old PrtSc vector
mov ax,word ptr es:[prtscoff]
mov cs:[offprtsc],ax
; get and save segment portion of old PrtSc vector
mov ax,word ptr es:[prtscseg]
mov cs:[segprtsc],ax
; disable interrupts while changing vector
cli ;disable interrupts
; change offset portion of PrtSc vector
mov ax,offset prtsctst
mov es:[prtscoff],ax
; change segment portion of PrtSc vector
mov ax,cs
mov es:[prtscseg],ax
xor al,al
; set PrtSc indicator byte in low core to READY
mov es:[indic],al
; tell DOS to save all code upto init
mov dx,offset init
; re-enable interrupts
sti ;enable interrupts
; bye bye!
int 27h
;
entry_point endp
;
;
code_seg ends
;
abs_0 segment at 0 ;low core segment
;this does not generate code -- is just present to establish addressing
org 20d
prtsc label dword ;PrtSc interrupt vector
prtscoff dw ? ; offset
prtscseg label word ; segment
org 500h
indic label byte ;PrtSc indicator byte
abs_0 ends
;
seg_a000 segment at 0a000H ;EGA video ram segment
;this does not generate code -- is just present to establish addressing
org 0
gr_buf label byte
seg_a000 ends
;
end entry_point

Вам также может понравиться