WeeGUI/applesoft.s
Quinn Dunki ac965177c8 - Compressed AppleSoft command table into half as many bytes
- Improved some AppleSoft error messages
- Integer arguments in AppleSoft now handle signed values as well as unsigned
- Fixed a bug in string arguments
- Added a temp string argument type, whereby the string is pointed to within the AppleSoft source
- Added &CURSR
- Added &PRINT
- Added &SCR
- Added &SCRBY
- Added &ERASE
- Fixed WGPrint not clipping top properly if last line is short and above the plane
- Fixed decorated window titles not rendering properly
2014-09-23 15:33:51 -07:00

867 lines
18 KiB
ArmAsm

;
; applesoft.s
; Applesoft API via the & extension point
;
; Created by Quinn Dunki on 8/15/14.
; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Applesoft ROM entry points and constants
;
LINNUML = $0050 ; Scratch pad for calculating line numbers (LSB)
LINNUMH = $0051 ; Scratch pad for calculating line numbers (MSB)
CURLINL = $0075 ; Current line number (LSB)
CURLINH = $0076 ; Current line number (MSB)
CHRGET = $00b1 ; Advances text point and gets character in A
CHRGOT = $00b7 ; Returns character at text pointer in A
TXTPTRL = $00b8 ; Current location in BASIC listing (LSB)
TXTPTRH = $00b9 ; Current location in BASIC listing (MSB)
FAC = $009d ; Floating point accumulator
AMPVECTOR = $03f5 ; Ampersand entry vector
ERROR = $d412 ; Reports error in X
NEWSTT = $d7d2 ; Advance to next Applesoft statement
GOTO = $d93e ; Entry point of Applesoft GOTO
LINGET = $da0c ; Read a line number (16-bit integer) into LINNUM
FRMNUM = $dd67 ; Evaluate an expression as a number and store in FAC
CHKCOM = $debe ; Validates current character is a ',', then gets it
SYNCHR = $dec0 ; Validates current character is what's in A
AYINT = $e10c ; Convert FAC to 8-bit signed integer
GETBYT = $e6f8 ; Gets an integer at text pointer, stores in X
GETNUM = $e746 ; Gets an 8-bit, stores it X, skips past a comma
TOKEN_GOSUB = $b0 ; Applesoft's token for GOSUB
TOKEN_HOME = $97 ; Applesoft's token for HOME
TOKEN_PRINT = $ba ; Applesoft's token for PRINT
TOKEN_MINUS = $c9 ; Applesoft's token for a minus sign
ERR_UNDEFINEDFUNC = 224
ERR_SYNTAX = 16
ERR_ENDOFDATA = 5
ERR_TOOLONG = 176
MAXCMDLEN = 6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGInitApplesoft
; Sets up Applesoft API
;
WGInitApplesoft:
pha
lda #$4c ; Patch in our jump vector for &
sta AMPVECTOR
lda #<WGAmpersand
sta AMPVECTOR+1
lda #>WGAmpersand
sta AMPVECTOR+2
pla
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersand
; The entry point from Applesoft. Applesoft text pointer
; will be positioned two after the '&', and accumulator will
; contain first character after the '&'
; Side effects: Clobbers S0
;
WGAmpersand:
tsx ; Start by caching a valid stack state to return to Applesoft,
stx WG_STACKPTR ; in case we need to do so in a hurry
sta SCRATCH0
SAVE_AXY
SAVE_ZPP
ldy #0
ldx SCRATCH0
WGAmpersand_parseLoop:
txa
beq WGAmpersand_matchStart ; Check for end-of-statement (CHRGET handles : and EOL)
cmp #'('
beq WGAmpersand_matchStart
sta WGAmpersandCommandBuffer,y
jsr CHRGET
tax
iny
cpy #MAXCMDLEN+1
bne WGAmpersand_parseLoop
WGAmpersand_parseFail:
ldx #ERR_UNDEFINEDFUNC
jsr ERROR
bra WGAmpersand_done
WGAmpersand_matchStart:
lda #0
sta WGAmpersandCommandBuffer,y ; Null terminate the buffer for matching
ldy #0
ldx #0 ; Command buffer now contains our API call
phx ; We stash the current command number on the stack
WGAmpersand_matchLoop:
lda WGAmpersandCommandBuffer,y
beq WGAmpersand_matchPossible
cmp WGAmpersandCommandTable,x
bne WGAmpersand_matchNext ; Not this one
iny
inx
bra WGAmpersand_matchLoop
WGAmpersand_matchPossible:
lda WGAmpersandCommandTable,x
beq WGAmpersand_matchFound ; Got one!
WGAmpersand_matchNext:
pla ; Advance index to next commmand in table
inc
pha
asl
asl
asl
tax
cpx #WGAmpersandCommandTableEnd-WGAmpersandCommandTable
beq WGAmpersand_matchFail ; Hit the end of the table
ldy #0
bra WGAmpersand_matchLoop
WGAmpersand_matchFound:
pla ; This is now the matching command number
inc
asl
asl
asl
tay
lda WGAmpersandCommandTable-2,y ; Prepare an indirect JSR to our command
sta WGAmpersand_commandJSR+1 ; Self-modifying code!
lda WGAmpersandCommandTable-1,y
sta WGAmpersand_commandJSR+2
; Self-modifying code!
WGAmpersand_commandJSR:
jsr WGAmpersand_done ; Address here overwritten with command
bra WGAmpersand_done
WGAmpersand_matchFail:
pla ; We left command number on the stack while matching
ldx #ERR_UNDEFINEDFUNC
jsr ERROR
WGAmpersand_done:
RESTORE_ZPP
RESTORE_AXY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersandBeginArguments
; Begins reading an ampersand argument list
; Side effects: Clobbers all registers
WGAmpersandBeginArguments:
pha
lda #'('
jsr SYNCHR ; Expect opening parenthesis
pla
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersandNextArgument
; Prepares for the next argument in the list
; Side effects: Clobbers all registers
WGAmpersandNextArgument:
jsr CHRGOT
jsr CHKCOM ; Verify parameter separator
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersandEndArguments
; Finishes reading an ampersand argument list
; Side effects: Clobbers all registers
WGAmpersandEndArguments:
pha
lda #')'
jsr SYNCHR ; Expect closing parenthesis
pla
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersandIntArgument
; Reads an integer argument for the current command
; OUT A : The argument
; Side effects: Clobbers all registers
WGAmpersandIntArgument:
jsr CHRGOT
cmp #TOKEN_MINUS
beq WGAmpersandIntArgument_signed
jsr GETBYT
txa
rts
WGAmpersandIntArgument_signed:
jsr CHRGET
jsr GETBYT
txa
eor #$ff
inc
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersandAddrArgument
; Reads a 16-bit pointer (or integer) argument for the current command
; OUT X : The argument (LSB)
; OUT Y : The argument (MSB)
; Side effects: Clobbers all registers
WGAmpersandAddrArgument:
jsr CHRGOT
jsr LINGET
ldx LINNUML
ldy LINNUMH
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersandStrArgument
; Reads a string argument for the current command in PARAM0/1.
; This string is copied into privately allocated memory.
; OUT X : Pointer to a stored copy of the string (LSB)
; OUT Y : Pointer to a stored copy of the string (MSB)
; Side effects: Clobbers P0/P1 and all registers
WGAmpersandStrArgument:
lda #'"'
jsr SYNCHR ; Expect opening quote
lda TXTPTRL ; Allocate for, and copy the string at TXTPTR
sta PARAM0
lda TXTPTRH
sta PARAM1
lda #'"' ; Specify quote as our terminator
jsr WGStoreStr
WGAmpersandStrArgument_loop:
jsr CHRGET ; Consume the string for Applesoft
beq WGAmpersandStrArgument_done
cmp #'"' ; Check for closing quote
bne WGAmpersandStrArgument_loop
WGAmpersandStrArgument_done:
lda #'"'
jsr SYNCHR ; Expect closing quote
ldx PARAM0
ldy PARAM1
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersandTempStrArgument
; Reads a string argument for the current command in PARAM0/1.
; This string is pointed to IN PLACE, and NOT copied.
; OUT X : Pointer to a stored copy of the string (LSB)
; OUT Y : Pointer to a stored copy of the string (MSB)
; OUT A : String length
; Side effects: Clobbers P0/P1 and all registers
WGAmpersandTempStrArgument:
lda #'"'
jsr SYNCHR ; Expect opening quote
lda TXTPTRL ; Grab current TXTPTR
sta PARAM0
lda TXTPTRH
sta PARAM1
WGAmpersandTempStrArgument_loop:
jsr CHRGET ; Consume the string for Applesoft
beq WGAmpersandTempStrArgument_done
cmp #'"' ; Check for closing quote
bne WGAmpersandTempStrArgument_loop
WGAmpersandTempStrArgument_done:
lda #'"'
jsr SYNCHR ; Expect closing quote
; Compute the 8-bit distance TXTPTR moved. Note that we can't simply
; count in the above loop, because CHRGET will skip ahead unpredictable
; amounts
sec
lda TXTPTRL
sbc PARAM0
dec
ldx PARAM0 ; Return results
ldy PARAM1
; pla
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Ampersand API entry points
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersand_HOME
; Clears the screen
; &HOME
WGAmpersand_HOME:
jsr WGClearScreen
jsr WGBottomCursor
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersand_DESK
; Render the desktop
; &DESK
WGAmpersand_DESK:
jsr WGDesktop
jsr WGBottomCursor
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersand_WINDW
; Create a view
; &WINDW(id,style,x,y,width,height,canvas width,canvas height)
WGAmpersand_WINDW:
jsr WGAmpersandBeginArguments
jsr WGAmpersandIntArgument
sta WGAmpersandCommandBuffer+0
jsr WGAmpersandNextArgument
jsr WGAmpersandIntArgument
ora #VIEW_STYLE_APPLESOFT ; Flag this as an Applesoft-created view
sta WGAmpersandCommandBuffer+1
jsr WGAmpersandNextArgument
jsr WGAmpersandIntArgument
sta WGAmpersandCommandBuffer+2
jsr WGAmpersandNextArgument
jsr WGAmpersandIntArgument
sta WGAmpersandCommandBuffer+3
jsr WGAmpersandNextArgument
jsr WGAmpersandIntArgument
sta WGAmpersandCommandBuffer+4
jsr WGAmpersandNextArgument
jsr WGAmpersandIntArgument
sta WGAmpersandCommandBuffer+5
jsr WGAmpersandNextArgument
jsr WGAmpersandIntArgument
sta WGAmpersandCommandBuffer+6
jsr WGAmpersandNextArgument
jsr WGAmpersandIntArgument
sta WGAmpersandCommandBuffer+7
jsr WGAmpersandEndArguments
CALL16 WGCreateView,WGAmpersandCommandBuffer
jsr WGEraseView
jsr WGPaintView
jsr WGBottomCursor
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersand_CHKBX
; Create a checkbox
; &CHKBX(id,x,y,"title")
WGAmpersand_CHKBX:
jsr WGAmpersandBeginArguments
jsr WGAmpersandIntArgument
sta WGAmpersandCommandBuffer+0
jsr WGAmpersandNextArgument
jsr WGAmpersandIntArgument
sta WGAmpersandCommandBuffer+1
jsr WGAmpersandNextArgument
jsr WGAmpersandIntArgument
sta WGAmpersandCommandBuffer+2
jsr WGAmpersandNextArgument
jsr WGAmpersandStrArgument
stx WGAmpersandCommandBuffer+3
sty WGAmpersandCommandBuffer+4
jsr WGAmpersandEndArguments
CALL16 WGCreateCheckbox,WGAmpersandCommandBuffer
LDY_ACTIVEVIEW ; Flag this as an Applesoft-created view
lda #VIEW_STYLE_APPLESOFT
ora WG_VIEWRECORDS+4,y
sta WG_VIEWRECORDS+4,y
jsr WGPaintView
jsr WGBottomCursor
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersand_BUTTN
; Create a button
; &BUTTN(id,x,y,width,lineNum,"title")
WGAmpersand_BUTTN:
jsr WGAmpersandBeginArguments
jsr WGAmpersandIntArgument
sta WGAmpersandCommandBuffer+0
jsr WGAmpersandNextArgument
jsr WGAmpersandIntArgument
sta WGAmpersandCommandBuffer+1
jsr WGAmpersandNextArgument
jsr WGAmpersandIntArgument
sta WGAmpersandCommandBuffer+2
jsr WGAmpersandNextArgument
jsr WGAmpersandIntArgument
sta WGAmpersandCommandBuffer+3
jsr WGAmpersandNextArgument
jsr WGAmpersandAddrArgument
stx WGAmpersandCommandBuffer+4
sty WGAmpersandCommandBuffer+5
jsr WGAmpersandNextArgument
jsr WGAmpersandStrArgument
stx WGAmpersandCommandBuffer+6
sty WGAmpersandCommandBuffer+7
jsr WGAmpersandEndArguments
CALL16 WGCreateButton,WGAmpersandCommandBuffer
LDY_ACTIVEVIEW ; Flag this as an Applesoft-created view
lda #VIEW_STYLE_APPLESOFT
ora WG_VIEWRECORDS+4,y
sta WG_VIEWRECORDS+4,y
jsr WGPaintView
jsr WGBottomCursor
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersand_SEL
; Select a view
; &SEL(id)
WGAmpersand_SEL:
jsr WGAmpersandBeginArguments
jsr WGAmpersandIntArgument
jsr WGSelectView
jsr WGAmpersandEndArguments
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersand_FOC
; Focuses selected view
; &FOC
WGAmpersand_FOC:
jsr WGViewFocus
jsr WGBottomCursor
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersand_FOCN
; Focuses next view
; &FOCN
WGAmpersand_FOCN:
jsr WGViewFocusNext
jsr WGBottomCursor
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersand_FOCP
; Focuses previous view
; &FOCP
WGAmpersand_FOCP:
jsr WGViewFocusPrev
jsr WGBottomCursor
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersand_ACT
; Takes action on focused view
; &ACT
WGAmpersand_ACT:
jsr WGViewFocusAction
jsr WGBottomCursor
bvs WGAmpersand_ACTGosub
rts
WGAmpersand_ACTGosub:
jmp WGGosub ; No coming back from an Applesoft GOSUB!
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersand_STACT
; Sets the callback for the selected view
; &STACT(lineNum)
WGAmpersand_STACT:
jsr WGAmpersandBeginArguments
jsr WGAmpersandAddrArgument
stx PARAM0
sty PARAM1
jsr WGAmpersandEndArguments
jsr WGViewSetAction
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersand_TITLE
; Sets the title for the selected view
; &TITLE("title")
WGAmpersand_TITLE:
jsr WGAmpersandBeginArguments
jsr WGAmpersandStrArgument
stx PARAM0
sty PARAM1
jsr WGAmpersandEndArguments
jsr WGViewSetTitle
jsr WGPaintView
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersand_CURSR
; Sets the cursor position in selected viewspace
; &CURSR(x,y)
WGAmpersand_CURSR:
jsr WGAmpersandBeginArguments
jsr WGAmpersandIntArgument
pha
jsr WGAmpersandNextArgument
jsr WGAmpersandIntArgument
pha
jsr WGAmpersandEndArguments
ply
plx
jsr WGSetCursor
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersand_PRINT
; Prints a string in the selected view at the local cursor
; &PRINT("string")
WGAmpersand_PRINT:
jsr WGAmpersandBeginArguments
jsr WGAmpersandTempStrArgument
stx PARAM0
sty PARAM1
pha
jsr WGAmpersandEndArguments
; We're pointing to the string directly in the Applesoft
; source, so we need to NULL-terminate it for printing. In
; order to avoid copying the whole thing, we'll do something
; kinda dirty here.
pla
tay
lda (PARAM0),y ; Cache the byte at the end of the string
pha
lda #0
sta (PARAM0),y ; Null-terminate the string in-place
jsr WGPrint
pla
sta (PARAM0),y ; Put original byte back
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersand_SCR
; Sets scroll position of selected view
; &SCR(x,y)
WGAmpersand_SCR:
jsr WGAmpersandBeginArguments
jsr WGAmpersandIntArgument
pha
jsr WGAmpersandNextArgument
jsr WGAmpersandIntArgument
pha
jsr WGAmpersandEndArguments
pla
jsr WGScrollY
pla
jsr WGScrollX
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersand_SCRBY
; Adjusts scroll position of selected view by a delta
; &SCRBY(x,y)
WGAmpersand_SCRBY:
jsr WGAmpersandBeginArguments
jsr WGAmpersandIntArgument
pha
jsr WGAmpersandNextArgument
jsr WGAmpersandIntArgument
pha
jsr WGAmpersandEndArguments
pla
jsr WGScrollYBy
pla
jsr WGScrollXBy
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersand_GOSUB
; A custom gosub, because we can. Only for testing at the moment
; &GOSUB
WGAmpersand_GOSUB:
lda #$e8
sta PARAM0
lda #$03
sta PARAM1
jmp WGGosub
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGAmpersand_ERASE
; Erases the contents of the selected view
; &ERASE
WGAmpersand_ERASE:
jsr WGEraseViewContents
jsr WGBottomCursor
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGBottomCursor
; Leave the cursor state in a place that Applesoft is happy with
;
WGBottomCursor:
SAVE_AY
lda #0
sta CH
sta OURCH
lda #23
sta CV
sta OURCV
lda TEXTLINES_H+23
sta BASH
lda TEXTLINES_L+23
sta BASL
RESTORE_AY
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WGGosub
; Performs an Applesoft GOSUB to a line number
; PARAM0: Line number (LSB)
; PARAM1: Line number (MSB)
;
WGGosub:
; Can't come back from what we're about to do, so cleanup from the
; original Ampersand entry point now! This is some seriously voodoo
; shit we're gonna pull here.
ldx WG_STACKPTR
txs
; Fake an Applesoft GOSUB by pushing the same stuff it would do
lda TXTPTRH
pha
lda TXTPTRL
pha
lda CURLINH
pha
lda CURLINL
pha
lda #TOKEN_GOSUB
pha
; Here's the tricky bit- we jump into Applesoft's GOTO
; just after the part where it reads the line number. This
; allows us to piggy back on the hard work of finding the
; line number in the Applesoft source code, and storing
; it in the TXTPTR (thus performing the jump portion of
; a GOSUB). Since GOSUB normally falls through into GOTO,
; by faking the setup portion of the GOSUB, then leaving
; the state as GOTO expects it, we can fake the entire
; process to GOSUB to a line number we specify
lda PARAM0
sta LINNUML
lda PARAM1
sta LINNUMH
jsr GOTO+3
; The goto has pointed the interpreter at the subroutine,
; so now advance to the next statement to continue executing.
; We'll never regain control, which is why we had to clean
; up from the ampersand entry before we got here.
jmp NEWSTT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Applesoft API state
;
WGAmpersandCommandBuffer:
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
WGAmpersandCommandBufferEnd:
.byte 0 ; Make sure this last byte is always kept as a terminator
WG_STACKPTR: ; A place to save the stack pointer for tricky Applesoft manipulation
.byte 0
; Jump table for ampersand commands.
; Each row is 8 bytes (5 for name, NULL terminator, 2 for address)
;
; Note the strange byte values amidst some strings- this is because
; all text is tokenized before we receive it, so reserved words may
; be compressed
;
WGAmpersandCommandTable:
.byte TOKEN_HOME,0,0,0,0,0
.addr WGAmpersand_HOME
.byte "DESK",0,0
.addr WGAmpersand_DESK
.byte "WINDW",0
.addr WGAmpersand_WINDW
.byte "CHKBX",0
.addr WGAmpersand_CHKBX
.byte "BUTTN",0
.addr WGAmpersand_BUTTN
.byte "SEL",0,0,0
.addr WGAmpersand_SEL
.byte "FOC",0,0,0
.addr WGAmpersand_FOC
.byte "FOCN",0,0
.addr WGAmpersand_FOCN
.byte "FOCP",0,0
.addr WGAmpersand_FOCP
.byte "ACT",0,0,0
.addr WGAmpersand_ACT
.byte "STACT",0
.addr WGAmpersand_STACT
.byte "TITLE",0
.addr WGAmpersand_TITLE
.byte "CURSR",0
.addr WGAmpersand_CURSR
.byte "SCR",0,0,0
.addr WGAmpersand_SCR
.byte "SCRBY",0
.addr WGAmpersand_SCRBY
.byte "ERASE",0
.addr WGAmpersand_ERASE
.byte TOKEN_PRINT,0,0,0,0,0
.addr WGAmpersand_PRINT
;.byte TOKEN_GOSUB,0,0,0,0,0,0,0,0,0,0,0,0,0 ; For internal testing of the procedural gosub
;.addr WGAmpersand_GOSUB
WGAmpersandCommandTableEnd: