; Keystroke Module

; v1.06 17 Jan 1996
; v1.07 09 Dec 2002 Changed by ?
;       Just module version/date string changed
; v1.08 25 Sep 2013 Changes by Martin Avison...
;       Corrected blank task name (reported by Jim Nagle)
;       Corrected rubbish task name for *Desktop_KeystrokeMod
;	Added error number to *Desktop_KeystrokeMod error
;       Added Poll mask for all unused reason codes
;       Changed Wimp Poll to PollIdle with 10cs delay to reduce CPU load

R1  RN 1
R2  RN 2
R3  RN 3
R4  RN 4
R5  RN 5
R6  RN 6
R7  RN 7
R8  RN 8
R9  RN 9
R10 RN 10
R11 RN 11
R12 RN 12
R13 RN 13
R14 RN 14
PC  RN 15

XWimp_SendMessage   * &600E7
XOS_Module          * &2001E
XOS_ReadMonotonicTime * &20042		; +v1.08
XWimp_ReadSysInfo   * &600F2
XWimp_Initialise    * &600C0
XWimp_CloseDown     * &600DD
;XWimp_Poll          * &600C7            ; -v1.08
XWimp_PollIdle      * &600E1		; +v1.08
XOS_CLI             * &20005
XOS_Exit            * &20011
XOS_SetVarVal       * &20024

Report_Regs * &54C82
overflow    * &10000000


;workspace offsets


 AREA code,CODE

 ENTRY

offwego     * startup-start
title       * titlestr-start
help        * helpstr-start
init        * initial-start
fin         * final-start
comms       * commtable-start
flag32      * flagword-start

start
 DCD offwego,init,fin,0
 DCD title,help,comms,0
 DCD 0,0,0,0
 DCD flag32

titlestr
 = "KeystrokeMod",0
 ALIGN

helpstr
 = "KeystrokeMod",9,"1.08 (25 Sep 2013)",0
 ALIGN

flagword
 DCD 1

commtable
 = "Desktop_KeystrokeMod",0
 ALIGN
 DCD keymod-start,0,kmodinvalid-start,kmodhelp-start
 = "KeySet",0
 ALIGN
 DCD keyset-start,&FF0002,ksetinvalid-start,ksethelp-start
 = "Keystroke",0
 ALIGN
 DCD keystroke-start,&FF0001,0,0
 = "KeystrokeIcon",0
 ALIGN
 DCD keyicon-start,&FF0001,0,0
 = "KeystrokeLoad",0
 ALIGN
 DCD keyload-start,&FF0001,0,0
 = "KeystrokeAuto",0
 ALIGN
 DCD keyauto-start,&FF0001,0,0
 = "KeystrokeDemo",0
 ALIGN
 DCD keydemo-start,&FF0001,0,0
 DCD 0

kmodinvalid
 = "Syntax: *Desktop_KeystrokeMod",0

kmodhelp
 = "The Keystroke module is for use by the Keystroke application.",0

ksetinvalid
 = "Syntax: *KeySet <varname> <value>",0

ksethelp
 = "*KeySet checks for any Keystroke variables, and notifies the Keystroke main task.",0

 ALIGN

service
 STMDB   R13!,{R14}
 TEQ     R1,#&49       ;StartWimp
 BEQ     wimpstart
 TEQ     R1,#&4A       ;StartedWimp
 BEQ     wimpstarted
 TEQ     R1,#&27       ;Reset
 MOVEQ   R14,#0
 STREQ   R14,wimpver
 LDMIA   R13!,{PC}

wimpstart
 LDR     R14,wimpver
 TEQ     R14,#0
 MVNEQ   R14,#0
 STREQ   R14,wimpver
 ADR     R0,commtable
 MOVEQ   R1,#0
 LDMIA   R13!,{PC}

wimpstarted
 LDR     R14,wimpver
 CMP     R14,#1
 MOVEQ   R14,#0
 STREQ   R14,wimpver
 LDMIA   R13!,{PC}

keymod				; Desktop_KeystrokeMod
 STMDB   R13!,{R14}
 MOV     R2,R0
 MOV     R0,#0			; read active tasks
 SWI     XWimp_ReadSysInfo
 CMP     R0,#0			; outside desktop?
 BEQ     notask                 ; yes
;ADR     R1,title               ; does not give => titlestr!      -v1.08
 ADR     R1,titlestr		; r1 => titlestr                  ~v1.08
 MOV     R0,#2			; Enter to start as task
 SWI Report_Regs
 SWI     XOS_Module             ; should not return!
 LDMIA   R13!,{PC}

notask
 ADR     R0,usedesk
 LDMIA   R13!,{R14}
 TEQ     PC,PC
 ORRNES  PC,R14,#overflow       ;26-bit
 MSR     CPSR_f,#overflow       ;32-bit
 MOV     PC,R14

usedesk
 DCD	 0			; needs error number! 		+v1.08
 = "Use *Desktop to start KeystrokeMod",0
 ALIGN

