--- title: "Basic Renumber" id: 64744 type: "computer_media" slug: "basic-renumber" url: "http://localhost/computer_media/basic-renumber/" markdown_url: "http://localhost/computer_media/basic-renumber.md" published_at: "2026-03-07T14:43:57+00:00" modified_at: "2026-03-30T21:41:04+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "A two-part BASIC renumbering tool that walks raw program memory, patches line-number headers with POKE, and reports every GO TO and GO SUB target that needs updating." 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: "Programming" slug: "programming" taxonomy: "genre" url: "http://localhost/type/programming/" - name: "Utility" slug: "utility" taxonomy: "genre" url: "http://localhost/type/utility/" media_contents: - id: 64715 title: "Miscellaneous Programs" type: "computer_media" url: "http://localhost/computer_media/miscellaneous-programs/" media_type: "Program" mediadate: "198x" media_type_tags: "Programming, Utility" --- # Basic Renumber This program is a BASIC renumbering utility that operates in two distinct parts. Lines 9949–9956 implement a line-listing display routine that walks through program memory using the system variable at address 23635–23636 (PROG, the start-of-BASIC pointer) to read and print each line number and its tokenised source. Lines 9957–9998 form the renumbering engine: it prompts for a start number and step, then scans the program body from address 26710 (stored in `bs`) to patch line headers via direct POKE operations and resolve all GO TO and GO SUB targets (token bytes 236 and 237) by scanning the ASCII digits before the embedded five-byte floating-point literal (token 14). The renumberer searches backward through digit characters to reconstruct the referenced line number, locates it in the program, calculates its new number, and prints the updated value — notably it prints rather than POKEs the GO TO/GO SUB arguments, meaning the user sees what needs changing rather than having them automatically rewritten. The program saves itself with SAVE “BASRENUM” at line 9999. *** ## Program Structure The listing splits cleanly into two functional sections, both residing at the top of the line-number space (9949–9999) so they can coexist with any user program loaded below them: 1. **Lister (9949–9956):** Reads the `PROG` system variable from addresses 23635–23636, iterates through the tokenised program body, and prints each line with its line number right-aligned at column `4-LEN STR$ l`. 2. **Renumberer (9957–9998):** Accepts a start number and step, walks the program from the hard-coded base address stored in `bs` (26710), rewrites line-header bytes with `POKE`, and identifies but only *prints* GO TO / GO SUB targets rather than patching them automatically. ## Key Variables | Variable | Role | | --- | --- | | `g` | Byte pointer into program memory; also reused as new start line number | | `l` | Current line number (lister) / decimal place accumulator (renumberer) | | `bs` | Hard-coded base address of the program to renumber (26710) | | `ff` | Renumber step size | | `m` | Running new line number counter | | `i` | Byte pointer used by the renumberer scan loop | | `j`, `k`, `n` | Offset counter, target line number, and ordinal index of matched line | | `h` | Token discriminator: 1 = GO TO (236), 2 = GO SUB (237) | ## Memory Layout Assumptions The lister uses the standard system variable `PROG` held as a 16-bit little-endian word at 23635–23636. Each BASIC line in memory follows the layout: `[high byte of line no.][low byte of line no.][length low][length high][tokens…][0x0D]`. The lister reconstructs the line number as `PEEK g * 256 + PEEK (g+1)` (big-endian), advances `g` by 4 to skip the header, then prints tokens until it encounters a newline byte (13). The renumberer hard-codes `bs = 26710` as the start of the target program. This means the utility and the program being renumbered must coexist in memory at a known layout; the constant would need manual adjustment for a different host address. ## Token Detection Idioms The five-byte floating-point embedded number is detected by token byte `14`. The renumberer skips these literals in the lister (line 9952) and uses their presence as an anchor when reconstructing a GO TO / GO SUB argument (line 9974–9977). GO TO and GO SUB are identified by their token codes 236 and 237 respectively. The boolean expression on line 9965 exploits the fact that `1 AND condition` evaluates to 1 or 0, giving `h` the value 1, 2, or 0 — a compact multi-way flag without IF chains. The keyword strings on line 9969 use string multiplication by a boolean: `(" GO TO " AND h=1)` produces the string when true, or an empty string when false — a classic Spectrum BASIC string-selection idiom. ## Renumbering Algorithm 1. Walk lines from `bs`; at each newline (byte 13), check whether the following byte exceeds 34 (i.e., the line number MSB is in range). If above 34, branch to the POKE phase (9990). 2. For each GO TO / GO SUB found, scan forward up to 5 bytes to locate the embedded float marker (14), then read the ASCII digit characters backward to reconstruct the decimal target line number `k`. 3. Count how many lines from `bs` have a header value less than `k` to find ordinal `n`, then compute the new target as `g + n * ff`. 4. Print (do not POKE) the new target value — the user must manually correct GO TO / GO SUB arguments or use a companion editor. 5. The POKE phase (9990–9998) iterates all lines and rewrites the two-byte big-endian line number in each header, splitting the new value into high byte (`j`) and low byte (`g` after repeated subtraction of 256). ## Notable Techniques - Right-aligning line numbers in the lister via `AT PI,4-LEN STR$ l` — using `PI` (truncated to 3) as the row avoids a separate row variable. - Skipping floating-point literals with `IF PEEK g=14 THEN LET g=g+6` (line 9952) — the token plus 5 bytes of IEEE-like mantissa/exponent. - The digit-reconstruction loop (9978–9982) walks right-to-left through ASCII digit bytes, accumulating `k` using an explicit powers-of-ten multiplier `l`. - `PAUSE 0` on line 9956 halts the lister between pages, consistent with the keypress-wait idiom. ## Bugs and Anomalies - The renumberer only *prints* GO TO / GO SUB new targets; it does not patch them. The program is therefore a semi-automatic aid rather than a fully automatic renumberer — the user must act on the printed output. ## Source Code ``` 9949 LET g=PEEK 23635+PEEK 23636*256 9950 LET l=PEEK g*256+PEEK (g+1): LET g=g+4 9951 PRINT AT PI,4-LEN STR$ l;l; 9952 IF PEEK g=14 THEN LET g=g+6 9953 IF PEEK g=13 THEN LET l=0 9954 PRINT CHR$ PEEK g;: LET g=g+1 9955 IF l THEN GO TO 9952 9956 PAUSE 0: CLS : GO TO 9950 9957 LET bs=26710: REM RENUM STARTS HERE 9958 INPUT " INPUT start no. ";g: INPUT " THEN INPUT STEP ";ff 9959 LET m=g: CLS 9960 PRINT "Change these lines": LET i=bs+4 9961 IF PEEK i<>13 THEN GO TO 9965 9962 IF PEEK (i+1)>34 THEN GO TO 9990 9963 LET m=m+ff 9964 LET i=i+5 9965 LET h=(1 AND PEEK i=236)+(2 AND PEEK i=237) 9966 IF PEEK i=14 THEN LET i=i+5 9967 IF h THEN GO SUB 9969 9968 LET i=i+1: GO TO 9961 9969 PRINT m;(" GO TO " AND h=1)+(" GO SUB " AND h=2); 9970 LET h=0 9971 IF PEEK (i+1)>=48 AND PEEK (i+1)<58 THEN GO TO 9973 9972 PRINT " * ": RETURN 9973 LET j=2 9974 IF PEEK (i+j)=14 THEN GO TO 9978 9975 LET j=j+1 9976 IF j>5 THEN GO TO 9972 9977 GO TO 9974 9978 LET l=1: LET k=0 9979 LET k=k+(PEEK (i+j-1)-48)*l 9980 LET j=j-1 9981 IF PEEK (i+j-1)=236 OR PEEK (i+j-1)=237 THEN GO TO 9983 9982 LET l=l*10: GO TO 9979 9983 LET j=bs: LET n=0 9984 IF PEEK j*256+PEEK (j+1)>=k THEN GO TO 9988 9985 LET n=n+1 9986 LET j=j+(PEEK (j+2)+PEEK (j+3)*256)+4 9987 GO TO 9984 9988 LET k=g+n*ff 9989 PRINT k: RETURN 9990 LET j=0: LET i=bs 9991 GO SUB 9994 9992 LET i=i+PEEK (i+2)+PEEK (i+3)*256+4 9993 GO TO 9991 9994 IF PEEK i>34 THEN STOP 9995 IF g<256 THEN GO TO 9997 9996 LET j=j+1: LET g=g-256 9997 POKE i,j: POKE (i+1),g 9998 LET g=g+ff: RETURN 9999 SAVE "BASRENUM" ```