Double-Width Double-Height

Developer(s): Keith Skapinski
Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Demo

Double-Width Double-Height is a display utility that renders a 16-character text message in three different size combinations: double-width/double-height, single-width/double-height, and double-width/single-height. Each scaling routine works by scanning the pixel data of a message printed at row 10 using POINT, then re-plotting the pixels in the target scale using PLOT and DRAW. The double-width/double-height routine scans 128 pixels horizontally across 7 rows (j=94 to 88) and plots each detected pixel as a 2×2 block using four PLOT calls. The program cycles through all three display modes with a PAUSE between each, then loops back with RUN.


Program Analysis

Program Structure

The program is organized as a main routine starting at line 150 and three subroutines, each preceded by a REM label:

  • Lines 30–50: Double-width, double-height scaling subroutine
  • Lines 70–90: Single-width, double-height scaling subroutine
  • Lines 110–130: Double-width, single-height scaling subroutine
  • Line 140: Pause-and-clear helper subroutine
  • Lines 150–200: Main entry point — input, display, and cycle loop
  • Line 220: SAVE with autostart

Line 10 (RUN 150) redirects execution to the main routine, skipping the subroutines. Line 200 uses RUN to loop the program from the top, which has the side effect of clearing all variables including l$, prompting the user for a new message each cycle.

Pixel-Scanning Technique

The core technique relies on printing the user’s message at AT 10,0 (line 160), which places it in a known screen region, then scanning that region pixel-by-pixel with POINT. The scan covers rows j=94 down to j=88 (7 pixel rows, corresponding to one character row’s height in the ZX81’s 64×44 pixel coordinate system) and the appropriate number of horizontal pixels for each mode.

Detected pixels are then re-plotted at a translated coordinate in the upper portion of the screen (around y=170), scaled according to the mode. This is an entirely BASIC-based font scaling approach — no character data tables or machine code are used.

Scaling Routines Compared

LinesModeX rangePixel rendering
30–50Double-width, double-height0–1274 × PLOT calls per pixel (2×2 block)
70–90Single-width, double-height0–255PLOT + DRAW 0,1 (vertical pair)
110–130Double-width, single-height0–127PLOT + DRAW 1,0 (horizontal pair)

The double-width modes scan only 128 horizontal pixels (half the screen width) since each source pixel maps to two output pixels, keeping the output within the 256-pixel display width. The single-width/double-height mode scans all 256 pixels and stretches only vertically.

Coordinate Mapping

The vertical output coordinate formula 170-(94-j)*2 (or without the *2 for single-height) maps the source scan rows starting at j=94 downward to output rows starting at y=170 and increasing downward. Since j decrements from 94 to 88 and the plot coordinate increases as j decreases, the image is rendered top-to-bottom correctly. The choice of y=170 as the base positions the scaled text in the upper-middle area of the screen.

The Pause/Clear Subroutine

Line 140 uses PAUSE VAL "200" followed by PRINT AT 0,0,,,,,,,,:RETURN. The use of VAL "200" in the PAUSE argument is a memory optimization. The series of commas in the PRINT statement advances the print position through multiple fields, effectively overwriting the scaled display area with spaces to clear it before the next mode is shown, without issuing a full CLS.

Notable Anomalies and Limitations

  • The INPUT prompt at line 150 guides the user toward 16 characters with a template of underscores, but there is no enforcement of this limit.
  • The message is printed at row 12 for the mode label (lines 170–190), but the source text for scanning remains at row 10 (line 160). The scaling subroutines are called while both strings are on screen; however, the scan range (rows 94–88) targets only row 10’s pixels, so the label at row 12 does not interfere.
  • Performance is noted as slow by the author in line 210’s REM, which suggests the POINT-based scan loop in pure BASIC is the bottleneck. The author explicitly requests a machine code conversion.
  • Line 210 contains a REM with spaces missing between words, consistent with manual typing: tryingto, goa, someonecan, M/CKeith.

Image Gallery

Source Code

  10 RUN 150
  20 REM                        DOUBLE WIDTH       DOUBLE HEIGHT 
  30 FOR j=94 TO 88 STEP -1:FOR i=0 TO 127
  40 IF POINT (i,j) THEN PLOT i*2,170-(94-j)*2:PLOT i*2,(170-(94-j)*2)+1:PLOT (i*2)+1,170-(94-j)*2:PLOT (i*2)+1,(170-(94-j)*2)+1
  50 NEXT i:NEXT j:RETURN 
  60 REM                        SINGLE WIDTH       DOUBLE HEIGHT 
  70 FOR j=94 TO 88 STEP -1:FOR i=0 TO 255
  80 IF POINT (i,j) THEN PLOT i,170-(94-j)*2:DRAW 0,1
  90 NEXT i:NEXT j:RETURN 
 100 REM                        DOUBLE WIDTH       SINGLE HEIGHT 
 110 FOR j=94 TO 88 STEP -1:FOR i=0 TO 127
 120 IF POINT (i,j) THEN PLOT i*2,170-(94-j):DRAW 1,0
 130 NEXT i:NEXT j:RETURN 
 140 PAUSE VAL "200":PRINT AT 0,0,,,,,,,,:RETURN 
 150 CLS :INPUT "MESSAGE 16 characters"'" ________________"'l$
 160 PRINT AT 10,0;l$
 170 PRINT AT 12,0;"Double Width, Double Height":GO SUB 20:GO SUB 140
 180 PRINT AT 12,0;"Single Width, Double Height":GO SUB 60:GO SUB 140
 190 PRINT AT 12,0;"Double Width, Single Height":GO SUB 100:GO SUB 140
 200 RUN 
 210 REM To LIST ;  I have been tryingto get these 3 programs to goa little faster. Maybe someonecan convert them to M/CKeith Skapinski
 220 SAVE "DW/DH" LINE 1

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.