;> TaskMan

; APT changes :

; 1) TEQP PC,#IFLAG in CALLROUT

; 2) samsinterlock added to prevent reentrant CallBack occuring (I suspect
;      this occasionally happens with normal twin and Brazil : AB as a task
;      with FX12,1 set, and RETURN held down, seemed able to hang Twin
;      occasionally on my 2nd processor.)

; 3) Minor change to ReadC interception : can retry SWICS ReadC successfully

FixSWICS_ReadC * 1 ; 0 for old code.

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
 SWI READC
 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
GETTASKGAP 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 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
 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
 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
 [ ARTHUR=1
 MOV R0,#1
 STR R0,samsinterlock
 ADR R0,HISREGS
 ADR R1,CALLROUT
 SWI CALLBACK
 ]
 ADR R1,SVCHN1
 STR R1,EVTLOC
 BL SVCADR
 STR R2,OLDHAN
 ADD R7,ARGP,#STRACC
RUNONE MOV R0,R7
 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
 STRB R0,[ARGP,#TASK]
 STRB R0,[AP,#TASKQ]
 STRB R0,TASKDIRTY
 STRB R0,TASKDIRTY+1
 B REENTER
EVTHAM1
 [ ARTHUR=1
 LDR 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
 STR R11,samsinterlock

;MOV R12,#1
 MOV PC,R14
CALLROUT

 TEQP PC,#IFLAG          ; APT modification
 B SVCH2X
samsinterlock & 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

;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
 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
 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
TASKPAINT1A 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}
TASKRD1 MOV R0,#&81
 MOV R1,#0
 MOV R2,#0
 SWI BYTE
 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
 ADR R1,SVCHN1
 BL SVCADR
; STR R2,OLDHAN
 ADR R0,TASKRD
 STR R0,MYREGS+15*4
 ADR R0,HISREGS
 LDMIA R0,{R0-R14}
 SWI ENTERSWI

 [ ARTHUR = 1
  MOV R14,#1
  STR R14,samsinterlock
 ]

 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

 [ FixSWICS_ReadC = 0
 BIC R14,R14,#&30000000 ;clear V, C flags
 STR R14,HISREGS+14*4
 ]

 LDR R1,BUFPTR
SVCN04A LDRB R0,[R1],#1
 CMP R0,#254
 BEQ SVCN04A
 BCS SVCN04NEW

 [ FixSWICS_ReadC = 1
 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

 [ FixSWICS_ReadC = 1
 ADR R0,HISREGS
 LDMIA R0,{R0,R1,R2}
 SUBS PC,R14,#4
 |
 SUB R14,R14,#4
 STR R14,HISREGS+14*4
 B SVCN1X
 ]

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
 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

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
TASKENTER1 LDRB R3,[R1],#1
 TEQ R3,#254
 STRNEB R3,[R2],#1
 TEQ R3,#255
 BNE TASKENTER1
 CMP R4,R2
 BCS TASKENTER2
 BL MSG
 = "Keyboard input buffer for task is full",0
 ALIGN
TASKENTER2 MOV PC,R14
TASKR1 MOV R0,R1
 MOV PC,R14
TASKR2 MOV R0,#&81
 MOV R1,#100
 MOV R2,#0
 SWI BYTE
 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
 MOV R0,#1
 SUB R1,SP,#256
 SWI WORD
 LDR R8,[R1]
 LDRB R6,[R1,#4]
 BL PRINTTIME
 BL DECWIN
 BL CSRXY
 LDMFD SP!,{R14}
 B TASKR2
 LNK Paginate
