Commit | Line | Data |
---|---|---|
c1b567d8 MW |
1 | REM |
2 | REM tearSupt.bs | |
3 | REM | |
4 | REM TearoffSupport code (encrypted) | |
5 | REM | |
6 | REM © 1994-1998 Straylight | |
7 | REM | |
8 | ||
9 | REM ----- Licensing note ---------------------------------------------------- | |
10 | REM | |
11 | REM This file is part of Straylight's Tearoff Menu System (TMS), but it's | |
12 | REM distributed with Straylight's core libraries (corelib). | |
13 | REM | |
14 | REM TMS is free software; you can redistribute it and/or modify | |
15 | REM it under the terms of the GNU General Public License as published by | |
16 | REM the Free Software Foundation; either version 2, or (at your option) | |
17 | REM any later version | |
18 | REM | |
19 | REM TMS is distributed in the hope that it will be useful, | |
20 | REM but WITHOUT ANY WARRANTY; without even the implied warranty of | |
21 | REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
22 | REM GNU General Public License for more details. | |
23 | REM | |
24 | REM You should have received a copy of the GNU General Public License | |
25 | REM along with Corelib. If not, write to the Free Software Foundation, | |
26 | REM 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
27 | ||
28 | LIBRARY "libs:BAS" | |
29 | ||
30 | ON ERROR ERROR 0,REPORT$+" ["+STR$(ERL)+"]" | |
31 | PROCbas_init | |
32 | PROCbas_aofInit(&4000) | |
33 | ||
34 | XOS_ClaimProcessorVector=&20069 | |
35 | XOS_SynchroniseCodeAreas=&2006E | |
36 | ||
37 | PRINT "Assembling..."; | |
38 | ||
39 | ts_version=110 | |
40 | ||
41 | FOR o=4 TO 6 STEP 2 | |
42 | [ opt o | |
43 | FNpass | |
44 | ||
45 | ;----- TearoffSupport interface code ---------------------------------------- | |
46 | ||
47 | FNarea("Asm$$Code","CODE,READONLY") | |
48 | ||
49 | ; --- tearSupport_init --- | |
50 | ; | |
51 | ; On entry; -- | |
52 | ; | |
53 | ; On exit; -- | |
54 | ; | |
55 | ; Use; Initialises tearSupport | |
56 | ||
57 | FNexport("tearSupport_init") | |
58 | .tearSupport_init | |
59 | ||
60 | stmfd r13!,{r0-r4,r12,r14} ;Save some registers | |
61 | mvn r0,#0 ;Find address of TearSupport | |
62 | swi "XOS_ChangeEnvironment" ;Find the address then | |
63 | bvc tSupt_init10 ;If resident, skip install | |
64 | ||
65 | ; --- We need to set up the RMA block --- | |
66 | ||
67 | .tSupt_init00 ldr r3,ts__image ;Load RMA block size wanted | |
68 | mov r0,#6 ;Allocate RMA space | |
69 | swi "OS_Module" ;Try to allocate anyway | |
70 | mov r1,r2 ;Keep pointer to RMA block | |
71 | ||
72 | ; --- Copy the program across and decrypt it --- | |
73 | ||
74 | adr r0,ts__image+4 ;Point to encrypted image | |
75 | ldr r3,FNlitw(ts__imageEnd-ts__image-4) | |
76 | ldr r12,FNlitw(&1b9a7f83) ;IV for decryption process | |
77 | ||
78 | .tSupt_init05 ldr r4,[r0],#4 ;Get a word from the image | |
79 | eor r14,r12,r4,ror #24 ;Decrypt the word | |
80 | str r14,[r2],#4 ;Store the word in the block | |
81 | mov r12,r4 ;Update IV from ciphertext | |
82 | subs r3,r3,#4 ;Decrement the size counter | |
83 | bgt tSupt_init05 ;More to do -- loop | |
84 | ||
85 | ; --- Be friendly to StrongARM --- | |
86 | ; | |
87 | ; By spooky coincidence, these registers are set up already. | |
88 | ||
89 | mov r0,#1 ;Synchronise address range | |
90 | sub r2,r2,#4 ;Because Acorn are weird... | |
91 | swi XOS_SynchroniseCodeAreas ;Go and do that, please | |
92 | ||
93 | ; --- Initialise the image --- | |
94 | ||
95 | mov r14,pc ;Get return address | |
96 | add pc,r1,#0 ;Call the initialise routine | |
97 | str r1,ts__image ;Store base address away | |
98 | ldmfd r13!,{r0-r4,r12,pc}^ ;Return to caller | |
99 | ||
100 | ; --- It's already resident --- | |
101 | ||
102 | .tSupt_init10 cmp r2,#ts_version ;Which version is in there? | |
103 | strcs r1,ts__image ;New enough -- store base | |
104 | ldmcsfd r13!,{r0-r4,r12,pc}^ ;And return to caller | |
105 | ||
106 | adr r0,ts__tooOld ;Point to error message | |
107 | swi "OS_GenerateError" ;And raise merry hell | |
108 | ldmfd r13!,{r0-r4,r12,pc}^ ;Return to caller | |
109 | ||
110 | .ts__tooOld dcd 1 | |
111 | dcb "Tearoff support code is too old" | |
112 | dcb 0 | |
113 | ||
114 | FNltorg | |
115 | ||
116 | ; --- tearSupport_opened --- | |
117 | ; | |
118 | ; On entry; R0 == task handle of task which opened tearoff menu | |
119 | ; | |
120 | ; On exit; -- | |
121 | ; | |
122 | ; Use; Informs TearSupport that a transient tearoff menu has been | |
123 | ; opened, and which task owns the menu. | |
124 | ||
125 | FNexport("tearSupport_opened") | |
126 | .tearSupport_opened | |
127 | ||
128 | stmfd r13!,{r12,r14} | |
129 | ldr r12,ts__image | |
130 | mov r14,pc | |
131 | add pc,r12,#4 | |
132 | ldmfd r13!,{r12,pc}^ | |
133 | ||
134 | ; --- tearSupport_closed --- | |
135 | ; | |
136 | ; On entry; -- | |
137 | ; | |
138 | ; On exit; -- | |
139 | ; | |
140 | ; Use; Informs TearSupport that a transient tearoff menu has been | |
141 | ; closed, and that support is no longer required for it. | |
142 | ||
143 | FNexport("tearSupport_closed") | |
144 | .tearSupport_closed | |
145 | ||
146 | stmfd r13!,{r12,r14} | |
147 | ldr r12,ts__image | |
148 | mov r14,pc | |
149 | add pc,r12,#8 | |
150 | ldmfd r13!,{r12,pc}^ | |
151 | ||
152 | ; --- tearSupport_switch --- | |
153 | ; | |
154 | ; On entry; R0 == 1 to disable, 0 to enable trapping | |
155 | ; | |
156 | ; On exit; -- | |
157 | ; | |
158 | ; Use; Enables or disables trapping of Wimp_CreateMenu while a | |
159 | ; transient tearoff menu is open. This is intended to allow | |
160 | ; use of Wimp_CreateMenu by the transient tearoff owner while | |
161 | ; a transient tearoff is open (e.g. to close Wimp menus). | |
162 | ||
163 | FNexport("tearSupport_switch") | |
164 | .tearSupport_switch | |
165 | ||
166 | stmfd r13!,{r12,r14} | |
167 | ldr r12,ts__image | |
168 | mov r14,pc | |
169 | add pc,r12,#12 | |
170 | ldmfd r13!,{r12,pc}^ | |
171 | ||
172 | ;----- The actual TearoffSupport code --------------------------------------- | |
173 | ||
174 | ; --- Structure of the code --- | |
175 | ; | |
176 | ; Since this chunk is going to be copied into the RMA, we need to be able to | |
177 | ; interface with it. We stick a branch table on the beginning and encrypt | |
178 | ; everything else. | |
179 | ||
180 | FNnoReloc | |
181 | ||
182 | .ts__image dcd ts__wSize+ts__wSpace-ts__image-4 | |
183 | b ts_init | |
184 | b ts_opened | |
185 | b ts_closed | |
186 | b ts_switch | |
187 | b ts_unload | |
188 | ||
189 | ;----- Initialisation ------------------------------------------------------- | |
190 | ||
191 | ; --- ts_init --- | |
192 | ; | |
193 | ; On entry; -- | |
194 | ; | |
195 | ; On exit; -- | |
196 | ; | |
197 | ; Use; Initialises the TearSupport system. | |
198 | ||
199 | .ts_init stmfd r13!,{r0-r2,r14} ;Stack link register nicely | |
200 | FNadrl (r12,ts__wSpace) ;Find workspace address | |
201 | mov r0,#0 ;A nice 0 value | |
202 | str r0,[r12,#ts_useCount] ;Stuff it in the usage count | |
203 | str r0,[r12,#ts_owner] ;No task using me yet | |
204 | strb r0,[r12,#ts_swiCaught] ;Remember we're not on SWIV | |
205 | ||
206 | mov r0,#ChangeEnvV ;Trap OS_ChangeEnvironment | |
207 | adr r1,ts_changeEnv ;Point to my handler | |
208 | mov r2,r12 ;Pass my workspace pointer | |
209 | swi "XOS_Claim" ;Claim the vector nicely | |
210 | ||
211 | ; --- Read the OS version --- | |
212 | ||
213 | mov r0,#129 ;Load the OS version number | |
214 | mov r1,#0 ;Set up OS_Byte arguments | |
215 | mov r2,#255 ;For most obscure OS call | |
216 | swi "OS_Byte" ;Read the version number | |
217 | strb r1,[r12,#ts_osVersion] ;Save this away for later | |
218 | ||
219 | ; --- I think that's it --- | |
220 | ||
221 | ldmfd r13!,{r0-r2,pc}^ ;Return to caller happy | |
222 | ||
223 | FNltorg | |
224 | ||
225 | ; --- ts_unload --- | |
226 | ; | |
227 | ; On entry; -- | |
228 | ; | |
229 | ; On exit; V clear if unloaded OK, otherwise V set | |
230 | ; | |
231 | ; Use; Attempts to remove TearSupt from memory, to replace it with | |
232 | ; a later version. If we can't close down, because we're in | |
233 | ; use, we return an error. | |
234 | ||
235 | .ts_unload bic r14,r14,#&10000000 ;Clear the V flag | |
236 | stmfd r13!,{r0-r2,r14} ;Save some registers | |
237 | FNadrl (r12,ts__wSpace) ;Find the workspace address | |
238 | ||
239 | ; --- Free all the vectors --- | |
240 | ||
241 | mov r0,#ChangeEnvV ;Trap OS_ChangeEnvironment | |
242 | adr r1,ts_changeEnv ;Point to my handler | |
243 | mov r2,r12 ;Pass my workspace pointer | |
244 | swi "XOS_Release" ;Let go of that | |
245 | ||
246 | bl ts_closed ;Pretend the transient closed | |
247 | ||
248 | ; --- Deallocate my memory --- | |
249 | ; | |
250 | ; This is a bit tricky, because I'm in it. I have to | |
251 | ; copy a bit of myself onto the stack, and call that. Yuk. | |
252 | ||
253 | adr r14,ts__return ;Point to return code | |
254 | ldmia r14,{r0-r2} ;Load the code out | |
255 | stmfd r13!,{r0-r2} ;Save it onto the stack | |
256 | ||
257 | adr r2,ts__image+4 ;Point to the block base | |
258 | mov r0,#7 ;Deallocate an RMA block | |
259 | mov pc,r13 ;Call return code | |
260 | ||
261 | .ts__return swi "OS_Module" ;Deallocate the memory | |
262 | add r13,r13,#12 ;Point to stack frame | |
263 | ldmfd r13!,{r0-r2,pc}^ ;Return without mishap | |
264 | ||
265 | FNltorg | |
266 | ||
267 | ; --- Vector numbers --- | |
268 | ] | |
269 | MouseV = &1A | |
270 | InsV = &14 | |
271 | ChangeEnvV = &1E | |
272 | [ opt o | |
273 | ||
274 | ; --- ts_opened --- | |
275 | ; | |
276 | ; On entry; R0 == task handle attempting to open tearoff transient | |
277 | ; | |
278 | ; On exit; -- | |
279 | ; | |
280 | ; Use; Informs the TearSupt system that a task is opening a | |
281 | ; transient tearoff menu. | |
282 | ||
283 | ||
284 | .ts_opened stmfd r13!,{r0-r2,r11,r12,r14} | |
285 | mov r11,r0 ;Look after the task handle | |
286 | FNadrl (r12,ts__wSpace) ;Find my workspace address | |
287 | ||
288 | ; --- Make sure we need to do this --- | |
289 | ||
290 | ldr r0,[r12,#ts_useCount] ;Get the counter | |
291 | cmp r0,#0 ;Am I currently running? | |
292 | bne ts_opened00 ;Yes -- skip this little bit | |
293 | ||
294 | ; --- Claim event vector --- | |
295 | ||
296 | swi "XOS_Mouse" ;Get the current mouse pos | |
297 | str r2,[r12,#ts_mouseState] ;Store it in workspace | |
298 | ||
299 | mov r0,#MouseV ;Vector number | |
300 | adr r1,ts_mouse ;Point to event handler | |
301 | mov r2,r12 ;Point to workspace | |
302 | swi "XOS_Claim" ;Try it and see | |
303 | ||
304 | mov r0,#InsV ;Vector number | |
305 | adr r1,ts_insert ;Point to event handler | |
306 | mov r2,r12 ;Point to workspace | |
307 | swi "XOS_Claim" ;Try it and see | |
308 | ||
309 | addvs r13,r13,#4 | |
310 | ldmvsfd r13!,{r1,r2,r11,r12,pc} ;Can't see this failing, but | |
311 | ||
312 | bl ts_swiClaim | |
313 | ||
314 | ; --- Update my tables and leave --- | |
315 | ||
316 | .ts_opened00 ldr r0,[r12,#ts_owner] ;Who's using me at the mo? | |
317 | cmp r0,r11 ;Is it someone else? | |
318 | cmpne r0,#0 ;Make sure s'not a ghost | |
319 | blne ts_escape_cb ;Tell the appl to close | |
320 | str r11,[r12,#ts_owner] ;Store the new handle | |
321 | ||
322 | ldr r0,[r12,#ts_useCount] ;Find my usage counter | |
323 | add r0,r0,#1 ;Bump it | |
324 | str r0,[r12,#ts_useCount] ;And store it back for later | |
325 | ||
326 | ldmfd r13!,{r0-r2,r11,r12,pc}^ | |
327 | ||
328 | FNltorg | |
329 | ||
330 | ; --- ts_closed --- | |
331 | ; | |
332 | ; On entry; -- | |
333 | ; | |
334 | ; On exit; -- | |
335 | ; | |
336 | ; Use; Informs TearSupt that the transient tearoff has been closed. | |
337 | ; If no transient is open, no action is performed. | |
338 | ||
339 | .ts_closed stmfd r13!,{r12,r14} ;Save some registers | |
340 | adr r12,ts__wSpace ;Find my workspace address | |
341 | ldr r14,[r12,#ts_useCount] ;Find out my counter thing | |
342 | cmp r14,#0 ;Is it zero? | |
343 | ldmeqfd r13!,{r12,pc}^ ;Someone's being silly | |
344 | subs r14,r14,#1 ;Decrement the counter | |
345 | str r14,[r12,#ts_useCount] ;Store for later | |
346 | ldmnefd r13!,{r12,pc}^ ;Return if still nonzero | |
347 | ||
348 | ; --- Remove handlers and things --- | |
349 | ||
350 | stmfd r13!,{r0-r2} ;Save some more registers | |
351 | bl ts_swiRelease ;Release SWI vector patch | |
352 | ||
353 | mov r0,#InsV ;Vector number | |
354 | adr r1,ts_insert ;Point to handler code | |
355 | mov r2,r12 ;Point to workspace | |
356 | swi "XOS_Release" ;Let go of the vector | |
357 | ||
358 | mov r0,#MouseV ;Vector number | |
359 | adr r1,ts_mouse ;Point to handler code | |
360 | mov r2,r12 ;Point to workspace | |
361 | swi "XOS_Release" ;Let go of the vector | |
362 | ||
363 | ldmfd r13!,{r0-r2,r12,pc}^ ;Return to caller | |
364 | ||
365 | FNltorg | |
366 | ||
367 | ; --- ts_switch --- | |
368 | ; | |
369 | ; On entry; R0 == 1 to suspend trapping, 0 to unsuspend | |
370 | ; | |
371 | ; On exit; -- | |
372 | ; | |
373 | ; Use; Enables or disables trapping of Wimp_CreateMenu, to enable | |
374 | ; TMS implementations to close Wimp menus where necessary. | |
375 | ||
376 | .ts_switch stmfd r13!,{r12,r14} ;Save some registers | |
377 | adr r12,ts__wSpace ;Find my workspace | |
378 | strb r0,[r12,#ts_swiThreaded] ;Disable the SWI patch | |
379 | ldmfd r13!,{r12,pc}^ ;And return to caller | |
380 | ||
381 | FNltorg | |
382 | ||
383 | ;----- The handlers and callbacks ------------------------------------------- | |
384 | ||
385 | ; --- ts_changeEnv --- | |
386 | ; | |
387 | ; On entry; As for OS_ChangeEnvironment | |
388 | ; | |
389 | ; On exit; R0 == address of TearSupt, if R0 == -1 on entry | |
390 | ; | |
391 | ; Use; Traps odd calls to OS_ChangeEnvironment to allow TearSupt | |
392 | ; to be located. | |
393 | ||
394 | .ts_changeEnv cmn r0,#1 ;Is it our special env code? | |
395 | adreq r1,ts__image+4 ;Yes -- return ptr to base | |
396 | moveq r2,#ts_version ;And get the version number | |
397 | ldmeqfd r13!,{pc}^ ;And claim the vector | |
398 | movs pc,r14 ;Otherwise pass on vector | |
399 | ||
400 | ; --- ts_insert --- | |
401 | ; | |
402 | ; On entry; R0 == byte inserted into buffer | |
403 | ; R1 == buffer number | |
404 | ; | |
405 | ; On exit; -- | |
406 | ; | |
407 | ; Use; Inspects all insertions into buffers, and traps attempts | |
408 | ; to insert escape keypresses, converting these to requests | |
409 | ; to close the current transient tearoff. | |
410 | ||
411 | .ts_insert cmp r0,#27 ;Make sure it's an escape | |
412 | cmpeq r1,#0 ;And it's from the keyboard | |
413 | movnes pc,r14 ;If not, give up and leave | |
414 | stmfd r13!,{r14} ;Save a register | |
415 | ldr r14,[r12,#ts_owner] ;Get my owner's ID | |
416 | cmn r14,#1 ;Is it valid? | |
417 | ldmeqfd r13!,{pc}^ ;No -- then return to caller | |
418 | ||
419 | ; --- Mess about with the processor status --- | |
420 | ||
421 | stmfd r13!,{r0,r1,r8} ;Store registers away | |
422 | mov r8,pc ;Get PC with PSR | |
423 | teqp pc,#3 ;Enter SVC mode | |
424 | mov r0,r0 ;Avoid contention of R13/R14 | |
425 | stmfd r13!,{r14} ;Stack return address | |
426 | adr r0,ts_escape_cb ;Point to callback routine | |
427 | mov r1,r12 ;Point to workspace | |
428 | swi "XOS_AddCallBack" ;Add the callback routine | |
429 | ldmfd r13!,{r14} ;Restore R14_svc | |
430 | teqp r8,#0 ;Restore old PSR values | |
431 | mov r0,r0 ;No-op to keep ARM happy | |
432 | ldmfd r13!,{r0,r1,r8,pc}^ ;Return to caller | |
433 | ||
434 | FNltorg | |
435 | ||
436 | ; --- ts_mouse --- | |
437 | ; | |
438 | ; On entry; -- | |
439 | ; | |
440 | ; On exit; -- | |
441 | ; | |
442 | ; Use; Inspects all mouse positions returned by OS_Mouse, and sends | |
443 | ; them to the current transient owner. | |
444 | ||
445 | .ts_mouse stmfd r13!,{r10-r12,r14} ;Stack some registers | |
446 | ||
447 | ; --- Pass on the vector, leaving ourself on the stack --- | |
448 | ; | |
449 | ; Modified from Acorn's code to avoid dependency on | |
450 | ; possibly non-compatible PC+12 behaviour. | |
451 | ||
452 | mov r14,pc ;Get current program counter | |
453 | add r14,r14,#12 ;Point at our processing code | |
454 | stmfd r13!,{r14} ;Make us get called back | |
455 | add r12,r13,#4 ;Point to saved R10 on stack | |
456 | ldmia r12,{r10-r12,pc} ;Call next routine on vector | |
457 | ||
458 | ; --- The vector has now completed nicely --- | |
459 | ||
460 | ldr r12,[r13,#8] ;Get my stacked r12 | |
461 | ||
462 | stmfd r13!,{r0-r3} ;Stack some registers for me | |
463 | ldr r0,[r12,#ts_mouseState] ;Get old mouse state | |
464 | str r2,[r12,#ts_mouseState] ;Store as the old state | |
465 | bics r2,r2,r0 ;Find out what changed | |
466 | ldmeqfd r13!,{r0-r3,r10-r12,r14,pc} ;If nothing then return | |
467 | ||
468 | ; --- A button was clicked -- tell our client --- | |
469 | ||
470 | add r1,r12,#ts_message+20 ;Point to message buffer | |
471 | swi "XWimp_GetPointerInfo" ;Get pointer info | |
472 | sub r1,r1,#20 ;Point to base of message | |
473 | mov r0,#40 ;Length of message | |
474 | str r0,[r1,#0] ;Store in message block | |
475 | mov r0,#0 ;This isn't a reply | |
476 | str r0,[r1,#12] ;So zero the your_ref | |
477 | ldr r0,FNlitw(&4A340) ;The magic message number | |
478 | str r0,[r1,#16] ;Fill it in | |
479 | mov r0,#17 ;Don't want it bouncing | |
480 | ldr r2,[r12,#ts_owner] ;Find my owner application | |
481 | swi "XWimp_SendMessage" ;Send it the message | |
482 | ||
483 | ldmfd r13!,{r0-r3,r10-r12,r14,pc} ;We're a happy bunny | |
484 | ||
485 | FNltorg | |
486 | ||
487 | ; --- ts_escape_cb --- | |
488 | ; | |
489 | ; On entry; -- | |
490 | ; | |
491 | ; On exit; -- | |
492 | ; | |
493 | ; Use; Sends a message to the transient tearoff owner, to tell | |
494 | ; it to close the transient. This is usually as a result of | |
495 | ; the user pressing escape or another task calling | |
496 | ; Wimp_CreateMenu. | |
497 | ||
498 | .ts_escape_cb stmfd r13!,{r0-r3,r14} ;Save some registers | |
499 | add r1,r12,#ts_message ;Point to message buffer | |
500 | mov r0,#20 ;Length of message | |
501 | str r0,[r1,#0] ;Store in message block | |
502 | mov r0,#0 ;This isn't a reply | |
503 | str r0,[r1,#12] ;So zero the your_ref | |
504 | ldr r0,FNlitw(&4A341) ;The magic message number | |
505 | str r0,[r1,#16] ;Fill it in | |
506 | mov r0,#17 ;Don't want it bouncing | |
507 | ldr r2,[r12,#ts_owner] ;Find my owner application | |
508 | swi "XWimp_SendMessage" ;Send it the message | |
509 | mvn r0,#0 ;Stop it happening again | |
510 | str r0,[r12,#ts_owner] ;Won't happen now! | |
511 | ldmfd r13!,{r0-r3,pc}^ ;Don't worry. Be happy. | |
512 | ||
513 | FNltorg | |
514 | ||
515 | ;----- SWI vector handling -------------------------------------------------- | |
516 | ; | |
517 | ; Warning; this section contains some really heavy stuff. If you're nervous, | |
518 | ; you may wish to seek medical advice before looking at this code. We can't | |
519 | ; accept any responsibility for any loss or disability incurred as a result | |
520 | ; of reading this source. | |
521 | ||
522 | ; --- ts_swiClaim --- | |
523 | ; | |
524 | ; On entry; -- | |
525 | ; | |
526 | ; On exit; -- | |
527 | ; | |
528 | ; Use; Sets up the SWI vector patch. | |
529 | ||
530 | .ts_swiClaim stmfd r13!,{r0-r3,r14} ;Stack some registers | |
531 | ldrb r0,[r12,#ts_swiCaught] ;Have we done it already? | |
532 | cmp r0,#0 ;Just check | |
533 | ldmnefd r13!,{r0-r3,pc}^ ;If so, just carry on | |
534 | ||
535 | ldrb r14,[r12,#ts_osVersion] ;Get the OS version | |
536 | cmp r14,#&a5 ;Is this a RISC PC? | |
537 | bcs ts_swiClaim50 ;Yes -- do special things | |
538 | ||
539 | mov r0,#0 ;Point to hardware vectors | |
540 | ldr r1,[r0,#&08] ;Get the SWIV instruction | |
541 | str r1,[r12,#ts_oldSWIinstr] ;Remember this instruction | |
542 | and r2,r1,#&0F000000 ;Get the basic instruction | |
543 | cmp r2,#&0A000000 ;Is it a branch? | |
544 | beq ts_swiClaim00 ;Yes -- handle that | |
545 | ||
546 | ; --- Mangle an LDR PC,[PC,#...] --- | |
547 | ||
548 | ldr r2,FNlitw(&FFF) ;Mask off LDR bits | |
549 | and r2,r1,r2 ;Get the offset of LDR | |
550 | tst r1,#1<<23 ;Check the sign bit | |
551 | addne r3,r2,#&10 ;If additive, then add offset | |
552 | rsbeq r3,r2,#&10 ;If subtractive, subtract ;-) | |
553 | str r3,[r12,#ts_oldSWIaddr] ;Store this address away | |
554 | b ts_swiClaim01 ;Now insert our branch code | |
555 | ||
556 | ; --- Mangle a B ... --- | |
557 | ||
558 | .ts_swiClaim00 bic r2,r1,#&FF000000 ;Clear instruction bits | |
559 | add r2,r2,#4 ;Take pipeline into account | |
560 | mov r2,r2,lsl #2 ;Word align the result | |
561 | bic r2,r2,#&FC000003 ;Turn it into a real address | |
562 | str r2,[r12,#ts_dummySWIptr] ;Store this in our pointer | |
563 | add r3,r12,#ts_dummySWIptr ;Point to this pointer | |
564 | str r3,[r12,#ts_oldSWIaddr] ;Store *this* address away | |
565 | ||
566 | ; --- Now insert our own instruction --- | |
567 | ||
568 | .ts_swiClaim01 adr r1,ts_swiClaimer ;Point to the routine | |
569 | mov r1,r1,lsr #2 ;Shift off bottom zero bits | |
570 | sub r1,r1,#4 ;Adjust the address of branch | |
571 | orr r1,r1,#&EA000000 ;Make it a branch instr | |
572 | str r1,[r12,#ts_newSWIinstr] ;Store this new instruction | |
573 | swi "OS_EnterOS" ;We're messing with SWI vect | |
574 | str r1,[r0,#8] ;This is now the SWI vector | |
575 | teqp pc,#0 ;Back to user mode | |
576 | mov r0,r0 ;No-op for strange reasons | |
577 | mov r0,#1 ;We've now patched SWIV | |
578 | strb r0,[r12,#ts_swiCaught] ;So remember this | |
579 | mov r0,#0 ;Not yet threaded, though | |
580 | strb r0,[r12,#ts_swiThreaded] | |
581 | ldmfd r13!,{r0-r3,pc}^ ;Return to caller | |
582 | ||
583 | ; --- We have an OS call to do this --- | |
584 | ||
585 | .ts_swiClaim50 mov r0,#2 ;Claim SWI vector | |
586 | orr r0,r0,#256 ;Set the `claim' flag | |
587 | adr r1,ts_swi610 ;Point to handler routine | |
588 | swi "XOS_IntOff" ;Stop all SWIs for a bit | |
589 | swi XOS_ClaimProcessorVector | |
590 | str r1,[r12,#ts_dummySWIptr] ;Save old handler address | |
591 | add r3,r12,#ts_dummySWIptr ;Point to this pointer | |
592 | str r3,[r12,#ts_oldSWIaddr] ;And store *this* address | |
593 | swi "XOS_IntOn" ;We can handle SWIs again now | |
594 | ||
595 | mov r0,#1 ;We've now patched SWIV | |
596 | strb r0,[r12,#ts_swiCaught] ;So remember this | |
597 | mov r0,#0 ;Not yet threaded, though | |
598 | strb r0,[r12,#ts_swiThreaded] | |
599 | ||
600 | ldmfd r13!,{r0-r3,pc}^ ;Return to caller | |
601 | ||
602 | FNltorg | |
603 | ||
604 | ; --- ts_swiRelease --- | |
605 | ; | |
606 | ; On entry; -- | |
607 | ; | |
608 | ; On exit; CS if patch removed OK, else CC | |
609 | ; | |
610 | ; Use; Attempts to remove the SWI vector patch. If this can't be | |
611 | ; done, then the patch is left in. | |
612 | ||
613 | .ts_swiRelease stmfd r13!,{r0-r2,r14} ;Stack registers | |
614 | ldrb r0,[r12,#ts_swiCaught] ;Is the vector trapped? | |
615 | cmp r0,#0 ;Quick check... | |
616 | ldmeqfd r13!,{r0-r2,pc}^ ;No -- return then | |
617 | ||
618 | ; --- Check if this is a RISC PC --- | |
619 | ||
620 | ldrb r0,[r12,#ts_osVersion] ;Load the OS version | |
621 | cmp r0,#&a5 ;Is this a RISC PC | |
622 | bcs ts_swiRel50 ;Yes -- do different things | |
623 | ||
624 | mov r0,#0 ;Point to hardware vectors | |
625 | ldr r1,[r0,#8] ;Get SWI vector instruction | |
626 | ldr r2,[r12,#ts_newSWIinstr] ;Get our one | |
627 | cmp r1,r2 ;Are they the same? | |
628 | bne ts_swiRel90 ;No -- couldn't reset it | |
629 | ||
630 | ldr r1,[r12,#ts_oldSWIinstr] ;Get the old version then | |
631 | swi "OS_EnterOS" ;We're messing with SWI vect | |
632 | str r1,[r0,#8] ;Reinstate the old vector | |
633 | teqp pc,#0 ;Back to user mode | |
634 | mov r0,r0 ;Wait for things to settle | |
635 | strb r0,[r12,#ts_swiCaught] ;SWIV no longer patched | |
636 | ldmfd r13!,{r0-r2,r14} ;Return to caller | |
637 | orrs pc,r14,#1<<29 ;Setting C to say *YES* | |
638 | ||
639 | ; --- Release SWI vector using OS call --- | |
640 | ||
641 | .ts_swiRel50 mov r0,#2 ;Releasing the SWI vector | |
642 | ldr r1,[r12,#ts_dummySWIptr] ;Load address of old claimer | |
643 | adr r2,ts_swi610 ;Point to expected handler | |
644 | swi XOS_ClaimProcessorVector | |
645 | bvs ts_swiRel90 ;Error -- couldn't do it | |
646 | ||
647 | mov r14,#0 ;Clear claimed flag | |
648 | strb r14,[r12,#ts_swiCaught] ;SWIV no longer patched | |
649 | ldmfd r13!,{r0-r2,r14} ;Return to caller | |
650 | orrs pc,r14,#1<<29 ;Setting C to say *YES* | |
651 | ||
652 | ; --- Couldn't do it --- | |
653 | ||
654 | .ts_swiRel90 ldmfd r13!,{r0-r2,r14} ;Restore registers | |
655 | bics pc,r14,#1<<29 ;But clear C on exit | |
656 | ||
657 | FNltorg | |
658 | ||
659 | ; --- ts_swi610 --- | |
660 | ; | |
661 | ; On entry; R0-R8 == arguments to SWI | |
662 | ; R9-R12 == random values from the OS | |
663 | ; R13 == supervisor stack pointer | |
664 | ; R14 == return address from client | |
665 | ; | |
666 | ; On exit; R0-R8 == returned from SWI | |
667 | ; R9-R13 *AND SPSR_svc* preserved | |
668 | ; | |
669 | ; Use; Intercepts all SWI calls in the system, catching | |
670 | ; Wimp_CreateMenus and informing the transient owner of them. | |
671 | ||
672 | .ts_swi610 stmfd r13!,{r10-r12,r14,pc} ;Stack some registers | |
673 | ||
674 | ; --- Move into 26 bit mode --- | |
675 | ||
676 | dcd &e14fb000 ;mrs r11,spsr_all | |
677 | stmfd r13!,{r11} ;Save this on the stack | |
678 | and r12,r11,#&f0000003 ;Get the processor status | |
679 | orr r14,r14,r12 ;Add it to the R14 value | |
680 | and r12,r11,#&c0 ;Get the interrupt flags | |
681 | orr r14,r14,r12,lsl #20 ;Put them into R14 too | |
682 | dcd &e10fb000 ;mrs r11,cpsr_all | |
683 | bic r11,r11,#&1f ;Clear all the mode bits | |
684 | orr r11,r11,#&03 ;Set SVC_26 | |
685 | dcd &e129f00b ;msr cpsr_all,r11 | |
686 | ||
687 | ; --- Now find out about the SWI --- | |
688 | ||
689 | adr r12,ts__wSpace ;Point to workspace pointer | |
690 | ldrb r10,[r12,#ts_swiThreaded] ;Is this routine threaded? | |
691 | cmp r10,#0 ;Check now, or forever... | |
692 | bne ts_swi610_00 ;If so, skip onwards | |
693 | bic r10,r14,#&FC000003 ;Mask off saved PSR bits | |
694 | ldr r11,[r10,#-4] ;Get SWI instruction | |
695 | ldr r10,FNlitw(&FFF20000) ;Mask off silly SWI bits | |
696 | bic r11,r11,r10 ;Get the pure SWI number | |
697 | ldr r10,FNlitw(FNswiNum("Wimp_CreateMenu")) | |
698 | cmp r10,r11 ;See if it's interesting | |
699 | beq ts_swi610_10 ;Yes -- process it nicely | |
700 | ||
701 | .ts_swi610_00 ldmfd r13!,{r14} ;Load the saved SPSR | |
702 | dcd &e169f00e ;msr spsr_all,r14 | |
703 | ||
704 | ldr r14,[r12,#ts_oldSWIaddr] ;Point to old pointer | |
705 | ldr r14,[r14,#0] ;Dereference the pointer | |
706 | str r14,[r13,#16] ;Overwrite PC on the stack | |
707 | ldmfd r13!,{r10-r12,r14,pc} ;Pass on to real SWI routine | |
708 | ||
709 | ; --- Wimp_CreateMenu handling --- | |
710 | ||
711 | .ts_swi610_10 mov r10,#1 ;Set the threaded flag | |
712 | strb r10,[r12,#ts_swiThreaded] ;Remember we're in here | |
713 | ||
714 | bl ts_escape_cb ;Send out the close message | |
715 | ||
716 | .ts_swi610_01 mov r10,#0 ;Not threaded any more | |
717 | strb r10,[r12,#ts_swiThreaded] ;Store this for others | |
718 | b ts_swi610_00 ;And continue main thread | |
719 | ||
720 | FNltorg | |
721 | ||
722 | ; --- ts_swiClaimer --- | |
723 | ; | |
724 | ; On entry; R0-R8 == arguments to SWI | |
725 | ; R9-R12 == random values from the OS | |
726 | ; R13 == supervisor stack pointer | |
727 | ; R14 == return address from client | |
728 | ; | |
729 | ; On exit; R0-R8 == returned from SWI | |
730 | ; R9-R13 preserved | |
731 | ; | |
732 | ; Use; Intercepts all SWI calls in the system, catching | |
733 | ; Wimp_CreateMenus and informing the transient owner of them. | |
734 | ||
735 | .ts_swiClaimer stmfd r13!,{r10-r12,r14,pc} ;Stack some registers | |
736 | adr r12,ts__wSpace ;Point to workspace pointer | |
737 | ldrb r10,[r12,#ts_swiThreaded] ;Is this routine threaded? | |
738 | cmp r10,#0 ;Check now, or forever... | |
739 | bne ts_swiClaimer00 ;If so, skip onwards | |
740 | bic r10,r14,#&FC000003 ;Mask off saved PSR bits | |
741 | ldr r11,[r10,#-4] ;Get SWI instruction | |
742 | ldr r10,FNlitw(&FFF20000) ;Mask off silly SWI bits | |
743 | bic r11,r11,r10 ;Get the pure SWI number | |
744 | ldr r10,FNlitw(FNswiNum("Wimp_CreateMenu")) | |
745 | cmp r10,r11 ;See if it's interesting | |
746 | beq ts_swiClaimer10 ;Yes -- process it nicely | |
747 | ||
748 | .ts_swiClaimer00 | |
749 | ldr r14,[r12,#ts_oldSWIaddr] ;Point to old pointer | |
750 | ldr r14,[r14,#0] ;Dereference the pointer | |
751 | str r14,[r13,#16] ;Overwrite PC on the stack | |
752 | ldmfd r13!,{r10-r12,r14,pc} ;Pass on to real SWI routine | |
753 | ||
754 | ; --- Wimp_CreateMenu handling --- | |
755 | ||
756 | .ts_swiClaimer10 | |
757 | mov r10,#1 ;Set the threaded flag | |
758 | strb r10,[r12,#ts_swiThreaded] ;Remember we're in here | |
759 | ||
760 | bl ts_escape_cb ;Send out the close message | |
761 | ||
762 | .ts_swiClaimer01 | |
763 | mov r10,#0 ;Not threaded any more | |
764 | strb r10,[r12,#ts_swiThreaded] ;Store this for others | |
765 | b ts_swiClaimer00 ;And continue main thread | |
766 | ||
767 | FNltorg | |
768 | ||
769 | .ts__wSpace | |
770 | .ts__imageEnd | |
771 | ] | |
772 | ||
773 | PROCws_start | |
774 | ts_useCount =FNws_word | |
775 | ts_owner =FNws_word | |
776 | ts_mouseState =FNws_word | |
777 | ts_newMouse =FNws_word | |
778 | ts_oldSWIaddr =FNws_word | |
779 | ts_dummySWIptr =FNws_word | |
780 | ts_oldSWIinstr =FNws_word | |
781 | ts_newSWIinstr =FNws_word | |
782 | ts_swiCaught =FNws_byte | |
783 | ts_swiThreaded =FNws_byte | |
784 | ts_osVersion =FNws_byte | |
785 | PROCws_align | |
786 | ts_message =FNws (40) | |
787 | ts__wSize =FNws (0) | |
788 | ||
789 | NEXT | |
790 | ||
791 | PRINT '"Encrypting..."; | |
792 | ||
793 | REM --- Encrypt the RMA resident section --- | |
794 | ||
795 | iv%=&1b9a7f83 | |
796 | FOR i%=ts__image+4 TO ts__imageEnd STEP 4 | |
797 | x%=i%!(O%-P%) EOR iv% | |
798 | x%=(x%>>>8) OR (x%<<24) | |
799 | i%!(O%-P%)=x% | |
800 | iv%=x% | |
801 | NEXT | |
802 | ||
803 | PRINT '"Saving..."; | |
804 | PROCbas_aofSave | |
805 | PRINT '"Done" | |
806 | END | |
807 | ||
808 | DEF FNswiNum(swi$) | |
809 | LOCAL swin% | |
810 | SYS "OS_SWINumberFromString",,swi$ TO swin% | |
811 | =swin% | |
812 |