;> TaskMan

 [ OSTYPE=1
; Vector number definitions

WrchV * 3
RdchV * 4
ChangeEnvironmentV * &1E

; handler numbers
CallBackEnvNum * 7
EscHanEnvNum   * 9
EvtHanEnvNum   * 10

; and the SWIs
XOS_Claim             * (1:SHL:17)+&1F
XOS_Release           * (1:SHL:17)+&20
XOS_ChangeEnvironment * (1:SHL:17)+&40
OS_GenerateError      *  &2B

  ]

TASKLNK LDRB R0,[ARGP,#TASKLINK]
 EORS R0,R0,#255
 STRB R0,[ARGP,#TASKLINK]
 BNE TASKLNK1
 BL INFORR
 = "TaskLinked",0
 B EDITOR

TASKLNK1 BL INFORR
 = "TaskUnLinked",0
 B EDITOR

TASKMAN LDRB R1,[AP,#TASKQ]
 TEQ R1,#0
 BEQ TASKNEW
 BL PROMPT
 = "Kill this task? [Y/N]:",0
 BL AREADC
 BIC R0,R0,#" "
 TEQ R0,#"Y"
 BNE EDITST
 MOV R0,#0
 STRB R0,[AP,#TASKQ]
 STRB R0,[ARGP,#TASK]
 MOV R1,#0
 SWI OPEN ;close any files
 BL GETTASKGAP
 B EDITST
;recover gap from stopped task, free vectors if on Arthur

GETTASKGAP
 [ OSTYPE=1
 MOV  R0, #WrchV
 ADRL R1, TwinsWrch
 MOV  R2, #0
 SWI  XOS_Release
 MOV  R0, #RdchV
 ADR R1, TwinsRdch
 SWI  XOS_Release
 MOV  R0, #ChangeEnvironmentV
 ADRL R1, TwinsEnvironmentCheck
 SWI  XOS_Release
 ]

 LDR R0,[AP,#GE]
 LDR R1,[AP,#END]
 LDR R2,[AP,#TOP]
 SUB R2,R2,#1
 STR R2,[AP,#END]
 CMP R0,R1
 BEQ GETTASKGAP2
GETTASKGAP1 LDRB R3,[R1,#-1]!
 STRB R3,[R2,#-1]!
 CMP R0,R1
 BNE GETTASKGAP1
GETTASKGAP2 STR R2,[AP,#GE]
 MOV PC,R14

TASKNEW LDRB R2,[ARGP,#TASK]
 TEQ R2,#0
 BEQ TASKNEW1
 BL MSG
 = "Can't start another task, there already is one running",0
 ALIGN 

CFILE STRB R1,[ARGP,#CFILEH]
DOCFIL
 [ OSTYPE=1
 MOV R1, #0
 STRB R1, SWIGrabbing
 TEQP PC, #0       ; ensure user mode, irqson
 |
 LDR R1,OLDHAN
 BL SVCADR
 ]

 BL SETARGP
 LDRB R1,[ARGP,#CFILEH]
 LDR R2,TASKAP
 LDR R2,[R2,#END] ;WRITEC
 MOV R0,#"*"
 STRB R0,[R2],#1
 MOV R0,#" "
 STRB R0,[R2],#1
 MOV R7,R2
DOCFL1 SWI BGET
 BCS CFILEX
 STRB R0,[R2],#1
 TEQ R0,#LF
 TEQNE R0,#CR
 TEQNE R0,#0
 BNE DOCFL1
 MOV R0,#TERM
 STRB R0,TASKDIRTY
 STRB R0,[R2,#-1]
 LDR R1,TASKAP
 STR R2,[R1,#END] ;WRITEC

 [ OSTYPE=1
 MOV R1, #1
 STRB R1, SWIGrabbing
 |
 ADR R1,SVCHN1
 STR R1,EVTLOC
 BL SVCADR
 ]

 STR R2,OLDHAN
 B RUNONE

CFILEX MOV R0,#0
 SWI OPEN
 B ENDTSK

TASKNEW1 LDR R1,[AP,#GS]
 LDR R2,[AP,#GE]
 SUB R0,R2,R1
 CMP R0,#4096
 BCS TASKNEW2
 BL MSG
 = "Insufficient memory free in the buffer to start the task",0
 ALIGN

TASKNEW2 STMFD SP!,{R0,R2}
 BL PROMPT
 = "Command: ",0
 ADD R4,ARGP,#TASKBUF+512
 BL READLR
 ADD R2,ARGP,#TASKBUF+512
 BL MOVBUF
 LDMFD SP!,{R0,R1}
 LDR R3,[AP,#END]
 MOV R4,R0,LSR #1 ;number of bytes allocated
 SUB R0,R1,R4
 STR R0,[AP,#GE] ;dest
 SUB R2,R3,R1 ;number to move
 BL MOVEBYTESUP
 SUB R1,R3,R4
 STR R1,[AP,#END]
 MOV R0,#TERM
TASKNEWGAP2 STRB R0,[R1],#1
 CMP R1,R3
 BCC TASKNEWGAP2

 [ OSTYPE=1
 MOV R5, #255
 STRB R5, [ARGP, #TASKBUF] ; initialise readc buffer
 ]

 ADD R5,ARGP,#TASKBUF
 STR R5,BUFPTR ;Stash address for ReadC
 STR AP,TASKAP
 ADR R0,MYREGS
 STMIA R0,{R0-R15}
 ADR R0,EXTTASK
 STR R0,MYREGS+15*4
 ADR R8,MYHANDLERS
 BL SAVEHANDLERS
 BL SETSTART
 ADR R0,ENDTASK
 MOV R2,#0
 MOV R3,#2
 MOV R4,#0
 MOV R5,#0
 MOV R6,#0
 MOV R7,#0
 SWI SETENV
 [ OSTYPE=1
 SWI ENTERSWI ; avoid callback for a while
 MOV R0,#1
 STRB R0,samsinterlock
 ADR R0,HISREGS
 ADR R1,CALLROUT
 SWI CALLBACK
 MOV R0, #1
 STRB R0, [ARGP, #TASK]
 STRB R0, [AP, #TASKQ]
 MOV R0, #14            ; now have some events
 MOV R1, #2
 SWI BYTE
 MOV R1, #4
 SWI BYTE

; Now ntercept vectors

 MOV R0, #WrchV
 ADR R1, TwinsWrch
 MOV R2, #0
 SWI XOS_Claim
 MOV R0, #RdchV
 ADR R1, TwinsRdch
 SWI XOS_Claim
 MOV R0, #ChangeEnvironmentV
 ADR R1, TwinsEnvironmentCheck
 SWI XOS_Claim

 MOV R1, #1
 STRB R1, SWIGrabbing
 |
 ADR R1,SVCHN1
 STR R1,EVTLOC
 BL SVCADR
 ]
 STR R2,OLDHAN
 ADD R7,ARGP,#STRACC
RUNONE MOV R0,R7
 [ OSTYPE=1
 SWI ENTERSWI              ; avoid callback etc.
 SWI CLI  + (1:SHL:17)
 MOV R1, #0
 STRB R1, SWIGrabbing
 BVS taskCLI_error 
 MOV R0,#198
 MOV R1,#0
 MOV R2,#0
 SWI BYTE
 TEQ R1,#0
 BNE CFILE
 BL SETARGP
 LDRB R1,[ARGP,#CFILEH]
 TEQ R1,#0
 BNE DOCFIL
 BL  StopTask
 ADR R0, NoTaskBwana
 SWI OS_GenerateError ;  BL MSG didn't reset something vital

NoTaskBwana
 &  42                 ; random error number: we don't really care
 = "No task was run as a result of that command",0
 ALIGN

StopTask
 MOV  R9, R14
 MOV  R0, #0
 STRB R0, [AP, #TASKQ]
 STRB R0, [ARGP, #TASK]
 STRB R0, samsinterlock
 MOV  R0, #13
 MOV  R1, #2
 SWI  BYTE
 MOV  R1, #4
 SWI  BYTE
 TEQP PC, #IFLAG
 BL   GETTASKGAP
 ADR  R8,MYHANDLERS
 BL   GETHANDLERS

; now point callback at an empty handler
 ADR  R0, HISREGS
 ADR R1, nullcallback
 SWI  CALLBACK
 SWI  INTON
 MOV  PC, R9

taskCLI_errorP & 0
taskCLI_error
 STR R0,taskCLI_errorP
 BL SETARGP
 BL StopTask
 LDR R0,taskCLI_errorP
 SWI OS_GenerateError     ; longjump to Twin error handler

 |
 SWI CLI
 LDR R1,OLDHAN
 BL SVCADR
 MOV R0,#198
 MOV R1,#0
 MOV R2,#0
 SWI BYTE
 TEQ R1,#0
 BNE CFILE
 BL SETARGP
 LDRB R1,[ARGP,#CFILEH]
 TEQ R1,#0
 BNE DOCFIL
 BL GETTASKGAP
 ADR R8,MYHANDLERS
 BL GETHANDLERS
 BL MSG
 = "No task was run as a result of that command",0
 ALIGN
 ]
EXTTASK MOV R0,#255
 STRB R0,[ARGP,#TASKBUF]
 MOV R0,#1
 [ OSTYPE<>1
 STRB R0,[ARGP,#TASK]
 STRB R0,[AP,#TASKQ]
 ]
 STRB R0,TASKDIRTY
 STRB R0,TASKDIRTY+1
 B REENTER
EVTHAM1
 [ OSTYPE=1
 LDRB R12,samsinterlock     ; R12 meaningless in Arthur.
  [ 1=0 
; insert this code to demonstrate the need for this interlock.
   CMP    R12,#0
   MOVEQ  R11,#&3400000
   MOVEQ  R12,#&4000000F
   STREQ  R12,[R11]
   MOVEQ  R12,#0
  ]

 MOV R11,#0
 STRB R11,samsinterlock
 MOV PC,R14
CALLROUT

 TEQP PC,#IFLAG          ; APT modification
 B SVCH2X
samsinterlock = 0
SWIGrabbing   = 0
 |
 TEQ R12,#0
 STRNE R14,EVTLOC
 MOVNE PC,R14
 LDMFD R13!,{R0,R1,R2,R11,R12,R14}
 B SVCHN2A
 ]
BUFPTR & 0
TASKAP & 0
TASKDIRTY & 0
OLDHAN & 0
EVTLOC & 0
MYREGS
 % 16*4
MYHANDLERS
 % 12*4
HISREGS
 % 16*4
HISHANDLERS
 % 12*4

 [ OSTYPE=1

; the vector routines

TwinsWrch ROUT
   LDRB   R12, SWIGrabbing
   CMP    R12, #0
   MOVEQ  PC, R14          ; not for us - pass on
   LDR    R14, TASKAP
   LDR    R12, [R14, #END]
   CMP    R0, #&7F
   MOVEQ  R0, #TERM
   STREQB R0, [R12, #-1]!
   BEQ    %FT01
   CMP    R0, #TERM :EOR: 7
   STRNEB R0, [R12], #1

01 STR    R12, [R14, #END]
   MOV    R12, #4
   STRB   R12, TASKDIRTY
   LDMFD  R13!, {R14}
   MOVS   PC, R14

TwinsRdch ROUT
   LDRB   R12, SWIGrabbing
   CMP    R12, #0
   MOVEQ  PC, R14          ; not for us - pass on
   STMFD  R13!, {R10}
   MOV    R10, R13         ; keep for error trapping

   TEQP   PC, #0           ; user mode, ints on: let callback go
02 SWI    INTOFF+(1:SHL:17)
   LDR    R12, BUFPTR
01 LDRB   R0, [R12], #1
   CMP    R0, #254
   BEQ    %BT01
   SWICS  INTON+(1:SHL:17)
   BCS    %BT02
   SWI    ENTERSWI + (1 :SHL: 17)
   MOV    R14, #254
   STRB   R14, [R12, #-1]

; now the gungy bit: if Twin has task swapped and had an error, then
; the MOS has flattened the supervisor stack, so we better not pull anything!
   CMP    R10, R13
   BNE    twintaskrdch_Failed

   LDMFD  R13!, {R10, R14}
   BICS   PC, R14, #(1 :SHL: 29)  ; back with C clear.

twintaskrdch_Failed
   ADR    R0, ttr_err
   SWI    OS_GenerateError        ; shame if they called the X form!!!
ttr_err
   &      17                      ; sort of Escape...
   =     "Task swap failure - sorry!",0
   ALIGN

TwinsEnvironmentCheck
  LDRB    R12, SWIGrabbing
  CMP     R12, #0
  MOVEQ   PC, R14          ; not for us - pass on
  CMP     R0, #CallBackEnvNum  ; CallBack handler change?
  MOVEQ   R3, #0
  CMPNE   R0, #EvtHanEnvNum    ; or event handler?

; it would seem reasonable to suggest that Twin could sit on EventV,
; instead of needing the event handler: only thing is that e.g. the C
; library probably aborts if it's (default) event handler is ever entered.
; Needs more investigation, really.

;;;;;;  CMPNE   R0, #EscHanEnvNum    ; escape handler?
  MOVEQ   R2, #0
  MOVEQ   R1, #0
  MOV     PC, R14

 |
;svchn1 runs one CLI statement. If there has been an event it stops the program
SVCHN1 STR R0,HISREGS
 STR R1,HISREGS+4
 STR R2,HISREGS+8
 STR R14,HISREGS+14*4
 BIC R2,R14,#&FC000003
 LDR R2,[R2,#-4]
 BICS R2,R2,#&FF000000
 BEQ SVCN00
 CMP R2,#READC
 BLS SVCN0
 CMP R2,#READLINE
 BCS SVCN1
 LDR R1,EVTLOC
 TEQ R1,#0
 ADR R1,SVCHN2
 BLNE SVCADR
TASKDOSWI ADR R14,HISREGS
 LDMIA R14,{R0,R1,R2}
 LDR R14,HISREGS+14*4
 LDR PC,OLDHAN
 ]

ENDTASK TEQP PC,#0
 BL SETARGP
 LDRB R0,[ARGP,#CFILEH]
 TEQ R0,#0
 BNE DOCFIL
ENDTSK LDR R1,TASKAP
 MOV R0,#0
 STRB R0,[R1,#TASKQ] ;[ARGP,#TASK] is set when the status is painted
 STRB R0,[ARGP,#CFILEH]
 STRB R0,TASKDIRTY+1
 LDR AP,TASKAP
 BL GETTASKGAP

 [ OSTYPE<>1
 B SVCH2X ;continue main Twin
;svchn2 runs no cli statements but does save state and re runs Twin
SVCHN2 SUB R14,R14,#4
SVCHN2A STR R14,HISREGS+15*4 ;pc
 TEQP PC,#IFLAG ;user mode with no irq
 STR R0,HISREGS ;r0
 ADR R0,(HISREGS+4)
 STMIA R0,{R1-R14} ;all his regs!
SVCH2X
 LDR R1,OLDHAN
 BL SVCADR
 |
SVCH2X
 MOV R1, #0
 STRB R1, SWIGrabbing
 ]

 SWI INTOFF
 MOV R0,#13
 MOV R1,#2
 SWI BYTE ;keyboard event: disable
 MOV R1,#4
 SWI BYTE ;VSYNC event: disable
 ADR R8,HISHANDLERS
 BL SAVEHANDLERS
 ADR R8,MYHANDLERS
 BL GETHANDLERS
 ADR R0,MYREGS
 LDMIA R0,{R0-R14}
 SWI ENTERSWI
 ADR R14,(MYREGS+15*4)
 LDMIA R14,{PC}^ ;run me again

TASKRD LDRB R0,[ARGP,#TASK]
 TEQ R0,#1
 BNE TASKR2
 LDRB R0,[ARGP,#ERRCTL]
 TEQ R0,#255
 BEQ TASKR2 ;don't run task in cursor copy mode since can't press ESCAPE
 STMFD SP!,{AP,UPDATE,R14}
 LDR AP,TASKAP
 LDRB R0,[AP,#ONSCREEN]
 TEQ R0,#0
 BEQ TASKRD1A
 LDRB R0,TASKDIRTY
 CMP R0,#1
 BEQ TASKPAINT1
 LDRB R0,[ARGP,#TASKLINK]
 TEQ R0,#0
 BNE TASKPAINTUNLINK
 LDR R4,[AP,#END]
 BL GPFWD
 BL NORMAL
 STRB R6,[AP,#X]
 LDRB R0,[AP,#BSM]
 STRB R0,[AP,#Y]
TASKPAINTUNLINK LDRB R0,[AP,#MODIFY]
 TEQ R0,#4
 MOV R0,#1
 STRNEB R0,[AP,#MODIFY]
 BL CUROFF
 MOV UPDATE,#FULLSCREEN
 MOV R7,#0
 BL REDRMN
 LDRB R0,TASKDIRTY+1
 TEQ R0,#1
 BEQ TASKPAINT2
TASKPAINT1 LDRB R0,TASKDIRTY+1
 TEQ R0,#1
 BEQ TASKRD1A
 BL DECWIN
 BL CUROFF
 LDR R0,[ARGP,#USINGAP]
 CMP R0,AP
 MOVEQ R1,#1
 MOVNE R1,#0
 BL STATOT
 MOV R0,#0
 STRB R0,[ARGP,#TASK]
TASKPAINT2 LDMFD SP,{AP,UPDATE}
 BL DECWIN
 BL CSRXY
 BL CURON
 MOV R0,#1
 STRB R0,TASKDIRTY
 STRB R0,TASKDIRTY+1
TASKRD1A LDMFD SP!,{AP,UPDATE,R14}
 MOV R1,#0
 MOV R2,#0
 STMFD SP!,{R14}
 BL AINKEY
 LDMFD SP!,{R14}
 BCC TASKR1
 TEQ R2,#&1B
 BEQ ESCAPE
 LDRB R0,[ARGP,#TASK]
 TEQ R0,#1
 BNE TASKRD
 MOV R0,#0
 STR R0,EVTLOC
 ADR R0,MYREGS
 STMIA R0,{R0-R15}
 ADR R8,MYHANDLERS
 BL SAVEHANDLERS
 ADR R8,HISHANDLERS
 BL GETHANDLERS
 SWI INTOFF
 MOV R0,#14
 MOV R1,#2
 SWI BYTE ;keyboard event: enable
 MOV R1,#4
 SWI BYTE ;VSYNC event: enable

 [ OSTYPE=1
 MOV R1, #1
 STRB R1, SWIGrabbing
 |
 ADR R1,SVCHN1
 BL SVCADR
 ]

; STR R2,OLDHAN
 ADR R0,TASKRD
 STR R0,MYREGS+15*4
nullcallback
 ADR R0,HISREGS
 LDMIA R0,{R0-R14}
 SWI ENTERSWI

 [ OSTYPE=1
 MOV R14,#1
 STRB R14,samsinterlock

 ADR R14,(HISREGS+15*4)
 LDMIA R14,{PC}^ ;run him

IFLAG * 1 :SHL: 27

 |

 ADR R14,(HISREGS+15*4)
 LDMIA R14,{PC}^ ;run him
;TASKSETENV MOV R4,#0
; MOV R5,#0
; MOV R6,#0
; MOV R7,#0
; B TASKDOSWI
SVCN15 MOV R3,#0 ;no change to event handler allowed!
SVCN16 B TASKDOSWI
SVCN02 LDR R2,HISREGS
SVCS2 LDRB R0,[R2],#1
 TEQ R0,#0
 BEQ SVCS2A
 CMP R0,#TERM :EOR: 7
 STRNEB R0,[R1],#1
 B SVCS2
SVCS2A STR R2,HISREGS
 LDR R2,TASKAP
 B SVCN0Y
SVCN03 LDR R2,TASKAP
 LDR R1,[R2,#END]
 MOV R0,#TERM
 B SVCN0X
IFLAG * &08000000
SVCN04
 LDR R1,BUFPTR
SVCN04A LDRB R0,[R1],#1
 CMP R0,#254
 BEQ SVCN04A
 BCS SVCN04NEW
 BIC R14,R14,#&30000000 ;clear V, C flags
 STR R14,HISREGS+14*4
 STR R0,HISREGS
 MOV R0,#254
 STRB R0,[R1,#-1]
 B SVCN1X
SVCN0 BEQ SVCN04
 CMP R2,#2
 LDR R2,TASKAP
 LDR R1,[R2,#END]
 BEQ SVCN02
 BCS SVCN03
SVCN01 LDR R2,HISREGS+14*4
 BIC R2,R2,#&FC000003
SVCS1 LDRB R0,[R2],#1
 TEQ R0,#0
 BEQ SVCS1A
 CMP R0,#TERM :EOR: 7
 STRNEB R0,[R1],#1
 B SVCS1
SVCS1A ADD R2,R2,#3
 BIC R2,R2,#3
 STR R2,HISREGS+14*4
 LDR R2,TASKAP
 B SVCN0Y
SVCN1 BEQ SVCN14 ;readline
 CMP R2,#16
 BCC SVCN15 ;control
 BEQ SVCN16 ;getenv
; CMP R2,#SETENV
; BEQ TASKSETENV
 CMP R2,#256
 BCC TASKDOSWI
 CMP R2,#512
 BCS TASKDOSWI
SVCNWI AND R0,R2,#255
SVCN00 LDR R2,TASKAP
 LDR R1,[R2,#END]
SVCN0X CMP R0,#&7F
 MOVEQ R0,#TERM
 STREQB R0,[R1,#-1]!
 BEQ SVCN0Y
 CMP R0,#TERM :EOR: 7
 STRNEB R0,[R1],#1
SVCN0Y STR R1,[R2,#END]
 MOV R14,#4
 STRB R14,TASKDIRTY
SVCN1X
 ADR R14,HISREGS
 LDMIA R14,{R0,R1,R2}
 LDR R14,HISREGS+14*4
 BICS PC,R14,#&10000000 ;clear V flag
SVCN04NEW
 ADR R0,HISREGS
 LDMIA R0,{R0,R1,R2}
 SUBS PC,R14,#4

RDLNREGS & 0
 & 0
 & 0
 & 0
SVCN14 BIC R14,R14,#&30000000 ;clear C, V flags
 STR R14,RDLNREGS+3*4
 STR R0,RDLNREGS ;gets smashed by ReadC
 LDR R2,HISREGS+4*2
 STR R4,RDLNREGS+4*1 ;work reg
 STR R5,RDLNREGS+4*2 ;work reg
 MOV R4,R0
 MOV R5,R0
 TEQP PC,#0
SRDLN1 SWI READC
 TEQ R0,#&7F
 TEQNE R0,#8
 BNE SRDLN2
 TEQ R4,R5
 SWINE WRITEI+127
 SUBNE R4,R4,#1
 B SRDLN1
SRDLN2 TEQ R0,#&15
 BNE SRDLN4
SRDLN3 TEQ R4,R5
 SWINE WRITEI+127
 SUBNE R4,R4,#1
 BNE SRDLN3
 B SRDLN1
SRDLN4 ; ADD SVCWK0,SVCWK0,R1
; CMP R4,SVCWK0
; SUB SVCWK0,SVCWK0,R1
; BCS SRDLN1 ;MAXIMUM LENGTH TEST
; SWI WRITEC
; BNE SRDLN1
 TEQ R0,#10
 MOVEQ R0,#13
 CMP R0,R2
 CMPCS R3,R0
 STRCSB R0,[R4],#1
 TEQ R0,#13
 SWINE WRITEC
 BNE SRDLN1
 SWI NEWLINE
 CMP R0,R2
 STRCCB R0,[R4],#1
 LDR R0,RDLNREGS
 SUB R1,R4,R0
 SUB R1,R1,#1
 ADR R4,RDLNREGS+4*1
 LDMIA R4,{R4,R5,PC}^
 ]

TASKBOT LDRB R0,[ARGP,#TASK]
 TEQ R0,#1
 BNE CUREDF
 LDR AP,TASKAP
 LDR R4,[AP,#END]
 BL GPFWD
 BL NORMAL
 STRB R6,[AP,#X]
 LDRB R0,[AP,#BSM]
 STRB R0,[AP,#Y]
 LDR AP,[ARGP,#USINGAP]
 MOV R0,#4
 STRB R0,TASKDIRTY
 B EDITOR

SAVEHANDLERS MOV R0,#0
 MOV R1,#0
 MOV R2,#0
 MOV R3,#2
 MOV R4,#0
 MOV R5,#0
 MOV R6,#0
 MOV R7,#0
 SWI SETENV
 STMIA R8!,{R0-R7}
 MOV R0,#0
 MOV R1,#0
 MOV R2,#0
 MOV R3,#0
 SWI CONTROL
 STMIA R8!,{R0-R3}
 MOV PC,R14

GETHANDLERS LDMIA R8!,{R0-R7}
 SWI SETENV
 LDMIA R8!,{R0-R3}
 MOV R3,#0
 SWI CONTROL
 MOV PC,R14

 [ OSTYPE<>1
SVCADR SUB R1,R1,#&10 ;plant new svc handler (addr in R1) return old (in R2)
 MOV R1,R1,LSR #2
 ORR R1,R1,#&EA000000
 MOV R0,#8 ;plant handler
 LDR R2,[R0]
 STR R1,[R0]
 BIC R2,R2,#&FF000000
 MOV R2,R2,LSL #2
 ADD R2,R2,#&10
 MOV PC,R14
 ]

TASKENTER BL TASKENTERSUB
 STRB R0,[R2,#-1]
 STRB R3,[R2]
 B EDITOR

TASKENTERSUB ADD R1,ARGP,#TASKBUF
 MOV R2,R1
 ADD R4,R1,#512
 SUB R4,R4,#1
TASKENTER1 LDRB R3,[R1],#1
 TEQ R3,#254
 STRNEB R3,[R2],#1
 TEQ R3,#255
 BNE TASKENTER1
 CMP R4,R2
 MOVCS PC,R14
 BL MSG
 = "Keyboard input buffer for task is full",0
 ALIGN
TASKR1 MOV R0,R1
 MOV PC,R14
TASKR2
 [ OSTYPE=1
 MOV R1,#50
 |
 MOV R1,#100
 ]
 MOV R2,#0
 STMFD SP!,{R14}
 BL AINKEY
 LDMFD SP!,{R14}
 BCC TASKR1
 TEQ R2,#&1B
 BEQ ESCAPE
 LDRB R0,[ARGP,#TUTMODE]
 CMP R0,#"D"
 CMPNE R0,#"T"
 BNE TASKR2
 STMFD SP!,{R14}
 SWI WRITES
 = 26,31,WIDTH-18,0
 TEQ R0,#"T"
 SWIEQ WRITEI+0
 SWINE WRITEI+15
 SUB R1,SP,#256
 [ OSTYPE=1
 MOV R0,#3
 STR R0,[R1]
 MOV R0,#14
 |
 MOV R0,#1
 ]
 SWI WORD
 LDR R8,[R1]
 LDRB R6,[R1,#4]
 BL PRINTTIME
 BL DECWIN
 BL CSRXY
 LDMFD SP!,{R14}
 B TASKR2

 LNK Paginate
