Classic Computer Magazine Archive COMPUTE! ISSUE 47 / APRIL 1984 / PAGE 154

VIC/64 Screenprint

Frank C. Gutowski

To copy the contents of your screen to the printer, just insert "Screenprint" into your program as a one-line subroutine. Refer to the "Automatic Proofreader" article before typing these programs in.

Using just one line of BASIC and less than 80 bytes of memory, "Screenprint" opens the needed files, captures the entire screen, sends it to the printer, and closes the files.

Most screen print routines follow this logic:

  1. Find where the screen memory is.
  2. Start PEEKing screen locations.
  3. Convert screen code to ASCII.
  4. Assemble an ASCII line and send it to the printer.
  5. Repeat until the entire screen has been displayed.

Screenprint takes a different approach. By treating the screen as an input device, we can combine the first three steps into one, creating a compact yet powerful subroutine that is easy to insert into any program.

Input From Screen Memory

The screen is normally the default output device. The VIC and 64 operating systems automatically send keyboard input to the screen unless you redirect it with a CMD command. However, you also can OPEN a screen file for input and read data from screen memory, using some of the same commands and statements which control input from tape or disk.

Screenprint opens a screen file with OPEN3,3. This does not in any way affect normal PRINTs to the screen; it just opens another path (File 3) to the screen (device 3). Now, statements like GET#3 or PRINT#3 can direct input or output from or to the screen. Once the screen file is OPENed, Screenprint uses GET#3, A$ to input a screen character. The character under the cursor at the time of the GET#3 is assigned to the string variable A$, and the cursor moves one space to the right.

Dealing With Screen Wraparound

A good feature of this screen GET is that when it gets to the end of a line, it will read a CHR$(13), and cause a carriage return to be sent to the printer. This means that a line that wraps around on the screen will appear as one line on the printer. If this is not desired, it can be eliminated by inserting an IF-THEN statement that will cause carriage returns to be ignored.

This version of One-Line Screenprint is for VIC:

10 OPEN3, 3:OPEN4, 4:PRINT "{HOME}"; :FORI=0T
   O505:GET#3, A$:PRINT#4,A$; :NEXT:CLOSE3:
   CLOSE4

Program Explanation

OPEN3,3: opens the screen file.
OPEN4,4: opens the print file.
PRINT"[HOME]": places the cursor in the home position for the screen read.
FORI = 0TO505: sets the number of characters to capture from the screen.
GET#3,A$: captures a character from the screen and moves the cursor right one space.
PRINT#4,A$;: prints the captured screen character with no RETURN.
NEXT:CLOSE4:CLOSE3:RETURN: ends the loop, closes the files and returns to the caller.

For the 64, use this version of One-Line Screenprint:

10 OPEN3,3:OPEN4,4:PRINT"{HOME}":FORI=0T
   O999:GET#3,A$:PRINT#4,A$;:NEXT:CLOSE3:
   CLOSE4

To get all this on one line in the 64, you'll need to abbreviate some of the BASIC keywords. For example, O SHIFT-P can stand for OPEN, a question mark can be substituted for PRINT, P SHIFT-R for PRINT#, etc.

Printing Reversed Characters

The GET statement puts ASCII numbers into A$, not the screen code, so you can send the characters to the printer without translation. However, reversed characters do not have distinct ASCII numbers; these are returned as normal characters. If you must have a screen print with reversed characters, you will need another, longer routine. We must find where screen memory is (on the VIC), then look at each screen code to see if it is greater than 127 (reversed character). If the character is reversed, we have to send the appropriate commands to make the printer go into, then out of, reverse mode.

Those of you who want an exact copy of the screen, including low-resolution graphics and reversed characters, can use the screen copy routines below. The control characters sent are set up for the 1515 and 1525 printers, but may be changed for other printers.

VIC Screen Copy

100 PRINT "{HOME}"; : SS = (PEEK(210)) * 256 : OPE
    N3, 3 : OPEN 4, 4                  : rem 236
110 FOR R = 0 TO 22 : B$ = ""            : rem 96
120 FOR C = 0 TO 21 : A$ = ""            : rem 80
130 IF PEEK(SS + ((R * 22) + C))>127 THEN : GET#3, A
    $ : B$ = B$ + CHR$ (18) + A$ + CHR$ (146) : GOTO 160 : rem 61
140 GET#3, A$ : IF A$ = CHR$(13) THEN : A$ = "" : rem 204
150 B$ = B$ + A$                                      : rem 47
160 NEXT C : PRINT#4, B$ : NEXT R : CLOSE 4 : CLOSE 3 : rem 91

64 Screen Copy

100 PRINT "{HOME}"; : SS = (PEEK(210)) * 256 : OPE
    N3, 3 : OPEN 4, 4                  : rem   236
110 FOR R = 0 TO 24 : B$ = ""            : rem  98
120 FOR C = 0 TO 39 : A$ = ""            : rem  89
130 IF PEEK(SS + ((R * 40) + C))>127 THEN : GET#3, A
    $ : B$ = B$ + CHR$(18) + A$ + CHR$(146) : GOTO 160 : rem  61
