Category : Printer Utilities
Archive   : EGASCN.ZIP
Filename : DMP200.ASM
Output of file : DMP200.ASM contained in archive : EGASCN.ZIP
title Graphics Module for Print Screen with the EGA
Dmp200 segment para public 'code'
assume cs:Dmp200,ds:Dmp200,es:Dmp200
org 100h
jmp Setup
Mlen db 'Graphics 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
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 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
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...............
;--------------------------------------------------------------------
; Radio Shack DMP-200 Printer with IBM-PC
;--------------------------------------------------------------------
Line_Sp db 7,27,20,18,27,16,0,0
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
; 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
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],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
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
mov ax,cs
mov ds,ax
mov ah,09h
mov dx,Offset Message1
int 21h
int 20h ; if same then dont 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
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 'Graphics routine is already resident',13,10,'$'
Message2 db 'Graphics routine is now resident ('
Field1 db '0000-'
Field2 db '0000)',13,10,'$'
Ascii db '0123456789abcdef'
Dmp200 ends
end
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/