--- title: "Banner3" id: 53829 type: "computer_media" slug: "banner3" url: "http://localhost/computer_media/banner3/" markdown_url: "http://localhost/computer_media/banner3.md" published_at: "2024-05-13T19:02:00+00:00" modified_at: "2026-03-30T21:41:03+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "This banner printer scans the screen's own character pixels with POINT and redirects them as oversized block-graphic text to a printer — two size modes included." 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: "Printer" slug: "printer" taxonomy: "genre" url: "http://localhost/type/printer/" media_contents: - id: 55361 title: "SINCUS Exchange Tape 102 – Utilities & Business" type: "computer_media" url: "http://localhost/computer_media/sincus-exchange-tape-102-utilities-business/" media_type: "Program" mediadate: "1985" images: - url: "http://localhost/wp-content/uploads/2024/05/banner3.png" media_type_tags: "Banner, Printer" --- # Banner3 Banner3 is a banner-printing utility that reads text typed by the user, renders it invisibly on screen using the built-in character generator, then samples the pixel grid with POINT to reproduce each character as a pattern of block-graphic characters sent to a printer via LPRINT. The program supports two size modes — small (every pixel column) and large (every other pixel column, using a step of 0.5 which effectively doubles the output width) — as well as normal and inverse video rendering. It works by printing the input string at screen coordinates row 0 and then scanning the pixel rows from Y=166 to Y=175 (the bottom two character rows) and X from 0 to L*8-1, mapping lit pixels to the filled block graphic █ (escaped as \::). The program was published in the S.L.U.G. Newsletter, Louisville, Kentucky, November 1985. *** ## Program Analysis ### Program Structure The program is a short interactive loop occupying lines 1–16, with a `SAVE` statement at line `9999`. Execution begins at line `1` (via the `LINE 1` auto-run directive) and cycles back to line `2` after each banner is printed, allowing repeated use without restarting. 1. **Lines 2–3:** Accept and validate the message string (maximum 32 characters). 2. **Lines 4–6:** Accept size selection; set step variable `T` to `1` (small) or `0.5` (large). 3. **Lines 7–8:** Accept normal/inverse selection, validated by character code range. 4. **Lines 9–11:** Initialize print-position counters `A` (row) and `B` (column); render the input string on screen at row 0 using either normal or inverse video. 5. **Lines 12–15:** Nested `FOR` loops scan the pixel grid and output block graphics to the printer. 6. **Line 16:** Clear screen and loop back to line `2`. ### Screen-as-Font Technique The core technique exploits the display itself as a font renderer. The input string `A$` is `PRINT`ed at screen row 0 (the top of the display), where the built-in character set draws each character as an 8×8 pixel matrix. The outer `FOR X` loop (line `12`) steps through pixel columns 0 to `L*8-1`, and the inner `FOR Y` loop (line `13`) steps through pixel rows 166 to 175. The `POINT` function at line `14` tests each pixel; if set, the solid block graphic `█` (`\::`) is sent to the printer with `LPRINT AT A,B`. The Y range 166–175 corresponds to the bottom two character rows of the 176-row pixel display (rows 0–175 in the Spectrum’s coordinate system, where Y=0 is the bottom). This means the program actually scans the *bottom* two character rows of the screen, not row 0 where the text is printed. This is a significant bug: the text is displayed at row 0 (the topmost text row), which occupies pixel rows Y=168–175 for the first character row and Y=160–167 for the second. The Y range 166–175 straddles both rows, capturing only part of the rendered characters and producing garbled output. ### Size Mode Implementation The two size modes are implemented by varying the `STEP` value `T` in both `FOR` loops. For small mode (`S$="1"`), `T=1` samples every pixel column and every pixel row. For large mode (`S$="2"`), `T=0.5` halves the step, causing each pixel to be visited twice and doubling the printed output dimensions. Using a fractional `STEP` with `FOR`/`NEXT` is a valid BASIC technique but doubles the number of loop iterations and significantly slows printing. ### Input Validation User inputs are validated by testing `CODE` of the first character of the input string against ASCII ranges. Size input accepts codes 49–50 (‘1’ or ‘2’); inverse input accepts codes 48–49 (‘0’ or ‘1’). Invalid entries simply `GO TO` the relevant `INPUT` line. The message length is checked with `LEN` and a `PAUSE 120` error pause is given before re-prompting. ### Variable Summary | Variable | Purpose | | --- | --- | | `A$` | Input message string | | `L` | Length of `A$` | | `S$` | Size selection (‘1’ or ‘2’) | | `T` | Loop step (1 or 0.5) | | `I$` | Inverse selection (‘0’ or ‘1’) | | `A` | Current LPRINT row counter | | `B` | Current LPRINT column counter | | `X` | Pixel column loop variable | | `Y` | Pixel row loop variable | ### Bugs and Anomalies - **Wrong Y scan range:** The text is printed at text row 0, which in Spectrum pixel coordinates occupies Y=168–175 (first character row). The scan range Y=166–175 misses the top two pixel rows of the characters (Y=175 is the topmost pixel row in screen coordinates) and includes two rows of the blank area below, likely producing incomplete or misaligned character output. - **Variable `A` initialized to 2:** Line `9` sets `A=2` rather than 0, so the printer output starts at row 2 rather than row 0, leaving a two-row gap at the top of each banner. - **Axes transposed in loop:**`X` iterates over pixel columns (horizontal position, 0 to `L*8-1`) and `Y` iterates over pixel rows (vertical position, 166–175), but `X` is the outer loop and `Y` is the inner loop. This means the printer output is rotated 90 degrees: each printed row corresponds to one pixel column of the original text, not one pixel row, producing a sideways banner rather than upright text. ## Source Code ``` 1 REM Banner3 S.L.U.G. Newsletter Nov. 85 Louisville, Ky. 2 CLS : INPUT "Type In Message (Max 32 Char)",A$ 3 LET L=LEN (A$): IF L>32 THEN PRINT "Sorry 32 Max": PAUSE 120: CLS : GO TO 2 4 INPUT "Size (1-Small Or 2-Large) ";S$ 5 IF CODE S$<49 OR CODE S$>50 THEN GO TO 4 6 LET T=1: IF S$="2" THEN LET T=.5 7 INPUT "0 >Normal or 1 >Inverse ";I$ 8 IF CODE I$<48 OR CODE I$>49 THEN GO TO 7 9 LET A=2: LET B=0 10 IF CODE I$=48 THEN PRINT AT 0,0; A$ 11 IF CODE I$=49 THEN PRINT AT 0,0; INVERSE 1;A$ 12 FOR X=0 TO (L*8)-1 STEP T 13 FOR Y=166 TO 175 STEP T 14 IF POINT (X,Y)=1 THEN LPRINT AT A,B;"\::"; 15 LET B=B+1: NEXT Y: LET B=0: LPRINT : LET A=A+1: NEXT X 16 CLS : GO TO 2 9999 SAVE "banner3" LINE 1 ```