AID is a programmer’s toolkit for BASIC development, offering seven utilities: line finding, byte-level memory inspection and POKEing, REM line creation, line guarding, self-start/save, single-line listing, and program renumbering. The renumber routine (lines 9941–9997) traces through BASIC program memory starting at address 16513, patching line-number tokens following GOTO (token 236) and GOSUB (token 237) opcodes, and updates the raw line-number bytes stored in the program area. The REM creation tool (lines 9873–9885) uses USR calls to a machine code routine and directly manipulates the STKEND/program pointers at addresses 16514–16516 to insert a blank REM line of a user-specified length. Memory addresses such as 16509 (PROG), 16425–16426 (PPC/NXTLIN), and 16530 (USR 16530 for free bytes) are accessed throughout via PEEK and POKE.
Program Analysis
Program Structure
The program loads via a short bootstrap at lines 3–4 that jumps to line 9831, where the main menu is displayed. Each menu option maps to a subroutine block in the high 9800s. The dispatch is performed at line 9838 with:
GOTO VAL "9822"+CODE ")"*G
CODE ")" evaluates to 14 (the ZX81 character code for )), so selecting menu option n jumps to line 9822 + 14×n, landing on one of the REM anchors at 9836, 9856, 9873, 9890, 9907, 9924, or 9941. The variable J is permanently set to 9831 (the menu line) and is reused everywhere a “return to menu” GOTO is needed, saving token space.
Menu Options Summary
| Option | Function | Entry line |
|---|---|---|
| 1 | Find a line / show address & length | 9840 |
| 2 | Alter a byte’s data (PEEK/POKE) | 9857 |
| 3 | Create a REM line | 9874 |
| 4 | Line guard (STOP after listing self) | 9891 |
| 5 | Self-start / SAVE | 9908 |
| 6 | LIST one line at a time | 9926 |
| 7 | Renumber | 9943 |
Option 1 – Line Finder
Starting from D = 16509 (PROG system variable), the loop at 9843–9846 reads two-byte line numbers (PEEK D * 256 + PEEK (D+1)) and steps through lines using the stored line-length bytes at offsets +2 and +3. When the target line M is found, its address and byte length are printed. The user is then offered the chance to enter the byte-editing sub-loop (option 2 reused inline at 9848–9872).
Option 2 – Byte Editor
The user supplies a start address; eight consecutive bytes are displayed as address/decimal/character triplets. The user then inputs an address and a value to POKE, with a Y/N confirmation guard at line 9869–9870.
Option 3 – REM Line Creator
This option calls machine code. USR 16524 returns the start address of free memory minus 2, stored in L. A loop POKEs zero bytes into the new space. The STKEND pointer at 16514–16515 is updated each iteration to claim the growing block. RAND 16516 (i.e., RANDOMIZE USR 16516) is used as a lightweight machine-code call mid-loop. The line-length field of the new REM is written at offsets −1 and −2 from L, incorporating A2 (= CODE "▝" = 1, used as a constant for the minimum REM overhead).
Option 4 – Line Guard
Lines 9891–9897 list line 9893 itself, then read the current line pointer from system variables 16425–16426 (PPC/NXTLIN) and overwrite the first two bytes of the next line with NOT PI (= 0), effectively corrupting the line number of any line that follows, preventing further execution or listing beyond that point.
Option 5 – Self-Start / Save
Line 9910 performs a SAVE "AID". Line 9911 uses GOTO SGN PI (= GOTO 1) which targets a non-existent line, a standard technique for a clean warm restart without error.
Option 6 – Single-Line Lister
Starting at D = 16509, the loop walks program memory byte-by-byte. Token 126 (the ZX81 number-follows marker) causes a 6-byte skip via CODE "▞" (= 5, plus the +1 from the main increment). Token 118 (NEWLINE) triggers a pause and resets to the next line. Characters are printed with CHR$ PEEK D. Line numbers are right-aligned using TAB INT PI (= TAB 3) minus the string length of the line number.
Option 7 – Renumberer
This is the most complex routine. The user inputs a start number G and a step FF. The outer loop (9949–9958) scans program memory for NEWLINE tokens (118) at each line boundary, then searches for GOTO (236) or GOSUB (237) tokens. When found, subroutine 9959 is called.
Inside 9959–9984, the routine extracts the numeric argument of the GOTO/GOSUB by locating the floating-point number representation (terminated by token 126). It reconstructs the integer target line number K from the BCD-like digit tokens (tokens 28–37 representing digits 0–9) using positional arithmetic with L as a power-of-10 accumulator, multiplied by CODE "\~~" (= 10). It then counts how many program lines precede line K (loop 9977–9981), deriving offset N, and computes the renumbered target as G + N*FF.
The actual line-number rewriting is done by subroutine 9990–9997, which iterates over all lines, updating the two-byte header of each with the new sequential number built from J (high byte, incremented every 256 steps) and G (low byte, incremented by FF).
Key BASIC Idioms and Techniques
VAL "expression"is used throughout to encode numeric constants and expressions as strings, reducing token storage cost (e.g.,VAL "9831",VAL "256",VAL "16509").NOT PI= 0 andSGN PI= 1 are used as compact numeric literals.CODE "char"encodes small constants:CODE ")"= 14 (dispatch multiplier),CODE "▝"= 1 (A2),CODE "7"= 7,CODE "6"= 6,CODE "▌"= 4 (line-header size),CODE "▞"= 5,CODE "\~~"= 10.PAUSE Jwith subsequentINKEY$check is the standard efficient keypress-wait idiom.J= 9831 is reused as both the return-to-menu target and as the argument toPAUSE(a very long pause), serving dual purpose.- The REM blocks at 9839, 9856, 9873, 9890, 9907, 9924, 9941, 9998, 9999 act as labeled anchors and dispatch targets, with their content sometimes holding encoded data visible in the listing header (line 2).
Anomalies and Notable Points
- Line 9847 uses
TAB INT PI=TAB 3andTAB NOT PI=TAB 0for layout control. - Line 9876:
USR 16524-2— the subtraction of 2 is performed in BASIC arithmetic, not inside the string, suggesting the machine code at 16524 returns a pointer that needs a 2-byte offset correction for the REM body start. - The renumberer prints candidate GOTO/GOSUB targets but does not automatically patch the numeric tokens in place — it appears to be an interactive “show what would change” display rather than a fully automatic in-place patch, with the actual line-header rewrite in 9990–9997 being a separate pass.
- Line 9951 uses
VAL "PEEK (I+1)>34"to evaluate a relational expression inside a string, returning 1 (true) or 0 (false), which serves as the condition for skipping past the end-of-program marker test.
Content
Source Code
2 REM [,,]#E▙RNDLN [.],,TAN E£RND##TAN E0RND##5 T[Z] GOSUB PI##TAN <>5#RNDY#W<>7<>[Y] 4 RAND <>[Y]▘COS Y REM <>[Y]▌4 FOR Y><>[Y]▞4▀<> FASTAT W<>[Y]▞4<=<> FAST LPRINT GOSUB PI777VAL <> LPRINT <>#▖<>#▀TAN
3 LET J=VAL "9831"
4 GOTO J
9830 REM >
9831 CLS
9832 PRINT ,," TO DELETE ""AID"": RAND USR 16546 THENDELETE LINE 9830"," INPUT NO. TO : ","1 FIND A LINE""S ADD.","2 ALTER A BYTE""S DATA","3 CREATE A REM LINE","4 LINE GUARD",,"5 SELF START / SAVE ","6 LIST 1 LINE AT A TIME","7 RENUMBER ",,,," ";VAL "USR 16530";" BYTES LEFT"," [A]█["][P][E][H]█[S][O][F][T][W][A][R][E]["]█[S][P][E][C][I][A][L]"
9834 LET F=VAL "256"
9835 LET A2=CODE "▝"
9836 LET D=VAL "16509"
9837 INPUT G
9838 GOTO VAL "9822"+CODE ")"*G
9839 REM
9840 PRINT ,,"LINE NO. ? "
9841 INPUT M
9843 LET G=PEEK D*F+PEEK (D+SGN PI)
9844 IF M=G THEN GOTO VAL "9847"
9845 LET D=D+VAL "PEEK (D+2)+PEEK (D+3)*F+4"
9846 GOTO VAL "9843"
9847 PRINT TAB INT PI;M;" AT ";D;";";VAL "PEEK (D+2)+PEEK (D+3)*F+4";" BYTES";,TAB NOT PI;"ALTER A BYTES DATA? (Y/N)"
9848 PAUSE J
9849 IF INKEY$ ="N" THEN GOTO J
9856 REM
9857 PRINT ,," INPUT ""D"" OR ANOTHER ADD TO LIST "
9858 INPUT M
9859 CLS
9860 FOR G=M TO M+CODE "7"
9861 PRINT G;"/";PEEK G;"=";CHR$ PEEK G,;
9862 NEXT G
9863 PRINT
9864 PRINT " INPUT ADD. TO POKE THENDATA, ""0"" TO STOP"
9865 INPUT G
9866 IF NOT G THEN GOTO J
9867 INPUT D
9868 PRINT " POKE ";G;",";D;" RIGHT? (Y/N)"
9869 PAUSE J
9870 IF INKEY$ ="Y" THEN POKE G,D
9872 GOTO J
9873 REM
9874 PRINT " INPUT REM LINE LEN "
9875 INPUT D
9876 LET L=VAL "USR 16524-2"
9877 FOR G=SGN PI TO D
9878 POKE 16515,INT ((L+G)/F)
9879 POKE 16514,L+G-F*PEEK 16515
9880 RAND 16516
9881 POKE L+G,NOT PI
9882 NEXT G
9883 POKE L-SGN PI,INT ((D+A2)/F)
9884 POKE L-A2,D+A2-F*PEEK (L-SGN PI)
9885 GOTO J
9890 REM
9891 CLS
9893 LIST 9893
9894 LET NO=VAL "PEEK 16425+256*PEEK 16426"
9895 POKE NO,NOT PI
9896 POKE (NO+SGN PI),NOT PI
9897 STOP
9907 REM
9908 PRINT ,," FOR AN ASIS SAVE INPUT ""C"""
9910 SAVE "AI[D]"
9911 GOTO SGN PI
9924 REM
9926 CLS
9927 LET G=PEEK D*F+PEEK (D+SGN PI)
9928 PRINT AT CODE ",,",CODE "▖"-LEN STR$ G;G;
9929 LET D=D+CODE "▖"
9930 IF PEEK D=VAL "126" THEN LET D=D+CODE "▞"
9931 IF PEEK D=VAL "118" THEN LET G=NOT G
9932 IF G THEN PRINT CHR$ PEEK D;
9933 LET D=D+SGN PI
9934 IF G THEN GOTO 9930
9936 PAUSE J
9938 GOTO VAL "9926"
9941 REM
9943 PRINT " INPUT START NO. THEN INPUT STEP "
9944 INPUT G
9945 LET M=G
9946 INPUT FF
9947 CLS
9948 PRINT "CHANGE THESE LINES"
9949 LET I=VAL "16513"
9950 IF PEEK I<>VAL "118" THEN GOTO 9954
9951 IF VAL "PEEK (I+1)>34" THEN GOTO 9985
9952 LET M=M+FF
9953 LET I=I+CODE "▌"
9954 LET H=VAL "(1 AND PEEK I=236)+(2 AND PEEK I=237)"
9955 IF PEEK I=VAL "126" THEN LET I=I+CODE "▌"
9956 IF H THEN GOSUB 9959
9957 LET I=I+SGN PI
9958 GOTO 9950
9959 PRINT M;(" GOTO " AND H=SGN PI)+(" GOSUB " AND H=A2);
9960 LET H=NOT H
9961 IF VAL "PEEK (I+1)>27 AND PEEK (I+1)<38" THEN GOTO 9964
9962 PRINT " * "
9963 RETURN
9964 LET J=A2
9965 IF PEEK (I+J)=VAL "126" THEN GOTO 9969
9966 LET J=J+SGN PI
9967 IF J>CODE "▌" THEN GOTO 9962
9968 GOTO 9965
9969 LET L=SGN PI
9970 LET K=NOT J
9971 LET K=K+VAL "(PEEK (I+J-1)-28)"*L
9972 LET J=J-SGN PI
9973 IF VAL "PEEK (I+J-1)=236 OR PEEK (I+J-1)=237" THEN GOTO 9976
9974 LET L=L*CODE "~~"
9975 GOTO 9971
9976 LET J=VAL "16509"
9977 LET N=NOT J
9978 IF PEEK J*F+PEEK (J+SGN PI)>=K THEN GOTO 9982
9979 LET N=N+SGN PI
9980 LET J=J+VAL "PEEK (J+2)+PEEK (J+3)*F+4"
9981 GOTO 9978
9982 LET K=G+N*FF
9983 PRINT K
9984 RETURN
9985 LET J=NOT J
9986 LET I=VAL "16509"
9987 GOSUB 9990
9988 LET I=I+VAL "PEEK (I+2)+PEEK (I+3)*F+4"
9989 GOTO 9987
9990 IF PEEK I>CODE "6" THEN STOP
9991 IF G<F THEN GOTO 9994
9992 LET J=J+SGN PI
9993 LET G=G-F
9994 POKE I,J
9995 POKE (I+SGN PI),G
9996 LET G=G+FF
9997 RETURN
9998 REM <
9999 REM
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
