home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
archives
/
mskermit.zip
/
mspdmp.asm
< prev
next >
Wrap
Assembly Source File
|
1990-06-19
|
15KB
|
527 lines
page 60,132
title Graphics Module for Print Screen with the EGA
Dmp200 segment para public 'code'
assume cs:Dmp200,ds:Dmp200,es:Dmp200
Comment #
This routine was written by Dr. R.Brooks Van Horn, Jr. to fill a void
left by Big Blue when their support for the EGA never arrived. This
routine will perform the Shift Print Screen function for a Radio Shack
DMP200 printer. I also have an Epson (IBM Printer) version and an EGA
Mode 16 driver to supplement EGA BIOS versions that like IBM's do not
support a read/write mode 16 (10H) interupt.
#
org 100h
jmp Setup
Mlen db 'EGA Print Screen Version 2.0'
Cmp_Str dw $-mlen
; normal int 5 entry point
Begin: pushf ; enable further interrupts
push ax
push bx
push bp
push di
push si
push ds
xor ax,ax
mov ds,ax
mov al,Byte Ptr ds:[449h] ; get the video mode
pop ds ; restore data set register
and al,07fh ; mask off any unwanted data
mov cs:[Mode],ax ; and save it for future use
cmp al,7 ; is this a mono card?
jz Outz ; yes, exit - when in text mode
cmp al,3 ; see if we are in the graphics mode?
jg cont ; yes, go around using dos
Outz: 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 printer status
or al,al
jnz Getout ; if 500h 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...............
;--------------------------------------------------------------------
; Radio Shack DMP-200 Printer with PC or AT
;--------------------------------------------------------------------
; set graphics mode, condensed, 8 CRs, and tab to pos 45 to print
Line_Sp db 11,27,20,18,10,10,10,10,10,10,10,10,27,16,0,45
NofByte dw 0 ; total number of columns required
Restore db 6,30,27,18,27,31,12
Line_Buf db 800 dup (?) ; line buffer
Col_2_Do dw 0 ; column being printed
Eight dw 7
Four dw 4
Switch db 0
Sp_Save dw 0
Temp db 0,0
save_bp dw 0
; Modes = 4 5 6 7 8 9 A B C D E F 10 11 12 13
Col_Mode dw 320,320,640, 0, 0,320,640, 0,720,320,640,640,640,640,640,350
Row_Mode dw 200,200,200, 0, 0,200,200, 0,348,200,200,350,350,480,480,320
Mode dw 0 ; Current Video Mode
Rows dw 0 ; Number of rows for this mode
Cols dw 0 ; Number of columns for this mode
;--------------------------------------------------------------------
;
; Print a Table of Control Values
; ===============================
;
Tabptr: mov al,cs:[si]
call Printer
inc si
loop Tabptr
nop
ret
;
; Send an alarm bell sound
; ========================
;
Bell: mov al,7
mov ah,14
int 10h
ret
; Send the character in AL to the printer
; =======================================
;
Printer: push dx
sub dx,dx
xor ah,ah
int 17h
pop dx
test ah,25h
jnz Error
ret
;
; Error returns on printer commands
; =================================
;
Error: call Bell
call Bell
jmp Exit
;
; Send a form feed to the Printer
; ===============================
;
Cr_Lf: push dx
sub dx,dx
mov ax,0dh
int 17h
mov ax,0ah
int 17h
pop dx
test ah,25h
jnz Error
ret
;---------------------------------------------------------------------
; l
; Graphics Processing Section l
; l
;---------------------------------------------------------------------
Process: 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 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,40h ; else fill the byte
Br_Fill: shr 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
or bl,80h ; turn on the high order bit
mov Byte Ptr cs:[di],bl ; save filled byte
mov Byte Ptr cs:[di+1],bl ; twice for filling
cmp cs:[Rows],199
jg Br_Two
mov Byte Ptr cs:[di+2],bl
inc di
inc si
Br_Two: add di,2 ; up the buffer ptr
and bl,7fh
jz Br_Skp
mov Word Ptr 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
xor bl,bl
cmp dx,0 ; and test to see if we are finished
jge Br_Cont ; loop
mov si,Offset Line_Buf ; get print line pointer
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
call TabPtr ; print the line
Br_NoP: call Cr_Lf
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
mov cx,799 ; clear the buffer
mov di,Offset cs:Line_Buf
cld
mov ax,0
mov Word Ptr cs:[Temp],ax
push cs
pop es
rep stosb
; 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]
mov cs:[Temp],bh
xor si,si ; max characters to print
mov cs:[Col_2_Do],si
mov di,Offset Line_Buf
; for each column in the row, do
Bc_Pick: mov bl,cs:[di] ; get the last value
mov al,cs:[Temp] ; and see if this is a four or three count
shr al,1
shl al,1
cmp al,cs:[Temp] ; if even then use four
je Bc_Cont
dec bh ; otherwise use three
mov cs:[Temp],bh
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,60h ; else fill the byte
Bc_Fill: shr bl,1 ; move reg left one bit
shr 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,2 ; add two to the column counter
or bl,80h ; turn on the high order bit
mov Byte Ptr cs:[di],bl ; save filled byte
mov Byte Ptr cs:[di+1],bl ; twice for filling
add di,2 ; up the buffer ptr
and bl,7fh
jz Bc_Skp
mov Word Ptr cs:[Col_2_Do],si ; save index
Bc_Skp: mov bh,cs:[Temp] ; set loop for 8 more cols per row
mov bl,cs:[di] ; get the last value
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_Pick ; loop
mov bp,Word Ptr cs:[Temp] ; save the current Temp setting
xor Byte Ptr cs:[Temp],7
mov si,Offset Line_Buf ; get print line pointer
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
call TabPtr ; print the line
Bc_NoP: call Cr_Lf
pop dx
add dx,bp ; 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
;--------------------------------------------------------------------
;
; Read Dot Routine Using DOS/BIOS or VDI interface for int 10h
;
;-------------------------------------------------------------------
Read: 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],6
jg Read_Dot
mov ah,13
push bx
push cx
push dx
mov cs:[save_bp],bp
int 10h ; let BIOS read the dots
mov bp,cs:[save_bp]
pop dx
pop cx
pop bx
xor ah,ah ; clear the high byte for testing
Read_Ret: ret
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
dw -1 ; fense
;--------------------------------------------------------------------
;
; Initialization Routine for Graphics.Com
;
;--------------------------------------------------------------------
Setup: 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
; Bad news, it is already resident
push cs ; now setup to display a message
pop ds
mov ax,es:[0016h] ; get current segment address
mov di,Offset Field3
call Convert
add di,5 ; increase pointer to next field
mov ax,es:[0014h] ; and the offset address
call Convert
mov ax,cs
mov ds,ax
mov ah,09h
mov dx,Offset Message1 ; setup to display message
int 21h
int 20h ; if same then dont overlay but exit
; Good News, make DMP200 resident and display location message
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
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 'DMP200 Graphics routine is already resident ('
Field3 db '0000-0000)',13,10,'$'
Message2 db 'DMP200 Graphics routine is now resident ('
Field1 db '0000-'
Field2 db '0000)',13,10,'$'
Ascii db '0123456789abcdef'
Dmp200 ends
end