RLEPro decodes and displays run-length-encoded (RLE) picture data loaded as machine code from tape into memory at address 40000, then renders it using PLOT commands to build a high-resolution bitmap image. The decoder scans for a two-byte header sequence (values 71 and 72) that marks the start of the picture data, then interprets alternating run-count and color bytes. Attribute memory (22528–23295) is filled with INK 7 (white) via a POKE loop when an end-of-data sentinel is detected. After drawing, the completed screen can be saved back to tape as a SCREEN$ file, with the program prompting for a filename if one was not already supplied.
Program Structure
The program is organized into a linear initialization phase, a main decode loop, and several subroutines. Lines 4–12 handle setup: setting display attributes, prompting for a filename, loading binary data to address 40000, and initializing coordinate variables. Lines 50–230 form the main decode loop. Lines 500–550 and 600–640 are subroutines that read the run-count and color fields respectively. Lines 700–750 perform the actual PLOT rendering. Lines 800–820 handle saving the completed screen. Line 900 is a standalone tape-save routine for the BASIC program itself.
RLE Data Format and Header Detection
The binary data blob loaded at address 40000 uses a simple synchronization header. The decoder first scans for byte value 27 (ESC) at line 60–80, then scans for byte 71 (‘G’) at lines 100–120, then byte 72 (‘H’) at lines 140–160. This three-byte sequence ESC G H marks the beginning of the encoded picture data. Line 9 ensures the first byte at 40000 is 27 if it is not already, providing a fallback entry point for the scan.
Decode Loop Logic
Starting at line 180, the loop alternates between two subroutine calls and a draw call:
- Line 180 calls subroutine 500, which reads a run-count byte and stores
C = PEEK A - 32. - Line 200 calls subroutine 600, which reads a color/attribute byte (stored in
Cagain, overwriting the run-count). - Line 211 skips the draw call if
C=0, then line 220 calls subroutine 700 to PLOTCpixels.
The subtraction of 32 from each raw byte offsets the data into a printable-ASCII-friendly encoding range, so a byte of 32 decodes as 0 (end of run or transparent), and values below 32 trigger the end-of-picture routine.
Coordinate Management
The drawing origin is X=0, Y=175 (top-left in Spectrum PLOT coordinates, since Y=175 is near the top of the 176-row display). Subroutine 500 advances X by the run-count and wraps to the next scanline when X exceeds 255. Subroutine 700 increments X one pixel at a time for each plotted point, also performing scanline wrap at lines 715–716. When Y goes negative the picture is complete and execution jumps to line 800.
Attribute Coloring
When the end-of-data condition is detected (a byte less than 32 is read), a FOR loop POKEs the entire attribute file (addresses 22528 to 23295) with the value 7, setting every cell to INK 7 on PAPER 0 (white on black). This is done in subroutines 500 and 600 as well as in subroutine 700, covering all possible exit paths from the decode loop.
Screen Save Feature
After drawing completes, line 800 checks whether a filename was supplied. If so, it prompts the user to press a key twice (the double-pause idiom with PAUSE 0 followed by INPUT "") before saving with SAVE a$ SCREEN$. If no filename was given, line 810 prompts for one interactively using a lower screen INPUT AT statement before proceeding to the save.
Notable Bugs and Anomalies
- Color byte overwritten: The variable
Cis used for both the run-count (subroutine 500) and the color value (subroutine 600). After subroutine 600 returns,Cholds only the color byte; the original run-count from subroutine 500 is lost. Subroutine 700 then usesCas the pixel count to plot, meaning it is actually plotting color-count pixels rather than run-count pixels. Whether this is intentional or a bug depends on the RLE data format conventions used by the encoder. - CLEAR before LOAD: Line 5 uses
CLEAR 39999to lower RAMTOP before the machine code load at line 8, protecting the loaded data from being overwritten by BASIC’s memory management — a correct and necessary technique.
Key Variables
| Variable | Role |
|---|---|
A | Current read pointer into the data block at 40000 |
B | Raw byte value from PEEK A |
C | Decoded value (B−32); used as run-count then color count |
D | Pixel counter within subroutine 700 |
X | Current horizontal pixel position |
Y | Current vertical pixel position (counts down from 175) |
a$ | Tape filename for loading and saving |
Source Code
1 REM RLE Picture program, © 1986...John Ryan
2 REM
3 REM Modified by Carl Forst to automatically clear Ramtop & LOAD M/C @ 40000 as well as to SAVE SCREEN$ after picture is drawn. (GOTO 900 to save this program to tape)
4 BEEP .5,40: BORDER 0: PAPER 0: INK 7: CLS : PAUSE 10: BEEP .75,40: PRINT AT 10,10; FLASH 1;"STOP TAPE": PAUSE 200
5 CLEAR 39999: PRINT AT 7,0;"Run-Length-Encoded Picture Prog.";AT 10,3;"(High-Resolution Graphics)"
6 INPUT " INPUT Pic. File Name (if known)";"(10 Chars.Max.) or just <ENTER>: "; LINE a$
8 LOAD a$CODE 40000
9 IF PEEK 40000<>27 THEN POKE 40000,27
10 LET A=40000
11 LET X=0
12 LET Y=175
50 CLS
60 LET B=PEEK A
70 IF B=27 THEN GO TO 90
80 LET A=A+1: GO TO 60
90 LET A=A+1
100 LET B=PEEK A
110 IF B=71 THEN GO TO 130
120 GO TO 90
130 LET A=A+1
140 LET B=PEEK A
150 IF B=72 THEN GO TO 170
160 GO TO 140
170 LET A=A+1
180 GO SUB 500
190 LET A=A+1
200 GO SUB 600
210 LET A=A+1
211 IF C=0 THEN GO TO 180
220 GO SUB 700
230 GO TO 180
500 LET B=PEEK A
510 LET C=B-32
520 IF C=0 THEN RETURN
530 IF C<0 THEN FOR q=22528 TO 23295: POKE q,7: NEXT q: GO TO 800
540 LET X=X+C: IF X>255 THEN LET X=X-256: LET Y=Y-1
550 RETURN
600 LET B=PEEK A
610 LET C=B-32
620 IF C=0 THEN RETURN
630 IF C<0 THEN FOR q=22528 TO 23295: POKE q,7: NEXT q: GO TO 800
640 RETURN
700 LET D=0
715 IF 255<X THEN LET Y=Y-1
716 IF 255<X THEN LET X=X-256
717 IF Y<0 THEN FOR q=22528 TO 23295: POKE q,7: NEXT q: GO TO 800
718 IF X>255 THEN GO TO 730
720 PLOT X,Y
730 LET D=D+1
731 LET X=X+1
740 IF D=C THEN RETURN
750 GO TO 710
800 IF a$<>"" THEN PRINT #0;AT 0,0;"Press any key (twice) to save",a$;" pic. or BREAK to Stop.": PAUSE 0: INPUT "": GO TO 820
810 INPUT AT 0,0;"Type Name of picture for saving:";"(10 Chars. max.) "; LINE a$
820 SAVE a$SCREEN$ : GO TO 9999
900 SAVE "RLEPRO" LINE 4: VERIFY "": STOP
9999 PRINT #0;AT 0,1;a$: PAUSE 0::::::: REM
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.