This program is a two-pass Z80 assembler and integer BASIC compiler combined into a single listing. The assembler section (lines 366–8999) reads REM-statement source lines, performs two passes to resolve forward label references stored in string array B$, and writes Z80 machine code bytes directly into memory using POKE, with the entire Z80 opcode table encoded as a single long REM statement at line 0. The compiler section (lines 9000–9999) translates a subset of Sinclair BASIC—including LET, IF, PRINT, LPRINT, GO TO, GO SUB, RETURN, DIM, POKE, BEEP, PLOT, PAUSE, OUT, BORDER, INVERSE, OVER, INK, PAPER, FLASH, and string handling—into Z80 machine code using DATA statements and a RESTORE/READ loop to emit opcode sequences. Line 9999 prints instructions explaining that the assembler can coexist with the compiler in memory, but the compiler requires the assembler to be deleted first.
Program Analysis
Overall Structure
The listing contains two largely independent tools sharing a single file. Lines 0–8999 implement a two-pass Z80 assembler (“JRC TWO PASS ASSEMBLER”), while lines 9000–9999 implement an integer BASIC compiler (“Integer Basic Compiler”), both credited to John Richard Coffey / JRC Software, 1984. Line 9999 explicitly documents that the assembler can run alongside the compiler but the compiler requires the assembler to be deleted first, due to variable and memory conflicts.
Line 0 — The Opcode Table
Line 0 is an enormous REM statement containing a concatenated string of every Z80 mnemonic (including CB- and ED-prefixed opcodes, IX/IY variants, and ED-block instructions). The assembler’s lookup routine at line 3000 searches this string using USR 31909 — it POKEs the search key into a fixed memory area starting at address 31898 and calls machine code to locate the mnemonic, returning an opcode number k. This is an elegant technique: the entire opcode table fits in one REM line and is searched by a machine-code routine rather than by slow BASIC string scanning.
Assembler: Two-Pass Design (Lines 366–8999)
The assembler uses the variable L cycling from -1 to 0 (line 369) to implement two passes. On pass 1 (L=-1), label addresses are collected but no output is generated for forward-reference arguments (line 3210 substitutes 0). On pass 2 (L=0), real values are resolved and both PRINT and LPRINT output occur (line 495).
Source code is embedded as REM statements in the BASIC program itself (lines 11–81 show the sample program). The GET subroutine (line 400) reads memory directly with PEEK starting at address G, skipping the BASIC line header and tokenized keyword bytes, and normalizes lowercase to uppercase (line 425).
Assembler: Label and Symbol Handling
Labels are defined with a backtick prefix (e.g., `LOOP) and processed in the LBL subroutine (lines 2400–2500). Symbols defined with LET pseudo-ops are stored in parallel arrays B$ (names, padded to 10 chars) and M (values), both dimensioned to 100 entries at line 367. The EEV subroutine (lines 3200–3350) handles expression evaluation and label substitution within operand strings, replacing label names with their numeric values via STR$ insertion.
Duplicate label resolution is handled at lines 8000–8500: when a label is redefined on pass 2, the earlier entry is updated and the duplicate entry is collapsed.
Assembler: Pseudo-Ops
| Pseudo-op | Handler lines | Function |
|---|---|---|
ORG | 620–690 | Sets base address D and saves origin in E |
NUM | 1000–1060 | Emits a 16-bit little-endian word |
TXT | 1400–1460 | Emits a quoted ASCII string as bytes |
TBL | 1600–1670 | Emits a table of N word values from subsequent source lines |
RSV | 1800–1840 | Reserves N bytes (advances D without emitting) |
BYT | 2200–2240 | Emits a single evaluated byte |
LET | 2000–2110 | Defines a named numeric constant |
STOP | 800–890 | Ends assembly, prints size and label table |
Assembler: Opcode Encoding (Lines 392–398)
After finding opcode index k via USR 31909, the assembler encodes prefix bytes automatically. If k>255, a 0xCB prefix is POKEd; if k>511, a 0xED prefix is POKEd instead. The base opcode is then written as k MOD 256 (with double-subtraction handling both ranges). The ARG subroutine (lines 3600–3690) uses a second machine-code lookup at address 31130+k to determine the argument type (0=none, 1=byte, 2=relative branch, 4=word via DPK).
Compiler: Structure (Lines 9000–9999)
The compiler also uses a two-pass loop (FOR P=0 TO 1, lines 9005–9006). On pass 0, line/address pairs are accumulated in parallel string arrays X$ and Y$ (each pair encoded as two characters) by the STORE subroutine (lines 9550–9560), allowing forward GO TO/GO SUB branch targets to be resolved on pass 1. The variable LOC tracks the current machine code write address.
Three DEF FN functions are defined: FN P reads a 16-bit little-endian value from memory, FN H extracts the high byte, and FN L extracts the low byte. These are used throughout to decompose addresses for POKE sequences and DATA streams.
Compiler: POKE/DATA Idiom
The compiler’s most pervasive technique is using RESTORE to a specific line number followed by GO SUB POKE, where the POKE subroutine (lines 9530–9540) READs values from a DATA statement on the same line until it encounters -PI as a sentinel. This allows each BASIC statement handler to embed its Z80 opcode sequence inline. Some DATA values use FN L(...) and FN H(...) to compute address bytes dynamically (e.g., for DIM array addresses and string constant pointers).
Compiler: Expression Evaluation
Arithmetic expressions are evaluated by E1 (line 9240) and E2 (line 9230), which call ITEM and then loop on operators +, -, =, <, *, /, AND, and OR. Results are accumulated in the HL register pair in generated machine code, with DE used as a second operand via the E2 push/exchange pattern (line 9230: PUSH HL / E1 / EX DE,HL / POP HL). Division (line 9300) emits a 43-byte inline Z80 routine performing 16-bit integer division by repeated subtraction with shifts.
Compiler: String Handling
The STRING subroutine (lines 9620–9730) handles PRINT arguments including quoted literals (emitting LD A,n / RST 16 sequences), CHR$, INKEY$, STR$, AT, TAB, INVERSE, BRIGHT, OVER, PAPER, INK, FLASH, and the newline shorthand '. String variable assignment (LET a$=) is handled separately at lines 9900–9980, supporting both expression-based and literal string assignment via LDIR block copy.
Compiler: SOUND Statement
Lines 9740–9770 handle the SOUND keyword by rewriting the source string in-place, translating SOUND-specific delimiters into OUT 245, and OUT 246, sequences before falling through to the normal statement dispatcher. This is a simple textual macro expansion within the compiler’s input buffer A$.
Notable Bugs and Anomalies
- Line 1630 calls
GO SUB EEV+1(i.e., address 3201), which skips the first character strip of theEEVsubroutine — this appears intentional for the TBL context but could cause subtle parsing differences. - Line 3335 uses
PI/NOT PI(which isPI/0) to force a division-by-zero error when an undefined label is encountered — a deliberate error-stopping technique. - In the compiler’s
IFhandler (line 9190), the false branch jumps to the next BASIC line number by embeddingGO TO NLINEin the reconstructed source, which only works correctly if NLINE has been read ahead; this is set at lines 9045/9070. - Line 2240 uses
GO TO ADV(a variable holding line number 1200) rather thanGO SUB ADV, meaning after advancingD, execution falls into whatever follows line 1200 rather than returning — theRETURNat line 1220 will nevertheless return to the BYT caller’s caller, which works because BYT setsH=1before calling. - The compiler’s
SAVEline at 9998 saves withLINE 9998, causing auto-run from line 9998 on load, which re-presents the save/verify prompt.
Memory Map
| Address | Usage |
|---|---|
| 31898–31908 | Assembler mnemonic search buffer (POKEd by BASIC, searched by USR 31909) |
| 31909 | Entry point of assembler opcode-search machine code routine |
| 31130+k | Assembler argument-type table indexed by opcode number k |
| 31997 | Default start address for assembler source scan (G) |
| USR “A” + 2*n | Compiler: 16-bit integer variable storage for variables A–Z (52 bytes) |
| ORG / LOC | User-specified or default (60000) machine code output area |
Content
Source Code
0 REM NOPLD BC,eLD (BC),AINC BCINC BDEC BLD B,eRLCAEX AF,AFADD HL,BCLD A,(BC)DEC BCINC CDEC CLD C,eRRCHDJNZ eLD DE,eLD (DE),AINC DEINC DDEC DLD D,eRLAJR eADD HL,DELD A,(DE)DEC DEINC EDEC ELD E,eRRAJR NZ,eLD HL,eLD (e),HLINC HLINC HDEC HLD H,eDAAJR Z,eADD HL,HLLD HL,(e)DEC HLINC LDEC LLD L,eCPLJR NC,eLD SP,eLD (e),AINC SPINC (HL)DEC (HL)LD (HL),eSCFJR C,eADD HL,SPLD A,(e)DEC SPINC ADEC ALD A,eCCFLD B,BLD B,CLD B,DLD B,ELD B,HLD B,LLD B,(HL)LD B,ALD C,BLD C,CLD C,DLD C,ELD C,HLD C,LLD C,(HL)LD C,ALD D,BLD D,CLD D,DLD D,ELD D,HLD D,LLD D,(HL)LD D,ALD E,BLD E,CLD E,DLD E,ELD E,HLD E,LLD E,(HL)LD E,ALD H,BLD H,CLD H,DLD H,ELD H,HLD H,LLD H,(HL)LD H,ALD L,BLD L,CLD L,DLD L,ELD L,HLD L,LLD L,(HL)LD L,ALD (HL),BLD (HL),CLD (HL),DLD (HL),ELD (HL),HLD (HL),LHALTLD (HL),ALD A,BLD A,CLD A,DLD A,ELD A,HLD A,LLD A,(HL)LD A,AADD A,BADD A,CADD A,DADD A,EADD A,HADD A,LADD A,(HL)ADD A,AADC A,BADC A,CADC A,DADC A,EADC A,HADC A,LADC A,(HL)ADC A,ASUB BSUB CSUB DSUB ESUB HSUB LSUB (HL)SUB ASBC A,BSBC A,CSBC A,DSBC A,ESBC A,HSBC A,LSBC A,(HL)SBC A,AAND BAND CAND DAND EAND HAND LAND (HL)AND AXOR BXOR CXOR DXOR EXOR HXOR LXOR (HL)XOR AOR BOR COR DOR EOR HOR LOR (HL)OR ACP BCP CCP DCP ECP HCP LCP (HL)CP ARET NZPOP BCJP NZ,eJP eCALL NZ,ePUSH BCADD A,eRST 0RET ZRETJP Z,eCALL Z,eCALL eADC A,eRST 8RET NCPOP DEJP NC,eOUT (e),ACALL NC,ePUSH DESUB eRST 16RET CEXXJP C,eIN A,(e)CALL C,eIXSBC A,eRST 24RET POPOP HLJP PO,eEX (SP),HLCALL PO,ePUSH HLAND eRST 32RET PEJP (HL)JP PE,eEX DE,HLCALL PE,eXOR eRST 40RET PPOP AFJP P,eDICALL P,ePUSH AFOR eRST 48RET MLD SP,HLJP M,eEICALL M,eIYCP eRST 56RLC BRLC CRLC DRLC ERLC HRLC LRLC (HL)RLC ARRC BRRC CRRC DRRC ERRC HRRC LRRC (HL)RRC ARL BRL CRL DRL ERL HRL LRL (HL)RL ARR BRR CRR DRR ERR HRR LRR (HL)RR ASLA BSLA CSLA DSLA ESLA HSLA LSLA (HL)SLA ASRA BSRA CSRA DSRA ESRA HSRA LSRA (HL)SRA ASRL BSRL CSRL DSRL ESRL HSRL LSRL (HL)SRL ABIT 0,BBIT 0,CBIT 0,DBIT 0,EBIT 0,HBIT 0,LBIT 0,(HL)BIT 0,ABIT 1,BBIT 1,CBIT 1,DBIT 1,EBIT 1,HBIT 1,LBIT 1,(HL)BIT 1,ABIT 2,BBIT 2,CBIT 2,DBIT 2,EBIT 2,HBIT 2,LBIT 2,(HL)BIT 2,ABIT 3,BBIT 3,CBIT 3,DBIT 3,EBIT 3,HBIT 3,LBIT 3,(HL)BIT 3,ABIT 4,BBIT 4,CBIT 4,DBIT 4,EBIT 4,HBIT 4,LBIT 4,(HL)BIT 4,ABIT 5,BBIT 5,CBIT 5,DBIT 5,EBIT 5,HBIT 5,LBIT 5,(HL)BIT 5,ABIT 6,BBIT 6,CBIT 6,DBIT 6,EBIT 6,HBIT 6,LBIT 6,(HL)BIT 6,ABIT 7,BBIT 7,CBIT 7,DBIT 7,EBIT 7,HBIT 7,LBIT 7,(HL)BIT 7,ARES 0,BRES 0,CRES 0,DRES 0,ERES 0,HRES 0,LRES 0,(HL)RES 0,ARES 1,BRES 1,CRES 1,DRES 1,ERES 1,HRES 1,LRES 1,(HL)RES 1,ARES 2,BRES 2,CRES 2,DRES 2,ERES 2,HRES 2,LRES 2,(HL)RES 2,ARES 3,BRES 3,CRES 3,DRES 3,ERES 3,HRES 3,LRES 3,(HL)RES 3,ARES 4,BRES 4,CRES 4,DRES 4,ERES 4,HRES 4,LRES 4,(HL)RES 4,ARES 5,BRES 5,CRES 5,DRES 5,ERES 5,HRES 5,LRES 5,(HL)RES 5,ARES 6,BRES 6,CRES 6,DRES 6,ERES 6,HRES 6,LRES 6,(HL)RES 6,ARES 7,BRES 7,CRES 7,DRES 7,ERES 7,HRES 7,LRES 7,(HL)RES 7,ASET 0,BSET 0,CSET 0,DSET 0,ESET 0,HSET 0,LSET 0,(HL)SET 0,ASET 1,BSET 1,CSET 1,DSET 1,ESET 1,HSET 1,LSET 1,(HL)SET 1,ASET 2,BSET 2,CSET 2,DSET 2,ESET 2,HSET 2,LSET 2,(HL)SET 2,ASET 3,BSET 3,CSET 3,DSET 3,ESET 3,HSET 3,LSET 3,(HL)SET 3,ASET 4,BSET 4,CSET 4,DSET 4,ESET 4,HSET 4,LSET 4,(HL)SET 4,ASET 5,BSET 5,CSET 5,DSET 5,ESET 5,HSET 5,LSET 5,(HL)SET 5,ASET 6,BSET 6,CSET 6,DSET 6,ESET 6,HSET 6,LSET 6,(HL)SET 6,ASET 7,BSET 7,CSET 7,DSET 7,ESET 7,HSET 7,LSET 7,(HL)SET 7,AIN B,(C)OUT (C),BSBC HL,BCLD (e),BCNEGRETNIM 0LD I,AIN C,(C)OUT (C),CADC HL,BCLD BC,(e)RETILD R,AIN D,(C)OUT (C),DSBC HL,DELD (e),DEIM 1LL A,IIN E,(C)OUT (C),EADC HL,DELD DE,(e)IM 2LD A,RIN H,(C)OUT (C),HSBC HL,HLLD (e),HLRRDIN L,(C)OUT (C),LADC HL,HLLD HL,(e)RLDSBC HL,SPLD (e),SPIN A,(C)OUT (C),AADC HL,SPLD SP,(e)LDICPIINIOUTILDDCPDINDOUTDLDIRCPIRINIROTIRLDDRCPDRINDROTDRLD HL,eAMh!\k STICK PEEK #>= PRINT RETURN ( SAVE LN >= STOP MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN
5 REM REM JRC TWO PASS ASSEMBLER \* 1984 BY JRC SOFTWARE po box 448 scottsburg, in 47170
11 REM REM sample program; INSTANT SCREEN INVERSE
15 REM ORG 60000
21 REM LD HL,16384
31 REM LD BC,6144
41 REM `LOOP;LD A,(HL);XOR 255
51 REM LD (HL),A;INC HL
61 REM DEC BC;LD A,B;OR C
71 REM JR NZ,LOOP
81 REM RET
366 REM STOP
367 DIM B$(100,10): DIM m(100)
368 GO SUB 600
369 FOR L=-1 TO 0
370 LET G=31997: GO SUB GET
375 GO SUB GET
376 LET H=0
377 GO SUB STP
378 GO SUB NUM
379 GO SUB TXT
380 IF NOT LEN I$ THEN GO TO VAL "375"
381 GO SUB TBL
382 GO SUB RSV
383 GO SUB LET
384 IF CODE I$=CODE " LET " THEN GO TO VAL "375"
385 GO SUB BYT
386 GO SUB LBL
387 IF H THEN GO TO 373+H+SGN LEN I$
388 LET g$=i$: LET j$=""
389: IF LEN g$ THEN IF g$(1)<>" " THEN LET j$=j$+CHR$ CODE g$: LET g$=g$(2 TO ): GO TO 389
390 LET g$=g$(2 TO ): GO SUB rip
391 IF LEN t$ THEN LET j$=j$+" "+t$: LET g$=g$(2 TO ): GO SUB rip:: IF LEN t$ THEN LET j$=j$+","+t$
392 GO SUB fnd
393 IF k>255 THEN POKE D,203
394 IF k>511 THEN POKE D,237
395 IF k>255 THEN GO SUB ADV
396 POKE D,k-256*(k>255)-256*(k>511)
397 GO SUB ADV
398 GO SUB ARG
399 GO TO 375
400: LET I$="": IF PEEK g=32 THEN LET g=g+1: GO TO 400
401 IF CHR$ PEEK G<>" REM " THEN GO TO VAL "410"
405 LET G=G+1
407 IF PEEK G<>13 THEN GO TO 405
410 IF PEEK G=13 THEN GO TO 460
420 IF PEEK G=CODE ";" OR PEEK g=CODE ":" THEN GO TO 470
425 IF PEEK g>=CODE "a" AND PEEK g<=CODE "z" THEN POKE g,PEEK g-CODE "a"+CODE "A"
430 LET I$=I$+CHR$ PEEK G
440 LET G=G+1
450 GO TO 410
460 LET G=G+5
470 LET G=G+1
480 IF NOT LEN I$ THEN GO TO GET
485 POKE 23692,99
490 PRINT I$,D
495 IF L THEN LPRINT I$,D
500 RETURN
600 LET l=-1: LET d=0: LET g=31997: LET dpk=1030::: LET arg=3600: LET get=400: LET stp=800: LET num=1000: LET adv=1200: LET txt=1400: LET tbl=1600: LET rsv=1800: LET let=2000: LET byt=2200: LET lbl=2400: LET fnd=3000: LET eev=3200: LET rip=3400
610 GO SUB get
620 IF i$( TO 4)<>"ORG " THEN PRINT "NO ORG (NUMBER) AT BEGINNING": STOP
625 LET D=VAL I$(5 TO )
630 LET c=0
660 LET E=D
690 RETURN
800 IF CODE I$<>CODE " STOP " THEN RETURN
820 IF NOT L THEN PRINT "THE MACHINE CODE TAKES ";D-E;" BYTES"
830 IF L THEN LET D=E:
840 NEXT L
850 PRINT "LABEL","ADDRESS"
860 IF C THEN FOR H=1 TO C
870 IF C THEN PRINT B$(H),M(H)
880 IF C THEN NEXT H
890 STOP
1000 IF LEN I$<3 THEN RETURN
1001 IF I$( TO 3)<>"NUM" THEN RETURN
1010 LET H=1
1020 GO SUB EEV
1030 LET N=INT (VAL I$/256)
1040 POKE D,VAL I$-N*256
1050 GO SUB ADV
1060 POKE D,N
1200 LET D=D+1
1220 RETURN
1400 IF CODE I$<>34 THEN RETURN
1410 LET H=1
1420 LET I$=I$(2 TO )
1430 IF NOT LEN I$ THEN RETURN
1440 POKE D,CODE I$
1450 GO SUB ADV
1460 GO TO 1420
1600 IF (I$+" ")( TO 3)<>"TBL" THEN RETURN
1610 FOR H=1 TO VAL I$(4 TO )
1620 GO SUB GET
1630 GO SUB EEV+1
1640 GO SUB DPK
1650 NEXT H
1660 LET H=1
1670 RETURN
1800 IF (I$+" ")( TO 3)<>"RSV" THEN RETURN
1810 LET D=D+VAL I$(4 TO )
1830 LET H=1
1840 RETURN
2000 IF CODE I$<>CODE " LET " THEN RETURN
2010 LET H=1
2020 IF NOT L THEN RETURN
2030 LET J$=""
2040 LET I$=I$(2 TO )
2050 IF CODE I$=CODE "=" THEN GO TO 2080
2060 LET J$=J$+CHR$ CODE I$
2070 GO TO 2040
2080 LET C=C+1
2090 LET B$(C)=J$
2100 LET M(C)=VAL I$(2 TO )
2110 GO TO 8000
2200 IF (I$+" ")( TO 3)<>"BYT" THEN RETURN
2210 GO SUB EEV
2220 POKE D,VAL I$
2230 LET H=1
2240 GO TO ADV
2400 IF CODE i$<>CODE "`" THEN RETURN
2410 LET i$=i$(2 TO ): LET J$=""
2420 LET J$=J$+CHR$ (CODE I$)
2430 LET I$=I$(2 TO )
2440 IF I$>="A" THEN IF I$<="Z" THEN GO TO 2420
2450 LET H=2
2460 IF NOT L THEN RETURN
2470 LET C=C+1
2480 LET B$(C)=J$
2490 LET M(C)=D
2500 GO TO 8000
3000:: FOR U=31898 TO LEN J$+31897: POKE U,CODE J$(U-31897): NEXT U: POKE U,13: LET k=USR 31909
3100 IF k=768 THEN PRINT "SYNTAX ERROR"'"THIS STATEMENT INCORRECT"'VAL ""
3150 RETURN
3200 LET I$=I$(4 TO LEN I$)
3210 IF L THEN LET I$="0"
3220 IF L THEN RETURN
3230 FOR K=1 TO LEN I$
3240 IF I$(K)>="A" AND I$(K)<="Z" THEN GO TO 3270
3250 NEXT K
3260 RETURN
3270 LET V=K
3280 IF V=LEN I$ THEN GO TO 3320
3290 IF I$(V+1)<"A" OR I$(V+1)>"Z" THEN GO TO 3320
3300 LET V=V+1
3310 GO TO 3280
3320 FOR U=1 TO C
3330 IF B$(U)<>I$(K TO V)+" "( TO 10+k-v-1) THEN NEXT U
3335 IF U>C THEN PRINT "ERROR: ";I$(K TO V);" UNDEFINED";PI/NOT PI
3340 LET I$=I$( TO K-1)+STR$ M(U)+I$(V+1 TO )
3350 GO TO 3230
3400 REM rip
3410 LET t$=""
3420 IF LEN g$ THEN IF g$(1)<>"," THEN LET t$=t$+CHR$ CODE g$: LET g$=g$(2 TO ): GO TO 3420
3430 IF LEN t$<=2+(CODE t$=CODE "(")*2 THEN RETURN
3440 IF t$(1)="(" THEN LET i$=t$(2 TO LEN t$-1): LET t$="(e)"
3450 IF t$(1)<>"(" THEN LET i$=t$: LET t$="e"
3460 RETURN
3600 LET W=PEEK (31130+k)
3610 IF NOT W THEN RETURN
3620 LET I$=" "+i$
3630 GO SUB EEV
3640 IF W=4 THEN GO TO DPK
3650 IF W=1 THEN POKE D,VAL I$
3660 IF W=1 THEN GO TO ADV
3670 LET Y=VAL I$-d-(W=2)
3680 IF NOT L THEN POKE D,Y+256*(Y<0)
3690 GO TO ADV
8000 FOR U=SGN PI TO C
8100 IF B$(U)<>B$(C) THEN NEXT U
8200 IF U=C THEN RETURN
8300 LET M(U)=M(C)
8400 LET C=C-SGN PI
8500 RETURN
8999 STOP
9000 REM RESET 1984 JRC SOFTWARE Integer Basic Compiler writtn by John Richard Coffey with thanks to John M. Brown JRC SOFTWARE po box 448 Scottsburg, In 47170
9001: DIM s(26): LET M=0: LET MODE=PI: LET HIMEM=0
9002 LET STRING=9620: POKE USR "A"+54,195: LET LTOT=0: LET ITEM2=9315: DIM X$(2000): DIM Y$(2000): LET CHOP=9490: LET FETCH=9500: LET CONS=9360: LET CONS2=9440: LET ITEM=9320: LET E1=9240: LET E2=9230: LET POKE=9530: LET BRANCH=9565: LET ADVANCE=9480: LET STATEMENT=9120: LET LINE=9050: LET STORE=9550
9005 IF MODE THEN INPUT "WHERE DO YOU WANT TO PUT THE MACHINE CODE"'''N: LET ORG=N: FOR P=0 TO 1: LET LOC=ORG
9006 IF NOT MODE THEN POKE 23692,99: LET N=6E4: LET ORG=N: FOR P=0 TO 1: LET LOC=ORG
9010 DEF FN P(A)=PEEK A+256*PEEK (A+1)
9020 DEF FN H(A)=INT (A/256)
9030 DEF FN L(A)=A-256*FN H(A)
9040 LET NPROG=FN P(23635)+4
9045 LET NLINE=PEEK (NPROG-3)+256*PEEK (NPROG-4)
9050 LET PROG=NPROG:: REM LINE
9060 LET NPROG=PROG+FN P(PROG-2)+4
9065: GO SUB STORE
9070 LET NLINE=PEEK (NPROG-3)+256*PEEK (NPROG-4)
9080 IF NLINE>9E3 THEN GO SUB 9990: NEXT p: PRINT INVERSE 1; INK 4;"THE MACHINE CODE TAKES ";LOC-ORG;" BYTES": STOP
9090:: LET A$="": FOR L=PROG TO NPROG-6:: IF PEEK L=14 THEN LET L=L+5: GO TO 9110
9095 IF PEEK L>=CODE "a" AND PEEK l<=CODE "z" THEN IF PEEK (l-1)=CODE " LET " OR PEEK (l+1)=CODE "$" THEN POKE l,PEEK l-CODE "a"+CODE "A"
9100 LET A$=A$+CHR$ PEEK L
9110 NEXT L: PRINT LOC;TAB 6;a$ : POKE 23692,99
9120:: IF NOT LEN A$ THEN GO TO LINE
9123 IF A$(1)=":" THEN GO SUB CHOP
9124 IF NOT LEN a$ THEN GO TO line
9125: IF A$(1)=" REM " THEN GO TO LINE: REM STATEMENT
9130 IF A$(1)=" STOP " OR A$(1)=" RETURN " THEN POKE LOC,201: GO SUB ADVANCE: GO TO LINE
9135 IF A$(1)=" COPY " THEN RESTORE 9135: GO SUB chop: GO SUB poke: GO TO statement: DATA 205,2,10,-PI
9140 IF A$(1)=" GO TO " THEN :: POKE LOC,195: GO TO BRANCH
9145 IF A$(1)="}" THEN GO TO 9740
9150 IF A$(1)=" GO SUB " THEN POKE LOC,205: GO TO BRANCH
9160 IF CODE A$<>CODE " DIM " THEN GO TO 9170
9161 GO SUB CHOP: LET S=1+CODE A$-CODE "A": GO SUB CHOP: GO SUB CHOP: GO SUB CHOP:: LET J=0
9162 LET J=J*10+VAL CHR$ CODE A$: GO SUB CHOP: IF CODE A$<>CODE ")" THEN GO TO 9162
9163 IF NOT P THEN LET S(S)=J
9170 IF A$(1)=" POKE " THEN GO SUB E1:: GO SUB E2: POKE LOC,115: GO SUB ADVANCE: GO TO STATEMENT
9172 IF A$(1)=" BEEP " THEN GO SUB E1: GO SUB E2: RESTORE 9172: GO SUB POKE: GO TO STATEMENT: DATA 235,1,60,0,9,197,229,213,205,233,48,193,205,233,48,239,1,5,56,193,205,233,48,193,205,233,48,239,3,56,205,54,4,-PI
9174 IF A$(1)=" PLOT " THEN GO SUB E1: GO SUB E2: RESTORE 9174: GO SUB POKE: GO TO STATEMENT: DATA 67,77,205,62,38,-PI
9175 IF A$(1)=" RANDOMIZE " THEN GO SUB E1:: RESTORE 9175: GO SUB POKE: GO TO STATEMENT: DATA 68,77,205,215,30,-PI
9176 IF A$(1)=" CLS " THEN GO SUB chop: RESTORE 9176: GO SUB POKE: GO TO STATEMENT: DATA 205,234,8,-PI
9179 IF A$(1)=" PAUSE " THEN GO SUB E1:: RESTORE 9179: GO SUB POKE: GO TO STATEMENT: DATA 68,77,205,233,48,205,235,31,-PI
9180 IF A$(1)=" OUT " THEN GO SUB E1: GO SUB E2: RESTORE 9180: GO SUB POKE: GO TO STATEMENT: DATA 68,77,235,237,105,-PI
9182 IF A$(1)=" RUN " THEN LET A$=" GO TO 1"+A$(2 TO ): GO TO STATEMENT
9185 IF A$(1)=" INVERSE " OR A$(1)=" OVER " OR A$(1)="AT " OR A$(1)= "TAB " OR A$(1)=" BRIGHT " OR A$(1)=" PAPER " OR A$(1)=" INK " OR A$(1)=" FLASH " THEN GO SUB STRING: RESTORE 9185: GO SUB POKE: GO TO STATEMENT : DATA 215,42,143,92,34,141,92,-PI
9187 IF A$(1)=" BORDER " THEN GO SUB E1: RESTORE 9187 : GO SUB POKE : GO TO STATEMENT: DATA 125, 211,254
9190 IF A$(1)=" IF " THEN GO SUB E1:: RESTORE 9190: GO SUB POKE: LET A$=" GO TO "+STR$ NLINE+":"+A$(2 TO ):: GO TO 9140: DATA 124,181,32,3,-PI
9195 IF a$(1)=" LET " THEN IF a$(3)="$" THEN GO SUB 9900: GO TO 9210
9200 IF A$(1)=" LET " THEN LET V=USR "A"+2*(CODE A$(2)-CODE "A")::: GO SUB CHOP: GO SUB CHOP: GO SUB E1: POKE LOC,34::: POKE LOC+1,FN L(V): POKE LOC+2,FN H(V): LET LOC=LOC+3:: GO TO STATEMENT
9201: IF A$(1)<>" PRINT " AND a$(1)<>" LPRINT " THEN GO TO 9210
9203 LET lprint=a$(1)=" LPRINT ": IF lprint THEN RESTORE 9203: GO SUB poke: DATA 33,59,92,203,206,-PI
9204: GO SUB CHOP
9205: IF LEN A$>=2 THEN IF A$(1 TO 2)=";:" THEN GO SUB CHOP: GO SUB CHOP: GO TO 9800
9206: IF LEN A$=1 THEN IF A$(1)=";" THEN GO SUB CHOP: GO TO 9800
9207: IF CODE A$=CODE ":" OR NOT LEN A$ THEN GO SUB CHOP: RESTORE 9207: GO SUB POKE: GO TO 9800: DATA 62,13,215,42,141,92,34,143,92,-PI
9208: IF CODE A$<>CODE ";" THEN GO SUB STRING:: POKE LOC,215: GO SUB ADVANCE: GO TO 9205
9209 GO TO 9204
9210: IF LEN A$ THEN IF A$(1)<>":" AND LEN A$ THEN GO SUB chop: GO TO 9210
9220 LET A$=A$(2 TO ): GO TO STATEMENT*SGN LEN A$+LINE*NOT LEN A$
9230: POKE LOC,229: GO SUB ADVANCE: GO SUB E1: POKE LOC,235: GO SUB ADVANCE: POKE LOC,225: GO TO ADVANCE : REM E2
9240: GO SUB ITEM: REM E1
9250 IF NOT LEN A$ THEN RETURN
9251 LET LOOP=9250: IF A$(1)="+" THEN GO SUB ITEM2: POKE LOC,25: GO SUB ADVANCE: GO TO LOOP
9260 IF A$(1)="-" THEN GO SUB ITEM2: POKE LOC,167: POKE LOC+1,237: POKE LOC+2,82: LET LOC=LOC+3: GO TO LOOP
9270 IF A$(1)="=" THEN GO SUB ITEM2: RESTORE 9270: GO SUB POKE: GO TO LOOP: DATA 167,237,82,124,181,46,1,40,2,46,0,38,0,-PI
9280 IF A$(1)="<" THEN GO SUB ITEM2: RESTORE 9280: GO SUB POKE: GO TO LOOP: DATA 167,237,82,46,0,48,2,46,1,38,0,-PI
9290 IF A$(1)="*" THEN GO SUB ITEM2: RESTORE 9290: GO SUB POKE: GO TO LOOP: DATA 205,104,52,-PI
9300 IF A$(1)="/" THEN GO SUB ITEM2: RESTORE 9300: GO SUB POKE: GO TO LOOP: DATA 122,179,200,124,77,33,0,0,6,16,203,17,23,237,106,237,82,63,48,16,16,244,24,14,203,17,23,237,106,167,237,90,56,242,40,237,16,242,203,17,23,25,71,96,105,-PI
9305 IF A$(1)=" AND " THEN GO SUB ITEM2: RESTORE 9305: GO SUB POKE: GO TO LOOP: DATA 124,162,103,125,163,111,-PI
9307 IF A$(1)=" OR " THEN GO SUB ITEM2: RESTORE 9307: GO SUB POKE: GO TO LOOP: DATA 124,178,103,125,179,111,-PI
9310 RETURN
9315 POKE LOC,235: GO SUB ADVANCE: GO SUB ITEM : POKE LOC,235: GO TO ADVANCE
9320: LET A$=A$(2 TO ): REM ITEM
9325 IF LEN a$>1 THEN IF A$(1 TO 2)="POINT (" THEN GO SUB chop: GO SUB CONS2: POKE loc,229: GO SUB advance: GO SUB cons2: GO SUB chop:: RESTORE 9325: GO TO POKE: DATA 227,229,193,205,233,48,193,205,233,48,205,36,38,205,96,49,197,225,-PI
9330 IF A$(1)="PEEK " THEN GO SUB CONS2: POKE LOC,110: POKE LOC+1,38: POKE LOC+2,0: LET LOC=LOC+3: RETURN
9335 IF A$(1)="CODE " THEN GO SUB CHOP: GO SUB STRING: RESTORE 9335: GO TO POKE: DATA 38,0,111,-PI
9340 IF A$(1)="USR " THEN GO SUB CONS2: RESTORE 9340: GO TO POKE: DATA 213,34,143,255,205,142,255,96,105,209,-PI
9350 IF A$(1)="IN " THEN GO SUB CONS2: RESTORE 9350: GO TO POKE: DATA 68,77,237,72,38,0,105,-PI
9360: REM CONS
9365: IF LEN A$>=7 THEN IF A$(1 TO 7)="RND*65536" THEN LET A$=A$(8 TO ): RESTORE 9365 : GO TO POKE: DATA 237,75,118,92,205,233,48,239,161,15,52, 55,22,4,52,128,65,0,0,128, 50,2,161,3,49,56,205,96, 49,237,67,118,92,96,105,-PI
9369 IF A$(1)<="z" THEN IF a$(1)>="a" THEN LET a$(1)=CHR$ (CODE a$(1)-CODE "a"+CODE "A")
9370 LET DO=A$(1)<="Z" AND A$(1)>="A"
9380 IF NOT DO THEN GO SUB FETCH: POKE LOC,33
9390 IF DO THEN LET NUM=USR "A"+2*(CODE A$-CODE "A"): LET A$=A$(2 TO ): POKE LOC,42
9400 POKE LOC+1,FN L(NUM)
9410 POKE LOC+2,FN H(NUM)
9420 LET LOC=LOC+3
9430 RETURN
9440 GO SUB CHOP: GO TO CONS: REM CONS2
9480 LET LOC=LOC+1: RETURN : REM ADVANCE
9490 LET A$=A$(2 TO ): RETURN : REM CHOP
9500 LET NUM=0: REM FETCH
9510 IF CODE A$<CODE "0" OR CODE A$>CODE "9" THEN RETURN
9520 LET NUM=NUM*10+CODE A$-CODE "0": GO SUB CHOP: GO TO 9510
9530: READ ZZZZ: IF ZZZZ<>-PI THEN POKE LOC,ZZZZ:: GO SUB ADVANCE: GO TO 9530: REM POKE
9540 RETURN
9550 IF P THEN RETURN
9555 LET LTOT=LTOT+1: LET X$(LTOT*2-1 TO LTOT*2)=CHR$ FN L(NLINE)+CHR$ FN H(NLINE): REM STORE
9560 LET Y$(LTOT*2-1 TO LTOT*2)=CHR$ FN L(LOC)+CHR$ FN H(LOC): RETURN : REM STORE
9565: GO SUB ADVANCE: GO SUB CHOP :: GO SUB FETCH: REM BRANCH
9570 IF NOT P THEN GO SUB ADVANCE: GO SUB ADVANCE: GO TO STATEMENT
9580 FOR I=1 TO LTOT*2-1 STEP 2:
9590 IF NUM>CODE X$(I)+256*CODE X$(I+1) THEN NEXT I
9600 POKE LOC,CODE Y$(I): GO SUB ADVANCE
9610 POKE LOC,CODE Y$(I+1): GO SUB ADVANCE : GO TO STATEMENT
9620 REM STRING EVALUATOR
9625:: IF LEN A$>=2 THEN IF a$(2)="$" THEN : LET k=s(1+CODE a$-CODE "A"): GO SUB chop: GO SUB chop: GO SUB chop: POKE loc,229: GO SUB advance: GO SUB cons: GO SUB chop: RESTORE 9625: GO TO poke: DATA 1,FN l(k-1),FN h(k-1),9,126,225,-PI
9630 IF A$(1)="INKEY$" THEN GO SUB CHOP: RESTORE 9630: GO TO POKE: DATA 213,205,225,2,209,58, 5,92,167,40,3,58,8,92,-PI
9635 IF A$(1)="," THEN GO SUB CHOP: RESTORE 9635: GO TO POKE: DATA 62,6,-PI
9640 IF A$(1)="AT " THEN GO SUB E1: GO SUB E2:: RESTORE 9640: GO TO POKE : DATA 62,22,215,125,215, 123,-PI
9642 IF A$(1)="STR$ " THEN GO SUB E1: RESTORE 9642: GO TO POKE: DATA 68,77,205,233,48,205,161,49,62,32,-PI
9644 IF A$(1)="'" THEN GO SUB CHOP: RESTORE 9644: GO TO POKE: DATA 62, 13,-PI
9650 IF A$(1)="TAB " THEN GO SUB E1: RESTORE 9650: GO TO POKE: DATA 62,23,215, 125,215,62,0,-PI
9655 IF A$(1)=" INVERSE " THEN GO SUB E1: RESTORE 9655: GO TO POKE: DATA 62,20,215, 125,-PI
9660 IF A$(1)=" BRIGHT " THEN GO SUB E1: RESTORE 9660: GO TO POKE: DATA 62,19,215, 125,-PI
9665 IF A$(1)=" OVER " THEN GO SUB E1: RESTORE 9665: GO TO POKE: DATA 62,21,215, 125,-PI
9670 IF A$(1)=" PAPER " THEN GO SUB E1: RESTORE 9670: GO TO POKE: DATA 62,17,215, 125,-PI
9680 IF A$(1)=" INK " THEN GO SUB E1: RESTORE 9680: GO TO POKE: DATA 62,16,215, 125,-PI
9690 IF A$(1)=" FLASH " THEN GO SUB E1: RESTORE 9690: GO TO POKE: DATA 62,18,215, 125,-PI
9695:: IF A$(1)="CHR$ " THEN POKE loc,229: GO SUB advance: GO SUB E1: POKE loc,125: GO SUB advance: POKE LOC,225: GO TO ADVANCE
9700 IF A$(1)<>"""" THEN RETURN
9710 GO SUB CHOP
9720 IF A$(1)<>"""" THEN POKE LOC,62: GO SUB ADVANCE : POKE LOC,CODE A$ : GO SUB ADVANCE: GO SUB CHOP : IF A$(1)<>"""" THEN POKE LOC,215 : GO SUB ADVANCE: GO TO 9720
9730 GO TO CHOP
9740 REM SOUND
9745 LET SD=0
9750 LET SD=SD+1: IF A$(SD)=":" THEN GO TO 9770
9760 IF A$(SD)=";" THEN LET A$=A$( TO SD-1)+":}"+A$(SD+1 TO )
9765 IF A$(SD)="}" THEN LET A$=A$( TO SD-1)+" OUT 245,"+A$(SD+1 TO ): LET SD=SD+5:
9767 IF A$(SD)="," THEN LET A$=A$( TO SD-1)+": OUT 246,"+A$(SD+1 TO ): LET SD=SD+5
9769 IF SD<LEN A$ THEN GO TO 9750
9770 GO TO STATEMENT
9800 IF NOT lprint THEN GO TO statement
9810 RESTORE 9810: GO SUB poke: GO TO statement: DATA 33,59,92,203,142,-PI
9900 REM TRUE STRINGS
9910 LET S=1+CODE A$(2)-CODE "A"
9915 GO SUB CHOP: GO SUB CHOP: GO SUB CHOP
9920: IF CODE A$=CODE "=" THEN GO TO 9950
9921 GO SUB item
9922 GO SUB CHOP: GO SUB CHOP: GO SUB string
9923 RESTORE 9923:: GO TO POKE: DATA 1,FN L(S(S)-1),FN H(S(S)-1),9,119,-PI
9924 REM LD BC,STRING ADDRESS ADD HL,BC LD (HL),A
9950 IF a$( TO 2)<>"=""" THEN PRINT "string syntax error": STOP
9955: GO SUB chop: GO SUB chop
9962 LET SL=HIMEM: LET SH=SL
9965: IF CODE A$<>CODE """" THEN POKE HIMEM*P,CODE A$: LET HIMEM=HIMEM+1: LET SH=SH+1:: GO SUB CHOP: GO TO 9965
9970:: RESTORE 9970: IF SH>SL THEN :: GO TO POKE: DATA 17,FN L(S(S)),FN H(S(S)),33,FN L(SL),FN H(SL),1,FN L(SH-SL),FN H(SH-SL),237,176,-PI
9980 RETURN
9990 REM
9991: LET loc=(loc+himem)*(NOT p)+p*himem: IF NOT p THEN LET himem=loc-himem:
9992 IF NOT p THEN FOR s=1 TO 26:: LET temp=s(s): LET s(s)=loc: LET loc=temp+loc: NEXT s: RETURN
9993: RETURN
9998 PRINT "RESAVE?": PAUSE 0: IF INKEY$="Y" OR INKEY$="y" THEN SAVE "COMPASS" LINE 9998: PRINT "now VERIFY ": VERIFY "COMPASS": PRINT "program OK": GO TO 9998
9999 CLS : PRINT "If you want to use the assembler then type: DELETE 8888,9999 OR If you want to use the compiler then type: DELETE 0,8888 Note that the assembler will work with the compiler still in memory, but the compiler will not work with the assembler in memory. So DELETE the assemblerif you want to use the compiler."
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