140 GET#3, A$ : IF A$ = CHR$(13)THEN : A$ = "" : rem 204
150 B$ = B$ + A$                                     : rem  47
160 NEXT C : PRINT#4, B$ : NEXT R : CLOSE 4 : CLOSE 3 : rem 91

Lines 100–120: put the cursor to home position, find the start of screen memory (SS), open the needed files, and set the row and column pointers.

Line 130: look at the screen memory. When a screen character greater than 127 is found, it must be a reversed character. The character is then captured and added to string B$ between a [RVS] and [OFF] character.

Lines 140–150: capture all nonreversed characters, remove CHR$(13), and add the captured character to the print string B$.

Line 160: send the strings to the printer, close the files and return.

Screenprint In Action

Programs 1 and 2 are demonstration programs which use both subroutines. Once LOADed and RUNning, just key in anything you wish, even create a graphics picture using graphics characters. When you desire a copy, the f1 key will call One-Line Screenprint. The f3 key will call Screen Copy. This will print the screen including reversed characters and no line wrap.

Necessary Changes

To add either routine to your existing programs, add these lines any place you want the Screenprint option:

100 GETA$ : IFA$ = CHR$(133) THEN GOSUBxxx : A$ =
    " "
110 IFA$ = "" THEN 100

These lines call the Screenprint subroutine if the f1 key is depressed. Any other key will cause the program to continue. Replace the xxx with the line number of the selected Screenprint subroutine.

Don't forget, you can use the disk or tape as an output or input device just as easily as the screen. With a few modifications to Screenprint, you could be transferring screens of data to and from any device. That could make for some interesting and powerful applications, using only a few program lines.

Program 1: VIC Screenprint Demo

200 OPEN 3, 3 : OPEN 4, 4 : PRINT "{CLR} KEY IN ANYTHING" : rem 214
210 PRINT "{RVS}F1 = ONE LINE SCREEN" : PRINT "
    {3 RIGHT}{RVS}PRINT SUB{OFF}"                         : rem 113
220 PRINT "{RVS}F3 = SCREEN COPY{OFF}"                    : rem 186
230 GET A$ : IF A$ = CHR$(133) THEN GOSUB 260 : A$ = ""   : rem 149
240 IF A$ = CHR$(134) THEN GOSUB 270 : A$ = ""            : rem 25
250 PRINT A$; : A$ = "" : GOTO230                         : rem 236
260 PRINT "{HOME}"; : FOR I = 0 TO 505 : GET#3, A$ :
    PRINT#4, A$; : NEXT : RETURN                          : rem 73
270 PRINT "{HOME}"; : SS = (PEEK(210))*256                : rem 246
280 FOR R = 0 TO 22 : B$ = ""                             : rem 104
290 FOR C = 0 TO 21 : A$ = ""                             : rem 88
300 IF PEEK(SS + ((R * 22) + C))>127 THEN : GET#3, A$ :
    B$ = B$ + CHR$(18) + A$ + CHR$(146) : GOTO 330        : rem 59
310 GET#3, A$ : IF A$ = CHR$(13) THEN : A$ = ""           : rem 203
320 B$ = B$ + A$                                          : rem 46
330 NEXT C : PRINT#4, B$ : NEXT R : RETURN                : rem 173

Program 2:64 Screenprint Demo

200 OPEN 3, 3 : OPEN 4, 4 : PRINT "{CLR} KEY IN ANYTHING" : rem 214
210 PRINT "{RVS}F1 = ONE LINE SCREEN PRINT SUB{OFF}"      : rem 253
220 PRINT"{RVS}F3 = SCREEN COPY {OFF}"                    : rem 186
230 GET A$ : IF A$ = CHR$(133) THEN GOSUB 260 : A$ = ""   : rem 149
240 IF A$ = CHR?(134) THEN GOSUB 270 : A$ = ""            : rem 25
250 PRINTA$; : A$ = "" : GOTO230                          : rem 236
260 PRINT "{HOME}"; : FOR I = 0 TO 999 : GET#3, A$ :
    PRINT#4, A$; : NEXT : RETURN                          : rem 90
270 PRINT "{HOME}"; : SS = (PEEK(210)) * 256              : rem 246
280 FOR R = 0 TO 24 : B$ = ""                             : rem 106
290 FOR C = 0 TO 39 : A$ = ""                             : rem 97
300 IF PEEK(SS + ((R * 40) + C))>127 THEN : GET#3, A$ :
    B$ = B$ + CHR$(18) + A$ + CHR$(146) : GOTO 330        : rem 59
310 GET#3, A$ : IF A? = CHR$(13) THEN : A$ = " "          : rem 203
320 B$ = B$ + A$                                          : rem 46
330 NEXT C : PRINT#4, B$ : NEXT R : RETURN                : rem 173