--- title: "BATCODE" id: 51405 type: "computer_media" slug: "batcode" url: "http://localhost/computer_media/batcode/" markdown_url: "http://localhost/computer_media/batcode.md" published_at: "2023-07-30T08:20:55+00:00" modified_at: "2026-03-30T21:41:04+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2023/07/BATCODE-main.png" excerpt: "A full Core War programming environment — editor, assembler, and battle engine — lets two Redcode programs fight to the death inside a shared memory arena." 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/" indiv: - name: "Eduardo Fuentes" slug: "eduardo-fuentes" taxonomy: "indiv" url: "http://localhost/indiv/eduardo-fuentes/" genre: - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_type: "Program" programmers: - name: "Eduardo Fuentes" slug: "eduardo-fuentes" taxonomy: "indiv" url: "http://localhost/indiv/eduardo-fuentes/" download_url: "https://archive.org/download/timex-sinclair-software-archive/BATCODE%20%281986%29%28Martinez%20Lara%2C%20Sergio%20and%20Fuentes%2C%20Eduardo%29%28SP%20and%20BR%29%28TS2068%20and%20ZX%20Spectrum%29%28Program%29.zip" mediadate: "1986 and 2023" images: - url: "http://localhost/wp-content/uploads/2023/07/BATCODE-main.png" - url: "http://localhost/wp-content/uploads/2023/07/BATCODE-Help.png" media_type_tags: "Game" --- This program is a BASIC editor and simulator for “[Core War](https://en.wikipedia.org/wiki/Core_War),” a programming game in which two programs written in Redcode assembly battle each other inside a shared memory arena. The editor supports 13 Redcode mnemonics (DAT, JMP, DJN, MOV, ADD, SUB, JMZ, JMN, CMP, LDP, STP, XCH, NOP) with three addressing modes: immediate (#), indirect (@), and direct. Programs are stored as packed 5-byte records in string arrays, with the first byte encoding the opcode and both addressing mode nibbles, and the next four bytes storing the two operands as 16-bit little-endian two’s-complement integers. The battle engine itself is implemented as machine code loaded separately from tape and invoked via RANDOMIZE USR calls at addresses such as 64236, 64444, and 65507. Tape save/verify and a memory-transfer facility allow two competing programs to be loaded, swapped, or saved independently. Originally written by Sergio Martinez Lara, published in the Spanish language magazine Microhobby, [issues 70](https://kyenter.speccy.org/principl.php?accion=listar&revista=70) and [71](https://kyenter.speccy.org/principl.php?accion=listar&revista=71), BATCODE is a Redcode interpreter. It implements the [Core War programming game by D. G. Jones and A. K. Dewdney](https://en.wikipedia.org/wiki/Core_War). Translated to English by [Eduardo Fuentes](http://localhost/indiv/eduardo-fuentes/) in 2023. Eduardo updated the instruction set and made it [Redcode 94 compliant](http://www.koth.org/info/pmars-redcode-94.txt). He corrected some bugs and added a user’s guide, which is included in the download. *** ## Program Analysis ### Program Structure The program is organized into a command dispatcher at lines 1000–1170 that reads a single-letter command and branches accordingly, a syntactic analyzer/parser for Redcode assembly (lines 1490–1870), display and listing routines (lines 2040–2350), and dedicated command handlers for save, load, new, help, transfer, delete, move, and battle. Lines 8000–8030 save the BASIC program itself; lines 9000–9040 are the auto-run bootstrap that loads the companion machine code block from tape before jumping to line 10 (which does not exist, effectively falling through to line 50 — a deliberate technique). ### Data Representation Each Redcode instruction is stored as a 5-byte record packed into a string array. The first byte encodes the opcode in the high nibble and the two addressing mode fields in bits 3–2 and 1–0 respectively. The next two bytes are the first operand as a 16-bit little-endian value, and the final two bytes are the second operand in the same format. Two’s-complement negative values are converted by adding 65536 before packing (line 1930). Decoding reverses the process at lines 2370–2450 using integer division and modulo arithmetic. ### String Arrays as Memory Three large string arrays serve as the program’s working memory: - `p$(2500)` — the “player 1” warrior program (500 instructions × 5 bytes) - `m$(2500)` — the “player 2” warrior program - `f$(22000)` — the full 4400-cell arena used during battle Initializing a string array element to itself (e.g., `LET p$(1)=p$(1)`) is a well-known idiom that forces the interpreter to zero-fill the entire array without an explicit loop. ### Machine Code Integration The battle engine and several utility routines reside in a separately loaded machine code block. They are invoked via `RANDOMIZE USR` at fixed addresses: | Address | Purpose | | --- | --- | | `65502` | Zero-fill / clear a string array | | `65497` | Delete lines (bulk NOP fill) in `p$` | | `65507` | Initialize the arena `f$` with NOP instructions | | `64236` | Execute one battle step / full battle loop | | `64444` | Advance one execution step (step-by-step mode) | Parameters are passed to machine code by POKEing values directly into the code segment. For example, line 3040 uses `POKE 65498`/`65499` to pass a count, and lines 3140 sets the starting position of the second warrior via `POKE 64259`/`64260`. The step-by-step flag is passed at line 3170 via `POKE 64064`. ### Defined Functions Five `DEF FN` functions are declared at lines 50–90: - `FN j$(x)` — formats a number as a zero-padded 3-digit string - `FN s$(x)` — formats a number as a zero-padded 4-digit string (used for arena addresses) - `FN m(x)` — extracts the high byte of a 16-bit value (`INT(x/256)`) - `FN r(x)` — extracts the low byte (`x MOD 256` via subtraction) - `FN p(x)` — reads a 16-bit little-endian word from memory at address `x` Note that `FN s$` shadows the plain variable `s$` used as a blank-line string at line 200, which is a potential source of confusion but not a functional bug because the function and the variable occupy separate namespaces. ### Mnemonic Table The 13 Redcode opcodes are stored as a flat 39-character string `T$`, read from DATA at line 210, with each 3-character slice accessed as `t$(j*3+1 TO j*3+3)`. The opcodes and their indices are: | Index (j) | Mnemonic | Operand count | | --- | --- | --- | | 0 | DAT | 1 | | 1 | JMP | 1 | | 2 | DJN | 2 | | 3 | MOV | 2 | | 4 | ADD | 2 | | 5 | SUB | 2 | | 6 | JMZ | 2 | | 7 | JMN | 2 | | 8 | CMP | 2 | | 9 | LDP | 2 | | 10 | STP | 2 | | 11 | XCH | 1 | | 12 | NOP | 0 (blank line) | ### Parser Design The parser is a simple recursive-descent style analyzer. `GO SUB 1830` skips whitespace; `GO SUB 1640` reads a raw decimal number (with optional sign); `GO SUB 1730` reads an operand with an optional `#` (immediate, `md=1`) or `@` (indirect, `md=2`) prefix; `GO SUB 1490` reads two operands; and `GO SUB 1580` reads one operand. Errors are signaled via the variable `error` and displayed with a caret pointer at line 1890. ### Battle Execution Flow When the `E` command is issued, the arena `f$` is first filled with NOP instructions by the machine code at 65507. Player 1’s program is then copied into the arena starting at offset 1 (lines 3182–3184 use 250-byte chunks to work around string-slice size limits). Player 2 is placed at a random offset `pos2` between 1000 and 3400. The battle loop at line 3210 calls machine code at 64236 repeatedly, checking `PEEK 65122` for termination and `PEEK 65121` for the loser identity (encoded as A=1, B=2 via `CHR$(64+...)`). ### Notable Techniques and Anomalies - The title banner string `c$` is constructed at lines 130–140 by decoding pairs of decimal digits from a DATA string into characters, building a custom display string at runtime. - Line 2100 uses an address limit of 500 for `p$` listings, consistent with 500 instructions × 5 bytes = 2500, but line 2110 allows up to 4400 entries for the arena dump, matching `f$(22000)`. - The listing routine uses `CHR$(8)` (cursor left) at lines 2240–2250 to backspace over a space already printed before printing the addressing mode character, achieving in-place overwriting without attribute color changes. - The `POKE 23658,8` at line 1010 sets the caps-lock system variable so that `INPUT LINE` accepts lowercase input naturally. - Line 3080 calls `GO SUB 1630` directly (bypassing the modifier check of 1730) to read a plain number for the move-line count, which is intentional since a destination offset has no addressing mode. ## Source Code ``` 10 REM 20 REM (c) 1985 30 REM Sergio Martinez Lara 40 REM 50 DEF FN j$(x)="000"( TO 3-LEN STR$ x)+STR$ x 60 DEF FN s$(x)="0000"( TO 4-LEN STR$ x)+STR$ x 70 DEF FN m(x)=INT (x/256) 80 DEF FN r(x)=x-256*INT (x/256) 90 DEF FN p(x)=PEEK x+256*PEEK (x+1) 100 DATA "32495756543283698271737932776582847378699032" 110 DATA "DAT","JMP","DJN","MOV","ADD","SUB","JMZ","JMN","CMP","LDP","STP","XCH","NOP" 120 RESTORE 130 READ w$: LET c$=" ": LET c$(2)=CHR$ 127 140 FOR i=1 TO LEN w$ STEP 2: LET c$=c$+CHR$ VAL w$(i TO i+1): NEXT i 150 PAPER 1: INK 7: BORDER 1: CLS 160 PRINT AT 0,7; PAPER 2;"* BATCODE EDITOR *" 170 PRINT AT 2,5; INVERSE 1; BRIGHT 1;c$ 180 DIM T$(39): DIM f$(22000): DIM p$(2500): DIM m$(2500) 190 LET linea=-1 200 LET s$=" " 210 FOR I=1 TO 39 STEP 3: READ t$(i TO i+2): NEXT i 220 LET p$(1)=p$(1): RANDOMIZE USR 65502 230 LET m$(1)=m$(1): RANDOMIZE USR 65502 240 PAUSE 50: CLS 250 GO SUB 1000: INPUT "End this game? (Y/N) "; LINE l$: IF l$="Y" THEN STOP 260 GO TO 250 1000 REM syntactic analyzer 1010 POKE 23658,8: INPUT "Command: "; LINE l$ 1020 IF l$="" THEN RETURN 1030 LET i=1: GO SUB 1830: LET l$=l$(i TO ): LET i=1: IF error THEN GO TO 1000 1040 LET long=LEN l$: LET l$=l$+" " 1050 IF l$(1)="L" THEN LET Z$="L": GO TO 2040 1060 IF l$(1)="D" THEN LET Z$="D": GO TO 2040 1070 IF l$(1)="P" THEN LET z$="L": GO TO 2010 1080 IF l$(1)="I" THEN LET z$="D": GO TO 2010 1090 IF l$(1)="S" THEN GO TO 2470 1100 IF l$(1)="C" THEN GO TO 2580 1110 IF l$(1)="N" THEN GO TO 2650 1120 IF l$(1)="H" THEN GO TO 2720 1130 IF l$(1)="T" THEN GO TO 2850 1140 IF l$(1)="E" THEN GO TO 3130 1150 IF l$(1)="R" THEN GO TO 3000 1160 IF l$(1)="M" THEN GO TO 3060 1170 LET i=1: GO SUB 1640 1180 IF error THEN GO SUB 1890: GO TO 1010 1190 LET dir=valor 1200 IF dir<0 OR dir>2500 THEN GO SUB 1890: GO TO 1010 1210 LET r$=l$(i TO ) 1220 IF long<=4 THEN GO TO 1980 1230 IF l$(i)<>" " THEN GO SUB 1880: GO TO 1010 1240 GO SUB 1830 1250 IF long" " THEN GO SUB 1890: GO TO 1010 1290 FOR j=0 TO 12 1300 IF w$=t$(j*3+1 TO j*3+3) THEN GO TO 1330 1310 NEXT j 1320 GO SUB 1890: GO TO 1010 1330 LET cod=j 1335 IF cod=12 THEN GO TO 1980 1340 IF (cod=0 OR cod=1 OR cod=11) THEN GO SUB 1580: GO TO 1360 1350 GO SUB 1490 1360 IF error THEN GO SUB 1890: GO TO 1010 1370 LET x=op1 1380 GO SUB 1920 1390 LET v$=w$ 1400 IF cod=0 OR cod=1 THEN LET w$=CHR$ 0+CHR$ 0: LET md2=0: GO TO 1430 1410 LET x=op2 1420 GO SUB 1920 1430 LET p$(dir*5-4 TO dir*5)=CHR$ (16*cod+4*md1+md2)+v$+w$ 1440 PRINT AT 20,0;s$;s$ 1450 IF linea<19 THEN : LET linea=linea+1: GO TO 1470 1460 PRINT AT 21,0: POKE 23692,255: PRINT 1470 PRINT AT linea,0;FN j$(dir);r$ 1480 GO TO 1000 1490 REM ANALYSIS OF 2 OPERANDS 1500 GO SUB 1730 1510 IF error THEN RETURN 1520 IF I>long THEN LET error=1: RETURN 1530 LET md1=md: LET op1=valor 1540 GO SUB 1730 1550 IF error THEN RETURN 1560 LET md2=md: LET op2=valor 1570 RETURN 1580 REM ANALYSIS OF 1 OPERAND 1590 GO SUB 1730 1600 IF error THEN RETURN 1610 LET md1=md: LET op1=valor: LET md2=0: LET op2=0 1620 RETURN 1630 REM get a number 1640 GO SUB 1830: IF error THEN GO SUB 1890: GO TO 1000 1650 LET w$="" 1660 FOR i=i TO i+4 1670 IF l$(i)=" " THEN GO TO 1710 1680 IF (l$(i)<"0" OR l$(i)>"9") AND l$(i)<>"+" AND l$(i)<>"-" THEN LET error=1: RETURN 1690 LET w$=w$+l$(i) 1700 NEXT i 1710 LET valor=VAL w$ 1720 RETURN 1730 REM number with modifier 1740 LET md=0 1750 IF i>long THEN LET error=1: RETURN 1760 IF l$(i)<>" " THEN LET error=1: RETURN 1770 LET i=i+1 1780 IF i>long THEN LET error=1: RETURN 1790 IF l$(i)="#" THEN LET i=i+1: LET md=1: GO TO 1810 1800 IF l$(i)="@" THEN LET i=i+1: LET md=2: GO TO 1810 1810 GO SUB 1630 1820 RETURN 1830 REM SKIP SPACES 1840 LET error=0 1850 IF i>LEN l$ THEN LET error=1: RETURN 1860 IF l$(i)=" " THEN LET i=i+1: GO TO 1850 1870 RETURN 1880 REM ERROR MESSAGE 1890 PRINT AT 20,0;s$;s$;AT 20,0;l$;AT 21,i-1;"^ ERROR" 1900 BEEP 0.5,20 1910 RETURN 1920 REM 2 complement converter 1930 IF x<0 THEN LET x=x+65536 1940 LET w$=" " 1950 LET w$(2)=CHR$ (INT (x/256)) 1960 LET w$(1)=CHR$ (x-256*CODE w$(2)) 1970 RETURN 1980 REM borrado de una linea 1990 LET cod=12: LET op1=0: LET op2=op1: LET md1=op1: LET md2=op1 2000 GO TO 1370 2010 REM impresion 2020 LET x=3 2030 GO TO 2060 2040 REM listado 2050 LET x=2 2060 CLS 2070 LET dir=1 2080 IF LEN l$<3 THEN GO TO 2120 2090 LET i=2: GO SUB 1630 2100 IF error=0 AND valor>1 AND valor<=500 THEN LET dir=valor*5-4 2110 IF z$="D" AND (error=0 AND valor>1 AND valor<=4400) THEN LET dir=valor*5-4 2120 FOR i=0 TO 19 2130 IF Z$="D" THEN LET w$=F$(dir TO dir+4): GO TO 2150 2140 LET w$=p$(dir TO dir+4) 2150 GO SUB 2360 2160 IF z$<>"D" THEN PRINT #x;FN j$(INT (dir/5)+1);: GO TO 2180 2170 PRINT #x;FN s$(INT (dir/5)+1); 2180 PRINT #x;" ";t$(cod*3+1 TO cod*3+3);" "; 2190 IF cod=12 THEN GO TO 2270 2200 IF md1=1 THEN PRINT #x;"#";: GO TO 2220 2210 IF md1=2 THEN PRINT #x;"@";: GO TO 2220 2215 PRINT #x;" "; 2220 PRINT #x;op1;TAB 14; 2230 IF cod<=1 OR cod=11 THEN GO TO 2270 2240 IF md2=1 THEN PRINT #x;CHR$ (8);"#"; 2250 IF md2=2 THEN PRINT #x;CHR$ (8);"@"; 2260 PRINT #x;op2; 2270 LET dir=dir+5: IF dir>22000 THEN LET dir=1 2280 IF Z$="L" AND dir>2500 THEN LET dir=1 2290 PRINT #x: NEXT i 2300 PRINT AT 21,0;"Press 'Y' to continue listing " 2310 PAUSE 0: LET w$=INKEY$ 2320 IF w$="y" OR w$="Y" THEN CLS : GO TO 2120 2330 LET linea=19 2340 PRINT AT 20,0;s$;s$ 2350 GO TO 1000 2360 REM decodification 2370 LET md2=CODE w$(1) 2380 LET op1=CODE w$(2)+256*CODE w$(3) 2390 IF op1>32767 THEN LET op1=op1-65536 2400 LET op2=CODE w$(4)+256*CODE w$(5) 2410 IF op2>32767 THEN LET op2=op2-65536 2420 LET cod=INT (md2/16) 2430 LET md2=md2-cod*16 2440 LET md1=INT (md2/4) 2450 LET md2=md2-md1*4 2460 RETURN 2470 REM save program 2480 CLS 2490 PRINT AT 0,7; PAPER 2;"* SAVE PROGRAMS *" 2500 PRINT AT 2,5; INVERSE 1; BRIGHT 1;c$ 2510 INPUT "Programs name to save: "; LINE w$ 2520 IF w$="" THEN GO TO 2840 2530 SAVE w$ DATA p$() 2540 PRINT #1;"Rewind the tape to verify " 2550 PRINT AT 10,0; 2560 VERIFY w$ DATA p$() 2570 GO TO 2840 2580 REM load program 2590 CLS 2600 PRINT AT 0,7; PAPER 2;"* LOAD PROGRAMS *" 2610 PRINT AT 2,5; INVERSE 1; BRIGHT 1;c$ 2620 INPUT "Programs name to load: "; LINE w$ 2630 LOAD "" DATA p$() 2640 GO TO 2840 2650 REM NEW PROGRAM 2660 CLS 2670 PRINT AT 0,12; FLASH 1; PAPER 2;"* ""NEW"" *" 2680 PRINT AT 2,5; INVERSE 1; BRIGHT 1;c$ 2690 INPUT "Sure? (Y/N)";w$ 2700 IF w$="Y" OR w$="y" THEN LET p$(1)=p$(1): RANDOMIZE USR 65502: GO TO 2840 2710 GO TO 2840 2720 REM Help screen 2730 LET w$="H-Help R-Rubout ln.C-Load prog.S-Save prog.M-Move linesN-New prog.L-List P-Print listD-Dump mem. I-Print DumpT-Transfer E-Execute " 2740 PRINT AT 3,17; PAPER 6;" " 2750 PRINT AT 4,17; PAPER 6;" ";AT 4,31;" " 2760 FOR i=0 TO 11 2770 PRINT AT i+5,17; PAPER 6;" "; PAPER 1;" ";w$(i*12+1 TO (i+1)*12); PAPER 6;AT i+5,31;" " 2780 NEXT i 2790 PRINT AT 17,17; PAPER 6;" ";AT 17,31;" " 2800 PRINT AT 18,17; PAPER 6;" " 2810 PRINT AT 20,7; PAPER 2;"* HELP SCREEN *" 2820 PRINT #1;AT 0,5; INVERSE 1; BRIGHT 1;c$ 2830 PAUSE 0 2840 INK 7: PAPER 1: BORDER 1: CLS : LET linea=-1: GO TO 1000 2850 REM TRANSFER PROGRAM 2860 CLS 2870 PRINT AT 0,6; PAPER 2;"* TRANSFER PROGRAM *" 2880 PRINT AT 2,5; INVERSE 1; BRIGHT 1;c$ 2890 PRINT AT 9,7;"S .- Save progs." 2900 PRINT AT 11,7;"C .- Load progs." 2910 PRINT AT 13,7;"I .- Swap progs." 2920 PRINT #0;" Choose an opction (S/C/I) ";: PAUSE 0: LET o$=INKEY$: PRINT #0;O$: IF CODE o$>96 THEN LET o$=CHR$ (CODE o$-32) 2930 IF o$="S" THEN LET m$=p$ 2940 IF o$="C" THEN LET p$=m$ 2950 IF o$<>"I" THEN GO TO 2840 2960 LET f$( TO 2500)=m$ 2970 LET m$=p$ 2980 LET p$=f$( TO 2500) 2990 GO TO 2840 3000 REM Delete lines 3010 LET i=2: GO SUB 1490 3020 IF error THEN GO SUB 1890: GO TO 1000 3030 IF (op1+op2>501) OR op1<1 OR op2<1 THEN GO SUB 1890: GO TO 1000 3040 LET op1=op1*5-4: POKE 65498,FN r(op2): POKE 65499,FN m(op2) 3050 LET p$(op1)=p$(op1): RANDOMIZE USR 65497: GO TO 1000 3060 REM Move lines 3070 LET i=2: GO SUB 1490: IF error THEN GO SUB 1880: GO TO 1000 3080 GO SUB 1630: IF error THEN GO SUB 1880: GO TO 1000 3090 IF op1+valor>500 OR op2+valor>500 OR valor<0 OR op1<1 OR op2<1 THEN GO SUB 1880: GO TO 1000 3100 LET op1=op1*5-4: LET op2=op2*5-4: LET valor=valor*5-1 3110 LET m$=p$: LET p$(op2 TO op2+valor)=m$(op1 TO op1+valor) 3120 LET m$(1)=m$(1): RANDOMIZE USR 65502: GO TO 1000 3130 REM Battle !!! 3140 CLS : LET pos2=INT (RND*2400+1000): POKE 64259,FN r(pos2): POKE 64260,FN m(pos2) 3150 PRINT AT 0,5; PAPER 2;"* BATTLE OF PROGRAMS *" 3160 PRINT AT 2,5; INVERSE 1; BRIGHT 1;c$ 3170 INPUT "Execute step by step? (Y/N) "; LINE o$: POKE 64064,o$="y" OR o$="Y" 3180 LET f$(1)=f$(1): RANDOMIZE USR 65507 3182 FOR j=1 TO 2499 STEP 250: LET f$(j TO j+249)=p$(j TO j+249): NEXT j 3184 FOR j=1 TO 2499 STEP 250: LET f$(pos2*5+j TO pos2*5+j+249)=m$(j TO j+249): NEXT j 3200 INK 0: PAPER 6: BORDER 6 3210 LET f$(1)=f$(1): RANDOMIZE USR 64236 3220 IF o$="y" OR o$="Y" THEN PRINT AT 20,6;" Press any key ": PAUSE 0: PRINT AT 20,6; PAPER 2;" " 3230 IF INKEY$=" " THEN BEEP .1,.1: PRINT AT 20,6; FLASH 1;" Execution interrupted ": GO TO 3260 3240 IF PEEK 65122=0 THEN PRINT AT 20,6; FLASH 1;" Defeated program is ";CHR$ (64+PEEK 65121);" ": GO TO 2830 3250 LET f$(1)=f$(1): RANDOMIZE USR 64444: GO TO 3220 3260 PAUSE 0: IF INKEY$="C" OR INKEY$="c" THEN PRINT AT 20,6; PAPER 2;" ": GO TO 3240 3270 GO TO 2840 8000 REM SAVE THE EDITOR 8010 CLEAR : CLS : LET A$="BATTLE.BAS": PRINT "SAVING.. """;A$;"""...": SAVE A$ LINE 9000 8030 STOP 9000 REM LOAD MACHINE CODE 9010 CLEAR 63999: PRINT AT 10,5; FLASH 1;"LOADING MACHINE CODE..." 9020 LOAD ""CODE 9030 BORDER 7: PAPER 7: INK 0: CLS : PRINT FLASH 1;AT 10,8;" STOP THE TAPE ": FOR I=1 TO 64: BEEP .02,I: NEXT I: CLS 9040 GO TO 10 ```