wimpver
 DCD 0

task
 DCD &4B534154

setalias
 = "%Set Alias$Set Keyset %*0",0
 ALIGN

memsize
 DCD &17A0

startup
 LDR     R0,wimpver
 TEQ     R0,#0
 BLE     wimpinit
 LDR     R1,task
 SWI     XWimp_CloseDown
 MOV     R0,#0
 STR     R0,wimpver

wimpinit
 MOV     R0,#&C8		; 200
 LDR     R1,task
;ADR     R2,title               ; does not give => titlestr!      -v1.08
 ADR     R2,titlestr		; r1 => titlestr                  ~v1.08
 SWI     XWimp_Initialise
 STR     R1,wimpver
 ADR     R0,setalias
 SWI     XOS_CLI

pollloop
 SWI     XOS_ReadMonotonicTime	; 			+v1.08
 ADD	 r2,r0, #10		; add cs delay          +v1.08
;MOV     R0,#0			; should be mask        -v1.08
 LDR	 r0,pollmask		;                       +v1.08
 ADR     R1,block
;SWI     XWimp_Poll		; should be PollIdle    -v1.08
 SWI     XWimp_PollIdle		;                       +v1.08
 CMP     R0,#0
 BEQ     nullevent
 CMP     R0,#&11
 CMPNE   R0,#&12
 BEQ     message
 B       pollloop

unknown
 DCD &FFFF0
pollmask			;			+v1.08
 DCD &083972			; mask all unused codes +v1.08

block % 256

