--- title: "PrintScreen" id: 55028 type: "computer_media" slug: "printscreen" url: "http://localhost/computer_media/printscreen/" markdown_url: "http://localhost/computer_media/printscreen.md" published_at: "2024-06-10T07:55:01+00:00" modified_at: "2026-04-04T08:02:25+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "A machine code screen-dump utility embedded inside REM statements that drives a Memopak printer interface with a single RAND USR call." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" indiv: - name: "Peter McMullin" slug: "peter-mcmullin" taxonomy: "indiv" url: "http://localhost/indiv/peter-mcmullin/" genre: - name: "Printer" slug: "printer" taxonomy: "genre" url: "http://localhost/type/printer/" media_type: "Program" programmers: - name: "Peter McMullin" slug: "peter-mcmullin" taxonomy: "indiv" url: "http://localhost/indiv/peter-mcmullin/" download_url: "https://archive.org/download/timex-sinclair-software-archive/PRTSCR%20%281985%29%28McMullin%2C%20Peter%29%28TS1000%29%28US%29%28Program%29.zip" mediadate: "1985" related_content: - id: 54771 title: "Printscreen Utility User Manual" type: "document" url: "http://localhost/document/printscreen-utility-user-manual/" media_type_tags: "Printer" --- # PrintScreen PrintScreen is a utility that uses machine code routines, entered via BASIC, to send the screen contents to a printer through a Memopak interface. The program first lists itself (line 10), then prints characters 0–191 while skipping the range 64–127 (line 30 filters these out using an AND mask), and finally calls machine code at USR 16528 and USR 16840 to perform the actual screen dump. The REM line 0 encodes the machine code routine directly in its token stream, a well-known ZX81 technique for embedding binary data in a BASIC listing. Lines 1–8 display a decorative banner explaining the utility and its invocation method (RAND USR 16528). *** ## Program Analysis ### Program Structure The program is organized into two distinct regions: a set of REM lines that carry the machine code payload and a short BASIC driver that exercises and saves the routine. | Line(s) | Purpose | | --- | --- | | 0 (first) | Machine code embedded in REM token stream | | 1, 0, 0, 0, 0, 0, 7, 8 | Decorative banner / documentation REMs | | 10 | `LIST 1` — lists the program from line 1 | | 20–40 | Loops through characters 0–191, printing those outside 64–127 | | 50 | Calls machine code at USR 16528 and USR 16840 | | 60 | `STOP` | | 70 | `SAVE "PRTSC[R]"` | | 80 | `RUN` | ### Machine Code Embedding in REM The first `REM` at line 0 contains the machine code routine for the print-screen function. This is the classic ZX81 technique of storing binary data inside a `REM` statement: the interpreter never executes the body of a `REM`, so arbitrary bytes — including Z80 opcodes — can be stored there safely. The entry point is at address 16528 (the start of RAM, `16514 + 14` bytes of system variables), and a secondary entry or helper routine sits at 16840. The `RAND USR 16528` invocation documented in the banner calls directly into this embedded routine. ### Character Filter in Line 30 Line 30 uses the idiom `CHR$ N AND (N<64 OR N>127)`. On the ZX81, the boolean expressions `N<64` and `N>127` evaluate to 1 (true) or 0 (false). When the condition is false (i.e., N is in 64–127, the alphabetic and keyword range), the AND forces the argument to `CHR$` to zero, printing `CHR$ 0` (a space) instead. This neatly sidesteps characters that would otherwise invoke BASIC keywords or produce unwanted token output during the display pass. ### USR Call Chain in Line 50 Line 50 reads: - `RAND (USR 16528 + USR 16840 + USR 16528)` Each `USR` call jumps to the machine code, executes it, and returns a value (typically the BC register pair). The results are added together and passed to `RAND`, which simply discards the value — the entire expression is evaluated for its side effects (the three print-screen calls). Calling USR 16528 twice suggests the routine may need to be invoked more than once to complete a full 192-line screen dump, with USR 16840 handling a mid-point or secondary pass. ### Multiple Identical REM Lines at Line 0 Several REMs share line number 0. On the ZX81, duplicate line numbers are legal; the system stores each as a separate record in the program area and `LIST` displays them in sequence. This is exploited here to pack the decorative banner into lines that sort before line 1 yet after the machine code REM. `LIST 1` at line 10 deliberately skips line 0 entirely, presenting only the human-readable banner to the user. ### SAVE and RUN Lines Line 70 saves the program under the name `PRTSC` (the `[R]` escape represents the letter R in the zmakebas encoding, giving the filename a trailing R). Line 80’s `RUN` restarts the program after saving, providing a convenient loop for repeated use without manual re-entry. ### Notable Techniques Summary - Machine code stored in a `REM` statement at the start of RAM (address 16528). - Boolean arithmetic used as a character mask in `CHR$ N AND condition`. - Three `USR` calls chained inside a single arithmetic expression, results discarded via `RAND`. - Duplicate line-0 REMs used to layer machine code below the human-readable banner. - `LIST 1` used to suppress the machine code REM from normal display. ## Source Code ``` 0 REM .INKEY$ ▒.#> \,,.# ▝ █5▙RND▞▛#LN PD7( RAND LN [D]RNDY.LN PDYM#PDE£RND▞-VAL 7 FAST5[,,]RND▞▌#LN PD7( RAND LPRINT ▞4VAL #ACS #4" FAST5[?]RNDACS [Y]LN POKE RND/"ACS [Z] FAST5[?]RNDACS RETURNLN POKE RND LPRINT 7AT ( TO Y\~~LN PDY$LN PDAT LN #?K[I]([V]TAN 5 SAVE 1W#)▒ ;( CLEARLN [Q]INKEY$ ACS # FOR CODE ASN \~~LN ""INKEY$ ( PRINT LN [5]INKEY$ LN [M]INKEY$ ACS # FOR CODE ASN \~~LN ""INKEY$ ( PRINT LN [5]INKEY$ LN [M]INKEY$ ACS # FOR CODE ASN \~~LN ""INKEY$ ( PRINT LN [5]INKEY$ LN [M]INKEY$ ACS # FOR CODE ASN \~~LN ""INKEY$ ( PRINT LN [5]INKEY$ LN [M]INKEY$ ACS # FOR CODE ASN \~~LN ""INKEY$ ( PRINT LN [5]INKEY$ LN [M]INKEY$ ACS # FOR CODE ASN \~~LN ""INKEY$ ( PRINT LN [5]INKEY$ LN [M]INKEY$ ACS # FOR CODE ASN \~~LN ""INKEY$ ( PRINT LN [5]INKEY$ LN [M]INKEY$ ACS # FOR CODE ASN \~~LN ""INKEY$ ( PRINT LN [5]INKEY$ LPRINT TAN ACS COPYTAN ACS RUN TAN ACS LOAD TAN ACS SCROLLTAN ACS TO TAN ACS NOT TAN ACS INT TAN ACS SIN TAN 5[?]RNDACS #C▝ INPUT COPY PRINT LN PD LET #PDSGN LPRINT /▘SGN FASTSTR$ [J])[,,]INKEY$ ▞▒TAN FOR <<<7TAN **E£RND:-▞47#LEN █#( RAND 7$4 NEXT TAN ******** 1 REM ▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜ 0 REM ▌ P.MCMULLIN,1985 ▐ 0 REM ▛\~~\~~\~~\~~\~~\~~\~~\~~\~~\~~\~~\~~\~~\~~\~~\~~\~~\~~\~~▜ 0 REM ▌ RAND USR 16528 = ▐ 0 REM ▌ PRINT SCREEN ▐ 0 REM ▛\~~\~~\~~\~~\~~\~~\~~\~~\~~\~~\~~\~~\~~\~~\~~\~~\~~\~~\~~▜ 7 REM ▌MEMOPAK I/F VERSION▐ 8 REM ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ 10 LIST 1 20 FOR N=0 TO 191 30 PRINT CHR$ N AND (N<64 OR N>127); 40 NEXT N 50 RAND (USR 16528+USR 16840+USR 16528) 60 STOP 70 SAVE "PRTSC[R]" 80 RUN ```