1
0
mirror of https://github.com/PDP-10/its.git synced 2026-02-05 16:14:50 +00:00
Files
PDP-10.its/src/aplogo/logo.958
Lars Brinkhoff d536b228ac Apple II Logo.
Written by:
- Stephen L. Hain
- Patrick G. Sobalvarro
- Leigh L. Klotz.
2018-09-17 20:13:47 +02:00

13451 lines
204 KiB
Plaintext

;-*-MIDAS-*-
.NLIST SEQ
.ENABL LC
.TITLE APPLE-LOGO
; LOGO Language Interpreter for the Apple-II-Plus Personal Microcomputer
; Written and developed by Stephen L. Hain, Patrick G. Sobalvarro,
; and the M.I.T. LOGO Group, at the Massachusetts Institute of
; Technology.
; Property of the M.I.T. LOGO Laboratory,
; 545 Technology Square, Cambridge, MA 02139.
; All rights reserved.
.PAGE
.SBTTL Assembly Data
; Page Zero Variables:
LNIL =0 ;The NIL node
PRECED =4 ;Current function's precedence
NARGS =5 ;No. of arguments for current function
EXPOUT =6 ;Output expected if nonzero
OTPUTN =7 ;Number of outputs given
EDSW =8 ;Edit mode if nonzero
GRPHCS =9 ;Indicates graphics mode if nonzero
CHBUFS =10 ;Character buffer next-free-loc pointer
RUNFLG =11 ;Evaluating the RUN primitive if nonzero
STPFLG =12 ;Stop executing current Ufun if nonzero
DCOFLG =13 ;Return from current break-loop if nonzero
FUNTYP =14 ;Typecode of current function
UFRMAT =15 ;Format (List or Fpack) of current Ufun
ERRFLG =16 ;Error code of last error
RETADR =17 ;Holds stack pointer reset value for error recovery
ERRRET =18 ;Holds program counter reset value for error recovery
SP =20 ;Stack pointer
VSP =22 ;Value-stack pointer
SIZE1 =24 ;Size of area pointed to by AREA1
SIZE2 =26 ;Size of area pointed to by AREA2
AREA1 =28 ;Pointer to g.c.-protected area of SIZE1 contiguous nodes
AREA2 =30 ;Pointer to g.c.-protected area of SIZE2 contiguous nodes
; Monitor variables:
WNDLFT =32
WNDWTH =33
WNDTOP =34
WNDBTM =35
CH =36
CV =37
;DOS wants 38,39
BASLIN =40
BSLTMP =42
;DOS wants 42,43,44,45,46,47
MODE =49
INVFLG =50
;DOS wants 51
DSPFL1 =51
YSAV =52
YSAV1 =53 ;(DOS wants 53,54,55,56,57)
CSWL =54
CSWH =55
KSWL =56
KSWH =57
PCL =58
PCH =59
A1L =60
A1H =61
A2L =62 ;(DOS wants 62,63,64,65,66,67,68,69,70,71,72)
A2H =63
A3L =64
A3H =65
A4L =66
A4H =67
A5L =68
A5H =69
ACC =69
XREG =70
YREG =71
STATUS =72
SPNT =73
;(DOS wants 74,75,76,77)
LTRUE =78 ;TRUE atom pointer
LFALSE =80 ;FALSE atom pointer
RANDOM =82 ;Random number
MONFLG =84 ;Flag indicates Monitor mode (if non-zero)
BANK4K =85 ;High-RAM 4K bank select flag (0=first, 1=second)
PRDFLG =86 ;Indicates READ_LINE is executing, for CONS
INDEV =87 ;Input device code (zero is Apple standard I/O)
OUTDEV =88 ;Output device code (zero is Apple standard I/O)
SOBLST =89 ;Pointer to start of System Object List
SOBTOP =91 ;Pointer to end of System Object List
SARTOP =93 ;Pointer to end of System Array
FRLIST =95 ;Pointer to start of Freelist
TOKPTR =97 ;Token Pointer
CURTOK =99 ;Curent Token pointer
NEXTOK =101 ;Next Token pointer
FUNCT =103 ;Points to current Function
TEMPX3 =105 ;Temporary variable
FRAME =107 ;Pointer to current stack frame
XFRAME =109 ;Pointer to end of current stack frame
FBODY =111 ;Pointer to full body of current Ufun
FBODY1 =113 ;Current Ufun body or System index
LINNUM =115 ;Current Ufun line number
FPTR =117 ;Pointer to remainder of Ufun being executed
GOPTR =119 ;Pointer to location of Ufun line to GO to
ULNEND =121 ;Pointer to end of current line of Fpack Ufun
LEVNUM =123 ;Ufun nesting level
NEST =125 ;EVAL nesting of current EVLINE
DSPFL2 =127 ;DOS wants 127
TLLEVS =128 ;Number of tail recursions included in LEVNUM
IFLEVL =130 ;IF nesting level
EDTATM =132 ;Pointer to atom of Ufun currently being edited
MARK1 =134 ;Garbage collector protected variable
MARK2 =136 ; "
MARK3 =138 ; "
MARK4 =140 ; "
MARK5 =142 ; "
OBLIST =144 ;Pointer to Object List
UNSUM =146 ;Unary_Sum pointer
UNDIF =148 ;Unary_Difference pointer
ILINE =150 ;Pointer to current or last command line
EDBOD =152 ;Pointer to body of Ufun (Flist type) currently being edited
CELPTR =154 ;Garbage collector protected variable
PODEFL =156 ;Default Ufun atom for PO
ARG2 =158 ;Primitive's second argument
NARG2 =158 ;Primitive's second argument (numerical - 4 bytes)
ARG1 =162 ;Primitive's first argument
NARG1 =162 ;Primitive's first argument (numerical - 4 bytes)
TEMPNH =166 ;Temporary variable (must follow NARG1 for floating pt. routines)
TEMPN =168 ; "
TEMPN1 =170 ; "
TEMPN2 =172 ; "
TEMPN3 =174 ; "
TEMPN4 =176 ; "
ANSN =178 ; "
ANSN1 =179 ; "
TEMPN5 =180 ;(Last swapped) Temporary variable
TEMPN6 =182 ;Temporary variable
TEMPN7 =184 ; "
TEMPN8 =186 ; "
TEMPX1 =188 ; "
TEMPX2 =190 ; "
ANSN2 =192 ; "
ANSN3 =193 ; "
ANSNX =194 ; "
NNODES =195 ;Number of nodes allocated
; Turtle-Graphics/Editor variables:
EPOINT =197 ;Editor point
ENDBUF =199 ;Location after last character in buffer
PEN =201 ;Indicates pen down if nonzero
TSHOWN =202 ;Indicates turtle shown if nonzero
XCOR =203 ;X-Coordinate, floating pt.
YCOR =207 ;Y-Coordinate, floating pt.
HEADNG =211 ;Heading, floating pt.
GANSN2 =215
GRP0 =216
GRP1 =217
GRP2 =218
GRP5 =219
GTMP4 =220
DERCOD =222 ;Error code location for DOS
COLR =223 ;Color
CHBUFR =224 ;Character buffer next-char-to-read pointer
RNDL =225
RNDH =226
.PAGE
; LOGO primitive pointers (page 3):
ALL =$340
COMMNT =$342 ;Comment
ER =$344
ERASE =$346
LELSE =$348 ;Else
LEND =$34A ;End
LIF =$34C ;If
LPAR =$34E ;(Left-parenthesis)
LSTOP =$350 ;Stop
LTHEN =$352 ;Then
LTITLE =$354 ;Title
NAMES =$356
PO =$358
POTS =$35A
PRNTOT =$35C ;Printout
PROCS =$35E ;Procedures
RPAR =$360 ;(Right-parenthesis)
TI =$362
TITLES =$364
INFSUM =$366 ;(Infix Sum)
INFDIF =$368 ;(Infix Difference)
LASTPP =INFDIF
.PAGE
; Type code constants:
LIST =0 ;List
ATOM =1 ;Atom (either Qatom, Datom, Latom)
STRING =2 ;Regular linked-list
FIX =3 ;Integer (GT2NUM requires that FIX < FLO)
FLO =4 ;Floating point number
SFUN =5 ;System Function
UFUN =6 ;User Function
SATOM =7 ;System atom
QATOM =8 ;Quoted atom
DATOM =9 ;Dotted atom
LATOM =10 ;Label atom
FPACK =11 ;Packed Ufun
FLIST =12 ;Regular Ufun format
; Tokenizer constants:
NEWLIN =1 ;Start of input line
NEWLST =2 ;Start of sublist
REGCEL =3 ;Regular linked cell
; General constants:
FULCHR =$06 ;Full-screen graphics character (Control-F)
STPKEY =$07 ;Stop-key character code (Control-G)
MIXCHR =$0C ;Mixed-screen graphics character (Control-L)
PULCHR =$10 ;Re-enter last line typed (Control-P)
LSTKEY =$13 ;Interrupt output listing (Control-S)
PAUSKY =$1A ;Pause-key character code (Control-Z)
RPRMPT =$3C ;REQUEST prompt ("<")
EPRMPT =$3E ;Edit-mode prompt character (">")
QPRMPT =$3F ;Regular prompt character (Question-mark)
LBRAK =$5E ;Left-bracket replacement character
GCVST =MARK1 ;Start of Garbage Collecor protected variable area
GCVEND =CELPTR+2 ;End of Garbage Collector protected variable area
LININC =10 ;Default line number increment
MONNUM =15 ;Number of Monitor commands
RANDA =5353 ;Random transform constant "A"
RANDC =43277 ;Random transform constant "C"
TTLC1 =6 ;Turtle length constant, center to tip
TTLC2 =18 ;Turtle length constant, side
TTLC3 =12 ;Turtle length constant, rear
TTLA1 =160 ;Turtle angle constant, first turn
TTLA2 =110 ;Turtle angle constant, base turns
; I/O Device constants:
KBD =0 ;For Keyboard input
VDT =0 ;For Screen output
BUFFER =1 ;For buffer I/O
; Storage Parameters:
LINARY =$200 ;Input line buffer (page 2)
CHBSTT =$300 ;Start of character buffer
CHBLEN =64 ;Length of character buffer
TMPNUM =TEMPN5-TMPSTT+2;Number of temporary bytes to swap
TMPSTT =TEMPNH ;Start of page-zero swapped temporaries
TMPTAB =LASTPP+2 ;Start of temporary storage area (page 3)
GRPSTT =$2000 ;Start of hires graphics area
GRPEND =$4000 ;End of Hires graphics area
EDBUF =$2000 ;Start of editor buffer
EBFEND =$3FFB ;End of edit buffer (with room for CR and EOF marker)
SYSTAB =$30 ;Page no. of System tables (after loading)
GHOMEM =$D0 ;Page no. of Ghost-memory
TDIFF =$A000 ;Difference between above storage areas
; Mapped I/O locations:
GETRM1 =$C08B ;Enable high RAM (with first 4K bank)
GETRM2 =$C083 ;Enable high RAM (with second 4K bank)
KILRAM =$C08A ;Deselect high RAM (enable Monitor/BASIC)
KPFLAG =$C000 ;Keyboard input byte
KPCLR =$C010 ;Keyboard clear strobe
SPKR =$C030 ;Toggle speaker
IOADR =$C0 ;Start of I/O ROM area
; Interrupt Vector areas:
RSTVEC =$FFFC ;Location of RESET vector
IRQVEC =$FFFE ;Location of IRQ vector
NMIVEC =$FFFA ;Location of NMI vector (BRK command)
; System vectors:
USRADR =$03F8 ;User JMP location for ROM monitor
SYSMON =$FF59 ;ROM monitor entry point
; DOS sacred locations
DOSEAT =$A851 ;DOS subroutine to give DOS control of input
DOSERR =$00D8 ;DOS onerr goto flag - set high bit to turn on
DSERET =$9D5A ;DOS error return address
DLNGFG =$AAB6 ;DOS language flag -- stuff a $40 for Applesoft
FILLEN =$AA60 ;length of last file loaded
APCOUT =$FDED ;location of COUT routine in monitor (DOS calls it)
.PAGE
; System Function Constants:
INULL =0
ITHNGP =1 ;Thingp
IWORD =2
IWORDP =3
IUNSUM =4 ;Unary_sum
IUNDIF =5 ;Unary_difference
IMAKE =6
IOTPUT =7 ;Output
ISTOP =8
IPRINT =9
ITYPE =10
IDEFIN =11 ;Define
ICLEAR =12
ICNTIN =13 ;Continue
IPAUSE =14
IELSE =15
ISNTNC =16 ;Sentence
IBOTH =17
IEITHR =18 ;Either
ITHEN =19
INOT =20
ILPAR =21 ;(Left-parenthesis)
IRPAR =22 ;(Right-parenthesis)
IIF =23
IRUN =24
IGO =25
IBPT =26 ;.bpt
IGDBYE =27 ;Goodbye
IGCOLL =28 ;.gcoll
INODES =29 ;.nodes
IBTFST =30 ;Butfirst
IFIRST =31
IBTLST =32 ;Butlast
ILAST =33
ITO =34
IEDIT =35
IEND =36
ITEXT =37
IFORWD =38 ;Forward
IBACK =39
IRIGHT =40
ILEFT =41
ILIST =42
ICS =43
IHOME =44
IPENUP =45
IPENDN =46 ;Pendown
IEMPTP =47
ISHOWT =48 ;Showturtle
IHIDET =49 ;Hideturtle
ITSTAT =50 ;Turtlestate
ITITLE =51
IFPUT =52
IPO =53
IALL =54
INAMES =55
IERASE =56
IREAD =57
ISAVE =58
IREQST =59 ;Request
ITHING =60
IRETRV =61 ;Retrieve
ISUM =62
IDIF =63 ;Difference
IPROD =64 ;Product
IQUOT =65 ;Quotient
IGREAT =66 ;Greater
ILESS =67
ICOMNT =68 ;Comment
IEQUAL =69
ITRCBK =70 ;Traceback
IPOTS =71
ITITLS =72 ;Titles
IPROCS =73 ;Procedures
IPEEK =74
IPOKE =75
INSUM =76 ;Infix Sum
INDIF =77 ;Infix Difference
INPROD =78 ;Infix Product
INQUOT =79 ;Infix quotient
INGRTR =80 ;Infix Greater
INLESS =81 ;Infix Less
INEQUL =82 ;Infix Equal
ILPUT =83
IRANDM =84 ;Random
ICTYI =85
ICURSR =86 ;Cursor
IRNDMZ =87 ;Randomize
ICALL =88
ILISTP =89
INMBRP =90 ;Numberp
ICLINP =91
ICHNGE =92
IRPEAT =93
ISETX =94
ISETY =95
ISETXY =96
ISETH =97
ISETT =98
IXCOR =99
IYCOR =100
IHDING =101 ;Heading
INDSPL =102 ;Nodisplay
IINT =103
IFULL =104
IMIX =105
IDELET =106 ;delete file
ICATLG =107 ;list files
.PAGE
; Error Codes:
XUOP =1
XEOL =2
XUDF =3
XHNV =4
XNIP =5
XNOP =6
XRPN =7
XIFX =8
XVNA =9
XTIP =10
XWTA =11
XUBL =12
XNTL =13
XNTF =14
XELS =15
XBRK =16
XLABEL =17
XTHN =18
XLNF =19
XEDT =20
XDEF =21
XETL =22
XNED =23
XOPO =24
XTML =25
XDBZ =26
XNWE =27
XLNTB =28
XILN =29
XOFLOW =30
XNDF =31
XCRSR =32
XYNT =33
XOOB =34
XIOR =35
XWTP =36
XFNF =37
XDKF =38
XLKF =39
XZAP =100 ;(Errors not in dispatch table)
XARGTB =101
XNSTOR =0 ;(XZAP Quantifiers)
XNSTRN =1
XSTOP =2
XEXCED =3
.PAGE
; Storage Parameters and Map:
; Miscellaneous: Page 0 - Variables
; Page 1 - Processor Stack
; Page 2 - Input line buffer
; Page 3 - Pointers, variable storage, character buffer
; Pages 4 to 7 - Text screen page
; Pages 8 to 13 - System Primitive Array
; Pages 14 to 31 - Stacks (PDL, VPDL)
; Pages 32 to 63 - Hi-res. graphics scrren/Screen editor buffer
; MISC.: $0000 - $07FF: $ 800 bytes (2K bytes)
; SARRAY: $0800 - $0DFF: $ 600 bytes (1.5K characters)
; STACKS: $0E00 - $1FF9: $11F9 bytes (about 2.25K words) PDL, VDPL
; VECTORS: $1FFA - $1FFF: $ 6 bytes (2 vectors) Start address, restart address
; BUFFER: $2000 - $3FFF: $2000 bytes (8K bytes) Screen Editor, Graphics, boot buffer
; LOGO: $4000 - $95FF: $5600 bytes (21.5K bytes)
; DOS: $9600 - $BFFF: $2A00 bytes (10.5K bytes)
; I/O: $C000 - $CFFF: $1000 bytes (4K bytes)
; BIGARRAY: $D000 - $F65F: $2660 bytes (2456. nodes)
; TYPBASE: $F660 - $FFF7: $ 998 bytes (2456. typecodes)
; UNUSED: $FFF8 - $FFF9: $ 2 bytes
; INTRPTS.: $FFFA - $FFFF: $ 6 bytes (3 vectors) NMI, RESET, IRQ addresses
; GHOSTMEM: $D000 - $DFFF: $1000 bytes (4K bytes)
PGMSTT =$4000 ;Program starts after High-res. graphics storage
BIGBAS =$D000 ;Nodespace beginning
BBASX =BIGBAS-4
BIGLEN =$2660 ;Nodespace length
SINODS =BIGBAS+BIGLEN ;Nodespace end
;OFSET1 =BIGBAS/4 but the stupid cross assembler can't divide correctly so we have to it...
OFSET1 =$3400 ;Offset constant
TYPBAS =SINODS-OFSET1 ;Typebase offset
TYPLEN =BIGLEN/4 ;Typebase length
TYPEND =SINODS+TYPLEN ;Typebase end
NODTST =50 ;Minimum free nodes for tokenizer
NODLIM =TYPLEN-NODTST ;Node allocation limit
BASARY =$800 ;SARRAY beginning
SARLEN =$600 ;SARRAY length
STKLEN =$11F9 ;Combined stack length
PDLBAS =BASARY+SARLEN ;PDL beginning (grows upwards, Push-then-incr.)
VPDLBA =PDLBAS+STKLEN-2;VPDL beginning (grows downwards, Push-then-decr.)
STKLIM =80 ;Minimum unused stack space before panicking
.PAGE
.SBTTL Top Level
.=PGMSTT
;Calling point for the LOGO Interpreter
LOGO: LDA GETRM2 ;Select Ghost-memory bank 2 for writing
LDA GETRM2
LDX #$00
STX TEMPNH
STX TEMPN
INX
STX BANK4K
LDA #SYSTAB ;Page no. of tables
STA TEMPNH+1
LDA #GHOMEM ;Page no. of ghost-memory
STA TEMPN+1
LDY #$00
MOVLOP: LDA (TEMPNH),Y
STA (TEMPN),Y
INY
BNE MOVLOP
INC TEMPNH+1
INC TEMPN+1
LDA #ENDTAB^
CMP TEMPNH+1 ;See if last page transferred
BCS MOVLOP
;falls through
;Re-entry point for GOODBYE:
;falls in
LOGO1: SEI ;Disable interrupts
CLD ;Disable decimal mode
LDX #$00
TXS ;Initialize processor stack
STX MONFLG ;Disable monitor mode
STX $00 ;Define LNIL as $0000 at $0000
STX $01
STX $02
STX $03
STX BANK4K
LDA GETRM1
LDA GETRM1 ;Disable Ghost-memory bank 2
LDA #MONBRK&$FF
STA IRQVEC
STA NMIVEC ;Interrupts cause a break to Monitor
LDA #MONBRK^
STA IRQVEC+1
STA NMIVEC+1
LDA #MONBRK&$FF ;?Vector to LOGO when debugged
STA RSTVEC ;RESET reinitializes LOGO
LDA #MONBRK^
STA RSTVEC+1
JSR INITLZ
LDX #HELSTR&$FF
LDY #HELSTR^
JSR PRTSTR ;Types Hello-String
TOPLOP: LDX #ILINE
JSR PRDLIN ;Get a line
TYA
BNE TOPLOP ;Y nonzero means not OK
LDA ILINE+1
BEQ TOPLOP ;Ignore if line is empty
STA TOKPTR+1
LDA ILINE
STA TOKPTR
LDA EDSW
BEQ EVLUAT ;Evaluate it if not in Edit mode
JSR CHKLNN
LDY #$00
CMP #FIX
BEQ TOPEDL ;If there's a line number, add it to the procedure
JSR CHKEVL ;Returns Carry set if Evaluatable
BCS EVLUAT
TOPLIN: LDX #ILINE
STX ANSN
LDA #FLIST
JSR CONS
LDY #$01
TOPEDL: JSR EDLINE
JMP TOPLOP
.PAGE
.SBTTL Evaluator Routines
;EVLUAT initializes the Evaluator variables, starts EVLINE.
EVLUAT: LDA #PDLBAS&$FF
STA SP
LDA #PDLBAS^
STA SP+1 ;SP := PDLBASE
LDA #VPDLBA&$FF
STA VSP
LDA #VPDLBA^
STA VSP+1 ;VSP := VPDLBASE
LDA #$00
STA EXPOUT ;EXPECTED_OUTPUT := 0
STA RUNFLG ;RUN_FLAG := 0
STA STPFLG ;STOP_FLAG := 0
STA DCOFLG ;DONT_CONTINUE_FLAG := 0
STA ERRFLG ;ERROR_FLAG := 0
STA LEVNUM
STA LEVNUM+1 ;LEVEL_NUMBER := 0
STA LINNUM
STA LINNUM+1 ;LINE_NUMBER := 0
STA FRAME+1 ;FRAME := 0
STA XFRAME+1 ;XFRAME := 0
STA UFRMAT ;UFORMAT := LIST
LDX #TOPLOP&$FF
LDY #TOPLOP^
JSR PUSH ;Top-level Return Address (TOPLOP)
;falls through
.PAGE
;EVLINE called with TOKPTR pointing to line of code to execute.
; Pushes IFLEVEL and EXPOUT and then resets them.
;falls in
EVLINE: JSR STKTST
LDX EXPOUT
JSR PUSH
LDX #IFLEVL
JSR PUSHP
LDA #$00
STA EXPOUT ;EXPECTED_OUTPUT := 0
STA IFLEVL ;IF_LEVEL := 0
STA IFLEVL+1
LDA TOKPTR+1
BEQ EVLN1P
EVLN1: LDY #$00
LDA (TOKPTR),Y
STA TEMPN
INY
LDA (TOKPTR),Y
STA TEMPN+1 ;(GETTOK)
LDX #TEMPN
JSR GETTYP
CMP #LATOM
BNE EVLIN1
LDX #TOKPTR
JSR TTKADV
;falls through
;EVLIN1 keeps calling EVLEXP until EOL.
;falls in
EVLIN1: LDA TOKPTR+1
BNE EVLN1A
EVLN1P: LDX #IFLEVL
JSR POP
JSR POPB
STA EXPOUT
POPJ: LDX #TEMPN
JSR POP
JMP (TEMPN)
EVLN1A: LDA STPFLG
BNE EVLN1P
LDX #EVLIN1&$FF
LDY #EVLIN1^
JSR PUSH ;PUSH (EVLIN1) Return Address
;falls through
;EVLEXP calls EVAL with PRECED = 0. EVAL returns to EVEX1,
;which restores old PRECED.
;falls in
EVLEXP: LDX PRECED
JSR PUSH ;Call PUSH (PRECEDENCE)
LDA #$00
STA PRECED ;PRECEDENCE := 0
LDX #EVEX1&$FF
LDY #EVEX1^
JSR PUSH ;Call PUSH (EV_EX_1)
;falls through
.PAGE
;EVAL dispatches to either EVWRAP, PARLOP, UFUNCL, or SFUNCL.
;All return eventually to EVWRAP.
;falls in
EVAL: LDX #CURTOK ;Push CURTOK and increment NEST if FRAME <> 0
JSR PUSHP
LDA FRAME+1
BEQ XEVL2
XEVL1: INC NEST
BNE XEVL2
INC NEST+1
BPL XEVL2
JMP EXCED
XEVL2: LDA TOKPTR+1
BNE XEVL3
JMP SCMMT1 ;ERROR End-of-Line if EOL
XEVL3: LDY #$00 ;Get CURTOK and NEXTOK
LDA (TOKPTR),Y
STA CURTOK
INY
LDA (TOKPTR),Y
STA CURTOK+1 ;(GETTOK)
LDX #TOKPTR
JSR TTKADV
JSR GTNXTK
LDX #CURTOK
JSR GETTYP ;Dispatch off Type of CURTOK
CMP #SATOM
BEQ XCASA
CMP #ATOM
BEQ XCASA
CMP #DATOM
BEQ XCASD
CMP #LIST
BEQ XCASQ ;(If LIST)
CMP #QATOM
BEQ XCASQ
CMP #FIX
BEQ XCASQ
CMP #FLO
BEQ XCASQ
XCASL: LDA #XLABEL ;ERROR, can't execute a label
JMP ERROR
XCASD: LDY #CURTOK ;DATOM, so VPush it unless it's Novalue (then Error)
LDX #TEMPN
JSR GETVAL
LDX #TEMPN ;For VPUSHP in XCASQ1
LDA TEMPN+1
BNE XCASQ1
LDA TEMPN
BEQ XCASQ1
LDA CURTOK
AND #$FC
STA CURTOK
LDY #CURTOK
LDA #XHNV
JMP ERROR
XCASQ: LDA CURTOK ;QATOM, FIX, FLO, LIST: Just push it and set OTPUTN
AND #$FC ;Strip off last two bits
STA CURTOK
LDX #CURTOK
XCASQ1: JSR VPUSHP ;VPUSH (CURRENT_TOKEN)
INC OTPUTN
JMP EVWRAP
XCASA: LDX #CURTOK ;ATOM, SATOM: It's some sort of Function
LDA #FUNCT
JSR GETFUN
STA FUNTYP
LDA FUNCT+1
BNE XCASA1
LDY #CURTOK
LDA #XUDF
JMP ERROR ;Error if GETFUN couldn't find it
XCASA1: LDA FUNTYP
LDX #FUNCT
JSR INFIXP
BCC XCASA2
CMP #INSUM
BNE XCASA3
LDX UNSUM
LDY UNSUM+1
BNE XCASA4 ;(Always)
XCASA5: LDY #CURTOK
LDA #XIFX
JMP ERROR
XCASA3: CMP #INDIF
BNE XCASA5
LDX UNDIF
LDY UNDIF+1
XCASA4: STX CURTOK
STY CURTOK+1
LDX #CURTOK
LDA #FUNCT
JSR GETFUN
STA FUNTYP
XCASA2: LDX PRECED ;It should be a UFUN or SFUN
JSR PUSH
LDY FUNTYP
LDX #FUNCT
JSR GETPRC
STA PRECED
LDA FUNTYP
LDX #FUNCT
JSR GETNGS
BPL XCASF1
EOR #$FF ;NARGS := - NARGS - 1
XCASF1: STA NARGS
LDX #EVAL1&$FF
LDY #EVAL1^
JSR PUSH
;falls through
.PAGE
;falls in
ARGLOP: LDA NARGS ;ARGLOP gets the args for a function
BNE ARGLP1
JMP POPJ ;Exit if no args to be gotten
ARGLP1: LDX NARGS
STX ANSN ;AL1 will push this
JSR PUSH
LDX #FUNCT
JSR PUSHP
LDX FUNTYP
JSR PUSH
LDX EXPOUT
JSR PUSH
LDX #IFLEVL
JSR PUSHP
;falls through
;falls in
AL1: JSR GTNXTK
LDX #NEXTOK
JSR PUSHP
LDX ANSN
JSR PUSH
LDX PRECED
JSR PUSH
LDX #$00
STX IFLEVL
STX IFLEVL+1
INX
STX EXPOUT
LDX #AL2&$FF
LDY #AL2^
JSR PUSH
JMP EVAL
VL1RG: JMP VAL1R ;Error if no output received
AL2: JSR POPB
STA PRECED
JSR POPB
STA ANSN
LDX #NEXTOK
JSR POP
LDA OTPUTN
BEQ VL1RG
DEC ANSN
BNE AL1 ;Get another arg if not done
LDX #IFLEVL
JSR POP
JSR POPB
STA EXPOUT
JSR POPB
STA FUNTYP
LDX #FUNCT
JSR POP
JSR POPB
STA NARGS
JMP POPJ
CHKEVL: LDX TEMPN
LDY TEMPN+1
CPX POTS
BNE CHKEV2
CPY POTS+1
BEQ EVLOK
CHKEV2: CPX LEND
BNE CHKEV3
CPY LEND+1
BEQ EVLOK
CHKEV3: CPX PO
BNE CHKEV4
CPY PO+1
BEQ EVLOK
CHKEV4: CPX PRNTOT
BNE CHKEV5
CPY PRNTOT+1
BEQ EVLOK
CHKEV5: CPX LTITLE
BNE CHKEV6
CPY LTITLE+1
BEQ EVLOK
CHKEV6: CPX ERASE
BNE CHKEV7
CPY ERASE+1
BEQ EVLOK
CHKEV7: CPX ER
BNE EVLNO
CPY ER+1
BNE EVLNO
EVLOK: SEC
RTS
EVLNO: CLC
RTS
EVEX1: JSR POPB
STA PRECED
JMP POPJ
.PAGE
PARLOP: LDX #NEXTOK ;Executed when an LPAR is encountered
LDA #FUNCT
JSR GETFUN
STA FUNTYP
CMP #SFUN
BNE PARLPA
LDA NEXTOK
CMP RPAR
BNE PARLPA
LDA NEXTOK+1
CMP RPAR+1
BNE PARLPA
LDA #XNIP ;"Nothing inside parenthesis"
JMP ERROR
PARLPA: LDA FUNCT+1
BEQ PARLP7
PARLP1: LDA FUNTYP
LDX #FUNCT
JSR GETNGS
STA NARGS
PARLP4: LDA NARGS
BMI PARLP3
PARLP7: LDX EXPOUT
JSR PUSH
LDX #IFLEVL
JSR PUSHP
LDX #$00
STX IFLEVL ;IF_LEVEL := 0
STX IFLEVL+1
INX
STX EXPOUT
LDX #PLOP1&$FF
LDY #PLOP1^
JSR PUSH
JMP EVLEXP
PARLP3: LDY FUNTYP
LDX #FUNCT
JSR GETPRC
STA PRECED
LDA NEXTOK
STA CURTOK
LDA NEXTOK+1
STA CURTOK+1 ;CURRENT_TOKEN := NEXT_TOKEN
LDX #TOKPTR
JSR TTKADV
LDA #$00
STA NARGS ;NARGS := 0
LDX #FUNCT
JSR PUSHP
LDX FUNTYP
JSR PUSH
;falls through
.PAGE
;falls in
VARGLP: JSR GTNXTK
LDA NEXTOK
CMP RPAR
BNE VRGLP1
LDA NEXTOK+1
CMP RPAR+1
BNE VRGLP1
JSR POPB ;Call POP (FUNTYPE)
STA FUNTYP
LDX #FUNCT
JSR POP
LDX #TOKPTR
JSR TTKADV
LDA NARGS
EOR #$FF
STA NARGS ;NARGS := - NARGS - 1
JMP FNCAL1
VRGLP1: LDX NARGS
JSR PUSH
LDX #NEXTOK
JSR PUSHP
LDX EXPOUT
JSR PUSH
LDX #IFLEVL
JSR PUSHP
LDX #$00
STX IFLEVL ;IF_LEVEL := 0
STX IFLEVL+1
INX
STX EXPOUT
LDX PRECED
JSR PUSH
LDX #VAL1&$FF
LDY #VAL1^
JSR PUSH
JMP EVAL
.PAGE
VAL1: JSR POPB
STA PRECED
LDX #IFLEVL
JSR POP
JSR POPB
STA EXPOUT
LDX #NEXTOK
JSR POP
JSR POPB
STA NARGS
LDA OTPUTN
BEQ VAL1R
INC NARGS
BNE VARGLP
EXCED: LDA #XZAP
LDX #XEXCED
JMP ERROR
VAL1R: LDA #XNOP
LDY #NEXTOK
JMP ERROR
GTNXTK: LDY #$00
LDA (TOKPTR),Y
STA NEXTOK
INY
LDA (TOKPTR),Y
STA NEXTOK+1 ;(GETTOK)
RTS
.PAGE
;PLOP1 cleans up after a parenthesized expression.
PLOP1: LDX #IFLEVL
JSR POP
JSR POPB
STA EXPOUT
LDA TOKPTR+1
BEQ SCMMTG
JSR GTNXTK
LDA NEXTOK
CMP RPAR ;Next token must be an RPAR, else Error
BNE PLOP1B
LDA NEXTOK+1
CMP RPAR+1
BNE PLOP1B
LDX #TOKPTR ;Everything OK, get the next token and exit
JSR TTKADV
JMP POPJ
PLOP1B: LDA #XTIP
JMP ERROR
SCMMTG: JMP SCMMT1 ;Error if EOL
RUNHAN: LDX UFRMAT
JSR PUSH
LDX #ULNEND
JSR PUSHP
LDX #TOKPTR
JSR VPUSHP
LDA ARG1
STA TOKPTR
LDA ARG1+1
STA TOKPTR+1
LDX RUNFLG
JSR PUSH
LDX #$00
STX OTPUTN
STX UFRMAT
INX
STX RUNFLG
LDX #RH1&$FF
LDY #RH1^
JSR PUSH
JMP EVLINE
RH1: JSR POPB
STA RUNFLG
LDX #TOKPTR
JSR VPOP
LDX #ULNEND
JSR POP
JSR POPB
STA UFRMAT
JMP POPJ
.PAGE
SREAD1: LDA INDEV ;If something reset INDEV to default,
BEQ SREAD3 ;then break out, don't check for EOF.
SRED1A: LDA ENDBUF+1
CMP EPOINT+1
BNE EDIN
LDA ENDBUF
CMP EPOINT
BEQ SREAD2
EDIN: LDX #$00
EDIN2: LDY #$00
LDA (EPOINT),Y
STA LINARY,X
JSR INCPNT
LDA LINARY,X
CMP #$0D
BEQ EDIN1
INX
BNE EDIN2
EDIN1: STX TEMPN7
INC OUTDEV ;Nullify the TPCHR in PRDLIN (closing brackets, etc.)
LDA #ILINE
STA TEMPX2
JSR PRDLNX ;Read a line. If error, reset & go to SREAD2
DEC OUTDEV ;Re-enable TPCHR's
TYA
BEQ SRD1A ;Y zero means OK
LDA #$00
STA ERRFLG
SREAD2: LDA #KBD ;Break out of Read loop, reset INDEV
STA INDEV ;to default.
SREAD3: STA EDSW
STA OTPUTN ;OUTPUTN := 0
JMP POPJ ;Return to S_READ1's superior
SRD1A: LDA ILINE+1
STA TOKPTR+1
BEQ SRED1A
LDA ILINE
STA TOKPTR
LDA EDSW
BEQ SRD1E
JSR CHKLNN
LDY #$00
CMP #FIX
BEQ SRDEDL ;If there's a line number, add it to the procedure
JSR CHKEVL ;Returns Carry set if Evaluatable
BCC SRD1F
SRD1E: LDX #SREAD1&$FF
LDY #SREAD1^
JSR PUSH
JMP EVLINE
SRD1F: LDX #ILINE
STX ANSN
LDA #FLIST
JSR CONS
LDY #$01
SRDEDL: JSR EDLINE
JMP SREAD1
.PAGE
EVWRAP: LDA TOKPTR+1
BEQ EVRETN
LDA OTPUTN
BEQ EVRETN
LDA STPFLG
BNE EVRETN
LDY #$00
LDA (TOKPTR),Y
STA CURTOK
INY
LDA (TOKPTR),Y
STA CURTOK+1 ;(GETTOK)
LDA CURTOK
CMP RPAR
BNE EVW2
LDA CURTOK+1
CMP RPAR+1
BEQ EVRETN
EVW2: LDX #CURTOK
LDA #FUNCT
JSR GETFUN
STA FUNTYP
LDX #FUNCT
JSR INFIXP
BCC EVRETN
LDY FUNTYP
LDX #FUNCT
JSR GETPRC
STA ANSN2
CMP PRECED
BCC EVRETN
BEQ EVRETN
LDX #TOKPTR
JSR TTKADV
JSR GTNXTK
LDX #NEXTOK
JSR PUSHP
LDX #FUNCT
JSR PUSHP
LDX FUNTYP
JSR PUSH
LDX EXPOUT
JSR PUSH
LDX #IFLEVL
JSR PUSHP
LDX PRECED
JSR PUSH
LDA #$01
STA EXPOUT
LDA ANSN2
STA PRECED
LDX #EW1&$FF
LDY #EW1^
JSR PUSH
JMP EVAL
EVRETN: LDA FRAME+1
BEQ EVRET1
EVRTN1: DEC NEST
BPL EVRET1
DEC NEST+1
EVRET1: LDA OTPUTN
BEQ EVRET2
LDA EXPOUT
BNE EVRET2
LDA STPFLG
BNE EVRET2
LDA RUNFLG
BNE EVRET2
LDX #NEXTOK
JSR VPOP
LDY #NEXTOK
LDA #XUOP
JMP ERROR
EVRET2: LDX #CURTOK
JSR POP
JMP POPJ
.PAGE
;EW1 pops everything EVWRAP pushed, checks for output (error if none),
;then goes to FUNCAL with NARGS = 2.
EW1: JSR POPB
STA PRECED
LDX #IFLEVL
JSR POP
JSR POPB
STA EXPOUT
JSR POPB
STA FUNTYP
LDX #FUNCT
JSR POP
LDX #NEXTOK
JSR POP
LDA OTPUTN
BNE EW1A
JMP VAL1R ;(ERROR XNOP,NEXTOK)
EW1A: LDA #$02
STA NARGS ;NARGS := 2
BNE FUNCAL ;(Always)
EVAL1: JSR POPB ;Now that we have the args, get the old PRECED
STA PRECED ; back and do the function
;falls through
;FUNCAL calls either SFUNCL (with FBODY1 = Funct. #) or UFUNCL (with FBODY1
; pointing to text). Both return to EVWRAP. (FNCAL1 is same, except U&SFNCL
; don't return to EVWRAP).
;falls in
FUNCAL: LDX #EVWRAP&$FF
LDY #EVWRAP^
JSR PUSH
FNCAL1: LDA FUNTYP
CMP #SFUN
BEQ FUN1
LDY #$02 ;UFUN, get text pointer
LDA (FUNCT),Y
STA FBODY1
INY
LDA (FUNCT),Y
STA FBODY1+1 ;(CDR)
JMP XUFNCL
FUN1: LDY #$02 ;SFUN, get Function # from Sarray
LDA (FUNCT),Y ;FBODY1 := SARRAY[FUNCT + SA_SINDEX] (SA_SINDEX = 2)
STA FBODY1
;falls through
.PAGE
;falls in
XSFNCL: LDA #$00
STA OTPUTN ;Default, no outputs
LDA #GHOMEM ;Page no. of dispatch addresses
STA TEMPN+1
LDA FBODY1
ASL A
STA TEMPN
BCC XSFNC1
INC TEMPN+1
XSFNC1: LDA GETRM2 ;Ghost-memory bank 2, System table
INC BANK4K
LDY #$00
LDA (TEMPN),Y
STA TEMPNH
INY
LDA (TEMPN),Y
STA TEMPNH+1 ;(CAR)
LDA GETRM1 ;Ghost-memory bank 2 disable
LDA GETRM1
DEC BANK4K
JMP (TEMPNH) ;Execute the routine
;FBODY1 contains a one-byte index to a table of pointers to system routines
;The table starts at GHOMEM, and the index is multiplied by two for indexing
;the sixteen-bit addresses. Adresses in the table are stored low byte first,
;high byte next.
;For THEN, pointer points to XXSFR1
;For RPAR, pointer points to XXSFR2
;For LPAR, pointer points to PARLOP
;For ALL, NAMES, TITLES, and PROCEDURES, pointers all point to XXSFR3
XXSFR1: LDA #XTHN
JMP ERROR
XXSFR2: LDA #XRPN
JMP ERROR
XXSFR3: LDY #CURTOK
LDA #XOPO
JMP ERROR
.PAGE
XUFNCL: LDY #FPTR
LDX #TEMPN ;Lastline
JSR LINPEK
JSR STKTST
LDX #ULNEND
JSR PUSHP
LDX UFRMAT
JSR PUSH
LDX #FBODY
JSR PUSHP
LDX #FPTR
JSR PUSHP
LDX RUNFLG
JSR PUSH
LDA #$00
STA STPFLG
STA RUNFLG
STA GOPTR+1 ;GO_PTR := LNIL (0)
STA TEMPN1+1 ;TEMP := LNIL (0)
LDA FBODY1
STA FBODY
STA FPTR
LDA FBODY1+1
STA FBODY+1
STA FPTR+1
LDA NEST
BNE XUFN1
LDA NEST+1
BNE XUFN1
LDA LEVNUM
BNE XUFN2
LDA LEVNUM+1
BEQ XUFN1
XUFN2: LDA TEMPN+1 ;Lastline
BNE XUFN3
LDA TOKPTR+1
BNE XUFN5
JMP XUFN1A
XUFN3: LDA TOKPTR+1
BEQ XUFN1
XUFN5: LDY #$00
LDA (TOKPTR),Y
STA TEMPN1
INY
LDA (TOKPTR),Y
STA TEMPN1+1 ;(GETTOK)
XUFN1: LDX #FBODY
JSR GETTYP
STA UFRMAT
LDA TEMPN1
CMP LSTOP
BNE XUFN6
LDA TEMPN1+1
CMP LSTOP+1
BNE XUFN6
XUFN1A: LDA XFRAME
STA SP
LDA XFRAME+1
STA SP+1
JMP XTAIL
XUFN6: LDX FRAME
LDY FRAME+1
LDA SP
STA FRAME
LDA SP+1
STA FRAME+1 ;FRAME points to PREV_FRAME
JSR PUSH
LDX #XFRAME
JSR PUSHP
LDX UFRMAT
JSR PUSH
LDX #CURTOK
JSR PUSHP
LDX #NEST
JSR PUSHP
LDX #LINNUM
JSR PUSHP
LDX #TOKPTR
JSR PUSHP
LDX NARGS
INX
JSR PUSH ;PUSH (NARGS+1)
LDX #TLLEVS
JSR PUSHP
LDY #$00
LDA (FUNCT),Y
TAX
INY
LDA (FUNCT),Y
TAY ;(GET_FFRAME)
JSR PUSH
LDX FUNCT
LDY FUNCT+1
INX
BNE XUFN6B
INY
XUFN6B: JSR PUSH ;PUSH (FUNCT+1)
LDY #$01
STY TLLEVS
DEY
STY LINNUM
STY LINNUM+1
STY TLLEVS+1
DEY
STY NEST
STY NEST+1
INC LEVNUM
BNE XUFN6C
INC LEVNUM+1
BNE XUFN6C
JMP EXCED
XUFN6C: INY
LDA FRAME
STA (FUNCT),Y
INY
LDA FRAME+1
STA (FUNCT),Y ;(PUT_FFRAME)
JSR STPTR1
LDY #FBODY
LDX #TEMPN1 ;TEMPN1 gets ARGLIST
JSR GTTULN
XUFNW: LDA TEMPN1+1
BEQ XUFNWE
JSR PTVTST
LDY #$00
LDA (TEMPN1),Y
STA TEMPN2 ;TEMPN2 is VARNAM
INY
LDA (TEMPN1),Y
STA TEMPN2+1 ;(GETTOK)
LDX #TEMPN1
JSR TTKADV
LDY #TEMPN2
LDX #TEMPN ;TEMPN is TEMP1
JSR GETVAL
LDX #TEMPN
JSR PUSHP
LDY #$00
LDA (TEMPN5),Y ;TEMPN5 is POINTER
STA TEMPN
INY
LDA (TEMPN5),Y
STA TEMPN+1 ;(GETBAR)
JSR PTRDEC
LDX #TEMPN
LDY #TEMPN2
JSR PUTVAL
LDX #TEMPN2
JSR PUSHP
JMP XUFNW
XUFNWE: LDA SP
STA XFRAME ;XFRAME points to location after last binding pair
LDA SP+1
STA XFRAME+1
JSR INCVSP
;falls through
.PAGE
;UF1 does a line of the procedure.
;falls in
UF1: LDA GOPTR+1
BNE UF1A
LDX #FPTR
JSR ULNADV
JMP UF1C
UF1A: LDA GOPTR ;GOPTR <> NIL, so FPTR := GOPTR, reset GOPTR.
STA FPTR
LDA GOPTR+1
STA FPTR+1
LDA #$00
STA GOPTR+1
UF1C: LDA STPFLG
BNE UF2A
LDA FPTR+1
BEQ UF2
UF1D: LDY #FPTR
LDX #TOKPTR
JSR GTTULN
LDY #$00
LDA (TOKPTR),Y
STA LINNUM
INY
LDA (TOKPTR),Y
STA LINNUM+1 ;(GETTOK)
LDX #TOKPTR
JSR TTKADV
LDX #UF1&$FF
LDY #UF1^
JSR PUSH
JMP EVLINE
;End of a procedure.
UF2: STA OTPUTN
UF2A: SEC
LDA LEVNUM
SBC TLLEVS
STA LEVNUM
LDA LEVNUM+1
SBC TLLEVS+1
STA LEVNUM+1
LDA #$00
STA STPFLG
JSR POPFRM
JSR POPB
STA RUNFLG
LDX #FPTR
JSR POP
LDX #FBODY
JSR POP
JSR POPB
STA UFRMAT
LDX #ULNEND
JSR POP
JMP POPJ
.PAGE
ERROR1: LDX #$00
STX RUNFLG
LDA ERRFLG
STA ANSNX
STX ERRFLG
CMP #XZAP
BEQ PPTTP
LDX LEVNUM
BNE ERR1A
LDX LEVNUM+1
BEQ PPTTP
ERR1A: CMP #XBRK
BEQ ERR1B
PPTTP: LDA FRAME+1
BEQ PPTT2
PPTTP1: JSR RSTBND
LDY #$02 ;(SF_XFRAME = 2.)
LDA (FRAME),Y
STA XFRAME
INY
LDA (FRAME),Y
STA XFRAME+1 ;(GETBAR)
LDY #$00 ;(SF_PREVIOUS_FRAME = 0)
LDA (FRAME),Y
TAX
INY
LDA (FRAME),Y
STA FRAME+1 ;(GETBAR)
STX FRAME
BNE PPTTP1
PPTT2: LDA #$00
STA LEVNUM
STA LEVNUM+1
LDA ANSNX
CMP #XZAP
BNE JTOP
LDA ANSN3
CMP #XNSTRN
BNE JTOP
LDA #VPDLBA&$FF
STA VSP ;If error was "out-of-nodes",
LDA #VPDLBA^ ;reset VPDL, do a garbage collect,
STA VSP+1 ;and check remaining nodes. If low,
JSR GARCOL ;ask user to delete something.
LDA NNODES+1
CMP #NODLIM^
BCC JTOP
BNE NWARN
LDA NNODES
CMP #NODLIM&$FF
BCC JTOP
NWARN: JSR BREAK1
LDX #WRNMSG&$FF
LDY #WRNMSG^ ;"Please delete something"
JSR PRTSTR
JTOP: JMP TOPLOP
ERR1B: LDA #$00
STA EXPOUT ;(EXPOUT := 0)
CLC
LDA XFRAME
ADC #$02 ;Don't pop the top return address
STA SP ;(RESET_EVAL)
LDA XFRAME+1
ADC #$00
STA SP+1
LDX #TOKPTR ;Save rest of line for CONTINUE
JSR PUSHP
LDX #ULNEND ;Save uline-end for CONTINUE
JSR PUSHP
;falls through
.PAGE
;falls in
ERROR2: LDA DCOFLG
BEQ ERR2A
LDA #$00
STA STPFLG
STA DCOFLG
STA TOKPTR+1
ERR2A1: LDY #$04 ;(SF_FORMAT = 4.)
LDA (FRAME),Y
STA UFRMAT ;(GETBAR)
LDX #ULNEND
JSR POP ;Restore Uline-end
LDX #TOKPTR ;Restore rest of eval-line
JSR POP
JMP POPJ
ERR2A: LDA STPFLG
BNE ERR2A1 ;Zap out of EVLINE without resetting stuff.
LDA #'L ;Both flags = 0, it's a Pause.
JSR TPCHR ;Type an "L"
LDX #LEVNUM
JSR TYPFIX
LDX #TOKPTR
JSR PRDLIN ;Get a line
TYA
BEQ ERR2A2 ;Y zero means OK
JMP ERROR1
ERR2A2: LDX #ERROR2&$FF
LDY #ERROR2^
JSR PUSH
LDA #LIST
STA UFRMAT
JMP EVLINE
.PAGE
XTAIL: LDX #$00
STX LINNUM
STX LINNUM+1
DEX
STX NEST
STX NEST+1
INC LEVNUM
BNE XTAIL1
INC LEVNUM+1
BNE XTAIL1
JMP EXCED
XTAIL1: INC TLLEVS
BNE XTAIL2
INC TLLEVS+1
BNE XTAIL2
JMP EXCED
XTAIL2: JSR STPTR1 ;POINTER is TEMPN1
LDY #$0E ;SF_NUMBER_BINDINGS (14.)
LDA (FRAME),Y
STA TEMPN3 ;BINDINGS
LDY #FBODY
LDX #TEMPN2 ;ARGLIST
JSR GTTULN ;GET_ULINE (ARG_LIST,FBODY,TRUE)
LDY #$04 ;(SF_FORMAT = 4.)
LDA UFRMAT
STA (FRAME),Y ;(PUTBAR)
LDY #$06 ;(SF_UFUN = 6.)
LDA CURTOK
STA (FRAME),Y
INY
LDA CURTOK+1
STA (FRAME),Y ;(PUTBAR)
LDY #$00
LDA (FUNCT),Y
CMP FRAME
BNE XTALWB
INY
LDA (FUNCT),Y ;(GET_FFRAME)
CMP FRAME+1
BNE XTALWB
XTALWA: LDA TEMPN2+1
BEQ XTLWAE
XTALW1: JSR PTVTST
LDY #$00
LDA (TEMPN2),Y
STA TEMPN4 ;VAR_NAME
INY
LDA (TEMPN2),Y
STA TEMPN4+1 ;(GETTOK)
LDX #TEMPN2
JSR TTKADV
LDY #$00
LDA (TEMPN5),Y
STA TEMPN1
INY
LDA (TEMPN5),Y
STA TEMPN1+1 ;(GETBAR)
JSR PTRDEC
LDX #TEMPN1
LDY #TEMPN4
JSR PUTVAL
JMP XTALWA
XTLWAE: LDY #$0E ;(SF_NUMBER_BINDINGS = 14.)
LDA TEMPN3
STA (FRAME),Y
JMP XTAIL4
XTALWB: LDA TEMPN2+1
BEQ XTLWBE
XTALW2: JSR PTVTST
LDY #$00
LDA (TEMPN2),Y
STA TEMPN4
INY
LDA (TEMPN2),Y
STA TEMPN4+1 ;(GETTOK)
LDX #TEMPN2
JSR TTKADV
LDY #TEMPN4
LDX #TEMPN1
JSR GETVAL
LDX #TEMPN1
JSR PUSHP
LDY #$00
LDA (TEMPN5),Y
STA TEMPN1
INY
LDA (TEMPN5),Y
STA TEMPN1+1 ;(GETBAR)
JSR PTRDEC
LDX #TEMPN1
LDY #TEMPN4
JSR PUTVAL
LDX #TEMPN4
JSR PUSHP
JMP XTALWB
XTLWBE: LDY #$00
LDA (FUNCT),Y
STA TEMPN1
INY
LDA (FUNCT),Y
STA TEMPN1+1 ;(GET_FFRAME)
LDX #TEMPN1
JSR PUSHP
LDX FUNCT
LDY FUNCT+1
INX
BNE XTAIL5
INY
XTAIL5: JSR PUSH ;PUSH (FUNCT+1)
LDY #$00
LDA FRAME
STA (FUNCT),Y
INY
LDA FRAME+1
STA (FUNCT),Y ;(PUT_FFRAME)
LDY #$0E
SEC ;Carry added in (BINDINGS + NARGS + 1)
LDA TEMPN3
ADC NARGS
STA (FRAME),Y
LDA SP
STA XFRAME
LDA SP+1
STA XFRAME+1 ;XFRAME := SP (right above last binding pair)
XTAIL4: JSR INCVSP
JMP UF1
.PAGE
STPTR1: LDA NARGS
ASL A
STA TEMPNH
CLC
LDA VSP
ADC TEMPNH
STA TEMPN5
LDA VSP+1
ADC #$00
STA TEMPN5+1 ;POINTR := VSP + (NARGS * 2)
RTS
PTVTST: LDA VSP+1
CMP TEMPN5+1
BNE SBHAK1
LDA VSP
CMP TEMPN5
BNE SBHAK1
PTVBUG: JSR SYSBUG ;Error if POINTER = VSP
PTRDEC: SEC
LDA TEMPN5
SBC #$02
STA TEMPN5
BCS SBHAK1
DEC TEMPN5+1 ;POINTR := POINTR - 2
SBHAK1: RTS
INCVSP: LDA NARGS
ASL A
STA TEMPNH
CLC
LDA VSP
ADC TEMPNH
STA VSP
BCC INCVE
INC VSP+1 ;VSP := VSP + NARGS * 2
INCVE: RTS
.PAGE
.SBTTL Reader and Tokenizer
READLN: STX TEMPX2 ;Input line pointer location
BNE REDLN1 ;(Always)
PRDLIN: STX TEMPX2
LDA EDSW
BEQ PRD2
LDA #EPRMPT ;Edit-mode prompt
BNE PRD3
PRD2: LDA #QPRMPT ;Reqular prompt
PRD3: JSR TPCHR
REDLN1: JSR GETLN ;Get a line into the Line buffer
STX TEMPN7
PRDLNX: LDY #$00
STY TEMPN8 ;List-nesting counter
STY TEMPN8+1 ;Character buffer pointer
STY CELPTR
STY CELPTR+1
LDX TEMPX2
STY $00,X ;Initialize ANS to Lnil
STY $01,X
INY
STY PRDFLG
LDA #RDL1&$FF ;Error return address
STA ERRRET
LDA #RDL1^
STA ERRRET+1
TSX
STX RETADR
LDA #NEWLIN
STA TEMPX2+1 ;Current cell type
RDLNW: LDA TEMPN8+1 ;Loop processes line, token by token
CMP TEMPN7
BNE TGTTOK ;Process the next token
RDLNWE: LDA TEMPN8 ;Done, close all lists
BEQ RDL1A
RDL1A1: LDA OUTDEV
BNE RDL1A2
LDA #'] ;Close the list (unless non-default output)
RDL1A2: JSR TPCHR
LDX #TEMPN1
JSR POP ;Discard pushed list pointers
DEC TEMPN8 ;Decrement list nesting counter
BNE RDL1A1
JSR BREAK1
RDL1A: LDY #$00 ;Y zero means OK
BEQ RDL1B ;(Always)
RDL1: LDY #$01 ;Y nonzero means error
RDL1B: LDA #$00
STA CELPTR
STA CELPTR+1
STA PRDFLG
RSTERR: LDX #$00 ;General reset-error routine
STX RETADR
LDX #ERROR1&$FF
STX ERRRET
LDX #ERROR1^
STX ERRRET+1
RTS
TGTTOK: LDA #$00
STA ANSN3 ;No typecode yet (for SLFDLP)
STA TEMPN7+1 ;Funny-pname if non-zero
STA TEMPN4+1 ;Indicates quoted atom if non-zero
LDX TEMPN8+1
TGT1: LDA LINARY,X
CMP #$20
BNE TGT2
INX
CPX TEMPN7
BNE TGT1 ;Skip spaces
BEQ RDLNWE
TGT2: STX TEMPN8+1
CMP #']
BEQ TKRBR
PHA
JSR ALLSTC
PLA
CMP #'[
BEQ TKLBR
JSR SLFDLP
BCC TKNDL
STA TEMPN5
INC TEMPN8+1
LDX #$00
STX TEMPN5+1
LDY #TEMPN5 ;Cons up a pname
LDA #TEMPN6
STA ANSN
LDA #STRING
JSR CONS
LDA #ATOM
STA ANSN3
JMP ADDTOK
TKLBR: INC TEMPN8 ;Start list - increment list nesting counter
INC TEMPN8+1 ;Skip to next character
LDX #CELPTR
JSR PUSHP ;Push the list-pointer cell
LDA #NEWLST
STA TEMPX2+1 ;Next cell allocated will be New-list type
JMP RDLNW ;Continue processing line
TKRBR: DEC TEMPN8 ;End list - decrement list nesting counter
BMI TKRBR1 ;Error if unbalanced brackets
INC TEMPN8+1 ;Skip to next character
LDX #CELPTR
JSR POP ;Pop list pointer
LDA #REGCEL
STA TEMPX2+1
JMP RDLNW ;Continue processing line
TKRBR1: JSR RSTIO ;Reset I/O to master drivers
LDX #RDRER2&$FF
LDY #RDRER2^
JSR PRTSTR ;Print "You have mismatched brackets" error
JMP RDL1 ;Error escape
TKNDL: CMP #'"
BNE TGT3A
INC TEMPN4+1 ;Quoted atom
INC TEMPN8+1 ;Skip to next character
LDA #QATOM
STA ANSN3
JMP TGT3B1 ;Check for funny-pname
TGT3A: CMP #$27 ;(Single Quote)
BNE TGT3B
INC TEMPN8+1 ;Skip to next character
INC TEMPN7+1 ;Token is a funny_pname
TKAORL: LDA #ATOM ;Token is an Atom or Label
STA ANSN3
JMP TKATOM ;Tokenize it
TGT3B: CMP #':
BNE TKAORL
INC TEMPN8+1 ;Dotted atom, skip to next character
LDA #DATOM
STA ANSN3
TGT3B1: LDX TEMPN8+1
LDA LINARY,X
CMP #$27
BNE TKATOM
INC TEMPN7+1 ;Token is funny-pname
INC TEMPN8+1 ;Skip to next character
TKATOM: LDX TEMPN8+1
CPX TEMPN7 ;Check for empty word at end-of-line
BEQ EMPTWD
LDA TEMPN7+1
BNE NOTNUM ;Funny_pname, not fixnum then
TKATM2: LDA LINARY,X
CMP #$20 ;Check for empty word inside line
BNE TKATM1
EMTWD1: INC TEMPN8+1 ;Skip space if necessary
EMPTWD: LDA #$00 ;Empty word, link Lnil node onto input line
STA TEMPN6
STA TEMPN6+1
JMP ADDTOK ;Link up token and continue
TKATM1: JSR CLRNG1 ;Attempt to compute numerical value, clear indicators
ATM1: STX TEMPN2 ;Save temporary character pointer
CPX TEMPN7
BEQ ATM2 ;End of line encountered, must be numerical
LDA LINARY,X
JSR SLFDLP
BCS ATM2 ;Self delimiter encountered, must be numerical
JSR CNUML1 ;Process the next digit
BCC NOTNUM ;Carry clear means not a number
LDX TEMPN2
INX ;Get next digit
JMP ATM1
ATM2: STX TEMPN2 ;All characters processed - save character pointer
JSR CNUML2 ;Finish numerical processing
BCC NOTNUM
LDX TEMPN2
STX TEMPN8+1 ;Numerically ok, reset real charcater pointer
LDX #TEMPN6
STX ANSN
LDX #NARG1+2 ;High word
LDY #NARG1 ;Low word
JSR CONS ;Cons a numerical cell with the value in it
LDY #$00
LDA TEMPN6
STA (CELPTR),Y ;Link the cell on to the input line
INY
LDA TEMPN6+1
STA (CELPTR),Y
JMP RDLNW ;Continue processing line
NOTNUM: LDX #TEMPX1 ;Not a fixnum - cons up a pname (original pointer)
LDA #$00
STA TEMPN6 ;Zero pointer in case it's nil
STA TEMPN6+1
STA ANSNX ;Indicates end of pname if non-zero
PHA ;First time around, push zero
BEQ NXTCHS ;(Always)
NXTTWO: LDA ANSNX ;Next two characters
BNE ADDTOK ;Link up token if end of pname
LDA #$02
PHA ;Not first time around, push 2
LDX #TEMPN5 ;Next pointer
NXTCHS: STX ANSN
LDX TEMPN8+1
CPX TEMPN7
BEQ ADDTK1 ;Finish token (end of line), even no. chars.
LDA LINARY,X
STA TEMPN1 ;First character in pair
JSR SLFDLP
BCS ADDTK2 ;Finish token (delimiter hit), even no. chars.
INX ;Skip to next character
CPX TEMPN7
BEQ FINTK1 ;Finish token (end of line), odd no. chars.
LDA LINARY,X
STA TEMPN1+1 ;Second character in pair
JSR SLFDLP
BCS FINTK1 ;Finish token (delimiter hit), odd no. chars.
INX
BCC CNSSTR ;(Always) Cons new pair on to pname string
FINTK1: LDA #$00
STA TEMPN1+1 ;Odd no. chars. in pname, zero last character
INC ANSNX ;Indicates end of pname
CNSSTR: STX TEMPN8+1 ;Skip the last character (if not delimiter)
LDY #TEMPN1
LDX #$00
LDA #STRING
JSR CONS ;Cons up the new pname pair
PLA
TAY ;0 first time, 2 otherwise
BNE NTFRST
LDA TEMPX1
STA (CELPTR),Y ;(Linking garbage-collect-protects it)
STA TEMPN6 ;Atom pointer
INY
LDA TEMPX1+1
STA (CELPTR),Y
STA TEMPN6+1
JMP NXTTWO ;Continue making the pname
NTFRST: LDA TEMPN5 ;Link cell onto pname string
TAX
STA (TEMPX1),Y
INY
LDA TEMPN5+1
STA (TEMPX1),Y ;(RPLACD)
STA TEMPX1+1
STX TEMPX1
JMP NXTTWO ;Continue making the pname
ADDTK2: STX TEMPN8+1 ;In case colon or quote skipped
ADDTK1: PLA ;Pop chain indicator if loop exit
ADDTOK: LDX #TEMPN6
LDY #TEMPX1
JSR INTERN ;Intern atom
ATM12B: LDA ANSN3
CMP #ATOM
BEQ ATM12A
LDX #TEMPX1
JSR PUTTYP ;Give atom a type if not Atom
ATM12A: LDY #$00
LDA TEMPX1
STA (CELPTR),Y ;Link atom onto input line
INY
LDA TEMPX1+1
STA (CELPTR),Y
LDA TEMPN7+1
BEQ NXTE
LDX #TEMPX1
JSR PTSPNM ;Put-strange-pname if funny-pname indicated
NXTE: JMP RDLNW ;Continue processing line
ALLSTC: LDA #TEMPN ;Allocate a new list cell
STA ANSN
LDA #$00
TAX
TAY
JSR CONS ;(Type list)
LDY #$00
LDA TEMPX2+1
CMP #NEWLIN
BNE ALSTC1
LDX TEMPX2 ;New line, ANS pointer points to cell
LDA TEMPN
STA $00,X
LDA TEMPN+1
STA $01,X
BNE ALSTC3 ;(Always)
ALSTC1: CMP #NEWLST
BEQ ALSTC4 ;For new-list, rplaca onto input line
INY ;Regular cell, link onto input line
INY
ALSTC4: LDA TEMPN
STA (CELPTR),Y ;Rplaca or Rplacd for new-list or regular-cell
INY
LDA TEMPN+1
STA (CELPTR),Y
ALSTC3: LDA TEMPN
STA CELPTR ;New input line end pointer
LDA TEMPN+1
STA CELPTR+1
LDA #REGCEL
STA TEMPX2+1 ;Next cell allocated will be regular-cell
RTS
.PAGE
SLFDLP: LDY TEMPN7+1 ;Checks for self-delimiter
BEQ SLF2 ;Not funny-pname
CMP #$27 ;If funny-pname, look for quote
BNE DIGN ;Not delimiter if no quote
INX
LDA LINARY,X
CMP #$27 ;Look for pair of quotes
BEQ DIGN ;If pair, skip over one, not delimiter
JMP DIGY ;If no pair, the quote is a delimiter, skip it
SLF2: LDY TEMPN4+1 ;Check for quoted atom
BEQ SLF1
CMP #$20 ;Quoted atoms can be terminated by a space,
BEQ DIGY
CMP #'] ;or a closing bracket,
BEQ DIGY
CMP #') ;or a closing parenthesis.
BEQ DIGY
BNE DIGN ;(Always)
SLF1: LDY ANSN3 ;Check for type Atom
CPY #ATOM
BNE SLF3
CMP #': ;If Atom, check for colon (for Label atom)
BNE SLF3
INX ;If colon, skip over it and change type to Latom
LDY #LATOM
STY ANSN3
JMP DIGY
SLF3: CMP #$20 ;Compare character to all delimiters
BEQ DIGY
CMP #'<
BEQ DIGY
CMP #'>
BEQ DIGY
CMP #'=
BEQ DIGY
CMP #$3B ;(Semicolon)
BEQ DIGY
CMP #')
BEQ DIGY
CMP #'(
BEQ DIGY
CMP #'+
BEQ DIGY
CMP #'-
BEQ DIGY
CMP #'*
BEQ DIGY
CMP #'/
BEQ DIGY
CMP #']
BEQ DIGY
CMP #'[
BNE DIGN
DIGY: SEC ;Carry set means true
RTS
DIGITP: CMP #': ;Checks to see if character is a digit (0-9)
BCC DIGP1
DIGN: CLC ;Carry clear means not true
RTS
DIGP1: CMP #'0 ;(Sets carry correctly)
RTS
.PAGE
.SBTTL Number Parsing Utilities:
;Process a character, number-building
CNUML1: LDX TEMPN5 ;Flonum indicator
BNE NFLDIG ;Process next flonum character
JSR DIGITP ;Still a fixnum
BCC NTFIX1 ;Not a digit, isn't a fixnum then
INC TEMPN6+1 ;Indicate presence of digit
PHA ;Save digit
JSR NMROL1 ;Multiply by 2 first
BMI NTFIX3 ;Not a fixnum if value overflow
LDY #A1L
JSR XN1TOY ;Copy doubled number
JSR NMROL1 ;Multiplied by 4
BMI NTFIX2
JSR NMROL1 ;Multiplied by 8
BMI NTFIX2
JSR ADDNUM ;Multiplied by 10.
BMI NTFIX2
PLA
PHA
JSR ADDDIG ;Add value of current digit to subtotal
BMI NTFIX2
PLA ;Retrieve digit
NUMOK: SEC ;Indicate number OK
RTS
NTFIX2: LDY #A1L
JSR XYTON1 ;Fixnum overflow, doubled number is in A1L-A2H, transfer
NTFIX3: JSR NMROR1 ;Halve it
INC TEMPN5 ;Indicate flonum (1)
JSR FLOTN1 ;Convert to floating pt.
PLA ;Get the digit back
FADNML: INC TEMPN6+1 ;Indicate prescence of digit
JSR MULN10 ;Shift number before adding
JSR FADDIG ;Add it to the number (left of point)
JMP NUMOK
FNDIGD: INC TEMPN6+1 ;Indicate presence of digit
LDX TEMPX1+1 ;See if it's significant
BNE NUMOK ;No, ignore it
JSR FADDGN ;Yes, add it to the number (right of point)
JMP NUMOK
NFLDIG: CPX #$02 ;New flonum digit
BNE NFLDG1
JSR DIGITP ;In decimal mode
BCS FNDIGD ;If digit, add to number
BCC FCKEN ;Else check for E or N
NFLDG1: CPX #$03 ;See if exponent mode
BEQ FXDIG
JSR DIGITP ;Normal mode, check for digit
BCS FADNML ;Add it if it is, else
NTFIX1: CMP #'. ;See if digit is legal
BEQ FMDECI
FCKEN: CMP #'E ;Check for E or N
BEQ FXPOS
CMP #'N
BNE NTNUM
INC TEMPN5+1 ;Indicate negative exponent
FXPOS: LDA TEMPN6+1
BEQ NTNUM ;Check that a digit was typed (so ".Ex" is illegal)
LDX TEMPN5
LDA #$03
STA TEMPN5 ;Indicate exponent mode (3)
LDA #$00
STA TEMPN6+1 ;Now, indicates exponent digit presence
BEQ MAKFLO ;(Always)
FXDIG: JSR DIGITP ;Exponent mode, must be a digit
BCC CNMR
INC TEMPN6+1 ;Indicate presence of exponent digit
JSR INCEXP ;Exponentiate by vA
JMP NUMOK
FMDECI: LDX TEMPN5
LDA #$02
STA TEMPN5 ;Indicate decimal mode (2)
MAKFLO: TXA
BNE NUMOK ;Exit OK if flonum, else...
JSR FLOTN1 ;make it one
JMP NUMOK
NTNUM: CLC ;Not a number
CNMR: RTS
;Number gobbled, finish number-building.
CNUML2: LDX TEMPN5
BEQ CNUM2X
LDA TEMPN6+1 ;If floating pt., make sure that there's a digit
BEQ NTNUM
LDA TEMPN6 ;Check placeholder counter
BEQ CNUM2A
CNUM2B: JSR FDVD10 ;Divide by 10. until back to correct decimal point location
DEC TEMPN6
BNE CNUM2B
CNUM2A: LDA TEMPX1 ;Check for exponent
BEQ CNUM2R
LDA TEMPN5+1 ;Check its sign
BNE CNUM2D
CNUM2C: JSR MULN10 ;Multiply by 10 according to (positive) exponent value
BCS NTNUM
DEC TEMPX1
BNE CNUM2C
BEQ CNUM2R ;(Always)
CNUM2D: JSR FDVD10 ;Divide by 10 according to (negative) exponent value
DEC TEMPX1
BNE CNUM2D
CNUM2R: LDA #FLO
SEC
RTS
CNUM2X: LDA #FIX
SEC
RTS
CLRNG1: LDA #$00
STA NARG1 ;Initialize number to 0
STA NARG1+1
STA NARG1+2
STA NARG1+3
STA TEMPN5 ;Flonum indicator
STA TEMPN5+1 ;Exponent sign indicator
STA TEMPN6 ;Fraction decimal shift (placeholder) counter
STA TEMPN6+1 ;Indicates the presence of a mant. or exp. digit
STA TEMPX1 ;Exponent counter
STA TEMPX1+1 ;Significant digit indicator
RTS
NMROL1: ASL NARG1 ;Double number in NARG1
ROL NARG1+1
ROL NARG1+2
ROL NARG1+3
RTS
NMROR1: LSR NARG1+3 ;Halve number in NARG1
ROR NARG1+2
ROR NARG1+1
ROR NARG1
RTS
XN1TOY: LDX #$FC
XN1YL: LDA NARG1+4,X
STA $00,Y
INY
INX
BMI XN1YL
RTS
XYTON1: LDX #$FC
XYN1L: LDA $00,Y
STA NARG1+4,X
INY
INX
BMI XYN1L
RTS
XYTON2: LDX #$FC
XYN2L: LDA $00,Y
STA NARG2+4,X
INY
INX
BMI XYN2L
RTS
XN2TOY: LDX #$FC
XN2YL: LDA NARG2+4,X
STA $00,Y
INY
INX
BMI XN2YL
RTS
ADDNUM: LDX #$FC ;Add A1L to NARG1
CLC
ADDNML: LDA A1L+4,X
ADC NARG1+4,X
STA NARG1+4,X
INX
BMI ADDNML
TAX
RTS
ADDDIG: SEC ;Add Ascii digit in A to NARG1
SBC #'0
CLC
LDX #$FC
BNE ADDL1A ;(Always)
ADDLP1: LDA #$00
ADDL1A: ADC NARG1+4,X
STA NARG1+4,X
INX
BMI ADDLP1
TAX
RTS
FADDGX: SEC
SBC #'0 ;Get the digit's value
STA NARG2 ;Add A to NARG1, floating pt.
LDA #$00
STA NARG2+1 ;Put A in NARG2, make it floating pt., and add
STA NARG2+2
STA NARG2+3
JSR FLOTN2
JMP FADD
FADDIG: JSR FADDGX
BCS NUMOVF
RTS
FADDGN: PHA ;Add decimal digit to floating pt. number
LDY #A1L
JSR XN1TOY ;Save NARG1
JSR MULN10 ;Multiply number by 10
BCS FADDG1 ;Overflow, digit will be insignificant
PLA ;Get digit
JSR FADDGX ;and add it
BCS FADDG2 ;If overflow, digit not significant
INC TEMPN6 ;Else increment placeholder counter
RTS
FADDG1: PLA ;Discard digit
FADDG2: INC TEMPX1+1 ;Indicate no more significant digits, restore NARG1
LDY #A1L
JMP XYTON1
MULN10: LDX #$03 ;Multiply NARG1 by 10., floating pt.
MLN10L: LDA FLT10,X ;Put 10. (floating pt. constant) in NARG2
STA NARG2,X
DEX
BPL MLN10L
JMP FMUL ;and multiply (calling procedure checks for overflow)
FDVD10: LDX #$03 ;Divide NARG1 by 10., floating pt.
FDV10L: LDA FLT10,X ;Put 10. (floating pt. constant) in NARG2
STA NARG2,X
DEX
BPL FDV10L
JMP FDIV
INCEXP: SEC
SBC #'0
TAY ;Multiply exponent by ten and add new digit
ASL TEMPX1
BMI NUMOVF
LDA TEMPX1
ASL A
BMI NUMOVF
ASL A
BMI NUMOVF
ADC TEMPX1
BMI NUMOVF
STA TEMPX1
TYA
ADC TEMPX1
BMI NUMOVF
STA TEMPX1
RTS
NUMOVF: PLA ;Overflow, pop past subroutine
PLA
CLC ;Indicate not a number
RTS
.PAGE
.SBTTL Initializations
INITLZ: LDA #$00
STA GRPHCS
STA EDSW
STA EDBOD
STA EDBOD+1
JSR RSTIO ;Set I/O to to default
JSR RESETT ;Clear screen, etc.
JSR CLRMRK ;Reset G.C. Array (Typebase bits)
LDA #BASARY&$FF
STA TEMPN
LDA #BASARY^
STA TEMPN+1
LDY #$00
TYA ;Clear the SARRAY, 4 at a time
CLRLP1: STA (TEMPN),Y
INC TEMPN
BNE ADHAK4
INC TEMPN+1
ADHAK4: LDX TEMPN
CPX #PDLBAS&$FF ;PDL starts right after S_ARRAY
BNE CLRLP1
LDX TEMPN+1
CPX #PDLBAS^
BNE CLRLP1
;falls through
.PAGE
;falls in
REINIT: LDX #$00
STX NNODES ;Node allocation counter
STX NNODES+1
STX PODEFL+1
JSR CLRCBF
LDA #BASARY&$FF
STA SARTOP
LDA #BASARY^
STA SARTOP+1
LDA #PDLBAS&$FF
STA SP
LDA #PDLBAS^
STA SP+1
LDA #VPDLBA&$FF
STA VSP
LDA #VPDLBA^
STA VSP+1
LDA #EDBUF&$FF ;Tell RETRIEVE that buffer is not retrievable
STA ENDBUF
LDA #EDBUF^
STA ENDBUF+1
LDA #BIGBAS&$FF ;(FIRST_NODE)
STA SOBLST
STA SOBTOP
LDA #BIGBAS^
STA SOBLST+1 ;SOBLIST := FIRST_NODE
STA SOBTOP+1 ;SOBTOP is SOBPTR for now
LDA #PRMTAB&$FF ;Points to first byte of Primitive-table
STA TEMPN
LDA #PRMTAB^
STA TEMPN+1
SOBLP1: JSR SOBST1
LDA TEMPN+1
CMP #VPRMTB^
BNE SOBLP1
LDA TEMPN
CMP #VPRMTB&$FF
BNE SOBLP1
SEC
LDA SOBTOP
SBC #$08
STA TEMPN1 ;TEMPN1 is SOBTOP - 8, for comparison
LDA SOBTOP+1
SBC #$00
STA TEMPN1+1
SBVLP1: LDA GETRM2 ;Ghost-memory bank 2, VPrim table
INC BANK4K
LDY #$00
LDA (TEMPN),Y
STA ANSN ;ANSN is INDEX constant
INY
LDA (TEMPN),Y
STA TEMPN3+1 ;TEMPN3 is Primitive's pointer address
INY
LDA (TEMPN),Y
STA TEMPN3
INY
LDA (TEMPN),Y
STA ANSN3 ;ANSN3 is INSTANCE counter
LDA GETRM1 ;Ghost-memory disable
LDA GETRM1
DEC BANK4K
CLC
LDA TEMPN
ADC #$04
STA TEMPN
BCC ADHAK8
INC TEMPN+1
ADHAK8: LDA #BBASX&$FF
STA TEMPN2 ;TEMPN2 is temporary VARNAM pointer
LDA #BBASX^
STA TEMPN2+1
SBVRW: LDA TEMPN1+1
CMP TEMPN2+1
BNE SBVRW1
LDA TEMPN1
CMP TEMPN2
BNE SBVRW1
JSR SYSBUG
SBVRW1: CLC
LDA TEMPN2
ADC #$04
STA TEMPN2
BCC ADHAK9
INC TEMPN2+1
ADHAK9: LDY #$02
LDA (TEMPN2),Y
STA TEMPNH
INY
LDA (TEMPN2),Y
STA TEMPNH+1 ;(CDR)
DEY
LDA (TEMPNH),Y
CMP ANSN
BNE SBVRW
DEC ANSN3
BNE SBVRW
SBVRWE: LDY #$00
LDA TEMPN2 ;Put TEMPN2 in the right variable
STA (TEMPN3),Y
INY
LDA TEMPN2+1
STA (TEMPN3),Y
LDA TEMPN+1
CMP #VPRMTE^
BNE SBVLPJ
LDA TEMPN
CMP #VPRMTE&$FF
BEQ SBVLL1
SBVLPJ: JMP SBVLP1
SBVLL1: CLC
LDA SOBTOP
STA FRLIST
ADC #$04
STA TEMPN
LDA SOBTOP+1
STA FRLIST+1
ADC #$00
STA TEMPN+1
LDY #$02
LDA #$00
STA (SOBTOP),Y
INY
STA (SOBTOP),Y ;RPLACD (SOBTOP,LNIL)
DEY
RINLP2: LDA FRLIST
STA (TEMPN),Y
INY
LDA FRLIST+1
STA (TEMPN),Y ;(RPLACD)
DEY
CLC
LDA TEMPN
STA FRLIST
ADC #$04
STA TEMPN
LDA TEMPN+1
STA FRLIST+1
ADC #$00
STA TEMPN+1
CMP #SINODS^ ;(Ptr. to byte after last node)
BNE RINLP2
LDA TEMPN
CMP #SINODS&$FF
BNE RINLP2
LDX #$00
STX TEMPN1+1
INX
STX TEMPN1 ;Set to Novalue for MKSFUN
LDX #UNSUM
LDA #IUNSUM
JSR MKSFUN
LDX #UNDIF
LDA #IUNDIF
JSR MKSFUN
LDA #$00 ;(LNIL)
JSR CLMK5
STA CELPTR
STA CELPTR+1 ;CELL_PTR := LNIL
STA OBLIST+1 ;OBLIST := LNIL
STA SIZE1
STA SIZE1+1 ;SIZE1 := 0
STA SIZE2
STA SIZE2+1 ;SIZE2 := 0
LDA #'U
STA TEMPN2
LDA #'E
STA TEMPN2+1
LDX #$00
LDY #TEMPN2
LDA #TEMPN3
STA ANSN
LDA #STRING
JSR CONS ;"UE" of TRUE
LDA #'T
STA TEMPN2
LDA #'R
STA TEMPN2+1
LDY #TEMPN2
LDX #TEMPN3
STX ANSN
LDA #STRING
JSR CONS ;"TR" of TRUE
LDX #TEMPN3
LDA #LTRUE
STA ANSN2
JSR INTRNX
LDX #$00
STX TEMPN2+1
LDA #'E
STA TEMPN2
LDY #TEMPN2
LDA #TEMPN3
STA ANSN
LDA #STRING
JSR CONS ;"E" of FALSE
LDA #'L
STA TEMPN2
LDA #'S
STA TEMPN2+1
LDY #TEMPN2
LDX #TEMPN3
STX ANSN
LDA #STRING
JSR CONS ;"LS" of FALSE
LDA #'F
STA TEMPN2
LDA #'A
STA TEMPN2+1
LDY #TEMPN2
LDX #TEMPN3
STX ANSN
LDA #STRING
JSR CONS ;"FA" of FALSE
LDX #TEMPN3
LDA #LFALSE
STA ANSN2
JMP INTRNX
CLMK5: STA MARK5
STA MARK5+1 ;MARK5 := LNIL
CLMK4: STA MARK4
STA MARK4+1 ;MARK4 := LNIL
CLMK3: STA MARK3
STA MARK3+1 ;MARK3 := LNIL
CLMK2: STA MARK2
STA MARK2+1 ;MARK2 := LNIL
CLMK1: STA MARK1
STA MARK1+1 ;MARK1 := LNIL
RTS
.PAGE
SOBST1: LDY #$01
TYA
DEY
STA (SOBTOP),Y
TYA
INY
STA (SOBTOP),Y ;(RPLACA)
INY
LDA SARTOP
STA (SOBTOP),Y
INY
LDA SARTOP+1
STA (SOBTOP),Y ;(RPLACD)
LDA #SATOM
LDX #SOBTOP
JSR PUTTYP
LDA GETRM2 ;Ghost-memory bank 2, Prim table
INC BANK4K
LDY #$00
LDA (TEMPN),Y
STA (SARTOP),Y
INY
LDA (TEMPN),Y
STA (SARTOP),Y
INY
LDA (TEMPN),Y
STA (SARTOP),Y
SBST1A: INY
LDA (TEMPN),Y
STA (SARTOP),Y
CMP #$20 ;See if the last byte was transferred
BNE SBST1A ;Yes.
LDA GETRM1 ;Ghost-memory bank 2 disable
LDA GETRM1
DEC BANK4K
LDA #$00
STA (SARTOP),Y
INY
CLC
TYA
ADC SARTOP
STA SARTOP
BCC ADHAK5
INC SARTOP+1
ADHAK5: CLC
TYA
ADC TEMPN
STA TEMPN
BCC ADHAK6
INC TEMPN+1
ADHAK6: CLC
LDA SOBTOP
ADC #$04
STA SOBTOP
BCC ADHAK7
INC SOBTOP+1
ADHAK7: INC NNODES
BNE ADHK7A
INC NNODES+1
ADHK7A: RTS
.PAGE
.SBTTL Miscellaneous and Evaluator Utility Routines
; Toplevel Evaluator Utility Routines:
CHKLNN: LDY #$00
LDA (TOKPTR),Y
STA TEMPN
INY
LDA (TOKPTR),Y
STA TEMPN+1 ;(CAR)
LDX #TEMPN
JMP GETTYP
EDLINE: TYA
BNE GETHIG ;Y nonzero for default line number
LDA (ILINE),Y
STA TEMPN4 ;TEMPN4 is the line pointer
INY
LDA (ILINE),Y
STA TEMPN4+1 ;(car line)
LDY #$02
LDA (TEMPN4),Y
BNE EDLERR
INY
LDA (TEMPN4),Y
BNE EDLERR
LDY #$00
LDA (TEMPN4),Y
TAX
INY
LDA (TEMPN4),Y
STA TEMPN4+1
BMI LINERR ;Line numbers limited to two bytes, positive
STX TEMPN4
BNE EDL1
TXA
BNE EDL1
LINERR: LDA #XILN ;"Illegal Line Number"
JMP ERROR
EDLERR: LDA #XLNTB ;"Line number too big"
JMP ERROR
GETHIG: LDA #$00
STA TEMPN4
STA TEMPN4+1
LDY #$02 ;get body pointer
LDA (EDBOD),Y ;skip args
STA TEMPN3 ;TEMPN3 is BODY ptr.
INY
LDA (EDBOD),Y
STA TEMPN3+1 ;(cdr body)
GTHW: LDA TEMPN3+1 ;if it ain't LNIL,
BEQ GTHE ;take the cdr again
LDY #$00
LDA (TEMPN3),Y
STA TEMPN2 ;TEMPN2 is Current Line
INY ;(car line) - put pointer
LDA (TEMPN3),Y
STA TEMPN2+1 ;to line num in TEMPN2
INY
LDA (TEMPN3),Y
TAX ;get (cdr body)
INY
LDA (TEMPN3),Y
STA TEMPN3+1
STX TEMPN3
LDY #$00
LDA (TEMPN2),Y
TAX
INY ;(car line) -- this one
LDA (TEMPN2),Y ;gets actual line number
STA TEMPN2+1
STX TEMPN2
LDA TEMPN4+1
CMP TEMPN2+1 ;old greatest line #
BCC GTH3 ;old < new - replace
BNE GTHW ;old > new, go back for next
LDA TEMPN4
CMP TEMPN2
BCS GTHW ;old > new -- just go back
GTH3: LDA TEMPN2 ;replace old highest line #
STA TEMPN4 ;with new highest line number
LDA TEMPN2+1
STA TEMPN4+1
JMP GTHW ;look for more
GTHE: CLC
LDA TEMPN4
ADC #LININC ;make default line number
STA TEMPN4
BCC EDL1
INC TEMPN4+1
BMI EDLERR
EDL1: LDY #$00 ;place line # in car of line
LDA TEMPN4
STA (ILINE),Y
INY
LDA TEMPN4+1
STA (ILINE),Y ;(RPLACA)
LDA #FLIST
LDX ANSN1
JSR PUTTYP
LDY #TEMPN4 ;NUMBER
LDX #EDBOD
LDA #TEMPN2 ;Line to be gotten
JSR FNDLIN
BCC PTLN1 ;Branch if not found
LDX ANSN1 ;POINTER
LDY #$00
LDA $00,X
STA (TEMPN2),Y
INY
LDA $01,X
STA (TEMPN2),Y ;(RPLACA)
RTS
PTLN1: LDY #$02
LDA (TEMPN2),Y
STA TEMPN3
INY
LDA (TEMPN2),Y
STA TEMPN3+1 ;(CDR)
LDY ANSN1
LDX #TEMPN3
STX ANSN
LDA #LIST
JSR CONS
LDY #$02
LDA TEMPN3
STA (TEMPN2),Y
INY
LDA TEMPN3+1
STA (TEMPN2),Y ;(RPLACD)
RTS
.PAGE
MKSFUN: LDY #$02
STA (SARTOP),Y
DEY
LDA #$08 ;(PREC = 8)
STA (SARTOP),Y
TYA ;(NARGS = 1)
DEY
STA (SARTOP),Y
TYA
LDY #$03
STA (SARTOP),Y
STX ANSN
LDX #SARTOP
LDY #TEMPN1 ;TEMPN1 Set to Novalue by the calling procedure
LDA #SATOM
JSR CONS
CLC
LDA SARTOP
ADC #$04
STA SARTOP
BCC ADHK11
INC SARTOP+1
ADHK11: RTS
.PAGE
; Frame Utility Routines:
POPFRM: JSR RSTBND
LDX #TLLEVS
JSR POP
SEC
LDA SP
SBC #$02 ;Skip SF_NUMBER_BINDINGS
STA SP
BCS PPFM2
DEC SP+1
PPFM2: LDX #TOKPTR
JSR POP
LDX #LINNUM
JSR POP
LDX #NEST
JSR POP
LDX #CURTOK
JSR POP
JSR POPB
STA UFRMAT
LDX #XFRAME
JSR POP
LDX #FRAME
JMP POP
RSTBND: LDA XFRAME
STA SP
LDA XFRAME+1
STA SP+1
LDY #$0E ;(SF_NUMBER_BINDINGS = 14.)
LDA (FRAME),Y
BEQ RSTBWE
STA ANSN ;(GETBAR)
RSTBW: LDX #TEMPN1
JSR POP
LDX #TEMPN
JSR POP
LDX #TEMPN
LDY #TEMPN1
JSR PUTVAL
DEC ANSN
BNE RSTBW
RSTBWE: RTS
.PAGE
; Stack Routines:
;PUSHP is given the location of a page-zero variable in X,
;and pushes the contents of the variable onto the LOGO stack.
PUSHP: LDY #$00
LDA $00,X
STA (SP),Y
INY
LDA $01,X
STA (SP),Y
CLC
LDA SP
ADC #$02
STA SP
BCC PSHP1
INC SP+1
PSHP1: RTS
;PUSH pushes onto the stack the sixteen-bit value in the X and Y registers.
PUSH: TYA
LDY #$01
STA (SP),Y
DEY
TXA
STA (SP),Y
CLC
LDA SP
ADC #$02
STA SP
BCC PSHP2
INC SP+1
PSHP2: RTS
;VPUSHP is given the address of a page-zero variable in X,
;and pushes the contents of that variable onto the Value stack.
VPUSHP: LDY #$00
LDA $00,X
STA (VSP),Y
INY
LDA $01,X
STA (VSP),Y
SEC
LDA VSP
SBC #$02
STA VSP
BCS VPSH1
DEC VSP+1
VPSH1: RTS
.PAGE
;POP pops a value off of the LOGO stack and into the page-zero variable
;whose address is in X.
POP: SEC
LDA SP
SBC #$02
STA SP
BCS POP1
DEC SP+1
POP1: LDY #$00
LDA (SP),Y
STA $00,X
INY
LDA (SP),Y
STA $01,X
RTS
;VPOP pops a value off of the Value stack and into the page-zero variable
;whose address is in X. Doesn't destroy X.
VPOP: CLC
LDA VSP
ADC #$02
STA VSP
BCC VPOP1
INC VSP+1
VPOP1: LDY #$00
LDA (VSP),Y
STA $00,X
INY
LDA (VSP),Y
STA $01,X
RTS
;POPB pops a one-byte value off of the LOGO stack and returns with it in A.
POPB: SEC
LDA SP
SBC #$02
STA SP
BCS POPB1
DEC SP+1
POPB1: LDY #$00
LDA (SP),Y
RTS
.PAGE
;STKTS1 tests to see if the LOGO stack test limit has been exceeded,
;and gives an error if so. It doesn't poll for interrupts.
STKTS1: LDA VSP+1
CMP SP+1
BCC STKTZ
BNE STKTR
SEC
LDA VSP
SBC SP
CMP #STKLIM
BCC STKTZ
STKTR: RTS
STKTZ: LDA #PDLBAS&$FF
STA SP
LDA #PDLBAS^
STA SP+1 ;Reset the stack for reader/tokenizer
LDX #XNSTOR ;(No Stack) "No storage left" zapcode
LDA #XZAP
JMP ERROR
;STKTST tests to see if the LOGO stack test limit has been exceeded,
;and gives an error if so. Polls for interrupts.
STKTST: JSR STKTS1
;falls through
;STPPEK is the polling routine for user interrupts.
;falls in
STPPEK: JSR TSTCHR
BCC PRTS
BIT KPCLR
CMP #STPKEY
BEQ STPPK1
CMP #PAUSKY
BEQ STPPKZ
CMP #LSTKEY
BEQ PRTS
CMP #FULCHR ;Full-screen graphics character
BEQ STPFUL
CMP #MIXCHR ;Mixed-screen graphics character
BEQ STPMIX
TAY ;Save character
SEC
LDA CHBUFR
SBC CHBUFS ;Check for buffer-full
AND #$3F
CMP #$01
BEQ BOFL ;Buffer overflow if next-free loc right before next-to-read
LDA CHBUFS
AND #$3F
TAX
TYA
STA CHBSTT,X ;Store character in buffer
INC CHBUFS ;Increment next-free-loc
PRTS: RTS
BOFL: JMP BELL ;Ding-dong if buffer overflow
STPPKZ: LDA #XBRK
JMP ERROR
STPPK1: LDX #ERROR1&$FF
LDY #ERROR1^
JSR PUSH
LDX #XSTOP ;Stop_key Zapcode
LDA #XZAP
JMP ERROR
STPFUL: LDA GRPHCS
BEQ PRTS
LDA $C052
RTS
STPMIX: LDA GRPHCS
BEQ PRTS
LDA $C053
RTS
.PAGE
; Atomic Value Routines:
GETVAL: LDA $00,Y ;Get value into X's pointer from Y's pointer
AND #$FC ;Strip off last two bits
STA TEMPNH
LDA $01,Y
STA TEMPNH+1
LDY #$00
LDA (TEMPNH),Y
STA $00,X
INY
LDA (TEMPNH),Y
STA $01,X ;(CAR)
RTS
PUTVAL: LDA $00,Y
AND #$FC
STA TEMPNH
LDA $01,Y
STA TEMPNH+1
LDY #$00
LDA $00,X
STA (TEMPNH),Y
INY
LDA $01,X
STA (TEMPNH),Y ;(RPLACA)
RTS
.PAGE
; Function Utility Routines:
GETFUN: STA ANSN ;Save ANS_FUNCT pointer
LDA $00,X
STA TEMPN ;Get OBJECT pointer
LDA $01,X
STA TEMPN+1
JSR GETTYP
LDX ANSN
LDY #$02
CMP #ATOM
BEQ GTFN1
CMP #SATOM
BEQ GTFN2
LDA #$00
STA $01,X
RTS
GTFN1: LDA (TEMPN),Y
PHA
INY
LDA (TEMPN),Y
STA TEMPN+1
PLA
STA TEMPN
LDY #$00
LDA (TEMPN),Y
PHA
INY
LDA (TEMPN),Y
STA $01,X
PLA
STA $00,X ;(CAR)
LDA #UFUN
RTS
GTFN2: LDA (TEMPN),Y
STA $00,X
INY
LDA (TEMPN),Y
STA $01,X ;(CDR)
LDA #SFUN
RTS
.PAGE
PUTFUN: STY ANSN
STX ANSN1
JSR GETTYP
CMP #ATOM
BEQ PTFN2
PTFN1: LDY ANSN1
JSR PTRYOK
LDA #XUBL
JMP ERROR
PTFN2: LDX ANSN1
LDA $00,X
STA TEMPNH
LDA $01,X
STA TEMPNH+1
LDY #$02
LDA (TEMPNH),Y
TAX
INY
LDA (TEMPNH),Y
STA TEMPNH+1
STX TEMPNH ;(CDR)
LDX ANSN
LDY #$00
LDA $00,X
STA (TEMPNH),Y
INY
LDA $01,X
STA (TEMPNH),Y ;(RPLACA)
RTS
.PAGE
;GETPRC returns the precedence (in A) of the function in Y,
;given the funtype in X.
GETPRC: LDA #$05 ;Assume Ufun, precedence 5
CPY #UFUN
BEQ GPRCU
GPRCS: LDA $00,X
STA TEMPNH
LDA $01,X
STA TEMPNH+1
LDY #$01
LDA (TEMPNH),Y
GPRCU: RTS
GETNGS: CMP #SFUN
BEQ GTNG2
GTNG1: LDA $00,X
STA TEMPNH
LDA $01,X
STA TEMPNH+1
LDY #$04
LDA (TEMPNH),Y ;(GETBAR)
RTS
GTNG2: LDA $00,X
STA TEMPNH
LDA $01,X
STA TEMPNH+1
LDY #$00
LDA (TEMPNH),Y
RTS
.PAGE
INFIXP: CMP #SFUN
BNE IFP1
LDA $01,X
BNE IFP2
IFP1: CLC ;Not infix
RTS
IFP2: LDA $00,X
STA TEMPNH
LDA $01,X
STA TEMPNH+1
LDY #$02
LDA (TEMPNH),Y
CMP #INSUM
BEQ IFP3
CMP #INDIF
BEQ IFP3
CMP #INPROD
BEQ IFP3
CMP #INQUOT
BEQ IFP3
CMP #INGRTR
BEQ IFP3
CMP #INLESS
BEQ IFP3
CMP #INEQUL
BNE IFP1
IFP3: SEC ;Infix.
RTS ;Return with proper index in A
.PAGE
PTFTXT: STY ANSNX ;FUNTEXT
STA ANSN3 ;NARGS
STX TEMPN7 ;ATOMM
JSR GETTYP
CMP #ATOM
BEQ PTFTX2
LDY TEMPN7
LDA #XUBL
JMP ERROR
PTFTX2: LDX TEMPN7
LDA $00,X
STA TEMPNH ;TEMPNH is ATOMM
LDA $01,X
STA TEMPNH+1
LDY #$02
LDA (TEMPNH),Y
STA TEMPN5 ;TEMPN5 is CELL
INY
LDA (TEMPNH),Y
STA TEMPN5+1 ;(CDR)
LDY #$00
LDA (TEMPN5),Y
STA TEMPN6 ;TEMPN6 is FUNCT
INY
LDA (TEMPN5),Y
STA TEMPN6+1 ;(CAR)
BNE PTFTX3
LDX ANSNX ;FUNTEXT ptr.
LDA $00,X
STA MARK1
LDA $01,X
STA MARK1+1
LDA #$04
STA TEMPN8
LDA #$00
STA TEMPN8+1
LDY #TEMPN8
LDX #TEMPN6
JSR GETWDS
LDY #$01
LDA TEMPN6+1 ;FUNCT
BEQ PTFER
STA (TEMPN5),Y ;CELL
DEY
LDA TEMPN6
STA (TEMPN5),Y ;(RPLACA)
LDX #TEMPN6
LDA #UFUN
JSR PUTTYP
LDY #$06
LDX TEMPN7 ;ATOMM
LDA $00,X
STA (TEMPN6),Y
INY
LDA $01,X
STA (TEMPN6),Y ;(PUTBAR)
LDA #$00
STA MARK1
STA MARK1+1
PTFTX3: LDY #$00
TYA
STA (TEMPN6),Y
INY
STA (TEMPN6),Y ;(PUTBAR)
INY
LDX ANSNX
LDA $00,X ;FUNTEXT
STA (TEMPN6),Y
INY
LDA $01,X
STA (TEMPN6),Y ;(PUTBAR)
INY
LDX ANSN3 ;NARGS
LDA $00,X
STA (TEMPN6),Y
INY
LDA $01,X
STA (TEMPN6),Y ;(PUTBAR)
PTFTXE: RTS
PTFER: JMP CONSR ;(No Nodes, most likely) "No storage left" zapcode
.PAGE
UNFUNC: LDA $00,X
STA TEMPNH
LDA $01,X
STA TEMPNH+1
LDY #$02
LDA (TEMPNH),Y
TAX
INY
LDA (TEMPNH),Y
STA TEMPNH+1
STX TEMPNH ;(CDR)
LDY #$00
LDA #$01
STA (TEMPNH),Y
TYA
INY
STA (TEMPNH),Y ;(RPLACA)
RTS
.PAGE
; Nodespace Routines:
;CONS creates a new node from the freelist. X points to the Cdr,
;Y to the Car, ANSN to the node's pointer, and A holds the typecode.
CONS: PHA
CMP #LIST
BEQ FCONS
CMP #STRING
BEQ SCONS
CMP #FIX
BEQ NCONS
CMP #FLO
BEQ NCONS
CMP #ATOM
BEQ SCONS
CMP #FLIST
BEQ SCONS
CMP #SATOM
BEQ S1CONS
JSR SYSBUG
;"F" CONS - Protect both CAR and CDR. Used for Lists.
FCONS: JSR XCONS
LDX TEMPNH
JSR VPUSHP ;VPUSHP Xcar
LDX TEMPNH+1
JSR VPUSHP ;VPUSHP Xcdr
JSR GARCOL
CLC ;Reset the VPDL
LDA VSP
ADC #$04
JMP SCONS2
;"N" CONS - Doesn't protect either CAR or CDR. Used for numbers.
NCONS: JSR XCONS
JSR GARCOL
JMP CONSG1
;"S" CONS - Protects only CDR. Used for strings.
SCONS: JSR XCONS
LDX TEMPNH+1
JSR VPUSHP ;VPUSHP Xcdr
JSR GARCOL
JMP SCONS1 ;Reset the VPDL
;"S1" CONS - Protects only CAR. Used for Satoms.
S1CONS: JSR XCONS
LDX TEMPNH
JSR VPUSHP
JSR GARCOL
SCONS1: CLC
LDA VSP
ADC #$02
SCONS2: STA VSP
BCC CONSG1
INC VSP+1
BNE CONSG1 ;(Always)
XCONS: STY TEMPNH ;TEMPNH.L is XCAR
STX TEMPNH+1 ;TEMPNH.H is XCDR
LDA FRLIST+1
BEQ XCONSG
LDA PRDFLG
BNE XCONS2 ;Don't check limit for READ_LINE callers
LDA NNODES+1
CMP #NODLIM^
BCC XCONS2
BNE XCONSG
LDA NNODES
CMP #NODLIM&$FF
BCC XCONS2
XCONSG: RTS
XCONS2: PLA
PLA
JMP CONS2
CONSG1: LDA PRDFLG
BEQ CONST2
LDA FRLIST+1
BNE CONS2
BEQ CONSR
CONST2: LDA NNODES+1
CMP #NODLIM^
BCC CONS2
BNE CONSR
LDA NNODES
CMP #NODLIM&$FF
BCC CONS2
CONSR: LDX #XNSTRN ;Error "No storage left" (No nodes)
LDA #XZAP
JMP ERROR
CONS2: INC NNODES
BNE CONS2A
INC NNODES+1 ;Increment node counter
CONS2A: LDY #$00
LDX TEMPNH
LDA $00,X
STA (FRLIST),Y
INY
LDA $01,X
STA (FRLIST),Y ;(RPLACA)
INY
LDX TEMPNH+1
LDA (FRLIST),Y
PHA
LDA $00,X
STA (FRLIST),Y
INY
LDA (FRLIST),Y
PHA
LDA $01,X
STA (FRLIST),Y ;(RPLACD)
LDX ANSN
LDA FRLIST
STA $00,X
LDA FRLIST+1
STA $01,X
PLA
STA FRLIST+1
PLA
STA FRLIST
PLA ;GET TYPE
;falls through
;falls in
PUTTYP: CMP #LATOM+1
BCS PUTTP2
CMP #QATOM
BCC PUTTP2
SBC #$07
CLC
ADC $00,X
STA $00,X
PUTTPE: RTS
PUTTP2: LDY $01,X
BEQ PUTTPE
STY TEMPNH+1
LDY $00,X
STY TEMPNH
TAX
JSR TYPACS
TXA
STA (TEMPNH),Y
RTS
GETTYP: LDA $01,X
BEQ GETTPE
LDA $00,X
STA TEMPNH
LDA $01,X
STA TEMPNH+1
JSR TYPACS
CMP #ATOM
BEQ GETTP4
CMP #SATOM
BNE GETTPE
GETTP4: TAY
LDA $00,X
AND #$03
BEQ GETTPF
CLC
ADC #$07
GETTPE: RTS
GETTPF: TYA
RTS
TYPACS: LSR TEMPNH+1
ROR TEMPNH
LSR TEMPNH+1
ROR TEMPNH
CLC
LDA TEMPNH
ADC #TYPBAS&$FF
STA TEMPNH
LDA TEMPNH+1
ADC #TYPBAS^
STA TEMPNH+1
LDY #$00
LDA (TEMPNH),Y
RTS
.PAGE
PTSPNM: LDA $00,X
AND #$FC
STA TEMPNH
LDA $01,X
STA TEMPNH+1
LDY #$02
LDA (TEMPNH),Y
TAX
INY
LDA (TEMPNH),Y
STA TEMPNH+1
STX TEMPNH ;(CDR)
DEY
LDA (TEMPNH),Y
ORA #$01
STA (TEMPNH),Y
RTS2: RTS
.PAGE
;Tries to find a block of (Y) contiguous free words in nodespace.
;If successful, return the start addr in (X). If not, return LNIL.
GETWDS: STX ANSN ;ANSN is ans
STY ANSN1 ;ANSN1 is size
LDA #$00
STA $00,X ;zero ans
STA $01,X
LDA $00,Y
BNE GW1A
LDA $01,Y
BEQ RTS2 ;If size=0, just return with ANS = 0
GW1A: JSR GW1 ;try once
LDX ANSN
LDA $01,X
BNE RTS2 ;if found something, quit.
JSR GARCOL ;otherwise, try again after a GC
;falls through
;falls in
GW1: LDA #$00
STA TEMPN+1 ;Zero lastptr (TEMPN)
STA TEMPN4+1 ;and lastptr1 (TEMPN4)
LDA FRLIST ;init ptr (TEMPN1) and
STA TEMPN1 ;ptr1 (TEMPN3) to freelist
STA TEMPN3
LDA FRLIST+1
STA TEMPN1+1
STA TEMPN3+1
GW1W: LDX ANSN
LDA $01,X ;if ans neq LNIL, done
BEQ GW1WA ;cuz found something
GWRTS: LDX ANSN1
CLC
LDA NNODES
ADC $00,X
STA NNODES ;Adjust allocation pointer
LDA NNODES+1
ADC $01,X
STA NNODES+1
RTS
GW1WA: LDA TEMPN1+1 ;if ptr1 = LNIL, done cuz been thru whole
BEQ RTS2 ;freelist, found nothing
GW1W1: LDA #$00
STA TEMPN2 ;sofar (TEMPN2) := 0
STA TEMPN2+1
STA ANSN2 ;contig (ANSN2) := 0 (T)
GW1X: LDX ANSN1
LDA TEMPN2+1
CMP $01,X
BCC GW1X2 ;if sofar >= size, go if2
BNE GWIF2
LDA TEMPN2
CMP $00,X
BCS GWIF2
LDA ANSN2 ;if contig = false, go else
BNE GWELSE
LDA TEMPN3
BNE GW1X2 ;if ptr1 = LNIL, goto else
LDA TEMPN3+1
BEQ GWELSE
GW1X2: CLC
LDA TEMPN2
ADC #$02 ;sofar := sofar + 2
STA TEMPN2
BCC GW1X3
INC TEMPN2+1
GW1X3: LDY #$02
LDA (TEMPN3),Y
STA TEMPNH ;temp (TEMPNH) := (cdr ptr1)
INY
LDA (TEMPN3),Y
STA TEMPNH+1 ;(CDR)
CLC
LDA TEMPNH ;add 4 to temp and see if
ADC #$04 ;result is = ptr1
TAX
LDA TEMPNH+1
ADC #$00
CMP TEMPN3+1
BNE NCNTIG
CPX TEMPN3
BEQ CONTIG ;if so, contig := 1 (false)
NCNTIG: INC ANSN2
CONTIG: LDA TEMPN3
STA TEMPN4 ;lastptr1 := ptr1
LDA TEMPN3+1
STA TEMPN4+1
LDA TEMPNH
STA TEMPN3 ;ptr1 := temp
LDA TEMPNH+1
STA TEMPN3+1
JMP GW1X ;round the while loop
GWIF2: LDA TEMPN+1 ;if lastptr = LNIL, freelist := ptr1
BNE GWIF3
LDA TEMPN3
STA FRLIST ;freelist := ptr1
LDA TEMPN3+1
STA FRLIST+1
JMP GWIF4
GWIF3: LDY #$02 ;else (rplacd lasptr ptr1)
LDA TEMPN3
STA (TEMPN),Y
INY
LDA TEMPN3+1
STA (TEMPN),Y ;(rplacd)
GWIF4: LDX ANSN
LDA TEMPN4
STA $00,X ;ans := lastptr1
LDA TEMPN4+1
STA $01,X
JMP GW1W ;back to top
GWELSE: LDA TEMPN3
STA TEMPN1 ;ptr := ptr1
LDA TEMPN3+1
STA TEMPN1+1
LDA TEMPN4
STA TEMPN ;lastptr := lastptr1
LDA TEMPN4+1
STA TEMPN+1
JMP GW1W ;back to top
.PAGE
; Ufun Line Utility Routines:
FNDLIN: STA ANSN ;LINE returned
STY ANSN1 ;NUMBER looked for
LDA $00,X
STA TEMPN ;TEMPN is LAST_LINE
LDA $01,X
STA TEMPN+1
LDX ANSN
LDY #$02
LDA (TEMPN),Y
STA $00,X
INY
LDA (TEMPN),Y
STA $01,X ;(CDR)
BEQ FDLNWE
FDLNW: LDX ANSN
LDA $00,X
STA TEMPNH
LDA $01,X
STA TEMPNH+1
LDY #$00
LDA (TEMPNH),Y
STA TEMPN1 ;TEMPN1 is incremental ptr.
INY
LDA (TEMPNH),Y
STA TEMPN1+1 ;(CAR)
DEY
LDA (TEMPN1),Y
TAX
INY
LDA (TEMPN1),Y
STA TEMPN1+1
STX TEMPN1 ;(GETBAR)
LDX ANSN1
LDA TEMPN1+1
CMP $01,X
BCC FDLNW3
BNE FDLNWE
LDA TEMPN1
CMP $00,X
BEQ FDLNWF
BCS FDLNWE
FDLNW3: LDX ANSN
LDA $00,X
STA TEMPN
LDA $01,X
STA TEMPN+1
LDY #$02
LDA (TEMPN),Y
STA $00,X
INY
LDA (TEMPN),Y
STA $01,X ;(CDR)
BNE FDLNW
FDLNWE: LDX ANSN
LDA TEMPN
STA $00,X
LDA TEMPN+1
STA $01,X
CLC ;Clear Carry means Not Found
RTS
FDLNWF: SEC ;Set Carry means Found
RTS
.PAGE
LINPEK: LDA $00,Y
STA TEMPNH ;BODY
LDA $01,Y
STA TEMPNH+1
LDY #$02
LDA UFRMAT
BEQ LPK1
INY
INY
LPK1: LDA (TEMPNH),Y
STA $00,X
INY
LDA (TEMPNH),Y
STA $01,X ;(CDR or GETBAR)
RTS
.PAGE
GTFULN: LDA $00,Y
STA TEMPNH
LDA $01,Y
STA TEMPNH+1 ;BODY
LDY #$00
LDA (TEMPNH),Y
STA $00,X
INY
LDA (TEMPNH),Y
STA $01,X ;(CAR or GETBAR)
LDA UFRMAT
BEQ GTFR
GTF2: INY
LDA (TEMPNH),Y
STA ULNEND
INY
LDA (TEMPNH),Y
STA ULNEND+1 ;(GETBAR)
LDA $00,X
CMP ULNEND
BNE GTFR
LDA $01,X
CMP ULNEND+1
BEQ FLLIN
GTFR: RTS
GTTULN: JSR GTFULN
LDA $01,X
BEQ GTFR
GTT1: LDA $00,X
STA TEMPNH
LDA $01,X
STA TEMPNH+1
LDY #$00
LDA (TEMPNH),Y
CMP COMMNT
BNE GTFR
INY
LDA (TEMPNH),Y
CMP COMMNT+1
BNE GTFR
FLLIN: LDA #$00
STA $00,X
STA $01,X
RTS
.PAGE
ULNADV: LDA $00,X
STA TEMPNH
LDA $01,X
STA TEMPNH+1 ;BODY
LDY #$02
LDA UFRMAT
BNE ULDV2
ULDV1: LDA (TEMPNH),Y
PHA
INY
LDA (TEMPNH),Y
STA $01,X
PLA
STA $00,X ;(CDR)
RTS
ULDV2: INY
INY
LDA (TEMPNH),Y
PHA
INY
LDA (TEMPNH),Y ;(GETBAR)
BNE ULDV3
PLA
BNE ULDV3A
STA $00,X
STA $01,X
RTS
ULDV3: PLA
ULDV3A: CLC
LDA $00,X
ADC #$02
STA $00,X
BCC ADHK13
INC $01,X
ADHK13: RTS
.PAGE
; Token-list Routines:
TTKADV: JSR TFKADV
LDA TEMPNH
CMP COMMNT
BNE TTKE
LDA TEMPNH+1
CMP COMMNT+1
BNE TTKE
LDA #$00
STA $00,X
STA $01,X
TTKE: RTS
TFKADV: LDA UFRMAT
CMP #FPACK
BEQ TFK2
TFK1: LDA $00,X
STA TEMPNH
LDA $01,X
STA TEMPNH+1
LDY #$02
LDA (TEMPNH),Y
STA $00,X
INY
LDA (TEMPNH),Y
STA $01,X ;(CDR)
JMP TFK3
TFK2: CLC
LDA $00,X
ADC #$02
STA $00,X
BCC TFK2A
INC $01,X
TFK2A: CMP ULNEND
BNE TFK3
LDA $01,X
CMP ULNEND+1
BNE TFK3
LDA #$00
STA $00,X
STA $01,X
RTS
TFK3: LDA $00,X
STA TEMPNH
LDA $01,X
STA TEMPNH+1
LDY #$00
LDA (TEMPNH),Y
PHA
INY
LDA (TEMPNH),Y
STA TEMPNH+1
PLA
STA TEMPNH ;(GETTOK)
RTS
.PAGE
SKPPTH: LDA TOKPTR+1
BEQ RTSA2X
LDY #$00
LDA (TOKPTR),Y
STA TEMPN
INY
LDA (TOKPTR),Y
STA TEMPN+1 ;(GETTOK)
LDX #TOKPTR
JSR TTKADV
LDA TEMPN
CMP LPAR
BNE RTSA2X
LDA TEMPN+1
CMP LPAR+1
BNE RTSA2X
LDA #$01
STA ANSN ;ANSN is PAREN_COUNTER
SKPPW: LDA TOKPTR+1
BEQ RTSA2X
LDY #$00
LDA (TOKPTR),Y
STA TEMPN
INY
LDA (TOKPTR),Y
STA TEMPN+1 ;(GETTOK)
LDX #TOKPTR
JSR TTKADV
LDX TEMPN
LDY TEMPN+1
CPX LPAR
BNE SKPPW2
CPY LPAR+1
BNE SKPPW2
INC ANSN
JMP SKPPW
SKPPW2: CPX RPAR
BNE SKPPW
CPY RPAR+1
BNE SKPPW
DEC ANSN
BNE SKPPW
RTSA2X: RTS
.PAGE
EXIFSC: STX ANSN1 ;ANSN1 is ANS
LDA IFLEVL
STA TEMPN1 ;TEMPN2 is IF_COUNTER
LDA IFLEVL+1
STA TEMPN1+1
EXFW: LDA TEMPN1+1
CMP IFLEVL+1
BCC EXFWE
BNE EXFWA1
LDA TEMPN1
CMP IFLEVL
BCS EXFWA1
EXFWE: SEC
LDA IFLEVL
SBC #$01
STA IFLEVL
BCS EXFWR
DEC IFLEVL+1
EXFWR: RTS
EXFWA1: LDA TOKPTR+1
BEQ EXFWE
LDY #$00
LDX ANSN1
LDA (TOKPTR),Y
STA $00,X
INY
LDA (TOKPTR),Y
STA $01,X ;(GETTOK)
TAY
LDA $00,X
TAX
CPX LIF
BNE EXFW2
CPY LIF+1
BNE EXFW2
INC TEMPN1
BNE EXIFWB
INC TEMPN1+1
EXIFWB: LDX #TOKPTR
JSR TTKADV
JMP EXFW
EXFW2: CPX LELSE
BNE EXFW3
CPY LELSE+1
BNE EXFW3
SEC
LDA TEMPN1
SBC #$01
STA TEMPN1
BCS EXFWC
DEC TEMPN1+1
EXFWC: LDA TEMPN1+1
CMP IFLEVL+1
BCC EXFWE
BNE EXFWD
LDA TEMPN1
CMP IFLEVL
BCC EXFWE
EXFWD: LDX #TOKPTR
JSR TTKADV
JMP EXFWA1
EXFW3: CPX RPAR
BNE EXFW4
CPY RPAR+1
BEQ EXFWE
EXFW4: JSR SKPPTH
JMP EXFW
.PAGE
; Edit mode Utility Routines:
EDTSTP: LDA EDSW
CMP #$01
BEQ EDTSR1 ;Error if already in CHANGE (not EDIT) mode
LDA LEVNUM
BNE EDTSR2
LDA LEVNUM+1
BNE EDTSR2
LDA TOKPTR+1
BEQ EDTSR3
LDY #$00
LDA (TOKPTR),Y
STA ARG1
INY
LDA (TOKPTR),Y
STA ARG1+1 ;(GETTOK)
LDX #TOKPTR
JSR TTKADV
LDX #ARG1
JSR GETTYP
CMP #SATOM
BEQ EDTSR4
CMP #ATOM
BNE EDTSR5
LDA ARG1
STA EDTATM
STA PODEFL
LDA ARG1+1
STA EDTATM+1
STA PODEFL+1
RTS
EDTSR1: LDA #XEDT
JMP ERROR
EDTSR2: JMP STTLR2 ;(ERROR XETL)
EDTSR3: JMP SCMMT1 ;(ERROR XEOL)
EDTSR4: JMP SPO5S ;(ERROR XUBL,ARG1)
EDTSR5: JMP SMAKE2 ;(ERROR XWTA,ARG1,CURTOK)
EXTEDT: LDA #$00
STA EDSW
STA EDBOD
STA EDBOD+1
STA EDTATM
STA EDTATM+1
RTS9: RTS
.PAGE
; Stuffed stuff Routines:
STUFF: STA ANSN3 ;try to associate the name (ATOM)
STX ANSNX ;definition with the function (BODY).
LDA $00,X
STA TEMPNH
LDA $01,X
STA TEMPNH+1 ;TEMPNH is BODY
LDY #$00
LDA (TEMPNH),Y
STA TEMPN7
INY
LDA (TEMPNH),Y
STA TEMPN7+1 ;(CAR) to LINE
LDX #TEMPX2 ;TEMPX2 becomes NARGS
LDY #TEMPN7
JSR GETLEN
LDA #$00
STA TEMPN6 ;TEMPN6 is SIZE
STA TEMPN6+1
LDX ANSNX
LDA $00,X
STA TEMPNH ;TEMPNH is BODY
LDA $01,X
STA TEMPNH+1
GTSZW: LDA TEMPNH+1
BEQ GTSZND
LDY #$00
LDA (TEMPNH),Y
STA TEMPN
INY
LDA (TEMPNH),Y
STA TEMPN+1 ;(CAR) to LINE (GETSIZ local)
INY
LDA (TEMPNH),Y
TAX
INY
LDA (TEMPNH),Y
STA TEMPNH+1
STX TEMPNH ;(CDR)
GTSZX: LDA TEMPN+1
BEQ GTSZW
GTSZX1: INC TEMPN6
BNE GTSZX2
INC TEMPN6+1
GTSZX2: LDY #$02
LDA (TEMPN),Y
TAX
INY
LDA (TEMPN),Y
STA TEMPN+1
STX TEMPN ;(CDR)
BNE GTSZX1
BEQ GTSZW
GTSZND: LDX #TEMPN5 ;TEMPN5 becomes PTR
LDY #TEMPN6 ;SIZE
JSR GETWDS
LDA TEMPN5+1
BNE STFF1
STFFA: LDA #TEMPX2
LDY ANSNX
LDX ANSN3
JMP PTFTXT ;PUT_FTEXT (FUNATOM, BODY, NARGS) (X,Y,A)
STFF1: LDA TEMPN5
STA AREA1
LDA TEMPN5+1
STA AREA1+1
LDA TEMPN6
STA SIZE1
LDA TEMPN6+1
STA SIZE1+1
LDX #TEMPN6
LDY ANSNX ;BODY
JSR GETLEN
CLC
LDA TEMPN6
ADC #$02
STA TEMPN6
BCC ADHK55
INC TEMPN6+1
ADHK55: LDX #TEMPX1 ;TEMPX1 becomes INDEX
LDY #TEMPN6
JSR GETWDS
LDA TEMPX1+1
BNE STFF2
STA SIZE1
STA SIZE1+1
JMP STFFA
STFF2: LDA TEMPX1
STA AREA2
STA TEMPN1 ;TEMPN1 is INDEX1
LDA TEMPX1+1
STA AREA2+1
STA TEMPN1+1
CLC
LDA TEMPN6
ADC #$02
STA SIZE2
LDA TEMPN6+1
ADC #$00
STA SIZE2+1
LDX ANSNX
LDA $00,X
STA TEMPNH ;TEMPNH is BODY
LDA $01,X
STA TEMPNH+1
STFFW: LDA TEMPNH+1
BEQ STFFWE
STFFW1: LDY #$00
LDA TEMPN5 ;PTR
STA (TEMPN1),Y
INY
LDA TEMPN5+1
STA (TEMPN1),Y ;(PUTBAR)
CLC
LDA TEMPN1
ADC #$02
STA TEMPN1
BCC STFFX
INC TEMPN1+1
STFFX: LDA TEMPN7+1 ;LINE
BEQ STFFXE
LDY #$00
LDA (TEMPN7),Y
STA TEMPN3 ;TEMPN3 is TOKEN
INY
LDA (TEMPN7),Y
STA TEMPN3+1 ;(CAR)
INY
LDA (TEMPN7),Y
TAX
INY
LDA (TEMPN7),Y
STA TEMPN7+1
STX TEMPN7 ;(CDR)
LDY #$00
LDA TEMPN3
STA (TEMPN5),Y
INY
LDA TEMPN3+1
STA (TEMPN5),Y ;(PUTBAR)
CLC
LDA TEMPN5
ADC #$02
STA TEMPN5
BCC STFFX
INC TEMPN5+1
BNE STFFX ;(Always)
STFFXE: LDY #$03
LDA (TEMPNH),Y
TAX
DEY
LDA (TEMPNH),Y
STA TEMPNH ;(CDR)
STX TEMPNH+1
DEY
LDA (TEMPNH),Y
STA TEMPN7+1
DEY
LDA (TEMPNH),Y
STA TEMPN7 ;(CAR)
JMP STFFW
STFFWE: LDY #$00
LDA TEMPN5
STA (TEMPN1),Y ;TEMPN1 is INDEX1
INY
LDA TEMPN5+1
STA (TEMPN1),Y ;(PUTBAR)
INY
LDA #$00
STA (TEMPN1),Y
INY
STA (TEMPN1),Y ;(PUTBAR)
LDX #TEMPX1 ;INDEX
LDA #FPACK
JSR PUTTYP
LDA #TEMPX2
LDY #TEMPX1
LDX ANSN3
JSR PTFTXT ;(X,Y,A)
LDA #$00
STA SIZE1
STA SIZE1+1
STA SIZE2
STA SIZE2+1
RTS3: RTS
.PAGE
UNSTUF: STA ANSN2 ;ANSN2 is TEXTP
STY ANSN1 ;ANSN1 is BODY ptr. (X is FUN ptr.)
LDA $00,X
STA TEMPNH
LDA $01,X
STA TEMPNH+1
LDY #$02
LDA (TEMPNH),Y
STA TEMPN1 ;TEMPN1 is INDEX
INY
LDA (TEMPNH),Y
STA TEMPN1+1 ;(CDR)
LDX #TEMPN1
JSR GETTYP
CMP #FPACK
BEQ USTF2
USTF1: LDX ANSN1
LDA TEMPN1
STA $00,X
LDA TEMPN1+1
STA $01,X
USTFE1: RTS
USTF2: LDA #$00
STA MARK1
STA MARK1+1
LDA SP
STA TEMPN4 ;TEMPN4 is STACK
LDA SP+1
STA TEMPN4+1
USTFW2: LDY #$00
LDA (TEMPN1),Y
STA TEMPN2 ;TEMPN2 is PTR
INY
LDA (TEMPN1),Y
STA TEMPN2+1 ;(GETBAR)
INY
LDA (TEMPN1),Y
STA TEMPN3 ;TEMPN3 is ENDPTR
INY
LDA (TEMPN1),Y
STA TEMPN3+1 ;(GETBAR)
USTFW: LDA TEMPN3+1
BEQ USTFWE
JSR STKTST
LDX #TEMPN2
JSR PUSHP
CLC
LDA TEMPN1
ADC #$02
STA TEMPN1
BCC USTFW2
INC TEMPN1+1
JMP USTFW2
USTFWE: LDA TEMPN2
STA TEMPN3
LDA TEMPN2+1
STA TEMPN3+1
USTFX: LDA TEMPN4
CMP SP
BNE USTFX1
LDA TEMPN4+1
CMP SP+1
BEQ USTFXE
USTFX1: LDX #TEMPN2
JSR POP
LDA #$00
STA MARK2
STA MARK2+1
USTFY: LDA TEMPN3
CMP TEMPN2
BNE USTFY1
LDA TEMPN3+1
CMP TEMPN2+1
BEQ USTFYE
USTFY1: SEC
LDA TEMPN3
SBC #$02
STA TEMPN3
BCS USTFY2
DEC TEMPN3+1
USTFY2: LDY #$00
LDA (TEMPN3),Y
STA TEMPN
INY
LDA (TEMPN3),Y
STA TEMPN+1 ;(GETBAR)
LDA #LIST
LDX #MARK2
STX ANSN
LDY #TEMPN
JSR CONS
JMP USTFY
USTFYE: LDX #MARK2
LDA TEMPN4
CMP SP
BNE USTFX2
LDA TEMPN4+1
CMP SP+1
BNE USTFX2
LDA #LIST
JSR PUTTYP
JMP USTFX3
USTFX2: LDA #FLIST
JSR PUTTYP
LDA ANSN2
BEQ USTFX3
LDY #$02
LDA (MARK2),Y
TAX
INY
LDA (MARK2),Y
STA MARK2+1
STX MARK2 ;(CDR)
USTFX3: LDX #MARK1
STX ANSN
LDY #MARK2
LDA #LIST
JSR CONS
JMP USTFWE
USTFXE: LDX ANSN1 ;BODY
LDA MARK1
STA $00,X
LDA MARK1+1
STA $01,X
LDA #$00
JMP CLMK2 ;Clear MARK1, MARK2
USTFE: RTS
.PAGE
; Oblist Interning Routine:
INTERN: STX ANSN1 ;ANSN1 IS STRING PTR.
STY ANSN2 ;ANSN2 IS ANS PTR.
JSR VPUSHP
LDA OBLIST ;OBFIND starts
STA TEMPN4
LDA OBLIST+1
STA TEMPN4+1 ;TEMPN4 IS OB_PTR
BEQ OBFNFE
OBFW: LDY #$00
LDX ANSN2
LDA (TEMPN4),Y
STA $00,X
INY
LDA (TEMPN4),Y
STA $01,X ;(CAR) TO ANS
LDY #TEMPN5 ;TEMPN5 IS PNAME
JSR GETPNM
LDX ANSN1 ;MATCH2 starts (STRING1 IS TEMPN5)
LDA $00,X
STA TEMPNH
LDA $01,X
STA TEMPNH+1 ;TEMPNH IS STRING2
MTC2W: LDA TEMPNH+1
BNE MTC2W1
LDA TEMPN5+1 ;IF STRING2 IS 0 AND STRING1 ISN'T, NOT FOUND
BNE OBFNF
LDX #TEMPN5
JMP VPOP ;Pop the Vpushed string
MTC2W1: LDY #$00
LDA (TEMPNH),Y
CMP (TEMPN5),Y
BNE OBFNF
INY
LDA (TEMPNH),Y
CMP (TEMPN5),Y
BNE OBFNF
INY
LDA (TEMPNH),Y
TAX
INY
LDA (TEMPNH),Y
STA TEMPNH+1
STX TEMPNH ;(CDR)
DEY
LDA (TEMPN5),Y
TAX
INY
LDA (TEMPN5),Y
STA TEMPN5+1
STX TEMPN5 ;(CDR)
JMP MTC2W ;TRY NEXT TWO CHARACTERS
OBFNF: LDY #$02 ;TRY NEXT OBLIST OBJECT
LDA (TEMPN4),Y ;(OB_PTR)
TAX
INY
LDA (TEMPN4),Y
STA TEMPN4+1
STX TEMPN4 ;(CDR)
BNE OBFW
OBFNFE: LDX ANSN1 ;IT'S NOT ON THE OBLIST
JSR VPOP ;GET STRING BACK
LDA SOBLST ;SOBFIND starts
LDX ANSN2 ;ANS BECOMES SOBLIST POINTER
STA $00,X
LDA SOBLST+1
STA $01,X
SBFW: LDX ANSN2 ;OBJECT POINTER
SBFWX: LDA $00,X
CMP SOBTOP
BNE SBFW1
LDA $01,X
CMP SOBTOP+1
BNE SBFW1
SBFWEN: LDX ANSN1 ;STRING
INTRNX: LDY #$00 ;Not found anywhere
STY TEMPN1+1
INY
STY TEMPN1
LDA ANSN2
STA ANSN
LDY #TEMPN1 ;(NOVALUE)
LDA #LIST
JSR CONS
LDA ANSN2
STA ANSN ;(ANS)
TAX
LDY #TEMPN1 ;(NOVALUE)
LDA #ATOM
JSR CONS
LDA #LIST
LDX #OBLIST
STX ANSN
LDY ANSN2 ;ANS
JMP CONS
SBFW1: LDA $00,X
STA TEMPNH
LDA $01,X
STA TEMPNH+1
LDY #$02
LDA (TEMPNH),Y
INY
CLC
ADC #$03
STA TEMPN2 ;TEMPN2 IS SOBNAME
LDA (TEMPNH),Y
ADC #$00
STA TEMPN2+1 ;(CDR)
LDX ANSN1 ;ANSN1 POINTS TO STRING
LDA $00,X
STA TEMPNH
LDA $01,X
STA TEMPNH+1 ;TEMPNH BECOMES PNAME
MTC1W: LDA TEMPNH
BNE MTC1W1
LDA TEMPNH+1
BEQ SBFNF
MTC1W1: LDY #$00
LDA (TEMPNH),Y
STA TEMPN ;TEMPN IS TEMP
INY
LDA (TEMPNH),Y
STA TEMPN+1 ;(CAR)
DEY
LDA (TEMPN2),Y
CMP TEMPN
BNE SBFNF
INC TEMPN2
BNE ADHK21
INC TEMPN2+1
ADHK21: LDA (TEMPN2),Y
CMP TEMPN+1
BNE SBFNF
LDY #$02
LDA (TEMPNH),Y ;TEMPNH IS PNAME
TAX
INY
LDA (TEMPNH),Y
STA TEMPNH+1
STX TEMPNH ;(CDR)
LDY #$00
LDA (TEMPN2),Y
BEQ MTC1WF
INC TEMPN2
BNE MTC1WE
INC TEMPN2+1
MTC1WE: LDA TEMPNH+1
BNE MTC1W1
LDA (TEMPN2),Y
BNE SBFNF
MTC1WF: RTS
SBFNF: CLC ;NOT THIS SOBLIST OBJECT
LDX ANSN2 ;ANS
LDA $00,X
ADC #$04
STA $00,X
BCC SBFWJ
INC $01,X
SBFWJ: JMP SBFWX
.PAGE
; Linked-list Utility Routines:
GETLEN: LDA $00,Y
STA TEMPNH ;LIST
LDA $01,Y
STA TEMPNH+1
LDA #$00
STA $00,X ;NARGS
STA $01,X
GLENW: LDA TEMPNH+1
BEQ GTLCR
GLENW1: LDY #$00
LDA (TEMPNH),Y
STA TEMPN
INY
LDA (TEMPNH),Y
STA TEMPN+1 ;(CAR)
INY
LDA (TEMPNH),Y
PHA
INY
LDA (TEMPNH),Y
STA TEMPNH+1
PLA
STA TEMPNH ;(CDR)
LDA TEMPN
CMP COMMNT
BNE GLENW2
LDA TEMPN+1
CMP COMMNT+1
BEQ GTLCR
GLENW2: INC $00,X
BNE GLENW
INC $01,X
BNE GLENW ;(Always)
GTLSTC: STX ANSN
LDA $00,X
STA TEMPNH
LDA $01,X
STA TEMPNH+1 ;PTR
LDY #$02
GTLC2: LDA (TEMPNH),Y
TAX
BEQ GTLC3
INY
LDA (TEMPNH),Y
GTLC2A: STA TEMPNH+1
STX TEMPNH ;(CDR)
DEY
JMP GTLC2
GTLC3: INY
LDA (TEMPNH),Y
BNE GTLC2A
LDX ANSN
LDA TEMPNH
STA $00,X
LDA TEMPNH+1
STA $01,X
GTLCR: RTS
.PAGE
; Error Break Routines:
;Note - the only temporary variables which can be passed to ERROR
;as pointers are TEMPN6, TEMPN7, TEMPX1, and TEMPX2. PTRXOK and
;PTRYOK insure that the X or Y args point to safe temporaries.
PTRXOK: LDA $00,X
STA TEMPX2
LDA $01,X
STA TEMPX2+1
LDX #TEMPX2
RTS
PTRYOK: LDA $00,Y
STA TEMPX2
LDA $01,Y
STA TEMPX2+1
LDY #TEMPX2
RTS
ERROR: STA ERRFLG
PHA
STA ANSN2
ASL ANSN2 ;Error pointers are stored two bytes apart
STX ANSN3
STY ANSN1
LDA GRPHCS
BEQ ERRO1
LDA $C053 ;If FULL Graphics, make MIXED
ERRO1: JSR RSTIO
JSR EXTEDT ;Zap out of EDIT or CHANGE mode if necessary
PLA
LDX RETADR
TXS ;Restore all necessary return addresses
CMP #XZAP
BEQ ERRZ1
CMP #XARGTB
BEQ ERRZ2
CLC ;The Error-table holds pointers to the error-strings
LDA #ERRTBL&$FF
ADC ANSN2
STA TEMPN8
LDA #ERRTBL^
ADC #$00
STA TEMPN8+1
LDA GETRM2 ;Ghost-memory bank 2, error table
INC BANK4K
LDY #$00
LDA (TEMPN8),Y
TAX
INY
LDA (TEMPN8),Y
STA TEMPN8+1
STX TEMPN8
ERRW: LDA GETRM2 ;Ghost-memory bank 2, error messages
INC BANK4K
LDY #$00
LDA (TEMPN8),Y
LDX GETRM1 ;Ghost-memory bank 2 disable
LDX GETRM1
DEC BANK4K
TAX
BEQ ERRW2
CMP #$FF
BEQ ERRWE
CMP #$01
BEQ ERRW1
JSR TPCHR
JMP ERRW4
ERRZ1: JSR ZAPMSG
JMP ERRWE
ERRZ2: LDX ANSN3
JSR TYPFIX
LDX #ERRM4&$FF
LDY #ERRM4^
JSR PRTSTR
LDA #$00
LDX ANSN1
JSR LTYPE
JMP ERRWE
ERRW1: LDX ANSN3
JMP ERRW3
ERRW2: LDX ANSN1
ERRW3: LDA #$00
JSR LTYPE
ERRW4: INC TEMPN8
BNE ERRW
INC TEMPN8+1
BNE ERRW ;(Always)
ERRWE: LDA #$00
JSR CLMK5 ;Clear all the MARK pointers
LDA LEVNUM
BNE ERRWE1
LDA LEVNUM+1
BEQ ERR1
ERRWE1: JSR BREAK1
LDX #ERRM1&$FF
LDY #ERRM1^
JSR PRTSTR
LDX #LEVNUM
JSR TYPFIX
LDX #ERRM2&$FF
LDY #ERRM2^
JSR PRTSTR
LDX #LINNUM
JSR TYPFIX
LDX #ERRM3&$FF
LDY #ERRM3^
JSR PRTSTR
LDY #$06 ;(SF_UFUN = 6.)
LDA (FRAME),Y
STA TEMPN8
INY
LDA (FRAME),Y
STA TEMPN8+1 ;(CAR)
LDA #$00
LDX #TEMPN8
JSR LTYPE
ERR1: JSR BREAK1
LDA ERRRET
LDY ERRRET+1
JSR RSTERR
STA TEMPNH
STY TEMPNH+1
JMP (TEMPNH)
.PAGE
;ZAPMSG is a special case of ERROR, for error XZAP. It displays the
;appropriate error message.
ZAPMSG: JSR BREAK1
JSR BREAK1
LDA ANSN3
CMP #XNSTRN
BEQ ZPC1
CMP #XNSTOR
BEQ ZPC1
CMP #XSTOP
BEQ ZPC2
CMP #XEXCED
BEQ ZPC3
JSR SYSBUG
ZPC1: LDX #ZPMSG1&$FF
LDY #ZPMSG1^ ;"No Storage Left!"
JMP PRTSTR
ZPC2: LDX #ZPMSG2&$FF
LDY #ZPMSG2^ ;"Stopped!"
JMP PRTSTR
ZPC3: LDX #ZPMSG3&$FF
LDY #ZPMSG3^ ;"Evaluator Overflow"
JMP PRTSTR
;SYSBUG prints an error message and exits.
SYSBUG: STA $02
PLA
STA $01 ;Store calling point in locations $00,$01
PLA
STA $00
TXA
PHA
TYA
PHA
JSR RSTIO
LDX #LBUG1&$FF
LDY #LBUG1^
JSR PRTSTR ;Print "LOGO BUG!"
PLA
TAY
PLA
TAX
LDA $02
;falls through
;falls in
SBPT: BRK
NOP
NOP
JMP POPJ ;Monitor "G" command re-enters here
.PAGE
.SBTTL Garbage Collector
GARCOL: TSX
STX RETADR
LDA #GCLERR&$FF
STA ERRRET
LDA #GCLERR^
STA ERRRET+1
JSR SWAPT1
LDA SOBLST
STA TEMPN3 ;TEMPN3 is INDEX
LDA SOBLST+1
STA TEMPN3+1
GCLP2: LDX #TEMPN3
JSR MARK
CLC
LDA TEMPN3
ADC #$04
STA TEMPN3
BCC GCLP2A
INC TEMPN3+1
GCLP2A: LDA TEMPN3
CMP SOBTOP
BNE GCLP2
LDA TEMPN3+1
CMP SOBTOP+1
BNE GCLP2
LDA #VPDLBA&$FF
STA TEMPN3
LDA #VPDLBA^
STA TEMPN3+1
GCLP3: LDA TEMPN3
CMP VSP
BNE GCLP3X
LDA TEMPN3+1
CMP VSP+1
BEQ GCLP3A
GCLP3X: LDY #$00
LDA (TEMPN3),Y
STA TEMPN
INY
LDA (TEMPN3),Y
STA TEMPN+1 ;(GETBAR)
JSR MARKX ;Expects TEMPN as node
SEC
LDA TEMPN3
SBC #$02
STA TEMPN3
BCS GCLP3
DEC TEMPN3+1
BNE GCLP3 ;(Always)
GCLP3A: LDA FRAME
STA TEMPN3 ;TEMPN3 is FRAMEPTR
LDA FRAME+1
BEQ GCOL1
STA TEMPN3+1
GCLP4: LDY #$0E ;(SF_NUMBER_BINDINGS = 14.)
LDA (TEMPN3),Y
BEQ GCLP5E
STA ANSN1 ;ANSN1 is NARGS
CLC
LDA TEMPN3
ADC #$12 ;PTR1 points to first binding pair
STA TEMPN4 ;TEMPN4 is PTR1
LDA TEMPN3+1
ADC #$00
STA TEMPN4+1
GCLP5: LDY #$02
LDA (TEMPN4),Y ;See if it's a fun/frame pair
ROR A
BCS GCLP5A
LDY #$00 ;Nope, get value and mark
LDA (TEMPN4),Y
STA TEMPN
INY
LDA (TEMPN4),Y
STA TEMPN+1
JSR MARKX ;Expects TEMPN as node
GCLP5A: CLC
LDA TEMPN4
ADC #$04
STA TEMPN4
BCC GCLP5B
INC TEMPN4+1
GCLP5B: DEC ANSN1
BNE GCLP5
GCLP5E: LDY #$00 ;(SF_PREVIOUS_FRAME)
LDA (TEMPN3),Y
TAX
INY
LDA (TEMPN3),Y
STA TEMPN3+1
STX TEMPN3 ;(GETBAR)
BNE GCLP4
GCOL1: LDA #GCVST ;Mark all G.C.-protected variables
STA ANSN1
GCOL1L: LDX ANSN1
JSR MARK
INC ANSN1
INC ANSN1
LDA ANSN1
CMP #GCVEND
BNE GCOL1L
LDX #SIZE1
LDY #AREA1
JSR MARKA
LDX #SIZE2
LDY #AREA2
JSR MARKA
LDA #$00
STA FRLIST
STA FRLIST+1
STA NNODES
STA NNODES+1
LDA #BIGBAS&$FF
STA TEMPNH
LDA #BIGBAS^
STA TEMPNH+1 ;Nodespace pointer
LDA #SINODS&$FF
STA TEMPN
LDA #SINODS^
STA TEMPN+1 ;Typebase pointer
GCLP6: LDY #$00
LDA (TEMPN),Y
ROL A ;Type bit
BCS GCLP6C
LDY #$02
LDA FRLIST
STA (TEMPNH),Y
INY
LDA FRLIST+1
STA (TEMPNH),Y ;(RPLACD)
LDA TEMPNH
STA FRLIST
LDA TEMPNH+1
STA FRLIST+1
JMP GCLP6F
GCLP6C: INC NNODES
BNE GCLP6F
INC NNODES+1
GCLP6F: CLC
LDA TEMPNH
ADC #$04
STA TEMPNH
BCC GCLP6D
INC TEMPNH+1
GCLP6D: INC TEMPN
BNE GCLP6E
INC TEMPN+1
GCLP6E: LDA TEMPN
CMP #TYPEND&$FF
BNE GCLP6
LDA TEMPN+1
CMP #TYPEND^
BNE GCLP6
JSR CLRMRK
JSR SWAPT2
JMP RSTERR
GCLERR: LDA #$00
STA FRLIST
STA FRLIST+1
JSR CLRMRK
JSR SWAPT2
JMP ERROR1
.PAGE
CLRMRK: LDA #SINODS&$FF
STA TEMPNH
LDA #SINODS^
STA TEMPNH+1 ;TEMPN is pointer to Typebase
LDY #$00
GCLP1: LDA (TEMPNH),Y
AND #$7F ;Set Mark bit to 0 (False)
STA (TEMPNH),Y
INC TEMPNH
BNE GCLP1A
INC TEMPNH+1
GCLP1A: LDA TEMPNH
CMP #TYPEND&$FF
BNE GCLP1
LDA TEMPNH+1
CMP #TYPEND^
BNE GCLP1
MRKRTS: RTS
MARKA: LDA $00,X
STA TEMPN
LDA $01,X
STA TEMPN+1 ;TEMPN is SIZE
LDA $00,Y
STA TEMPNH
LDA $01,Y
STA TEMPNH+1
JSR TYPACS ;TEMPNH becomes address of typecodes
MRKAW: LDA TEMPN+1
BMI MRKRTS
BNE MRKAW1
LDA TEMPN
BEQ MRKRTS
MRKAW1: LDA (TEMPNH),Y
ORA #$80 ;Mark the word
STA (TEMPNH),Y
INC TEMPNH
BNE MRKAW2
INC TEMPNH+1
MRKAW2: SEC
LDA TEMPN
SBC #$01
STA TEMPN
BCS MRKAW
DEC TEMPN+1
JMP MRKAW
.PAGE
MARK: LDA $00,X
STA TEMPN
LDA $01,X
STA TEMPN+1 ;TEMPN is INDEX
MARKX: LDX #$FF
LDY #$FF
JSR PUSH
MRKW: LDA #$FF
CMP TEMPN
BNE MRKW1
CMP TEMPN+1
BEQ MRKRTS
MRKW1: LDA TEMPN+1
BEQ MRKW3
STA TEMPNH+1
LDA TEMPN
STA TEMPNH
JSR TYPACS
STA ANSN
ROL A
BCC MRKW2
MRKW3: JSR STKTS1
LDX #TEMPN
JSR POP
JMP MRKW
MRKW2: LDA ANSN
ORA #$80
STA (TEMPNH),Y
AND #$7F
CMP #LIST
BEQ MRKCL
CMP #STRING
BEQ MRKCF
CMP #FIX
BEQ MRKW3
CMP #FLO
BEQ MRKW3
CMP #FLIST
BEQ MRKCF
CMP #UFUN
BEQ MRKCU
CMP #SATOM
BEQ MRKCS
CMP #ATOM
BEQ MRKCL
CMP #DATOM
BEQ MRKCL
CMP #LATOM
BEQ MRKCL
CMP #QATOM
BEQ MRKCL
CMP #FPACK
BEQ MRKCP
JSR SYSBUG
MRKCF: LDY #$02
MRKCN: LDA (TEMPN),Y
TAX
INY
LDA (TEMPN),Y
BEQ MRKW3
TAY
MRKCF1: JSR PUSH
JMP MRKW3
MRKCS: LDY #$00
JMP MRKCN
MRKCL: LDA TEMPN
AND #$FC
STA TEMPN
LDY #$00
LDA (TEMPN),Y
TAX
INY
LDA (TEMPN),Y
BEQ MRKCF
TAY
MRKCL1: JSR PUSH
JMP MRKCF
MRKCU: CLC
LDA TEMPN
ADC #$04
STA TEMPNH
LDA TEMPN+1
ADC #$00
STA TEMPNH+1
JSR TYPACS
ORA #$80
STA (TEMPNH),Y
JMP MRKCF
MRKCP: LDY #$01
STY ANSN ;ANSN is FIRSTLINE
DEY
MRKCP1: LDA (TEMPN),Y
STA TEMPN1 ;TEMPN1 is LINE
INY
LDA (TEMPN),Y
STA TEMPN1+1 ;(GETBAR)
INY
LDA (TEMPN),Y
STA TEMPN2 ;TEMPN2 is LINE_END
INY
LDA (TEMPN),Y
STA TEMPN2+1 ;(GETBAR)
MRKPW: LDA TEMPN2+1
BNE MRKPW1
CLC
LDA TEMPN
ADC #$02
STA TEMPNH
LDA TEMPN+1
ADC #$00
STA TEMPNH+1
JSR TYPACS
ORA #$80
STA (TEMPNH),Y
JMP MRKW3
MRKPW1: CLC
LDA TEMPN
ADC #$02
STA TEMPNH
LDA TEMPN+1
ADC #$00
STA TEMPNH+1
JSR TYPACS
ORA #$80
STA (TEMPNH),Y
LDA TEMPN1
STA TEMPNH
LDA TEMPN1+1
STA TEMPNH+1
JSR TYPACS
ORA #$80
STA (TEMPNH),Y
LDA ANSN
BNE MRKPW2
CLC
LDA TEMPN1
ADC #$02
STA TEMPN1
BCC MRKPW2
INC TEMPN1+1
MRKPW2: LDA #$00
STA ANSN
MRKPX: LDA TEMPN1
CMP TEMPN2
BNE MRKPX1
LDA TEMPN1+1
CMP TEMPN2+1
BNE MRKPX1
MRKPXE: CLC
LDA TEMPN
ADC #$02
STA TEMPN
BCC MRKCP1
INC TEMPN+1
BNE MRKCP1 ;(Always)
MRKPX1: LDA TEMPN1
STA TEMPNH
LDA TEMPN1+1
STA TEMPNH+1
JSR TYPACS
ORA #$80
STA (TEMPNH),Y
LDA (TEMPN1),Y
TAX
INY
LDA (TEMPN1),Y
TAY
JSR PUSH
JSR STKTS1
CLC
LDA TEMPN1
ADC #$02
STA TEMPN1
BCC MRKPX
INC TEMPN1+1
BNE MRKPX ;(Always)
.PAGE
SWAPT1: LDY #TMPNUM-1
LDX #TMPSTT
SWPLP1: LDA $00,X
STA TMPTAB,Y
INX
DEY
BPL SWPLP1
RTS
SWAPT2: LDY #TMPNUM-1
LDX #TMPSTT
SWPLP2: LDA TMPTAB,Y
STA $00,X
INX
DEY
BPL SWPLP2
RTS
.PAGE
.SBTTL Output Routines:
;PRTSTR prints the Ascii string whose address is in the X and Y registers.
;The string is terminated with a 0.
PRTSTR: STX TEMPNH
STY TEMPNH+1
LDA GETRM2 ;Ghost-memory bank 2, Text strings
INC BANK4K
LDY #$00
PTSTR1: LDA (TEMPNH),Y
BEQ PTRRTS
JSR TPCHR
INY
BNE PTSTR1 ;(Always)
PTRRTS: LDA GETRM1 ;Ghost-memory bank 2 disable
LDA GETRM1
DEC BANK4K
RTS
SPRNT: LDA NARGS
BEQ SPRNT2
BPL SPRNT1
EOR #$FF
STA NARGS
SPRNT1: LDX #ARG1
JSR VPOP
LDA #$01
JSR LTYPE
DEC NARGS
BNE SPRNT1
SPRNT2: RTS
LTYPE: STA TEMPN4 ;TOPLEVELP
LDA $00,X
STA TEMPN5
LDA $01,X
STA TEMPN5+1 ;THING
LDX #LTPRTS&$FF
LDY #LTPRTS^
JSR PUSH
PRTHNG: LDX #TEMPN5
JSR GETTYP
CMP #LIST
BEQ LTPLS
CMP #ATOM
BEQ LTPA
CMP #SATOM
BEQ LTPS
CMP #DATOM
BEQ LTPD
CMP #QATOM
BEQ LTPQ
CMP #LATOM
BEQ LTPL
PHA ;Assuming Fix or Flo, save typecode
LDY #$00 ;and prep. for TYPFIX/FLO
LDX #$03
LTYPL1: LDA (TEMPN5),Y
STA NARG1,Y
INY
DEX
BPL LTYPL1
PLA
CMP #FIX
BEQ LTPF
CMP #FLO
BEQ LTPF1
JSR SYSBUG
LTPQ: LDA #'"
BNE LTPD1 ;(Always)
LTPD: LDA #':
LTPD1: JSR TPCHR
LTPA: JSR TYPATM
JMP POPJ
LTPS: JSR TPSATM
JMP POPJ
LTPL: JSR TYPATM
LDA #':
JSR TPCHR
JMP POPJ
LTPF: JSR TPBFIX
JMP POPJ
LTPF1: JSR TYPFLO
JMP POPJ
LTPLS: LDA #$01
STA TEMPN4+1 ;NOSPACE
LDA TEMPN4 ;TOPLEVELP
BNE PLSTLP
LDA #'[
JSR TPCHR
PLSTLP: JSR STKTST
LDA TEMPN5+1
BNE PLLP1
LDA TEMPN4 ;TOPLEVELP
BNE PLLP2
STA TEMPN4+1 ;Print a space after Sublists
LDA #']
JSR TPCHR
PLLP2: JMP POPJ
PLLP1: LDA TEMPN4+1 ;NOSPACE
BNE PLLP1A
LDA #$20 ;(Space)
JSR TPCHR
PLLP1A: LDX #TEMPN5
JSR PUSHP
LDX TEMPN4
JSR PUSH
LDY #$00
STY TEMPN4
STY TEMPN4+1
LDA (TEMPN5),Y
TAX
INY
LDA (TEMPN5),Y
STA TEMPN5+1
STX TEMPN5 ;(CAR)
LDX #TPP1&$FF
LDY #TPP1^
JSR PUSH
JMP PRTHNG
TPP1: JSR POPB
STA TEMPN4
LDX #TEMPN5
JSR POP
LDY #$02
LDA (TEMPN5),Y
TAX
INY
LDA (TEMPN5),Y
STA TEMPN5+1
STX TEMPN5 ;(CDR)
JMP PLSTLP
.PAGE
TYPATM: LDA TEMPN5
AND #$FC
STA TEMPN5
LDX #TEMPN5
LDY #TEMPN5
JSR GETPNM ;Returns with A nonzero if Funny-pname
STA ANSN
BEQ TPATMW
LDA INDEV
BEQ TPATMW
LDA #$27 ;(Single Quote)
JSR TPCHR
TPATMW: LDA TEMPN5+1
BEQ TPTMWE
LDY #$00
LDA (TEMPN5),Y
STA TEMPNH
INY
LDA (TEMPN5),Y
STA TEMPNH+1 ;(CAR)
INY
LDA (TEMPN5),Y
TAX
INY
LDA (TEMPN5),Y
STA TEMPN5+1
STX TEMPN5 ;(CDR)
LDA TEMPNH
JSR TPCHR
LDA TEMPNH+1
BEQ TPTMWE
JSR TPCHR
JMP TPATMW
TPTMWE: LDA ANSN
BEQ LTPRTS
LDA INDEV
BEQ LTPRTS
LDA #$27 ;(Single Quote)
JMP TPCHR
.PAGE
TPSATM: LDY #$02
LDA (TEMPN5),Y
TAX
INY
LDA (TEMPN5),Y
STA TEMPN5+1
STX TEMPN5 ;(CDR)
LDY #$03
TPSTMW: LDA (TEMPN5),Y
BEQ LTPRTS
STY ANSN
JSR TPCHR
LDY ANSN
INY
BNE TPSTMW ;(Always)
LTPRTS: RTS
;Types a two-byte fixnum, always positive.
TYPFIX: JSR CVFIX ;Get string on PDL
JMP PRTPDL ;Type string on PDL
;Types a four-byte fixnum in NARG1.
TPBFIX: JSR CVBFIX ;Get string on PDL
JMP PRTPDL ;Type string on PDL
;Type the flonum in NARG1.
TYPFLO: JSR CVFLO ;Get String on PDL
;falls through
;Type the string on the PDL, ANSN1 holds character count.
;falls in
PRTPDL: LDA #$00
PHA ;Push stop indicator
PRTPL1: JSR POPB ;Pop chars off PDL and onto stack
PHA
DEC ANSN1
BNE PRTPL1
PRTPL2: PLA ;Pop chars from stack and type them
BEQ LTPRTS ;until stop indicator popped
JSR TPCHR
JMP PRTPL2
.PAGE
PONAMS: LDA OBLIST
STA TEMPN8
LDA OBLIST+1
STA TEMPN8+1 ;TEMPN8 is OBLIST pointer
PONW1: LDA TEMPN8+1
BEQ PONW1E ;See if done
LDY #$00
LDA (TEMPN8),Y
STA TEMPN6 ;Get name pointer
INY
LDA (TEMPN8),Y
STA TEMPN6+1 ;(CAR)
INY
LDA (TEMPN8),Y
TAX
INY
LDA (TEMPN8),Y
STA TEMPN8+1
STX TEMPN8 ;(CDR) to next OBLIST object
JSR PON1 ;Print the name and value
JMP PONW1
PONW1E: LDA SOBLST
STA TEMPN6 ;TEMPN6 is SOBLIST pointer
LDA SOBLST+1
STA TEMPN6+1
PONW2: LDA TEMPN6
CMP SOBTOP
BNE PONW2A ;See if done
LDA TEMPN6+1
CMP SOBTOP+1
BNE PONW2A
PONRTS: RTS
PONW2A: JSR PON1 ;Print the name and value
CLC
LDA TEMPN6
ADC #$04
STA TEMPN6
BCC PONW2
INC TEMPN6+1
BNE PONW2 ;(Always)
.PAGE
PON1: LDX #TEMPN7 ;TEMPN7 is value
LDY #TEMPN6 ;TEMPN6 is NAME
JSR GETVAL
LDA TEMPN7+1
BNE PON1A
LDA TEMPN7
BNE PONRTS ;Skip if NOVALUE
PON1A: LDA INDEV
BNE PON1B ;Use "MAKE" if not screen output
LDA #'"
JSR TPCHR
LDA #$00
LDX #TEMPN6
JSR LTYPE
LDX #PNMSG1&$FF ;"IS "
LDY #PNMSG1^
JSR PRTSTR
LDA #$00
LDX #TEMPN7
JSR LTYPE
JMP BREAK1
PON1B: LDX #PNMSG2&$FF ;"MAKE "
LDY #PNMSG2^
JSR PRTSTR
LDA #'"
JSR TPCHR
LDA #$00
LDX #TEMPN6
JSR LTYPE
LDA #$20
JSR TPCHR
LDX #TEMPN7
JSR GETTYP
CMP #ATOM
BNE PON1C
LDA #'"
JSR TPCHR
PON1C: LDA #$00
LDX #TEMPN7
JSR LTYPE
JMP BREAK1
.PAGE
POFUNS: STA ANSN2 ;ANSN2 is FULL
LDA OBLIST
STA TEMPX2 ;TEMPN7 is OBLIST pointer
LDA OBLIST+1
STA TEMPX2+1
POFNSW: LDY #$03
LDA (TEMPX2),Y
PHA
DEY
LDA (TEMPX2),Y
PHA
DEY
LDA (TEMPX2),Y
TAX
DEY
LDA (TEMPX2),Y
STA TEMPX2
STX TEMPX2+1
LDA #TEMPX2
JSR PTEXTX
PLA
STA TEMPX2
PLA
STA TEMPX2+1
BNE POFNSW
RTS
.PAGE
POTEXT: STX ANSN2 ;ANSN2 is FULL
PTEXTX: STA ANSN1 ;Save ATOMM (Entry point for POFUNS)
TAX
LDA #TEMPN6 ;TEMPN6 becomes FUN
JSR GETFUN
LDA TEMPN6+1
BEQ PTXRTS
LDX #TOMSG&$FF ;"TO "
LDY #TOMSG^
JSR PRTSTR
LDX ANSN1 ;Retrieve ATOMM
LDA #$00
JSR LTYPE ;Print the title
LDY #$02
LDA (TEMPN6),Y
TAX
INY
LDA (TEMPN6),Y
STA TEMPN6+1
STX TEMPN6 ;(CDR)
LDX #TEMPN6
JSR GETTYP
CMP #LIST
BEQ POTXTL
JMP POTXTF
POTXTL: LDY #$00
LDA (TEMPN6),Y
STA TEMPN8 ;TEMPN8 is LINE
INY
LDA (TEMPN6),Y
STA TEMPN8+1 ;(CAR)
INY
LDA (TEMPN6),Y
TAX
INY
LDA (TEMPN6),Y
STA TEMPN6+1
STX TEMPN6 ;(CDR)
PTXLW: LDA TEMPN8+1
BEQ PTXLWE
LDY #$00
LDA (TEMPN8),Y
STA TEMPX1
INY
LDA (TEMPN8),Y
STA TEMPX1+1 ;(CAR)
INY
LDA (TEMPN8),Y
TAX
INY
LDA (TEMPN8),Y
STA TEMPN8+1
STX TEMPN8
LDA #$20 ;(Space)
JSR TPCHR
LDA #$00
LDX #TEMPX1
JSR LTYPE
JMP PTXLW
PTXLWE: JSR BREAK1
LDA ANSN2 ;FULL
BNE PTXLX
PTXRTS: RTS
PTXLX: LDA TEMPN6+1
BNE PTXLX1
PTXEND: LDX #ENDMSG&$FF
LDY #ENDMSG^
JMP PRTSTR
PTXLX1: LDY #$00
LDA (TEMPN6),Y
STA TEMPN8
INY
LDA (TEMPN6),Y
STA TEMPN8+1 ;(CAR)
INY
LDA (TEMPN6),Y
TAX
INY
LDA (TEMPN6),Y
STA TEMPN6+1
STX TEMPN6 ;(CDR)
LDY #$00
LDA (TEMPN8),Y
STA TEMPX1
INY
LDA (TEMPN8),Y
STA TEMPX1+1 ;(CAR)
INY
LDA (TEMPN8),Y
TAX
INY
LDA (TEMPN8),Y
STA TEMPN8+1
STX TEMPN8 ;(CDR)
LDA INDEV
BNE PTXLY ;If screen editor, no line numbers
LDA EDSW
BEQ PTXLY ;else if not other editor, no line numbers
PTXLX2: LDX #TEMPX1
JSR TYPFIX
PTXLY: LDA TEMPN8+1
BEQ PTXLYE
LDY #$00
LDA (TEMPN8),Y
STA TEMPX1
INY
LDA (TEMPN8),Y
STA TEMPX1+1 ;(CAR)
INY
LDA (TEMPN8),Y
TAX
INY
LDA (TEMPN8),Y
STA TEMPN8+1
STX TEMPN8
LDA #$20 ;(Space)
JSR TPCHR
LDA #$00
LDX #TEMPX1
JSR LTYPE
JMP PTXLY
PTXLYE: JSR BREAK1
JMP PTXLX
POTXTF: LDY #$00
LDA (TEMPN6),Y
STA TEMPN8 ;TEMPN8 is PTR
INY
LDA (TEMPN6),Y
STA TEMPN8+1 ;(GETBAR)
INY
LDA (TEMPN6),Y
STA TEMPN7 ;TEMPN7 is ENDPTR
INY
LDA (TEMPN6),Y
STA TEMPN7+1 ;(GETBAR)
CLC
LDA TEMPN6
ADC #$02
STA TEMPN6
BCC PTXFW
INC TEMPN6+1
PTXFW: LDA TEMPN7
CMP TEMPN8
BNE PTXFW1
LDA TEMPN7+1
CMP TEMPN8+1
BEQ PTXFWE
PTXFW1: LDY #$00
LDA (TEMPN8),Y
STA TEMPX1
INY
LDA (TEMPN8),Y
STA TEMPX1+1 ;(GETBAR)
CLC
LDA TEMPN8
ADC #$02
STA TEMPN8
BCC PTXFW2
INC TEMPN8+1
PTXFW2: LDA #$20
JSR TPCHR
LDA #$00
LDX #TEMPX1
JSR LTYPE
JMP PTXFW
PTXFWE: JSR BREAK1
LDA ANSN2
BNE PTXFX
RTS
PTXFX: LDA TEMPN7+1
BNE PTXFX1
JMP PTXEND
PTXFX1: LDA TEMPN7
STA TEMPN8
LDA TEMPN7+1
STA TEMPN8+1
LDY #$02
LDA (TEMPN6),Y
STA TEMPN7
INY
LDA (TEMPN6),Y
STA TEMPN7+1 ;(GETBAR)
CLC
LDA TEMPN6
ADC #$02
STA TEMPN6
BCC PTXFX2
INC TEMPN6+1
PTXFX2: LDA TEMPN7+1
BNE PTXFX3
JMP PTXEND
PTXFX3: LDY #$00
LDA (TEMPN8),Y
STA TEMPX1
INY
LDA (TEMPN8),Y
STA TEMPX1+1 ;(GETBAR)
CLC
LDA TEMPN8
ADC #$02
STA TEMPN8
BCC PTXFX4
INC TEMPN8+1
PTXFX4: LDA INDEV
BNE PTXFY ;No line numbers if screen-editor
LDA EDSW
BEQ PTXFY ;or if not in otherr editor
PTXFX5: LDX #TEMPX1
JSR TYPFIX
PTXFY: LDA TEMPN7
CMP TEMPN8
BNE PTXFY1
LDA TEMPN7+1
CMP TEMPN8+1
BEQ PTXFYE
PTXFY1: LDY #$00
LDA (TEMPN8),Y
STA TEMPX1
INY
LDA (TEMPN8),Y
STA TEMPX1+1 ;(GETBAR)
CLC
LDA TEMPN8
ADC #$02
STA TEMPN8
BCC PTXFY2
INC TEMPN8+1
PTXFY2: LDA #$20
JSR TPCHR
LDA #$00
LDX #TEMPX1
JSR LTYPE
JMP PTXFY
PTXFYE: JSR BREAK1
JMP PTXFX
.PAGE
.SBTTL Arithmetic Routines:
;Floating Point routines:
FLOTN2: JSR SWAP
JSR FLOTN1
JMP SWAP
FLOTN1: LDA NARG1+3
BPL XFLOAT
LDX #NARG1
JSR COMPL
JSR XFLOAT
JMP FCOMPL
XFLOAT: LDA #$9E
STA ANSN ;Shift counter (exponent)
XFLT1: LDA NARG1+3
CMP #$C0
BMI XFLT2
ASL NARG1
ROL NARG1+1 ;Rotate left to left-justify
ROL NARG1+2
ROL NARG1+3
DEC ANSN
BNE XFLT1 ;Stop if exponent is zero
XFLT2: LDA NARG1+1 ;Reverse LSB, MSB for floating pt. format
LDY NARG1+3
STY NARG1+1
STA NARG1+3
LDA ANSN
STA NARG1 ;Put in exponent
RTS
;Add M1 and M2, result in M1.
ADD: CLC ;Clear carry
LDX #$02 ;Index for 3-byte add
ADD1: LDA NARG1+1,X
ADC NARG2+1,X ;Add a byte of Mant2 to Mant1
STA NARG1+1,X
DEX ;Index to next more signif. byte
BPL ADD1 ;Loop until done
RTS ;Return
;Makes X/M1 and X/M2 positive. Returns with LSB of SIGN equal to XOR of
;signs of original numbers. Copies (positive) mantissa of X/M1 into E.
MD1: ASL ANSN ;Clear LSB of Sign
JSR ABSWAP ;Abs. val. of M1, then swap with M2
ABSWAP: BIT NARG1+1 ;Is Mant1 negative...
BPL ABSWP1 ;No, swap with Mant2 and return
JSR FCOMPL ;Yes, complement it.
INC ANSN ;Increment sign, complementing LSB
ABSWP1: SEC ;Set carry for return to MUL/DIV
;Swaps X/M1 and X/M2 and leaves a copy of M1 in E.
SWAP: LDX #$04 ;Index for 4-byte swap
SWAP1: STY TEMPNH-1,X
LDA NARG1-1,X ;Swap a byte of Exp/Mant1 with
LDY NARG2-1,X ;Exp/Mant2 and leave a copy of
STY NARG1-1,X ;Mant1 in E (3 bytes). (E+3 is destroyed.)
STA NARG2-1,X
DEX ;Advance index to next byte
BNE SWAP1 ;Loop until done
RTS ;Return
;Normalize M1 and X1 to standard format floating pt. (left-justified mantissa,
;exponent tells how much so).
NORM1: LDA NARG1+1 ;High-order Mant1 byte
CMP #$C0 ;Are Upper two bits unequal...
BMI RTS1 ;Yes, return with Mant1 normalized.
DEC NARG1 ;Decrement X1
ASL NARG1+3
ROL NARG1+2 ;Shift Mant1 3 bytes left
ROL NARG1+1
FNORM: LDA NARG1 ;Is Exp1 zero...
BNE NORM1 ;No, continue normalizing.
RTS1: RTS ;Return
;Floating pt. add. X/M1 becomes X/M2 + X/M1.
FADD: JSR FADD1
CLC ;If it returns, then no overflow
RTS
FSUB: JSR SWAP ;It does M2-M1, we want M1-M2
FSUBX: JSR FSUB1
CLC
RTS
FMUL: JSR FMULT
CLC
RTS
FDIV: JSR SWAP ;It does M2/M1, we want M1/M2.
JSR FDIVD
CLC
RTS
;Floating pt. subtract. X/M1 becomes X/M2 - X/M1.
FSUB1: JSR FCOMPL ;Complement Mant1, clears carry unless 0
SWPALN: JSR ALNSWP ;Right shift Mant1 or swap
FADD1: LDA NARG2
CMP NARG1 ;Compare Exp1 with Exp2
BNE SWPALN ;If unequal, swap addends or align mantissas
JSR ADD ;Add aligned mantissas
;Cleans up after complementing mantissa, or after adding mantissas.
ADDEND: BVC FNORM ;No overflow, normalize result
BVS RTLOG ;(Always) Overflow - shift M1 right, carry into Sign
;Either swap mantissas (for another alignment) or do an alignment. Carry bit
;resultants determine which to do each time over.
ALNSWP: BCC SWAP ;Swap if carry clear, else shift right arith.
;Shifts mantissa right, towards pure fixnum.
RTAR: LDA NARG1+1 ;Sign of M1 into carry for
ASL A ;right arith. shift
;Make upper two bits of mantissa unequal by shifting M1 right.
;Also shifts LSB of M1 into MSB of E.
RTLOG: INC NARG1 ;Increment X1 to adjust for right shift
BEQ OVFL ;Exp1 out of range
RTLOG1: LDX #$FA ;Index for 6 byte right shift
ROR1: ROR TEMPNH+3,X ;(M1 and E must be contiguous)
INX ;Next byte of shift
BNE ROR1 ;Loop until done
RTS ;Return
;Floating pt. multiply. X/M1 becomes X/M1 * X/M2.
FMULT: JSR MD1 ;Absolute value of Mant1, Mant2.
ADC NARG1 ;Add Exp1 to Exp2 for product Exp
JSR MD2 ;Check product exp. and prepare for multiply
CLC ;Clear carry for first bit
FMUL1: JSR RTLOG1 ;M1 and E right (product and multiplier)
BCC FMUL2 ;If carry clear, skip partial product
JSR ADD ;Add multiplicand to product
FMUL2: DEY ;Next multiply iteration
BPL FMUL1 ;Loop until done
MDEND: LSR ANSN ;Test Sign LSB
NORMX: BCC FNORM ;If even, normalize product, else complement
;Complement the mantissa of M1.
FCOMPL: SEC ;Set carry for subtract
LDX #$03 ;Index for 3-byte subtract
COMPL1: LDA #$00 ;Clear A
SBC NARG1,X ;Subtract byte of Exp1
STA NARG1,X ;Restore it
DEX ;Next more significant byte
BNE COMPL1 ;Loop until done
BEQ ADDEND
;Floating pt. multiply. X/M1 becomes X/M1 / X/M2.
FDIVD: JSR MD1 ;Take abs. val. of Mant1, Mant2
SBC NARG1 ;Subtract Exp1 from Exp2
JSR MD2 ;Save as quotient exp.
DIV1: SEC ;Set carry for subtract
LDX #$02 ;Index for 3-byte subtraction
DIV2: LDA NARG2+1,X
SBC TEMPNH,X ;Subtract a byte of E from Mant2
PHA ;Save on stack
DEX ;Next more significant byte
BPL DIV2 ;Loop until done
LDX #$FD ;Index for 3-byte conditional move
DIV3: PLA ;Pull byte of difference off stack
BCC DIV4 ;If M2 smaller than E then don't restore M2
STA NARG2+4,X
DIV4: INX ;Next less significant byte
BNE DIV3 ;Loop until done
ROL NARG1+3
ROL NARG1+2 ;Roll quotient left, carry into LSB
ROL NARG1+1
ASL NARG2+3
ROL NARG2+2 ;Shift dividend left
ROL NARG2+1
BCS OVFL ;Overflow is due to un-normalized divisor
DEY ;Next divide iteration
BNE DIV1 ;Loop until done 23 iterations
BEQ MDEND ;(Always) Normalize quotient and correct sign
;Prepare for multiply or divide, check result's exponent.
MD2: STX NARG1+3
STX NARG1+2 ;Clear Mant1 (3 bytes) for MUL/DIV
STX NARG1+1
BCS OVCHK ;If calculation set carry, check for overflow
BMI MD3 ;If negative, then no underflow
PLA ;Pop one return level (undeflow, answer is 0)
PLA
BCC NORMX ;Clear X1 and return
MD3: EOR #$80 ;Complement sign bit of exponent
STA NARG1 ;Store it.
LDY #$17 ;Count 24. (MUL) or 23. (DIV) iterations
RTS ;Return
OVCHK: BPL MD3 ;If positive exponent, then no overflow.
PLA
PLA ;Pop past MD2 call
OVFL: PLA ;Overflow, pop past first function call
PLA
SEC ;Indicate overflow
RTS
;Changes the argument in (X) from Flonum to four-byte Fixnum.
XINT2: JSR SWAP ;Pos or neg, only NARG2
JSR XINT1
JMP SWAP
XINT1: LDA NARG1 ;Pos or neg, only NARG1
BMI FFIXP
LDA #$00 ;Negative exponent gives zero result
STA NARG1
STA NARG1+1
STA NARG1+2
STA NARG1+3
FFIXR: RTS
FFIXP: CMP #$9F
BCS OVFL1 ;Exponent too high, overflow
LDA NARG1+1
BPL FFIXP1
JSR FCOMPL
JSR FFIXP1
LDX #NARG1
JMP COMPL
FFIXP1: LDA NARG1
STA ANSN
LDA #$00
STA NARG1 ;Init LSB to zero
LDA NARG1+1
LDY NARG1+3 ;Switch LSB, MSB for fixnum format
STY NARG1+1
STA NARG1+3
FFIX1: LDA ANSN
CMP #$9E
BEQ FFIXR ;Done when Exp=30. (4 bytes, binary point two places in)
LSR NARG1+3
ROR NARG1+2 ;Rotate to right-justify
ROR NARG1+1
ROR NARG1
INC ANSN
BNE FFIX1 ;(Always)
OVFL1: LDA #XOFLOW
JMP ERROR
;Complement (negate) a fixnum.
COMPL: LDY #$03
SEC
CMPL1: LDA $00,X
EOR #$FF ;Complement
ADC #$00 ;and increment.
STA $00,X
INX
DEY
BPL CMPL1
RTS
;Divides NARG1 by 10.
XDVD10: LDA #$0A
STA NARG2
LDA #$00
STA NARG2+1
STA NARG2+2
STA NARG2+3
;falls through
.PAGE
;Fast and clean fixnum division routine, assumes positive numbers.
;Dividend in NARG1, divisor in NARG2.
;NARG1 becomes quotient.
;falls in
XDIVID: LDA #$00 ;Zero temp. quotient (A1L-A2H)
LDX #$03
XDLP1: STA A1L,X
STA TEMPN,X
DEX
BPL XDLP1
INC TEMPN ;Initialize bitholder (TEMPN,TEMPN1)
NORM: ASL TEMPN ;Normalize the bitholder...
ROL TEMPN+1
ROL TEMPN1
ROL TEMPN1+1
ASL NARG2
ROL NARG2+1 ;and the divisor
ROL NARG2+2
ROL NARG2+3
BPL NORM ;to the left side
BMI SHFT ;(Always)
SHFTX: PLA ;(Discard intermediate result)
SHFT: LSR TEMPN1+1 ;Back 'em off one
ROR TEMPN1
ROR TEMPN+1
ROR TEMPN
LSR NARG2+3
ROR NARG2+2
ROR NARG2+1
ROR NARG2
LDX #$03
XDLP2: LDA TEMPN,X
BNE DV2 ;If bitholder is zero, done
DEX
BPL XDLP2
BMI DONE ;(Always)
DV2: SEC ;Subtract divisor from dividend
LDA NARG1
SBC NARG2
PHA
LDA NARG1+1
SBC NARG2+1
TAX
LDA NARG1+2
SBC NARG2+2
TAY
LDA NARG1+3
SBC NARG2+3
BCC SHFTX ;If borrow, don't save remainder
STA NARG1+3 ;or add to result
STY NARG1+2
STX NARG1+1
PLA
STA NARG1
CLC
LDX #$FC
XDLP3: LDA A1L+4,X ;Add bitholder to result
ADC TEMPN+4,X
STA A1L+4,X
INX
BMI XDLP3
BPL SHFT ;(Always)
DONE: LDA NARG1
PHA
LDY #A1L
JSR XYTON1
PLA
CLC
ADC #'0
RTS
.PAGE
.SBTTL Screen Editor
;increment the point (EPOINT,EPOINT+1).
INCPNT: INC EPOINT
BNE INCPT2
INC EPOINT+1
INCPT2: RTS
;decrement the point.
DECPNT: LDA EPOINT
SEC
SBC #$01
STA EPOINT
BCS DECPT2
DEC EPOINT+1
DECPT2: RTS
;set the point to the beginning of the buffer.
PNTBEG: LDA #EDBUF&$FF
STA EPOINT
LDA #EDBUF^
STA EPOINT+1
RTS
;place cursor at top of screen
TOPSCR: LDA #$00 ;cursor at top of screen
STA BASLIN ;baseline for top of screen
STA CH
STA CV
LDA #$04
STA BASLIN+1
RTS
;output char in AC to EDBUF at point. Increments point. Does NOT
;increment last-char-in-buffer pointer. Returns without modifying if
;at end of buffer.
EDOUT: TAX ;save char
STY YSAV1
LDA EPOINT+1
CMP #EBFEND^
BCC EDOUT1
BNE EDORTS
LDA EPOINT
CMP #EBFEND&$FF ;Are we at end of edit buffer...
BCS EDORTS ;if so, quit
EDOUT1: LDY #$00
TXA
STA (EPOINT),Y ;if not, store char and inc pointer
JSR INCPNT
EDORTS: LDY YSAV1
NULOUT: RTS
;top level loop in the editor; listens for characters; outputs them to
;the screen and the edit buffer; accepts commands and has them
;processed.
CHGLOP: JSR RDKEY ;get char from kbd
CMP #$03 ;^C means finished
BEQ CHGLPC ;read function into Logo and return.
CMP #$02 ;^B means previous screen
BEQ CHGLPB
CMP #$04 ;^D is delete char under cursor
BEQ CHGLPD
CMP #$06 ;^F means forward screen
BEQ CHGLPF
CMP #$08 ;^H means back char
BEQ CHGLPH
CMP #$0C ;^L means center point on screen
BEQ CHGLPL
CMP #$0F ;^O means open line
BEQ CHGLPO
CMP #$10 ;^P means up line
BEQ CHGLPP
CMP #$15 ;^U means forward char
BEQ CHGLPU
CMP #$1B ;ESC means rubout
BEQ CHGLRB
JSR INSERT ;not a command - insert it
JMP CHGLOP
CHGLPB: JSR PRVSCR
JMP CHGLOP
CHGLPC: JMP EDDONE
CHGLPD: JSR DELETE ;the return address CHGLOP was pushed
JMP CHGLOP
CHGLPF: JSR NXTSCR ;for these above (space bum)
JMP CHGLOP
CHGLPH: JSR BACKUP
JMP CHGLOP
CHGLPL: JSR CENTER
JMP CHGLOP
CHGLPO: JSR OPLINE
JMP CHGLOP
CHGLPP: JSR UPLINE
JMP CHGLOP
CHGLPU: JSR FORCHR
JMP CHGLOP
CHGLRB: JSR RUBOUT
JMP CHGLOP
;EDDONE will read the editor-defined code back into Logo.
EDDONE: LDY #$00
LDA #$0D ;Carriage return at end, just in case none there
STA (ENDBUF),Y
INC ENDBUF
BNE EDDON2
INC ENDBUF+1
EDDON2: LDX #ERDBK1&$FF
LDY #ERDBK1^
JSR PUSH ;Return address from SREAD2
JSR PNTBEG ;point to beginning
JSR RESETT ;Clear the output device
LDX #WAITM&$FF
LDY #WAITM^
JSR PRTSTR
JMP SREAD1
ERDBK1: JSR RSTIO
JMP POPJ
;this function will display the buffer beginning at the point on the
;screen, beginning at CH, CV (should be consistent with BASLIN). It
;will stop if there is nothing more in the buffer, or when there is no
;more room on the screen. Updates TEMPN8 (last-char-displayed
;pointer). EDSPBF will check as it displays for the point and will set
;CV, CH accordingly. If you would like it to turn on the cursor at a
;place other than the point, set A4L,A4H to it and call EDPBUF.
EDSPBF: LDA EPOINT
STA A4L
LDA EPOINT+1
STA A4H
EDPBUF: LDA CV
STA A2L
LDA CH
STA A2H
EDSPLP: LDA EPOINT+1
CMP ENDBUF+1
BCC EDSPB1
BNE EDPRTS
LDA EPOINT
CMP ENDBUF
BCS EDPRTS ;quit if no more in buffer
EDSPB1: LDY #$00
LDA (EPOINT),Y ;get char
CMP #$0D ;#$0D = CR
BEQ EDSPCR
LDX CH
INX
CPX WNDWTH ;if at end of line and next char is a
BCC EDPCHR ;cr, then no !. otherwise yes.
PHA
LDA #'!
JSR COUT ;output continuation line char
PLA
LDX CV ;when we output the continuation char COUT
JMP EDPCR1 ;inc'ed CV, so don't now.
EDOPCR: LDX CV
INX ;if we output the CR (or char on next line),
EDPCR1: CPX WNDBTM ;will we have exceeded the screen length...
BCS EDPRTS ;yes, quit while we're not ahead
EDPCHR: LDX EPOINT
CPX A4L
BNE EDPCH2
LDX EPOINT+1 ;if we're at point then set CV, CH so we can
CPX A4H ;display the cursor in the right place when
BNE EDPCH2 ;we come back
LDX CV
STX A2L
LDX CH
STX A2H
EDPCH2: JSR COUT ;output char; back for more
JSR INCPNT
JMP EDSPLP
EDSPCR: PHA
JSR CLREOL
PLA
JMP EDOPCR
EDPRTS: JSR CLREOP
LDX EPOINT
CPX A4L
BNE EDPRS2
LDX EPOINT+1 ;if we're at point then set CV, CH so we can
CPX A4H ;display the cursor in the right place when
BNE EDPRS2 ;we come back
LDX CV
STX A2L
LDX CH
STX A2H
EDPRS2: LDY #$00
LDA (EPOINT),Y
CMP #$0D ;if it was a CR then it was displayed even if
BNE EDPRS3 ;we couldn't COUT it, so INCPNT so TEMPN8 is
JSR INCPNT ;correct.
EDPRS3: LDA EPOINT ;point is now at location after last char on
STA TEMPN8 ;screen; store in char-after-last-char-pointer
LDA EPOINT+1
STA TEMPN8+1
LDA A2H
STA CH
LDA A2L
STA CV
JSR BCALCA ;have CV in AC already
LDA A4L
STA EPOINT
LDA A4H
STA EPOINT+1
RTS
CHGSTP: LDA INDEV
BNE CHGSR1 ;Error if already editing with CHANGE
CHGST1: LDA LEVNUM
BNE CHGSR2
LDA LEVNUM+1
BNE CHGSR2
LDA TOKPTR+1
BEQ CHGNON
LDY #$00
LDA (TOKPTR),Y
STA ARG1
INY
LDA (TOKPTR),Y
STA ARG1+1 ;(GETTOK)
LDX #ARG1
JSR GETTYP
CMP #SATOM
BEQ CHGSR4
CMP #ATOM
BNE CHGSR5
LDX #ARG1
LDA #TEMPN1
JSR GETFUN
LDA TEMPN1+1
BEQ CHGNEW
CHGOLD: JSR CHGIN1
LDX #$01
LDA #ARG1
JSR POTEXT ;store function text in EDBUF
JSR CHGIN2
JMP CHGIN3
CHGSR1: LDA #XEDT
JMP ERROR
CHGSR2: JMP STTLR2 ;(ERROR XETL)
CHGSR4: JMP SPO5S ;(ERROR XUBL,ARG1)
CHGSR5: JMP SMAKE2 ;(ERROR XWTA,ARG1,CURTOK)
CHGNON: JSR CHGIN1
JSR PNTBEG ;set point to beginning of buffer
JSR CHGIN2
CHGIN3: JSR EDSPBF ;call edit-display-buffer
JMP CHGLOP ;call text and command handling loop
CHGNEW: JSR CHGIN1
LDX #TOMSG&$FF
LDY #TOMSG^
JSR PRTSTR
LDX #ARG1
LDA #$01
JSR LTYPE
CHGNLP: LDX #TOKPTR
JSR TFKADV
LDA TOKPTR+1
BEQ CHGN2
LDY #$00
LDA (TOKPTR),Y
STA ARG1
INY
LDA (TOKPTR),Y
STA ARG1+1
LDA #$20
JSR TPCHR
LDA #$00
LDX #ARG1
JSR LTYPE
JMP CHGNLP
CHGN2: LDA EPOINT
STA A4L
LDA EPOINT+1
STA A4H
JSR CHGIN2
JSR EDPBUF
JMP CHGLOP
CHGIN2: JSR SETVID ;make output device be screen again
LDA EPOINT
STA ENDBUF ;save end of buffer
LDA EPOINT+1
STA ENDBUF+1
CHGX1: JSR PNTBEG
LDA #$17 ;Window bottom to allow display of
STA WNDBTM ;"Apple Logo Editor" crock
LDA #EDBUF^ ;store location of first char displayed
STA TEMPN7+1 ;on screen (at beginning of buffer)
LDA #EDBUF&$FF
STA TEMPN7
JSR TOPSCR
JMP CHGNYM ;print editor name
CHGIN1: LDA #EDOUT&$FF ;location of edbuf output
STA CSWL
LDA #EDOUT^ ;routine (for TPCHR)
STA CSWH
LDA #BUFFER
STA INDEV
JMP PNTBEG ;initialize point for EDOUT
CHGNYM: LDA INVFLG
PHA ;Save old INVFLG
JSR SETINV ;print the "Apple Logo Screen Editor" thing on
LDA CH ;the bottom line in reversed characters.
PHA
LDA CV ;save current screen location
PHA
LDA BASLIN ;save old baseline
PHA
LDA BASLIN+1
PHA
LDA #$00
STA CH ;far left
LDA #$23
STA CV ;bottom of screen
LDA #$D0 ;slight speed bum -- we know we want
STA BASLIN ;the bottom of the screen, so instead
LDA #$07 ;of calculating it via BCALC, we load
STA BASLIN+1 ;it up.
LDX #CHGMSG&$FF
LDY #CHGMSG^
JSR PRTSTR
PLA
STA BASLIN+1
PLA
STA BASLIN
PLA
STA CV
PLA
STA CH
PLA
STA INVFLG ;Restore previous INVFLG
RTS
.PAGE
;Command subroutines. It is the responsibility of a command to do its
;own redisplay, leave CH and CV indicating the position of the point
;on the screen, and the appropriate value in BASLIN before returning
;to CHGLOP. The cursor will be turned on by CHGLOP, however.
;Any command (that does anything) must update the database. The
;database consists of the edit buffer (EDBUF), whose contents must be
;updated by insertions/deletions; the point (EPOINT,EPOINT+1); the
;location in the EDBUF of the first character displayed on the screen
;(TEMPN7,TEMPN7+1); the location in the EDBUF AFTER the last character
;displayed on the screen (TEMPN8,TEMPN8+1), and the location AFTER
;the last character in the EDBUF (ENDBUF,ENDBUF+1).
INSERT: PHA ;save char
JSR MVDOWN ;move the buffer (starting at point) down one.
PLA
PHA
JSR EDOUT ;put the char in the edit buffer
PLA
CMP #$0D
BEQ INSRCR
LDX CH
INX
CPX WNDWTH ;Are we at end of line...
BCC INSRT2 ;no, output straight
PHA
LDA #'! ;output a line continuation char.
JSR COUT
PLA ;recover char
LDX CV ;if we output the line cont. char then COUT
JMP INSRT0 ;has inc'ed CV, so don't do it again.
INSRT1: LDX CV
INX
INSRT0: CPX WNDBTM ;are we at end of screen...
BNE INSRT2
PHA ;yes, redisplay instead of EDSPBF
JSR CENTER ;^L type redisplay
PLA
INSRTS: RTS
INSRT2: JSR COUT ;output char to screen
JMP EDSPBF ;redisplay buffer from point down
INSRCR: PHA
JSR CLREOL
PLA
JMP INSRT1
;move the contents of the edit buffer after point down one until
;reaching end of buffer contents (NOT end of buffer). Increments end
;of buffer contents pointer. Bashes AC,Y.
MVDOWN: LDA ENDBUF
SEC
SBC #$01
STA A1L
LDA ENDBUF+1
SBC #$00
STA A1H
LDY #$01
MVLOOP: LDA A1H
CMP EPOINT+1
BCC MVRTS
BNE MVCONT
LDA A1L
CMP EPOINT
BCC MVRTS
MVCONT: DEY
LDA (A1L),Y
INY
STA (A1L),Y
LDA A1L
SEC
SBC #$01
STA A1L
BCS MVLOOP
DEC A1H
BCC MVLOOP ;(Always)
MVRTS: INC ENDBUF
BNE MVRTS1
INC ENDBUF+1
MVRTS1: RTS
;RDSPNT repositions the text on the screen around the point. The AC
;should hold the number of lines before the point one wants redisplay
;to start from. So, for ^L it should hold 12; for M-V it should hold
;23. RDSPNT will get confused if given a buffer that contains more
;than 256*39 contiguous chars without a carriage-return in them,
;because we have a one-bite physical line counter. You change it. Sets
;first and last char on screen pointers.
RDSPNT: STA A1H ;store the number of lines one wants before
LDY #$00 ;point on screen
STY A1L ;zero char-counter
STY A2L ;zero line-counter
LDA EPOINT+1
STA A4H ;save for recovery by EDPBUF
LDA EPOINT
STA A4L
SEC
SBC CH ;get to beginning of screen line
STA EPOINT
BCS RDSPT2
DEC EPOINT+1
RDSPT2: JSR DECPNT
LDA #EDBUF^
CMP EPOINT+1
BCC RDSPT3 ;if EDBUF is less than point, you're in
LDA #EDBUF&$FF ;buffer, otherwise at beginning or before
CMP EPOINT ;if at beginning or before (horrors) quit
BCC RDSPT3 ;else continue
JSR PNTBEG
JMP COUNTM
RDSPT3: LDA (EPOINT),Y
CMP #$0D ;CR
BEQ COUNTM ;if so, see if we have enough lines now
INC A1L ;else bump char counter
LDA A1L
CMP #$27 ;do we have a full line...
BNE RDSPT2 ;no, go back for more
COUNTM: STY A1L ;zero char counter
INC A2L ;bump line counter
LDA A2L ;lines gotten
CMP A1H ;lines wanted
BEQ REDISP ;if same, we done won, go redisplay.
BCS CNTDWN
LDA EPOINT+1
CMP #EDBUF^
BNE RDSPT2 ;if too few and at beginning of buffer,
LDA EPOINT
CMP #EDBUF&$FF ;redisplay anyway
BEQ REDISP
BNE RDSPT2 ;else go for more
CNTDWN: LDA A2L ;faster than a multiply, usually
SEC
SBC A1H ;# of extra lines
STA A3L
CNTLOP: LDA EPOINT
CLC
ADC #$27 ;move down a screen line of chars
BCC CNTLP2
INC EPOINT+1
CNTLP2: LDA A3L
SEC
SBC #$01 ;dec line counter
STA A3L
BNE CNTLOP ;go for more if not zero
REDISP: JSR TOPSCR ;physical cursor at top of screen
LDA EPOINT
STA TEMPN7 ;make first-char-on-screen point
LDA EPOINT+1
STA TEMPN7+1
JMP EDPBUF ;redisplay and restore point
;redisplay screen around point. Sets CV, CH, BASLIN,
;first-char-on-screen, char-after-last-char-on-screen.
CENTER: LDA #$0C ;#$0C = 12.
JMP RDSPNT ;redisplay for point on 13th line
;NXTSCR moves to the next screenful in the buffer and displays it,
;setting point to the character after the last char on the previous
;screenful (thus it will be at top of screen).
NXTSCR: LDA TEMPN8+1
CMP ENDBUF+1
BNE NXTSC2
LDA TEMPN8
CMP ENDBUF
BEQ RCMPLN ;complain if no next screen
NXTSC2: LDA TEMPN8
STA EPOINT ;point
STA TEMPN7 ;first char on screen
LDA TEMPN8+1
STA EPOINT+1
STA TEMPN7+1
JSR TOPSCR
JMP EDSPBF ;display
;PRVSCR moves to the previous screenful in the buffer, leaves point at
;the top.
PRVSCR: LDA TEMPN7
STA EPOINT ;make point be beginning of screen
LDA TEMPN7+1
STA EPOINT+1
LDA #$17 ;redisplay 23 lines before it
JSR RDSPNT
LDA TEMPN7
STA EPOINT ;make point be beginning of screen
LDA TEMPN7+1
STA EPOINT+1
JMP TOPSCR ;cursor at top of screen
;RUBOUT deletes char behind cursor, redisplays.
RUBOUT: LDA EPOINT+1
CMP #EDBUF^
BCC RCMPLN ;are we before or at beginning...
BNE RUBOT2
LDA #EDBUF&$FF ;I know the switch is unorthodox, sorry
CMP EPOINT
BCS RCMPLN
RUBOT2: JSR BACKUP
JMP DELET2
RCMPLN: JMP BELL ;complain if so.
;DELETE deletes char under cursor, redisplays.
DELETE: LDA ENDBUF+1
CMP EPOINT+1
BCC RCMPLN ;if at buffer end, complain
BNE DELET2
LDA EPOINT
CMP ENDBUF
BCS RCMPLN
DELET2: LDA #$01 ;only moving stuff up one place
STA A1L
LDA #$00
STA A1H
LDA #A1L&$FF
JSR MOVEUP
JMP EDSPBF
;MOVEUP takes the location of an arg in AC,Y and moves the argth char
;after the point into the point, the arg+1th into the point+1, and so
;on until the buffer end is reached. Then it sets the end of buffer
;pointer to the point before restoring it. Better make plenty damned
;sure that MOVEUP is used carefully so that end-of-buffer-pointer
;doesn't become too small.
MOVEUP: TAX
LDA EPOINT ;we are saving point to restore it later
PHA
STA TEMPX3 ;in TEMPX3 for source
LDA EPOINT+1
PHA
STA TEMPX3+1
LDA $00,X
CLC
ADC TEMPX3 ;and add to point for source address
STA TEMPX3
LDA $01,X
ADC TEMPX3+1
STA TEMPX3+1
MVULOP: LDA TEMPX3+1
CMP ENDBUF+1 ;are we looking at end-of-buffer...
BCC MVULP2 ;no, continue
BNE MVURTS ;past, return
LDA TEMPX3
CMP ENDBUF
BCS MVURTS ;past or end, return
MVULP2: LDY #$00
LDA (TEMPX3),Y ;source
STA (EPOINT),Y ;dest
JSR INCPNT ;inc dest
INC TEMPX3 ;inc source
BNE MVULOP
INC TEMPX3+1
JMP MVULOP
MVURTS: LDA EPOINT
STA ENDBUF ;new end-of-buffer
LDA EPOINT+1
STA ENDBUF+1
PLA
STA EPOINT+1
PLA
STA EPOINT ;recover point
RTS ;that's all, folks
;FORCHR moves forward one character, bells if at end of buffer.
FORCHR: LDA EPOINT+1
CMP ENDBUF+1
BCC FORCH2 ;if at buffer end complain
BNE FCMPLN
LDA EPOINT
CMP ENDBUF
BCS FCMPLN
FORCH2: LDA TEMPN8 ;!!**CROCK**!! THIS CAUSES REDISPLAY WHEN
SEC ;YOU TRY FORWARD ON NEXT TO LAST CHAR IN
SBC #$01 ;BUFFER!!! SHOULD CHECK CV,CH OR (EPOINT).
STA A3L ;see if on last char on screen
LDA TEMPN8+1
SBC #$00
STA A3H
CMP EPOINT+1
BNE FORCH3
LDA A3L
CMP EPOINT
BNE FORCH3
JSR INCPNT ;yes, inc point and center
JMP CENTER
FCMPLN: JMP BELL
FORCH3: LDY #$00
LDA (EPOINT),Y
CMP #$0D
BNE FORCH5
FORCH4: STY CH ;if on a CR, we know we're not at end of
INC CV ;screen by now, so zero CH, inc CV.
JSR BCALC ;must calc new baseline
JMP INCPNT
FORCH5: LDA CH
CMP #$26 ;at right before "!"
BEQ FORCH4
INC CH
JMP INCPNT
;BACKUP backs CH and CV up, decs point. No redisplay, unless page
;boundary crossed, or previous char is a CR. Don't call it unless the
;database is consistent; i.e., CV and CH are at the point on the
;screen.
BACKUP: LDA #EDBUF^ ;check if at beginning of buffer
CMP EPOINT+1
BCC BACK2 ;no, win
BNE FCMPLN ;yes, complain, quit
LDA #EDBUF&$FF
CMP EPOINT
BCS FCMPLN
BACK2: JSR DECPNT
LDA CV ;see if we're at beginning of screen
BNE BACK3
LDA CH
BNE BACK3
JMP CENTER ;center
BACK3: LDA CH
BNE BACK5
LDY #$00
LDA (EPOINT),Y
CMP #$0D ;#$0D = CR
BNE BACK4
LDA EPOINT
STA A4L ;when we back over a cr we call
LDA EPOINT+1 ;EDPBUF so as to save space (by
STA A4H ;not having code here to count down a
LDA TEMPN7 ;line)
STA EPOINT
LDA TEMPN7+1
STA EPOINT+1
JSR TOPSCR
JMP EDPBUF ;don't need redisplay, space bum
BACK4: DEC CV
LDA #$26 ;just before the "!"
STA CH
JSR BCALC
RTS
BACK5: DEC CH
RTS
;UPLINE moves to the previous line, maintaining horizontal position if
;that line's length allows it. Does redisplay. Bashes A4L, A4H, A3L,
;A3H.
UPLINE: LDY #$00
STY A4L ;zero char counters - A3L, A3H for desired
STY A3L ;line's length; A4L, A4H for current line's
STY A4H ;length up to current char
STY A3H
LDA EPOINT ;complain if at beginning of buffer
CMP #EDBUF&$FF
BNE UPLOP1
LDA EPOINT+1
CMP #EDBUF^
BEQ UCMPLN
UPLOP1: JSR DECPNT ;dec point; we are searching (while counting
LDA EPOINT ;chars) for the beginning of this line.
CMP #EDBUF&$FF
BNE UPLOP2 ;complain if you encounter the buffer
LDA EPOINT+1 ;beginning while doing this, because this
CMP #EDBUF^ ;means there was no previous line.
BEQ UCMPLN
UPLOP2: LDA (EPOINT),Y
CMP #$0D ;if we are on a CR we have gotten as far as we
BEQ GETNXT ;want, found Nirvana, all that stuff. Go check
INC A4L ;out the previous line; else inc counter and
BNE UPLOP1 ;go back for more.
INC A4H
JMP UPLOP1
UCMPLN: JMP BELL ;complain
GETNXT: LDA EPOINT ;if at buffer beginning we are done and should
CMP #EDBUF&$FF ;go do compares.
BNE GTNXT2
LDA EPOINT+1
CMP #EDBUF^
BEQ GTDOWN ;if we get to buffer beginning count back
JSR DECPNT ;down
GTNXT2: LDA (EPOINT),Y
CMP #$0D ;also count back down if we found a CR, but
BNE GTNXT3 ;first inc pint to be on real beginning of
JSR INCPNT ;line.
JMP GTDOWN
GTNXT3: INC A3L ;else inc counter and go fer more.
BNE GETNXT
INC A3H
JMP GETNXT
GTDOWN: LDA A4H ;in GTDOWN (maw faw) what we are doing is
CMP A3H ;comparing the lengths of the desired line
BCC OLDWIN ;and the old line. If that of the desired
BNE NEWWIN ;is the lesser, we will move down it the
LDA A4L ;length of the old one. Otherwise we will
CMP A3L ;go to its end.
BCC OLDWIN
BCS NEWWIN
OLDWIN: LDA EPOINT
CLC
ADC A4L ;add length to point
STA EPOINT
LDA EPOINT+1
ADC A4H
STA EPOINT+1
JMP GTRDSP
NEWWIN: LDA EPOINT
CLC
ADC A3L ;add length to point
STA EPOINT
LDA EPOINT+1
ADC A3H
STA EPOINT+1
GTRDSP: CMP TEMPN7+1
BCC UCENTR ;now we see if we are off the screen
BNE GTRDP2
LDA EPOINT
CMP TEMPN7
BCC UCENTR ;if before beginning CENTER
BEQ UTPSCR ;if exactly at top no redisplay necessary
GTRDP2: LDA EPOINT+1
CMP TEMPN8+1
BCC GTRDP3 ;if in bounds call EDPBUF
BNE UCENTR ;if after (need to check because this
LDA EPOINT ;routine also used by NXTLIN), CENTER.
CMP TEMPN8
BCC GTRDP3
BCS UCENTR ;always
GTRDP3: LDA EPOINT ;point stored for recovery by EDPBUF
STA A4L
LDA EPOINT+1
STA A4H
JMP REDISP
UCENTR: JMP CENTER
UTPSCR: JMP TOPSCR
;OPLINE inserts a CR at point w/o inc'ing point.
OPLINE: LDA EPOINT+1
CMP #EBFEND^
BCC OPLIN1
BNE OPLRTS
LDA EPOINT
CMP #EBFEND&$FF ;Are we at end of edit buffer...
BCS OPLRTS ;if so, quit
OPLIN1: JSR MVDOWN
LDY #$00
LDA #$0D
STA (EPOINT),Y ;insert CR at point
JMP EDSPBF ;redisplay from here down.
OPLRTS: RTS
.PAGE
.SBTTL File System
SDELET: LDX #ARG1
JSR VPOP
JSR GETTYP
CMP #SATOM
BEQ SDELR2
CMP #ATOM
BNE SDELR3
JSR DOSSTP
LDX #DELETM&$FF
LDY #DELETM^
JSR PRTSTR
JSR DTPATM ;Type atom DOS-style
LDX #LOGOM&$FF
LDY #LOGOM^
JSR PRTSTR
LDA #$8D
JSR TPCHR
JSR RSTIO
JMP POPJ
SDELR2: JMP SPO5S ;(ERROR XUBL,ARG1)
SDELR3: JMP SMAKE2 ;(ERROR XWTA,ARG1,CURTOK)
;file routines should call this to set up error return from DOS.
STDERR: LDA DOSERR
ORA #$80 ;high bit on for DOSERR flag
STA DOSERR
LDA #DERROR&$FF
STA DSERET
LDA #DERROR^
STA DSERET+1
RTS
;DOS error routine comes here
DERROR: JSR RSTIO
LDA DERCOD ;DOS error code
CMP #$04
BEQ WTPROT ;write-protected file
CMP #$06
BEQ FLNFND ;file not found
CMP #$09
BEQ DSKFUL ;disk full
CMP #$0A
BEQ LCKFIL ;attempt to overwrite a locked file
IOERRR: LDA #XIOR ;i/o error
JMP ERROR
WTPROT: LDA #XWTP
JMP ERROR
FLNFND: LDA #XFNF
JMP ERROR
DSKFUL: LDA #XDKF
JMP ERROR
LCKFIL: LDA #XLKF
JMP ERROR
;set up magic things for DOS
DOSSTP: LDA #$40 ;magic number for Applesoft
STA DLNGFG ;store in DOS language flag
LDA #$00
STA DSPFL2 ;store things not = to $FF
STA DSPFL1 ;or apple val for ], in these, respectively.
JSR STDERR ;set up return address for DOS error
JSR SAPOUT ;store APOUT in CSWL so DOS prints properly
JMP DOSEAT ;let DOS eat these
SSAVE: LDA INDEV
BNE SAVSR1 ;Error if editing with ALEC
LDA GRPHCS
BEQ SAVST1
JSR RESETT
LDX #SCS&$FF
LDY #SCS^
JSR PUSH ;So we return to graphics mode when done
SAVST1: LDX #ARG1
JSR VPOP
JSR GETTYP
CMP #SATOM
BEQ SAVSR2
CMP #ATOM
BNE SAVSR3
JSR CHGIN1 ;output to buffer
JSR POFUNS ;get functions into buffer
JSR PONAMS ;get variables into buffer
LDA EPOINT
STA ENDBUF
LDA EPOINT+1
STA ENDBUF+1
LDA #$00
STA INDEV ;Reset INDEV so quotes not printed on funny-pnames
JSR DOSSTP ;Wake up DOS
LDX #SAVEM&$FF
LDY #SAVEM^
JSR PRTSTR
JSR DTPATM ;Type atom DOS-style
LDX #LOGOM&$FF
LDY #LOGOM^
JSR PRTSTR
LDX #SAVEM2&$FF
LDY #SAVEM2^
JSR PRTSTR ;write file
JSR DPRLEN ;Give it file's length
LDA #$8D
JSR TPCHR ;let it go
JSR PNTBEG
LDA #EDBUF&$FF
STA ENDBUF
LDA #EDBUF^
STA ENDBUF+1 ;zero ENDBUF so RETRIEVE not possible
JSR RSTIO
JMP POPJ
SAVSR1: LDA #XNWE ;can't hack files from editor
JMP ERROR
SAVSR2: JMP SPO5S ;(ERROR XUBL,ARG1)
SAVSR3: JMP SMAKE2 ;(ERROR XWTA,ARG1,CURTOK)
DPRLEN: SEC
LDA ENDBUF
SBC #$00
STA TEMPN
LDA ENDBUF+1
SBC #$20
STA TEMPN+1
JSR DPR2HX
LDA TEMPN
DPR2HX: PHA
LSR A
LSR A
LSR A
LSR A
JSR DPRHEX
PLA
DPRHEX: AND #$0F
CMP #$0A
BCC DPRH1
ADC #$06
DPRH1: ORA #$B0
JMP TPCHR
SREAD: LDA INDEV
BNE SAVSR1 ;Error if editing with ALEC
LDA GRPHCS
BEQ SRDF1
JSR RESETT
LDX #SCS&$FF
LDY #SCS^
JSR PUSH ;So we return to graphics mode when done
SRDF1: LDX #ARG1
JSR VPOP
JSR GETTYP
CMP #SATOM
BEQ SAVSR2
CMP #ATOM
BNE SAVSR3
JSR DOSSTP
LDX #LOADM&$FF
LDY #LOADM^
JSR PRTSTR
JSR DTPATM ;Type atom DOS-style
LDX #LOGOM&$FF
LDY #LOGOM^
JSR PRTSTR
LDA #$8D
JSR TPCHR
JSR RSTIO
CLC
LDA FILLEN
ADC #EDBUF&$FF
STA ENDBUF ;recover buffer length from file length
LDA FILLEN+1
ADC #EDBUF^
STA ENDBUF+1
LDA #BUFFER
STA INDEV
LDX #SRDF2&$FF
LDY #SRDF2^
JSR PUSH ;Return address from SREAD2
JSR PNTBEG ;point to beginning
JMP SREAD1
SRDF2: JSR RSTIO
LDA #EDBUF&$FF ;If successful, RETRIEVE won't be necessary
STA ENDBUF
LDA #EDBUF^
STA ENDBUF+1
JMP POPJ
SCATLG: JSR DOSSTP
LDA APCOUT
PHA
LDA APCOUT+1
PHA
LDA APCOUT+2
PHA ;Incredibly bletcherous hack to allow DOS to work
LDA #$6C ;(JMP indirect code)
STA APCOUT
LDA #CSWL ;for JMP (CSWL)
STA APCOUT+1
LDA #$00 ;DOS does a JSR $FDED here -
STA APCOUT+2 ;it depends on their monitor being in place (End of gross hack)
LDX #CATLGM&$FF
LDY #CATLGM^
JSR PRTSTR
PLA
STA APCOUT+2
PLA
STA APCOUT+1
PLA
STA APCOUT
JSR RSTIO
JMP POPJ
DTPATM: LDA ARG1
AND #$FC
STA ARG1
LDX #ARG1
LDY #TEMPN5
JSR GETPNM
DTPTMW: LDA TEMPN5+1
BEQ RSTR
LDY #$00
LDA (TEMPN5),Y
STA TEMPNH
INY
LDA (TEMPN5),Y
STA TEMPNH+1 ;(CAR)
INY
LDA (TEMPN5),Y
TAX
INY
LDA (TEMPN5),Y
STA TEMPN5+1
STX TEMPN5 ;(CDR)
LDA TEMPNH
ORA #$80
JSR TPCHR
LDA TEMPNH+1
BEQ RSTR
ORA #$80
JSR TPCHR
JMP DTPTMW
APOUT: AND #$7F ;eat Apple idiot char codes, type Ascii
JMP COUT
SAPOUT: LDA #APOUT&$FF
STA CSWL
LDA #APOUT^
STA CSWH
RTS
.PAGE
.SBTTL Monitor Routines
BREAK1: LDA #$0D
JMP TPCHR
;Reset I/O to default drivers (INDEV, OUTDEV = 0).
RSTIO: JSR SETVID
JSR SETKBD
LDA #KBD
STA INDEV
STA OUTDEV
RSTR: RTS
CLRCBF: LDA CHBUFR ;Buffer empty when next-free equals next-to-read
STA CHBUFS
RTS
GTBUF: SEC
LDA CHBUFR
SBC CHBUFS
AND #$3F
BEQ GTBRTS ;Return zero if buffer empty (CHBUFR = CHBUFS)
LDX CHBUFR
AND #$3F
LDA CHBSTT,X
INC CHBUFR ;Increment next-to-read
GTBRTS: RTS
;Clear the display/output.
RESETT: JSR SETTXT
JSR SETNRM
JMP HOME
;TPCHR should always be called with an Ascii character. If you want it to flash
;or be inverted, call SETFLS or SETINV first, and resetting INVFLG when done.
TPCHR: JMP (CSWL)
.PAGE
;Modified Monitor for Apple-LOGO
SCRN2: BCC RTMSKZ
LSR A
LSR A
LSR A
LSR A
RTMSKZ: AND #$0F
RTS
PRNTYX: TYA
PRNTAX: JSR PRBYTE
PRNTX: TXA
JMP PRBYTE
INSDS1: LDX PCL
LDY PCH
JSR PRYX2
PRBLNK: LDX #$03
PRBL2: LDA #$20
PRBL3: JSR TPCHR
DEX
BNE PRBL2
RTS
.PAGE
MONBRK: PHA
LDA GETRM1
LDA GETRM1
LDA #$00
STA BANK4K
JSR SETNRM
JSR SETVID
JSR SETKBD
JSR CLRCBF
PLA
PLP
JSR SAVE
PLA
STA PCL
PLA
STA PCH
LDA #$01
STA MONFLG
OLDBRK: JSR INSDS1
JSR RGDSP1
MON: CLD
JSR BELL
MONZ: JSR BREAK1
LDA #'*
JSR TPCHR
JSR GETLN
JSR ZMODE
NXTITM: JSR GETNMB
STY YSAV
LDY #MONNUM
CHRSRC: DEY
BMI MON
CMP CHRTBL,Y
BNE CHRSRC
JSR TOSUB
LDY YSAV
JMP NXTITM
.PAGE
DIG: LDX #$03
ASL A
ASL A
ASL A
ASL A
NXTBIT: ASL A
ROL A2L
ROL A2H
DEX
BPL NXTBIT
NXTBAS: LDA MODE
BNE NXTBS2
LDA A2H,X
STA A1H,X
STA A3H,X
NXTBS2: INX
BEQ NXTBAS
BNE NXTCHR
GETNMB: LDX #$00
STX A2L
STX A2H
NXTCHR: LDA LINARY,Y
INY
CMP #'0
BCC NTDIG
CMP #':
BCC DIG
CMP #'A
BCC NTDIG
CMP #'G
BCS NTDIG
ADC #$09
BNE DIG ;(Always)
TOSUB: TYA
ASL A
TAY
LDA SUBTBL,Y
STA BSLTMP
INY
LDA SUBTBL,Y
STA BSLTMP+1
LDA MODE
JSR ZMODE
JMP (BSLTMP)
ZMODE: LDY #$00
STY MODE
NTDIG: RTS
.PAGE
REGDSP: JSR BREAK1
RGDSP1: LDA #ACC
STA A3L
LDA #ACC^
STA A3H
LDX #$FB
RDSP1: LDA #$20
JSR TPCHR
LDA RTBL-$FB,X
JSR TPCHR
LDA #'=
JSR TPCHR
LDA ACC+5,X
JSR PRBYTE
INX
BMI RDSP1
RTS
NXTA4: INC A4L
BNE NXTA1
INC A4H
NXTA1: LDA A1L
CMP A2L
LDA A1H
SBC A2H
INC A1L
BNE RTS4B
INC A1H
RTS4B: RTS
PRA1: LDY A1H
LDX A1L
PRYX2: JSR BREAK1
JSR PRNTYX
LDY #$00
LDA #'-
JMP TPCHR
.PAGE
XAM8: LDA A1L
ORA #$07
STA A2L
LDA A1H
STA A2H
MD8CHK: LDA A1L
AND #$07
BNE DATAOT
XAM: JSR PRA1
DATAOT: LDA #$20
JSR TPCHR
LDA (A1L),Y
JSR PRBYTE
JSR NXTA1
BCC MD8CHK
RTS4C: RTS
PRBYTE: PHA
LSR A
LSR A
LSR A
LSR A
JSR PRHEXZ
PLA
PRHEX: AND #$0F
PRHEXZ: CLC
ADC #'0
CMP #':
BCC PRHEXC
ADC #$06
PRHEXC: JMP TPCHR
BL1: DEC YSAV
BEQ XAM8
BLANK: DEX
BNE SETMDZ
CMP #':
BNE XAM
STOR: STA MODE
LDA A2L
STA (A3L),Y
INC A3L
BNE RTS5
INC A3H
RTS5: RTS
SETMOD: LDY YSAV
LDA LINARY-1,Y
SETMDZ: STA MODE
RTS
.PAGE
LT: LDX #$01
LT2: LDA A2L,X
STA A4L,X
STA A5L,X
DEX
BPL LT2
RTS
MOVE: LDA (A1L),Y
STA (A4L),Y
JSR NXTA4
BCC MOVE
RTS
VFY: LDA (A1L),Y
CMP (A4L),Y
BEQ VFYOK
JSR PRA1
LDA (A1L),Y
JSR PRBYTE
LDA #$20
JSR TPCHR
LDA #'(
JSR TPCHR
LDA (A4L),Y
JSR PRBYTE
LDA #')
JSR TPCHR
VFYOK: JSR NXTA4
BCC VFY
RTS
A1PC: TXA
BEQ A1PCRT
A1PCLP: LDA A1L,X
STA PCL,X
DEX
BPL A1PCLP
A1PCRT: RTS
SETFLS: LDY #$40
BNE SETIFL ;(Always)
SETINV: LDY #$00
BEQ SETIFL ;(Always)
SETNRM: LDY #$80 ;(Negative flag ignored)
SETIFL: STY INVFLG
RTS
.PAGE
SETKBD: LDA #$00
STA A2L
INPRT: LDY #KEYIN&$FF
LDA #KEYIN^
LDX #KSWL
BNE IOPRT ;(Always)
SETVID: LDA #$00
STA A2L
OUTPRT: LDY #COUT&$FF
LDA #COUT^
LDX #CSWL
IOPRT: STA $01,X
LDA A2L
AND #$0F
BEQ IOPRT1
ORA #IOADR^
STA $01,X
LDY #$00
IOPRT1: STY $00,X
RTS
GO: JSR A1PC
JSR RESTOR
LDA #$00
STA MONFLG
JMP (PCL)
BSWTCH: LDA BANK4K
BNE BSW1
INC BANK4K
LDA GETRM2
LDA GETRM2
LDA #'2
JSR TPCHR
JMP BREAK1
BSW1: DEC BANK4K
LDA GETRM1
LDA GETRM1
LDA #'1
JSR TPCHR
JMP BREAK1
.PAGE
XMON: LDA KILRAM
LDA #$4C ;(JMP instruction code)
STA USRADR
LDA #MONBRK&$FF
STA USRADR+1
LDA #MONBRK^
STA USRADR+2
JMP SYSMON ;User can re-enter this monitor with control-Y
CRMON: JSR BL1
PLA
PLA
JMP MONZ
RESTOR: LDA STATUS
PHA
LDA A5H
RESTR1: LDX XREG
LDY YREG
PLP
RTS
SAVE: STA ACC
SAV1: STX XREG
STY YREG
PHP
PLA
STA STATUS
TSX
STX SPNT
CLD
RTS
.PAGE
BELL: LDA #$40
JSR WAIT
LDY #$C0
BELL1: LDA #$0C
JSR WAIT
LDA SPKR
DEY
BNE BELL1
BRTS: RTS
;HOME - Home the cursor and clear the screen
HOME: LDA WNDTOP
STA CV
LDY #$00
STY CH
BEQ CLEOP1 ;(always branches)
;COUT - Output the character in A to the screen
COUT: PHA
STY YSAV1
JSR COUT1
PLA
LDY YSAV1
RTS
;CROUT - Output a Carriage return; suppress output if necessary
CROUT: JSR CLREOL
JSR TSTCHR
BCC CR
CMP #LSTKEY
BNE CR
BIT KPCLR
JSR RWAIT
JMP CR
;CLREOP - Clear to end-of-page
CLREOP: LDY CH
LDA CV
CLEOP1: PHA
JSR BCALCA
JSR CLEOL1
LDY #$00
PLA
ADC #$00
CMP WNDBTM
BCC CLEOP1
BCS BCALC ;(Always)
.PAGE
COUT1: CMP #$0D
BEQ CROUT
CMP #$07
BEQ BELL ;bell on output of ^G
ORA #$80 ;Assume normal first
CMP #$E0
BCC COUTZ ;See if it's lower case
AND #$DF ;Make it uppercase if so
COUTZ: LDY INVFLG ;Flash or Invert if set
BMI COUTZ1
AND #$3F ;Flash or invert - strip top bits
ORA INVFLG ;and OR in flag
COUTZ1: LDY CH
STA (BASLIN),Y
INC CH ;Advance Horizontally
LDA CH
CMP WNDWTH
BCC BRTS
CR: LDA #$00
STA CH
LF: INC CV
LDA CV
CMP WNDBTM
BCC BCALCA ;Finish if scrolling unnecessary
DEC CV
SCROLL: LDA WNDTOP
PHA
JSR BCALCA
SCRL1: LDA BASLIN
STA BSLTMP
LDA BASLIN+1
STA BSLTMP+1
LDY WNDWTH
DEY
PLA
ADC #$01
CMP WNDBTM
BCS SCRL3
PHA
JSR BCALCA
SCRL2: LDA (BASLIN),Y ;Shift a line up one, character by character
STA (BSLTMP),Y
DEY
BPL SCRL2 ;Next character
BMI SCRL1 ;Next line
SCRL3: LDY #$00
JSR CLEOL1 ;Clear the bottom line, then calculate new base
;falls through
.PAGE
;falls in
BCALC: LDA CV
BCALCA: PHA
LSR A
AND #$03
ORA #$04
STA BASLIN+1
PLA
AND #$18
BCC BCALC2
ADC #$7F
BCALC2: STA BASLIN
ASL A
ASL A
ORA BASLIN
ADC WNDLFT
STA BASLIN
RTS
;CLREOL - Clear to end-of-line
CLREOL: LDY CH
CLEOL1: LDA #$A0 ;(Space, non-flashing, non-inverted)
CLEOL2: STA (BASLIN),Y
INY
CPY WNDWTH
BCC CLEOL2
RTS
RDKEY: JSR GTBUF ;Get character from the buffer if non-empty
CMP #$00
BNE KRTS
JMP (KSWL)
KEYIN: LDY CH
LDA (BASLIN),Y
PHA
AND #$7F
ORA #$40
STA (BASLIN),Y ;Make cursor position flash
JSR RDKEY1
STA BSLTMP
PLA
STA (BASLIN),Y
LDA BSLTMP
KRTS: RTS
RDKEY1: INC RNDL
BNE RDKEY2
INC RNDH
RDKEY2: JSR TSTCHR
BCC RDKEY1
BIT KPCLR
RTS
.PAGE
;Check for input character. Return with carry set and character in A if
;character pending, else carry clear. Supplies "[" for replacement character.
TSTCHR: BIT KPFLAG ;KBD device, check special locations
BPL KNONE
LDA KPFLAG
AND #$7F
CMP #LBRAK
BNE TRTS
LDA #'[
TRTS: SEC
RTS
KNONE: CLC ;Return carry clear if no character
RTS
;SETTXT - Set text mode
SETTXT: LDA $C054 ;Primary page
LDA $C051 ;Set text mode
LDA #$00
STA WNDTOP
STA WNDLFT
LDA #$18
STA WNDBTM
LDA #$28
STA WNDWTH
LDA #$17
STA CV
JMP BCALCA
.PAGE
;GETLN - Gets a line of input from the keyboard. Looks for LOGO interrupt
; characters, and recognizes the left-bracket alias character. Returns
; number of characters (not including terminator) in X.
GETLN: LDX #$00 ;X is LINARY index
JSR RDKEY ;Get an ascii value from keyboard
CMP #PULCHR ;(Pull back last line), Check at first character
BNE NPRVLN
PREVLN: LDA LINARY,X ;get char from line-array
BEQ GNXTX ;done if null char
CMP #$0D
BEQ GNXTX ;or carriage-return encountered
JSR TPCHR ;output char to screen
INX ;next char
BNE PREVLN ;(Always)
NPRVLN: TAY
TXA ;If first character, clear line array
GTLN1L: DEX
STA LINARY,X
BNE GTLN1L
TYA
BNE GTLN1X ;(Always)
NEXTC: JSR RDKEY ;Get an ascii value from keyboard
GTLN1X: CMP #$1B ;(ESC)
BEQ GRUBOT ;do a getln rubout
CMP #$04 ;(^D)
BEQ GDELET ;do a getln delete
CMP #$15 ;(Forward arrow)
BNE GTLN1C
LDA LINARY,X ;Get character under cursor
BEQ GTLNX1
CMP #$0D
BNE GTLNX2
GTLNX1: LDA #$20
GTLNX2: STA LINARY,X
JSR TPCHR ;Echo character
CPX #$F8
BCC GETLN3
JSR BELL
GETLN3: INX
BNE NEXTC
JMP CANCEL
GRUBOT: TXA
BEQ NEXTC
DEX
DEC CH
BPL GDELET
LDA WNDWTH
STA CH
DEC CH
LDA WNDTOP
CMP CV
BCS GDELET
DEC CV
JSR BCALC
JMP GDELET
GTLN1C: CMP #$08 ;(Back arrow)
BEQ BCKSPC
JMP GTLN1D
BCKSPC: TXA
BEQ NEXTC
DEX
DEC CH
BPL NEXTC
LDA WNDWTH
STA CH
DEC CH
LDA WNDTOP
CMP CV
BCS NEXTC
DEC CV
JSR BCALC
GNXTX: CPX #$00
BEQ GNXTC
LDA #$00
STA LINARY+1,X
GNXTC: JMP NEXTC
GDELET: TXA
PHA ;save location in LINARY
LDA CH ;and location on screen
PHA
LDA CV
PHA
GDLTLP: INX ;get next char in LINARY
LDA LINARY,X
STA LINARY-1,X ;store in previous location
BEQ GDLDON ;if null done
CMP #$0D
BEQ GDLTLP
JSR TPCHR ;type out
JMP GDLTLP
GDLDON: LDA #$20 ;found a null, print a space at line
JSR TPCHR ;end
PLA
STA CV
PLA
STA CH
JSR BCALC
PLA
TAX
JMP NEXTC
CANCEL: LDA #'\
JSR TPCHR
JSR BREAK1
JMP GETLN
GTLN1D: CMP #$18 ;(Cancel line)
BEQ CANCEL
LDY MONFLG
BNE GTLN2A ;Don't check for interrupt characters if in monitor
LDY INDEV
BNE GTLN2A ;or if evaluating the edit buffer
CMP #STPKEY
BEQ GTLNR1
CMP #PAUSKY
BEQ GTLNR2
CMP #FULCHR
BEQ GTLNR3
CMP #MIXCHR
BNE GTLN2A
JSR STPMIX
JMP NEXTC
GTLNR3: JSR STPFUL
JMP NEXTC
GTLN2A: LDY LINARY,X
STA LINARY,X
CMP #$0D
BEQ GCR
JSR TPCHR
TXA
PHA ;save location in LINARY
LDA CH ;and location on screen
PHA
LDA CV
PHA
GINSL1: LDA LINARY+1,X ;get next location
PHA ;Save value
TYA ;Get previous location
BEQ GINSDN ;if null done
CMP #$0D
BEQ GINSDN
STA LINARY+1,X ;store in next location
JSR TPCHR ;type out
PLA
TAY
CPX #$F8
BCC GINSL2
JSR BELL
GINSL2: INX
BNE GINSL1
JMP CANCEL
GINSDN: PLA ;Discard null
PLA
STA CV
PLA
STA CH
PLA
TAX
INX
JSR BCALC
JMP NEXTC
GCR: JMP BREAK1
GTLNR1: JMP STPPK1
RWAIT: JSR RDKEY
CMP #STPKEY
BEQ GTLNR1
CMP #PAUSKY
BNE WRTS
GTLNR2: JMP STPPKZ
WAIT: SEC
WAIT1: PHA
WAIT2: SBC #$01
BNE WAIT2
PLA
SBC #$01
BNE WAIT1
WRTS: RTS
.PAGE
.SBTTL Argument Passing Routines:
;Gets a numerical argument. Returns with carry set if flonum.
GT1NUM: LDX #NARG1
JSR VPOP
GT1NMX: JSR GTNUM1 ;Alt. entry
BCC GTERR1
CMP #FLO ;(Sets carry if Flonum)
RTS
;Gets two numerical arguments. Coerces one to Real if not same type.
;Returns with carry set if Flonum results.
GT2NUM: LDX #TEMPX2
JSR VPOP
LDX #NARG1
JSR VPOP
JSR GETNUM ;GETNUM returns carry clear if argument non-numerical
BCC GTERR1
STA ANSN3 ;Save first type
JSR GTNUM2 ;Special GETNUM for NARG2
BCC GTERR2
CMP ANSN3
BNE GT2NM1
CMP #FLO ;(Sets carry if Flonum)
RTS
GT2NM1: CMP #FIX ;Assume ARG1 is the integer
BNE GT2NM2
JSR FLOTN2 ;Nope, it was NARG2, convert to flt. pt.
SEC
RTS
GT2NM2: JSR FLOTN1 ;Convert NARG1 to floating pt.
SEC
RTS
GTERR1: JMP SMAKE2 ;(ERROR XWTA,ARG1,CURTOK)
GTERR2: JMP SFPT1 ;(ERROR XWTA,ARG2,CURTOK)
;Gets a numerical argument, changes to integer if Real.
;Give an error if high bytes not zero.
GT1FIX: LDX #NARG1
JSR VPOP
JSR GETNUM
BCC GTERR1
CMP #FIX
BEQ GT1FX1
JSR XINT1
GT1FX1: LDX #NARG1
JSR CHKINT
BCS GTERR1
RTS
;Gets two numerical arguments, changes either or both to integer if Real.
;Gives an error if either arg. has high bytes non-zero.
GT2FIX: LDX #TEMPX2
JSR VPOP
LDX #NARG1
JSR VPOP
JSR GETNUM
BCC GTERR1
CMP #FIX
BEQ GT2FX1
JSR XINT1
LDX #NARG1
JSR CHKINT
BCS GTERR1
GT2FX1: JSR GTNUM2 ;Special GETNUM for NARG2
BCC GTERR2
CMP #FIX
BEQ GT2FX2
JSR XINT2
GT2FX2: LDX #NARG2
JSR CHKINT
BCS GTERR2
RTS
CHKINT: LDA $02,X
BNE CHKIN2
LDA $03,X
BNE CHKNNT
CHKIOK: CLC
RTS
CHKIN2: CMP #$FF
BNE CHKNNT
CMP $03,X
BEQ CHKIOK
CHKNNT: SEC
RTS
;GETNM2 saves NARG1 before calling GETNUM with NARG2, then restores NARG1.
GTNUM2: LDY #A3L
JSR XN1TOY ;Save NARG1
LDA TEMPX2
STA NARG2
LDA TEMPX2+1
STA NARG2+1
LDX #NARG2
JSR GETNUM
PHA ;Save type
LDY #A3L
JSR XYTON1 ;Restore NARG1
PLA ;Get type back
RTS
;Gets a numerical argument if possible. Returns with carry clear if successful.
;Returns with type of argument (Fix/Flo) in A.
;(Note: ATMTFX destroys previous values of NARG1 and NARG2. Call with NARG1 first,
; then save it, then call with NARG2, then restore NARG1.)
GTNUM1: LDX #NARG1
GETNUM: STX ANSN1 ;Address of argument
JSR GETTYP
LDX ANSN1
CMP #ATOM
BEQ ATMTXX
CMP #STRING
BEQ ATMTXX
CMP #FIX
BEQ GTNM2
CMP #FLO
BEQ GTNM2
GTNMNO: CLC ;Carry clear means argument not OK
RTS
GTNM2: PHA ;Save type
LDA $00,X
STA TEMPNH
LDA $01,X
STA TEMPNH+1
LDY #$03
GTNML: LDA (TEMPNH),Y
STA $03,X
DEX
DEY
BPL GTNML
PLA ;Retrieve type
SEC ;Carry set means argument OK
RTS
.PAGE
;Convert an atom to a Fixnum or Flonum if possible. Sets the carry
;if successful. Returns type of number (Fix/Flo) in A.
;(Note: Destroys previous values of NARG1 and NARG2.)
ATMTFX: STX ANSN1 ;ANSN1 points to argument
ATMTXX: LDY #TEMPN4 ;TEMPN4 becomes PNAME (Entry point for GETNUM)
JSR GETPNM
LDA TEMPN4+1
BEQ GTNMNO
JSR CLRNG1 ;Initialize number to 0
LDY #$01
LDA (TEMPN4),Y
STA TEMPN7+1
DEY
STY ANSN2 ;ANSN2 is SIGN
LDA (TEMPN4),Y
STA TEMPN7 ;(CAR) a pair of digits to TEMPN7
CMP #'-
BNE ATMT3
INC ANSN2 ;ANSN2 is SIGN
BNE ATMT4A ;(Always)
ATMT3: JSR GOBDIG
ATMT4: LDX TEMPN4+1
BEQ ATMT4E
ATMT4A: LDY #$02
LDA (TEMPN4),Y
TAX
INY
LDA (TEMPN4),Y
STA TEMPN4+1
STX TEMPN4 ;(CDR) PNAME to next two characters
LDA TEMPN7+1
BEQ ATMT4
JSR GOBDIG
LDX TEMPN4+1
BEQ ATMT4E
LDY #$01
LDA (TEMPN4),Y
STA TEMPN7+1
DEY
LDA (TEMPN4),Y ;(CAR) next two characters
JSR GOBDIG
JMP ATMT4
ATMT4E: JSR CNUML2
BCC NOTNM2
PHA ;Save type
LDX ANSN2
BEQ ATMT5
LDX #NARG1
TAY ;(Type of number is in A)
BNE ATMT41
JSR COMPL
JMP ATMT5
ATMT41: JSR FCOMPL
ATMT5: LDY ANSN1 ;ANSN1 is argument pointer
LDX #$FC
ATMT5L: LDA NARG1+4,X ;NARG1 is NUMBER
STA $00,Y
INY
INX
BMI ATMT5L
PLA ;Retrieve type
SEC ;Carry set means argument is a number
RTS
GOBDIG: JSR CNUML1
BCS GBDGR
NOTNM1: PLA ;Return back past ATMTFX
PLA
NOTNM2: CLC ;Carry clear means argument non-numeric
GBDGR: RTS
.PAGE
GTBOOL: STX ANSN1
JSR GETTYP
LDX ANSN1
CMP #STRING
BNE GTBOL1
LDY #TEMPX1
JSR INTERN ;Intern it if it's a String, in case it's a boolean word
LDX #TEMPX1
GTBOL1: LDA $00,X
LDY #$00
CMP LTRUE
BNE GTBL1
LDA $01,X
CMP LTRUE+1
BNE GTBL1
GTRTS: RTS
GTBL1: INY
LDA $00,X
CMP LFALSE
BNE GTBL2
LDA $01,X
CMP LFALSE+1
BEQ GTRTS
GTBL2: LDY ANSN
JSR PTRYOK
LDA #XNTF
JMP ERROR
.PAGE
MAKPNM: STY ANSN2 ;ANS
STX ANSN1 ;ARG
JSR GETTYP
LDX ANSN1
CMP #ATOM
BEQ MKPN1
CMP #SATOM
BEQ MKPN1
CMP #STRING
BEQ MKPN1
PHA ;Save type
LDA $00,X ;Assume it's a fixnum or flonum
STA TEMPN2
LDA $01,X
STA TEMPN2+1
LDX #$03
LDY #$00
MKP2L1: LDA (TEMPN2),Y
STA NARG1,Y
INY
DEX
BPL MKP2L1
PLA ;Retrieve type
TAX
LDA ANSN2
PHA ;Save ANS pointer
CPX #FIX
BEQ MKPN2
CPX #FLO
BEQ MKPN3
JMP STTLR4 ;(ERROR XWTA,CURTOK)
MKPN1: LDY ANSN2
JMP GETPNM
MKPN2: JSR CVBFIX ;Get string on PDL
JMP CNSPDL ;CONS string from PDL
MKPN3: JSR CVFLO ;Get the string on PDL
;falls through
;CONS a string from the characters on the PDL, ANSN1 holds counter, ANS on stack.
;falls in
CNSPDL: LDX #$00
STX MARK1
STX MARK1+1
LDA ANSN1
ROR A
BCC CSPD1
JSR PUSH ;If odd no. characters, push a 0 to make it even
INC ANSN1
CSPD1: JSR POPB ;Pop two characters
STA TEMPN+1
JSR POPB
STA TEMPN
LDX #MARK1
STX ANSN
LDY #TEMPN
LDA #STRING
JSR CONS ;Cons a node
DEC ANSN1
DEC ANSN1
BNE CSPD1 ;Continue if not done
PLA ;Retrieve ANS pointer
TAX
LDA MARK1
STA $00,X
LDA MARK1+1
STA $01,X
LDA #$00
STA MARK1
STA MARK1+1
RTS
.PAGE
GETPNM: STY TEMPN1+1 ;TEMPN1.H is returned PNAME pointer
STX TEMPN1 ;TEMPN1.L is ATOMM pointer
LDA $00,X
AND #$FC
STA $00,X
JSR GETTYP
LDY TEMPN1
CMP #STRING
BNE GTPNM1
STY TEMPN1+1
LDA $00,Y
TAX
AND #$FC
STA $00,Y
TXA
AND #$01
RTS
GTPNM1: LDX $00,Y
STX TEMPNH ;TEMPNH becomes ATOMM
LDX $01,Y
STX TEMPNH+1
LDY #$02
CMP #SATOM
BEQ GTPN2
GTPN1: LDA (TEMPNH),Y ;(Y is $02)
TAX
INY
LDA (TEMPNH),Y
STA TEMPNH+1
STX TEMPNH ;(CDR)
LDX TEMPN1+1 ;PNAME ptr.
DEY
LDA (TEMPNH),Y
PHA
INY
LDA (TEMPNH),Y
STA $01,X
PLA
GTPN1A: TAY ;(CDR)
AND #$FC
STA $00,X
TYA
AND #$01
RTS
GTPN2: LDA (TEMPNH),Y ;(Y is $02)
STA TEMPN ;TEMPN is INDEX
INY
LDA (TEMPNH),Y
STA TEMPN+1 ;(CDR)
LDA #$03
STA TEMPN1
LDA #$00
STA ANSN1 ;Character counter
GTPNW: LDY TEMPN1
LDA (TEMPN),Y ;Gets INDEX + 3 (SA_PNAME)
BEQ GTPNWE
TAX
JSR PUSH
INC ANSN1
INC TEMPN1
BNE GTPNW ;(Always)
GTPNWE: LDA TEMPN1+1 ;ANS pointer
PHA
JSR CNSPDL
LDA #$00 ;No Funny-pname SATOMs
RTS
;Converts a two-byte fixnum to a string on the PDL
CVFIX: LDA $00,X
STA NARG1
LDA $01,X
STA NARG1+1 ;NARG1 is the number to type
LDA #$00
STA ANSN1 ;Character counter
CVFIXX: STA NARG1+2 ;(Alternate entry point)
STA NARG1+3
BEQ CVFX2 ;(Always)
;Get 4-byte fixnum in NARG1 to string on PDL
CVBFIX: LDA #$00
STA ANSN1 ;Character counter
LDA NARG1+3
BPL CVFX1
LDX #NARG1
JSR COMPL
LDX #'-
JSR PUSH
INC ANSN1
CVFX1: LDA #$00
CVFX2: STA ANSN ;ANSN is digit counter
CVBNMR: JSR XDVD10 ;Divide NARG1 by ten and get remainder
PHA ;Push remainder digit
INC ANSN ;Increment digit counter
LDX #$03
CVBL1: LDA NARG1,X
BNE CVBNMR
DEX
BPL CVBL1
CVBNMF: PLA ;Pop a digit
TAX
JSR PUSH ;Push it
INC ANSN1
DEC ANSN
BNE CVBNMF
RTS
;Converts flonum NARG1 to characters on PDL
CVFLO: LDA ANSNX
PHA
LDA #$00
STA ANSN1 ;Counts number of characters pushed
STA ANSN2 ;ODE
LDX #$03
TPFLL1: LDA NARG1,X
BNE TPFL1
DEX
BPL TPFLL1
INC ANSN1
LDX #'0 ;If NARG1 = 0, push "0." and return
JSR PUSH
INC ANSN1
LDX #'.
JSR PUSH
PLA
STA ANSNX
RTS
TPFL1: LDA NARG1+1
BPL TPFL2 ;If NARG1 negative, invert and push "-"
JSR FCOMPL
INC ANSN1
LDX #'-
JSR PUSH
TPFL2: LDA NARG1 ;Now get 1 <= NARG1 < 10
BPL TPFLS1 ;Exponent too small, so multiply number
CMP #$84
BCS TPFLG1 ;Exponent greater than 3, so too big
CMP #$83
BNE GINTP1 ;Ok if 0,1, or 2
LDA NARG1+1 ;Else if 3,
CMP #$50 ;Make sure X < 10 (01.01 0000 Bin)
BCC GINTP1
TPFLG1: LDY #A1L
JSR XN1TOY ;Save NARG1, so it's now XNUM
TPFLL2: JSR FDVD10 ;So divide by 10
INC ANSN2 ;Increment ODE
LDA NARG1
CMP #$84
BCS TPFLL2
CMP #$83
BNE GINTP2
LDA NARG1+1
CMP #$50
BCS TPFLL2
BCC GINTP2
TPFLS1: JSR MULN10 ;NARG1 too small, so multiply by 10
DEC ANSN2 ;Decrement ODE
LDA NARG1
BPL TPFLS1
GINTP1: LDY #A1L
JSR XN1TOY
GINTP2: JSR GETINT
LDY #A1L
JSR XYTON1
LDA ANSN2
STA ANSNX ;NDE
BPL TPFLG2
CMP #$FF
BCC TPFLF1 ;NARG1 < 0.1, use floating pt. format (N)
;falls through
;falls in
TPFLR: STA ANSN3 ;Counter for Exp+1 iterations
INC ANSN3
BEQ TPFLR1
TPFLL5: JSR GTDECH
DEC ANSN3
BNE TPFLL5
TPFLR1: LDX #'.
JSR PUSH ;Push decimal pt.
INC ANSN1
SEC
LDA #$06
SBC ANSN2
STA ANSN3 ;Counter for 6-Exp iterations
BEQ POPTZS
TPFLL6: JSR GTDECH
DEC ANSN3
BNE TPFLL6
POPTZS: JSR POPB ;Pop all trailing zeroes
DEC ANSN1
CMP #'0
BEQ POPTZS
TAX
INC ANSN1
JSR PUSH ;Done
PLA
STA ANSNX
RTS
TPFLG2: CMP #$07
BCC TPFLR ;NARG1 < 10000000, use regular format
TPFLF1: JSR GTDECH ;Floating pt. format, call Get-Decimal-Char for digit
LDX #'.
JSR PUSH ;Push a "."
INC ANSN1
LDA #$06 ;Counter for six iterations
STA ANSN3
TPFLL3: JSR GTDECH ;Get another decimal digit
DEC ANSN3
BNE TPFLL3
JSR POPTZS ;Pop all trailing zeros
LDA ANSN2
BPL TPFLEP
EOR #$FF ;If Exp negative, invert
STA ANSN2
INC ANSN2 ;(Complement and increment)
LDX #'N ;and push "N"
BNE TPFLEX ;(Always)
TPFLEP: LDX #'E ;Exp positive, push "E"
TPFLEX: JSR PUSH
INC ANSN1
LDA ANSN2
STA NARG1
LDA #$00
STA NARG1+1
JSR CVFIXX ;Routine converts (2-byte) ARG1 into string on PDL
PLA
STA ANSNX
RTS
GETINT: LDA #$00 ;Gets the integer part of NARG1
STA TEMPN1 ;INTP
GETL1: LDA NARG1
BEQ GTDR
CMP #$80 ;Done if Binary-exp is 0
BEQ GTD1
ASL NARG1+1 ;Rotate NARG1 mantissa into TEMPN1
ROL TEMPN1
DEC NARG1 ;Decrement Binary-exp
BNE GETL1 ;(Always)
GTD1: ASL NARG1+1
ROL TEMPN1 ;Shift two more bits into TEMPN1
ASL NARG1+1
ROL TEMPN1
GTDR: RTS
;Gets the most significant decimal digit of NARG1, then positions it for next one.
GTDECH: CLC
LDA TEMPN1
ADC #'0
TAX
JSR PUSH
INC ANSN1
LDA ANSNX
BMI GTDC1
BEQ GTDC1
STA TEMPN1+1
LDY #A1L
JSR XN1TOY
LDA TEMPN1
STA NARG1
LDA #$00
STA NARG1+1
STA NARG1+2
STA NARG1+3
JSR FLOTN1
GTDL1: JSR MULN10
DEC TEMPN1+1
BNE GTDL1
LDY #A1L
JSR XYTON2
JSR FSUBX
LDY #A1L
JSR XN1TOY
DEC ANSNX
BEQ GTDL3E
LDA ANSNX
STA TEMPN1+1
GTDL3: JSR FDVD10
DEC TEMPN1+1
BNE GTDL3
GTDL3E: JSR GETINT
LDY #A1L
JMP XYTON1
GTDC1: LDA TEMPN1
STA NARG2
LDA #$00
STA NARG2+1
STA NARG2+2
STA NARG2+3
JSR FLOTN2
JSR FSUB
JSR MULN10
LDY #A1L
JSR XN1TOY
JSR GETINT
LDY #A1L
JMP XYTON1
;Execution diagram, flonum-to-string conversion:
;ODE := 0
;IF NUM <= 1 THEN DO NUM := NUM * 10, ODE := ODE - 1, UNTIL NUM >= 1, INTP = INT(NUM)
; ELSE IF NUM >= 10 THEN XNUM := NUM, DO XNUM := XNUM / 10, ODE := ODE + 1, UNTIL XNUM < 10,
; INTP := INT(XNUM)
;NDE := ODE
;IF ODE > 6 OR ODE < -1 THEN GET-DIG, PUSH("."), REPEAT 6 GET-DIG, POP-TZS, PR-EXP
; ELSE REPEAT ODE+1 GET-DIG, PUSH("."), REPEAT 6-ODE GET-DIG, POP-TZS
;
;GET-DIG:
; PUSH(INTP)
; IF NDE > 0 THEN REPEAT NDE INTP := INTP * 10, NDE := NDE - 1,
; NUM := NUM - INTP, XNUM := NUM, REPEAT NDE XNUM := XNUM / 10,
; INTP := INT(XNUM)
; ELSE NUM := NUM - INTP, NUM := NUM * 10, INTP := INT(NUM)
.PAGE
OTPFX1: LDA #TEMPN ;Output a two-byte fixnum value (Y is ptr.)
STA ANSN
LDX #$00
LDA #FIX
JSR CONS
LDX #TEMPN
JSR VPUSHP
INC OTPUTN
JMP POPJ
OTPFL1: LDY #NARG1
OTPFLO: LDA #FLO
BNE OTPNUM ;(Always)
OTPFIX: LDA $03,X
CMP #$80
BNE OTPFXA
LDA $02,X
BNE OTPFXA
LDA $01,X
BNE OTPFXA
LDA $00,X
BNE OTPFXA
JMP ROFLOW ;Attempted to output -2^15, so Overflow Error
OTPFXA: LDA #FIX
OTPNUM: PHA ;Save type
LDA #TEMPN ;Entered with type (Fix/Flo) in A
STA ANSN
TYA
TAX
INX
INX
PLA ;Retrieve type
JSR CONS
LDX #TEMPN
JSR VPUSHP
INC OTPUTN
JMP POPJ
.PAGE
.SBTTL System Functions
; Arithmetic Functions:
SUNDIF: LDA INFDIF
STA CURTOK ;(For possible error message in GT1NUM)
LDA INFDIF+1
STA CURTOK+1
JSR GT1NUM
BCS SNDIF2
LDX #NARG1
JSR COMPL
LDY #NARG1
JMP OTPFIX
SNDIF2: JSR FCOMPL ;Complements flonum in NARG1.
JMP OTPFL1
SSUM: JSR GT2NUM
BCS SSUMF
LDA NARG1+3
STA TEMPN1
CLC
LDX #$FC
SSMLP1: LDA NARG1+4,X
ADC NARG2+4,X
STA NARG1+4,X
INX
BMI SSMLP1
LDA NARG2+3
EOR TEMPN1
BMI SSUMOK ;Different signs, never an overflow
LDA NARG1+3
EOR NARG2+3
BPL SSUMOK ;Overflow if result not same sign as one argument
ROFLOW: LDA #XOFLOW
JMP ERROR
SSUMF: JSR FADD ;Floating pt. addition
BCS ROFLOW
JMP OTPFL1
SSUMOK: LDY #NARG1
JMP OTPFIX
SDIF: JSR GT2NUM
BCS SDIFF
LDA NARG1+3
STA TEMPN1
SEC
LDX #$FC
SDIFL1: LDA NARG1+4,X
SBC NARG2+4,X
STA NARG1+4,X
INX
BMI SDIFL1
LDA TEMPN1
EOR NARG2+3
BPL SSUMOK ;Same signs, never an overflow
LDA NARG1+3
EOR TEMPN1
BMI ROFLOW ;Different signs, overflow
BPL SSUMOK ;(Always)
SDIFF: JSR FSUB ;Floating pt. subtraction
BCS ROFLOW
JMP OTPFL1
.PAGE
SPROD: JSR GT2NUM
BCS SPRODF
LDA NARG1+3
EOR NARG2+3
STA ANSN
LDA NARG1+3
BPL SPRD1
LDX #NARG1
JSR COMPL
SPRD1: LDA NARG2+3
BPL SPRD2
LDX #NARG2
JSR COMPL
SPRD2: LDA #$00
LDX #$03
SPRDL1: STA TEMPN,X
DEX
BPL SPRDL1
LDY #$20 ;Bit counter
MUL2: LSR NARG2+3
ROR NARG2+2
ROR NARG2+1
ROR NARG2
BCC MUL4
CLC
LDX #$FC
SPRDL2: LDA TEMPN+4,X ;Add multiplicand (NARG1) to partial product (TEMPN, TEMPN1)
ADC NARG1+4,X
STA TEMPN+4,X
INX
BMI SPRDL2
TAX
BMI SPRODR
MUL4: ASL NARG1
ROL NARG1+1
ROL NARG1+2
ROL NARG1+3
BPL MUL4A
LDX #$03 ;Sig. bit dropped from NARG1, so bit counter better be 0
MUL4B: LDA NARG2,X
BNE SPRODR ;It isn't, error
DEX
BPL MUL4B
BMI MUL4C ;(Always) It is, so we're done
MUL4A: DEY
BNE MUL2 ;Next bit
MUL4C: LDA ANSN
BPL MULEND
LDX #TEMPN
JSR COMPL
MULEND: LDY #TEMPN
JMP OTPFIX
SPRODF: JSR FMUL ;Floating pt. multiply
BCS SPRODR
JMP OTPFL1
SPRODR: JMP ROFLOW
.PAGE
SDIVID: JSR GT2NUM
BCS SDIVF
LDX #$03
SDVLP1: LDA NARG2,X
BNE SDVD1
DEX
BPL SDVLP1
LDA #XDBZ
JMP ERROR
SDIVF: JSR FDIV ;Floating pt. divide
BCS SPRODR
JMP OTPFL1
SDVD1: LDX #$03
SDVLP2: LDA NARG1,X
BNE SDVD1A
DEX
BPL SDVLP2
LDY #NARG1
JMP OTPFIX ;Answer is zero if numerator is zero
SDVD1A: LDA #$00
STA ANSN ;SIGN
LDA NARG1+3
BPL SDVD2
LDX #NARG1
JSR COMPL
INC ANSN
SDVD2: LDA NARG2+3
BPL SDVD3
LDX #NARG2
JSR COMPL
LDA ANSN
EOR #$01
STA ANSN
SDVD3: JSR XDIVID ;NARG2 is divisor, NARG1 is dividend, then quotient
LDA ANSN
BEQ SDVD4
LDX #NARG1
JSR COMPL
SDVD4: LDY #NARG1
JMP OTPFIX
SUNSUM: LDA INFSUM
STA CURTOK ;(For possible error message in GT1NUM)
LDA INFSUM+1
STA CURTOK+1
JSR GT1NUM
BCS SNSM1
LDY #NARG1
JMP OTPFIX
SNSM1: JMP OTPFL1
SINT: JSR GT1NUM
BCC SINT1
JSR XINT1
SINT1: LDY #NARG1
JMP OTPFIX
.PAGE
; Boolean Functions:
SGRTR: JSR GT2NUM
SGRTRX: BCS SGRTRF
SGRTR1: LDA NARG1+3
BMI SGRTRM
LDA NARG2+3
BMI JTRU ;POS > NEG
SGRTRP: LDX #$03
SGRLP1: LDA NARG2,X
CMP NARG1,X
BCC JTRU
BNE JFLS
DEX
BPL SGRLP1
JFLS: JMP VPLFLS
SGRTRM: LDA NARG2+3
BPL JFLS ;NEG not > POS
AND #$7F ;Both negative, strip sign bit and compare
STA NARG2+3
LDA NARG1+3
AND #$7F
STA NARG1+3
JMP SGRTRP
JTRU: JMP VPLTRU
SGRTRF: LDA NARG1+1
BMI SGRTFM
LDA NARG2+1
BMI JTRU ;POS > NEG
BPL SGRTF1
SGRTFM: LDA NARG2+1
BPL JFLS ;NEG not > POS
SGRTF1: JSR FSUBX ;Both same sign - subtract NARG1 from NARG2
LDA NARG1+1 ;If NARG1 negative, then it was larger
BMI JTRU
BPL JFLS
SLESS: JSR GT2NUM
JSR SWAP ;Switch the args and call S_GREATER
JMP SGRTRX
SNOT: LDX #ARG1
JSR VPOP
JSR GTBOOL
TYA
BNE VPLTRU
JMP VPLFLS
.PAGE
SBOTH: LDX #ARG2
JSR VPOP
LDX #ARG1
JSR VPOP
JSR GTBOOL
STY ANSNX
LDX #ARG2
JSR GTBOOL
TYA
BNE VPLFLS
LDA ANSNX
BNE VPLFLS
JMP VPLTRU
SEITHR: LDX #ARG2
JSR VPOP
LDX #ARG1
JSR VPOP
JSR GTBOOL
STY ANSNX
LDX #ARG2
JSR GTBOOL
TYA
BEQ VPLTRU
LDA ANSNX
BNE VPLFLS
;falls through
;falls in
VPLTRU: LDX #LTRUE
JSR VPUSHP
INC OTPUTN
JMP POPJ
VPLFLS: LDX #LFALSE
JSR VPUSHP
INC OTPUTN
JMP POPJ
.PAGE
SFPUT: LDX #ARG2
JSR VPOP
LDX #ARG1
JSR VPOP
LDX #ARG2
JSR GETTYP
CMP #LIST
BNE SFPT1
LDX #ARG1
JSR GETTYP
LDY #ARG1
CMP #STRING
BNE SFPT2
LDX #ARG1
LDY #TEMPX1
JSR INTERN ;If String, intern before FPUTting
LDY #TEMPX1
SFPT2: LDX #ARG2
STY ANSN
JSR CONS
JMP OTPRG1
SFPT1: LDX #ARG2
LDY #CURTOK
LDA #XWTA
JMP ERROR
.PAGE
SLPUT: LDX #ARG2
JSR VPOP
LDX #ARG1
JSR VPOP
LDX #ARG2
JSR GETTYP
CMP #LIST
BNE SFPT1
SLPUT1: LDA ARG2+1
BNE SLPUT2
LDX #ARG1
JSR GETTYP
LDY #ARG1
CMP #STRING
BNE SLPT1A
LDX #ARG1
LDY #TEMPX1
JSR INTERN ;Intern it if it's a String
LDY #TEMPX1
SLPT1A: STY ANSN
TYA
LDX #$00
TXA ;(Type LIST)
JSR CONS
JMP OTPRG1
SLPUT2: LDA ARG1
STA MARK2 ;Protect the last element
LDA ARG1+1
STA MARK2+1
LDA ARG2
STA MARK3 ;Protect the original list (or what's left of it)
LDA ARG2+1
STA MARK3+1
LDY #$00
LDA (MARK3),Y
STA TEMPN1
INY
LDA (MARK3),Y
STA TEMPN1+1 ;(CAR) First element
INY
LDA (MARK3),Y
TAX
INY
LDA (MARK3),Y
STA MARK3+1
STX MARK3 ;(CDR)
LDA #MARK1 ;Pointer to start of new list
STA ANSN
LDX #$00
TXA
LDY #TEMPN1
JSR CONS
LDA MARK1
STA TEMPN2 ;Pointer to newest node
LDA MARK1+1
STA TEMPN2+1
SLPTW: LDA MARK3+1 ;Make a new list, element by element
BEQ SLPT2
LDY #$00
LDA (MARK3),Y
STA TEMPN1 ;Get an element
INY
LDA (MARK3),Y
STA TEMPN1+1 ;(CAR)
INY
LDA (MARK3),Y
TAX
INY
LDA (MARK3),Y
STA MARK3+1
STX MARK3 ;(CDR) Advance element pointer
LDA #TEMPN ;New pointer to newest node
STA ANSN
LDX #$00
TXA ;(Type LIST)
LDY #TEMPN1
JSR CONS
LDY #$02
LDA TEMPN
STA (TEMPN2),Y ;Pointer to last node
TAX
INY
LDA TEMPN+1
STA (TEMPN2),Y ;(CDR) Link new node onto list
STA TEMPN2+1
STX TEMPN2
JMP SLPTW
SLPT2: LDX #ARG1
JSR GETTYP
LDY #ARG1
CMP #STRING
BNE SLPT2A
LDX #ARG1
LDY #TEMPX1
JSR INTERN ;Intern it if it's a string
LDY #TEMPX1
SLPT2A: LDA #TEMPN
STA ANSN
LDX #$00
TXA ;(Type LIST)
JSR CONS ;Get a pointer to first argument
LDY #$02
LDA TEMPN
STA (TEMPN2),Y
INY
LDA TEMPN+1
STA (TEMPN2),Y ;(RPLACD) Link final node on
JMP SSN2 ;MARK1 points to our new list
.PAGE
SSNTNC: LDA #$00
STA MARK1
STA MARK1+1
LDA NARGS
BPL SSN1
EOR #$FF ;NARGS := - NARGS - 1
STA NARGS
SSNW: LDA NARGS
SSN1: BNE SSNWA
SSN2: LDA MARK1
STA ARG1
LDA MARK1+1
STA ARG1+1
LDA #$00
JSR CLMK3
JMP OTPRG1
SSNWA: LDX #MARK2
JSR VPOP
JSR GETTYP
CMP #LIST
BEQ SSNW1
LDY #MARK2
CMP #STRING
BNE SSNWA1
LDX #MARK2
LDY #TEMPX1
JSR INTERN ;Intern it if it's a String
LDY #TEMPX1
SSNWA1: LDX #MARK1
STX ANSN
LDA #LIST
JSR CONS
JMP SSNW2
SSNW1: LDA VSP
STA TEMPN1
LDA VSP+1
STA TEMPN1+1
LDA #SSNERR&$FF
STA ERRRET
LDA #SSNERR^
STA ERRRET+1
TSX
STX RETADR ;Save all necessary return addresses
SSNX: LDA MARK2+1
BEQ SSNY
LDY #$00
LDA (MARK2),Y
STA MARK3
INY
LDA (MARK2),Y
STA MARK3+1 ;(CAR)
INY
LDA (MARK2),Y
TAX
INY
LDA (MARK2),Y
STA MARK2+1
STX MARK2 ;(CDR)
LDX #MARK3
JSR VPUSHP
JMP SSNX
SSNY: LDA TEMPN1
CMP VSP
BNE SSNY1
LDA TEMPN1+1
CMP VSP+1
BEQ SSNW2
SSNY1: LDX #MARK3
JSR VPOP
LDX #MARK1
STX ANSN
LDY #MARK3
LDA #LIST
JSR CONS
JMP SSNY
SSNERR: LDA TEMPN1
STA VSP
LDA TEMPN1+1
STA VSP+1
JMP ERROR1
SSNW2: DEC NARGS
JMP SSNW
.PAGE
; Miscellaneous Functions:
SMAKE: LDX #ARG2
JSR VPOP
LDX #ARG1
JSR VPOP
JSR GETTYP
LDY #ARG1
CMP #ATOM
BEQ SMAKE1
CMP #SATOM
BEQ SMAKE2
CMP #STRING
BNE SMAKE2
LDX #ARG1
LDY #TEMPX1
JSR INTERN ;Intern the Name if it's a string
LDY #TEMPX1
SMAKE1: LDX #ARG2
JSR PUTVAL
JMP POPJ
SMAKE2: LDX #ARG1
LDY #CURTOK
LDA #XWTA
JMP ERROR
SOUTPT: LDA LEVNUM
BNE SOTPT2
LDA LEVNUM+1
BEQ SOTPT1
SOTPT2: LDA #$01
STA STPFLG
STA OTPUTN
JMP POPJ
SOTPT1: LDY #CURTOK
LDA #XNTL
JMP ERROR
.PAGE
SSTOP: LDA LEVNUM
BNE SSTOP1
LDA LEVNUM+1
BEQ SOTPT1
SSTOP1: LDA #$01
STA STPFLG
JMP POPJ
SCOMMT: LDA #$00
STA TOKPTR
STA TOKPTR+1
LDA EXPOUT
BNE SCMMT1
JMP POPJ
SCMMT1: LDA #XEOL
JMP ERROR
SCNTIN: LDA #$01
STA STPFLG
STA DCOFLG
JMP POPJ
.PAGE
SIF: INC IFLEVL
BNE SIFA
INC IFLEVL+1
BNE SIFA
JMP EXCED
SIFA: JSR GTNXTK
LDA NEXTOK
CMP LTHEN
BNE SIF1
LDA NEXTOK+1
CMP LTHEN+1
BNE SIF1
LDX #TOKPTR
JSR TTKADV
SIF1: LDX #ARG1
JSR VPOP
JSR GTBOOL
CPY #$00
BNE SIF2
SIF3A: JMP POPJ
SIF2: LDX #NEXTOK
JSR EXIFSC
LDA TOKPTR
BNE SIF3
LDA TOKPTR+1
BEQ SIF3A
SIF3: LDA NEXTOK
CMP LELSE
BNE SIF3A
LDA NEXTOK+1
CMP LELSE+1
BNE SIF3A
LDX #TOKPTR
JSR TTKADV
JMP POPJ
.PAGE
SELSE: SEC
LDA IFLEVL
SBC #$01
STA IFLEVL
LDA IFLEVL+1
SBC #$00
STA IFLEVL+1
BCC SELSE1
LDA IFLEVL
BNE SELSE2
LDA IFLEVL+1
BNE SELSE2
STA TOKPTR
STA TOKPTR+1
JMP POPJ
SELSE2: LDX #TEMPN2
JSR EXIFSC
JMP POPJ
SELSE1: LDA #XELS
JMP ERROR
.PAGE
SGO: JSR STPPEK
LDX #ARG1
JSR VPOP
JSR GETTYP
CMP #ATOM
BEQ SGO1
CMP #SATOM
BEQ SGO1
JMP SRUN1
SGO1: LDA #LATOM
LDX #ARG1
JSR PUTTYP
LDA FBODY
STA GOPTR
LDA FBODY+1
STA GOPTR+1
LDX #GOPTR
JSR ULNADV
SGOW: LDA GOPTR
BNE SGOW1
LDA GOPTR+1
BEQ SGOR
SGOW1: LDX #TEMPN1
LDY #GOPTR
JSR GTTULN
LDY #$00
LDA (TEMPN1),Y
STA TEMPN
INY
LDA (TEMPN1),Y
STA TEMPN+1 ;(GETTOK)
LDX #TEMPN1
JSR TTKADV
LDY #$00
LDA (TEMPN1),Y
TAX
INY
LDA (TEMPN1),Y
STA TEMPN1+1
STX TEMPN1 ;(GETTOK)
LDA ARG1
CMP TEMPN1
BNE SGOW2
LDA ARG1+1
CMP TEMPN1+1
BEQ SGOE1
SGOW2: LDX #GOPTR
JSR ULNADV
JMP SGOW
SGOE1: LDA TEMPN
STA LINNUM
LDA TEMPN+1
STA LINNUM+1
JMP POPJ
SGOR: LDY #ARG1
LDA #XLNF
JMP ERROR
.PAGE
SRPEAT: LDX #ARG2
JSR VPOP
JSR GT1FIX
LDA ARG1+1
BMI SRUN1
JSR SWAP ;Swap ARG1 and ARG2
LDX #ARG1
JSR GETTYP
CMP #LIST
BNE SRUN1
SRPLOP: LDA ARG2
BNE SRPLP1
LDA ARG2+1
BNE SRPLP1
JMP POPJ
SRPLP1: SEC
LDA ARG2
SBC #$01
STA ARG2
BCS SRPLP2
DEC ARG2+1
SRPLP2: JSR STPPEK
LDX #ARG2
JSR PUSHP
LDX #ARG1
JSR PUSHP
LDX #SREPT1&$FF
LDY #SREPT1^
JSR PUSH
JMP RUNHAN
SREPT1: LDX #ARG1
JSR POP
LDX #ARG2
JSR POP
JMP SRPLOP
.PAGE
SRUN: JSR STPPEK
LDX #ARG1
JSR VPOP
JSR GETTYP
CMP #LIST
BNE SRUN1
JMP RUNHAN
SRUN1: JMP SMAKE2 ;(ERROR XWTA,ARG1,CURTOK)
STHING: LDX #ARG2
JSR VPOP
JSR GETTYP
LDY #ARG2
CMP #ATOM
BEQ STH1
CMP #SATOM
BEQ STH1
CMP #STRING
BNE STH2
LDX #ARG2
LDY #TEMPX1
JSR INTERN ;Intern the Name if it's a string
LDY #TEMPX1
STH1: LDX #ARG1
JSR GETVAL
LDA ARG1+1
BNE OTPRG1
LDA ARG1
BEQ OTPRG1
LDY #ARG2
LDA #XHNV
JMP ERROR
STH2: LDX #ARG2
JMP STLR4A
OTPRG1: INC OTPUTN
LDX #ARG1
JSR VPUSHP
JMP POPJ
SPTHNG: LDX #ARG2
JSR VPOP
JSR GETTYP
CMP #ATOM
BEQ SPTH1
CMP #SATOM
BEQ SPTH1
SPTH2: JMP VPLFLS
SPTH1: LDX #ARG1
LDY #ARG2
JSR GETVAL
LDA ARG1+1
BNE SPTH3
LDA ARG1
BNE SPTH2
SPTH3: JMP VPLTRU
.PAGE
SPWRDP: LDX #ARG1
JSR VPOP
JSR GETTYP
CMP #ATOM
BEQ SPTH3
CMP #SATOM
BEQ SPTH3
CMP #FIX
BEQ SPTH3
CMP #FLO
BEQ SPTH3
JMP VPLFLS
SNODES: SEC
LDA #TYPLEN&$FF
SBC NNODES
STA TEMPN1
LDA #TYPLEN^
SBC NNODES+1
STA TEMPN1+1
LDY #TEMPN1
JMP OTPFX1
SREQU: LDA #RPRMPT
JSR TPCHR
LDX #ILINE
JSR VPUSHP ;Save ILINE
LDX #ILINE
JSR READLN
TYA
BEQ SREQU1 ;Y zero means OK
JMP ERROR1
SREQU1: LDA ILINE ;Restore ILINE
STA ARG1
LDA ILINE+1
STA ARG1+1
LDX #ILINE
JSR VPOP
JMP OTPRG1
SGCOLL: JSR GARCOL
SGCE: JMP POPJ
.PAGE
SRETRV: LDA INDEV
BNE SRTRE
LDA ENDBUF
CMP #EDBUF&$FF
BNE SCHG1
LDA ENDBUF+1
CMP #EDBUF^
BEQ SGCE ;Buffer never used, so ignore
SCHG1: LDA #BUFFER
STA INDEV
JSR CHGX1
JMP CHGIN3
SRTRE: LDA #XEDT
JMP ERROR
SCHNGE: LDA GRPHCS
BEQ SCHNG2
JSR RESETT ;Nodisplay, get the text page back
LDX #SCS&$FF
LDY #SCS^
JSR PUSH ;So we return to graphics mode when done
SCHNG2: JMP CHGSTP ;get arg to CHG
.PAGE
STITLE: LDA EDSW
BEQ STTLR1
LDA LEVNUM
BNE STTLR2
LDA LEVNUM+1
BNE STTLR2
LDA TOKPTR+1
BNE STTL1
JMP POPJ
STTLR1: LDA #XNED
JMP ERROR
STTLR2: LDA #XETL
JMP ERROR
STTLR3: LDY #TEMPN3
JSR PTRYOK
LDA #XUBL
JMP ERROR
STTLR4: JSR PTRXOK
STLR4A: LDY #CURTOK
LDA #XWTA
JMP ERROR
STTL1: LDY #$00
LDA (TOKPTR),Y
STA TEMPN3 ;(ATOMM)
INY
LDA (TOKPTR),Y
STA TEMPN3+1 ;(CAR)
INY
LDA (TOKPTR),Y
TAX
INY
LDA (TOKPTR),Y
STA TOKPTR+1
STA TEMPN1+1 ;(ARGLIST)
STX TOKPTR ;(CDR)
STX TEMPN1
LDX #TEMPN3
JSR GETTYP
CMP #SATOM
BEQ STTLR3
CMP #ATOM
BNE STTLR4
LDA TEMPN3
CMP EDTATM
BNE STTL2
LDA TEMPN3+1
CMP EDTATM+1
BEQ STTL3
STTL2: LDX #EDTATM
LDA #TEMPN2 ;(FUN)
JSR GETFUN
LDX #EDTATM
JSR UNFUNC
LDA TEMPN3
STA EDTATM
STA PODEFL
LDA TEMPN3+1
STA EDTATM+1
STA PODEFL+1
LDY #TEMPN2
LDX #EDTATM
JSR PUTFUN
STTL3: LDA #$00
STA ANSN1
STTLW: LDA TOKPTR+1
BEQ STTLWE
LDY #$00
LDA (TOKPTR),Y
STA TEMPN
INY
LDA (TOKPTR),Y
STA TEMPN+1 ;(CAR)
INY
LDA (TOKPTR),Y
TAX
INY
LDA (TOKPTR),Y
STA TOKPTR+1
STX TOKPTR ;(CDR)
LDA TEMPN
CMP COMMNT
BNE STTLW2
LDA TEMPN+1
CMP COMMNT+1
BEQ STTLW
STTLW2: LDX #TEMPN
JSR GETTYP
CMP #ATOM
BEQ STTLW3
CMP #SATOM
BEQ STTLW3
LDX #TEMPN
JMP STTLR4
STTLW3: INC ANSN1
JMP STTLW
STTLWE: LDY #$00
STY TOKPTR
STY TOKPTR+1
LDA TEMPN1
STA (EDBOD),Y
INY
LDA TEMPN1+1
STA (EDBOD),Y ;(RPLACA)
LDX #EDTATM
LDA #TEMPN1
JSR GETFUN
LDY #$04
LDA ANSN1
STA (TEMPN1),Y ;(PUTNGS)
SERR4: JMP POPJ
.PAGE
SPRINT: JSR SPRNT
JSR BREAK1
JMP POPJ
STYPE: JSR SPRNT
JMP POPJ
.PAGE
SDEFIN: LDX #ARG2
JSR VPOP
LDX #ARG1
JSR VPOP
JSR GETTYP
CMP #ATOM
BNE SDFNR1
LDX #ARG2
JSR GETTYP
CMP #LIST
BNE SDFNR2
LDY #$00
LDA (ARG2),Y
STA TEMPN
INY
LDA (ARG2),Y
STA TEMPN+1 ;(CAR)
LDX #TEMPN
JSR GETTYP
CMP #LIST
BNE SDFNR2
LDY #ARG1
LDA ARG2+1
BNE DEFUN1
LDX ARG2
JSR UNFUNC
JMP POPJ
SDFNR1: JMP SMAKE2
SDFNR2: JMP SFPT1
DEFUN1: JSR VPUSHP
LDA #LININC
STA TEMPN4 ;TEMPN4 is NUMBER
LDA #$00
STA TEMPN4+1
LDA VSP
STA TEMPN1 ;TEMPN1 is PTR
LDA VSP+1
STA TEMPN1+1
LDA ARG2
STA TEMPN
LDA ARG2+1
STA TEMPN+1
LDY #$00
LDA (TEMPN),Y
STA TEMPN2
INY
LDA (TEMPN),Y
STA TEMPN2+1 ;(CAR)
LDX #TEMPN2
JSR VPUSHP
LDY #$02
LDA (TEMPN),Y
STA TEMPN2 ;TEMPN2 is TLIST
INY
LDA (TEMPN),Y
STA TEMPN2+1 ;(CDR)
DEFUNW: LDA TEMPN2+1
BEQ DEFNWE
LDY #$00
LDA (TEMPN2),Y
STA TEMPN3 ;TEMPN3 is T1
INY
LDA (TEMPN2),Y
STA TEMPN3+1 ;(CAR)
LDX #TEMPN3
JSR GETTYP
CMP #LIST
BNE DEFNER
LDX #TEMPN3
STX ANSN
LDY #TEMPN4
LDA #FLIST
JSR CONS
LDX #TEMPN3
JSR VPUSHP
LDY #$02
LDA (TEMPN2),Y
TAX
INY
LDA (TEMPN2),Y
STA TEMPN2+1
STX TEMPN2 ;(CDR)
CLC
LDA TEMPN4
ADC #LININC
STA TEMPN4
BCC DEFUNW
INC TEMPN4+1
BPL DEFUNW
JMP EDLERR
DEFNWE: LDA #$00
STA ARG2
STA ARG2+1
DEFUNX: LDA TEMPN1
CMP VSP
BNE DEFNX1
LDA TEMPN1+1
CMP VSP+1
BEQ DEFNXE
DEFNX1: LDX #TEMPN3
JSR VPOP
LDX #ARG2
STX ANSN
LDY #TEMPN3
LDA #LIST
JSR CONS
JMP DEFUNX
DEFNXE: LDX #ARG2
LDA #ARG1
JSR STUFF
JMP POPJ
DEFNER: LDX #ARG2
JMP STTLR4 ;(ERROR XWTA,CURTOK)
.PAGE
STEXT: LDX #ARG1
JSR VPOP
JSR GETTYP
CMP #ATOM
BNE STEXTR
LDX #ARG1
LDA #TEMPN5 ;FUN is TEMPN5
JSR GETFUN
LDA TEMPN5+1
BNE STEXT1
STA TEMPN6 ;BODY is TEMPN6
STA TEMPN6+1
JMP STEXT3
STEXTR: JMP SMAKE2
STEXT1: LDY #$02
LDA (TEMPN5),Y
STA TEMPN6
INY
LDA (TEMPN5),Y
STA TEMPN6+1 ;(CDR)
LDX #TEMPN6
JSR GETTYP
CMP #LIST
BEQ STXT1A
STXT1B: LDY #TEMPN6
LDX #TEMPN5
LDA #$01
JSR UNSTUF
JMP STEXT3
STXT1A: LDA TEMPN6
STA TEMPN5
LDA TEMPN6+1
STA TEMPN5+1
LDA VSP
STA TEMPN1 ;TEMPN1 is STACK
LDA VSP+1
STA TEMPN1+1
LDY #$00
LDA (TEMPN5),Y
STA TEMPN2 ;TEMPN2 is LINE
INY
LDA (TEMPN5),Y
STA TEMPN2+1 ;(CAR)
INY
LDA (TEMPN5),Y
TAX
INY
LDA (TEMPN5),Y
STA TEMPN5+1
STX TEMPN5 ;(CDR)
LDX #TEMPN2
JSR VPUSHP
STXTW: LDA TEMPN5+1
BEQ STXTWE
LDY #$00
LDA (TEMPN5),Y
STA TEMPN2
INY
LDA (TEMPN5),Y
STA TEMPN2+1 ;(CAR)
INY
LDA (TEMPN5),Y
TAX
INY
LDA (TEMPN5),Y
STA TEMPN5+1
STX TEMPN5 ;(CDR)
DEY
LDA (TEMPN2),Y
TAX
INY
LDA (TEMPN2),Y
STA TEMPN2+1
STX TEMPN2 ;(CDR)
LDX #TEMPN2
JSR VPUSHP
JMP STXTW
STXTWE: LDA #$00
STA MARK1
STA MARK1+1
STXTX: LDA TEMPN1
CMP VSP
BNE STXTX1
LDA TEMPN1+1
CMP VSP+1
BEQ STXTXE
STXTX1: LDX #TEMPN2
JSR VPOP
LDX #MARK1
STX ANSN
LDY #TEMPN2
LDA #LIST
JSR CONS
JMP STXTX
STXTXE: LDA MARK1
STA TEMPN6
LDA MARK1+1
STA TEMPN6+1
LDA #$00
STA MARK1
STA MARK1+1
STEXT3: LDX #TEMPN6
JSR VPUSHP
INC OTPUTN
JMP POPJ
.PAGE
SFIRST: LDX #ARG1
JSR VPOP
JSR GETTYP
CMP #LIST
BEQ SFRST1
CMP #ATOM
BEQ SFRST2
CMP #SATOM
BEQ SFRST2
CMP #FIX
BEQ SFRST2
CMP #FLO
BEQ SFRST2
CMP #STRING
BEQ SFRST2
SDFNRR: JMP SMAKE2 ;(ERROR XWTA,ARG1,CURTOK)
SFRST1: LDY #$00
LDA (ARG1),Y
TAX
INY
LDA (ARG1),Y
STA ARG1+1
STX ARG1 ;(CAR)
JMP OTPRG1
SFRST2: LDA ARG1+1
BEQ SDFNRR
SFRST3: LDY #TEMPN6 ;TEMPN6 is TEMP
LDX #ARG1
JSR MAKPNM
LDY #$00
LDA (TEMPN6),Y
STA TEMPN5
LDX #$00
STX TEMPN5+1
LDA #ARG1
STA ANSN
LDY #TEMPN5
LDA #STRING
JSR CONS
JMP OTPRG1
.PAGE
SLAST: LDX #ARG2
JSR VPOP
JSR GETTYP
CMP #LIST
BEQ SLST1
CMP #ATOM
BEQ SLST2
CMP #SATOM
BEQ SLST2
CMP #FIX
BEQ SLST2
CMP #FLO
BEQ SLST2
CMP #STRING
BEQ SLST2
JMP SDFNR1
SLST1: LDX #ARG2
JSR GTLSTC
LDY #$00
LDA (ARG2),Y
STA ARG1
INY
LDA (ARG2),Y
STA ARG1+1 ;(CAR)
JMP OTPRG1
SLST2: LDY #ARG1
LDX #ARG2
JSR MAKPNM
LDX #ARG1
JSR GTLSTC
LDY #$01
LDA (ARG1),Y
BEQ SLST3
STA TEMPN ;(CAR)
DEY
STY TEMPN+1
LDA #ARG1
STA ANSN
LDX #$00
LDY #TEMPN
LDA #STRING
JSR CONS
SLST3: JMP OTPRG1
.PAGE
SEQUAL: LDA LTRUE
STA TEMPX2 ;TEMPX2 is PRED
LDA LTRUE+1
STA TEMPX2+1
LDX #ARG2
JSR VPOP
LDX #ARG1
JSR VPOP
INC OTPUTN
LDA SP
STA TEMPN8
LDA SP+1
STA TEMPN8+1
LDX #SEQEND&$FF
LDY #SEQEND^
JSR PUSH
;falls through
.PAGE
;falls in
EQ: LDX #ARG2
JSR GETTYP
STA ANSN
LDX #ARG1
JSR GETTYP
STA ANSNX
CMP #LIST
BEQ EQL
CMP #FIX
BEQ EQF
CMP #FLO
BEQ EQF
CMP #ATOM
BEQ EQA
EQO: LDA ANSNX
CMP ANSN
BNE EQFF
EQO1: LDA ARG1
CMP ARG2
BNE EQFF
LDA ARG1+1
CMP ARG2+1
BEQ EQPOP
EQFF: LDA LFALSE
STA TEMPX2 ;PRED
LDA LFALSE+1
STA TEMPX2+1
JMP SEQEND
EQPOP: JMP POPJ
EQL: LDA ANSN
CMP #LIST
BNE EQFF
JMP EQLIST
EQF: LDX #ARG1 ;ARG1 is a Fixnum
JSR GTNM2 ;(GETNUM) Get first arg in NARG1
LDX #ARG2
JSR GETNUM ;Get second arg in NARG2
BCC EQFF ;Not a number
EQFC: CMP ANSNX ;See if same type...
BEQ EQF1 ;Yes, skip conversion
CMP #FLO ;If NARG2 is Flonum,
BEQ EQF2 ;then correct
JSR FLOTN2 ;Else NARG2 is Fixnum, convert to flt. pt.
JMP EQF1
EQF2: JSR FLOTN1 ;Convert NARG1 to floating pt.
EQF1: LDX #$03
EQFLP: LDA NARG1,X
CMP NARG2,X
BNE EQFF
DEX
BPL EQFLP
JMP POPJ
EQA: LDA ANSN
CMP #FIX
BEQ EQA1
CMP #FLO
BNE EQO
EQA1: STA ANSNX
LDX #NARG2
JSR GTNM2
JSR GTNUM1
BCC EQFF
CMP ANSNX
JMP EQFC
EQLIST: LDA ARG1+1
BNE EQLST1
LDA ARG2+1
BNE EQFF
JMP POPJ
EQLST1: LDA ARG2+1
BEQ EQFF
LDX #ARG1
JSR PUSHP
LDX #ARG2
JSR PUSHP
LDY #$00
LDA (ARG1),Y
TAX
INY
LDA (ARG1),Y
STA ARG1+1
STX ARG1 ;(CAR)
DEY
LDA (ARG2),Y
TAX
INY
LDA (ARG2),Y
STA ARG2+1
STX ARG2 ;(CAR)
JSR STKTST
LDX #EL1&$FF
LDY #EL1^
JSR PUSH
JMP EQ
EL1: LDX #ARG2
JSR POP
LDX #ARG1
JSR POP
LDY #$02
LDA (ARG1),Y
TAX
INY
LDA (ARG1),Y
STA ARG1+1
STX ARG1 ;(CDR)
LDX #ARG1
JSR GETTYP
CMP #LIST
BNE EL1R
LDY #$02
LDA (ARG2),Y
TAX
INY
LDA (ARG2),Y
STA ARG2+1
STX ARG2 ;(CDR)
LDX #ARG2
JSR GETTYP
CMP #LIST
BNE EL1R
JMP EQLIST
EL1R: JSR SYSBUG
SEQEND: LDX #TEMPX2 ;PRED
JSR VPUSHP
LDA TEMPN8
STA SP
LDA TEMPN8+1
STA SP+1
JMP POPJ
.PAGE
STO: LDA GRPHCS
BEQ STO2
JSR RESETT
LDX #SCS&$FF
LDY #SCS^
JSR PUSH ;So we return to graphics mode when done
STO2: LDA INDEV
BNE STO1
JMP CHGST1 ;Not in EDIT-eval loop, so call screen editor
STO1: JSR EDTSTP ;In edit-eval loop
LDA #BUFFER
STA EDSW
LDA #TEMPX2 ;FUN is TEMPX2
LDX #ARG1
JSR GETFUN
LDA TEMPX2+1
BEQ STO1A
LDX #ARG1
JSR UNFUNC
STO1A: LDA #$00
STA NARGS
LDA TOKPTR
STA MARK1
LDA TOKPTR+1
STA MARK1+1
BEQ STOWE
STOW: LDA TOKPTR+1
BEQ STOWE
LDY #$00
LDA (TOKPTR),Y
STA TEMPX2 ;TEMPX2 is TOKEN
INY
LDA (TOKPTR),Y
STA TEMPX2+1 ;(GETTOK)
STOW2: LDX #TEMPX2
JSR GETTYP
CMP #ATOM
BEQ STOW3
CMP #SATOM
BEQ STOW3
CMP #DATOM
BEQ STOW3
LDX #TEMPX2
JMP STLR4A
STOW3: LDX #TOKPTR
JSR TTKADV
INC NARGS
BNE STOW
JMP EXCED
STOWE: LDX #$00
STX TEMPX1+1
LDA #EDBOD
STA ANSN
TXA ;(Type LIST)
LDY #MARK1
JSR CONS
LDY #EDBOD
LDX #EDTATM
LDA NARGS
STA TEMPX1
LDA #TEMPX1
JSR PTFTXT
JMP POPJ
STOERR: LDA #XDEF
LDY #ARG1
JMP ERROR
.PAGE
SEDIT: JSR EDTSTP
LDA #$01
STA EDSW
LDA #TEMPN5 ;FUN
LDX #ARG1
JSR GETFUN
LDA TEMPN5+1
BNE SEDIT1
LDA #XUDF
LDY #ARG1
JMP ERROR
SEDIT1: LDA #$00
LDX #TEMPN5
LDY #EDBOD
JSR UNSTUF
LDY #$00
LDA (EDBOD),Y
STA TEMPN1 ;ARGS
INY
LDA (EDBOD),Y
STA TEMPN1+1 ;(CAR)
LDX #TEMPX1
LDY #TEMPN1
JSR GETLEN
LDA #TEMPX1
LDY #EDBOD
LDX #ARG1
JSR PTFTXT
JSR RSTERR
JMP POPJ
.PAGE
SEND: LDA EDSW
BNE SEND1 ;if edit switch off, give
JMP STTLR1 ;(ERROR XNED)
SEND1: LDA LEVNUM ;if not at top level, complain.
BNE SENDR
LDA LEVNUM+1
BNE SENDR
LDA #EDTATM
LDX #EDBOD
JSR STUFF ;try to put the function def together
LDA #$00
LDX #EDTATM
JSR LTYPE
LDX #SENDM&$FF ;" DEFINED"
LDY #SENDM^
JSR PRTSTR
SEND2: JSR EXTEDT
JMP POPJ
SENDR: JMP STTLR2 ;(ERROR XETL)
.PAGE
SPO: LDA TOKPTR+1
BNE SPO1
LDA PODEFL+1
BNE SPO1A
JMP POPJ
SPO1: LDY #$00
LDA (TOKPTR),Y
STA ARG1
INY
LDA (TOKPTR),Y
STA ARG1+1 ;(GETTOK)
LDX #TOKPTR
JSR TTKADV
LDX ARG1
LDY ARG1+1
CPX ALL
BNE SPO2
CPY ALL+1
BNE SPO2
LDA #$01
JSR POFUNS
SPON: LDA #$01
JSR PONAMS
JMP POPJ
SPO2: CPX NAMES
BNE SPO3
CPY NAMES+1
BEQ SPON
SPO3: CPX TITLES
BNE SPO4
CPY TITLES+1
BNE SPO4
SPOTS: LDA #$00
JSR POFUNS
JMP POPJ
SPO5A: LDA ARG1
STA PODEFL
LDA ARG1+1
STA PODEFL+1
SPO1A: LDX #PODEFL
LDA #TEMPN1
JSR GETFUN
LDA TEMPN1+1
BEQ PFERR
LDX #$01
LDA #PODEFL
JSR POTEXT
JMP POPJ
SPO4: CPX PROCS
BNE SPO5
CPY PROCS+1
BNE SPO5
LDA #$01
JSR POFUNS
JMP POPJ
SPO5: LDX #ARG1
JSR GETTYP
CMP #ATOM
BEQ SPO5A
CMP #SATOM
BEQ SPO5S
JMP SMAKE2 ;(ERROR XWTA,ARG1,CURTOK)
SPO5S: LDY #ARG1
LDA #XUBL
JMP ERROR
PFERR: LDY #PODEFL
LDA #XNDF
JMP ERROR
.PAGE
STRCBK: LDA FRAME+1
BNE TCBK1
LDX #TBMSG1&$FF
LDY #TBMSG1^
JSR PRTSTR
JMP TCBKWE
TCBK1: LDX #TBMSG2&$FF
LDY #TBMSG2^
JSR PRTSTR
LDA #$01
STA ANSN1 ;ANSN1 is FIRST
LDA FRAME
STA TEMPX1 ;TEMPX1 is FR
LDA FRAME+1
STA TEMPX1+1
LDA XFRAME
STA TEMPX2 ;TEMPX2 is XFR
LDA XFRAME+1
STA TEMPX2+1
TCBKW: LDA TEMPX1+1
BNE TCBKW1
JMP TCBKWE
TCBKW1: CLC
LDA TEMPX1
ADC #$12 ;(SF_BINDINGS = 18.)
STA TEMPN6 ;TEMPN6 is PTR
LDA TEMPX1+1
ADC #$00
STA TEMPN6+1
SEC
LDA TEMPX2
SBC #$02 ;PTR1 (TEMPN7) points to top binding (name)
STA TEMPN7
LDA TEMPX2+1
SBC #$00
STA TEMPN7+1
TCBKX: LDA TEMPN7+1
CMP TEMPN6+1
BCC TCBKXE
BNE TCBKX1
LDA TEMPN7
CMP TEMPN6
BCC TCBKXE
TCBKX1: LDY #$00
LDA (TEMPN7),Y
STA TEMPNH
INY
LDA (TEMPN7),Y
STA TEMPNH+1 ;(GETBAR)
LDA TEMPNH
ROR A
BCC TCBKX2
LDA ANSN1
BNE TCBKX3
LDA #',
JSR TPCHR
LDA #$20
JSR TPCHR
JMP TCBKX4
TCBKX3: DEC ANSN1
TCBKX4: LDY #$05
LDA (TEMPNH),Y
STA TEMPN8
INY
LDA (TEMPNH),Y
STA TEMPN8+1 ;(GETBAR)
LDA #$00
LDX #TEMPN8
JSR LTYPE
TCBKX2: SEC
LDA TEMPN7
SBC #$04
STA TEMPN7
BCS TCBKX
DEC TEMPN7+1
JMP TCBKX
TCBKXE: LDY #$03 ;(SF_XFRAME = 2.)
LDA (TEMPX1),Y
STA TEMPX2+1
DEY
LDA (TEMPX1),Y
STA TEMPX2 ;(GETBAR)
DEY ;(SF_PREV_FRAME = 0)
LDA (TEMPX1),Y
TAX
DEY
LDA (TEMPX1),Y
STA TEMPX1
STX TEMPX1+1 ;(GETBAR)
JMP TCBKW
TCBKWE: JSR BREAK1
JMP POPJ
.PAGE
SERASE: LDA TOKPTR+1
BNE SERAS1
JMP SCMMT1 ;(ERROR XEOL)
SERAS1: LDY #$00
LDA (TOKPTR),Y
STA ARG1
INY
LDA (TOKPTR),Y
STA ARG1+1 ;(GETTOK)
LDX #TOKPTR
JSR TTKADV
LDA EDSW
BNE SERASB
LDX ARG1
LDY ARG1+1
CPX ALL
BNE ECMP2
CPY ALL+1
BNE ECMP2
JSR REINIT
JMP TOPLOP
ECMP2: CPX NAMES
BNE ECMP3
CPY NAMES+1
BNE ECMP3
JSR ERNAMS
JMP POPJ
ECMP3: CPX TITLES
BNE ECMP4
CPY TITLES+1
BEQ SERPS
ECMP4: CPX PROCS
BNE SERAP
CPY PROCS+1
BNE SERAP
SERPS: JSR ERPROS
JMP POPJ
SERAP: LDX #ARG1
JSR GETTYP
CMP #ATOM
BNE SERAR1
LDX #ARG1
JSR UNFUNC
JMP POPJ
SERAR1: CMP #FIX
BNE SERAR2
JMP STTLR1 ;(ERROR XNED)
SERAR2: JMP SMAKE2 ;(ERROR XWTA,ARG1,CURTOK)
SERASB: LDX #ARG1
JSR GETTYP
CMP #FIX
BNE SERAR3
LDY #$00
LDA (ARG1),Y
TAX
INY
LDA (ARG1),Y
STA ARG1+1
STX ARG1 ;(CAR)
LDA EDBOD
STA TEMPN ;TEMPN is LASTLINE
LDA EDBOD+1
STA TEMPN+1
LDY #$02
LDA (TEMPN),Y
STA TEMPN1 ;TEMPN1 is LINE
INY
LDA (TEMPN),Y
STA TEMPN1+1 ;(CDR)
DLTW: LDA TEMPN1+1
BEQ DLTWE
DLTW2: LDY #$00
LDA (TEMPN1),Y
STA TEMPNH ;TEMPNH is TEMP
INY
LDA (TEMPN1),Y
STA TEMPNH+1 ;(CAR)
DEY
LDA (TEMPNH),Y
TAX
INY
LDA (TEMPNH),Y
STA TEMPNH+1
STX TEMPNH ;(CAR)
CMP ARG1+1
BCC DLTW1
BNE DLTWE
LDA TEMPNH
CMP ARG1
BEQ DLTWF
BCS DLTWE
DLTW1: LDA TEMPN1
STA TEMPN
LDA TEMPN1+1
STA TEMPN+1
LDY #$02
LDA (TEMPN1),Y
TAX
INY
LDA (TEMPN1),Y
STA TEMPN1+1
STX TEMPN1 ;(CDR)
JMP DLTW
DLTWF: LDY #$02
LDA (TEMPN1),Y
STA TEMPNH
INY
LDA (TEMPN1),Y
STA TEMPNH+1 ;(CDR)
DEY
LDA TEMPNH
STA (TEMPN),Y
INY
LDA TEMPNH+1
STA (TEMPN),Y ;(RPLACD)
DLTWE: JMP POPJ
SERAR3: LDA #XNWE
JMP ERROR
ERPROS: LDA OBLIST
STA TEMPN
LDA OBLIST+1
STA TEMPN+1
ERPRSW: LDA TEMPN+1
BEQ RTS30
LDY #$00
LDA (TEMPN),Y
STA TEMPN1
INY
LDA (TEMPN),Y
STA TEMPN1+1 ;(CAR)
INY
LDA (TEMPN),Y
TAX
INY
LDA (TEMPN),Y
STA TEMPN+1
STX TEMPN ;(CDR)
LDX #TEMPN1
JSR UNFUNC
JMP ERPRSW
RTS30: RTS
.PAGE
ERNAMS: LDA OBLIST
STA TEMPN
LDA OBLIST+1
STA TEMPN+1 ;TEMPN is OBLIST pointer
LDX #$00
STX TEMPN1+1 ;TEMPN1 is NOVALUE
INX
STX TEMPN1
ERNMSW: LDA TEMPN+1
BEQ ERNMWE
LDY #$00
LDA (TEMPN),Y
STA TEMPN2 ;TEMPN2 is NAME
INY
LDA (TEMPN),Y
STA TEMPN2+1 ;(CAR)
INY
LDA (TEMPN),Y
TAX
INY
LDA (TEMPN),Y
STA TEMPN+1
STX TEMPN ;(CDR)
LDX #TEMPN1
LDY #TEMPN2
JSR PUTVAL
JMP ERNMSW
ERNMWE: LDA SOBLST
STA TEMPN
LDA SOBLST+1
STA TEMPN+1
ERNMX: LDA TEMPN
CMP SOBTOP
BNE ERNMX1
LDA TEMPN+1
CMP SOBTOP+1
BEQ RTS30
ERNMX1: LDX #TEMPN1
LDY #TEMPN
JSR PUTVAL
CLC
LDA TEMPN
ADC #$04
STA TEMPN
BCC ERNMX
INC TEMPN+1
JMP ERNMX
.PAGE
SBTFST: LDX #ARG2
JSR VPOP
JSR GETTYP
CMP #LIST
BEQ SBFL
CMP #SATOM
BEQ SBFA
CMP #ATOM
BEQ SBFA
CMP #FIX
BEQ SBFA
CMP #FLO
BEQ SBFA
CMP #STRING
BEQ SBFA
SBFR: JMP SMAKE2 ;(ERROR XWTA,ARG1,CURTOK)
SBFL: LDA ARG2+1
BEQ SBFR
LDY #$02
LDA (ARG2),Y
STA ARG1
INY
LDA (ARG2),Y
STA ARG1+1 ;(CDR)
JMP OTPRG1
SBFA: LDX #ARG2
LDY #ARG1 ;ARG1 is OLD_PTR
JSR MAKPNM
LDX #ARG1
JSR VPUSHP
LDY #$00
STY ANSN1
LDA (ARG1),Y
STA TEMPN1 ;TEMPN1 is OLD_CAR
INY
LDA (ARG1),Y
STA TEMPN1+1 ;(CAR)
BNE SBFA1A
LDA TEMPN1
BEQ SBFR
SBFA1: LDA TEMPN1+1
BEQ SBFB
SBFA1A: LDX #$00
LDA TEMPN1+1
STA TEMPN1
STX TEMPN1+1
LDY #TEMPN1
LDA #TEMPN2
STA ANSN
TXA ;(LIST)
JSR CONS
LDA ANSN1
BNE SBFC
LDX #TEMPN2
JSR VPUSHP
INC ANSN1 ;BEG_OF_PNAME
BNE SBFC1 ;(Always)
SBFC: LDY #$02
LDA TEMPN2
STA (TEMPN),Y ;TEMPN is NEW_PTR
INY
LDA TEMPN2+1
STA (TEMPN),Y ;(RPLACD)
SBFC1: LDA TEMPN2
STA TEMPN
LDA TEMPN2+1
STA TEMPN+1
SBFB: LDY #$02
LDA (ARG1),Y
TAX
INY
LDA (ARG1),Y
STX ARG1
STA ARG1+1 ;(CDR)
BEQ SBFD
SBFB1: LDA TEMPN1
TAX
LDY #$00
LDA (ARG1),Y
STA TEMPN1 ;(OLD_CAR)
INY
LDA (ARG1),Y
STA TEMPN1+1 ;(CAR)
DEY
TXA
STA (TEMPN),Y
INY
LDA TEMPN1
STA (TEMPN),Y
JMP SBFA1
SBFD: LDX #ARG1
JSR VPOP
LDA ANSN1
BNE SBFD1
LDA #$00
STA ARG1
STA ARG1+1
BEQ SBFD2 ;(Always)
SBFD1: LDX #TEMPN ;(OLD_CAR, discard)
JSR VPOP
SBFD2: JMP OTPRG1
.PAGE
SPEEK: JSR GT1FIX
LDY #$00
LDA (NARG1),Y
STA NARG1
STY NARG1+1
LDY #NARG1
JMP OTPFX1
SPOKE: JSR GT2FIX ;First argument is location
LDY #$00
LDA NARG2+1
BNE SPKERR
LDA NARG2
STA (NARG1),Y
JMP POPJ
SPKERR: JMP SFPT1 ;Error, ARG2 too big
SRANDM: LDA #$00
STA NARG1 ;Zero running total
STA NARG1+1
LDA #RANDA&$FF ;Multiply 16-bit Random number by
STA TEMPNH ;transform constant "A"
LDA #RANDA^
STA TEMPNH+1
LDY #$10
RMUL2: LSR RANDOM+1
ROR RANDOM
BCC RMUL4
CLC
RMUL3: LDA NARG1
ADC TEMPNH
STA NARG1
LDA NARG1+1
ADC TEMPNH+1
STA NARG1+1
RMUL4: ASL TEMPNH
ROL TEMPNH+1
DEY
BNE RMUL2
CLC
LDA NARG1
ADC #RANDC&$FF ;Add transform constant "C"
STA RANDOM
STA NARG1
LDA NARG1+1
ADC #RANDC^
STA RANDOM+1
STA NARG1+1
JSR CVFIX ;Convert to string on PDL
RNDLP1: JSR POPB
DEC ANSN1
BNE RNDLP1 ;Pop all characters, just use last one
STA TEMPN1
LDA #$00
STA TEMPN1+1
LDY #TEMPN1
JMP OTPFX1
.PAGE
SRNDMZ: LDA RNDL
STA RANDOM
LDA RNDH
STA RANDOM+1
JMP POPJ
SCTYI: LDA #$00
STA TEMPN+1
JSR RDKEY
STA TEMPN
LDA #ARG1
STA ANSN
LDY #TEMPN
LDX #$00
LDA #STRING ;(String typecode)
JSR CONS ;Cons a cell with the character in it
JMP OTPRG1 ;And output it
SCURSR: JSR GT2FIX
LDA NARG1+1 ;Horizontal position 0 - 39.
BNE SCRSR1
LDA NARG1
CMP #$29
BCS SCRSR1
LDA NARG2+1 ;Vertical position 0 - 23.
BNE SCRSR1
LDA NARG2
CMP #$19
BCS SCRSR1
LDA NARG1
STA CH
LDA NARG2
STA CV
JSR BCALCA
SCALL1: JMP POPJ
SCRSR1: LDA #XCRSR ;"Position off of screen"
JMP ERROR
.PAGE
SCALLR =SCALL1-1
SCALL: JSR GT1FIX
LDA #SCALLR^
PHA ;Push return address for RTS
LDA #SCALLR&$FF
PHA
JMP (NARG1)
.PAGE
SWORD: LDA NARGS
BPL SWRD1
EOR #$FF
STA NARGS
SWRD1: LDA #$00
STA MARK5
STA MARK5+1
LDA NARGS
ASL A
STA ANSNX
CLC
LDA VSP
ADC ANSNX
STA TEMPN6
LDA VSP+1
ADC #$00
STA TEMPN6+1
SWRDW: LDA NARGS
BEQ SWRD2
LDY #$00
LDA (TEMPN6),Y
STA MARK3
INY
LDA (TEMPN6),Y
STA MARK3+1
SEC
LDA TEMPN6
SBC #$02
STA TEMPN6
BCS SWRDW1
DEC TEMPN6
SWRDW1: DEC NARGS
LDY #MARK4
LDX #MARK3
JSR MAKPNM
LDA MARK4+1
BEQ SWRDW
JSR CONCAT ;MARK5 := (Concatenate MARK5 MARK4)
JMP SWRDW
SWRD2: CLC
LDA VSP
ADC ANSNX
STA VSP
BCC SWRD3
INC VSP+1
SWRD3: LDX #MARK5
JSR VPUSHP
INC OTPUTN
LDA #$00
JSR CLMK5
JMP POPJ
.PAGE
CONCAT: LDA MARK5+1
BNE CNCT1
LDA MARK4 ;MARK5 is Lnil, so make
LDX MARK4+1 ;MARK5 a copy of second word and return
LDY #MARK5
JMP COPY
CNCT1: LDA MARK5
LDX MARK5+1
LDY #TEMPN3 ;Make TEMPN3 a copy of MARK5
JSR COPY
LDA TEMPN3
STA TEMPN4 ;Save the first word's pointer in TEMPN4
LDA TEMPN3+1
STA TEMPN4+1
LDX #TEMPN3 ;Get the last cell of first word (TEMPN3)
JSR GTLSTC
LDY #$01
LDA (TEMPN3),Y
BEQ CNCODD
LDA MARK4 ;Even no. chars. in first word
LDX MARK4+1
LDY #TEMPN5 ;Make TEMPN5 a copy of second word
JSR COPY
LDY #$02
LDA TEMPN5
STA (TEMPN3),Y ;Link second word onto first
INY
LDA TEMPN5+1
STA (TEMPN3),Y
CNCTWE: LDA TEMPN4 ;Restore pointer to new word
STA MARK5
LDA TEMPN4+1
STA MARK5+1
RTS
CNCODD: LDY #$00 ;Odd no. chars. in first word
STY TEMPN1+1
LDA (MARK4),Y ;Get first char. of second word
INY
STA (TEMPN3),Y ;Append it to end of first word
LDA (MARK4),Y
STA TEMPN1 ;TEMPN1 holds second char. of second word
CNCTW: LDA MARK4+1
BEQ CNCTWE
LDY #$02
LDA (MARK4),Y
TAX
INY
LDA (MARK4),Y
STA MARK4+1 ;Advance second word char-ptr
STX MARK4
LDA TEMPN1 ;If even-numbered char. of second word nil, exit
BEQ CNCTWE ;(already appended odd-numbered char. preceeding)
LDA MARK4+1
BNE CNCTW1
STA TEMPN1+1 ;Zero last character (because odd no.)
BEQ CNCTW2 ;(Always) Just add last char. if end of second word
CNCTW1: LDY #$00
LDA (MARK4),Y
STA TEMPN1+1 ;Get odd-numbered (3,5,...) char.
INY
LDA (MARK4),Y
STA ANSN1 ;Get next even-numbered (4,6,...) char.
CNCTW2: LDA #TEMPN
STA ANSN
LDY #TEMPN1
LDA #$00
TAX
LDA #STRING
JSR CONS ;Cons new cell
LDY #$02
LDA TEMPN
STA (TEMPN3),Y
TAX
INY
LDA TEMPN+1
STA (TEMPN3),Y ;Append to new word
STA TEMPN3+1
STX TEMPN3 ;New new-word end pointer
LDA ANSN1
STA TEMPN1 ;Last even char. becomes new odd char.
JMP CNCTW
.PAGE
COPY: STY ANSN1 ;Y is STR1
STA TEMPN1 ;Make (ANSN1) point to a copy of (vXA)
STX TEMPN1+1
TXA
BNE COPY1
STA $00,Y ;If (vAX) is Lnil, make (ANSN1) Lnil
STA $00,Y
RTS
COPY1: STY ANSN ;Cons up an empty cell
LDA #$00
TAX
TAY
LDA #STRING
JSR CONS
LDX ANSN1
JSR VPUSHP ;Vpush forming string
COPYW: LDX ANSN1
LDA $00,X
STA TEMPN2
LDA $01,X
STA TEMPN2+1 ;TEMPN2 points to empty last cell of copy
LDY #$00
LDA (TEMPN1),Y
STA (TEMPN2),Y ;Copy two characters into cell
INY
LDA (TEMPN1),Y
STA (TEMPN2),Y
INY
LDA (TEMPN1),Y
TAX
INY
LDA (TEMPN1),Y
STA TEMPN1+1 ;Advance char-ptr of original
STX TEMPN1
TAX
BEQ COPYWE ;Exit if end of original
LDA #TEMPN
STA ANSN
LDA #$00
TAX
TAY
LDA #STRING
JSR CONS ;Cons a new cell
LDY #$02
LDX ANSN1
LDA TEMPN
STA (TEMPN2),Y
STA $00,X
INY
LDA TEMPN+1
STA (TEMPN2),Y ;Link new cell on to end of copy
STA $01,X ;Advance copy's last-cell ptr
JMP COPYW
COPYWE: LDX ANSN1 ;Vpop copy's beginning pointer
JMP VPOP
.PAGE
SBTLST: LDX #ARG1
JSR VPOP
JSR GETTYP
CMP #LIST
BEQ BTLSTL
CMP #ATOM
BEQ BTLSTA
CMP #SATOM
BEQ BTLSTA
CMP #FIX
BEQ BTLSTA
CMP #FLO
BEQ BTLSTA
CMP #STRING
BEQ BTLSTA
BTLSTR: JMP SMAKE2
BTLSTA: LDY #TEMPN5
LDX #ARG1
JSR MAKPNM
LDA #ATOM
STA ANSN2
LDY #$00
LDA (TEMPN5),Y
BEQ BTLSTR
LDA TEMPN5
STA ARG1
LDA TEMPN5+1
STA ARG1+1
JMP BTLSTX
BTLSTL: STA ANSN2
LDA ARG1+1
BEQ BTLSTR
BTLSTX: LDA #$00
STA ANSN1 ;NEW_LIST
LDX #ARG1
JSR VPUSHP
BTLSW: LDY #$03
LDA (ARG1),Y
BEQ BTLSWE
LDY #$00
LDA (ARG1),Y
STA TEMPN1 ;TEMP_CAR
INY
LDA (ARG1),Y
STA TEMPN1+1
LDA #TEMPN ;TEMP
STA ANSN
LDY #TEMPN1
LDA #$00
TAX
JSR CONS
LDA ANSN2
CMP #ATOM
BNE BTLSW1
LDX #TEMPN
LDA #STRING
JSR PUTTYP
BTLSW1: LDA ANSN1
BNE BTLSW2
LDX #TEMPN
JSR VPUSHP
LDX TEMPN
LDA TEMPN+1
INC ANSN1
BNE BTLSW3 ;(Always)
BTLSW2: LDY #$02
LDA TEMPN
STA (TEMPN2),Y
TAX
INY
LDA TEMPN+1
STA (TEMPN2),Y
BTLSW3: STA TEMPN2+1
STX TEMPN2
LDY #$02
LDA (ARG1),Y
TAX
INY
LDA (ARG1),Y
STA ARG1+1
STX ARG1
JMP BTLSW
BTLSWE: LDA ANSN2
CMP #LIST
BNE BTLWE1
LDA ANSN1
BNE BTLWL1
LDA #$00
STA ARG1
STA ARG1+1
BEQ BTLWL2 ;(Always)
BTLWL1: LDX #ARG1
JSR VPOP
BTLWL2: LDX #TEMPN1
JSR VPOP
JMP OTPRG1
BTLWE1: LDY #$00
LDA (ARG1),Y
STA TEMPN1
INY
LDA (ARG1),Y
STA TEMPN1+1
BEQ BTLWE2
LDA #TEMPN
STA ANSN
LDA #$00
TAX
STA TEMPN1+1
LDY #TEMPN1
JSR CONS
LDA ANSN1
BNE BTLWE3
LDA TEMPN
STA ARG1
LDA TEMPN+1
STA ARG1+1
JMP BTLWE5
BTLWE3: LDY #$02
LDA TEMPN
STA (TEMPN2),Y
INY
LDA TEMPN+1
STA (TEMPN2),Y
JMP BTLWE4
BTLWE2: LDA ANSN1
BNE BTLWE4
LDA #$00
STA ARG1
STA ARG1+1
BEQ BTLWE5 ;(Always)
BTLWE4: LDX #ARG1
JSR VPOP
BTLWE5: LDX #TEMPN
JSR VPOP
JMP OTPRG1
.PAGE
SLISTP: LDX #ARG1
JSR VPOP
JSR GETTYP
CMP #LIST
BNE NTLST
YESLST: JMP VPLTRU
SNMBRP: LDX #ARG1
JSR VPOP
JSR GETTYP
CMP #FIX
BEQ YESLST
CMP #FLO
BEQ YESLST
CMP #ATOM
BNE NTLST
LDX #ARG1
JSR ATMTFX
BCS YESLST
NTLST: JMP VPLFLS
.PAGE
SEMPTP: LDX #ARG1
JSR VPOP
JSR GETTYP
CMP #LIST
BEQ SEMPT1
CMP #ATOM
BNE NTLST
LDY #$02
LDA (ARG1),Y
TAX
INY
LDA (ARG1),Y
STA ARG1+1
STX ARG1
LDA (ARG1),Y
BNE NTLST
BEQ YESLST
SEMPT1: LDA ARG1+1
BNE NTLST
BEQ YESLST
.PAGE
SLIST: LDA NARGS
BPL SLIST1
EOR #$FF
STA NARGS
SLIST1: LDA #MARK1
STA ANSN
LDA #$00
STA MARK1
STA MARK1+1
LDA NARGS
BEQ SLSTWE
SLISTW: LDX #MARK2
JSR VPOP
JSR GETTYP
LDY #MARK2
CMP #STRING
BNE SLSTWA
LDX #MARK2
LDY #TEMPX1
JSR INTERN ;Intern it if it's a String
LDY #TEMPX1
SLSTWA: LDX #MARK1
STX ANSN
LDA #$00 ;(Type LIST)
JSR CONS
DEC NARGS
BNE SLISTW
SLSTWE: LDA MARK1
STA ARG1
LDA MARK1+1
STA ARG1+1
LDA #$00
JSR CLMK2
JMP OTPRG1
SCLINP: JSR CLRCBF ;Clear input buffer and character strobe
JMP POPJ
SCLEAR: JSR HOME
JMP POPJ
.PAGE
; Turtle-Graphics Primitives:
SCS: LDA INDEV
BNE SCS2
LDA GRPHCS
BNE SCS1
LDA #EDBUF&$FF ;Tell RETRIEVE that buffer is not retrievable
STA ENDBUF
LDA #EDBUF^
STA ENDBUF+1
LDA $C054 ;INIT Routine, set for primary page
LDA $C057
LDA $C053
LDA $C050
LDA #$14
STA WNDTOP ;Set for 4 lines text
JSR HOME
INC GRPHCS ;Indicate Graphics mode
LDA #$7F
STA COLR ;Color is "White1"
SCS1: LDA #$01
STA PEN
STA TSHOWN ;turtle shown
JSR TTLHOM
JSR GETX
JSR GETY
JSR GPOSN ;Set initial POSN point for future GLINE's
JSR GCLEAR
JSR GSHWT1
SCS2: JMP POPJ
SNDSPL: JSR RESETT ;Nodisplay, get the text page back
LDA #$00
STA GRPHCS
JMP POPJ
SPENUP: JSR GCHK
LDA #$00 ;Penup
STA PEN
JMP POPJ
SPENDN: JSR GCHK
LDA #$01 ;Pendown
STA PEN
JMP POPJ
SHOME: JSR GCHK
JSR GSHWT1 ;Erase turtle if it's there
JSR TTLHOM
JSR GETX
JSR GETY
JSR GDLINE
JMP POPJ
SXCOR: JSR GCHK ;Xcor
LDY #XCOR
JMP OTPFLO
SYCOR: JSR GCHK ;Ycor
LDY #YCOR
JMP OTPFLO
SHDING: JSR GCHK ;Heading
LDY #HEADNG
JMP OTPFLO
SRT: JSR GCHK
JSR GSHWT1
LDX #NARG1 ;Right
JSR VPOP
JSR GT1NMX
BCS SRT1
JSR FLOTN1
SRT1: JSR SRTX
JSR GSHWT1 ;Show it again if necessary
JMP POPJ
SLT: JSR GCHK
JSR GSHWT1
LDX #NARG1 ;Left
JSR VPOP
JSR GT1NMX
BCS SLT1
JSR FLOTN1
SLT1: LDY #HEADNG
JSR XYTON2
JSR FSUBX
JSR GSETHX
JSR GSHWT1
JMP POPJ
STS: JSR GCHK ;Turtlestate
LDA #$00
STA MARK1
STA MARK1+1
LDA TSHOWN
JSR CONSTF
LDA PEN
JSR CONSTF
LDA #HEADNG
JSR CONSNM
LDA #YCOR
JSR CONSNM
LDA #XCOR
JSR CONSNM
LDX #MARK1
JSR VPUSHP
INC OTPUTN
LDA #$00
STA MARK1
STA MARK1+1
JMP POPJ
SSETX: JSR GCHK
JSR GSHWT1
LDX #NARG1 ;Setx
JSR VPOP
JSR GSETX
JSR GETY
JSR GDLINE
JMP POPJ
SSETY: JSR GCHK
JSR GSHWT1
LDX #NARG1 ;Sety
JSR VPOP
JSR GSAVX
JSR GSETY
JSR GETX
JSR GDLINE
JMP POPJ
SSETXY: JSR GCHK
JSR GSHWT1
LDX #TEMPX2
JSR VPOP
LDX #NARG1
JSR VPOP
JSR GSETX
LDA TEMPX2
STA NARG1
LDA TEMPX2+1
STA NARG1+1
JSR GSETY
JSR GDLINE
JMP POPJ
SSETH: JSR GCHK
JSR GSHWT1
LDX #NARG1
JSR VPOP
JSR GSETH
JSR GSHWT1
JMP POPJ
SSETT: JSR GCHK
JSR GSHWT1
LDX #TEMPX2
JSR VPOP ;Setturtle
JSR GETTYP
CMP #LIST
BNE SSETTR
LDA #$FB ;Index for dispatching
STA ANSNX
SSETTL: LDA TEMPX2+1
BEQ SSETTD
LDA ANSNX
BEQ SSETTD
JSR SSTTLL
INC ANSNX
JMP SSETTL
SSETTD: JSR GDLINE
JMP POPJ
SSETTR: JMP SMAKE2 ;Error XWTA,ARG1,CURTOK
.PAGE
SSHOWT: JSR GCHK
LDA TSHOWN
BNE SSHWTR
INC TSHOWN
JSR XORDRW
SSHWTR: JMP POPJ
SHIDET: JSR GCHK
LDA TSHOWN
BEQ SSHWTR
DEC TSHOWN
JSR XORDRW
JMP POPJ
SFULL: JSR GCHK
LDA $C052
JMP POPJ
SMIX: JSR GCHK
LDA $C053
JMP POPJ
.PAGE
SBK: JSR GCHK
JSR GSHWT1
LDX #NARG1
JSR VPOP ;Forward
JSR GT1NMX
BCS SBK1
JSR FLOTN1
SBK1: JSR FCOMPL
JSR SFDX
JSR GDLINE
JMP POPJ
SFD: JSR GCHK
JSR GSHWT1
LDX #NARG1
JSR VPOP ;Forward
JSR GT1NMX
BCS SFD1
JSR FLOTN1
SFD1: JSR SFDX
JSR GDLINE
JMP POPJ
.PAGE
.SBTTL Turtle-Graphics Utility Routines:
SRTX: LDY #HEADNG
JSR XYTON2
JSR FADD
JMP GSETHX
CONSTF: BNE CNSTF1
LDY #LFALSE
BNE CNSNM1 ;(Always)
CNSTF1: LDY #LTRUE
BNE CNSNM1 ;(Always)
CONSNM: TAX
TAY
INX
INX
LDA #TEMPX1
STA ANSN
LDA #FLO
JSR CONS ;CONS the number
LDY #TEMPX1
CNSNM1: LDX #MARK1
STX ANSN
LDA #LIST
JMP CONS ;CONS the node
SSTTLL: LDY #$00
LDA (TEMPX2),Y
STA ARG1
INY
LDA (TEMPX2),Y
STA ARG1+1
INY
LDA (TEMPX2),Y
TAX
INY
LDA (TEMPX2),Y
STA TEMPX2+1
STX TEMPX2
LDX #ARG1
LDY ANSNX
INY
BEQ SSTTS
INY
BEQ SSTTP
INY
BEQ GSETH
INY
BEQ GSETY
BNE GSETX
SSTTS: JSR GTBOL1 ;(GTBOOL doesn't have to Intern, since arg is from a list)
TYA
EOR #$FF
STA TSHOWN
RTS
SSTTP: JSR GTBOL1
TYA
EOR #$FF
STA PEN
RTS
GSETX: JSR GT1NMX ;Set X
BCS GSTX1
JSR FLOTN1
GSTX1: JSR XCHK
JMP GSAVX
GSETY: JSR GT1NMX ;Set Y
BCS GSTY1
JSR FLOTN1
GSTY1: JMP YCHK
GSETH: JSR GT1NMX ;Setheading
BCS GSETHX
JSR FLOTN1
GSETHX: LDA NARG1
CMP #$8F
BCS GSETHR
LDA #$00
STA ANSN1
LDA NARG1+1 ;Normalize to within +/- 180.
BPL SSETDL ;Go to decrement-loop if positive
JSR FCOMPL
INC ANSN1
SSETDL: LDA NARG1
CMP #$87
BCC SSETH2
BNE SSETD
LDA NARG1+1
BMI SSETH2 ;If negative, OK
CMP #$5A ;Check the high byte
BCC SSETH2
BNE SSETD
LDA NARG1+2
BNE SSETD
LDA NARG1+3
BEQ SSETH2
SSETD: LDX #$03
SETHL: LDA FCIRC,X ;Constant, 360.
STA NARG2,X
DEX
BPL SETHL
JSR FSUB ;Subtract 360 degrees
JMP SSETDL
SSETH2: LDA ANSN1
BEQ SSETH3
JSR FCOMPL
SSETH3: LDY #HEADNG
JMP XN1TOY
GSETHR: LDA #XOFLOW
JMP ERROR
GDLINE: LDA PEN
BNE GDLIN1
JSR GPOSN ;Just do a GPOSN if pen is up
JMP GSHWT1
GDLIN1: LDA #$00
STA ANSNX
JSR GLINE
GSHWT1: LDA TSHOWN
BNE XORDRW
RTS
XORDRW: JSR GSAVX ;Save new value of X, in case turtle is out-of-bounds
LDX #$13 ;Draw the turtle, XOR mode
XRDRL1: LDA XCOR,X ;Save XCOR,YCOR,HEADNG,hires vars on stack
PHA
DEX
BPL XRDRL1
LDA #$01
STA ANSNX ;Set up XOR mode
LDA #TTLC1 ;Move to tip
JSR SETARG
JSR SFDX
JSR GPOSN
LDA #TTLA1 ;Turn right to draw first side
JSR SETARG
JSR SRTX
LDA #TTLC2 ;Draw first side
JSR SETARG
JSR SFDX
JSR GLINE
LDA #TTLA2 ;Turn right to draw rear
JSR SETARG
JSR SRTX
LDA #TTLC3 ;Draw rear
JSR SETARG
JSR SFDX
JSR GLINE
LDA #TTLA2 ;Turn right to draw second side
JSR SETARG
JSR SRTX
LDA #TTLC2 ;Draw second side
JSR SETARG
JSR SFDX
JSR GLINE
DEC ANSNX
LDX #$EC
XRDRL2: PLA ;Restore XCOR,YCOR,HEADNG,hires vars from stack
STA XCOR+20,X
INX
BMI XRDRL2
XRDR: RTS
SETARG: STA NARG1
LDA #$00
STA NARG1+1
STA NARG1+2
STA NARG1+3
JMP FLOTN1
GCHK: LDA GRPHCS ;Checks to see if Graphics mode
BNE XRDR
LDA #XYNT
LDY #CURTOK
JMP ERROR ;If not, error "You need a turtle"
TTLHOM: LDX #XCOR
JSR CLRFLT
JSR CLRFLT
CLRFLT: LDA #$00 ;Clear a 4-byte argument
LDY #$03
TTLL1: STA $00,X
INX
DEY
BPL TTLL1
RTS
SFDX: LDY #TEMPX1
JSR XN1TOY ;Save Length in TEMPX1,2
JSR GETHED
LDA NARG1
PHA ;Save table index
JSR MULSIN
LDY #TEMPN7
JSR XYTON2 ;Restore interpolation fraction
JSR FMUL ;Get interpolation correction
LDY #TEMPN5
JSR XYTON2 ;Get uncorrected table value...
JSR FADD ;and correct it!
LDY #TEMPX1
JSR XYTON2 ;Get length back
JSR FMUL ;Multiply Length by fraction
LDA ANSN1 ;X-Incr. sign
BEQ SFDP1
JSR FCOMPL
SFDP1: LDY #XCOR ;Get XCOR in NARG2
JSR XYTON2
JSR FADD ;Add XCOR and NARG1 (X-incr.)
JSR XCHK
PLA ;Retrieve NARG1
STA NARG1
JSR MULCOS
LDY #TEMPN7
JSR XYTON2 ;Restore interpolation fraction
JSR FMUL ;Get interpolation correction
LDY #TEMPN3
JSR XYTON2 ;Get uncorrected table value...
JSR FSUBX ;and correct it!
LDY #TEMPX1
JSR XYTON2 ;Get length back
JSR FMUL ;Multiply Length by fraction
LDA ANSN2 ;Y-Incr. sign
BEQ SFDP2
JSR FCOMPL
SFDP2: LDY #YCOR
JSR XYTON2 ;Get YCOR in NARG2
JSR FADD ;Add YCOR and NARG1 (Y-incr.)
JMP YCHK
GETHED: LDA #$00
STA ANSN1
STA ANSN2
LDY #HEADNG
JSR XYTON2 ;Get HEADING in NARG2
LDY #HEADNG
JSR XYTON1 ;And in NARG1
JSR XINT1 ;Make it integer...
JSR FLOTN1 ;then floating again, zapping fraction bits
JSR FSUBX ;which remain after subtract
LDY #TEMPN7
JSR XN1TOY ;Save fraction for interpolating
LDY #HEADNG
JSR XYTON1 ;Get heading back for munching
LDA NARG1+1
BPL HDPOS
JSR FCOMPL
INC ANSN1 ;Sign of X incr.
HDPOS: LDA NARG1 ;See if it's > 90.
CMP #$86
BCC HDYPOS
BNE HDYNEG
LDA NARG1+1
CMP #$5A
BCC HDYPOS
BNE HDYNEG
LDA NARG1+2
BNE HDYNEG
LDA NARG1+3
BEQ HDYPOS
HDYNEG: LDX #$03
HDYNL: LDA FCIRC1,X
STA NARG2,X
DEX
BPL HDYNL
JSR FSUBX ;Subtract from 180. if > 90.
INC ANSN2
HDYPOS: JMP XINT1 ;Make Heading integer
MULCOS: CLC ;Indexes 90-ANGLE-1 entry and following entry
LDA #$5A
SBC NARG1
MULSIN: ASL A ;Multiply by 2 for offset
PHA ;Save index
TAY
INY
INY
LDA GETRM2
INC BANK4K ;Enable bank 2 ghost-memory
LDA SINTB1,Y ;Get the table's entry
STA NARG1
LDA SINTB1+1,Y
STA NARG1+1
LDA SINTB2,Y
STA NARG1+2
LDA SINTB2+1,Y
STA NARG1+3
LDY #TEMPN5
JSR XN1TOY ;Save table value
PLA ;Retrieve index
TAY
INY
INY
LDA SINTB1+2,Y ;Get the next entry for interpolating
STA NARG2
LDA SINTB1+3,Y
STA NARG2+1
LDA SINTB2+2,Y
STA NARG2+2
LDA SINTB2+3,Y
STA NARG2+3
LDY #TEMPN3
JSR XN2TOY ;Save table value
JSR FSUBX ;Get difference of entries in NARG1
LDA GETRM1
LDA GETRM1
DEC BANK4K ;Re-enable bank 1 ghost-memory
RTS
GCLEAR: LDA #$00 ;CLEAR Routine
STA TEMPN3
LDA #$20
STA TEMPNH+1
LDY #$00
STY TEMPNH
D01B: LDA TEMPN3
STA (TEMPNH),Y
JSR D0A2
INY
BNE D01B
INC TEMPNH+1
LDA TEMPNH+1
AND #$1F
BNE D01B
RTS
GPOSN: JSR GNORM
LDA COLR
STA ANSN1
LDX NARG2+2
LDY NARG2+3
LDA NARG2
;falls through
;falls in
D02E: STA GRP2
STX GRP0
STY GRP1
PHA
AND #$C0
STA GTMP4
LSR A
LSR A
ORA GTMP4
STA GTMP4
PLA
STA GTMP4+1
ASL A
ASL A
ASL A
ROL GTMP4+1
ASL A
ROL GTMP4+1
ASL A
ROR GTMP4
LDA GTMP4+1
AND #$1F
ORA #$20
STA GTMP4+1
TXA
CPY #$00
BEQ D063
LDY #$23
ADC #$04
D062: INY
D063: SBC #$07
BCS D062
STY GRP5
TAX
LDA D1EA-256,X
STA GANSN2
TYA
LSR A
LDA ANSN1
D075: STA TEMPN3
BCS D0A2
RTS
D088: BPL D0AE
LDA GANSN2
LSR A
BCS D094
EOR #$C0
D091: STA GANSN2
RTS
D094: DEY
BPL D099
LDY #$27
D099: LDA #$C0
D09B: STA GANSN2
STY GRP5
LDA TEMPN3
D0A2: ASL A
CMP #$C0
BPL D0AD
LDA TEMPN3
EOR #$7F
STA TEMPN3
D0AD: RTS
D0AE: LDA GANSN2
ASL A
EOR #$80
BMI D091
LDA #$81
INY
CPY #$28
BCC D09B
LDY #$00
BCS D09B ;(Always taken)
D0F9: BMI D12B
CLC
LDA GTMP4+1
BIT D1EA
BNE D125
ASL GTMP4
BCS D121
BIT D0F3
BEQ D111
ADC #$1F
SEC
BCS D123 ;(Always taken)
D111: ADC #$23
PHA
LDA GTMP4
ADC #$B0
BCS D11C
ADC #$F0
D11C: STA GTMP4
PLA
BCS D123
D121: ADC #$1F
D123: ROR GTMP4
D125: ADC #$FC
D127: STA GTMP4+1
RTS
D12B: LDA GTMP4+1
D12D: ADC #$04
BIT D1EA
BNE D127
ASL GTMP4
BCC D151
ADC #$E0
CLC
BIT D12D+1
BEQ D153
LDA GTMP4
ADC #$50
EOR #$F0
BEQ D14A
EOR #$F0
D14A: STA GTMP4
LDA #$20
BCC D153
D151: ADC #$E0
D153: ROR GTMP4
BCC D127 ;(Always branches)
D164: PHA
SEC
SBC GRP0
PHA
TXA
SBC GRP1
STA TEMPN6+1
BCS D17C
PLA
EOR #$FF
ADC #$01
PHA
LDA #$00
SBC TEMPN6+1
D17C: STA TEMPN5+1
STA TEMPN7+1
PLA
STA TEMPN5
STA TEMPN7
PLA
STA GRP0
STX GRP1
TYA
CLC
SBC GRP2
BCC D197
EOR #$FF
ADC #$FE
D197: STA TEMPN6
STY GRP2
ROR TEMPN6+1
SEC
SBC TEMPN5
TAX
LDA #$FF
SBC TEMPN5+1
STA TEMPN3+1
LDY GRP5
BCS D1B2 ;(Always taken)
D1AD: ASL A
JSR D088
SEC
D1B2: LDA TEMPN7
ADC TEMPN6
STA TEMPN7
LDA TEMPN7+1
SBC #$00
D1BC: STA TEMPN7+1
LDA ANSNX
BEQ XORHK1
LDA #$FF
BNE XORHK2
XORHK1: LDA (GTMP4),Y
EOR TEMPN3
XORHK2: AND GANSN2
EOR (GTMP4),Y
STA (GTMP4),Y
INX
BNE D1CF
INC TEMPN3+1
BNE D1CF
RTS
D1CF: LDA TEMPN6+1
BCS D1AD
JSR D0F9
CLC
LDA TEMPN7
ADC TEMPN5
STA TEMPN7
LDA TEMPN7+1
ADC TEMPN5+1
BVC D1BC ;(Always taken)
$81
$82
$84
$88
$90
$A0
$C0
D1EA: $1C
D1EB: $FF
D1EC: $FE
$FA
$F4
$EC
$E1
$D4
$C5
$B4
$A1
$8D
$78
$61
$49
$31
$18
$FF
D0F3: $03
GLINE: JSR GNORM
LDA GRP5
LSR A
LDA COLR
JSR D075
LDX NARG2+3
LDA NARG2+2
LDY NARG2
JMP D164
XCHK: LDY #A1L
JSR XN1TOY
JSR XINT1
LDX #NARG1
JSR CHKINT
BCS D3AC1
LDA NARG1+1
BMI XCHKM
BNE D3AC1
LDA NARG1
CMP #$8C
BCS D3AC1
BCC XRTS
XCHKM: CMP #$FF
BNE D3AC1
LDA NARG1
CMP #$74
BCC D3AC1
XRTS: LDX #$03
XCHL: LDA A1L,X
STA XCOR,X
DEX
BPL XCHL
STOX: LDA NARG1
STA EPOINT
LDA NARG1+1
STA EPOINT+1
RTS
D3AC: LDX #$03
D3ACL: LDA A3L,X
STA XCOR,X
DEX
BPL D3ACL
D3AC1: LDA #XOOB ;Error "Out of Bounds"
JMP ERROR
YCHK: LDY #A1L
JSR XN1TOY
LDX #$03
YCHL1: LDA GRPHK1,X
STA NARG2,X
DEX
BPL YCHL1
JSR FMUL ;First multiply by 0.8
JSR XINT1
LDX #NARG1
JSR CHKINT
BCS D3AC
LDA NARG1+1
BMI YCHKM
BNE D3AC
LDA NARG1
CMP #$60
BCC YRTS
BCS D3AC
YCHKM: CMP #$FF
BNE D3AC
LDA NARG1
CMP #$A0
BCC D3AC
YRTS: LDX #$03
YCHL: LDA A1L,X
STA YCOR,X
DEX
BPL YCHL
STOY: LDA NARG1
STA A5L
RTS
GETX: LDY #XCOR
JSR XYTON1
JSR XINT1
JMP STOX
GETY: LDY #YCOR
JSR XYTON1
JSR XINT1
JMP STOY
GSAVX: LDX #$03
GSVXL: LDA XCOR,X
STA A3L,X
DEX
BPL GSVXL
RTS
GNORM: SEC
LDA #$5F
SBC A5L ;Subtract Ycoord from 95.
STA NARG2
GNORM2: CLC
LDA EPOINT
ADC #$8C ;Add 140. to Xcoord
STA NARG2+2
LDA EPOINT+1
ADC #$00
STA NARG2+3
GNORM1: RTS
ZZZZZZ=. ;(Label quickly noticeable in symbol table)
.PAGE
.SBTTL Stored Interpreter Data:
; Monitor data:
CHRTBL: .ASCII "VM<NIG S:."
$05 ;^E
$0D ;(Carriage-return)
$10 ;^P
$0B ;^K
$02 ;^B
SUBTBL: .ADDR VFY
.ADDR MOVE
.ADDR LT
.ADDR SETNRM
.ADDR SETINV
.ADDR GO
.ADDR BLANK
.ADDR BSWTCH
.ADDR SETMOD
.ADDR SETMOD
.ADDR REGDSP
.ADDR CRMON
.ADDR OUTPRT
.ADDR INPRT
.ADDR XMON
RTBL: .ASCII "AXYPS"
; Constants:
FLT10: $83 ;Floating-point constant, 10.0
$50
$00
$00
FCIRC: $88 ;Floating-point constant, 360.0
$5A
$00
$00
FCIRC1: $87 ;Floating-point constant, 180.0
$5A
$00
$00
GRPHK1: $7F ;Floating-point constant, 0.8
$66
$66
$66
.PAGE
; Primitive Address Dispatch Table:
.=SYSTAB*$100 ;Original load area
; System Function address table:
; (Ghost-memory bank 2)
.ADDR SYSBUG ;For INULL, in case of indexing error
.ADDR SPTHNG
.ADDR SWORD
.ADDR SPWRDP
.ADDR SUNSUM
.ADDR SUNDIF
.ADDR SMAKE
.ADDR SOUTPT
.ADDR SSTOP
.ADDR SPRINT
.ADDR STYPE
.ADDR SDEFIN
.ADDR SCLEAR
.ADDR SCNTIN
.ADDR STPPKZ
.ADDR SELSE
.ADDR SSNTNC
.ADDR SBOTH
.ADDR SEITHR
.ADDR XXSFR1 ;Then
.ADDR SNOT
.ADDR PARLOP ;Left-parenthesis
.ADDR XXSFR2 ;Right-parenthesis
.ADDR SIF
.ADDR SRUN
.ADDR SGO
.ADDR SBPT
.ADDR LOGO1 ;Goodbye
.ADDR SGCOLL
.ADDR SNODES
.ADDR SBTFST
.ADDR SFIRST
.ADDR SBTLST
.ADDR SLAST
.ADDR STO
.ADDR SEDIT
.ADDR SEND
.ADDR STEXT
.ADDR SFD
.ADDR SBK
.ADDR SRT
.ADDR SLT
.ADDR SLIST
.ADDR SCS
.ADDR SHOME
.ADDR SPENUP
.ADDR SPENDN
.ADDR SEMPTP
.ADDR SSHOWT
.ADDR SHIDET
.ADDR STS
.ADDR STITLE
.ADDR SFPUT
.ADDR SPO
.ADDR XXSFR3 ;All
.ADDR XXSFR3 ;Names
.ADDR SERASE
.ADDR SREAD
.ADDR SSAVE
.ADDR SREQU
.ADDR STHING
.ADDR SRETRV
.ADDR SSUM
.ADDR SDIF
.ADDR SPROD
.ADDR SDIVID
.ADDR SGRTR
.ADDR SLESS
.ADDR SCOMMT
.ADDR SEQUAL
.ADDR STRCBK
.ADDR SPOTS
.ADDR XXSFR3 ;Titles
.ADDR XXSFR3 ;Procedures
.ADDR SPEEK
.ADDR SPOKE
.ADDR SSUM
.ADDR SDIF
.ADDR SPROD
.ADDR SDIVID
.ADDR SGRTR
.ADDR SLESS
.ADDR SEQUAL
.ADDR SLPUT
.ADDR SRANDM
.ADDR SCTYI
.ADDR SCURSR
.ADDR SRNDMZ
.ADDR SCALL
.ADDR SLISTP
.ADDR SNMBRP
.ADDR SCLINP
.ADDR SCHNGE
.ADDR SRPEAT
.ADDR SSETX
.ADDR SSETY
.ADDR SSETXY
.ADDR SSETH
.ADDR SSETT
.ADDR SXCOR
.ADDR SYCOR
.ADDR SHDING
.ADDR SNDSPL
.ADDR SINT
.ADDR SFULL
.ADDR SMIX
.ADDR SDELET
.ADDR SCATLG
.PAGE
; Error-string address table:
ERRTBL=.+TDIFF-2 ;(Ghost-memory bank 2)
.ADDR XXUOP+TDIFF
.ADDR XXEOL+TDIFF
.ADDR XXUDF+TDIFF
.ADDR XXHNV+TDIFF
.ADDR XXNIP+TDIFF
.ADDR XXNOP+TDIFF
.ADDR XXRPN+TDIFF
.ADDR XXIFX+TDIFF
.ADDR XXVNA+TDIFF
.ADDR XXTIP+TDIFF
.ADDR XXWTA+TDIFF
.ADDR XXUBL+TDIFF
.ADDR XXNTL+TDIFF
.ADDR XXNTF+TDIFF
.ADDR XXELS+TDIFF
.ADDR XXBRK+TDIFF
.ADDR XXLAB+TDIFF
.ADDR XXTHN+TDIFF
.ADDR XXLNF+TDIFF
.ADDR XXEDT+TDIFF
.ADDR XXDEF+TDIFF
.ADDR XXETL+TDIFF
.ADDR XXNED+TDIFF
.ADDR XXOPO+TDIFF
.ADDR XXTML+TDIFF
.ADDR XXDBZ+TDIFF
.ADDR XXNWE+TDIFF
.ADDR XXLNT+TDIFF
.ADDR XXILN+TDIFF
.ADDR XXOFL+TDIFF
.ADDR XXNDF+TDIFF
.ADDR XXCRS+TDIFF
.ADDR XXYNT+TDIFF
.ADDR XXOOB+TDIFF
.ADDR XXIOR+TDIFF
.ADDR XXWTP+TDIFF
.ADDR XXFNF+TDIFF
.ADDR XXDKF+TDIFF
.ADDR XXLKF+TDIFF
.PAGE
; Error Messages:
; (Ghost-memory bank 2)
XXUOP: .ASCII "You don't say what to do with "
$00
$FF
XXEOL: .ASCII "Unexpected end of line"
$FF
XXUDF: .ASCII "You haven't told me how to "
$00
$FF
XXHNV: $00
.ASCII " has no value"
$FF
XXNIP: .ASCII "Nothing inside parenthesis"
$FF
XXNOP: $00
.ASCII " didn't output"
$FF
XXRPN: .ASCII "Unexpected )"
$FF
XXIFX: .ASCII "There's nothing before the "
$00
$FF
XXVNA: .ASCII "You need ( )'s around "
$00
$FF
XXTIP: .ASCII "Too much inside parenthesis"
$FF
XXWTA: $00
.ASCII " doesn't like "
$01
.ASCII " as input"
$FF
XXUBL: $00
.ASCII " is used by LOGO"
$FF
XXNTL: $00
.ASCII " should only be called inside a procedure"
$FF
XXNTF: $00
.ASCII " was given instead of TRUE or FALSE"
$FF
XXELS: .ASCII "ELSE is out of place"
$FF
XXBRK: .ASCII "I was told to pause"
$FF
XXLAB: .ASCII "There's a label in the middle of a line"
$FF
XXTHN: .ASCII "THEN is out of place"
$FF
XXLNF: .ASCII "I can't find the label "
$00
$FF
XXEDT: .ASCII "You're already editing something"
$FF
XXDEF: $00
.ASCII " is already defined"
$FF
XXETL: .ASCII "You can only edit at top level"
$FF
XXNED: .ASCII "You're not in Edit mode"
$FF
XXOPO: .ASCII "You can only say "
$00
.ASCII " to PO, ER, etc."
$FF
XXTML: .ASCII "Too many display commands"
$FF
XXDBZ: .ASCII "You tried to divide by zero"
$FF
XXNWE: .ASCII "You can't do that while in Edit mode"
$FF
XXLNT: .ASCII "Line number too big"
$FF
XXILN: .ASCII "Illegal line number"
$FF
XXOFL: .ASCII "Arithmetic overflow"
$FF
XXNDF: $00
.ASCII " is not defined"
$FF
XXCRS: .ASCII "Cursor coordinates off of screen"
$FF
XXYNT: .ASCII "You need a turtle to do "
$00
$FF
XXOOB: .ASCII "Turtle Out-of-Bounds"
$FF
XXIOR: .ASCII "I/O Error"
$FF
XXWTP: .ASCII "The file is write-protected"
$FF
XXFNF: .ASCII "File not found"
$FF
XXDKF: .ASCII "You have a write-protected disk"
$FF
XXLKF: .ASCII "The file is locked"
$FF
.PAGE
; Primitive table:
; (Ghost-memory bank 2)
PRMTAB =.+TDIFF
0
0
IALL
.ASCII "ALL "
1
0
IBACK
.ASCII "BACK "
1
5
IBTFST
.ASCII "BF "
1
0
IBACK
.ASCII "BK "
1
5
IBTLST
.ASCII "BL "
2
1
IBOTH
.ASCII "BOTH "
1
5
IBTFST
.ASCII "BUTFIRST "
1
5
IBTLST
.ASCII "BUTLAST "
0
0
ICATLG
.ASCII "CATALOG "
0
0
IEDIT
.ASCII "CHANGE "
0
0
IEDIT
.ASCII "CHG "
0
0
ICLEAR
.ASCII "CLEAR "
0
0
ICLINP
.ASCII "CLEARINPUT "
0
0
ICS
.ASCII "CLEARSCREEN "
0
0
ICNTIN
.ASCII "CO "
0
0
ICNTIN
.ASCII "CONTINUE "
0
0
ICS
.ASCII "CS "
2
5
ICURSR
.ASCII "CURSOR "
2
0
IDEFIN
.ASCII "DE "
2
0
IDEFIN
.ASCII "DEFINE "
1
0
IDELET
.ASCII "DELETE "
2
6
IDIF
.ASCII "DIFFERENCE "
0
0
ICHNGE
.ASCII "ED "
0
0
ICHNGE
.ASCII "EDIT "
2
1
IEITHR
.ASCII "EITHER "
0
1
IELSE
.ASCII "ELSE "
1
5
IEMPTP
.ASCII "EMPTY? "
0
0
IEND
.ASCII "END "
2
3
IEQUAL
.ASCII "EQUAL? "
0
0
IERASE
.ASCII "ER "
0
0
IERASE
.ASCII "ERASE "
1
5
IFIRST
.ASCII "F "
1
0
IFORWD
.ASCII "FD "
1
5
IFIRST
.ASCII "FIRST "
1
0
IFORWD
.ASCII "FORWARD "
2
0
IFPUT
.ASCII "FPUT "
0
0
IFULL
.ASCII "FULL "
1
0
IGO
.ASCII "GO "
0
0
IGDBYE
.ASCII "GOODBYE "
2
4
IGREAT
.ASCII "GREATER? "
0
0
IHIDET
.ASCII "HIDETURTLE "
0
0
IHDING
.ASCII "HEADING "
0
0
IHOME
.ASCII "HOME "
0
0
IHIDET
.ASCII "HT "
1
0
IIF
.ASCII "IF "
1
8
IINT
.ASCII "INT "
1
8
IINT
.ASCII "INTEGER "
1
5
ILAST
.ASCII "L "
1
5
ILAST
.ASCII "LAST "
1
0
ILEFT
.ASCII "LEFT "
2
4
ILESS
.ASCII "LESS? "
-3
5
ILIST
.ASCII "LIST "
1
5
ILISTP
.ASCII "LIST? "
2
0
ILPUT
.ASCII "LPUT "
1
0
ILEFT
.ASCII "LT "
2
0
IMAKE
.ASCII "MAKE "
0
0
IMIX
.ASCII "MIX "
0
0
INAMES
.ASCII "NAMES "
0
0
INDSPL
.ASCII "ND "
0
0
INDSPL
.ASCII "NODISPLAY "
1
2
INOT
.ASCII "NOT "
1
5
INMBRP
.ASCII "NUMBER? "
1
0
IOTPUT
.ASCII "OP "
1
0
IOTPUT
.ASCII "OUTPUT "
0
0
IPAUSE
.ASCII "PAUSE "
0
0
IPENDN
.ASCII "PD "
0
0
IPENDN
.ASCII "PENDOWN "
0
0
IPENUP
.ASCII "PENUP "
0
0
IPO
.ASCII "PO "
0
0
IPOTS
.ASCII "POTS "
-2
0
IPRINT
.ASCII "PR "
-2
0
IPRINT
.ASCII "PRINT "
-2
0
ITYPE
.ASCII "PRINT1 "
0
0
IPO
.ASCII "PRINTOUT "
0
0
IPROCS
.ASCII "PROCEDURES "
2
7
IPROD
.ASCII "PRODUCT "
0
0
IPENUP
.ASCII "PU "
2
7
IQUOT
.ASCII "QUOTIENT "
0
0
IRANDM
.ASCII "RANDOM "
0
0
IRNDMZ
.ASCII "RANDOMIZE "
0
0
ICTYI
.ASCII "RC "
1
0
IREAD
.ASCII "READ "
0
0
ICTYI
.ASCII "READCHARACTER "
2
0
IRPEAT
.ASCII "REPEAT "
0
0
IREQST
.ASCII "REQUEST "
0
0
IRETRV
.ASCII "RETRIEVE "
1
0
IRIGHT
.ASCII "RIGHT "
0
0
IREQST
.ASCII "RQ "
1
0
IRIGHT
.ASCII "RT "
1
0
IRUN
.ASCII "RUN "
1
0
ISAVE
.ASCII "SAVE "
-3
5
ISNTNC
.ASCII "SE "
-3
5
ISNTNC
.ASCII "SENTENCE "
1
0
ISETH
.ASCII "SETH "
1
0
ISETH
.ASCII "SETHEADING "
1
0
ISETT
.ASCII "SETT "
1
0
ISETT
.ASCII "SETTURTLE "
1
0
ISETX
.ASCII "SETX "
2
0
ISETXY
.ASCII "SETXY "
1
0
ISETY
.ASCII "SETY "
0
0
ISHOWT
.ASCII "SHOWTURTLE "
0
0
ISHOWT
.ASCII "ST "
0
0
ISTOP
.ASCII "STOP "
2
6
ISUM
.ASCII "SUM "
0
0
ITRCBK
.ASCII "TB "
1
5
ITEXT
.ASCII "TEXT "
0
0
ITHEN
.ASCII "THEN "
1
5
ITHING
.ASCII "THING "
1
5
ITHNGP
.ASCII "THING? "
0
0
ITITLE
.ASCII "TI "
0
0
ITITLE
.ASCII "TITLE "
0
0
ITITLS
.ASCII "TITLES "
0
0
ITO
.ASCII "TO "
0
0
ITRCBK
.ASCII "TRACEBACK "
0
0
ITSTAT
.ASCII "TS "
0
0
ITSTAT
.ASCII "TURTLESTATE "
-3
5
IWORD
.ASCII "WORD "
1
5
IWORDP
.ASCII "WORD? "
0
0
IXCOR
.ASCII "XCOR "
0
0
IYCOR
.ASCII "YCOR "
0
0
ILPAR
.ASCII "( "
0
0
IRPAR
.ASCII ") "
2
7
INPROD
.ASCII "* "
2
6
INSUM
.ASCII "+ "
2
6
INDIF
.ASCII "- "
0
0
IBPT
.ASCII ".BPT "
1
5
ICALL
.ASCII ".CALL "
2
0
IPOKE
.ASCII ".DEPOSIT "
1
0
IPEEK
.ASCII ".EXAMINE "
0
0
IGCOLL
.ASCII ".GCOLL "
0
0
INODES
.ASCII ".NODES "
2
7
INQUOT
.ASCII "/ "
0
0
ICOMNT
.ASCII "; "
2
4
INLESS
.ASCII "< "
2
3
INEQUL
.ASCII "= "
2
4
INGRTR
.ASCII "> "
.PAGE
; V-Primitive table:
; (Ghost-memory bank 2)
VPRMTB =.+TDIFF
INSUM
.WORD INFSUM
1
INDIF
.WORD INFDIF
1
ILPAR
.WORD LPAR
1
IRPAR
.WORD RPAR
1
IIF
.WORD LIF
1
IELSE
.WORD LELSE
1
ITHEN
.WORD LTHEN
1
INAMES
.WORD NAMES
1
IALL
.WORD ALL
1
ITITLS
.WORD TITLES
1
IPROCS
.WORD PROCS
1
IEND
.WORD LEND
1
IPO
.WORD PO
1
IPO
.WORD PRNTOT
2
IPOTS
.WORD POTS
1
IERASE
.WORD ER
1
IERASE
.WORD ERASE
2
ITITLE
.WORD TI
1
ITITLE
.WORD LTITLE
2
ISTOP
.WORD LSTOP
1
ICOMNT
.WORD COMMNT
1
VPRMTE =.+TDIFF
.PAGE
; Miscellaneous text strings:
; (Ghost-memory page 2)
HELSTR=.+TDIFF
.ASCII "Welcome to Apple Logo!"
$0D
.ASCII "Preliminary Version"
$0D
.ASCII "Assembled 8/06/80" ;(Use correct date when assembling)
$0D
$00
LBUG1=.+TDIFF
.ASCII "LOGO bug; exiting..."
$0D
$00
RDRER1=.+TDIFF
.ASCII "Reader error: Too many sublists"
$0D
$00
RDRER2=.+TDIFF
.ASCII "You have mismatched brackets"
$0D
$00
ZPMSG1=.+TDIFF
.ASCII "No storage left!"
$0D
$00
ZPMSG2=.+TDIFF
.ASCII "Stopped!"
$0D
$00
ZPMSG3=.+TDIFF
.ASCII "Evaluator overflow!"
$0D
$00
WRNMSG=.+TDIFF
.ASCII "Please ERASE something:"
$0D
$00
ERRM1=.+TDIFF
.ASCII "At level "
$00
ERRM2=.+TDIFF
.ASCII " in line "
$00
ERRM3=.+TDIFF
.ASCII " of "
$00
ERRM4=.+TDIFF
.ASCII " is too big for "
$00
SENDM=.+TDIFF
.ASCII " defined"
$0D
$00
PNMSG1=.+TDIFF
.ASCII " is "
$00
PNMSG2=.+TDIFF
.ASCII "MAKE "
$00
TBMSG1=.+TDIFF
.ASCII "We're now at top-level."
$0D
$00
TBMSG2=.+TDIFF
.ASCII "We're currently inside "
$00
CHGMSG=.+TDIFF
.ASCII " APPLE LOGO SCREEN EDITOR "
$00
TOMSG=.+TDIFF
.ASCII "TO "
$00
ENDMSG=.+TDIFF
.ASCII "END"
$0D
$00
WAITM=.+TDIFF
.ASCII "Please wait..."
$0D
$00
SAVEM=.+TDIFF
$8D
$84 ;^D for DOS
$C2 ;B these have their high
$D3 ;S bits turned on because
$C1 ;A that's the way that
$D6 ;V Apple does it and DOS
$C5 ;E understands it.
$00
SAVEM2=.+TDIFF
$AC ;,
$C1 ;A
$A4 ;$
$B2 ;2
$B0 ;0
$B0 ;0
$B0 ;0
$AC ;,
$CC ;L
$A4 ;$
$00
LOADM=.+TDIFF
$8D
$84 ;^D for DOS
$C2 ;B
$CC ;L
$CF ;O
$C1 ;A
$C4 ;D
$00
DELETM=.+TDIFF
$8D
$84
$C4 ;D
$C5 ;E
$CC ;L
$C5 ;E
$D4 ;T
$C5 ;E
$00
CATLGM=.+TDIFF
$8D
$84
$C3 ;C
$C1 ;A
$D4 ;T
$C1 ;A
$CC ;L
$CF ;O
$C7 ;G
$8D
$00
LOGOM=.+TDIFF
$AE
$CC
$CF
$C7
$CF
$00
;Start of Sine table (91 4-byte flonums, first 2 bytes only)
SINTB1=.-2+TDIFF
$00
$00
$7A
$47
$7B
$47
$7B
$6B
$7C
$47
$7C
$59
$7C
$6B
$7C
$7C
$7D
$47
$7D
$50
$7D
$58
$7D
$61
$7D
$6A
$7D
$73
$7D
$7B
$7E
$42
$7E
$46
$7E
$4A
$7E
$4F
$7E
$53
$7E
$57
$7E
$5B
$7E
$5F
$7E
$64
$7E
$68
$7E
$6C
$7E
$70
$7E
$74
$7E
$78
$7E
$7C
$7F
$40
$7F
$41
$7F
$43
$7F
$45
$7F
$47
$7F
$49
$7F
$4B
$7F
$4D
$7F
$4E
$7F
$50
$7F
$52
$7F
$53
$7F
$55
$7F
$57
$7F
$58
$7F
$5A
$7F
$5C
$7F
$5D
$7F
$5F
$7F
$60
$7F
$62
$7F
$63
$7F
$64
$7F
$66
$7F
$67
$7F
$68
$7F
$6A
$7F
$6B
$7F
$6C
$7F
$6D
$7F
$6E
$7F
$6F
$7F
$71
$7F
$72
$7F
$73
$7F
$74
$7F
$74
$7F
$75
$7F
$76
$7F
$77
$7F
$78
$7F
$79
$7F
$79
$7F
$7A
$7F
$7B
$7F
$7B
$7F
$7C
$7F
$7C
$7F
$7D
$7F
$7D
$7F
$7E
$7F
$7E
$7F
$7E
$7F
$7F
$7F
$7F
$7F
$7F
$7F
$7F
$7F
$7F
$7F
$7F
$7F
$7F
$80
$40
$80 ;Extra entry for interpolation routine
$40
;Start of Sine table (91 4-byte flonums, second 2 bytes only)
SINTB2=.-2+TDIFF
$00
$00
$7C
$2D
$79
$63
$2F
$1D
$6E
$3E
$3F
$5B
$09
$82
$CB
$51
$41
$B2
$18
$2E
$E8
$6A
$B1
$B7
$73
$67
$2C
$C9
$DD
$30
$41
$F7
$90
$2B
$D8
$DF
$1B
$BD
$58
$6F
$8E
$A2
$BE
$01
$E6
$38
$06
$F5
$1F
$E5
$30
$B6
$39
$17
$38
$B9
$2F
$4A
$1C
$7C
$00
$00
$EC
$C5
$D4
$65
$B6
$BB
$93
$A2
$6A
$F4
$3C
$8C
$08
$46
$CD
$FF
$8D
$92
$46
$DD
$F9
$BE
$A6
$12
$4B
$B9
$EA
$91
$82
$7A
$13
$54
$9D
$00
$1F
$5F
$9A
$53
$0D
$BF
$79
$85
$DD
$89
$39
$B0
$8D
$DE
$D9
$F9
$1D
$E7
$59
$8F
$8C
$D7
$B7
$A8
$D9
$EC
$F3
$8A
$04
$6D
$0C
$80
$0B
$AF
$01
$E5
$EF
$0F
$D3
$1A
$AD
$F6
$7F
$90
$47
$D9
$06
$C1
$BC
$38
$68
$32
$0A
$A0
$A3
$75
$32
$A6
$B8
$29
$33
$F1
$A5
$F6
$0E
$2E
$6C
$92
$C1
$1B
$0B
$C1
$4C
$7E
$83
$4F
$B0
$2E
$D3
$18
$EC
$0A
$FB
$02
$00
$00
$00 ;Extra entry for interpolation routine
$00
ENDTAB=. ;End of Ghost-memory bank 2 storage
.=SYSTAB*$100-$1006
JMP LOGO ;Vector for BRUN to work from DOS
JMP LOGO1 ;Re-entry point for crash or GOODBYE
.=$95F5 ;(Causes assembler to signal error if program crashes into DOS)
$00
.END