message
 LDR     R0,[R1,#16]
 CMP     R0,#0
 BNE     pollloop
 LDR     R0,wimpver
 LDR     R1,task
 SWI     XWimp_CloseDown
 MOV     R0,#0
 STR     R0,wimpver
 SWI     XOS_Exit

initial
 STMDB   R13!,{R14}
 MOV     R0,#6
 LDR     R3,memsize
 SWI     XOS_Module
 BVS     nomem
 STR     R2,[R12,#0]
 LDMIA   R13!,{PC}

nomem
 LDMIA   R13!,{R14}
 ADR     R0,memerror
 MOV     PC,R14

memerror
 = "Not enough room in RMA for KeystrokeMod to initialise",0
 ALIGN

final
 STMDB   R13!,{R14}
 MOV     R0,#7
 LDR     R2,[R12,#0]
 SWI     XOS_Module
 LDR     R0,wimpver
 TEQ     R0,#0
 LDRGT   R1,task
 SWIGT   XWimp_CloseDown
 MOV     R1,#0
;STR     R0,wimpver			; r0 is corrupt!      -v1.08
 STR     R1,wimpver                     ; zeroise task handle ~v1.08
 ADR     R0,unsetalias
 SWI     XOS_CLI
 LDMIA   R13!,{PC}

unsetalias
 = "%Unset Alias$Set",0
 ALIGN

keyset
 STMDB   R13!,{R14}
 MOV     R4,#0
 ADR     R3,keysetblock
 MOV     R1,R0

setloop1
 LDRB    R2,[R1],#1
 STRB    R2,[R3],#1
 CMP     R2,#&20
 BNE     setloop1

setloop2
 LDRB    R2,[R1],#1
 CMP     R2,#&20
 BEQ     setloop2
 SUB     R1,R1,#1
 MOV     R2,#1
 MOV     R3,#0
 SWI     XOS_SetVarVal
 MOV     R0,#0
 ADR     R1,keysetblock

setloop3
 LDRB    R2,[R1,R0]
 CMP     R2,#&61
 BLT     keyset1
 CMPGE   R2,#&7A
 SUBLE   R2,R2,#&20
 STRLEB  R2,[R1,R0]

keyset1
 ADD     R0,R0,#1
 CMP     R2,#&20
 BGE     setloop3
 ADR     R3,keysetblock
 MOV     R1,R3
 ADR     R2,demovar
 BL      findvar
 CMP     R0,#0
 MOVNE   R0,#1
 BNE     keyset2
 MOV     R1,R3
 ADR     R2,loadvar
 BL      findvar
 CMP     R0,#0
 MOVNE   R0,#2
 BNE     keyset2
 MOV     R1,R3
 ADR     R2,dovar
 BL      findvar
 CMP     R0,#0
 MOVNE   R0,#3
 BNE     keyset2
 MOV     R1,R3
 ADR     R2,autovar
 BL      findvar
 CMP     R0,#0
 MOVNE   R0,#4
 BNE     keyset2
 MOV     R1,R3
 ADR     R2,iconvar
 BL      findvar
 CMP     R0,#0
 MOVNE   R0,#5
 BNE     keyset2

return
 LDMIA   R13!,{PC}

demovar
 = "KEYSTROKE$DEMO",0

loadvar
 = "KEYSTROKE$LOAD",0

dovar
 = "KEYSTROKE$DO",0

autovar
 = "KEYSTROKE$AUTO",0

iconvar
 = "KEYSTROKE$ICON",0
 ALIGN

keysetblock % 260

keyset2
 STMDB   R13!,{R0-R2}
 STR     R0,smblock
 MOV     R1,#&FF
 ADR     R2,smblock
 STR     R1,[R2,R0,LSL #2]
 LDMIA   R13!,{R0-R2}
 B       return

smblock % 24

pword
 DCD 0

nullevent
 LDR     R12,pword
 ADR     R9,store
 LDR     R8,[R9,#0]
 MOV     R7,#0

nullloop1
 CMP     R7,R8
 BEQ     null1
 MOV     R0,#&11
 MOV     R1,R7,LSL #8
 ADD     R1,R1,R7,LSL #5
 ADD     R1,R1,R12
 MOV     R2,#0
 SWI     XWimp_SendMessage
 ADD     R7,R7,#1
 B       nullloop1

null1
 MOV     R0,#0
 STR     R0,[R9,#0]
 ADR     R0,smblock
 LDR     R1,[R0,#0]
 CMP     R1,#0
 BEQ     pollloop
 STR     R1,[R0,#0]
 MOV     R7,#0

nullloop2
 CMP     R7,#5
 BEQ     pollloop
 ADD     R7,R7,#1
 ADR     R6,smblock
 LDR     R5,[R6,R7,LSL #2]
 CMP     R5,#0
 BEQ     nullloop2
 MOV     R5,#0
 STR     R5,[R6,R7,LSL #2]
 ADR     R1,msgblock
 MOV     R2,#&18
 STR     R2,[R1,#0]
 MOV     R2,#0
 STR     R2,[R1,#4]
 STR     R2,[R1,#8]
 STR     R2,[R1,#12]
 LDR     R2,msg8317f
 STR     R2,[R1,#16]
 MOV     R2,R7
 STR     R2,[R1,#20]
 MOV     R2,#0
 MOV     R0,#&11
 SWI     XWimp_SendMessage
 B       nullloop2

msg8317f
 DCD &8317F

msgblock ;834
 ANDEQ   R0,R0,R0
 ANDEQ   R0,R0,R0
 ANDEQ   R0,R0,R0
 ANDEQ   R0,R0,R0
 ANDEQ   R0,R0,R0
 ANDEQ   R0,R0,R0
 ANDEQ   R0,R0,R0

msgvarexec
 DCD &8317E

store
 DCD 0

keystroke
 STMDB   R13!,{R0-R9,R14}
 MOV     R7,#1
 B       process

keyicon
 STMDB   R13!,{R0-R9,R14}
 MOV     R7,#2
 B       process

keyload
 STMDB   R13!,{R0-R9,R14}
 MOV     R7,#3
 B       process

keyauto
 STMDB   R13!,{R0-R9,R14}
 MOV     R7,#4
 B       process

keydemo
 STMDB   R13!,{R0-R9,R14}
 MOV     R7,#5
 B       process

process
 LDR     R12,[R12,#0]
 STR     R12,pword
 LDR     R6,store
 CMP     R6,#&14
 LDMGEIA R13!,{R0-R9,PC}
 MOV     R5,R6,LSL #8
 ADD     R5,R5,R6,LSL #5
 ADD     R6,R6,#1
 STR     R6,store
 ADD     R8,R12,R5
 ADD     R8,R8,#&18
 MVN     R3,#0

procloop
 ADD     R3,R3,#1
 CMP     R3,#&D2
 BGE     process1
 LDRB    R2,[R0,R3]
 CMP     R2,#&20
 BLT     process1
 STRB    R2,[R8,R3]
 B       procloop

process1
 MOV     R2,#0
 STRB    R2,[R8,R3]
 AND     R4,R3,#3
 RSB     R2,R4,#4
 ADD     R3,R3,R2
 ADD     R3,R3,#&18
 SUB     R8,R8,#&18
 STR     R3,[R8,#0]
 MOV     R4,#0
 STR     R4,[R8,#4]
 STR     R4,[R8,#8]
 STR     R4,[R8,#12]
 LDR     R4,msgvarexec
 STR     R4,[R8,#16]
 STR     R7,[R8,#20]
 LDMIA   R13!,{R0-R9,PC}

findvar
 STMDB   R13!,{R1-R7,R14}
 MOV     R3,#0
 MOV     R0,R3
 ADD     R1,R1,R3

findloop1
 MOV     R4,R1
 MOV     R5,R2
 ADD     R0,R0,#1

findloop2
 LDRB    R6,[R4],#1
 LDRB    R7,[R5],#1
 CMP     R7,#&20
 BLT     endfind
 CMP     R6,R7
 BEQ     findloop2
 LDRB    R6,[R1],#1
 CMP     R6,#&20
 BGE     findloop1
 MOV     R0,#0

endfind
 LDMIA   R13!,{R1-R7,PC}

 END
