; Screen blanker support module

        GET     Hdr:ListOpts
        GET     Hdr:Macros
        GET     Hdr:System
        GET     Hdr:ModHand
        GET     Hdr:Proc
        GET     Hdr:Services

        ^       0, r12
Last_Activity # 4
Priv_Wkspce   # 4
ReEntrancy    # 4
Last_MousePos # 4
Wkspce_Size * :INDEX: {VAR}

Module_BaseAddr
        LEADR   Module_LoadAddr

 ASSERT (.=Module_BaseAddr)

        DCD     0       ; no run entry point
        DCD     Support_Init         -Module_BaseAddr
        DCD     Support_Die          -Module_BaseAddr
        DCD     Support_Service      -Module_BaseAddr
        DCD     Support_TitleString  -Module_BaseAddr
        DCD     Support_HelpString   -Module_BaseAddr
        DCD     0       ; no commands

Support_TitleString
        DCB     "ScrBlank_Support",0
Support_HelpString
        DCB     "ScrBlank_Support 0.00 (31 Mar 1991)",0

        ALIGN

Support_Init ENTRY
        MOV     r3, #Wkspce_Size
        MOV     r0, #ModHandReason_Claim
        SWI     XOS_Module
        EXIT    VS
        STR     r2, [r12]
        STR     r12, [r2, #:INDEX:Priv_Wkspce]
        MOV     r12, r2
        BL      Somethings_Happened
        BLVC    ReadUnbufferedMousePosition
        STRVC   r0, Last_MousePos

        ; Ticker settup
        MOVVC   r0, #0
        STRVC   r0, ReEntrancy
        MOVVC   r0, #TickerV
        ADRVC   r1, TickerChecker
        MOVVC   r2, r12
        SWIVC   XOS_AddToVector
        BVS     %FT90

        ; Event handler
        MOV     r0, #EventV
        ADR     r1, EventChecker
        MOV     r2, r12
        SWI     XOS_AddToVector
        BVS     %FT85

        ; Enable key down/up events
        MOV     r0, #14
        MOV     r1, #11
        SWI     XOS_Byte
        BVS     %FT80

        ; Enable mouse button events
        MOV     r0, #14
        MOV     r1, #10
        SWI     XOS_Byte
        BVS     %FT75

        EXIT

Support_Die ALTENTRY
        LDR     r12, [r12]

        ; Disable mouse button events
        MOV     r0, #13
        MOV     r1, #10
        SWI     XOS_Byte
        BVS     %FT80

75
        ; Disable key down/up events
        MOV     r0, #13
        MOV     r1, #11
        SWI     XOS_Byte
        BVS     %FT80
80
        ; remove event handler
        MOV     r0, #EventV
        ADR     r1, EventChecker
        MOV     r2, r12
        SWI     XOS_Release

85
        ; Remove ticker
        MOV     r0, #TickerV
        ADR     r1, TickerChecker
        MOV     r2, r12
        SWI     XOS_Release
        EXIT    VS
90
        MOV     r0, #ModHandReason_Free
        MOV     r2, r12
        SWI     XOS_Module
        MOVVC   r2, #0
        STRVC   r2, [r1]
        EXIT

TickerChecker ROUT
        Push    "lr"

        ; Avoid reentrancy
        LDR     lr, ReEntrancy
        TEQ     lr, #0
        Pull    "lr",NE,^
        MOV     lr, #1
        STR     lr, ReEntrancy

        ; Save old mode and switch to SVC mode, IRQs enabled
        MOV     r2, pc
        TEQP    pc, #SVC_mode
        NOP

        ; Now on SVC stack - save SVC r14
        Push    "lr"
        BL      ReadUnbufferedMousePosition
        LDR     r1, Last_MousePos
        STR     r0, Last_MousePos
        TEQ     r0, r1
        BLNE    Somethings_Happened
        Pull    "lr"

        ; return to original mode and IRQ disable and enable reentrancy
        TEQP    pc, r2
        ; NoNOP
        MOV     r2, #0
        STR     r2, ReEntrancy
        Pull    "pc",,^

EventChecker ROUT
        ; Rapid event rejection
        TEQ     r0, #10         ; Mouse
        TEQNE   r0, #11         ; Key up/down
        MOVNES  pc, lr

        Push    "r0,r2,lr"

        ; Save old mode and switch to SVC mode, IRQs enabled
        MOV     r2, pc
        TEQP    pc, #SVC_mode
        NOP

        ; Now on SVC stack - save SVC r14
        Push    "lr"
        BL      Somethings_Happened
        Pull    "lr"

        ; return to original mode and IRQ disable
        TEQP    pc, r2
        NOP

        Pull    "r0,r2,pc",,^

Support_Service
        TEQ     r1, #Service_Reset
        MOVNES  pc, lr

        TEQ     r1, #Service_Reset
        BEQ     DoService_Reset
        MOVS    pc, lr

; Service_Reset handling:
;
; We've been stripped from the vectors, so kill ourselves off.
; Construct kill-off code on stack to avoid tramplement after
; module's been killed, but before we've returned to the service
; handler.
DoService_Reset
        Push    "sp,lr"         ; Original sp as it's 1st in the list
        Push    "r0,r1"
        ADR     lr, KillMeOff
        LDMIA   lr, {r0,r1,lr}
        Push    "r0,r1,lr"
        MOV     r0, #ModHandReason_Delete
        ADR     r1, Support_TitleString
        MOV     pc, r13

KillMeOff
        SWI     XOS_Module
        ADD     r1, sp, #3*4
        LDMIA   r1, {r0,r1,sp,pc}^

Somethings_Happened ENTRY
        SWI     XOS_ReadMonotonicTime
        STRVC   r0, Last_Activity
        EXIT

ReadUnbufferedMousePosition ENTRY "r1",8
        MOV     r0, #4
        STRB    r0, [sp, #3]
        MOV     r0, #21
        ADD     r1, sp, #3
        SWI     XOS_Word
        LDRVC   r0, [sp, #4]
        EXIT

        END
