;Entry_JoystickKeys
;------------------
;Translates Joystick movement into key presses

STRUCT Joystick_Keys
{
  .right	DCB 0
  .left		DCB 0
  .down		DCB 0
  .up		DCB 0
  .down_right	DCB 0
  .down_left	DCB 0
  .up_right	DCB 0
  .up_left	DCB 0
  .buttons	DCD 0
		DCD 0
		DCD 0
		DCD 0
  .size			; size must be word aligned
}

;Entry:
; R0 - Command tail
; R1 = no. of parameters
; R12 - pointer to module private word

;Exit:
; R0 - corrupt

.Entry_ADFJoystickKeys
 STMFD   R13!, {R1-R4, R7, R12, R14}
 LDR     R12, [R12, #0]

 ADD     R7, R12, #Joystick_Keymapping - VARS	;R7=joystick table
 MOV     R4, R7				;R4=pointer to Joystick 1
 
 TEQ     R1, #0				;are we shutting down?
 BEQ     _exit_cancel			;YES

 MOV     R1, R0				;R1=command tail
 MOV     R0, #1 << 29			;restrict OS_ReadUnsigned to value in R2
 ._L1
   LDRB    R2, [R1], #1
   TEQ     R2, #ASC(" ")
   BEQ     _L1				;ignore SPACE

   BIC     R2, R2, #32			;force to uppercase
   TEQ     R2, #ASC("J")
   BEQ     _joystick			;its a Joystick

   TEQ     R2, #ASC("R")
   MOVEQ   R3, #Joystick_Keys.right
   BEQ     _read_key

   TEQ     R2, #ASC("L")
   MOVEQ   R3, #Joystick_Keys.left
   BEQ     _read_key

   TEQ     R2, #ASC("D")
   MOVEQ   R3, #Joystick_Keys.down
   BEQ     _read_key_diagonal

   TEQ     R2, #ASC("U")
   MOVEQ   R3, #Joystick_Keys.up
   BEQ     _read_key_diagonal

   TEQ     R2, #ASC("B")
   BEQ     _read_button

   TEQ     R2, #0
 BNE     _L1

 LDR     R0, [R7, #-4]
 TEQ     R0, #0				;is handler already running?
 BNE     _exit				;YES

 MOV     R0, #1				;50/sec
 ADR     R1, Joystick_handler
 MOV     R2, R12
 SWI     XOS_CallEvery
 STRVC   R1, [R7, #-4]

 ._exit
LDMFD   R13!, {R1-R4, R7, R12, PC}

._exit_cancel
 LDR     R0, [R7, #-4]
 TEQ     R0, #0				;is handler running?
 LDMEQFD R13!, {R1-R4, R7, R12, PC}	;NO, exit

 MVN     R3, #0				;clear mapping table
 MOV     R2, #Joystick_Keys.size*Max_Joysticks
 ._L8
   SUBS    R2, R2, #4
   STR     R3, [R7, R2]
 BNE     _L8

 MOV     R1, R12			;YES
 SWI     XOS_RemoveTickerEvent
 MOVVC   R2, #0
 STRVC   R2, [R7, #-4]
LDMFD   R13!, {R1-R4, R7, R12, PC}


._joystick
 MOV     R2, #Max_Joysticks		;R2=max value
 SWI     XOS_ReadUnsigned		;read the value PRM1-460
 BVS     _exit				;exit on error
 SUB     R2, R2, #1			;reduce value

 MOV     R4, #Joystick_Keys.size
 MLA     R4, R2, R4, R7			;R4=pointer to Joystick_Keymapping

 MVN     R3, #0				;clear mapping table
 MOV     R2, #Joystick_Keys.size
 ._L3
   SUBS    R2, R2, #4
   STR     R3, [R4, R2]
 BNE     _L3
B        _L1

 ;Entry
 ; R4 - pointer to Joystick_Keymapping

._read_button
  MOV     R2, #32			;R2=max value (32 buttons)
  SWI     XOS_ReadUnsigned		;read the value PRM1-460
  BVS     _exit				;exit on error

  ADD     R3, R2, #Joystick_Keys.buttons-1	;R3=button offset
._read_key
   LDRB    R2, [R1], #1			;find the value
   ._L2
   TEQ     R2, #0
   BEQ     _exit
   TEQ     R2, #ASC("=")
 BNE     _read_key

 MOV     R2, #254			;R2=max value
 SWI     XOS_ReadUnsigned		;read the value PRM1-460
 BVS     _exit				;exit on error
 STRB    R2, [R4, R3]
B       _L1

 ;Entry R3: 2 Down  3 Up
 ;Exit  R3: 4 DR 5 DL 6 UR 7 UL
._read_key_diagonal
  LDRB    R2, [R1], #1			;read next char
  BIC     R14, R2, #32			;force to uppercase
  TEQ     R14, #ASC("L")
  TEQNE   R14, #ASC("R")
  BNE     _L2

  MOV     R3, R3, LSL #1		;R3=4 Down  R3=6 Up
  TEQ     R14, #ASC("L")
  ADDEQ   R3, R3, #1			;+1 if Left
B     _read_key




;Entry:
; R12 - pointer to VARS

.Joystick_handler
 STMFD   R13!, {R0-R10, R14}

 ADD     R4, R12, #Joystick_Keymapping - VARS
 ADD     R6, R4, #Joystick_Buttons - Joystick_Keymapping
 ADD     R8, R4, #Joystick_DeadZones - Joystick_Keymapping
 MOV     R9, #Vector_KeyV

 MOV     R7, #0				;R7=Joystick being checked
 ._L7
   LDR     R5, [R8, R7, LSL #2]		;R5=Jn 16-bit deadzone
   MOV     R3, #0			;R3=RTFM Joystick state
   MOV     R10, #0			;R10=32 buttons
   ORR     R0, R7, #1 << 8		;read 16bit Joystick interface
   SWI     XJoystick_Read
   BVS     _no_Joystick16		;16bit not supported
   MOVS    R10, R1			;Fire (check all buttons)
   ORRNE   R3, R3, #1 << 4
   BIC     R1, R0, #&FFFF << 16
   MOV     R0, R0, LSR #16
   SUB     R1, R1, #1 << 15		;R1= - down / + up
   SUB     R0, R0, #1 << 15		;R0= - left / + right

   CMN     R1, R5			;check Up/Down
   ORRLT   R3, R3, #1 << 2		;Down
   CMP     R1, R5
   ORRGT   R3, R3, #1 << 3		;Up
   CMN     R0, R5			;check Left/Right
   ORRLT   R3, R3, #1 << 1		;Left
   CMP     R0, R5
   ORRGT   R3, R3, #1			;Right

   ._no_Joystick16
   MOV     R0, R7
   SWI     XJoystick_Read		;add support for RTFM interface
   MVNVS   R0, #0			;-1 = unsupported
   BVS     _no_Joystick			;no Joystick interface
   MOV     R1, R0, LSL #24		;check Up/Down
   CMN     R1, R5, LSL #16
   ORRLT   R3, R3, #1 << 2		;Down
   CMP     R1, R5, LSL #16
   ORRGT   R3, R3, #1 << 3		;Up
   MOV     R1, R0, LSL #16		;check Left/Right
   CMN     R1, R5, LSL #16
   ORRLT   R3, R3, #1 << 1		;Left
   CMP     R1, R5, LSL #16
   ORRGT   R3, R3, #1			;Right
   MOVS    R0, R0, LSR #16		;Fire (check all buttons)
   ORRNE   R3, R3, #1 << 4
   TEQ     R10, #0			;any 16bit buttons?
   MOVNE   R10, R0			;NO, use 8bit instead

   LDR     R1, [R12, #Joystick_Keymapping-4 - VARS]
   LDRB    R2, [R6, #Econet_Registers+4 - Joystick_Buttons]	;current Econet state
   TEQ     R7,#1			;Joystick 1?
   ANDEQ   R5, R2, #%10000		;YES, Econet order is %UDLFR000
   BICEQ   R2, R2, #%10000		;%0UDL0R000
   ORREQ   R2, R2, R5, LSL #4		;%FUDL0R000
   ANDEQ   R5, R2, #%1000
   ORREQ   R2, R2, R5, LSL #1		;%FUDLRR000
   MOVEQ   R2, R2, LSR #4		;%FUDLR
   TEQ     R1, #0			;are keys mapped?
   BLNE    _key_translate		;YES
   TEQ     R7,#1			;Joystick 2?
   ANDEQ   R5, R3, #%1			;YES, change from %FUDLR to %UDLFR000
   BICEQ   R3, R3, #%1			;%FUDL0
   ORREQ   R3, R3, R3, LSR #4		;%FUDLF
   ORREQ   R3, R5, R3, LSL #1		;%FUDLFR
   MOVEQ   R3, R3, LSL #3		;%FUDLFR000
   STRB    R3, [R6, #Econet_Registers+4 - Joystick_Buttons]	;update Econet register
   ._no_Joystick
   STR     R10, [R6], #4		;store Button state

   ADD     R7, R7, #1
   ADD     R4, R4, #Joystick_Keys.size	;next Joystick keymapping
   CMP     R7, #Max_Joysticks
 BNE       _L7
LDMFD   R13!, {R0-R10, PC}


 ;Entry:
 ; R2 - previous RTFM Joystick state
 ; R3 - current RTFM Joystick state
 ; R4 - pointer to Joystick_Keymapping
 ; R6 - pointer to Joystick_Buttons
 ; R9 - Vector_KeyV (19)
 ; R10 - Current button state

 ;Exit:
 ; R1, R5 - corrupt

 ._key_translate
 EOR     R2, R2, R3			;bit set if changed
 STMFD   R13!, {R2-R4, R14}
 MOV     R5, #4
 ._L5
   LDRB    R1, [R4], #1			;R1=key to press/release
   MOVS    R2, R2, LSR #1		;C set if changed
   ANDCS   R0, R3, #1
   ADDCS   R0, R0, #1			;R0 1=released or 2=pressed
   MOV     R3, R3, LSR #1
   BCC     _P5				;skip if state hasn't changed
   TEQ     R1, #&FF			;is there a mapping?
   SWINE   XOS_CallAVector		;YES, PRM1-70

   ._P5
   SUBS    R5, R5, #1
 BNE     _L5
					;check diagonals
 LDMIB   R13, {R2-R3}			;get R2, R3 from stack
 MOV     R5, #%0101			;Down Right
 ._L6
   LDRB    R1, [R4], #1			;R1=key to press/release
   TEQ     R1, #&FF			;is there a key mapping?
   ANDNES  R0, R2, R5			;YES, has the Joystick changed?
   BEQ     _P6				;NO
   AND     R0, R3, R5
   TEQ     R0, R5
   MOVEQ   R0, #2			;pressed
   MOVNE   R0, #1
   SWI     XOS_CallAVector		;PRM1-70

   ._P6
   ADD     R5, R5, #1
   TEQ     R5, #%0111			;FUDLR
   MOVEQ   R5, #%1001			;Up Right
   TEQ     R5, #%1011
 BNE     _L6

 LDR     R2, [R6, #0]			;previous button state
 MOV     R3, R10			;current button state
 MOV     R5, #31			;32 Joystick buttons
 ._L4
   LDRB    R1, [R4], #1			;R1=key to press/release
   MOVS    R2, R2, LSR #1		;C set if changed
   ANDCS   R0, R3, #1
   ADDCS   R0, R0, #1			;R0 1=released or 2=pressed
   MOV     R3, R3, LSR #1
   BCC     _P4
   TEQ     R1, #&FF			;is there a mapping?
   SWINE   XOS_CallAVector		;YES, PRM1-70

   ._P4
   SUBS    R5, R5, #1
 BNE     _L4
LDMFD   R13!, {R2-R4, PC}
