Program Performs Print Screen (PC Magazine Vol 2 No 6 Nov 1983 User-to-User) Using IBM PC BASIC 2.0, it is possible to duplicate the function of the Ctrl-PrtSc key combination under program control. To turn ON echo of screen output to the printer: DEF SEG:POKE &H758,&HFF To turn this printer echo OFF: DEF SEG:POKE &H758,0 ----------------------------------------------------------------- Ctrl-PrtSc Toggle (from PC Magazine Vol 4 No 16 Aug 6, 1985 PC Tutor) Writing batch files, for example, to execute timing programs that do speed tests on various tests and doing a Ctrl-PrtSc first will send all results to the printer. The following is a small assembly language routine that will toggle Ctrl-PrtSc. This program will only work on IBM PCs and very close compatibles, since it assumes IBM's specific placement of the keyboard buffer, and it also assumes that the PrtSc flag is located 7200 hex. A>DEBUG PRINTTOG.COM File not found -A100 xxxx:0100 B84000 MOV AX,0040 ;set data segment xxxx:0103 8EC0 MOV ES,AX ;to BIOS area xxxx:0105 BB1A00 MOV BX,001A ;set buffer head to xxxx:0108 B81E00 MOV AX,001E ;first pos (flush) xxxx:010B 26 ES: xxxx:010C 8907 MOV [BX],AX ; xxxx:010E 40 INC AX ;set to next pos ... xxxx:010F 40 INC AX xxxx:0110 26 ES: xxxx:0111 894702 MOV [BX+02],AX ;the buffer tail xxxx:0114 B80072 MOV AX,7200 ;put PrtSc flag xxxx:0117 26 ES: xxxx:0118 894704 MOV [BX+04],AX ;into buffer xxxx:011B B8000B MOV AX,0B00 ;read bfr status ;(set ctlpt) xxxx:011E CD21 INT 21 xxxx:0120 B8004C MOV AX,4C00 ;exit gracefully xxxx:0123 CD21 INT 21 -RCX CX 0000 : 30 -w Writing 0030 bytes -q ----------------------------------------------------------------- Optimizing Print 3.0 (PC Magazine Vol 4 No 21 Oct 15, 1985 PC Tutor) PRINT.COM was introduced with DOS 2.0. It is a resident program that prints disk files while other programs are running. It is thus fundamentally different from other "background" (or spooler) printing programs. Most of the latter create a software print buffer by allocating a large chunk of user memory to act as a holding area for text that is to be sent to the printer. The print buffer program intercepts printer output, stores it in the created memory buffer, and then later transfers it to the printer. This frees up the system for other activities. DOS PRINT.COM transfers disk files to the printer directly and so takes up much less memory than a buffer-based program. The size of the files is limited only by disk space, not by the size of a preallocated spooling buffer. Once a regular print RAM buffer becomes full, further transfer into the buffer slows down to the speed of the printer. Although PRINT can be used with a diskette system, it is best suited for a hard disk system. DOS 2.x PRINT.COM programs had problems which is why people chose to ignore it. Directory paths could not be specified with the filename and the operation of PRINT could not be optimized for particular printers, for example. But the DOS 3.x PRINT corrected these problems. The new parameters are designed to help optimize PRINT for your system, your printer and your needs. The /D (device name) and /Q (queue size) parameters are simple enough. Normally, /D:PRN or /D:LPT1 will be specified, so you'll print to the first parallel printer. /Q can be set to the largest number of files you'll want to print at one time. The /B parameter sets the buffer size; its default is 512 bytes. This is the amount of memory PRINT will set aside for reading the disk file. The default value means that the print file will be 512 bytes at a time. If the buffer is too small, you'll see frequent disk accesses, particularly with a fast printer. If the buffer is too large, the disk accesses will be less frequent but will take longer, and PRINT will occupy more memory -- more than a traditional spooler. For a hard disk system with 640K, I recommend setting the buffer size at something like 4,096 or 8,192, both of which will work efficiently because they are multiples of 512. To understand the /S, /M and /U parameters, we'll have to take a look at how PRINT works. During operation of the PC, the 8253 timer chip invokes a hardware interrupt (08h) 18.2 times per second, or about once every .055 second. This interrupt executes a short routine in the ROM BIOS. The main job of that routine is to count the number of times it has been called, so DOS can know what time it is. Additionally, the Interrupt 08h routine invokes Interrupt 1Ch, often called the "Timer Tick." PRINT intercepts the Timer Tick interrupt to trigger its own operation. The /S parameter, which the IBM manual calls the "Time Slice," is the number of timer ticks during which PRINT will sit idle. During this time the rest of the PC system operates normally, as if PRINT had not been called at all. Thus, the /S parameter should really be called the "System Time Slice." The /M parameter, called "Max Tick," is the number of timer ticks during which PRINT actively tries to shovel characters out to the printer. This is really the time slice allocated to PRINT. Assuming that the printer is ready to receive these characters, PRINT will have nearly total control during this period, and any other programs that are running will be suspended. The default settings are /M:2 and /S:8. This means that PRINT is alternately active for 0.11 second and inactive for 0.44 second (assuming that the printer is ready to accept characters when PRINT tries to send them down the line). Consequently, PRINT will be working 20 percent of the time; any other program will work at 80 percent of normal speed. The /U parameter, which IBM calls the "Busy Tick," only comes into play if the printer happens to be busy at the moment PRINT attempts to send it a character. The default value is /U:1, which means that PRINT will wait one clock tick (0.055 second) before relinquishing its /M time slice. The rest of the system then goes back to work for /S timer tick before PRINT makes another attempt to feed the printer. PRINT also gives up its time slice if a disk access is in progress. The reason for this is obvious: if PRINT has to get another piece of the file during this time, then real problems develop should another program be accessing the disk. PRINT's time slice is also forfeited if a DOS function call is in progress. If /M is very high in relation to /S, you'll notice a significant degradation in system speed. If /M is too low, printing will not proceed as fast as the printer can manage. If /U is too high, PRINT may spend too much time just checking the printer without actually printing anything if the printer is busy. One problem with PRINT.COM is that all these parameters may only be specified when PRINT is first loaded. So, unless you like doing little three-finger exercises repeatedly, you would normally have a very difficult time optimizing the parameters for your system. There is a solutino for that. I'll discuss the "standard" (though recently discontinued) IBM Personal Computer Graphics Printer. The IBM Graphics Printer has an 80-character internal buffer. It will not begin printing until the buffer is full or until the printer receives a carriage return or a form feed. When the printer does begin printing, it remains busy and cannot accept any more characters until its internal buffer is empty. The optimum parameter settings for this printer, then, consist of an /M value equal to the number of timer ticks needed for PRINT to fill the printer's buffer, and an /S value equal to the timer ticks required for the printer to print the contents of the buffer. The short PRINTSET.BAS program (below) will let you experiment with PRINT settings after PRINT has been loaded. Load PRINT for a reasonably large average file of the type you usually print: PRINT bigfile. Go into BASICA, load the PRINTSET program, and run it. The program will ask whether DOS 3.0 or 3.1 is being used. The PRINTSET program shows the current settings of the /S, /M, and /U parameters. You may change any parameter by entering the letter (S, M, or U in either upper- or lowercase), followed by a comma, followed by the new value from 1 to 255. To exit PRINTSET, press Ctrl-Break. For the IBM Graphics Printer, start off by setting /M and /U equal to 1, and /S to 90 timer ticks, which is equivalent to about 5 seconds. This means that PRINT will be in charge for only one clock tick out of every 91. You should get one line printed about every 15 or 20 seconds. Obviusly, then, that one /M clock tick is not long enough for PRINT to fill the printer's internal buffer. Gradually increase the value of /M until one line is printed every 5 seconds. You may notice that most lines print once every 5 seconds, but that some lines take longer. Try increasing the value of /U to 2 to get a steady one line every 5 seconds. Now gradually decrease /S until the printer prints continuously. For the IBM Graphics Printer, using 80-character lines, good values are /S:20, /M:4, and /U:2. These values resulted in better performance than the DOS default values, even though for most lines, PRINT is active only one-sixth of the total system time. The PRINT command in my AUTOEXEC.BAT file is: PRINT /D:PRN /Q:20 /B:8192 /S:20 /M:4 /U:2 Unlike the IBM Graphics Printer, many other printers have internal buffers much larger than 80 characters. If you tried to set /M equal to the time it takes for PRINT to fill up a large buffer, you may find it to be something like 20 clock ticks or more. In operation, this would be intolerable, since the rest of your system would be halted during that time. For printers with large internal buffers, set /U equal to 1 and /M equal to 4 or 5 (about 0.25 second), and then experiment with /S. For very fast printers, you may find /S to be low in relation to /M. You may want to deliberately slow down the printing so you can get some work done, or speed up the printing if that's what's important. In any case, you can use PRINTSET.BAS at any time to adjust PRINT. PRINT can be used to print any text file, with or without control chracters, stored on a disk. Tabs are expanded, and ASCII 1Ah is taken to be an end of file, however, so PRINT cannot be used for graphics. PRINT will be active during any program that does not replace Interrupt 1Ch with its own interrupt routine. (Some compiled BASIC programs do this.) Using PRINT with Lotus's 1-2-3 is fine. To actually print 1-2-3 files in the background while using 1-2-3 may prove a little clumsy, however. You'll have to print your worksheet to a file with the extension .PRN, exit to the system, execute PRINT for that file, and then reenter 1-2-3. Programs that allow going to and returning from the DOS command level, such as XyWrite or Symphony or Word, make this process a lot easier. Be sure, though, to initially load PRINT before you use it from within another program, since you don't want to make it resident on top of another application. Here's the real kicker: at the DOS command level, and during execution of any program that uses DOS function calls to obtain keyboard input, PRINT operates in a totally different manner, and none of the good stuff explained above about timer ticks is applicable. Check it out. You could set completely wrong values for PRINT (/S to 255 and /M to 1) and when you exit BASIC to DOS, your printer will churn away, printing your text as fast as possible. To understand why this is so, we'll have to take a look at the more technical internal workings of PRINT. Because PRINT works with disk files, it must make DOS calls to pull these files into memory. During a DOS function call, DOS switches to an internal stack. DOS actually maintains three stacks: one for function calls 01h through 0Ch; another for function calls 0Dh and above (which includes the file accesses); and a third for function calls 01h through 0Ch when a Critical Error is in progress. Because of this internal stack, PRINT (or any other multitasking utility triggered by a hardware interrupt) cannot arbitrarily make DOS function calls to access a disk file. If another program is making a DOS function call, PRINT's function calls may clobber the internal stack and eventually cause the system to crash. To prevent this, PRINT uses the undocumented DOS Interrupt 21h function call 34h when it is first loaded. This function call returns registers ES:BX pointing to a byte in DOS. Whenever this byte is nonzero, a DOS function call is in progress. When PRINT is triggered by a timer tick, it checks this byte. If it's nonzero, PRINT just returns from the interrupt without attempting to print anything. Now this creates a real problem, because on the DOS command level, COMMAND.COM executes a DOS function call 0Ah for keyboard input, and this DOS call remains in progress until the user presses the Enter key at the end of a line. Many other DOS programs, such as DEBUG or EDLIN, also use this function call. So, PRINT takes advantage of still another undocumented feature of DOS: Interrupt 28h. PC-DOS itself continually executes an Interrupt 28h whenever it is in a wait state (that is, when it is waiting for keyboard input) during a function call of 01h through 0Ch. When an Interrupt 28h is invoked, PRINT knows that a function call of 01h through 0Ch is in progress. Because a separate stack is used for function calls of 0Dh and above, which includes all the file access calls, PRINT knows that it's safe to retrieve a file if necessary. PRINT will always grind to a halt during any disk access. But you'll also see it stop during a TYPE command after the disk has been accessed. This is because TYPE uses function call 40h to write the file to the display, and PRINT cannot use DOS during that time. Anyone who believes that multitasking is simple to implement in PC-DOS should dissassemble PRINT.COM and take a look at the backflips and contortions required for simple background printing from disk files. When the rumored PC-DOS 4.0 gives us a true multitasking operating system (we hope), PRINT will be dramatically outclassed, but until that time, it's one of the most interesting parts of the operating system. One final note about PRINTSET.BAS: the program uses the segment address of Interrupt 2Fh to find the location of PRINT in memory. This interrupt allows subsequent PRINT runs to transfer filenames to the initially loaded PRINT. But SHARE also uses Interrupt 2Fh, so if you want to use PRINTSET and you also use SHARE, run SHARE before PRINT. That way PRINTSET won't change bytes in the SHARE program. - - - - - 100 'PRINTSET.BAS: For setting DOS 3.x PRINT parameters 110 DEFINT A-Z 120 INPUT "Enter 0 for PC-DOS 3.0, 1 for PC-DOS 3.1: ",V 130 V=V*11 140 DEF SEG=0 150 DEF SEG=PEEK(4*&H2F+2)+256*PEEK(4*&H2F+3) 170 CLS:PRINT"PRINT.COM Timer Values":PRINT 180 PRINT "S (Time Slice) = ";PEEK(&H2CF+V) 190 PRINT "M (Max Tick) = ";PEEK(&H2D0+V) 200 PRINT "U (Busy Tick) = ";PEEK(&h2D1+V) 210 PRINT 220 INPUT "Enter S, M, or U, a comma, and the new value:",A$,X 230 IF (A$="S") OR (A$="s") THEN POKE &H2CF+V,X 240 IF (A$="M") OR (A$="m") THEN POKE &H2D0+V,X 250 if (A$="U") OR (A$="u") THEN POKE &H2D1+V,X 260 GOTO 170 ----------------------------------------------------------------- A Better Way (PC Magazine Vol 4 No 14 July 9, 1985 Power User) When printing on single-sheet paper in an Epson MX100, the printer's paper-out switch causes the printer to stop printing before a document is done. You can use BASIC to send the printer command sequence to disable the paper-out switch (CHR$(27)+"8"), but that requires keeping BASIC on your word processing disk. A better way is a 12-byte .COM program created with DEBUG. Running this program before printing disables the paper-out switch and offers the luxury of printing on single sheets. Editor's Note: You can create a companion (PAPERIN.COM) program that re-enables the paper-out switch when you go back to tractor-feed paper. Just replace the "8" on the fourth line of PAPEROUT.COM (38H) with a "9" (39H). -A 0B28:0100 MOV DL,1B 0B28:0102 MOV AH,05 0B28:0104 INT 21 0B28:0106 MOV DL,38 0B28:0108 INT 21 0B28:010A INT 20 0B28:010C -N PAPEROUT.COM -RCX CX 0000 :0C -W -Q ----------------------------------------------------------------- Perforation Problems (PC Magazine Vol 4 No 15 July 23, 1985 Power User) Many programs don't bother to skip over the perforations when printing on continuous form paper resulting in characters printed half on one page and half on the next. You can change the DIP switch settings on an Epson MX, RX or FX to enable a "skip over perforation" of about 1/2 inch on either side, but that's time consuming and can ruin the efforts of programs that are smart enough to skip the page breaks. Use an editor to make a pair of batch files (PGBRKON.BAT and PGBRKOFF.BAT). Run PGBRKON before you print yout listing and PGBRKOFF afterwards. PGBRKON copies a file name PGBRK.BEG to the printer, which enables a "skip over perforation," and PGBRKOFF copies a file named PGBRK.END to the printer, which disables it. This is PGBRKON.BAT: copy pgbrk.beg prn: And this is PGBRKOFF.BAT: copy pgbrk.end prn: All you need are the two files and the BASIC program below creates them for you. PGBRK.BAS will generate files that tell you Epson to skip over SKIPLINES% lines. The lines will be divided evenly between the current and next pages. If SKIPLINES% is set to 12, six lines will be skipped on one page and six on the next. The only restriction to correct operation is that SKIPLINES% cannot be less than 0 or greater than 127. PGBRK.BAS will work correctly for all IBM printers and all compatibles. 10 'PGBRK.BAS 20 SKIPLINES%=12 'SKIPLINES% cannot be less then 0 or greater than 127 30 OPEN "PGBRK.BEG" FOR OUTPUT AS 1 40 PRINT #1,USING "\ \";CHR$(27)+"N"+CHR$(SKIPLINES%); 50 CLOSE 1 60 OPEN "PGBRK.END" FOR OUTPUT AS 1 70 PRINT #1,USING "\ \";CHR$(140)+CHR$(27)+"O"; 80 CLOSE 1 90 END ----------------------------------------------------------------- Way to Set Printer Options (PC Magazine Vol 4 No 22 October 29, 1985 Power User) A way to set printer options is to use DOS's ability to redirect ECHO statements in batch files to the printer. For example, if your batch file contains: ECHO string > lpt1, the character string "string" will be printed on the default printer. You can send printer command sequences by specifying them as "string." All you need is an editor that lets you enter the Escape character (ASCII 27) and other non- printing ASCII characters. SETPRINT.BAT sets the options for an Okidata Microline printer. If you don't enter any parameters on SETPRINT's commmand line, a help screen is presented (see the label :HELP) that tells you which parameters are valid and what they do. SETPRINT will send any number of valid options to your printer. You just type in the sequences you want sent. Editor's Note: All characters in SETPRINT.BAT that are to be directed to the printer are enclosed in braces ({}). Except for the Escape character, which is listed as {esc}, nonprinting codes are shown as a-xxx, where the notation xxx represents the ASCII code, and "a-" means that you use the Alt key in conjunction with the keypad to enter the number. As an alternative to using an editor to generate the ECHO statements, you might use a short BASIC program that prints them to a file. Such a program would contain statements such as: PRINT #1, "echo "+chr$(27) where file number 1 is the open file. SETPRINT.BAT: echo off if "%1" == "" goto HELP echo Setting Printer Options: goto %1 :HELP cls echo The following printer commands are available: echo . echo WIDE - Double Width COND - Condensed Mode echo ULON - Underline On ULOFF - Underline Off echo BOLD - Double Strike CORR - Correspondence Mode echo DATA - Data Proc Mode ELITE - Elite Mode echo RESET - Resets Printer PAGE - Page Feed echo . echo Enter: %0 command1 command2 .....commandN goto END :WIDE echo {a-31} > lpt1 goto SPEAK :COND echo {a-29} > lpt1 goto SPEAK :ULON echo {esc}{C} > lpt1 goto SPEAK :ULOFF echo {esc}{D} > lpt1 goto SPEAK :BOLD echo {esc}{T} > lpt1 goto SPEAK :DATA echo {esc}{0} > lpt1 goto SPEAK :CORR echo {esc}{1} > lpt1 goto SPEAK :ELITE echo {a-28} > lpt1 goto SPEAK :RESET echo {a-24} > lpt1 goto SPEAK :PAGE echo {a-12} > lpt1 :SPEAK echo . "%1" sent to printer shift if not "%1" == "" goto %1 :END ----------------------------------------------------------------- DOS PRINT tip: DOS 2.0 and later versions contain a utility called GRAPHICS.COM that augments the original screen dump routine. Put a copy of GRAPHICS.COM in drive A: and, at the DOS prompt, type GRAPHICS and press Enter. Shift-PrtSc will now dump graphics screens to a graphics printer. ----------------------------------------------------------------- Switching Between Parallel Printers (PC World November 1985 The Help Screen) SWAPLPTS.BAS permits switching between two parallel ports, LPT1 and LPT2, to run two printers. 10 DEF SEG=&H40 20 A=PEEK(8):B=PEEK(9) 30 POKE 8,PEEK(10):POKE 9,PEEK(11) 40 POKE 10,A:POKE 11,B 50 SYSTEM Whenever you want to switch printers, run this program from DOS with the command: BASIC SWAPLPTS. Each parallel port installed in a PC is configured with a unique port address value. When you start the computer it checks its slots for parallel port addresses and builds a table in a specific portion of low RAM, listing the port addresses for LPT1, LPT2 and LPT3. An application's request to DOS to send output to LPT1, for example, requires that DOS read the first entry in the parallel port address table and direct output to that port. SWAPLPTS.BAS exchanges the values of the first and second entries in the port address table, thereby changing the port address used for LTP1 output. Thus, output is directed to the other printer. Running SWAPLPTS.BAS, of course, requires that BASIC be available. Using DEBUG.COM, you can easily assemble a .COM file that can be run directly from DOS: A>DEBUG -A xxxx:0100 MOV AX,40 xxxx:0103 MOV DS,AX xxxx:0105 MOV BX,[8] xxxx:0109 MOV CX,[A] xxxx:010D MOV [8],CX xxxx:0111 MOV [A],BX xxxx:0115 INT 20 xxxx:0117 -R CX CX 0000 :17 -N SWAPLPTS.COM -W Writing 17 bytes -Q SWAPLPTS.COM accomplishes the same task as SWAPLPTS.BAS but does so without BASIC. ----------------------------------------------------------------- Printer Check Perfected (PC World Star-Dot-Star March 1985) If a BASIC program attempts to print while the printer is off, the program will halt and the message "Device Fault" will be displayed. The PC can support three parallel printer adapters. When the system is started, it determines which adapters are present and creates a list of pointers to indicate the location (base port) of each one found. The standard printer device designator, PRN:, is set to use the printer connected to the first adapter in the list (LPT1:). The printer check subroutine should check the adapter indicated by the first pointer in the list. The PRTRCHEK.BAS subroutine does that. You can change the value of PRNTR in line 8000 if you wish to check the status of one of the other adapters. PRTRCHEK.BAS: 100 GOSUB 8000:END 8000 PRNTR=1:DEF SEG=&H40:BASE=(PRNTR*2)+6 8010 IF PEEK(BASE)=0 THEN PRINT "No printer adapter present.":RETURN 8020 STAT=INP(PEEK(BASE)+PEEK(BASE+1)*256+1) AND 160 8030 IF STAT=128 THEN PRINT "Printer ready.":RETURN 8040 IF STAT=0 THEN PRINT "Printer not ready." 8050 IF STAT=32 THEN PRINT "Out of paper." 8060 IF STAT=160 THEN PRINT "Printer not on." 8070 RETURN ----------------------------------------------------------------- Sending Printer Control Codes (PC Magazine Vol 4 No 26 Dec 24, 1985 Power User) It's a simple matter to send printer control sequences while in DOS itself. All you have to do is use the COPY command to send characters, including control codes, to the printer. Only one real "trick" needs to be used, and that is for sending the Escape character and the ASCII character 0. All characters, except ASCII 0, can be generated by using the Alt key combined with the numeric keypad. Just hold the Alt key down while typing the desired character's ASCII code on the numeric keypad. Besides ASCII 0, Escape (ASCII 27) also causes problems because DOS has special uses for it (it "escapes" the current command line as entered so far). Both difficulties can be solve for Epson (and many other) printers by using the "high order" versions of these two characters. Just add 128 (high-order ASCII 0) to the character code, and peck away at the numeric keypad. For example, to set an Epson printer into compressed mode with subscripts and small (18/216 inch) line heights -- a very tiny print size handy for small-size directory listings -- use: A>copy con:lpt1: 155 S 128 15 155 3 018 F6 A> The Alt key combined with 155 (shown as 155) is the same as Escape (since 128 + 27 = 155), and Alt combined with 128 is the same as ASCII 0. Ordinary characters are typed where they can be used without trouble. Don't forget to press the F6 key at the end to close off communications between the console and the printer. Now you can simply use the printer in the mode set. In this case, pressing Ctrl-P to enable simultaneous printing makes it easy to print out a directory listing in tiny print. Editor's Note: This works with nearly all Epson-compatible printers, including IBM's models. Be careful to check yours for compatibility, since Escape codes can be more troublesome than they first appear.