; ; event.s ; ; Event handling routines (TMA) ; ; © 1994-1998 Straylight ; ;----- Licensing note ------------------------------------------------------- ; ; This file is part of Straylight's Sapphire library. ; ; Sapphire is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 2, or (at your option) ; any later version. ; ; Sapphire is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with Sapphire. If not, write to the Free Software Foundation, ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;----- Standard header ------------------------------------------------------ GET libs:header GET libs:swis ;----- External dependencies ------------------------------------------------ GET sapphire:sapphire GET sapphire:suballoc GET sapphire:hour ;----- Macros --------------------------------------------------------------- MACRO BUFCOPY LCLA counter counter SETA 0 STMFD R13!,{R0-R6} WHILE counter<8 LDMIA R9!,{R0-R6,R14} STMIA R8!,{R0-R6,R14} counter SETA counter+1 WEND LDMFD R13!,{R0-R6} MEND ;----- Main code ------------------------------------------------------------ AREA |Sapphire$$Code|,CODE,READONLY ; --- event__addToList --- ; ; On entry: R0 == pointer to routine to call ; R1 == R12 value to call routine ; R2 == pointer to list head to use ; ; On exit: R0-R1 preserved, unless V set (when R0 points to error) ; ; Use: Adds a rountine to the given list. Later added ; routines are called first event__addToList ROUT STMFD R13!,{R0-R1,R14} ;Stack some registers ; --- Allocate a block --- MOV R0,#list__size ;Size to allocate BL sub_alloc ;Allocate the block BVS %01 ;Branch ahead if error ; --- Fill the block in --- LDR R1,[R2] ;Get the list head STR R1,[R0,#list__next] ;Store in next field STR R0,[R2] ;Store new block at head LDMFD R13,{R1,R2} ;Get parameters STMIB R0,{R1,R2} ;Store them in the block ; --- And return to user --- LDMFD R13!,{R0-R1,R14} ;Load back link BICS PC,R14,#V_flag ;Return without error ; --- Barf if an error occured --- 01 ADD R13,R13,#4 ;Skip over R0 LDMFD R13!,{R1,R14} ;Branch if error ORRS PC,R14,#V_flag ;Return with error LTORG ; --- event_preFilter --- ; ; On entry: R0 == pointer to routine to call ; R1 == R12 value to call routine ; ; On exit: May return an error ; ; Use: Adds a routine to the pre-filter list. Later added ; routines are called first. EXPORT event_preFilter event_preFilter ROUT STMFD R13!,{R2,R10,R14} ;Save some registers ; --- Be careful not to alter flags --- WSPACE event__wSpace,R10 ;Get my workspace pointer ADR R2,event__preList ;Get the pre-list pointer BL event__addToList ;Add the routine to the list LDMFD R13!,{R2,R10,PC} ;Return cunningly LTORG ; --- event_fakeHandler --- ; ; On entry: R0 == pointer to routine to call ; R1 == R12 value to call routine ; ; On exit: May return an error ; ; Use: Adds a routine to the fake handler list. Later added ; routines are called first. EXPORT event_fakeHandler event_fakeHandler ROUT STMFD R13!,{R2,R10,R14} ;Save some registers ; --- Be careful not to alter flags --- WSPACE event__wSpace,R10 ;Get my workspace pointer ADR R2,event__fakeList ;Get the fake-list pointer BL event__addToList ;Add the routine to the list LDMFD R13!,{R2,R10,PC} ;Return cunningly LTORG ; --- event_postFilter --- ; ; On entry: R0 == pointer to routine to call ; R1 == R12 value to call routine ; ; On exit: May return an error ; ; Use: Adds a routine to the post-poll list. Later added ; routines are called first. EXPORT event_postFilter event_postFilter ROUT STMFD R13!,{R2,R10,R14} ;Save some registers ; --- Be careful not to alter flags --- WSPACE event__wSpace,R10 ;Get my workspace pointer ADR R2,event__postList ;Get the post-list pointer BL event__addToList ;Add the routine to the list LDMFD R13!,{R2,R10,PC} ;Return cunningly LTORG ; --- event_poll --- ; ; On entry: R0 == event mask and flags ; R1 == pointer to block to use ; R2 == earliest time to return with NULL event ; R3 == optional pointer to poll word ; ; On exit: R0 == reason code ; CS if the event was claimed, CC otherwise ; ; Use: This call perform a Wimp_Poll, and dispatches events to ; interested parties. EXPORT event_poll event_poll ROUT STMFD R13!,{R8-R10,R12,R14} WSPACE event__wSpace,R10 ;Find my workspace ; --- Run through the pre poll list here --- ADDS R0,R0,#0 ;Clear the carry flag LDR R8,event__preList ;Get pre-list pointer 00event_poll TEQ R8,#0 ;Are we at the end BEQ %05event_poll ;Yes -- branch ahead LDMIA R8,{R8,R9,R12} ;Get list fields MOV R14,PC ;Set up return address MOV PC,R9 ;Branch to client routine BCC %00event_poll ;Keep going through list ; -- If carry is set, jump the Wimp_Poll & fake list --- BCS %19event_poll ;Jump ahead ; --- If we are faking, do fake like things --- 05event_poll LDR R8,event__fakePos ;Get the current fake pos CMP R8,#-1 ;Are there any waiting? BEQ %10event_poll ;No -- do the Wimp_Poll MOV R8,R1 ;Point to users buffer ADR R9,event__buffer ;Point to my buffer BUFCOPY ;Copy the event LDR R0,event__prevR0 ;Get the event type B %11event_poll ;Continue with fakes ; --- Do the Wimp_Poll --- ; ; Make sure the hourglass goes off during the poll, though 10event_poll SUB R13,R13,#8 ;Make space for hourglass blk STMFD R13!,{R0} ;Save the event mask ADD R0,R13,#4 ;Point to the block BL hour_suspend ;Turn the hourglass off a bit LDR R0,[R13,#0] ;Load the event mask again CMP R2,#0 ;Are we getting NULLs ASAP SWIEQ Wimp_Poll ;Yes -- Normal Poll SWINE Wimp_PollIdle ;No -- PollIdle STR R0,[R13,#0] ;Save the Wimp_Poll reason ADD R0,R13,#4 ;Point to the block BL hour_resume ;Restore the hourglass state LDMFD R13!,{R0} ;Restore the reason code ADD R13,R13,#8 ;And reclaim the stack space ; --- Copy over the event --- ADR R8,event__buffer ;Point to my buffer MOV R9,R1 ;Point to users buffer BUFCOPY ;Copy the event STR R0,event__prevR0 ;Remember event type ; --- Deal with fake events --- 11event_poll LDR R8,event__fakePos ;Get the fake list CMP R8,#-1 ;Is there one? LDREQ R8,event__fakeList ;Get fake list if !resuming ADDS R0,R0,#0 ;Clear the carry flag 12event_poll TEQ R8,#0 ;Is there a fake handler? MOVEQ R8,#-1 ;No more to do BEQ %13event_poll ;No -- Scan filters LDMIA R8,{R8-R9,R12} ;Get arguments MOV R14,PC ;Set return point MOV PC,R9 ;Branch to handler BCC %12event_poll ;Keep trying 13event_poll STR R8,event__fakePos ;Store the fake position ; --- Store the last event away --- 19event_poll ADR R14,event__lastCode ;Point to last event cache STMIA R14,{R0,R1} ;Save the information away ; --- Scan the post-filters --- LDR R8,event__postList ;Get post-list pointer ADDS R0,R0,#0 ;Clear carry 20event_poll TEQ R8,#0 ;Are we at the end BEQ %30event_poll ;Yes -- branch ahead LDMIA R8,{R8-R9,R12} ;Get list fields MOV R14,PC ;Set up return address MOV PC,R9 ;Branch to client routine BCC %20event_poll ;Keep going through list 30event_poll LDMFD R13!,{R8-R10,R12,R14} BICCCS PC,R14,#C_flag ;Clear C if C clear :-) ORRCSS PC,R14,#C_flag ;Set C if C set LTORG ; --- event_last --- ; ; On entry: -- ; ; On exit: R0 == last event code received from Wimp_Poll ; R1 == pointer to accompanying event data ; ; Use: Allows you to read the full event information. The event ; is the same one currently being or most recently dispatched ; to the postfilter list, i.e. fake events are also returned ; by this call. If no event has yet been received, the return ; values are undefined. EXPORT event_last event_last ROUT LDR R0,event__wSpace ;Load my workspace offset LDR R1,sapph_workspace ;Load workspace base ADD R0,R1,R0 ;Find actual workspace addr ADD R0,R0,#:INDEX: event__lastCode LDMIA R0,{R0,R1} ;Load the information MOVS PC,R14 ;Return to caller LTORG ; --- event_init --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Initialises the event system. EXPORT event_init event_init ROUT STMFD R13!,{R0-R3,R10,R14} ;Stack some registers WSPACE event__wSpace,R10 ;Get my workspace ; --- Are we already initialised? --- LDR R0,event__flags ;Get my flags TST R0,#event__INITED ;Are we initialised? LDMNEFD R13!,{R0-R3,R10,PC}^ ;Yes -- return ORR R0,R0,#event__INITED ;Set initialised flag STR R0,event__flags ;And store them back ; --- Clear rest of workspace --- MOV R0,#0 ;Zero some registers MOV R1,#0 MOV R2,#0 MOV R3,#-1 STMIB R10,{R0-R3} ;Clear pre/post list ; --- Initialise suballoc --- BL sub_init ;Sub, short for SUBmarine ; --- That's it now --- LDMFD R13!,{R0-R3,R10,PC}^ ;Return LTORG event__wSpace DCD 0 ;My workspace pointer ;----- Workspace ------------------------------------------------------------ ^ 0,R10 event__wStart # 0 event__flags # 4 ;Flags event__INITED EQU (1<<0) ;I've been initialised event__preList # 4 ;Pre-Poll list event__fakeList # 4 ;Event-faking list event__postList # 4 ;Post-Poll list event__fakePos # 4 ;The current fake position event__lastCode # 4 ;The last event reason code event__lastData # 4 ;The last event data pointer event__prevR0 # 4 ;R0 for real event event__buffer # 256 ;The event received event__wSize EQU {VAR}-event__wStart ; --- Pre/Post list structure --- ^ 0 list__next # 4 list__proc # 4 list__r12 # 4 list__size # 0 AREA |Sapphire$$LibData|,CODE,READONLY DCD event__wSize ;Workspace size DCD event__wSpace ;Workspace pointer DCD 0 ;Scratchpad size DCD event_init ;Initialisation code ;----- That's all, folks ---------------------------------------------------- END