X-Git-Url: https://git.distorted.org.uk/~mdw/ssr/blobdiff_plain/a3da4c116d4216fdec125d687dfc347e343a8b28..c1b567d833a004bb3d978f1f7c99f42cefa7845c:/StraySrc/Libraries/Core/TearSupt/bs/tearSupt.bas diff --git a/StraySrc/Libraries/Core/TearSupt/bs/tearSupt.bas b/StraySrc/Libraries/Core/TearSupt/bs/tearSupt.bas new file mode 100644 index 0000000..20b3426 --- /dev/null +++ b/StraySrc/Libraries/Core/TearSupt/bs/tearSupt.bas @@ -0,0 +1,812 @@ +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% +