home *** CD-ROM | disk | FTP | other *** search
- page 60,132
- title Graphics Module for Print Screen with the EGA
- Epson segment para public 'code'
- assume CS:Epson,DS:Epson,ES:Epson
-
- comment #
-
- This routine is for public domain for those of you who bought an
- EGA and enhanced monitor and determined that you could no longer
- do a Shf_Prt_Scn in mode 10h (16). If you have an IBM compatible
- and an Epson FX series printer then this routine will replace the
- Graphics.com routine. I also have routines for Radio Shack DMP
- printers with 8 pins (but only 7 usable for graphics) and for HP
- LaserJet printers when used with an EGA. Enjoy...
-
- Dr. R. Brooks Van Horn, Jr.
- 701 Fall Place
- Herndon, VA. 22070
-
- Toad Hall tweak:
- Made "proper" near and far procedures so this would
- compile under MASM 5.0
- (Kept getting an "IP NOT 0" error when converting from
- .EXE to .COM.)
- Tabified, formatted to a "proper" .ASM file.
-
- Original .COM program was weird .. had an extra 100 bytes
- of miscellaneous code at the end (some sort of compiled
- C math routines from the looks of it). Suspicion was
- a virus appended to original code, but no such thing.
- Dr Van Horn has a VERY weird compiler/linker/exe2bin
- package!
- So .. I just recompiled with MASM .. and got the same
- size as his (with the garbage stripped off the end).
- What we have now is a clean EPSON.COM and source that'll
- compile, link, etc. with MASM, LINK, and several EXE2COM
- converters.
-
- This code is in MAJOR need of a rewrite. Almost ALL the
- segment overrides are unnecessary, and more.
- I'm almost done with a rewrite, but (1) I can't test it
- (no EGA card or graphics printer) and (2) My hack broke
- the code! Maybe one of these days.
-
- David Kirschbaum
- Toad Hall
- kirsch@arsocomvax.socom.mil
- #
-
- CSEG SEGMENT PUBLIC PARA 'CODE'
- ASSUME CS:CSEG, DS:CSEG, ES:CSEG
-
- ORG 100H
-
- Epson proc near
- jmp Setup
-
- Mlen db 'EGA Graphics Ver 1.0'
- Cmp_Str dw $-mlen
- Epson endp
-
- ; normal int 5 entry point
-
- Begin proc far
- pushf ; enable further interrupts
- push ax
- push bx
- push bp
- push di
- push si
- mov ah,15 ; setup a function call to dos to
- int 10h ; get the video mode
- and ax,007fh ; mask off unwanted data
- mov CS:[mode],ax ; and save it for future use
- cmp al,7 ; is this a mono card?
- jz Go_Out ; yes, exit - when in text mode
- cmp al,3 ; see if we are in the graphics mode?
- jg Cont ; yes, go around using dos
- Go_Out: pop si ; restore the registers saved
- pop di
- pop bp
- pop bx
- pop ax
- popf
- ;----- jump far to Dos
- db 0EAh ; jump far segment to Print
- dos dw 0 ; offset of jump
- dos2 dw 0 ; segment of jump
-
- Cont: push cx ; and save all the registers
- push dx
- push DS
- push ES
- push CS ; now put code seg register into
- pop ES ; the extra segment register
- xor ax,ax
- mov DS,ax
- inc al ; see if we are already being done
- mov al,Byte Ptr DS:[500h] ; get the current mode and also set it
- or al,al
- jnz Getout ; if 550h was not zero then exit
- push CS
- pop DS
- xchg al,Byte Ptr CS:switch
- or al,al
- jnz GetOut
- sti
- mov CS:[sp_save],sp
- jmp Process
-
- Return: mov si,Offset restore
- mov cl,CS:[si] ; get number of bytes to print
- xor ch,ch
- inc si
- call Tabptr ; restore printer to original state
- Exit: mov sp,CS:[sp_save]
- xor ax,ax
- mov Byte Ptr CS:switch,al ; set value to zero
- Getout: pop ES ; restore registers and exit
- pop DS
- pop dx
- pop cx
- pop si
- pop di
- pop bp
- pop bx
- pop ax
- popf
- sti
- iret ; bye...............
- Begin endp
-
- ;--------------------------------------------------------------------
- ; Epson FX Printer with IBM-PC
- ;--------------------------------------------------------------------
- line_sp db 3,27,51,24 ; Control Codes for 24/216" line spacing
- set_graf db 4,27,76 ; Cntrl Code for each graphics line printed
- col_2_do dw 0 ; last column number to be printed
- restore db 2,27,48,12 ; change count to 3 if you want a form feed
-
- line_buf db 960 dup (?) ; line buffer
- eight dw 8
- four dw 4
- switch db 0
- sp_save dw 0
- mode dw 0 ; Current Video Mode
- rows dw 0 ; Number of rows for this mode
- cols dw 0 ; Number of columns for this mode
-
- ; Modes = 4 5 6 7 8 9 A B C D E F 10
- col_mode dw 320,320,640, 0, 0,320,640, 0,720,320,640,640,640
- row_mode dw 200,200,200, 0, 0,200,200, 0,348,200,200,350,350
-
- ;--------------------------------------------------------------------
-
- ; Print a Table of Control Values
- ; ===============================
- ;
- Tabptr proc near
- mov al,CS:[si]
- call Printer
- inc si
- loop Tabptr
- nop
- ret
- Tabptr endp
-
- ;
- ; Send an alarm bell sound
- ; ========================
- ;
- Bell proc near
- mov al,7
- mov ah,14
- int 10h
- ret
- Bell endp
-
- ; Send the character in AL to the printer
- ; =======================================
- ;
- Printer proc near
- push dx
- sub dx,dx
- xor ah,ah
- int 17h
- pop dx
- test ah,25h
- jnz Error
- ret
- Printer endp
-
- ;
- ; Error returns on printer commands
- ; =================================
- ;
- Error proc near
- call Bell
- call Bell
- jmp Exit
- Error endp
- ;
- ; Send a form feed to the Printer
- ; ===============================
- ;
- Cr_Lf proc near
- push dx
- sub dx,dx
- mov ax,0dh
- int 17h
- mov ax,0ah
- int 17h
- pop dx
- test ah,25h
- jnz Error
- ret
- Cr_Lf endp
-
- ;---------------------------------------------------------------------
- ;
- ; Graphics Processing Section
- ;
- ;---------------------------------------------------------------------
-
- Process proc near
- mov bp,CS:[mode]
- sub bp,4
- sal bp,1
-
- mov ax,CS:row_mode[bp] ; save rows-1 and cols-1
- dec ax
- mov CS:rows,ax
- mov ax,CS:col_mode[bp]
- dec ax
- mov CS:cols,ax
-
- mov ah,1 ; initialize the printer
- xor dx,dx
- int 17h
-
- mov si,Offset CS:line_sp ; setup for correct interline spacing
- mov cl,CS:[si] ; get length
- xor ch,ch
- inc si
- call TabPtr
-
- mov ax,CS:[cols] ; decide to do graphics by row or column mode
- cmp ax,320
- jg By_Rows
- jmp By_Cols
-
- ;--------------------------------------------------------------------
- ; for By_Rows calls we have usually 640 x 200 type, so do 200
- ; across and 640 down the page. This means that we can only
- ; single dot to get lines to connect on the printer paper.
- ;--------------------------------------------------------------------
-
- By_Rows: mov cx,0 ; start the column index at zero
-
- Br_Strt:
- push cx ; save the current column index
- mov dx,CS:[rows] ; initialize the row count to max
- mov bh,Byte Ptr CS:[eight]
- xor si,si ; max characters to print
- mov CS:[col_2_do],si
- mov di,Offset CS:line_buf
- xor bl,bl
-
- ; do for a count of 'Eight'
-
- Br_Cont:
- call Read ; read the next dot at (row,col)
- and al,07fh ; check if any thing is there
- jz Br_Fill ; and skip if nothing there
- mov al,1 ; else fill the byte
- Br_Fill: shl bl,1 ; move reg left one bit
- or bl,al ; and or in the next value
- inc cx ; increment the column count
- dec bh ; and the loop index
- jnz Br_Cont ; continue loop for 8 times
-
- ; undo
-
- add si,2 ; add two to the column counter
- mov Byte Ptr CS:[di],bl ; save filled byte
- mov Byte Ptr CS:[di+1],bl ; twice for filling
- cmp CS:[rows],199 ; check for less than 200 rows
- jg Br_Two
- mov Byte Ptr CS:[di+2],bl ; and 3 times for low resolution
- inc di
- inc si
- Br_Two: add di,2 ; up the buffer ptr
- or bl,bl ; do we have anything to print?
- jz Br_Skp ; no, skip
-
- mov CS:[col_2_do],si ; save index
-
- Br_Skp: mov bh,Byte Ptr CS:[eight] ; set loop for 8 more cols per row
- dec dx ; delete one from the row index
- pop cx ; restore the column count
- push cx ; and save it again for this row
- cmp dx,0 ; and test to see if we are finished
- jge Br_Cont ; loop
-
- mov cx,CS:[col_2_do] ; get the number of bytes to print
- or cx,cx
- jz Br_NoP ; skip if didn't get anything
-
- push cx ; save number to do
- mov si,Offset CS:set_graf ; setup for graphics
- mov cl,CS:[si] ; get length
- xor ch,ch
- inc si ; point past length field
- call TabPtr ; perform the setup
- pop cx ; now get the real characters to do
- mov si,Offset CS:line_buf ; get print line pointer
- call TabPtr ; and print the line
-
- Br_NoP: call Cr_Lf ; do carriage return and line feed at end
-
- pop cx
- add cx,CS:[eight] ; add 8 to column count
- cmp cx,CS:[cols] ; compare to max to do
-
- jg Br_Ret
- jmp Br_Strt ; continue until fini
-
- Br_Ret: jmp Return ; restore printer and exit
-
- ;--------------------------------------------------------------------
- ; for By_Cols calls we have usually 320 x 200 type, so do 320
- ; across and 200 down the page. This means that we must double
- ; dot to get lines to connect on the printer paper.
- ;--------------------------------------------------------------------
-
- By_Cols: mov dx,0 ; start the row index at zero
-
- ; for each row do all the columns
- Bc_Strt:
- push dx ; save the current row index
- mov cx,0 ; initialize the col count to start
- mov bh,Byte Ptr CS:[four]
- xor si,si ; max characters to print
- mov CS:[col_2_do],si
- mov di,Offset CS:line_buf
-
- ; for each column in the row, do
- Bc_Cont:
- call Read ; read the next dot at (row,col)
- and al,07fh ; check if any thing is there
- jz Bc_Fill ; and skip if nothing there
- mov al,3 ; else fill the byte from the bottom
- Bc_Fill:
- shl bl,1 ; move reg left one bit
- shl bl,1 ; and repeat
- or bl,al ; and 'or' in the next value
- inc dx ; increment the row count
- dec bh ; and the loop index
- jnz Bc_Cont ; continue loop for 4 times
-
- add si,3 ; add three to the column counter
- mov Byte Ptr CS:[di],bl ; save filled byte
- mov Byte Ptr CS:[di+1],bl ; twice for filling
- mov Byte Ptr CS:[di+2],bl ; and three times for a lady
- add di,3 ; up the buffer ptr
- or bl,bl ; see if anything is there
- jz Bc_Skp ; skip if we have nothing to plot
-
- mov CS:[col_2_do],si ; save index
-
- Bc_Skp: mov bh,Byte Ptr CS:[four] ; set loop for 8 more cols per row
- inc cx ; add one to the col index
- pop dx ; restore the row count
- push dx ; and save it again for this row
- cmp cx,CS:[cols] ; and test to see if we are finished
- jle Bc_Cont ; loop
-
- mov cx,CS:[col_2_do] ; get the number of bytes to print
- or cx,cx
- jz Bc_NoP ; skip if didn't get anything
-
- push cx ; save number to do
- mov si,Offset CS:set_graf ; setup for graphics
- mov cl,CS:[si] ; get length
- xor ch,ch
- inc si ; point past length field
- call TabPtr ; perform the setup
-
- pop cx ; now get the real characters to do
- mov si,Offset CS:line_buf ; get print line pointer
- call TabPtr ; print the line
-
- Bc_NoP: call Cr_Lf
-
- pop dx
- add dx,CS:[four] ; add to column count
- cmp dx,CS:[rows] ; compare to max to do
-
- jg Bc_Ret ; if fini then exit
- jmp Bc_Strt ; else go do next row
-
- Bc_Ret: jmp Return ; restore printer and exit
-
- Process endp
-
- ;--------------------------------------------------------------------
- ;
- ; Read Dot Routine Using DOS/BIOS or VDI interface for int 10h
- ;
- ;-------------------------------------------------------------------
- Read proc near
- xor al,al
- cmp dx,0 ; see if all is ok
- jl Read_Ret
- cmp cx,CS:[cols] ; also check on overdoing it
- jg Read_Ret
- cmp CS:[mode],10h
- je Read_Dot ; if mode = 10 then do special I/O
-
- mov ah,13
- push bx
- push cx
- push dx
- int 10h
- pop dx
- pop cx
- pop bx
- xor ah,ah ; clear the high byte for testing
- Read_Ret:
- ret
-
- ;---------------------------------------------------------------
- ;
- ; Read a Pixel (Dot) from the EGA using Read Mode 0
- ;
- ;----------------------------------------------------------------
-
- Read_Dot: push bx
- push cx
- push dx
- mov ax,dx ; save column value
- mov bx,cx ; and row value
- mov dx,0a000h ; Video ram address
- mov DS,dx ; into segment register
- mov dx,80
- mul dx ; column * 80
- shr bx,1
- shr bx,1
- shr bx,1 ; row / 8
- add bx,ax ; actual data byte address
- and cl,7 ; row mod 8
- xor cl,7 ; bit mask 7 - (row mod 8)
- mov ch,1
- shl ch,cl ; 2^mask
- mov ah,3 ; initialize bit plane number
- Plane_Loop:
- mov dx,03CEh ; EGA Controller
- mov al,4 ; map select register
- out dx,al
- mov dx,03CFh ; data register
- mov al,ah ; select bit planes 3,2,1,0
- out dx,al
- mov al,DS:[bx] ; read bit plane
- shl cl,1
- and al,ch
- jz Not_On
- or cl,1
- Not_On: dec ah
- jge Plane_Loop
-
- and cl,0fh
- mov al,cl
- pop dx
- pop cx
- pop bx
- ret
- Read endp
-
- dw -1 ; fense
-
- ;--------------------------------------------------------------------
- ;
- ; Initialization Routine for Graphics.Com
- ;
- ;--------------------------------------------------------------------
- Setup proc near
- xor ax,ax
- mov ES,ax ; setup to address segment zero
- mov cx,ES:[0016h] ; get current segment
- mov bx,ES:[0014h] ; and offset
- mov DS,cx ; make that the data segment
- mov cx,CS:[Cmp_Str] ; setup to check bytes for same
- mov si,Offset CS:mlen ; data field "Graphic..."
- mov bx,si
-
- Check: mov ax,CS:[si] ; get a byte in accum
- cmp ax,DS:[bx] ;is it the same
- jne Ok ; no, then we are ok
- inc si ; otherwise, increment pointers
- inc bx ; to both fields
- loop Check ; and loop for 7 checks
-
- mov ax,CS
- mov DS,ax
- mov ah,09h
- mov dx,Offset Message1
- int 21h
- int 20h ; if same then don't overlay but exit
-
- Ok: mov bx,ES:[0014h] ; get the current offset in int vector
- mov ax,CS ; now setup to display a message
- mov DS,ax
- mov Word Ptr dos,bx ; and save it locally
- mov bx,ES:[0016h] ; get the segment location of item too
- mov Word Ptr dos2,bx ; and save it also
- mov ax,CS ; save our entry at int vector
- mov ES:[0016h],ax ; segment
- mov bx,Offset CS:Begin ; define entry point to routine
- mov ES:[0014h],bx ; offset
- mov di,Offset Field1
- call Convert ; convert starting address
- mov di,Offset Field2
- mov bx,Offset Setup
- add bx,15 ; convert to next paragraph addr
- mov cl,4
- shr bx,cl
- add ax,bx
- call Convert ; and the new ending address
- mov ah,09h ; now do our message
- mov dx,Offset Message2
- int 21h
- mov dx,Offset CS:Setup
- int 27h ; terminate but stay resident
- Setup endp
-
- Convert proc near
- ;
- ; ax = number to be converted
- ; di = address of field in which to put the hex characters
- ;
- push ax
- push bx
- push cx
- push dx
- lea bx,Ascii
- mov cl,4
- mov dx,ax
- mov al,ah
- shr al,cl
- xlat Ascii
- mov Byte Ptr CS:[di],al
- mov al,dh
- and al,0fh
- xlat Ascii
- mov Byte Ptr CS:[di+1],al
- mov al,dl
- shr al,cl
- xlat Ascii
- mov Byte Ptr CS:[di+2],al
- mov al,dl
- and al,0fh
- xlat Ascii
- mov Byte Ptr CS:[di+3],al
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- Convert endp
-
- Message1 db 'EGA Graphics routine is already resident',13,10,'$'
- Message2 db 'EGA Graphics routine is now resident ('
- Field1 db '0000-'
- Field2 db '0000)',13,10,'$'
- Ascii db '0123456789abcdef'
-
- CSEG ENDS
- END Epson