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