jeff@ducall.UUCP (01/24/87)
[] With more EGA high-res programs, and more high-res laser and dot matrix printers, the request has come to the net for a screen print utility that will dump such graphics onto such printers. I am herewith posting PrtSc.asm, a utility I wrote about six months ago. The code explains the program fairly well. In short, PrtSc is a memory resident utility that should be executed by the autoexec.bat file. Once loaded it supports either the Toshiba P351 or Hewlett-Packard LaserJet printers. It will print bold for high intensity characters, underlines for underlined characters, and italics (if available) for reverse video. It will also dump high resolution graphics screens in an appropriate resolution. Although low resolution support is not included, the hooks are present to add these routines. This program is now in the public domain, so please enjoy it. ================== CUT HERE ================================== #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # prtsc.asm # This archive created: Fri Jan 23 22:07:00 1987 export PATH; PATH=/bin:$PATH if test -f 'prtsc.asm' then echo shar: will not over-write existing file "'prtsc.asm'" else sed 's/^#//' << \FUNKY_STUFF > 'prtsc.asm' #; *********************************************************** #; #; PRTSC.ASM #; #; #; Jeffrey William Gillette #; Humanities Computing Center #; 104 Languages Building #; Duke University #; Durham, NC 27706 #; #; #; PrtSc is a memory resident program that replaces the normal #; IBM PC PrtSc interrupt (int 5). It correctly replaces IBM #; "extended ASCII" European characters with ISO European characters #; used by the Toshiba P351 and the Hewlett-Packard LaserJet #; printers. #; #; PrtSc supports the following screen attributes: bold, underline #; and reverse video (italic). #; #; PrtSc supports normal text and enhanced graphics modes. Note #; that hooks are in place for low resolution graphics, but these #; are not implemented at present. # #DEBUG equ 0 ; run as process (1) or tsr utility (0). # #TOSHIBA equ 1 #LASERJET equ 0 #PRINTER equ LASERJET ; set to either TOSHIBA or LASERJET # #_TEXT segment public byte 'CODE' # assume cs:_TEXT,ds:_DATA,ss:_STACK # #sseg dw 0 ; stack segment #sst dw 0 ; stack pointer #pseg dw 0 ; stack segment for prtsc #pst dw 0 ; stack segment for prtsc # #int5 proc near # mov cs:sseg,ss ; save stack and stack pointer # mov cs:sst,sp # # mov ax,_STACK # mov ss,ax # mov ax,offset top # mov sp,ax # # mov ss,cs:pseg # mov sp,cs:pst # # push es # push ds # push si # push di # push bp # push dx # push cx # push bx # push ax # # mov ax,_DATA # mov ds,ax # # ; jump to appropriate procedure # mov ah,0fh # int 10h ; get current video mode # xor ah,ah # shl ax,1 ; x 2 bytes per word # mov bx,modes ; offset for base # add bx,ax ; plus video mode # call [bx] ; call procedure # # pop ax # pop bx # pop cx # pop dx # pop bp # pop di # pop si # pop ds # pop es # mov ss,cs:sseg # mov sp,cs:sst #IF DEBUG # ret #ELSE # iret #ENDIF #int5 endp # #; set video segment for mono #mono proc near # mov ax,0b000h # mov es,ax # jmp text #mono endp # #; set video segment for color #color proc near # mov ax,0b800h # mov es,ax # jmp text #color endp # # #; ------------------------------------------------------------------ #; #; TEXT MODE ROUTINES #; #; ------------------------------------------------------------------ #; #text proc near # ; first initialize the printer # mov di,offset init # call p2 # # ; next set up the transfer # mov cx,25 # xor si,si # xor bx,bx # #t0: push cx ; do one row # mov cx,80 #t1: push cx # mov dx,es:[si] # # ; check attribute to see if it has changed # mov bl,dh # and bl,7fh ; mask out high bit # mov al,[offset attributes + bx] # cmp al,att # jz t4 # # ; change of attribute # mov ah,al ; save new attribute # xor al,att ; al now shows which functions need changing # mov att,ah ; save new attribute # # test al,8 ; bold # jz t2 # mov di,prtptr ; turn on bold # test ah,8 # jnz t1a # mov di,prtptr + 2 ; turn off bold #t1a: push ax # push dx # call p2 # pop dx # pop ax # #t2: test al,4 ; italic (reverse video) # jz t3 # mov di,prtptr + 4 ; turn on italic # test ah,4 # jnz t2a # mov di,prtptr + 6 ; turn off italic #t2a: push ax # push dx # call p2 # pop dx # pop ax # #t3: test al,2 ; underline # jz t4 # mov di,prtptr + 8 ; turn on underline # test ah,2 # jnz t3a # mov di,prtptr + 10 ; turn off underline #t3a: push dx # call p2 # pop dx # #t4: ; print the character # mov bl,dl # mov al,[ttrans + bx] ; get character to print from table # or al,al # jz t8 ; '\0' means go to special table # xor ah,ah # xor dx,dx # int 17h # #t5: add si,2 # pop cx # loop t1 ; next character # # mov di,offset crlf ; end of line # call p2 # pop cx # loop t6 ; do next line # # ; finally do an ending init # mov di,offset endit # call p2 # ret # #t6: jmp t0 ; kludge to handle long size jump # #t8: ; look up character in special table # push si # mov si,offset tspec - 4 #t8a: add si,4 # cmp word ptr [si],0 # jz t8b ; end of table - return # cmp [si],dl # jnz t8a ; loop till found # # add si,2 # mov di,[si] ; get address of string to send # call p2 ; to the printer. #t8b: pop si # jmp t5 # #text endp # #; ------------------------------------------------------------------ #; #; TOSHIBA GRAPHICS ROUTINES #; #; ------------------------------------------------------------------ # #; graphics a - 320x200 graphics print #tosgrfa proc near # ret #tosgrfa endp # #; graphics b - 640x200 graphics print #tosgrfb proc near # ret #tosgrfb endp # #; graphics c - 640x350 graphics print #tosgrfc proc near # ; set video segment to extended graphics # mov ax,0a000h # mov es,ax # # ; initialize the printer # mov di,offset gcinit # call p2 # # ; setup 30 iterations # mov cx,30 ; cx = count of iterations # mov bp,0 ; bx = base row for iteration # #gc1: ; line loop # mov di,offset gcline # call p2 # # ; do for 640 columns # push cx # mov cx,640 # xor bx,bx # #gc2: ; compute byte offset within memory # mov si,bx # shr si,1 # shr si,1 # shr si,1 ; column / 8 = byte offset # add si,bp ; add in row number # # ; compute bit mask # push cx # mov cl,bl # and cl,7 ; last three bits is bit offset # mov ah,80h # shr ah,cl # # ; four bytes per pass # mov cx,4 # mov di, offset gchold ; to store bitmaps # #gc3: ; do 12 pixels # push cx # mov cx,3 ; do 3 pixels per byte # xor dx,dx ; blank dx # #gc4: shl dl,1 ; shift dl left # mov al,ah ; put copy of bit mask in al # and al,es:[si] ; check [si] # jz gc5 ; is bit on? # inc dl ; if yes turn on bit for printer # shl dl,1 ; twice # inc dl # jmp gc6 #gc5: shl dl,1 #gc6: add si,80 ; next row # loop gc4 # # ; end of byte - store in gchold # mov [di],dl ; store in gchold # inc di # pop cx # loop gc3 ; do next 3 pixels # # ; end of 12 pixels - send to printer (twice) # mov cx,2 #gc7: push cx #IF DEBUG # push bx # mov ah,40h # mov bx,handle # mov dx,offset gchold # mov cx,4 # int 21h # pop bx #ELSE # mov cx,4 # mov di,offset gchold #gc8: mov al,[di] # xor ah,ah # xor dx,dx # push di # int 17h # pop di # inc di # loop gc8 #ENDIF # pop cx # loop gc7 # # inc bx ; move bx to next column # pop cx # loop gc2 ; do next column # # ; end of line # mov di,offset crlf ; print newline # call p2 # add bp,960 ; add 12 lines to base # pop cx # loop gc1 ; do next row # # ; end of screen # mov di,offset gcend # call p2 # ret #tosgrfc endp # #; ------------------------------------------------------------------ #; #; LASERJET GRAPHICS ROUTINES #; #; ------------------------------------------------------------------ # #; graphics a - 320x200 graphics print #ljgrfa proc near # ret #ljgrfa endp # #; graphics b - 640x200 graphics print #ljgrfb proc near # ret #ljgrfb endp # #; graphics c - 640x350 graphics print #ljgrfc proc near # ; set video segment to extended graphics # mov ax,0a000h # mov es,ax # # ; initialize the printer # mov di,offset gcinit # call p2 # # ; setup 350 iterations # mov cx,350 ; cx = count of iterations # xor si,si ; si = position on screen # #lgc1: ; line loop # mov di,offset gcline # call p2 # # ; do for 80 bytes (640 columns) # push cx # mov cx,80 # #lgc2: ; get byte and print it # mov al,es:[si] ; put character in al # xor ah,ah # xor dx,dx ; printer 0 # int 17h ; print it # inc si ; move pointer to next byte # loop lgc2 # # pop cx # loop lgc1 ; do next line # # mov di,offset gcend # call p2 # ret #ljgrfc endp # # #; null procedure for invalid video modes #null proc near # ret #null endp # #; Put a string out to the printer. #; ds:di points to null terminated string #puts proc near #p1: inc di # xor ah,ah # xor dx,dx # int 17h ; send to printer # #p2: mov al,[di] # or al,al # jnz p1 # ret #puts endp # #main proc near # ; setup pseg and pst # mov cs:pseg,ss # mov cs:pst,sp # #IF DEBUG # mov ax,_DATA # mov ds,ax # # ; call int5 # call int5 # # ; quit # mov ax,4c00h # int 21h #ELSE # # ; set int 5 offset # push ds # mov ax,_TEXT # mov ds,ax # mov dx,offset int5 # mov ax,2505h # int 21h # pop ds # # ; terminate and stay resident # mov dx,100h # mov ax,3100h # int 21h #ENDIF # #main endp #_TEXT ends # #_DATA segment public word 'DATA' #monoseg dw 0B000h ; monochrome video ram segment #cgaseg dw 0B800h ; color video ram segment #apaseg dw 0A000h ; APA segment (EGA high res) #scrmode db 0 ; current video mode # #att db 0 ; current attribute bits represent bold, italic, underline #crlf db 13,10,0 # #IF DEBUG #handle dw 0 ; for file i/o (only in DEBUG mode) #test db "test.123",0 ; name for test file #ENDIF # #IF PRINTER ; set modes to Toshiba or LaserJet #modes dw offset tosprocs #ELSE #modes dw offset ljprocs #ENDIF # #; Table of routines for various video modes #tosprocs dw offset color ; mode 0 - 40x25 color/bw # dw offset color ; mode 1 - 40x25 color # dw offset color ; mode 2 - 80x25 color/bw # dw offset color ; mode 3 - 80x25 color # dw offset tosgrfa ; mode 4 - 320x200 color # dw offset tosgrfa ; mode 5 - 320x200 color/bw # dw offset tosgrfb ; mode 6 - 640x200 color/bw # dw offset mono ; mode 7 - 80x25 mono # dw offset null ; mode 8 - invalid mode # dw offset null ; mode 9 - invalid mode # dw offset null ; mode a - invalid mode # dw offset null ; mode b - invalid mode # dw offset null ; mode c - invalid mode # dw offset tosgrfa ; mode d - 320x200 color # dw offset tosgrfb ; mode e - 640x200 color # dw offset tosgrfc ; mode f - 640x350 mono # dw offset tosgrfc ; mode 10 - 640x350 high res # #ljprocs dw offset color ; mode 0 - 40x25 color/bw # dw offset color ; mode 1 - 40x25 color # dw offset color ; mode 2 - 80x25 color/bw # dw offset color ; mode 3 - 80x25 color # dw offset ljgrfa ; mode 4 - 320x200 color # dw offset ljgrfa ; mode 5 - 320x200 color/bw # dw offset ljgrfb ; mode 6 - 640x200 color/bw # dw offset mono ; mode 7 - 80x25 mono # dw offset null ; mode 8 - invalid mode # dw offset null ; mode 9 - invalid mode # dw offset null ; mode a - invalid mode # dw offset null ; mode b - invalid mode # dw offset null ; mode c - invalid mode # dw offset ljgrfa ; mode d - 320x200 color # dw offset ljgrfb ; mode e - 640x200 color # dw offset ljgrfc ; mode f - 640x350 mono # dw offset ljgrfc ; mode 10 - 640x350 high res # #; table of attribute equivalents for possible attribute bytes #; 0 = normal, 2 = underline, 4 = reverse, 8 = bold, 10 = bold under #attributes db 0,2,0,0,0,0,0,0,0,10,8,8,8,8,8,8,0,2,0,0,0,0,0,0,8,10,8,8,8,8 # db 8,8,0,2,0,0,0,0,0,0,8,10,8,8,8,8,8,8,0,2,0,0,0,0,0,0,8,10,8,8 # db 8,8,8,8,0,2,0,0,0,0,0,0,8,10,8,8,8,8,8,8,0,2,0,0,0,0,0,0,8,10 # db 8,8,8,8,8,8,0,2,0,0,0,0,0,0,8,10,8,8,8,8,8,8,4,2,0,0,0,0,0,0 # db 4,10,8,8,8,8,8,8 # #; table of printer escape codes #prtptr dw offset boldon , offset boldoff # dw offset revon, offset revoff # dw offset unlon, offset unloff # #; #; Character translation tables #; #; These tables tell PrtSc what to send to the printer for every #; character on the screen. Note that 032 (space) is used for all #; non-printable characters. 000 is a special code that means "send #; escape sequence" for this character. Tspec is the lookup table for #; escape sequences. #; #; Note that the LaserJet does not really have box graphics chars. #; In the ttrans table these are handled by escape sequences which #; shift to a box.lj font developed at Duke. Others should change #; the escape sequences or replace the 000s with 032s. #; #IF PRINTER #; TOSHIBA P351 data #; Character translation table - handles control and extended ASCII #ttrans db 032,032,032,032,032,032,032,032,032,032,032,032,032,032,032 # db 032,032,032,032,032,175,169,032,032,032,032,032,032,032,032 # db 032,032,032,033,034,035,036,037,038,039,040,041,042,043,044 # db 045,046,047,048,049,050,051,052,053,054,055,056,057,058,059 # db 060,061,062,063,064,065,066,067,068,069,070,071,072,073,074 # db 075,076,077,078,079,080,081,082,083,084,085,086,087,088,089 # db 090,091,092,093,094,095,096,097,098,099,100,101,102,103,104 # db 105,106,107,108,109,110,111,112,113,114,115,116,117,118,119 # db 120,121,122,123,124,125,126,167,162,184,187,032,182,161,032 # db 162,032,032,189,032,032,032,177,032,032,032,032,032,183,032 # db 032,188,032,178,179,180,163,176,032,191,032,032,032,032,032 # db 032,032,032,032,032,032,174,172,032,032,032,032,032,000,000 # db 000,000,000,000,000,000,000,000,000,000,000,000,000,000,000 # db 000,000,000,000,000,000,000,000,000,000,000,000,000,000,000 # db 000,000,000,000,000,000,000,000,000,000,000,000,000,000,032 # db 185,032,032,032,032,165,032,032,032,032,032,032,032,032,032 # db 032,032,032,032,032,032,032,032,166,032,032,032,032,032,032 # db 032 #ELSE ; LaserJet #; Character translation table - handles control and extended ASCII #ttrans db 032,032,032,032,032,032,032,032,032,032,032,032,032,032,032 # db 032,032,032,032,032,175,169,032,032,032,032,032,032,032,032 # db 032,032,032,033,034,035,036,037,038,039,040,041,042,043,044 # db 045,046,047,048,049,050,051,052,053,054,055,056,057,058,059 # db 060,061,062,063,064,065,066,067,068,069,070,071,072,073,074 # db 075,076,077,078,079,080,081,082,083,084,085,086,087,088,089 # db 090,091,092,093,094,095,096,097,098,099,100,101,102,103,104 # db 105,106,107,108,109,110,111,112,113,114,115,116,117,118,119 # db 120,121,122,123,124,125,126,252,180,207,197,192,204,200,212 # db 181,193,205,201,221,209,217,216,208,220,215,211,194,206,202 # db 195,203,239,218,219,191,187,188,032,190,196,213,198,199,183 # db 182,249,250,185,032,032,248,247,184,251,253,032,032,032,000 # db 000,000,000,000,000,000,000,000,000,000,000,000,000,000,000 # db 000,000,000,000,000,000,000,000,000,000,000,000,000,000,000 # db 000,000,000,000,000,000,000,000,000,000,000,000,000,000,032 # db 222,032,032,032,032,032,032,032,032,032,032,032,032,032,032 # db 032,254,032,032,032,032,032,032,179,032,032,032,032,032,252 # db 032 #ENDIF # #; Tspec is the lookup table for special characters. It simply #; contains character values and offsets to the beginning of the #; escape sequence. When PrtSc sees 000 in the character table #; it will look down the tspec table until it finds an entry for #; the character in question. Note that tspec ends with two #; words of 0. #; #; At present only the 'box graphics' characters are included #; here, but with downloadable fonts and > 256 character display #; modes, the tspec table can be extended almost indefinitely. #; #tspec dw 179, offset ts10, 180, offset ts14 # dw 181, offset ts14, 182, offset ts14 # dw 183, offset ts7, 184, offset ts7 # dw 185, offset ts14, 186, offset ts10 # dw 187, offset ts7, 188, offset ts12 # dw 189, offset ts12, 190, offset ts12 # dw 191, offset ts7, 192, offset ts11 # dw 193, offset ts13, 194, offset ts8 # dw 195, offset ts9, 196, offset ts6 # dw 197, offset ts15, 198, offset ts9 # dw 199, offset ts9, 200, offset ts11 # dw 201, offset ts5, 202, offset ts13 # dw 203, offset ts8, 204, offset ts9 # dw 205, offset ts6, 206, offset ts15 # dw 207, offset ts13, 208, offset ts13 # dw 209, offset ts8, 210, offset ts8 # dw 211, offset ts11, 212, offset ts11 # dw 213, offset ts5, 214, offset ts5 # dw 215, offset ts15, 216, offset ts15 # dw 217, offset ts12, 218, offset ts5 # dw 219, offset ts0, 220, offset ts1 # dw 221, offset ts2, 222, offset ts3 # dw 223, offset ts4 # dw 0,0 #; #; Escape codes to present box graphics characters. #; Note that the LaserJet+ does not really have box #; graphics characters. These escape codes work for the #; box.lj font developed at Duke. Others should change #; or delete these codes. Note that all strings are null #; terminated. #; #IF PRINTER ; box graphics characters for Toshiba #ts0 db 27,"=o",27,"?",0 ; 219 #ts1 db 27,"=h",27,"?",0 ; 220 #ts2 db 27,"=i",27,"?",0 ; 221 #ts3 db 27,"=j",27,"?",0 ; 222 #ts4 db 27,"=g",27,"?",0 ; 223 #ts5 db 27,"=p",27,"?",0 ; 218 #ts6 db 27,"=q",27,"?",0 ; 196 #ts7 db 27,"=r",27,"?",0 ; 191 #ts8 db 27,"=s",27,"?",0 ; 194 #ts9 db 27,"=t",27,"?",0 ; 195 #ts10 db 27,"=u",27,"?",0 ; 179 #ts11 db 27,"=v",27,"?",0 ; 192 #ts12 db 27,"=w",27,"?",0 ; 217 #ts13 db 27,"=x",27,"?",0 ; 293 #ts14 db 27,"=y",27,"?",0 ; 180 #ts15 db 27,"=z",27,"?",0 ; 197 #ELSE ; LaserJet box graphics font #ts0 db 27,41,49,88,14,73,27,41,50,88,15,0 ; 219 #ts1 db 27,41,49,88,14,74,15,27,41,50,88,0 ; 220 #ts2 db 27,41,49,88,14,75,15,27,41,50,88,0 ; 221 #ts3 db 27,41,49,88,14,76,15,27,41,50,88,0 ; 222 #ts4 db 27,41,49,88,14,77,15,27,41,50,88,0 ; 223 #ts5 db 27,41,49,88,14,72,15,27,41,50,88,0 ; 218 #ts6 db 27,41,49,88,14,50,15,27,41,50,88,0 ; 196 #ts7 db 27,41,49,88,14,45,15,27,41,50,88,0 ; 191 #ts8 db 27,41,49,88,14,48,15,27,41,50,88,0 ; 194 #ts9 db 27,41,49,88,14,49,15,27,41,50,88,0 ; 195 #ts10 db 27,41,49,88,14,33,15,27,41,50,88,0 ; 179 #ts11 db 27,41,49,88,14,46,15,27,41,50,88,0 ; 192 #ts12 db 27,41,49,88,14,71,15,27,41,50,88,0 ; 217 #ts13 db 27,41,49,88,14,47,15,27,41,50,88,0 ; 293 #ts14 db 27,41,49,88,14,34,15,27,41,50,88,0 ; 180 #ts15 db 27,41,49,88,14,51,15,27,41,50,88,0 ; 197 #ENDIF #; #; Graphics mode codes #IF PRINTER ; Toshiba #gcinit db 27,26,"I",27,"L07",0 ; initialize the printer #gcline db 27,";1280",0 ; begin image data transfer #gchold db 0,0,0,0,0 #gcend db 12,27,26,"I",0 ; reinitialize printer #ELSE ; LaserJet #gcinit db 27,"*t100R",27,"*r0A",0 ; initialize the printer #gcline db 27,"*b80W",0 ; begin image data transfer #gchold db 0,0,0,0,0 #gcend db 27,"*rB",12,0 ; reinitialize printer #ENDIF # #; Text mode codes #IF PRINTER ; Toshiba escape sequences #init db 27,77,27,20,27,74,0 #boldon db 27,"K3",0 #boldoff db 27,"M",0 #revon db 27,"",0 #revoff db 27,"",0 #unlon db 27,"I",0 #unloff db 27,"J",0 #endit db 27,77,27,20,27,74,0 #ELSE ; LaserJet escape sequences #init db 15,27,41,50,88,0 #boldon db 27,40,115,51,66,0 #boldoff db 27,40,115,48,66,0 #revon db 27,40,115,48,83,0 #revoff db 27,40,115,49,83,0 #unlon db 27,38,100,68,0 #unloff db 27,38,100,64,0 #endit db 12,0 #ENDIF # #_DATA ends # #_STACK segment stack para 'STACK' # db 100h dup('TheStack') #top db 0 #_STACK ends # #end main # FUNKY_STUFF chmod +x 'prtsc.asm' fi # end of overwriting check # End of shell archive exit 0 -- Jeffrey William Gillette uucp: mcnc!ethos!ducall!jeff Humanities Computing Facility bitnet: DYBBUK at TUCCVM Duke University