REM REM tearSupt.bs REM REM TearoffSupport code (encrypted) REM REM © 1994-1998 Straylight REM REM ----- Licensing note ---------------------------------------------------- REM REM This file is part of Straylight's Tearoff Menu System (TMS), but it's REM distributed with Straylight's core libraries (corelib). REM REM TMS is free software; you can redistribute it and/or modify REM it under the terms of the GNU General Public License as published by REM the Free Software Foundation; either version 2, or (at your option) REM any later version REM REM TMS is distributed in the hope that it will be useful, REM but WITHOUT ANY WARRANTY; without even the implied warranty of REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the REM GNU General Public License for more details. REM REM You should have received a copy of the GNU General Public License REM along with Corelib. If not, write to the Free Software Foundation, REM 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. LIBRARY "libs:BAS" ON ERROR ERROR 0,REPORT$+" ["+STR$(ERL)+"]" PROCbas_init PROCbas_aofInit(&4000) XOS_ClaimProcessorVector=&20069 XOS_SynchroniseCodeAreas=&2006E PRINT "Assembling..."; ts_version=110 FOR o=4 TO 6 STEP 2 [ opt o FNpass ;----- TearoffSupport interface code ---------------------------------------- FNarea("Asm$$Code","CODE,READONLY") ; --- tearSupport_init --- ; ; On entry; -- ; ; On exit; -- ; ; Use; Initialises tearSupport FNexport("tearSupport_init") .tearSupport_init stmfd r13!,{r0-r4,r12,r14} ;Save some registers mvn r0,#0 ;Find address of TearSupport swi "XOS_ChangeEnvironment" ;Find the address then bvc tSupt_init10 ;If resident, skip install ; --- We need to set up the RMA block --- .tSupt_init00 ldr r3,ts__image ;Load RMA block size wanted mov r0,#6 ;Allocate RMA space swi "OS_Module" ;Try to allocate anyway mov r1,r2 ;Keep pointer to RMA block ; --- Copy the program across and decrypt it --- adr r0,ts__image+4 ;Point to encrypted image ldr r3,FNlitw(ts__imageEnd-ts__image-4) ldr r12,FNlitw(&1b9a7f83) ;IV for decryption process .tSupt_init05 ldr r4,[r0],#4 ;Get a word from the image eor r14,r12,r4,ror #24 ;Decrypt the word str r14,[r2],#4 ;Store the word in the block mov r12,r4 ;Update IV from ciphertext subs r3,r3,#4 ;Decrement the size counter bgt tSupt_init05 ;More to do -- loop ; --- Be friendly to StrongARM --- ; ; By spooky coincidence, these registers are set up already. mov r0,#1 ;Synchronise address range sub r2,r2,#4 ;Because Acorn are weird... swi XOS_SynchroniseCodeAreas ;Go and do that, please ; --- Initialise the image --- mov r14,pc ;Get return address add pc,r1,#0 ;Call the initialise routine str r1,ts__image ;Store base address away ldmfd r13!,{r0-r4,r12,pc}^ ;Return to caller ; --- It's already resident --- .tSupt_init10 cmp r2,#ts_version ;Which version is in there? strcs r1,ts__image ;New enough -- store base ldmcsfd r13!,{r0-r4,r12,pc}^ ;And return to caller adr r0,ts__tooOld ;Point to error message swi "OS_GenerateError" ;And raise merry hell ldmfd r13!,{r0-r4,r12,pc}^ ;Return to caller .ts__tooOld dcd 1 dcb "Tearoff support code is too old" dcb 0 FNltorg ; --- tearSupport_opened --- ; ; On entry; R0 == task handle of task which opened tearoff menu ; ; On exit; -- ; ; Use; Informs TearSupport that a transient tearoff menu has been ; opened, and which task owns the menu. FNexport("tearSupport_opened") .tearSupport_opened stmfd r13!,{r12,r14} ldr r12,ts__image mov r14,pc add pc,r12,#4 ldmfd r13!,{r12,pc}^ ; --- tearSupport_closed --- ; ; On entry; -- ; ; On exit; -- ; ; Use; Informs TearSupport that a transient tearoff menu has been ; closed, and that support is no longer required for it. FNexport("tearSupport_closed") .tearSupport_closed stmfd r13!,{r12,r14} ldr r12,ts__image mov r14,pc add pc,r12,#8 ldmfd r13!,{r12,pc}^ ; --- tearSupport_switch --- ; ; On entry; R0 == 1 to disable, 0 to enable trapping ; ; On exit; -- ; ; Use; Enables or disables trapping of Wimp_CreateMenu while a ; transient tearoff menu is open. This is intended to allow ; use of Wimp_CreateMenu by the transient tearoff owner while ; a transient tearoff is open (e.g. to close Wimp menus). FNexport("tearSupport_switch") .tearSupport_switch stmfd r13!,{r12,r14} ldr r12,ts__image mov r14,pc add pc,r12,#12 ldmfd r13!,{r12,pc}^ ;----- The actual TearoffSupport code --------------------------------------- ; --- Structure of the code --- ; ; Since this chunk is going to be copied into the RMA, we need to be able to ; interface with it. We stick a branch table on the beginning and encrypt ; everything else. FNnoReloc .ts__image dcd ts__wSize+ts__wSpace-ts__image-4 b ts_init b ts_opened b ts_closed b ts_switch b ts_unload ;----- Initialisation ------------------------------------------------------- ; --- ts_init --- ; ; On entry; -- ; ; On exit; -- ; ; Use; Initialises the TearSupport system. .ts_init stmfd r13!,{r0-r2,r14} ;Stack link register nicely FNadrl (r12,ts__wSpace) ;Find workspace address mov r0,#0 ;A nice 0 value str r0,[r12,#ts_useCount] ;Stuff it in the usage count str r0,[r12,#ts_owner] ;No task using me yet strb r0,[r12,#ts_swiCaught] ;Remember we're not on SWIV mov r0,#ChangeEnvV ;Trap OS_ChangeEnvironment adr r1,ts_changeEnv ;Point to my handler mov r2,r12 ;Pass my workspace pointer swi "XOS_Claim" ;Claim the vector nicely ; --- Read the OS version --- mov r0,#129 ;Load the OS version number mov r1,#0 ;Set up OS_Byte arguments mov r2,#255 ;For most obscure OS call swi "OS_Byte" ;Read the version number strb r1,[r12,#ts_osVersion] ;Save this away for later ; --- I think that's it --- ldmfd r13!,{r0-r2,pc}^ ;Return to caller happy FNltorg ; --- ts_unload --- ; ; On entry; -- ; ; On exit; V clear if unloaded OK, otherwise V set ; ; Use; Attempts to remove TearSupt from memory, to replace it with ; a later version. If we can't close down, because we're in ; use, we return an error. .ts_unload bic r14,r14,#&10000000 ;Clear the V flag stmfd r13!,{r0-r2,r14} ;Save some registers FNadrl (r12,ts__wSpace) ;Find the workspace address ; --- Free all the vectors --- mov r0,#ChangeEnvV ;Trap OS_ChangeEnvironment adr r1,ts_changeEnv ;Point to my handler mov r2,r12 ;Pass my workspace pointer swi "XOS_Release" ;Let go of that bl ts_closed ;Pretend the transient closed ; --- Deallocate my memory --- ; ; This is a bit tricky, because I'm in it. I have to ; copy a bit of myself onto the stack, and call that. Yuk. adr r14,ts__return ;Point to return code ldmia r14,{r0-r2} ;Load the code out stmfd r13!,{r0-r2} ;Save it onto the stack adr r2,ts__image+4 ;Point to the block base mov r0,#7 ;Deallocate an RMA block mov pc,r13 ;Call return code .ts__return swi "OS_Module" ;Deallocate the memory add r13,r13,#12 ;Point to stack frame ldmfd r13!,{r0-r2,pc}^ ;Return without mishap FNltorg ; --- Vector numbers --- ] MouseV = &1A InsV = &14 ChangeEnvV = &1E [ opt o ; --- ts_opened --- ; ; On entry; R0 == task handle attempting to open tearoff transient ; ; On exit; -- ; ; Use; Informs the TearSupt system that a task is opening a ; transient tearoff menu. .ts_opened stmfd r13!,{r0-r2,r11,r12,r14} mov r11,r0 ;Look after the task handle FNadrl (r12,ts__wSpace) ;Find my workspace address ; --- Make sure we need to do this --- ldr r0,[r12,#ts_useCount] ;Get the counter cmp r0,#0 ;Am I currently running? bne ts_opened00 ;Yes -- skip this little bit ; --- Claim event vector --- swi "XOS_Mouse" ;Get the current mouse pos str r2,[r12,#ts_mouseState] ;Store it in workspace mov r0,#MouseV ;Vector number adr r1,ts_mouse ;Point to event handler mov r2,r12 ;Point to workspace swi "XOS_Claim" ;Try it and see mov r0,#InsV ;Vector number adr r1,ts_insert ;Point to event handler mov r2,r12 ;Point to workspace swi "XOS_Claim" ;Try it and see addvs r13,r13,#4 ldmvsfd r13!,{r1,r2,r11,r12,pc} ;Can't see this failing, but bl ts_swiClaim ; --- Update my tables and leave --- .ts_opened00 ldr r0,[r12,#ts_owner] ;Who's using me at the mo? cmp r0,r11 ;Is it someone else? cmpne r0,#0 ;Make sure s'not a ghost blne ts_escape_cb ;Tell the appl to close str r11,[r12,#ts_owner] ;Store the new handle ldr r0,[r12,#ts_useCount] ;Find my usage counter add r0,r0,#1 ;Bump it str r0,[r12,#ts_useCount] ;And store it back for later ldmfd r13!,{r0-r2,r11,r12,pc}^ FNltorg ; --- ts_closed --- ; ; On entry; -- ; ; On exit; -- ; ; Use; Informs TearSupt that the transient tearoff has been closed. ; If no transient is open, no action is performed. .ts_closed stmfd r13!,{r12,r14} ;Save some registers adr r12,ts__wSpace ;Find my workspace address ldr r14,[r12,#ts_useCount] ;Find out my counter thing cmp r14,#0 ;Is it zero? ldmeqfd r13!,{r12,pc}^ ;Someone's being silly subs r14,r14,#1 ;Decrement the counter str r14,[r12,#ts_useCount] ;Store for later ldmnefd r13!,{r12,pc}^ ;Return if still nonzero ; --- Remove handlers and things --- stmfd r13!,{r0-r2} ;Save some more registers bl ts_swiRelease ;Release SWI vector patch mov r0,#InsV ;Vector number adr r1,ts_insert ;Point to handler code mov r2,r12 ;Point to workspace swi "XOS_Release" ;Let go of the vector mov r0,#MouseV ;Vector number adr r1,ts_mouse ;Point to handler code mov r2,r12 ;Point to workspace swi "XOS_Release" ;Let go of the vector ldmfd r13!,{r0-r2,r12,pc}^ ;Return to caller FNltorg ; --- ts_switch --- ; ; On entry; R0 == 1 to suspend trapping, 0 to unsuspend ; ; On exit; -- ; ; Use; Enables or disables trapping of Wimp_CreateMenu, to enable ; TMS implementations to close Wimp menus where necessary. .ts_switch stmfd r13!,{r12,r14} ;Save some registers adr r12,ts__wSpace ;Find my workspace strb r0,[r12,#ts_swiThreaded] ;Disable the SWI patch ldmfd r13!,{r12,pc}^ ;And return to caller FNltorg ;----- The handlers and callbacks ------------------------------------------- ; --- ts_changeEnv --- ; ; On entry; As for OS_ChangeEnvironment ; ; On exit; R0 == address of TearSupt, if R0 == -1 on entry ; ; Use; Traps odd calls to OS_ChangeEnvironment to allow TearSupt ; to be located. .ts_changeEnv cmn r0,#1 ;Is it our special env code? adreq r1,ts__image+4 ;Yes -- return ptr to base moveq r2,#ts_version ;And get the version number ldmeqfd r13!,{pc}^ ;And claim the vector movs pc,r14 ;Otherwise pass on vector ; --- ts_insert --- ; ; On entry; R0 == byte inserted into buffer ; R1 == buffer number ; ; On exit; -- ; ; Use; Inspects all insertions into buffers, and traps attempts ; to insert escape keypresses, converting these to requests ; to close the current transient tearoff. .ts_insert cmp r0,#27 ;Make sure it's an escape cmpeq r1,#0 ;And it's from the keyboard movnes pc,r14 ;If not, give up and leave stmfd r13!,{r14} ;Save a register ldr r14,[r12,#ts_owner] ;Get my owner's ID cmn r14,#1 ;Is it valid? ldmeqfd r13!,{pc}^ ;No -- then return to caller ; --- Mess about with the processor status --- stmfd r13!,{r0,r1,r8} ;Store registers away mov r8,pc ;Get PC with PSR teqp pc,#3 ;Enter SVC mode mov r0,r0 ;Avoid contention of R13/R14 stmfd r13!,{r14} ;Stack return address adr r0,ts_escape_cb ;Point to callback routine mov r1,r12 ;Point to workspace swi "XOS_AddCallBack" ;Add the callback routine ldmfd r13!,{r14} ;Restore R14_svc teqp r8,#0 ;Restore old PSR values mov r0,r0 ;No-op to keep ARM happy ldmfd r13!,{r0,r1,r8,pc}^ ;Return to caller FNltorg ; --- ts_mouse --- ; ; On entry; -- ; ; On exit; -- ; ; Use; Inspects all mouse positions returned by OS_Mouse, and sends ; them to the current transient owner. .ts_mouse stmfd r13!,{r10-r12,r14} ;Stack some registers ; --- Pass on the vector, leaving ourself on the stack --- ; ; Modified from Acorn's code to avoid dependency on ; possibly non-compatible PC+12 behaviour. mov r14,pc ;Get current program counter add r14,r14,#12 ;Point at our processing code stmfd r13!,{r14} ;Make us get called back add r12,r13,#4 ;Point to saved R10 on stack ldmia r12,{r10-r12,pc} ;Call next routine on vector ; --- The vector has now completed nicely --- ldr r12,[r13,#8] ;Get my stacked r12 stmfd r13!,{r0-r3} ;Stack some registers for me ldr r0,[r12,#ts_mouseState] ;Get old mouse state str r2,[r12,#ts_mouseState] ;Store as the old state bics r2,r2,r0 ;Find out what changed ldmeqfd r13!,{r0-r3,r10-r12,r14,pc} ;If nothing then return ; --- A button was clicked -- tell our client --- add r1,r12,#ts_message+20 ;Point to message buffer swi "XWimp_GetPointerInfo" ;Get pointer info sub r1,r1,#20 ;Point to base of message mov r0,#40 ;Length of message str r0,[r1,#0] ;Store in message block mov r0,#0 ;This isn't a reply str r0,[r1,#12] ;So zero the your_ref ldr r0,FNlitw(&4A340) ;The magic message number str r0,[r1,#16] ;Fill it in mov r0,#17 ;Don't want it bouncing ldr r2,[r12,#ts_owner] ;Find my owner application swi "XWimp_SendMessage" ;Send it the message ldmfd r13!,{r0-r3,r10-r12,r14,pc} ;We're a happy bunny FNltorg ; --- ts_escape_cb --- ; ; On entry; -- ; ; On exit; -- ; ; Use; Sends a message to the transient tearoff owner, to tell ; it to close the transient. This is usually as a result of ; the user pressing escape or another task calling ; Wimp_CreateMenu. .ts_escape_cb stmfd r13!,{r0-r3,r14} ;Save some registers add r1,r12,#ts_message ;Point to message buffer mov r0,#20 ;Length of message str r0,[r1,#0] ;Store in message block mov r0,#0 ;This isn't a reply str r0,[r1,#12] ;So zero the your_ref ldr r0,FNlitw(&4A341) ;The magic message number str r0,[r1,#16] ;Fill it in mov r0,#17 ;Don't want it bouncing ldr r2,[r12,#ts_owner] ;Find my owner application swi "XWimp_SendMessage" ;Send it the message mvn r0,#0 ;Stop it happening again str r0,[r12,#ts_owner] ;Won't happen now! ldmfd r13!,{r0-r3,pc}^ ;Don't worry. Be happy. FNltorg ;----- SWI vector handling -------------------------------------------------- ; ; Warning; this section contains some really heavy stuff. If you're nervous, ; you may wish to seek medical advice before looking at this code. We can't ; accept any responsibility for any loss or disability incurred as a result ; of reading this source. ; --- ts_swiClaim --- ; ; On entry; -- ; ; On exit; -- ; ; Use; Sets up the SWI vector patch. .ts_swiClaim stmfd r13!,{r0-r3,r14} ;Stack some registers ldrb r0,[r12,#ts_swiCaught] ;Have we done it already? cmp r0,#0 ;Just check ldmnefd r13!,{r0-r3,pc}^ ;If so, just carry on ldrb r14,[r12,#ts_osVersion] ;Get the OS version cmp r14,#&a5 ;Is this a RISC PC? bcs ts_swiClaim50 ;Yes -- do special things mov r0,#0 ;Point to hardware vectors ldr r1,[r0,#&08] ;Get the SWIV instruction str r1,[r12,#ts_oldSWIinstr] ;Remember this instruction and r2,r1,#&0F000000 ;Get the basic instruction cmp r2,#&0A000000 ;Is it a branch? beq ts_swiClaim00 ;Yes -- handle that ; --- Mangle an LDR PC,[PC,#...] --- ldr r2,FNlitw(&FFF) ;Mask off LDR bits and r2,r1,r2 ;Get the offset of LDR tst r1,#1<<23 ;Check the sign bit addne r3,r2,#&10 ;If additive, then add offset rsbeq r3,r2,#&10 ;If subtractive, subtract ;-) str r3,[r12,#ts_oldSWIaddr] ;Store this address away b ts_swiClaim01 ;Now insert our branch code ; --- Mangle a B ... --- .ts_swiClaim00 bic r2,r1,#&FF000000 ;Clear instruction bits add r2,r2,#4 ;Take pipeline into account mov r2,r2,lsl #2 ;Word align the result bic r2,r2,#&FC000003 ;Turn it into a real address str r2,[r12,#ts_dummySWIptr] ;Store this in our pointer add r3,r12,#ts_dummySWIptr ;Point to this pointer str r3,[r12,#ts_oldSWIaddr] ;Store *this* address away ; --- Now insert our own instruction --- .ts_swiClaim01 adr r1,ts_swiClaimer ;Point to the routine mov r1,r1,lsr #2 ;Shift off bottom zero bits sub r1,r1,#4 ;Adjust the address of branch orr r1,r1,#&EA000000 ;Make it a branch instr str r1,[r12,#ts_newSWIinstr] ;Store this new instruction swi "OS_EnterOS" ;We're messing with SWI vect str r1,[r0,#8] ;This is now the SWI vector teqp pc,#0 ;Back to user mode mov r0,r0 ;No-op for strange reasons mov r0,#1 ;We've now patched SWIV strb r0,[r12,#ts_swiCaught] ;So remember this mov r0,#0 ;Not yet threaded, though strb r0,[r12,#ts_swiThreaded] ldmfd r13!,{r0-r3,pc}^ ;Return to caller ; --- We have an OS call to do this --- .ts_swiClaim50 mov r0,#2 ;Claim SWI vector orr r0,r0,#256 ;Set the `claim' flag adr r1,ts_swi610 ;Point to handler routine swi "XOS_IntOff" ;Stop all SWIs for a bit swi XOS_ClaimProcessorVector str r1,[r12,#ts_dummySWIptr] ;Save old handler address add r3,r12,#ts_dummySWIptr ;Point to this pointer str r3,[r12,#ts_oldSWIaddr] ;And store *this* address swi "XOS_IntOn" ;We can handle SWIs again now mov r0,#1 ;We've now patched SWIV strb r0,[r12,#ts_swiCaught] ;So remember this mov r0,#0 ;Not yet threaded, though strb r0,[r12,#ts_swiThreaded] ldmfd r13!,{r0-r3,pc}^ ;Return to caller FNltorg ; --- ts_swiRelease --- ; ; On entry; -- ; ; On exit; CS if patch removed OK, else CC ; ; Use; Attempts to remove the SWI vector patch. If this can't be ; done, then the patch is left in. .ts_swiRelease stmfd r13!,{r0-r2,r14} ;Stack registers ldrb r0,[r12,#ts_swiCaught] ;Is the vector trapped? cmp r0,#0 ;Quick check... ldmeqfd r13!,{r0-r2,pc}^ ;No -- return then ; --- Check if this is a RISC PC --- ldrb r0,[r12,#ts_osVersion] ;Load the OS version cmp r0,#&a5 ;Is this a RISC PC bcs ts_swiRel50 ;Yes -- do different things mov r0,#0 ;Point to hardware vectors ldr r1,[r0,#8] ;Get SWI vector instruction ldr r2,[r12,#ts_newSWIinstr] ;Get our one cmp r1,r2 ;Are they the same? bne ts_swiRel90 ;No -- couldn't reset it ldr r1,[r12,#ts_oldSWIinstr] ;Get the old version then swi "OS_EnterOS" ;We're messing with SWI vect str r1,[r0,#8] ;Reinstate the old vector teqp pc,#0 ;Back to user mode mov r0,r0 ;Wait for things to settle strb r0,[r12,#ts_swiCaught] ;SWIV no longer patched ldmfd r13!,{r0-r2,r14} ;Return to caller orrs pc,r14,#1<<29 ;Setting C to say *YES* ; --- Release SWI vector using OS call --- .ts_swiRel50 mov r0,#2 ;Releasing the SWI vector ldr r1,[r12,#ts_dummySWIptr] ;Load address of old claimer adr r2,ts_swi610 ;Point to expected handler swi XOS_ClaimProcessorVector bvs ts_swiRel90 ;Error -- couldn't do it mov r14,#0 ;Clear claimed flag strb r14,[r12,#ts_swiCaught] ;SWIV no longer patched ldmfd r13!,{r0-r2,r14} ;Return to caller orrs pc,r14,#1<<29 ;Setting C to say *YES* ; --- Couldn't do it --- .ts_swiRel90 ldmfd r13!,{r0-r2,r14} ;Restore registers bics pc,r14,#1<<29 ;But clear C on exit FNltorg ; --- ts_swi610 --- ; ; On entry; R0-R8 == arguments to SWI ; R9-R12 == random values from the OS ; R13 == supervisor stack pointer ; R14 == return address from client ; ; On exit; R0-R8 == returned from SWI ; R9-R13 *AND SPSR_svc* preserved ; ; Use; Intercepts all SWI calls in the system, catching ; Wimp_CreateMenus and informing the transient owner of them. .ts_swi610 stmfd r13!,{r10-r12,r14,pc} ;Stack some registers ; --- Move into 26 bit mode --- dcd &e14fb000 ;mrs r11,spsr_all stmfd r13!,{r11} ;Save this on the stack and r12,r11,#&f0000003 ;Get the processor status orr r14,r14,r12 ;Add it to the R14 value and r12,r11,#&c0 ;Get the interrupt flags orr r14,r14,r12,lsl #20 ;Put them into R14 too dcd &e10fb000 ;mrs r11,cpsr_all bic r11,r11,#&1f ;Clear all the mode bits orr r11,r11,#&03 ;Set SVC_26 dcd &e129f00b ;msr cpsr_all,r11 ; --- Now find out about the SWI --- adr r12,ts__wSpace ;Point to workspace pointer ldrb r10,[r12,#ts_swiThreaded] ;Is this routine threaded? cmp r10,#0 ;Check now, or forever... bne ts_swi610_00 ;If so, skip onwards bic r10,r14,#&FC000003 ;Mask off saved PSR bits ldr r11,[r10,#-4] ;Get SWI instruction ldr r10,FNlitw(&FFF20000) ;Mask off silly SWI bits bic r11,r11,r10 ;Get the pure SWI number ldr r10,FNlitw(FNswiNum("Wimp_CreateMenu")) cmp r10,r11 ;See if it's interesting beq ts_swi610_10 ;Yes -- process it nicely .ts_swi610_00 ldmfd r13!,{r14} ;Load the saved SPSR dcd &e169f00e ;msr spsr_all,r14 ldr r14,[r12,#ts_oldSWIaddr] ;Point to old pointer ldr r14,[r14,#0] ;Dereference the pointer str r14,[r13,#16] ;Overwrite PC on the stack ldmfd r13!,{r10-r12,r14,pc} ;Pass on to real SWI routine ; --- Wimp_CreateMenu handling --- .ts_swi610_10 mov r10,#1 ;Set the threaded flag strb r10,[r12,#ts_swiThreaded] ;Remember we're in here bl ts_escape_cb ;Send out the close message .ts_swi610_01 mov r10,#0 ;Not threaded any more strb r10,[r12,#ts_swiThreaded] ;Store this for others b ts_swi610_00 ;And continue main thread FNltorg ; --- ts_swiClaimer --- ; ; On entry; R0-R8 == arguments to SWI ; R9-R12 == random values from the OS ; R13 == supervisor stack pointer ; R14 == return address from client ; ; On exit; R0-R8 == returned from SWI ; R9-R13 preserved ; ; Use; Intercepts all SWI calls in the system, catching ; Wimp_CreateMenus and informing the transient owner of them. .ts_swiClaimer stmfd r13!,{r10-r12,r14,pc} ;Stack some registers adr r12,ts__wSpace ;Point to workspace pointer ldrb r10,[r12,#ts_swiThreaded] ;Is this routine threaded? cmp r10,#0 ;Check now, or forever... bne ts_swiClaimer00 ;If so, skip onwards bic r10,r14,#&FC000003 ;Mask off saved PSR bits ldr r11,[r10,#-4] ;Get SWI instruction ldr r10,FNlitw(&FFF20000) ;Mask off silly SWI bits bic r11,r11,r10 ;Get the pure SWI number ldr r10,FNlitw(FNswiNum("Wimp_CreateMenu")) cmp r10,r11 ;See if it's interesting beq ts_swiClaimer10 ;Yes -- process it nicely .ts_swiClaimer00 ldr r14,[r12,#ts_oldSWIaddr] ;Point to old pointer ldr r14,[r14,#0] ;Dereference the pointer str r14,[r13,#16] ;Overwrite PC on the stack ldmfd r13!,{r10-r12,r14,pc} ;Pass on to real SWI routine ; --- Wimp_CreateMenu handling --- .ts_swiClaimer10 mov r10,#1 ;Set the threaded flag strb r10,[r12,#ts_swiThreaded] ;Remember we're in here bl ts_escape_cb ;Send out the close message .ts_swiClaimer01 mov r10,#0 ;Not threaded any more strb r10,[r12,#ts_swiThreaded] ;Store this for others b ts_swiClaimer00 ;And continue main thread FNltorg .ts__wSpace .ts__imageEnd ] PROCws_start ts_useCount =FNws_word ts_owner =FNws_word ts_mouseState =FNws_word ts_newMouse =FNws_word ts_oldSWIaddr =FNws_word ts_dummySWIptr =FNws_word ts_oldSWIinstr =FNws_word ts_newSWIinstr =FNws_word ts_swiCaught =FNws_byte ts_swiThreaded =FNws_byte ts_osVersion =FNws_byte PROCws_align ts_message =FNws (40) ts__wSize =FNws (0) NEXT PRINT '"Encrypting..."; REM --- Encrypt the RMA resident section --- iv%=&1b9a7f83 FOR i%=ts__image+4 TO ts__imageEnd STEP 4 x%=i%!(O%-P%) EOR iv% x%=(x%>>>8) OR (x%<<24) i%!(O%-P%)=x% iv%=x% NEXT PRINT '"Saving..."; PROCbas_aofSave PRINT '"Done" END DEF FNswiNum(swi$) LOCAL swin% SYS "OS_SWINumberFromString",,swi$ TO swin% =swin%