DISA-Z is a Z80 disassembler written in BASIC that reads machine code from memory and prints human-readable mnemonics to a printer. It supports the full Z80 instruction set including all prefix bytes: CB (bit operations), DD (IX-indexed), FD (IY-indexed), and ED (extended instructions), as well as relative jump target resolution. A configuration flag at line 190 (`TS2=0` or `TS2=1`) switches hex digit output between the ZX81/TS1000 and TS2068 character sets, since the two platforms place A–F at different character code offsets. The program uses octal decomposition of opcodes (breaking each byte into two 3-bit fields and one further subdivision) to classify and decode instructions, a technique that mirrors the Z80’s own internal opcode structure. Output is sent via LPRINT and includes the address, raw hex bytes, and mnemonic for each instruction.
Program Analysis
Program Structure
The program is organised as a collection of subroutines branched to from a main loop starting at line 3500. After an INPUT J to set the start address, the loop at lines 3520–3700 repeatedly disassembles one instruction, prints it, and advances. The top-level flow per instruction is:
- Clear state variables (
DD,FD,CB) and the hex stringH$(lines 3520–3580). - Format the address via
GOSUB 350(address hexer). - Determine instruction length via
GOSUB 420(lines 430–960). - Peek and hex-format each byte of the instruction (lines 3630–3660).
- Generate the mnemonic string via
GOSUB 970(lines 970–3410). - Send the completed line to the printer with
LPRINT H$.
Platform Switch
Line 190 sets TS2=0 for ZX81/TS1000 or TS2=1 for TS2068. The constant NCOD (line 200) evaluates to either 28 (ZX81, where digit characters start at code 28) or 48 (TS2068, standard ASCII). The hex formatter at line 330 uses NCOD+Y+7*(Y>9)*TS2 to select the correct character code for A–F, compensating for the gap between digit and letter character codes on each platform.
Opcode Decoding via Octal Decomposition
The subroutine at line 230 decomposes an opcode byte into octal fields. It finds K (the top 2 bits, 0–3), then extracts C (bits 5–3, the middle octet) and T (bits 2–0, the low triad). This directly mirrors the Z80 designers’ own encoding scheme, where the three octal digits of an opcode determine its instruction group, register operand, and operation type respectively.
Instruction Length Calculation
Before disassembling mnemonics, the program must know how many bytes the instruction occupies so it can fetch operand bytes. The subroutine at line 420 handles prefix chaining: DD (0xDD) and FD (0xFD) prefixes call a helper (line 480) that peeks the next byte without permanently advancing the pointer, and recursively re-evaluates. The length is built up in variable L, with separate paths for:
- CB-prefixed bit instructions (line 550 → line 940)
- ED-prefixed extended instructions (lines 560–700)
- Unprefixed main-table instructions (lines 710–910)
The helper at line 920 handles two-byte operands (adding 2 to L) and line 940 adds 1 for single-byte operands; line 950 always adds 1 for the opcode itself.
Hex Formatting
The byte hexer (lines 300–340) peeks address J and appends two hex characters to H$. The address hexer (lines 360–410) calls the byte hexer twice for high and low bytes of a 16-bit address and appends a space. Operand bytes embedded in H$ at fixed character positions are later extracted by substring references such as H$(8 TO 9) (low byte) and H$(10 TO 11) (high byte), allowing the mnemonic builders to reuse already-formatted hex data without re-peeking memory.
Mnemonic Generation
The mnemonic subroutine (line 970) pads H$ to at least 14 characters, then dispatches by opcode group. Lookup tables stored as compact strings are used throughout:
| Variable | Contents | Usage |
|---|---|---|
O$ | ADDADCSUBSBCANDXOROR CP | ALU operation names (3 chars each) |
D$ | BCDEHLSPAFIXIY | 16-bit register pair names (2 chars each) |
R$ | BCDEHLXA | 8-bit register names (1 char each) |
E$ | NZZ NCC POPEP M | Condition code names (2 chars each) |
F$ | RLCARRCARLA RRA DAA CPL SCF CCF | Misc. first-group mnemonics (4 chars each) |
B$ | BITRESSET | CB-group bit instruction names (3 chars each) |
C$ | RSLRC AL | CB shift/rotate sub-field characters |
G$ | LDCPINOT | ED block instruction base names (2 chars each) |
Index Register Substitution
The subroutine at line 1170 checks the DD and FD flags. When neither is set, the “H” register slot (R$ position 6, labelled "X" internally) is replaced by (HL). When a prefix is active, the helper at line 1210 builds an (IX+d) or (IY+d) string by reading the displacement byte already formatted in H$(10 TO 11), neatly avoiding a second PEEK call.
Relative Jump Resolution
Lines 2180–2220 resolve JR and DJNZ target addresses. The displacement byte is read with PEEK (J-1) and sign-extended using the idiom (byte AND (byte<128)) + ((byte-256) AND (byte>127)), which converts an unsigned 0–255 value to a signed −128 to +127 integer without any bit-manipulation keywords. The absolute target address is then formatted as hex via the address hexer.
RST Instruction Formatting
Lines 1990–2010 compute the RST vector from octet field C: W=INT(C/2) gives the upper digit and 8*(C-2*W) the lower, producing values like RST 38 rather than the more conventional RST 38H. The result is decimal, not hex — a cosmetic anomaly compared to standard Z80 assembler notation.
ED-Prefix Block Instructions
Lines 2740–2840 handle the LDI, LDD, LDIR, LDDR, CPI, CPD, CPIR, CPDR, INI, IND, INIR, INDR, OUTI, OUTD, OTIR, and OTDR instructions by building suffixes: the I/D direction from the even/odd column, and the optional R repeat suffix from whether C>5.
Anomalies and Notes
- Line 2510 has no handler for
C=0(opcode 0xC3 is caught earlier at line 830) orC=1(handled by theT=1path). The label at 2520 is missing from the listing — line 2520 does not appear, so there is a gap between 2510 and 2530 that skips no code but may confuse a reader. - Line 2100 outputs
EX AF,AF"with a literal trailing double-quote character embedded in the string to represent the conventionalAF'prime notation. - The
OUT (C),0undocumented ED instruction is not specifically handled; theC=7column of the ED 0x70/0x78 row falls through silently. - The variable
CBis set at line 3180 but never tested elsewhere in the listing — it appears to be a flag reserved for future use or a remnant from development. - The main loop at line 3700 uses
GOTO 3520(not3510), so it does not re-prompt for an address; the disassembler runs continuously from the initial address without stopping.
Content
Source Code
10 REM *********************** DISA-Z
20 REM *********************** A Z80 DISASSEMBLER FOR TS COMPUTERS
30 REM ***********************
40 REM *********************** COPYRIGHT, 1983 RAY KINGSLEY
50 REM *********************** RUN AND ENTER START ADDRESS IN DECIMAL
60 REM ***********************
70 REM ***********************
90 REM DATA STRINGS
100 LET O$="ADDADCSUBSBCANDXOROR CP "
110 LET D$="BCDEHLSPAFIXIY"
120 LET B$="BITRESSET"
130 LET C$="RSLRC AL"
140 LET R$="BCDEHLXA"
150 LET E$="NZZ NCC POPEP M "
160 LET F$="RLCARRCARLA RRA DAA CPL SCF CCF "
170 LET G$="LDCPINOT"
180 REM FOR TS2068 SET TS2=1
190 LET TS2=0
200 LET NCOD=28+20*TS2
220 GOTO 3500
230 REM OCTAL DIGITS
240 FOR K=0 TO 3
250 IF X0>=K*64 AND X0<(K+1)*64 THEN LET X=X0-K*64
260 NEXT K
270 LET C=INT (X/8)
280 LET T=X-C*8
290 RETURN
295 REM BYTE HEXER
300 LET X=PEEK J
310 LET Y=INT (X/16)
320 LET Z=X-Y*16
330 LET H$=H$+CHR$ (NCOD+Y+7*(Y>9)*TS2)+CHR$ (NCOD+Z+7*(Z>9)*TS2)
340 RETURN
350 REM ADDRESS HEXER
360 LET X=INT (J/256)
370 GOSUB 310
380 LET X=J-256*X
390 GOSUB 310
400 LET H$=H$+" "
410 RETURN
420 REM GET INSTRUCTION LENGTH
430 LET L=0
440 IF X<>221 AND X<>253 THEN GOTO 540
450 IF L THEN RETURN
460 GOSUB 480
470 GOTO 440
480 LET L=1
490 LET J=J+1
500 GOSUB 300
510 LET J=J-1
520 LET H$=H$( TO LEN H$-2)
530 RETURN
535 REM I-LENGTH FOR PREFIXES
540 IF L THEN LET L=L+((X>51) AND (X<55) OR X=203)
550 IF X=203 THEN GOTO 940
560 IF X<>237 THEN GOTO 710
570 GOSUB 480
580 IF X<64 OR X>188 THEN RETURN
590 IF X<160 AND X>123 THEN RETURN
600 IF X<124 THEN GOTO 630
610 IF X-INT (X/8)*8<5 THEN GOTO 950
620 RETURN
630 IF X=78 OR X=102 OR X=110 OR X=112 OR X=113 OR X=118 OR X=119 THEN RETURN
640 LET W=X-67
650 IF NOT (W-INT (W/8)*8) THEN GOTO 920
660 LET W=X-76
670 IF W>=0 AND NOT (W-INT (W/8)*8) THEN RETURN
680 LET W=X-85
690 IF W>=0 AND NOT (W-INT (W/8)*8) THEN RETURN
700 GOTO 950
705 REM WITHOUT PREFIXES
710 IF X<64 OR X>191 THEN GOTO 740
720 IF L THEN LET L=L+(X-8*INT (X/8)=6)
730 GOTO 950
740 IF X>191 THEN GOTO 830
750 IF Z=1 THEN GOTO 920
760 LET W=X-34
770 IF W>=0 AND NOT (W-INT (W/8)*8) THEN GOTO 920
780 LET W=X-6
790 IF W>=0 AND NOT (W-INT (W/8)*8) THEN GOTO 940
800 LET W=X-16
810 IF W>=0 AND NOT (W-INT (W/8)*8) THEN GOTO 940
820 GOTO 950
830 IF X=195 OR X=205 THEN GOTO 920
840 IF X=211 OR X=219 THEN GOTO 940
850 LET W=X-194
860 IF NOT (W-INT (W/8)*8) THEN GOTO 920
870 LET W=W-2
880 IF NOT (W-INT (W/8)*8) THEN GOTO 920
890 LET W=W-2
900 IF NOT (W-INT (W/8)*8) THEN GOTO 940
910 GOTO 950
920 IF L=2 THEN GOTO 940
930 LET L=L+1
940 LET L=L+1
950 LET L=L+1
960 RETURN
970 REM MNEMONICS
980 LET H$=H$+" "
990 IF LEN H$<14 THEN GOTO 980
\n1000 IF X0=118 THEN GOTO 1290
\n1010 GOSUB 230
\n1020 IF X0<64 OR X0>191 THEN GOTO 1400
\n1030 IF X0>127 THEN GOTO 1310
\n1035 REM EIGHT-BIT REG LDS.
\n1040 LET P$=R$(C+1)
\n1050 LET Q$=R$(T+1)
\n1060 IF P$="X" OR Q$="X" THEN GOSUB 1170
\n1070 LET H$=H$+"LD "+P$+","+Q$
\n1080 RETURN
\n1085 REM ADD POINTER REGS TO H$
\n1090 IF NOT DD THEN GOTO 1120
\n1100 LET H$=H$+"IX"
\n1110 RETURN
\n1120 IF NOT FD THEN GOTO 1150
\n1130 LET H$=H$+"IY"
\n1140 RETURN
\n1150 LET H$=H$+"HL"
\n1160 RETURN
\n1165 REM CHECK FOR FD OR DD
\n1170 IF FD OR DD THEN GOTO 1210
\n1180 IF P$="X" THEN LET P$="(HL)"
\n1190 IF Q$="X" THEN LET Q$="(HL)"
\n1200 RETURN
\n1205 REM ADD INDEX REGS TO H$
\n1210 IF FD THEN LET W$="(IY+"
\n1220 IF DD THEN LET W$="(IX+"
\n1230 IF P$="X" THEN LET P$=W$+H$(10 TO 11)+")"
\n1240 IF Q$="X" THEN LET Q$=W$+H$(10 TO 11)+")"
\n1250 RETURN
\n1260 GOSUB 1170
\n1270 LET H$=H$+P$+","+R$(1+T)
\n1280 RETURN
\n1290 LET H$=H$+"HLT"
\n1300 RETURN
\n1310 REM ARITH/LOGIC OPS
\n1320 LET I=C*3+1
\n1330 LET Q$=R$(T+1)
\n1340 GOSUB 1170
\n1350 LET I$=" "
\n1360 IF I<7 OR I=10 THEN LET I$=" A,"
\n1370 IF I>18 THEN LET I$=""
\n1380 LET H$=H$+O$(I TO I+2)+I$+Q$
\n1390 RETURN
\n1395 REM 1ST AND 4TH GROUPS
\n1400 IF X0=203 THEN GOTO 3170
\n1410 IF X0=253 OR X0=221 THEN GOTO 3420
\n1420 IF X0>191 THEN GOTO 1570
\n1425 REM 1ST GROUP
\n1430 IF T=1 THEN GOTO 2020
\n1440 IF T=3 THEN GOTO 2240
\n1450 IF T=4 OR T=5 THEN GOTO 2300
\n1460 IF T=2 THEN GOTO 2370
\n1470 IF NOT T THEN GOTO 2080
\n1480 IF T<>6 THEN GOTO 1540
\n1490 LET Q$=R$(C+1)
\n1500 GOSUB 1170
\n1510 LET W=4*(FD OR DD)
\n1520 LET H$=H$+"LD "+Q$+","+H$(8+W TO 9+W)
\n1530 RETURN
\n1540 LET W=4*C+1
\n1550 LET H$=H$+F$(W TO W+3)
\n1560 RETURN
\n1570 REM DIRECT ARITHMETIC
\n1580 IF T<>6 THEN GOTO 1660
\n1590 LET I=3*C+1
\n1600 LET I$=" "
\n1610 IF I<7 OR I=10 THEN LET I$=" A,"
\n1620 IF I>18 THEN LET I$=""
\n1630 LET H$=H$+O$(I TO I+2)+I$
\n1640 LET H$=H$+H$(8 TO 9)
\n1650 RETURN
\n1660 REM 4TH GROUP
\n1670 IF X0=237 THEN GOTO 2700
\n1680 IF T=1 AND NOT (C-INT (C/2)*2) THEN GOTO 1920
\n1690 IF T=7 THEN GOTO 1990
\n1700 IF T=5 AND NOT (C-INT (C/2)*2) THEN GOTO 1940
\n1710 LET FL=0
\n1720 IF X0=205 OR T=4 THEN GOSUB 1830
\n1730 IF X0=195 OR T=2 THEN GOSUB 1800
\n1740 IF X0=201 OR NOT T THEN GOSUB 1870
\n1750 IF NOT T OR T=2 OR T=4 THEN GOSUB 1890
\n1760 IF T=3 AND NOT FL THEN GOTO 2510
\n1770 IF T=1 AND NOT FL THEN GOTO 2610
\n1780 IF FL THEN GOSUB 1850
\n1790 RETURN
\n1795 REM MAIN CONDITIONALS
\n1800 LET H$=H$+"JP "
\n1810 LET FL=1
\n1820 RETURN
\n1830 LET H$=H$+"CALL "
\n1840 GOTO 1810
\n1850 LET H$=H$+H$(10 TO 11)+H$(8 TO 9)
\n1860 RETURN
\n1870 LET H$=H$+"RET "
\n1880 GOTO 1810
\n1890 LET H$=H$+E$(2*C+1 TO 2*(C+1))
\n1900 IF NOT (C=1 OR C=3 OR C>5) THEN LET H$=H$+" "
\n1910 RETURN
\n1915 REM GROUP 4:C EVEN,T=1 OR 5
\n1920 LET H$=H$+"POP "
\n1930 GOTO 1950
\n1940 LET H$=H$+"PUSH "
\n1950 IF C=6 THEN LET C=8
\n1960 IF C=4 THEN LET C=C+6*(FD OR DD)
\n1970 LET H$=H$+D$(1+C TO 2+C)
\n1980 RETURN
\n1985 REM GROUP 4:T=7
\n1990 LET W=INT (C/2)
\n2000 LET H$=H$+"RST "+STR$ (W)+STR$ (8*(C-2*W))
\n2010 RETURN
\n2020 REM GROUP 1:T=1
\n2030 IF C-2*INT (C/2) THEN GOTO 2060
\n2040 LET H$=H$+"LD "+D$(C+1 TO C+2)+","
\n2050 GOTO 1850
\n2060 LET H$=H$+"ADD HL,"+D$(C TO C+1)
\n2070 RETURN
\n2080 REM GROUP 1:T=0 (JRS)
\n2090 IF C=0 THEN LET H$=H$+"NOP"
\n2100 IF C=1 THEN LET H$=H$+"EX AF,AF"""
\n2110 IF C=2 THEN LET H$=H$+"DJNZ"
\n2120 IF C>1 THEN GOTO 2140
\n2130 RETURN
\n2140 IF C>2 THEN LET H$=H$+"JR "
\n2150 LET W=C*2-7
\n2160 IF C>3 THEN LET H$=H$+E$(W TO W+1)
\n2170 IF NOT (C-2*INT (C/2)) THEN LET H$=H$+" "
\n2180 LET W=(PEEK (J-1) AND (PEEK (J-1)<128))+((PEEK (J-1)-256) AND (PEEK (J-1)>127))
\n2190 LET J0=J
\n2200 LET J=J+W
\n2210 GOSUB 350
\n2220 LET J=J0
\n2230 RETURN
\n2240 REM GROUP 1:T=3
\n2250 LET Q$="INC "
\n2260 IF C-2*INT (C/2) THEN LET Q$="DEC "
\n2270 LET W=2*INT (C/2)+1
\n2280 LET H$=H$+Q$+D$(W TO W+1)
\n2290 RETURN
\n2300 REM GROUP 1:T=4 OR 5
\n2310 LET Q$=R$(C+1)
\n2320 GOSUB 1170
\n2330 LET P$="INC "
\n2340 IF T-2*INT (T/2) THEN LET P$="DEC "
\n2350 LET H$=H$+P$+Q$
\n2360 RETURN
\n2370 REM GROUP 1:T=2
\n2380 LET H$=H$+"LD "
\n2390 IF NOT (C-2*INT (C/2)) THEN GOTO 2460
\n2400 IF C=5 THEN GOSUB 1090
\n2410 IF C=5 THEN GOTO 2430
\n2420 LET H$=H$+"A"
\n2430 IF C>3 THEN LET H$=H$+",("+H$(10 TO 11)+H$(8 TO 9)+")"
\n2440 IF C<4 THEN LET H$=H$+",("+D$(C TO C+1)+")"
\n2450 RETURN
\n2460 IF C<4 THEN LET H$=H$+"("+D$(C+1 TO C+2)+"),"
\n2470 IF C>3 THEN LET H$=H$+"("+H$(10 TO 11)+H$(8 TO 9)+"),"
\n2480 IF C=4 THEN GOTO 1090
\n2490 LET H$=H$+"A"
\n2500 RETURN
\n2510 REM GROUP 4:T=3
\n2530 IF C=2 THEN LET H$=H$+"OUT "+H$(8 TO 9)+",A"
\n2540 IF C=3 THEN LET H$=H$+"IN A,"+H$(8 TO 9)
\n2550 IF C=4 THEN LET H$=H$+"EX(SP),HL"
\n2560 IF C=5 THEN LET H$=H$+"EX DE,HL"
\n2580 IF C=6 THEN LET H$=H$+"DI"
\n2590 IF C=7 THEN LET H$=H$+"EI"
\n2600 RETURN
\n2610 REM GROUP 4:T=1
\n2620 IF C=3 THEN LET H$=H$+"EXX"
\n2630 IF C=5 THEN LET H$=H$+"JP("
\n2640 IF C=7 THEN LET H$=H$+"LD SP,"
\n2650 IF C<5 THEN RETURN
\n2660 GOSUB 1090
\n2670 IF C=7 THEN RETURN
\n2680 LET H$=H$+")"
\n2690 RETURN
\n2700 REM ED PREFIXES TO 3610
\n2710 IF L=1 THEN GOTO 3460
\n2720 LET X0=PEEK (J-L+1)
\n2730 GOSUB 230
\n2740 IF X0<160 OR X0>187 THEN GOTO 2850
\n2750 IF T>3 THEN RETURN
\n2760 IF T=3 AND C<6 THEN LET Q$="OUT"
\n2770 IF T=3 AND C<6 THEN GOTO 2800
\n2780 LET W=2*T+1
\n2790 LET Q$=G$(W TO W+1)
\n2800 IF (C-2*INT (C/2)) THEN LET Q$=Q$+"D"
\n2810 IF NOT (C-2*INT (C/2)) THEN LET Q$=Q$+"I"
\n2820 IF C>5 THEN LET Q$=Q$+"R"
\n2830 LET H$=H$+Q$
\n2840 RETURN
\n2850 IF X0<64 OR X0>123 THEN RETURN
\n2860 IF T>1 THEN GOTO 2910
\n2870 LET Q$=R$(C+1)
\n2880 IF T THEN LET H$=H$+"OUT(C),"+Q$
\n2890 IF NOT T THEN LET H$=H$+"IN "+Q$+",(C)"
\n2900 RETURN
\n2910 LET W=INT (C/2)
\n2920 IF T<>2 THEN GOTO 2960
\n2930 IF C-2*W THEN LET H$=H$+"ADD HL,"+D$(2*W+1 TO 2*W+2)
\n2940 IF NOT (C-2*W) THEN LET H$=H$+"SBC HL,"+D$(2*W+1 TO 2*W+2)
\n2950 RETURN
\n2960 IF T<>3 THEN GOTO 3020
\n2970 IF C-2*W THEN GOTO 3000
\n2980 LET H$=H$+"LD("+H$(12 TO 13)+H$(10 TO 11)+"),"+D$(2*W+1 TO 2*W+2)
\n2990 RETURN
\n3000 LET H$=H$+"LD "+D$(2*W+1 TO 2*W+2)+",("+H$(12 TO 13)+H$(10 TO 11)+")"
\n3010 RETURN
\n3020 IF T<>7 THEN GOTO 3120
\n3030 IF C>3 THEN GOTO 3090
\n3040 IF C=2*W THEN LET Q$="I"
\n3050 IF C<>2*W THEN LET Q$="R"
\n3060 IF C>1 THEN LET H$=H$+"LD A,"+Q$
\n3070 IF C<2 THEN LET H$=H$+"LD "+Q$+",A"
\n3080 RETURN
\n3090 IF C=4 THEN LET H$=H$+"RRD"
\n3100 IF C=5 THEN LET H$=H$+"RLD"
\n3110 RETURN
\n3120 IF T=6 AND C<4 AND C<>1 THEN LET H$=H$+"IM "+STR$ ((C>0)*(C-1))
\n3130 IF X0=68 THEN LET H$=H$+"NEG"
\n3140 IF X0=69 THEN LET H$=H$+"RETN"
\n3150 IF X0=77 THEN LET H$=H$+"RETI"
\n3160 RETURN
\n3170 REM BIT OPS
\n3180 LET CB=1
\n3190 LET X0=PEEK (J-1)
\n3200 LET W=INT (X0/64)
\n3210 LET X0=X0-W*64
\n3220 IF W THEN GOTO 3350
\n3230 LET B1=1+INT (X0/32)
\n3240 LET B2=INT (X0/16)
\n3250 LET X0=X0-B2*16
\n3260 LET B3=INT (X0/8)+3
\n3270 LET B2=B2+5
\n3280 LET X0=1+X0-(B3-3)*8
\n3290 LET Q$=R$(X0)
\n3300 GOSUB 1170
\n3310 LET H$=H$+C$(B1)+C$(B3)+C$(B2)
\n3320 IF B2<>6 THEN LET H$=H$+" "
\n3330 LET H$=H$+Q$
\n3340 RETURN
\n3350 LET W=3*W-2
\n3360 LET D=INT (X0/8)
\n3370 LET X0=X0-D*8+1
\n3380 LET Q$=R$(X0)
\n3390 GOSUB 1170
\n3400 LET H$=H$+B$(W TO W+2)+" "+STR$ (D)+","+Q$
\n3410 RETURN
\n3420 REM FD,DD PREFIXES
\n3430 LET DD=X0=221
\n3440 LET FD=X0=253
\n3450 IF L>1 THEN GOTO 3480
\n3460 LET H$=H$+"DATA"
\n3470 RETURN
\n3480 LET X0=PEEK (J-L+1)
\n3490 GOTO 1000
\n3500 REM MAIN LOOP
\n3510 INPUT J
\n3520 LET H$=""
\n3530 LET P$=H$
\n3540 LET Q$=H$
\n3550 LET DD=0
\n3560 LET FD=DD
\n3570 LET CB=DD
\n3580 GOSUB 350
\n3590 GOSUB 300
\n3600 GOSUB 420
\n3610 LET H$=H$( TO LEN H$-2)
\n3620 LET X0=PEEK J
\n3630 FOR K=1 TO L
\n3640 GOSUB 300
\n3650 LET J=J+1
\n3660 NEXT K
\n3670 GOSUB 970
\n3680 LPRINT H$
\n3700 GOTO 3520
\n3710 SAVE "1008%3"
\n3720 LIST
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
