1
0
mirror of https://github.com/PDP-10/its.git synced 2026-04-04 13:17:24 +00:00
Files
PDP-10.its/src/budd/live.palx
Lars Brinkhoff 0c9864e7e5 LIVE - Phil Budne's PALX Game of Life.
Runs in 11SIM and SIMH 11/45 mode.  Uses VT52 escape codes, so use a
VT52 capable terminal emulator, or use the CRTSTY option SIMULATE VT52.
2018-06-02 07:06:43 +02:00

606 lines
13 KiB
Plaintext
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
.TITLE LIVE -- A LIFE PROGRAM FOR VT52'S
.SBTTL PHIL BUDNE@DEC, DECEMBER 1982
; ************* STAND ALONE DEFINITIONS
TKS==177560
TKB==TKS+2
TPS==TKS+4
TPB==TKS+6
R0=%0
R1=%1
R2=%2
R3=%3
R4=%4
R5=%5
SP=%6
PC=%7
.=1000
; ************ END STAND ALONE DEFS
STAR='*
SPACE=<' >
; CELL STATE BITS
DEAD=0 ;* DEAD, STABLE (MUST BE ZERO)
ALIVE=1 ;* LIVE, STABLE
CHANGE=2
BIRTH=DEAD+CHANGE ;* DEAD -> LIVE SOON
DEATH=ALIVE+CHANGE ;* LIVE -> DEAD SOON
SCRWID=70. ;DISPLAY WIDTH 1..SCRWID
SCRLEN=24. ;DISPLAY LENGTH 1..SCRLEN
SCRPAD=10. ;AMOUNT TO PAD SCREEN BY ON EACH SIDE
SCRPDW=SCRPAD ;WIDTH PADDING
SCRPDL=SCRPAD*2 ;LENGTH PADDING
FLDWID=SCRWID+<2*SCRPDW> ;ACTUAL CELL FIELD WIDTH
FLDLEN=SCRLEN+<2*SCRPDL> ;ACTUAL CELL FIELD LENGTH
WIDTH=FLDWID+2 ;WIDTH W/ BUFFER CELLS
LENGTH=FLDLEN+2 ;LENGTH W/ BUFFER ROWS
TOP=WIDTH+1 ;FIRST ACTIVE CELL
BOT=<LENGTH-1>*WIDTH-2 ;LAST ACTIVE CELL
VTOP=TOP+<WIDTH*SCRPDL>+SCRPDW ;FIRST DISPLAYED CELL
XTOP=1 ;X CURSOR POS FOR VTOP
YTOP=1 ;Y CURSOR POS FOR VTOP
; 000000000000000000
; 0xXXXXXXXXXXXXXXX0
; 0XXXXXXXXXXXXXXXX0
; 0XX,...........XX0
; 0XX............XX0
; 0XX............XX0
; 0XX............XX0
; 0XX............XX0
; 0XXXXXXXXXXXXXXXX0
; 0XXXXXXXXXXXXXXXX0
; 000000000000000000
;
; . CELLS IN BOARD, FLD, SCR ,=VTOP
; X CELLS IN BOARD, FLD x=TOP
; 0 CELLS IN BOARD
UP=-WIDTH ;OFFSET TO GO UP 1 ROW
DOWN=WIDTH ;DOWN 1 RON
RIGHT=1 ;RIGHT 1 CELL
LEFT=-1 ;LEFT 1 CELL
; LEFT RIGHT
; -------------------------
; UP ! . ! . ! . !
; ! . ! . ! . !
; DOWN ! . ! . ! . !
; -------------------------
; SUML SUMC SUMR
SUML: .BLKW 1 ;SUM OF CELLS IN LEFT COLM
SUMC: .BLKW 1 ;SUM OF CELLS IN CENTER COLM
SUMR: .BLKW 1 ;SUM OF CELLS IN RIGHT COLM
STATES: .BLKW 4 ;SUM OF CELLS IN EACH STATE
XPOS: .BLKW 1 ;EDITING X POSN
YPOS: .BLKW 1 ;EDITING Y POSN
CELPOS: .BLKW 1 ;EDITING POINTER INTO CELLS
XTEMP: .BLKW 1
YTEMP: .BLKW 1
BRDSIZ=WIDTH*LENGTH
BOARD: .BLKB BRDSIZ
.EVEN
.SBTTL PROGRAM STARTS HERE
START: MOV #1000, SP ;GIVE US A STACK *** STAND ALONE ***
BEGIN: JSR PC, CM.CLR ;CLEAR SCREEN
TOPLVL: JSR PC, GETC
; HERE WITH CMD CHAR IN R0
1$: MOV #COMTBL, R1
2$: CMP (R1)+, R0 ;THIS IT?
BEQ 3$ ;YEP!
TST (R1)+ ;NO, DISCARD ADDR
BNE 2$ ;END?
MOV #'G-100, R0 ;FLEEP
JSR PC, PUTC
BR TOPLVL
3$: JSR PC, @(R1) ;GO!!, RETURN WITH CARRY SET IF ERROR
BR TOPLVL ;GET ANOTHER CMD
COMTBL: .WORD SPACE, CM.SPA ;SPACE - ERASE + EAST
.WORD STAR, CM.NEW ;STAR - NEW CELL + EAST
.WORD '., CM.NEW ;DOT - NEW CELL + EAST
.WORD '?, CM.HLP ;? - BE HELPFUL
.WORD 'S, CM.TOG ;S - TOGGLE
.WORD 'W, CM.N ;W - NORTH
.WORD 'X, CM.S ;X - SOUTH
.WORD 'D, CM.E ;D - EAST
.WORD 'A, CM.W ;A - WEST
.WORD 'E, CM.NE ;E - NORTH EAST
.WORD 'Q, CM.NW ;Q - NORTH WEST
.WORD 'C, CM.SE ;C - SOUTH EAST
.WORD 'Z, CM.SW ;Z - SOUTH WEST
.WORD '5, CM.TOG ;5 - TOGGLE
.WORD '8, CM.N ;8 - NORTH
.WORD '2, CM.S ;2 - SOUTH
.WORD '6, CM.E ;6 - EAST
.WORD '4, CM.W ;4 - WEST
.WORD '9, CM.NE ;9 - NORTH EAST
.WORD '7, CM.NW ;7 - NORTH WEST
.WORD '3, CM.SE ;3 - SOUTH EAST
.WORD '1, CM.SW ;1 - SOUTH WEST
.WORD '0, CM.SPA ;0 - CLEAR, ADVANCE
.WORD 'G, CM.RUN ;G - GO!
.WORD 'K, CM.CLR ;K - CLEAR SCREEN
.WORD 'H, CM.HLP ;H - HELP!!
.WORD 'R, CM.REF ;R - REFRESH
.WORD 33, CM.ESC ;ESC - DO ESCAPE PROCESSING
.WORD 'B-100, CM.W ;^B - WEST (ALA EMACS)
.WORD 'D-100, CM.KILL ;^D - ERASE
.WORD 'F-100, CM.E ;^F - EAST (ALA EMACS)
.WORD 'H-100, CM.W ;^H - WEST
.WORD 'J-100, CM.S ;^J - SOUTH
.WORD 'L-100, CM.REF ;^L - REFRESH
.WORD 'N-100, CM.S ;^N - SOUTH (ALA EMACS)
.WORD 'P-100, CM.N ;^P - NORTH (ALA EMACS)
.WORD 'Z-100, CM.QUIT ;^Z - QUIT
.WORD 177, CM.DEL ;DEL - RUBOUT
.WORD -1, 0
CM.HLP: JSR PC, CLRSCR ;CLEAR THE SCREEN
MOV #HLPMES, R1 ;POINT TO TEXT
JSR PC, PUTS ;OUTPUT IT
JSR PC, GETC ;GET A CHAR
JMP CM.REF ;RETURN, REFRESH
CM.ESC:
;;; JSR PC, CHKC ;GET ESCAPE DISPATCH CHAR
;;; BCS 2$ ;WELL, MAYBE NOT
JSR PC, GETC ;ALWAYS GET CHAR IN R0
MOV #ESCTBL, R1 ;POINT TO TABLE
1$: CMP (R1)+, R0 ;THIS IT?
BEQ 3$ ;YEP!
TST (R1)+ ;NO, DISCARD ADDR
BNE 1$ ;END?
2$: JMP FLEEP ;YES, WE'VE BEEN HAD!!
3$: JMP @(R1) ;GO!!, RETURN STATUS TO TOP
ESCTBL: .WORD 'A, CM.N ;<ESC>A - NORTH ON VT52 KEYPAD
.WORD 'B, CM.S ;<ESC>B - SOUTH ON VT52 KEYPAD
.WORD 'C, CM.E ;<ESC>C - EAST ON VT52 KEYPAD
.WORD 'D, CM.W ;<ESC>D - WEST ON VT52 KEYPAD
.WORD 'P, CM.RUN ;<ESC>P - BLU ON VT52 KEYPAD == RUN
.WORD 'Q, CM.CLR ;<ESC>Q - RED ON VT52 KEYPAD == CLEAR
.WORD 'R, RETT ;<ESC>R - GRY ON VT52 KEYPAD == NO-OP
.WORD 0, 0
CM.RUN: JSR PC, DOGEN ;DO IT!!
JSR PC, FIXSCR ;FIX UP SCREEN
TST STATES+<ALIVE*2> ;ANY LIVING CELLS
BEQ 3$ ;NO!!
MOV STATES+<BIRTH*2>, R0
ADD STATES+<DEATH*2>, R0
BEQ 2$ ;STABLE
1$: JSR PC, CHKC ;ANY INPUT?
BCC 4$ ;YES, RETURN
; MOV R1, SLPSEC ;SECONDS TO SLEEP
; BEQ CM.RUN ;NONE
; JSR PC, SLEEP ;DOZE
BR CM.RUN ;LOOP
2$: ; "STABLE"
3$: ; "ALL DEAD"
4$: ; "HALTED"
JMP CM.HOM ;HOME THE CURSOR, RETURN TRUE
FIXSCR: JMP UPDATE
CM.DEL: JSR PC, CM.W ;GO WEST..
BCC CM.KIL ;OK?, NOW KILL
RTS PC
CM.KIL: JSR PC, GO.ERA ;ERASE A CELL
MOV #SPACE, R0
JSR PC, PUTC
JSR PC, CURLFT
CM.RTT: JMP RETT
CM.TOG: JSR PC, GO.TOG ;TOGGLE A CELL
BR CM.RTT
CM.NEW: JSR PC, GO.DEP ;DEPOSIT A CELL
CM.DEP: MOV #STAR, R0
BR CM.ER2
CM.REF: JSR PC, FRESH
BR CM.RTT
CM.N: JSR PC, GO.UP ;TRY TO GO UP
BCS FLEEP ;NO GO
JSR PC, CURUP ;MOVE CURSOR
BR RETT
CM.S: JSR PC, GO.DWN ;TRY TO GO DOWN
BCS FLEEP ;SORRY!
JSR PC, CURDWN ;MOVE CURSOR
BR RETT
CM.SPA: JSR PC, GO.ERA ;ERASE
CM.ERA: MOV #SPACE, R0 ;SPACE
CM.ER2: JSR PC, PUTC
JSR PC, CURLFT ;GO BACK LEFT
CM.E: JSR PC, GO.RGH ;TRY TO GO RIGHT
BCS FLEEP ;FRAID NOT
JSR PC, CURRGT ;MOVE CURSOR
BR RETT
CM.W: JSR PC, GO.LFT ;TRY TO GO LEFT
BCS FLEEP ;SORRY CHARLIE
JSR PC, CURLFT ;MOVE CURSOR
BR RETT
CM.NE: JSR PC, CM.N ;NORTH
BCS FLEEP ;NO
JSR PC, CM.E ;EAST
BCC RETT ;OK
JSR PC, CM.S ;EAST LOST, FIX UP
BR FLEEP
CM.NW: JSR PC, CM.N ;NORTH
BCS FLEEP ;NO
JSR PC, CM.W ;WEST
BCC RETT ;OK
JSR PC, CM.S ;WEST LOST, FIX UP
BR FLEEP
CM.SE: JSR PC, CM.S ;SOUTH
BCS FLEEP ;NO
JSR PC, CM.E ;EAST
BCC RETT ;OK
JSR PC, CM.N ;EAST LOST, FIX UP
BR FLEEP
CM.SW: JSR PC, CM.S ;SOUTH
BCS FLEEP ;NO
JSR PC, CM.W ;WEST
BCC RETT ;OK
JSR PC, CM.N ;WEST LOST, FIX UP
BR FLEEP
FLEEP: MOV #'G-100, R0 ;CTRL-G
JSR PC, PUTC ;SAY IT
BR RETF ;SAY YOU ARE SORRY
CM.CLR: MOV #BOARD+TOP, R0 ;START OF ACTIVE BOARD
1$: MOVB #DEAD, (R0)+ ;MAKE DEAD
CMP R0, #BOARD+BOT ;DONE?
BLT 1$ ;NOPE
JSR PC, CLRSCR ;ZAP SCREEN
CM.HOM: JSR PC, CURHOM ;HOME CURSOR
JSR PC, GO.HOM ;HOME EDIT POINTERS
BR RETT
CM.QUI: JSR PC, DOQUIT ;ENVIRONMENT DEPENDANT
BR RETT
.SBTTL CELL MANIPULATION
GO.HOM: MOV #1, XPOS
MOV #1, YPOS
MOV #BOARD+VTOP, CELPOS
RTS PC
GO.DEP: MOVB #ALIVE, @CELPOS ;LIVE CELL
RTS PC
GO.TOG: TSTB @CELPOS ;DEAD CELL?
BEQ GO.DEP ;YES, MAKE LIVE
GO.ERA: MOVB #DEAD, @CELPOS ;DEAD CELL
RTS PC
GO.UP: DEC YPOS ;GO UP 1 LINE
BEQ 1$ ;TOO FAR?
ADD #UP, CELPOS ;MOVE CELL POINTER UP
BR RETT
1$: INC YPOS ;FIX POSN
RETF: SEC ;SET CARRY
RTS PC
GO.DWN: CMP YPOS, #SCRLEN ;COMPARE POSN TO SCREEN LENGTH
BEQ RETF ;ON THE EDGE NOW
INC YPOS ;ELSE, DOWN A LINE
ADD #DOWN, CELPOS ;AND UPDATE CELL POINTER
RETT: CLC ;HAPPY RETURN
RTS PC
GO.LFT: DEC XPOS ;OVER ONE ON X AXIS
BEQ 1$ ;OOOPS!
ADD #LEFT, CELPOS ;FIX CELL POINTER TOO
BR RETT ;GOOD RETURN
1$: INC XPOS ;FIXUP POSN
BR RETF ;FAIL
GO.RGH: CMP XPOS, #SCRWID ;ON THE EDGE
BEQ RETF ;YES, GO NO FURTHER
INC XPOS ;SLIDE OVER ONE
ADD #RIGHT, CELPOS ;SHIFT CELL POINTER
BR RETT
.SBTTL DOGEN - DO NEXT GENERATION
;CALL:
; JSR PC, DOGEN
;RETURNS:
; CHANGE BITS SET IN BOARD
DOGEN: MOV #BOARD+TOP, R0
CLR STATES+<DEAD*2> ;CLEAR DEAD COUNT
CLR STATES+<ALIVE*2> ;CLEAR ALIVE COUNT
CLR STATES+<BIRTH*2> ;CLEAR BIRTH COUNT
CLR STATES+<DEATH*2> ;CLEAR DEATH TOLL
BEGROW: MOV #FLDWID, R1 ;LIVE CELLS IN A ROW
CLR SUML ;NO LIVE CELLS TO THE LEFT
CLR SUMC ;ACCUMULATE CENTER SUM
BITB #ALIVE, UP(R0) ;ABOVE MAY HAVE CHANGE BIT SET
BEQ 1$ ;ALIVE?
INC SUMC ;IT WAS!
1$: TSTB DOWN(R0) ;BOTTOM CELL NOT CHANGED
BEQ 2$ ;ALIVE?
INC SUMC ;BUMP
2$: TSTB (R0) ;NOR CURRENT CELL
BEQ DORGHT ;ALIVE?
INC SUMC ;YES
BR DORGHT ;JOIN THE 'HUMAN' RACE
NXTCEL: INC R0 ;BUMP UP ONE CELL
MOV SUMC, SUML ;CENTER COLM BECOMES LEFT
MOV SUMR, SUMC ;AND RIGHT BECOMES CENTER
DORGHT: CLR R2 ;CALCULATE RIGHT SUM
BITB #ALIVE, UP+RIGHT(R0) ;UPPER RIGHT MIGHT BE CHANGED
BEQ 1$ ;ALIVE?
INC R2 ;YEP!
1$: BITB #ALIVE, RIGHT(R0) ;RIGHT, MAY HAVE CHANGED
BEQ 2$ ;ALIVE?
INC R2 ;BUMP COUNT
2$: TSTB RIGHT+DOWN(R0) ;BOTTOM RIGHT
BEQ 3$ ;ALIVE?
INC R2
3$: MOV R2, SUMR ;SAVE AS RIGHT SUM
ADD SUMC, R2 ;ADD IN CENTER COLM
ADD SUML, R2 ;AND LEFT COLM
TSTB (R0) ;LOOK AT CURRENT CELL
BNE 4$ ;LIVE?
MOVB DEDTAB(R2), R2 ;GET NEW STATUS FOR DEAD CELL
BR GONEXT
4$: MOVB LIVTAB-1(R2), R2 ;GET NEW STATUS FOR LIVE CELL
GONEXT: MOVB R2, (R0) ;STORE NEW CELL STATE
ASL R2 ;MAKE WORD OFFSET
INC STATES(R2) ;TALLY STATES
SOB R1, NXTCEL ;TICK OFF THIS CELL
CMP #BOT+BOARD, R0 ;DONE WITH BOTTOM ROW?
BLE DONE
ADD #WIDTH-FLDWID+1, R0 ;GO TO FRONT OF NEXT ROW
BR BEGROW ;AND START THE NEW ROW!
.POPJ:
DONE: RTS PC
; NEIGHBORS= 0 1 2 3 4 5 6 7 8
LIVTAB: .BYTE DEATH, DEATH, ALIVE, ALIVE, DEATH, DEATH, DEATH, DEATH, DEATH
DEDTAB: .BYTE DEAD, DEAD, DEAD, BIRTH, DEAD, DEAD, DEAD, DEAD, DEAD
.SBTTL FRESH - REPAINT SCREEN
FRESH: JSR PC, CLRSCR ;CLEAR THE SCREEN
MOV #BOARD+VTOP, R4 ;BOARD POINTER
MOV #1, R1 ;CURSOR NOW AT X=1
MOV R1, R2 ;AND Y=1
MOV #YTOP, YTEMP ;STARTING ROW
MOV #SCRLEN+1, R5 ;LINE COUNT
BR FR.ROW ;START A ROW
FR.NXT: INC XTEMP ;NEXT CELL IN A ROW
INC R4 ;UPDATE CELL PTR
FR.1ST: MOVB (R4), R0 ;GET CELL CONTENTS
BEQ FR.GO ;EMPTY, KEEP GOING
MOVB FR.TAB(R0), (R4) ;GET NEW STATE
BEQ FR.GO ;QUIT IF NOW DEAD
CMP R1, XTEMP ;IS X CORRECT?
BNE 1$ ;NO, USE CURSOR FUNCTIONS
CMP R2, YTEMP ;AND Y?
BEQ 2$ ;YES, JUST TYPE *
1$: MOV XTEMP, R1
MOV YTEMP, R2
JSR PC, GOPOS
2$: MOV #STAR, R0
JSR PC, PUTC ;PRINT LIVE CELL
INC R1 ;ADD 1 TO X
FR.GO: SOB R3, FR.NXT ;TICK OFF THIS CELL
DEC R5 ;TICK OFF THIS ROW
BEQ FR.RET ;DONE
INC YTEMP ;NO, START FRESH ROW
ADD #WIDTH-SCRWID+1, R4 ;GO TO FRONT OF NEXT ROW
FR.ROW: MOV #XTOP, XTEMP ;CURSOR SHOULD BE HERE
MOV #SCRWID, R3 ;WIDTH OF A LINE
BR FR.1ST
FR.RET: RTS PC
; DEAD, ALIVE, BIRTH, DEATH
FR.TAB: .BYTE DEAD, ALIVE, ALIVE, DEAD
.SBTTL UPDATE - CHANGE SCREEN
UPDATE: MOV #BOARD+VTOP, R4 ;BOARD POINTER
CLR R1 ;UNKNOWN CURSOR POSN
CLR R2 ;DITTO
MOV #YTOP, YTEMP ;ROW=1
MOV #SCRLEN+1, R5 ;LINES+1 TO UPDATE
BR UP.ROW ;START A ROW
UP.NXT: INC XTEMP ;NEXT CELL IN A ROW
INC R4 ;UPDATE CELL PTR
UP.1ST: MOVB (R4), R0 ;GET CELL CONTENTS
BEQ UP.GO ;EMPTY, KEEP GOING
MOVB UP.TAB(R0), (R4) ;GET NEW STATE
MOVB UP.CHR(R0), R0 ;GET NEW CHAR
BEQ UP.GO ;QUIT IF NO CHANGE
CMP R1, XTEMP ;IS X CORRECT?
BNE 1$ ;NO, USE CURSOR FUNCTIONS
CMP R2, YTEMP ;AND Y?
BEQ 2$ ;YES, JUST TYPE CHAR
1$: MOV XTEMP, R1 ;LOAD NEW XTEMP
MOV YTEMP, R2 ;AND YTEMP
MOV R0, -(SP) ;SAVE R0
JSR PC, GOPOS ;CURSOR ADDRESSING
MOV (SP)+, R0 ;RESTORE R0
2$: JSR PC, PUTC ;PRINT LIVE CELL (CHAR IN R0)
INC R1 ;ADD 1 TO X
UP.GO: SOB R3, UP.NXT ;TICK OFF THIS CELL
DEC R5 ;TICK OFF THIS LINE
BEQ UP.RET ;ALL DONE?
INC YTEMP ;START FRESH ROW
ADD #3, R4 ;GO TO FRONT OF NEXT ROW
UP.ROW: MOV #XTOP, XTEMP
MOV #FLDWID, R3 ;WIDTH OF A LINE
BR UP.1ST
UP.RET: RTS PC
; DEAD, ALIVE, BIRTH, DEATH
UP.TAB: .BYTE DEAD, ALIVE, ALIVE, DEAD
UP.CHR: .BYTE 0, 0, STAR, SPACE
.SBTTL CURSOR PRIMATIVES - VT52 ONLY
CLRSCR: MOV #CLRSTR, R1
JMP PUTS
; R1=X, R2=Y, 1 BASED
GOPOS: MOV #33, R0 ;ESC
JSR PC, PUTC
MOV #'Y, R0 ;Y
JSR PC, PUTC
MOV R2, R0
ADD #31., R0
JSR PC, PUTC ;Y POSN
MOV R1, R0
ADD #31., R0
BR PUTC ;X POSN
CLRSTR: .BYTE 33, 'H, 33, 'J, 0
.EVEN
CURUP: MOV #'A, R1
BR PUTESC
CURDWN: MOV #'B, R1
BR PUTESC
CURLFT: MOV #'D, R1
BR PUTESC
CURRGT: MOV #'C, R1
BR PUTESC
CURHOM: MOV #'H, R1
BR PUTESC
PUTESC: MOV #33, R0
JSR PC, PUTC
MOV R1, R0
BR PUTC
; ********* STAND ALONE GOODIES *********
PUTS: MOVB (R1)+, R0
BEQ 1$
JSR PC, PUTC
BR PUTS
1$: RTS PC
PUTC: TSTB @#TPS ;WAIT FOR PRINTER NOT BUSY
BPL PUTC
MOVB R0,@#TPB ;PRINT
RTS PC
GETC: TSTB @#TKS ;WAIT FOR A CHAR
BPL GETC
MOVB @#TKB,R0 ;INPUT
RTS PC
CHKC: TSTB @#TKS ;A CHAR?
BPL 1$ ;NOPE
MOVB @#TKB,R0 ;INPUT
CLC ;HAPPY RET
RTS PC
1$: SEC ;SAD RETURN
RTS PC
DOQUIT: HALT
RTS PC
.SBTTL HELP TEXT
CR='M-100
LF='J-100
.MACRO LINE STR
.ASCII \STR\<CR><LF>
.ENDM
HLPMES:
LINE <Hello and welcome to LIVE !!>
LINE <>
LINE <Movement Commands:>
LINE <Q W E 7 8 9 ^P>
LINE <A D 4 6 ^B ^F>
LINE <Z X C 1 2 3 ^N>
LINE <>
LINE <Character(s) Action>
LINE <============ ======>
LINE <.* Create cell>
LINE <G Start>
LINE <K Clear screen>
LINE <0,SPACE Clear cell>
LINE <S5 Toggle cell>
LINE <H? This mess>
LINE <R,^L Refresh screen>
LINE <^J Down line>
LINE <^H Move Left>
LINE <^D Clear cell>
LINE <^Z Exit>
LINE <DEL Rubout>
LINE <>
.ASCIZ /(type any key to return)/
.END START