--- title: "Extended SCREEN$" id: 71408 type: "computer_media" slug: "extended-screen-2" url: "http://localhost/computer_media/extended-screen-2/" markdown_url: "http://localhost/computer_media/extended-screen-2.md" published_at: "2026-09-03T09:01:43+00:00" modified_at: "2026-09-03T09:01:43+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/09/Extended-SCREEN.png" excerpt: "A machine code routine that supercharges the built-in SCREEN$ function to recognize UDGs, software graphics, and standard characters by their character codes." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "1987" slug: "year-1987" taxonomy: "post_tag" url: "http://localhost/tag/year-1987/" - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" basic: - name: "SCREEN$" slug: "screen" taxonomy: "basic" url: "http://localhost/basic/screen/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" indiv: - name: "Alvin Albrecht" slug: "albrecht-alvin" taxonomy: "indiv" url: "http://localhost/indiv/albrecht-alvin/" genre: - name: "Programming" slug: "programming" taxonomy: "genre" url: "http://localhost/type/programming/" media_type: "Program" programmers: - name: "Alvin Albrecht" slug: "albrecht-alvin" taxonomy: "indiv" url: "http://localhost/indiv/albrecht-alvin/" download_url: "https://archive.org/download/timex-sinclair-software-archive/Extended%20SCREEN%20(1987)(Albrecht%2C%20Alvin)(TS2068)(US)(Program).zip" mediadate: "1987" images: - url: "http://localhost/wp-content/uploads/2026/09/Extended-SCREEN.png" media_type_tags: "Programming" --- # Extended SCREEN$ Extended SCREEN$ is a machine code utility that extends the SCREEN$ function to also recognize user-defined graphics (UDGs), software-generated graphics, and standard alphanumeric characters, returning their character codes. The routine is loaded via POKE from DATA statements into a user-specified RAM address (defaulting to 60000), spanning 221 bytes. Before use, the caller must execute PRINT AT X,Y; to position the cursor, then call USR base to invoke the machine code, which returns the character code in the C register. A checksum of the DATA bytes is verified against the expected value of 25151 to catch transcription errors. The machine code includes a small software-generated graphics table embedded within the routine itself, with a self-modifying address patch applied at runtime in line 100. *** ### Program Structure The program is organized into three logical phases: 1. **Documentation (lines 10–80):** REM blocks describe the program’s purpose and usage instructions. 2. **Setup and loading (lines 90–120):** Prompts for a base address, POKEs machine code from DATA statements, patches a self-referential address, verifies a checksum, and prints usage instructions. 3. **Data (lines 130–150):** Three DATA lines holding the 221 bytes of Z80 machine code and embedded graphics data. ### Machine Code Loading and Self-Modification Line 100 loads the machine code byte-by-byte into memory starting at address `a` and accumulates a running checksum in `t`. After loading, two POKE statements patch bytes at offsets `a+87` and `a+88` to embed the absolute address `a+93` into the machine code. This is a classic self-modifying load technique: the routine contains a pointer to its own internal software-generated graphics table, and that pointer must be fixed up to reflect wherever in RAM the code was actually loaded. The patch computes the low byte as `(a+93) - 256 * INT((a+87)/256)` — essentially `(a+93) MOD 256` — and the high byte as `INT((a+93)/256)`, storing a standard Z80 little-endian 16-bit address. ### Checksum Verification Line 110 compares the accumulated sum `t` against the expected value `25151`. If the DATA lines were mistyped during entry, the program halts with an error message using inverse-video characters (character codes 18 and 1/0 for INVERSE ON/OFF) to highlight the message. This was a standard practice for machine code programs distributed in magazines to help users catch transcription errors. ### Usage Convention The routine uses an unconventional calling convention described in the REM at line 70: before invoking `USR base`, the caller must execute `PRINT AT X,Y;` (with a trailing semicolon so no newline is output) to position the system’s print position at the target cell. The machine code then reads the display file at that location and identifies the character. The result is returned in the BC register pair (specifically C), which BASIC receives as the USR function’s return value. ### DATA Encoding and the `b` Placeholder The DATA statements use the identifier `b` extensively as a placeholder within the embedded graphics table bytes. Because `b` is an uninitialized numeric variable (defaulting to 0 in BASIC), all occurrences of `b` in the DATA lines read as `0`. This is a deliberate space-saving technique: writing `b` is shorter than writing `0` repeatedly, reducing the line length of the DATA statements significantly. ### Software-Generated Graphics Table Starting at offset 93 from the base address (i.e., `a+93`), the machine code contains an embedded lookup table of software-generated graphic patterns. This table occupies the tail end of the loaded data block and is referenced by the self-patched pointer. The routine compares display file bytes against entries in this table to identify software-generated graphic characters. ### Output and Diagnostics Line 120 prints a summary showing the address range used, the location of the software-generated graphics table, and a ready-to-type BASIC line (`5 LET base=a`) that the user can enter into their program to use the routine. The `'` characters in the PRINT statement generate newlines, and `TAB 9` is used for alignment. ### Anomalies and Notes - The input validation in line 90 rejects addresses below 20000 or above 65000, falling back to 60000, but does not check whether the 221-byte range overlaps with system areas or the BASIC program itself. - The REM at line 80 notes that Graphic ‘A’ always matches the corresponding character block — this is a known property of the ZX81 UDG system where Graphic A’s pattern is identical to the regular character it shadows. - The self-patch arithmetic for the low byte uses `256 * INT((a+87)/256)` rather than the more idiomatic `INT((a+93)/256)*256`; both yield the correct low byte only if `a+87` and `a+93` fall in the same 256-byte page, which is guaranteed since they are only 6 bytes apart. ## Source Code ``` 10 REM <><><><><><><><><><><>< 20 REM <> EXTENDED SCREEN$ <> 30 REM <><><><><><><><><><><>< 40 REM <> By Alvin Albrecht <> 50 REM <> June 1987 <> 60 REM <><><><><><><><><><><>< 70 REM To do a SCREEN$ (X,Y), type;PRINT AT X,Y;:LET C=USR base. C will equal the CODE of the character at X,Y. If C=0, the character is not a UDG, S/W gen. gr, or alphanumeric char. 80 REM Graphic 'A' is always the same as the char. block. 90 INPUT "Base Address? (Default=60000): ";a:IF a<20000 OR a>65000 THEN LET a=60000 100 LET t=0:FOR z=a TO a+220:READ b:LET t=t+b:POKE z,b:NEXT z:POKE (a+87),a+93-256*(INT ((a+87)/256)):POKE (a+88), INT ((a+93)/256) 110 IF t <>25151 THEN PRINT "\{18}\{1}Error in DATA lines or line 100!\{18}\{0}":STOP 120 CLS :PRINT a;" to ";a+220;" is the location"; TAB 9;"of the m/c."'''a+93;" is the location of the"; TAB 9;"software generated"; TAB 9;"graphics."'''''"Now type:"'"5 LET base=";a:STOP 130 DATA 237,91,123,92,42,132,92,6,8,126,18,19,36,16,250,62,31,60,254,165,40,53,254,144,40,247,79,48,50,254,128,48,53,42,54,92,36,214,32,95,22,0,203,35,203,18,203,35,203,18,203,35,203,18 140 DATA 25,237,91,123,92,6,8,26,190,32,7,35,19,16,248,6,0,201,121,24,198,1,0,b,201,42,123,92,214,144,24,209,33,37,176,214,128,24,202,0,b,b,b,b,b,b,b,15,b,b,b,0,b,b,b,240,b,b,b,0,b,b,b,255,b,b,b,0,b,b,b,b,b,b,b,15,b,b,b,b,b,b,b,b,b,b,b 150 DATA 240,b,b,b,15,b,b,b,255,b,b,b,15,b,b,b,0,b,b,b,240,b,b,b,15,b,b,b,240,b,b,b,b,b,b,b,b,b,b,b,255,b,b,b,240,b,b,b,0,b,b,b,255,b,b,b,15,b,b,b,255,b,b,b,240,b,b,b,255,b,b,b,b,b,b,b,b,b,b,b ```