home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programming
/
powerprogramming1994.iso
/
progtool
/
ega
/
egaepsn1.arc
/
EPSON.ASM
next >
Wrap
Assembly Source File
|
1989-10-28
|
15KB
|
579 lines
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