--- title: "Magnify" id: 54994 type: "computer_media" slug: "magnify" url: "http://localhost/computer_media/magnify/" markdown_url: "http://localhost/computer_media/magnify.md" published_at: "2024-06-10T01:44:45+00:00" modified_at: "2026-03-30T21:43:33+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "Type two lines of text and watch each character balloon into a bold block-graphic display — with printer output — using a clever pixel-reading trick." 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 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" genre: - name: "Banner" slug: "banner" taxonomy: "genre" url: "http://localhost/type/banner/" - name: "Demo" slug: "demo" taxonomy: "genre" url: "http://localhost/type/demo/" media_contents: - id: 54964 title: "ISTUG Public Domain Library 6" type: "computer_media" url: "http://localhost/computer_media/istug-public-domain-library-6/" media_type: "Program" mediadate: "1984" images: - url: "http://localhost/wp-content/uploads/2024/06/SCR-20260329-nwqs.png" - url: "http://localhost/wp-content/uploads/2024/06/SCR-20260329-nxlb.png" media_type_tags: "Banner, Demo" --- This program magnifies text characters to a large block-graphic display on both the screen and printer, rendering each pixel of a character as a 2×2 cell of selectable graphics characters. It reads two lines of text from the user and processes them one character at a time, using the POINT function to test each pixel of a character printed at the screen edge (rows 20–21). Two UDGs are defined at startup using DATA statements: UDG “A” is loaded with a checkerboard pattern (alternating 170/85 bytes) and UDG “B” with a hollow rectangle (255/129 pattern). The program offers a choice of background and foreground fill characters from a palette that includes space, two UDGs, block graphic characters (full block, half-block variants), and custom-entered characters, with a “relief style” shortcut that pairs the checkerboard UDG against the full block. Output is sent simultaneously to the display and to a printer via LPRINT, using column coordinate calculation to position each magnified pixel block. *** ## Program Analysis ### Program Structure The program is organized into three broad phases: initialization (lines 10–180), user interface for character selection (lines 190–510), and text input plus rendering (lines 520–990). The rendering subroutine at lines 830–990 is the computational core, called once per character of the user’s input text. 1. **Lines 10–170:** Define UDG characters “A” (checkerboard) and “B” (hollow rectangle) via POKE. 2. **Lines 180–280:** Offer a quick “relief style” selection (keys 7 or 9) or fall through to the detailed character picker. 3. **Lines 290–510:** Full character-selection UI: four preset choices plus free-entry options for background and text fill characters. 4. **Lines 520–680:** Collect two lines of text, track maximum length, and populate the `L$` lookup table. 5. **Lines 690–820:** Set rendering parameters and iterate over each character position, calling the subroutine. 6. **Lines 830–990:** Subroutine — reads pixel data via `POINT` and prints/lprints the magnified output. ### UDG Initialization Two UDGs are defined at lines 110–170. The DATA for each entry begins with a letter identifying the UDG (“A” or “B”), followed by eight byte values POKEd into `USR L$(J,1)+H`. UDG “A” alternates 170 (10101010₂) and 85 (01010101₂), producing a checkerboard pattern. UDG “B” uses 255 for the top and bottom rows and 129 (10000001₂) for the six interior rows, yielding a hollow rectangle border. ### Pixel-Reading Technique The magnification subroutine exploits `POINT` to sample each pixel of the source character. Before the subroutine is called, the current character from each line is printed at rows 20 and 21 (lines 760–770), which are at the very bottom of the display. The subroutine then iterates column `C` (0–7) and row `R` (0–7), with `B` (0 or 1) selecting line 1 or line 2. `POINT (C, R+B*8)` tests whether the pixel is set, setting `SWITCH` to 1 (background) or 2 (foreground). This approach avoids any need to inspect character ROM data directly. ### Coordinate Calculation The magnified output position is computed at lines 899 and 910. With `M=2` (the magnification factor), each source pixel becomes a 2×2 block of print cells. The row coordinate is: `RCOOR = ROW - (M/2*8) + (C*M) + N` and the column coordinate is: `CCOOR = C(B+1) - (M/2*8) + (R*M) + L` Here `C(1)=7` and `C(2)=23` are the horizontal centers for the two input lines, and `ROW=11` is the vertical center. The nested loops over `N` (1 to M) and `L` (1 to M) fill in the 2×2 block for each source pixel. Note that the outer loop variable `C` (column, 0–7) shadows the array `C()` holding horizontal centers — this works because array access uses `C(B+1)` while the loop variable is used as a plain scalar. ### Fill Character Lookup Table The array `L$` (dimensioned 10×1) acts as a lookup table mapping selector numbers to display characters. The preset entries are: | Index | Character | Description | | --- | --- | --- | | 1 | space | Blank | | 2 | `\a` (UDG A) | Checkerboard | | 3 | `\b` (UDG B) | Hollow rectangle | | 4 | `\::` (█) | Full block | | 7 | `\ '` (▝) | Top-right quarter block | | 8 | `\.` (▖) | Bottom-left quarter block | | 9 | `\':` (▛) | Top-left three-quarter block | | 10 | `\:.` (▟) | Bottom-right three-quarter block | Entries 5 and 6 are populated at runtime when the user enters a custom character (lines 460 and 500). The “relief style” shortcuts (lines 250–260) set `D(2)` to index 8 or 10, pairing a quarter-block foreground against a user-supplied background digit stored in `D(1)`. ### Dual Output Line 920 sends each magnified pixel block to the screen with `PRINT AT RCOOR,CCOOR`, and line 930 simultaneously outputs it to the printer with `LPRINT TAB CCOOR`. Because the screen uses AT for absolute positioning while LPRINT uses TAB for column positioning, the printer output is column-aligned per cell but advances sequentially through rows in the natural print order driven by the loop structure. ### Notable Anomalies - Line 270 executes `LET D(1)=VAL D$` for both the “7” and “9” relief cases as well as any other numeric digit entry, but the GO TO 520 at line 280 is always reached regardless of which branch was taken — lines 250 and 260 do not terminate execution, so all three assignments may occur sequentially if D$ is “7” or “9”. - The variable name `C` is used both as a `FOR` loop counter (columns 0–7) and as the array `C()` holding horizontal center columns. BASIC treats these as distinct, so there is no collision, but the naming is potentially confusing. - `INK PI` at line 180 sets the ink color to `INT(PI)=3` (magenta), an unusual way to specify a color constant. - Line 170 uses lowercase `j` in `NEXT j`; BASIC on this platform is case-insensitive for variable names in most contexts, so this matches the `FOR J` at line 110 without error. ## Source Code ``` 10 REM *** PROGRAM "MAGNIFY11" 20 REM *** UPDATED 1/14/84 AM 30 DIM L$(10,1) 40 DIM C(2) 50 DIM A$(2,255) 60 DIM D(2) 70 DATA "A" 80 DATA 170,85,170,85,170,85,170,85 90 DATA "B" 100 DATA 255,129,129,129,129,129,129,255 110 FOR J=1 TO 2 120 READ L$(J,1) 130 FOR H=0 TO 7 140 READ K 150 POKE USR L$(J,1)+H,K 160 NEXT H 170 NEXT j 180 INK PI 190 PRINT AT 9,0;"FOR RELIEF STYLE (LIGHT) PRESS 7" 200 PRINT "FOR RELIEF STYLE (DARK) PRESS 9" 210 PRINT AT 13,6;"OTHERWISE, PRESS ENTER" 220 PRINT AT 14,11;"TO CONTINUE" 230 INPUT D$ 240 IF D$<" " THEN GO TO 290 250 IF D$="7" THEN LET D(2)=8 260 IF D$="9" THEN LET D(2)=10 270 LET D(1)=VAL D$ 280 GO TO 520 290 CLS 300 PRINT AT 5,12;"\a\a \b\b \::\::" 310 PRINT AT 6,12;"\a\a \b\b \::\::" 320 PRINT AT 8,6;"1 2 3 4 " 330 BORDER 6 340 PRINT AT 11,3;"SELECT BACKGROUND CHARACTER" 350 PRINT AT 13,8;"ENTER 1, 2, 3 OR 4" 360 PRINT AT 14,7;"OR ENTER 5 FOR OTHER" 370 INPUT D(1) 380 PRINT AT 11,0;" ": BORDER 5 390 PRINT AT 11,6;"SELECT TEXT CHARACTER" 400 INPUT D(2) 410 IF D(1)=D(2) AND D(1)<>5 THEN GO TO 400 420 CLS 430 IF D(1)<5 AND D(2)<5 THEN GO TO 520 440 IF D(1)<5 THEN GO TO 490 450 PRINT AT 11,3;"ENTER BACKGROUND CHARACTER" 460 INPUT L$(5,1) 470 CLS 480 IF D(2)<5 THEN GO TO 520 490 PRINT AT 11,6;"ENTER TEXT CHARACTER" 500 INPUT L$(6,1) 510 LET D(2)=6 520 CLS 530 LET LENGTH=0 540 FOR G=1 TO 2 550 PRINT AT 11,7;"ENTER TEXT - LINE ";G 560 INPUT Y$ 570 IF LEN Y$>LENGTH THEN LET LENGTH=LEN Y$ 580 CLS 590 LET A$(G)=Y$ 600 NEXT G 610 LET L$(1,1)=" " 620 LET L$(2,1)="\a" 630 LET L$(3,1)="\b" 640 LET L$(4,1)="\::" 650 LET L$(7,1)="\ '" 660 LET L$(8,1)="\. " 670 LET L$(9,1)="\':" 680 LET L$(10,1)="\:." 690 LET M=2 700 LET C(1)=7 710 LET C(2)=23 720 LET ROW=11 730 CLS 740 FOR X=1 TO LENGTH 750 INK 7 760 PRINT AT 20,0;A$(1,X) 770 PRINT AT 21,0;A$(2,X) 780 INK 9 790 GO SUB 830 800 CLS 810 NEXT X 820 STOP 830 FOR C=0 TO 7 840 FOR N=1 TO M 850 FOR B=0 TO 1 860 FOR R=0 TO 7 870 LET SWITCH=2 880 IF POINT (C,R+B*8)=0 THEN LET SWITCH=1 890 LET RCOOR=ROW-(M/2*8)+(C*M)+N 900 FOR L=1 TO M 910 LET CCOOR=C(B+1)-(M/2*8)+(R*M)+L 920 PRINT AT RCOOR,CCOOR;L$(D(SWITCH),1) 930 LPRINT TAB CCOOR;L$(D(SWITCH),1); 940 NEXT L 950 NEXT R 960 NEXT B 970 NEXT N 980 NEXT C 990 RETURN ```