Commit | Line | Data |
---|---|---|
c1b567d8 MW |
1 | REM |
2 | REM swiList.bs | |
3 | REM | |
4 | REM Build SWI name include files | |
5 | REM | |
6 | REM © 1995 Straylight | |
7 | REM | |
8 | ||
9 | REM -- Standard header ------------------------------------------------------ | |
10 | ||
11 | ON ERROR ERROR 0,"*** ERROR: "+REPORT$+" ["+STR$(ERL)+"]" | |
12 | ||
13 | LIBRARY "libs:BAS" | |
14 | PROCbas_init | |
15 | ||
16 | PROCbas_aofInit(&8000) | |
17 | ||
18 | V_flag=1<<28 | |
19 | C_flag=1<<29 | |
20 | ||
21 | FOR o=4 TO 6 STEP 2 | |
22 | ||
23 | [ opt o | |
24 | FNpass | |
25 | ||
26 | ;----- Revision history ----------------------------------------------------- | |
27 | ; | |
28 | ; Version By Change | |
29 | ; | |
30 | ; 1.xx MDW Old version written in C using STEEL. | |
31 | ; | |
32 | ; 2.00 MDW Rewrite from scratch in assembler using Sapphire. | |
33 | ; Keep SWI names in flex block, allow user format | |
34 | ; files, and add SWIs from modules dropped onto icon. | |
35 | ; | |
36 | ; 2.01 MDW Replaced format file loading with a chunk file, to | |
37 | ; support multiple programming languages. Added | |
38 | ; submenu to `Save list' for selecting which language | |
39 | ; to use. | |
40 | ; | |
41 | ; 2.02 MDW Added %d format specifier to output generation time/ | |
42 | ; date in given style. Also added revision history ;-) | |
43 | ; | |
44 | ; 2.03 MDW Added confirm on quit option, and prevented saving | |
45 | ; a dump from SWIList back into itself. | |
46 | ; | |
47 | ; 2.04 MDW Tidied up initialisation a little, and made it | |
48 | ; register the heap routines as allocators for smaller | |
49 | ; WimpSlot. | |
50 | ; | |
51 | ; 2.05 MDW Fiddled help message generation a little to (a) | |
52 | ; do message translation of the format names and (b) | |
53 | ; use %0 rather than the less pretty %9 in the help | |
54 | ; skeleton. | |
55 | ; | |
56 | ; 2.06 MDW Added full pathname for dump save, so you don't have | |
57 | ; to dig up the application to save the dump each time. | |
58 | ; | |
59 | ; 2.07 MDW Used SEH for error handling, instead of raw except- | |
60 | ; level stuff. | |
61 | ||
62 | ;----- External dependencies ------------------------------------------------ | |
63 | ||
64 | ; --- Sapphire library --- | |
65 | ||
66 | FNget ("sapphire:alloc") | |
67 | FNget ("sapphire:buttons") | |
68 | FNget ("sapphire:chunk") | |
69 | FNget ("sapphire:defHandler") | |
70 | FNget ("sapphire:errorBox") | |
71 | FNget ("sapphire:event") | |
72 | FNget ("sapphire:fastMove") | |
73 | FNget ("sapphire:flex") | |
74 | FNget ("sapphire:heap") | |
75 | FNget ("sapphire:help") | |
76 | FNget ("sapphire:hour") | |
77 | FNget ("sapphire:ibicon") | |
78 | FNget ("sapphire:libOpts") | |
79 | FNget ("sapphire:menu") | |
80 | FNget ("sapphire:menuDefs") | |
81 | FNget ("sapphire:msgs") | |
82 | FNget ("sapphire:note") | |
83 | FNget ("sapphire:progInfo") | |
84 | FNget ("sapphire:ptr") | |
85 | FNget ("sapphire:report") | |
86 | FNget ("sapphire:res") | |
87 | FNget ("sapphire:resources") | |
88 | FNget ("sapphire:sapphire") | |
89 | FNget ("sapphire:seh") | |
90 | FNget ("sapphire:string") | |
91 | FNget ("sapphire:warning") | |
92 | ||
93 | FNget ("sapphire:choices.choices") | |
94 | ||
95 | FNget ("sapphire:xfer.load") | |
96 | FNget ("sapphire:xfer.saveAs") | |
97 | FNget ("sapphire:xfer.save") | |
98 | FNget ("sapphire:xfer.xsave") | |
99 | ||
100 | ; --- Link-time generated strings --- | |
101 | ||
102 | FNimport("cright") | |
103 | FNimport("version") | |
104 | ||
105 | ;----- Initialisation ------------------------------------------------------- | |
106 | ||
107 | FNarea ("Client$$Code","CODE,READONLY") | |
108 | ||
109 | ; --- main --- | |
110 | ; | |
111 | ; On entry; -- | |
112 | ; | |
113 | ; On exit; Via OS_Exit | |
114 | ; | |
115 | ; Use; Allows saving of header files containing SWI name-number | |
116 | ; mappings. | |
117 | ||
118 | .main FNentry | |
119 | ||
120 | adr r0,FNlitsz("SWIList") ;Point to application name | |
121 | mov r1,#sl__wSize ;Get my workspace size | |
122 | mov r2,#0 ;Default stack size | |
123 | bl sapphire_init ;Start up the library | |
124 | bl sl__preInit ;Do pre-initialisation stuff | |
125 | bl sapphire_libInit ;Initialise rest of library | |
126 | bl sl__init ;Initialise me | |
127 | ||
128 | bl seh_throwErrors ;Make errors throw exceptions | |
129 | bl report_catchAll ;And catch exceptions | |
130 | ||
131 | .sl__pollLoop mov r0,#1 ;Don't have idle events | |
132 | add r1,r12,#sl__pollBlock ;Point to the poll block | |
133 | bl event_poll ;Handle an event | |
134 | blcc sl__unknowns ;Handle unknown events | |
135 | blcc defHandler ;Pass it on if unrecognised | |
136 | b sl__pollLoop ;And carry on round forever | |
137 | ||
138 | FNltorg | |
139 | ||
140 | ; --- sl__preInit --- | |
141 | ; | |
142 | ; On entry; -- | |
143 | ; | |
144 | ; On exit; R0-R10 corrupted | |
145 | ; | |
146 | ; Use; Does initialisation of things before the main Sapphire | |
147 | ; library awakes. | |
148 | ||
149 | .sl__preInit stmfd r13!,{r14} ;Save a register away | |
150 | bl resources_init ;Use shared resource DLL | |
151 | bl hour_init ;Wake up the hourglass system | |
152 | bl hour_on ;And turn it on | |
153 | ldr r0,[r11,#sapph_appName] ;Find the application name | |
154 | bl heap_init ;Initialise the resizing heap | |
155 | bl heap_useHeap ;Register it as an allocator | |
156 | adr r0,sl__sapphOpts ;Point to options block | |
157 | bl libOpts_register ;Register the options | |
158 | ldmfd r13!,{pc}^ ;Return to caller when done | |
159 | ||
160 | .sl__sapphOpts FNlibOpt("MENU") | |
161 | dcd 8192 | |
162 | FNlibOpts_end | |
163 | ||
164 | FNltorg | |
165 | ||
166 | ; --- sl__init --- | |
167 | ; | |
168 | ; On entry; -- | |
169 | ; | |
170 | ; On exit; -- | |
171 | ; | |
172 | ; Use; Initialises SWIList's workspace. | |
173 | ||
174 | .sl__init stmfd r13!,{r14} ;Save some registers | |
175 | bl sl__initWS ;Set up my workspace | |
176 | bl sl__loadFormat ;Load the user's format file | |
177 | bl sl__initList ;Create the SWI list | |
178 | bl sl__iconBar ;Create my icon | |
179 | bl sl__setFlags ;Finally set the flags up | |
180 | ldmfd r13!,{pc}^ ;And return to caller | |
181 | ||
182 | FNltorg | |
183 | ||
184 | ; --- sl__initWS --- | |
185 | ; | |
186 | ; On entry; -- | |
187 | ; | |
188 | ; On exit; R0-R10 corrupted | |
189 | ; | |
190 | ; Use; Initialises the application's workspace. | |
191 | ||
192 | .sl__initWS stmfd r13!,{r14} ;Save the link register | |
193 | mov r14,#0 ;Zero the anchor pointer | |
194 | str r14,[r12,#sl__flags] ;Clear the flags initially | |
195 | str r14,[r12,#sl__anchor] ;Say we have no block yet | |
196 | str r14,[r12,#sl__modNames] ;No module name table | |
197 | str r14,[r12,#sl__format] ;No format loaded yet | |
198 | ldmfd r13!,{pc}^ ;And return to caller | |
199 | ||
200 | FNltorg | |
201 | ||
202 | ; --- sl__loadFormat --- | |
203 | ; | |
204 | ; On entry; -- | |
205 | ; | |
206 | ; On exit; R0-R10 corrupted | |
207 | ; | |
208 | ; Use; Loads SWIList's format file. | |
209 | ||
210 | .sl__loadFormat stmfd r13!,{r14} ;Save the link register | |
211 | ||
212 | ; --- Enable the Choices support --- | |
213 | ||
214 | mov r0,#1 ;Enable `Choices' support | |
215 | bl choices_useChoices ;Allow read-only use nicely | |
216 | ||
217 | ; --- Create the format chunk file --- | |
218 | ||
219 | bl chunk_create ;Create a chunk file | |
220 | swivs "OS_GenerateError" ;Be unhappy if it fails | |
221 | str r0,[r12,#sl__format] ;Save this away | |
222 | ||
223 | ; --- Now do the actual load operation --- | |
224 | ||
225 | adr r0,FNlitsz("Format") ;Point to the leafname | |
226 | mov r1,r11 ;Build name in scratchpad | |
227 | mov r2,#0 ;I want to read the file | |
228 | bl choices_find ;Translate the name | |
229 | mov r1,r0 ;Point to the name | |
230 | sub r13,r13,#4 ;Make a flex anchor | |
231 | mov r2,r13 ;Point to this anchor | |
232 | bl load_file ;Load the file into it | |
233 | ldrvc r0,[r12,#sl__format] ;Find the format handle | |
234 | movvc r1,r13 ;And point to the anchor | |
235 | blvc chunk_read ;Add that to the chunks | |
236 | mov r0,r13 ;Point to that anchor again | |
237 | bl flex_free ;Get rid of the block | |
238 | add r13,r13,#4 ;And restore the stack | |
239 | ||
240 | ; --- Set flag if any format chunks found --- | |
241 | ||
242 | ldr r0,[r12,#sl__format] ;Find the format handle | |
243 | mov r1,#0 ;Start enumerating | |
244 | bl chunk_enum ;Are there any chunks? | |
245 | ldrcc r14,[r12,#sl__flags] ;Yes -- get the flags | |
246 | orrcc r14,r14,#slFlag__format ;Set the format flag | |
247 | strcc r14,[r12,#sl__flags] ;And save them back again | |
248 | ldmfd r13!,{pc}^ ;Return to caller when done | |
249 | ||
250 | FNltorg | |
251 | ||
252 | ; --- sl__initList --- | |
253 | ; | |
254 | ; On entry; -- | |
255 | ; | |
256 | ; On exit; R0-R10 corrupted | |
257 | ; | |
258 | ; Use; Initialises the SWI table, either by loading a saved dump | |
259 | ; or by scanning the modules in memory. | |
260 | ||
261 | .sl__initList stmfd r13!,{r14} ;Save the link register | |
262 | adr r0,FNlitsz("SWIDump") ;Point to the leafname | |
263 | mov r1,r11 ;Build name in scratchpad | |
264 | mov r2,#0 ;I want to read the file | |
265 | bl choices_find ;Translate the name | |
266 | mov r1,r0 ;Point to the name | |
267 | bl sl__loadDmp ;Load the default dump | |
268 | blvc sl__doneDmp ;If OK, set the rest up | |
269 | blvs sl__initBlock ;Otherwise, scan the modules | |
270 | ldmfd r13!,{pc}^ ;Return to caller when done | |
271 | ||
272 | FNltorg | |
273 | ||
274 | ; --- sl__iconBar --- | |
275 | ; | |
276 | ; On entry; -- | |
277 | ; | |
278 | ; On exit; -- | |
279 | ; | |
280 | ; Use; Sets up the icon bar icon. | |
281 | ||
282 | .sl__iconBar stmfd r13!,{r0-r6,r14} ;Save some registers | |
283 | adr r0,FNlitsz("!swilist") ;Point to sprite to use | |
284 | mov r1,#0 ;No text buffer here | |
285 | mvn r2,#NOT(-1) ;Put icon on the left | |
286 | mov r3,#0 ;Normal priority please | |
287 | adr r4,sl__ibEvents ;Point to event handler | |
288 | mov r5,#0 ;Pass no document handle | |
289 | mov r6,r12 ;Pass workspace pointer | |
290 | bl ibicon_create ;Create the icon nicely | |
291 | swivs "OS_GenerateError" ;If it failed, halt program | |
292 | ldmfd r13!,{r0-r6,pc}^ ;And return to caller | |
293 | ||
294 | FNltorg | |
295 | ||
296 | ; --- sl__ibEvents --- | |
297 | ; | |
298 | ; On entry; R0 == event code | |
299 | ; | |
300 | ; On exit; -- | |
301 | ; | |
302 | ; Use; Handles events for the icon bar icon. | |
303 | ||
304 | .sl__ibEvents cmp r0,#(sl__ibe10-sl__ibe00)/4 | |
305 | addcc pc,pc,r0,lsl #2 ;Dispatch through branch tbl | |
306 | movs pc,r14 ;Ignore unknown events | |
307 | ||
308 | .sl__ibe00 movs pc,r14 ;Ignore Select clicks | |
309 | b sl__ibMenu ;Handle a menu click | |
310 | movs pc,r14 ;Ignore Adjust clicks | |
311 | b sl__ibLoad ;Handle a load/save request | |
312 | b sl__ibLoad ;We treat them all the same | |
313 | b sl__ibHelp ;Handle a help request | |
314 | .sl__ibe10 | |
315 | ; --- Handle a menu click --- | |
316 | ||
317 | .sl__ibMenu stmfd r13!,{r0-r3,r14} ;Save some registers | |
318 | adr r0,sl__imDef ;Point to the menu definition | |
319 | adr r1,sl__imEvents ;Point to menu handler code | |
320 | mov r2,r10 ;Pass it the doc handle | |
321 | mov r3,r12 ;And my workspace address | |
322 | bl menu_create ;Display the menu nicely | |
323 | ldmfd r13!,{r0-r3,pc}^ ;And return to caller | |
324 | ||
325 | .sl__imDef FNmenu("SWIList") | |
326 | FNmenu_item("slINF") | |
327 | FNmenu_subWarn | |
328 | FNmenu_ruleOff | |
329 | FNmenu_item("slSVL") | |
330 | FNmenu_r12Data | |
331 | FNmenu_iShade(sl__flags,slFlag__savable) | |
332 | FNmenu_subWarn | |
333 | FNmenu_noWarn | |
334 | FNmenu_item("slSVD") | |
335 | FNmenu_r12Data | |
336 | FNmenu_iShade(sl__flags,slFlag__block) | |
337 | FNmenu_subWarn | |
338 | FNmenu_noWarn | |
339 | FNmenu_item("slSCN") | |
340 | FNmenu_item("slRFM") | |
341 | FNmenu_subWarn | |
342 | FNmenu_ruleOff | |
343 | FNmenu_item("slQUT") | |
344 | FNmenu_end | |
345 | ||
346 | ; --- Handle a help request --- | |
347 | ||
348 | .sl__ibHelp stmfd r13!,{r0,r14} ;Save some registers | |
349 | adr r0,FNlitsz("slhIB") ;Point to a message tag | |
350 | bl msgs_lookup ;Translate the tag | |
351 | bl help_add ;And add it to the help | |
352 | ldmfd r13!,{r0,pc}^ ;Return to caller | |
353 | ||
354 | ; --- Handle a load event --- | |
355 | ||
356 | .sl__ibLoad stmfd r13!,{r0-r2,r14} ;Save some registers | |
357 | bl event_last ;Find the last event | |
358 | ldr r0,[r1,#40] ;Load the filetype | |
359 | ldr r14,FNlitw(&FFA) ;Get the module filetype | |
360 | cmp r0,r14 ;Do these match | |
361 | beq sl__ibLdMod ;Yes -- handle that then | |
362 | ldr r14,FNlitw(&FFD) ;Get the data filetype | |
363 | cmp r0,r14 ;Do these match | |
364 | beq sl__ibLdDump ;Yes -- handle that then | |
365 | ldmfd r13!,{r0-r2,pc}^ ;Return to caller | |
366 | ||
367 | ; --- Handle loading a module --- | |
368 | ||
369 | .sl__ibLdMod adr r0,sl__lMod ;Point to load block | |
370 | mov r1,r10 ;Get document handle | |
371 | mov r2,r12 ;And workspace address | |
372 | bl load ;Do the load operation | |
373 | ldmfd r13!,{r0-r2,pc}^ ;And return when done | |
374 | ||
375 | .sl__lMod b sl__ibMod | |
376 | b load_killBuf | |
377 | b load_extendBuf | |
378 | b load_doneBuf | |
379 | b sl__loadMod | |
380 | b sl__doneMod | |
381 | b sl__lfMod | |
382 | ||
383 | ; --- Handle loading a dump --- | |
384 | ||
385 | .sl__ibLdDump ldr r14,[r12,#sl__flags] ;Load the flags word | |
386 | tst r14,#slFlag__saving ;Are we saving currently? | |
387 | bne sl__ild50 ;Yes -- moan at user then | |
388 | ||
389 | adr r0,sl__lDmp ;Point to load block | |
390 | mov r1,r10 ;Get document handle | |
391 | mov r2,r12 ;And workspace address | |
392 | bl load ;Yes -- start a load op | |
393 | ldmfd r13!,{r0-r2,pc}^ ;And return to caller | |
394 | ||
395 | .sl__ild50 adr r0,FNliterr(1,"slCSII") ;Point to error block | |
396 | bl msgs_error ;Translate the message | |
397 | mov r1,#1 ;Only display OK button | |
398 | bl errorBox ;Display the error | |
399 | ldmfd r13!,{r0-r2,pc}^ ;And return to caller | |
400 | ||
401 | .sl__lDmp b sl__ibDmp | |
402 | b load_killBuf | |
403 | b load_extendBuf | |
404 | b load_doneBuf | |
405 | b sl__loadDmp | |
406 | b sl__doneDmp | |
407 | b sl__lfDmp | |
408 | ||
409 | FNltorg | |
410 | ||
411 | ; --- sl__imEvents --- | |
412 | ; | |
413 | ; On entry; R0 == event code | |
414 | ; R1 == item number | |
415 | ; | |
416 | ; On exit; -- | |
417 | ; | |
418 | ; Use; Handles events from the icon bar menu. | |
419 | ||
420 | .sl__imEvents cmp r0,#mEvent_help ;A help request, perchance? | |
421 | beq sl__imHelp ;Yes -- deliver help on it | |
422 | cmp r0,#mEvent_select ;Is this a select event? | |
423 | cmpne r0,#mEvent_subMenu ;Or a submenu opening? | |
424 | movnes pc,r14 ;No -- ignore the event | |
425 | ||
426 | cmp r1,#(sl__ime10-sl__ime00)/4 | |
427 | addcc pc,pc,r1,lsl #2 ;Dispatch by item number | |
428 | movs pc,r14 ;Ignore unknown item numbers | |
429 | ||
430 | .sl__ime00 b sl__imInfo ;Display the info box | |
431 | b sl__imSave ;Save the SWI list | |
432 | b sl__imDump ;Save a SWI dump | |
433 | b sl__initBlock ;Reset the block | |
434 | b sl__imRefresh ;Refresh a particular module | |
435 | b sl__imQuit ;Close down the program | |
436 | .sl__ime10 | |
437 | ||
438 | ; --- Send a help message --- | |
439 | ||
440 | .sl__imHelp stmfd r13!,{r0,r14} ;Save some registers | |
441 | adr r0,FNlitsz("slhIM") ;Find the message base tag | |
442 | bl menu_help ;Give help on the item | |
443 | ldmfd r13!,{r0,pc}^ ;And return to caller | |
444 | ||
445 | ; --- Display the info window --- | |
446 | ||
447 | .sl__imInfo stmfd r13!,{r0-r2,r14} ;Save some registers | |
448 | adr r0,FNlitsz("slPUR") ;Point to purpose message | |
449 | bl msgs_lookup ;Translate message tag | |
450 | ldr r1,FNlitw(cright) ;Find the copyright string | |
451 | ldr r2,FNlitw(version) ;And the version string | |
452 | bl progInfo ;Display the box | |
453 | movvs r1,#1 ;If it failed, display error | |
454 | blvs errorBox ;In a pretty error box | |
455 | ldmfd r13!,{r0-r2,pc}^ ;And return to caller | |
456 | ||
457 | FNltorg | |
458 | ||
459 | ; --- Dislplay the menu of formats --- | |
460 | ||
461 | .sl__imSave cmp r0,#mEvent_subMenu ;Make sure this is a submenu | |
462 | movnes pc,r14 ;No -- not interested | |
463 | ||
464 | stmfd r13!,{r0-r5,r14} ;Save some registers | |
465 | adr r0,sl__fmtTitle ;Point to the title | |
466 | mov r1,#0 ;No handler for that | |
467 | bl menu_create ;Set that up to display | |
468 | ||
469 | ldr r4,[r12,#sl__format] ;Load the format chunk file | |
470 | mov r1,#0 ;Read first chunk name | |
471 | .loop mov r0,r4 ;Pop it in R0 for a bit | |
472 | bl chunk_enum ;Get the next chunk | |
473 | ldmcsfd r13!,{r0-r5,pc}^ ;Return when finished | |
474 | str r2,[r1,#4] ;Save pointer to name | |
475 | mov r2,r1 ;Point to the anchor | |
476 | mov r5,r1 ;Look after continuation | |
477 | adr r0,sl__fmtMenu ;Point to menu skeleton | |
478 | adr r1,sl__fmtHandler ;Point to handler routine | |
479 | mov r3,r12 ;Pass workspace in R12 | |
480 | bl menu_create ;Add that to the list | |
481 | mov r1,r5 ;Get the continuation value | |
482 | b loop ;And go back to the loop | |
483 | ||
484 | .sl__fmtTitle FNmenu("slSVFT") | |
485 | FNmenu_end | |
486 | ||
487 | .sl__fmtMenu FNmenu_itemInd(4) | |
488 | FNmenu_subWarn | |
489 | FNmenu_end | |
490 | ||
491 | FNltorg | |
492 | ||
493 | ; --- Dislplay the dump box --- | |
494 | ||
495 | .sl__imDump stmfd r13!,{r0-r5,r14} ;Save some registers | |
496 | ldr r0,[r12,#sl__used] ;Load the actual block size | |
497 | ldr r1,FNlitw(&ffd) ;Output as a data file | |
498 | add r2,r12,#sl__dumpFile ;Point to the dump file name | |
499 | adr r3,sl__dumpDef ;Point to handler block | |
500 | mov r4,r10 ;Pass document handle | |
501 | mov r5,r12 ;And pass the workspace addr | |
502 | bl saveAs ;Try to do the save op | |
503 | bvs sl__imd90 ;Tidy up if it failed | |
504 | ldr r14,[r12,#sl__flags] ;Load the current flags | |
505 | orr r14,r14,#slFlag__saving ;Say we're now saving | |
506 | str r14,[r12,#sl__flags] ;Save the flags back again | |
507 | ldmfd r13!,{r0-r5,pc}^ ;And return to caller | |
508 | ||
509 | .sl__imd90 mov r1,#1 ;If it failed, report error | |
510 | bl errorBox ;In a nice error box | |
511 | ldmfd r13!,{r0-r5,pc}^ ;And return to caller | |
512 | ||
513 | .sl__dumpDef FNs ("slSDT") ;Title for the save box | |
514 | b sl__svdDone ;Handle box closing | |
515 | b sl__saveDump ;Save to a disk file | |
516 | b sl__sendDump ;Send to another application | |
517 | movs pc,r14 ;Ignore completion | |
518 | b sl__svdFail ;Tidy up after a failure | |
519 | ||
520 | FNltorg | |
521 | ||
522 | ; --- Display a menu of modules to refresh --- | |
523 | ||
524 | .sl__imRefresh cmp r0,#mEvent_subMenu ;Is this a submenu? | |
525 | movnes pc,r14 ;No -- go away then | |
526 | stmfd r13!,{r0-r7,r14} ;Save some registers | |
527 | ||
528 | ; --- Free the old title block --- | |
529 | ||
530 | ldr r0,[r12,#sl__modNames] ;Load the pointer | |
531 | cmp r0,#0 ;Is the block allocated? | |
532 | blne free ;Yes -- deallocate it them | |
533 | movne r14,#0 ;And clear the pointer out | |
534 | strne r14,[r12,#sl__modNames] ;Done that | |
535 | ||
536 | ; --- Enumerate interesting modules --- | |
537 | ||
538 | mov r6,#0 ;Size of block required | |
539 | mov r1,#0 ;Start at the beginning | |
540 | ||
541 | ; --- Read the next module --- | |
542 | ||
543 | .loop mov r0,#12 ;Enumerate module names | |
544 | mov r2,#0 ;Not interested in instances | |
545 | swi "XOS_Module" ;Read the next module | |
546 | bvs sl__imRefAlloc ;No more -- go to next phase | |
547 | ||
548 | ; --- Update the arguments for next call --- | |
549 | ||
550 | cmp r2,#0 ;Is there another instance? | |
551 | addne r1,r1,#1 ;No -- update manually | |
552 | ||
553 | ; --- See whether this module was interesting --- | |
554 | ||
555 | ldr r14,[r3,#&20] ;Load the SWI handler offset | |
556 | cmp r14,#0 ;Does this look sensible? | |
557 | addne r6,r6,#8 ;Yes -- add another word | |
558 | b loop ;Get more modules | |
559 | ||
560 | ; --- Allocate the block --- | |
561 | ||
562 | .sl__imRefAlloc mov r0,r6 ;Get the required size | |
563 | bl alloc ;Allocate the block | |
564 | blcs alloc_error ;If it failed, point to error | |
565 | bcs sl__imRefError ;And handle that | |
566 | str r0,[r12,#sl__modNames] ;Store pointer for later | |
567 | mov r7,r0 ;Point to the block start | |
568 | ||
569 | ; --- Set up the title block --- | |
570 | ||
571 | adr r0,sl__rfmTitle ;Point to the title block | |
572 | adr r1,sl__rfmKernel ;Point to event handler | |
573 | mov r2,r10 ;Pass my R10 value | |
574 | mov r3,r12 ;And my R12 value | |
575 | bl menu_create ;Create the title | |
576 | ||
577 | ; --- Initialise for module scanning --- | |
578 | ||
579 | mov r6,#0 ;Current module number | |
580 | ||
581 | ; --- Read the next module --- | |
582 | ||
583 | .loop mov r0,#12 ;Enumerate module names | |
584 | mov r1,r6 ;Get next module number | |
585 | mov r2,#0 ;And next module name | |
586 | swi "XOS_Module" ;Read the next module | |
587 | ldmvsfd r13!,{r0-r7,pc}^ ;Return when done | |
588 | ||
589 | ; --- Update the arguments for next call --- | |
590 | ||
591 | cmp r2,#0 ;Is there another instance? | |
592 | moveq r6,r1 ;Yes -- store it normally | |
593 | addne r6,r1,#1 ;No -- update manually | |
594 | ||
595 | ; --- See whether this module was interesting --- | |
596 | ||
597 | ldr r14,[r3,#&20] ;Load the SWI handler offset | |
598 | cmp r14,#0 ;Does this look sensible? | |
599 | beq loop ;No -- loop round for more | |
600 | ||
601 | ; --- Add the menu item for this module --- | |
602 | ||
603 | ldr r14,[r3,#&10] ;Load the module name offset | |
604 | add r14,r3,r14 ;Add this on to the base | |
605 | stmia r7!,{r3,r14} ;Store base and name string | |
606 | adr r0,sl__rfmItem ;Point to the menu block | |
607 | adr r1,sl__rfmModule ;Point to the handler | |
608 | sub r2,r7,#8 ;Point to name pointer | |
609 | mov r3,r12 ;And get my workspace addr | |
610 | bl menu_create ;Add to the current menu | |
611 | b loop ;Keep on looping | |
612 | ||
613 | ; --- Report an error --- | |
614 | ||
615 | .sl__imRefError add r2,r0,#4 ;Point to error message | |
616 | adr r0,FNliterr(1,"slMLE") ;Point to skeleton | |
617 | bl str_error ;Mangle the message | |
618 | mov r1,#1 ;Just an OK button | |
619 | bl errorBox ;Report the message | |
620 | ldmfd r13!,{r0-r7,pc}^ ;And return to caller | |
621 | ||
622 | ; --- Refresh module title --- | |
623 | ||
624 | .sl__rfmTitle FNmenu("slMDS") | |
625 | ;FNmenu_item("slKNL") ;Not implemented | |
626 | FNmenu_end | |
627 | ||
628 | ; --- Refresh module items --- | |
629 | ||
630 | .sl__rfmItem FNmenu_itemInd(4) | |
631 | FNmenu_end | |
632 | ||
633 | FNltorg | |
634 | ||
635 | ; --- Quit the application --- | |
636 | ||
637 | .sl__imQuit stmfd r13!,{r14} ;Save return address away | |
638 | bl sl__okToQuit ;Make sure it's all right | |
639 | swics "OS_Exit" ;Yes -- just kill everything | |
640 | ldmfd r13!,{pc}^ ;Otherwise ignore the request | |
641 | ||
642 | FNltorg | |
643 | ||
644 | ; --- sl__rfmKernel --- | |
645 | ; | |
646 | ; On entry; -- | |
647 | ; | |
648 | ; On exit; -- | |
649 | ; | |
650 | ; Use; Refreshes the kernel SWIs table. | |
651 | ||
652 | .sl__rfmKernel movs pc,r14 ;Not implemented | |
653 | ||
654 | FNltorg | |
655 | ||
656 | ; --- sl__rfmModule --- | |
657 | ; | |
658 | ; On entry; -- | |
659 | ; | |
660 | ; On exit; -- | |
661 | ; | |
662 | ; Use; Refreshes a particular module. | |
663 | ||
664 | .sl__rfmModule stmfd r13!,{r0,r1,r14} ;Save link | |
665 | ldr r0,[r10,#0] ;Load module base | |
666 | bl sl__scanMod ;Scan the module | |
667 | movvs r1,#1 ;If it failed | |
668 | blvs errorBox ;Report the error | |
669 | ldmfd r13!,{r0,r1,pc}^ ;And return to caller | |
670 | ||
671 | FNltorg | |
672 | ||
673 | ; --- sl__setFlags --- | |
674 | ; | |
675 | ; On entry; -- | |
676 | ; | |
677 | ; On exit; -- | |
678 | ; | |
679 | ; Use; Sets up the flags from the flex anchors we have. | |
680 | ||
681 | .sl__setFlags stmfd r13!,{r0,r14} ;Save some registers | |
682 | ldr r0,[r12,#sl__flags] ;Load the flags word | |
683 | ldr r14,[r12,#sl__anchor] ;Load the block anchor | |
684 | cmp r14,#0 ;Is that defined? | |
685 | orrne r0,r0,#slFlag__block ;Yes -- set the flag | |
686 | biceq r0,r0,#slFlag__block ;No -- clear it | |
687 | tstne r0,#slFlag__format ;Is there a format chunk? | |
688 | orrne r0,r0,#slFlag__savable ;Yes -- set savable flag | |
689 | biceq r0,r0,#slFlag__savable ;No -- clear it then | |
690 | str r0,[r12,#sl__flags] ;Save modified flags | |
691 | ldmfd r13!,{r0,pc}^ ;And return to caller | |
692 | ||
693 | FNltorg | |
694 | ||
695 | ; --- sl__unknowns --- | |
696 | ; | |
697 | ; On entry; R0 == event code | |
698 | ; R1 == pointer to event data | |
699 | ; | |
700 | ; On exit; CS if event interesting, else CC | |
701 | ; R2-R10 corrupted | |
702 | ; | |
703 | ; Use; Handles interesting messages (e.g. PreQuit) | |
704 | ||
705 | .sl__unknowns cmp r0,#17 ;Is this a User_Message? | |
706 | cmpne r0,#18 ;Or a User_Message_Recorded? | |
707 | movnes pc,r14 ;No -- ignore it then | |
708 | ||
709 | ldr r2,[r1,#16] ;Load the event code | |
710 | cmp r2,#8 ;Is this a pre-quit message? | |
711 | movnes pc,r14 ;No -- not interested then | |
712 | ||
713 | ; --- Handle a PreQuit message --- | |
714 | ||
715 | orrs r14,r14,#C_flag ;We claim this event now | |
716 | stmfd r13!,{r14} ;Save return address | |
717 | bl sl__okToQuit ;Ask user if required | |
718 | ldmcsfd r13!,{pc}^ ;If OK then continue normally | |
719 | ||
720 | stmfd r13!,{r0-r2} ;Save some more registers | |
721 | mov r0,r11 ;Point to scratchpad | |
722 | ldr r2,[r1,#0] ;Load the message size | |
723 | bl fastMove ;Copy the message data over | |
724 | ldr r14,[r0,#8] ;Load his reference number | |
725 | str r14,[r0,#12] ;Set this as a reply to it | |
726 | mov r1,r0 ;Point to my copy | |
727 | mov r0,#19 ;Send this as an acknowledge | |
728 | ldr r2,[r1,#4] ;Load his task handle out | |
729 | swi "Wimp_SendMessage" ;Send the message back | |
730 | ldmfd r13!,{r0-r2,pc}^ ;Now return to caller | |
731 | ||
732 | FNltorg | |
733 | ||
734 | ; --- sl__okToQuit --- | |
735 | ; | |
736 | ; On entry; -- | |
737 | ; | |
738 | ; On exit; CS if we're allowed to quit, else CC | |
739 | ; | |
740 | ; Use; Works out if we're allowed to quit the application. If it | |
741 | ; isn't sure, it pops up a warning box and asks. | |
742 | ||
743 | .sl__okToQuit stmfd r13!,{r0,r1,r14} ;Save some registers | |
744 | ldr r14,[r12,#sl__flags] ;Load the flags word out | |
745 | tst r14,#slFlag__modified ;Has the block been changed? | |
746 | beq sl__otq90 ;No -- then skip onwards | |
747 | ||
748 | adr r0,FNlitsz("slOTQ") ;Point to warning messae | |
749 | bl msgs_lookup ;Translate the tag | |
750 | adr r1,sl__quitButts ;Point to buttons block | |
751 | bl warning ;Pop up the warning box | |
752 | ldmfd r13!,{r0,r1,r14} ;Unstack the registers | |
753 | orrcss pc,r14,#C_flag ;If OK, set the C flag | |
754 | bicccs pc,r14,#C_flag ;Otherwise clear it | |
755 | ||
756 | .sl__otq90 ldmfd r13!,{r0,r1,r14} ;Unstack the registers | |
757 | orrs pc,r14,#C_flag ;Set C -- we're OK | |
758 | ||
759 | .sl__quitButts FNbutton("slQUTB") | |
760 | FNbuttons_cancel | |
761 | FNbuttons_end | |
762 | ||
763 | FNltorg | |
764 | ||
765 | ;----- Save a SWI file ------------------------------------------------------ | |
766 | ||
767 | ; --- sl__fmtHandler --- | |
768 | ; | |
769 | ; On entry; R0 == menu event | |
770 | ; R1 == menu item | |
771 | ; R10 == pointer to chunk name | |
772 | ; | |
773 | ; On exit; -- | |
774 | ; | |
775 | ; Use; Handles events on the save menu. | |
776 | ||
777 | .sl__fmtHandler cmp r0,#mEvent_help ;Is this a help request? | |
778 | beq sl__fmtHelp ;Yes -- give help then | |
779 | cmp r0,#mEvent_subMenu ;Is this a submenu? | |
780 | cmpne r0,#mEvent_select ;Or a click? | |
781 | movnes pc,r14 ;No -- ignore this | |
782 | ||
783 | stmfd r13!,{r0-r5,r14} ;Save some registers | |
784 | ldr r0,[r12,#sl__used] ;Load the actual block size | |
785 | ldr r1,FNlitw(&fff) ;Output as a data file | |
786 | adr r2,FNlitsz("swis") ;Point to the dummy name | |
787 | adr r3,sl__saveDef ;Point to handler block | |
788 | mov r4,r10 ;Pass document handle | |
789 | mov r5,r12 ;And pass the workspace addr | |
790 | bl saveAs ;Try to do the save op | |
791 | movvs r1,#1 ;If it failed, report error | |
792 | blvs errorBox ;In a nice error box | |
793 | ldmfd r13!,{r0-r5,pc}^ ;And return to caller | |
794 | ||
795 | .sl__saveDef FNs ("slSVT") ;Title for the save box | |
796 | movs pc,r14 ;Don't care when it closes | |
797 | b sl__saveFile ;Save to a disk file | |
798 | b sl__send ;Send to another application | |
799 | b xsave_done ;Tell xsave it's all done | |
800 | b sl__failed ;Tidy up after a failure | |
801 | ||
802 | .sl__fmtHelp stmfd r13!,{r0-r2,r14} ;Save some registers | |
803 | ldr r0,[r10,#4] ;Find the format chunk name | |
804 | bl msgs_lookup ;Translate in case of tag | |
805 | mov r1,r0 ;Point to the result | |
806 | mov r0,r11 ;Point to scratchpad | |
807 | bl str_cpy ;Copy the string over | |
808 | .loop ldrb r14,[r0,#-1]! ;Load last byte of string | |
809 | subs r14,r14,#ASC(".") ;Is it part of an ellipsis? | |
810 | streqb r14,[r0,#0] ;Yes -- nobble that byte | |
811 | beq loop ;And try again | |
812 | adr r0,FNlitsz("slhSVF") ;Point to help message tag | |
813 | bl msgs_lookup ;Translate the message | |
814 | bl str_buffer ;Find an output buffer | |
815 | mov r2,r11 ;Point to scratchpad string | |
816 | bl str_subst ;And build the help string | |
817 | bl help_add ;Add this to help message | |
818 | ldmfd r13!,{r0-r2,pc}^ ;Return to caller | |
819 | ||
820 | FNltorg | |
821 | ||
822 | ; --- sl__saveFile --- | |
823 | ; | |
824 | ; On entry; R0 == pointer to file name | |
825 | ; R1 == safe flag | |
826 | ; | |
827 | ; On exit; -- | |
828 | ; | |
829 | ; Use; Saves the SWI block to a file. | |
830 | ||
831 | .sl__saveFile stmfd r13!,{r0-r5,r14} ;Save some registers | |
832 | mov r2,#0 ;No current name for this | |
833 | bl sl__replace ;Do we replace the file? | |
834 | movcc r0,#0 ;No -- return null error | |
835 | bcc sl__sf20 ;But cancel the save op | |
836 | ||
837 | ; --- Get on with saving the file --- | |
838 | ||
839 | .sl__sf10 mov r3,r0 ;Look after the file name | |
840 | adr r0,sl__writeList ;Point to saver routine | |
841 | mov r1,r10 ;Pass it the document handle | |
842 | mov r2,r12 ;And my workspace pointer | |
843 | ldr r4,FNlitw(&FFF) ;Pass the filetype over | |
844 | bl xsave_save ;Try to save the file | |
845 | bvs sl__sf20 ;If failed, abort now | |
846 | ||
847 | ; --- Now retrostamp the file --- | |
848 | ||
849 | mov r0,#17 ;Read info on the file | |
850 | mov r1,r3 ;Point to the filename | |
851 | swi "XOS_File" ;Read info on the file | |
852 | movvc r0,#1 ;Now we set the info | |
853 | bicvc r2,r2,#&FF ;Leave filetype alone | |
854 | orrvc r2,r2,#&3A ;Put in our dummy datestamp | |
855 | ldrvc r3,FNlitw(&BD896000) ;Set up rest of datestamp | |
856 | swivc "XOS_File" ;Now retrostamp it nicely | |
857 | ldmvcfd r13!,{r0-r5,pc}^ ;If it worked OK, return | |
858 | ||
859 | ; --- It failed --- | |
860 | ||
861 | .sl__sf20 add r13,r13,#4 ;Don't restore R0 on exit | |
862 | ldmfd r13!,{r1-r5,r14} ;Unstack saved registers | |
863 | orrs pc,r14,#V_flag ;And return to caller | |
864 | ||
865 | FNltorg | |
866 | ||
867 | ; --- sl__send --- | |
868 | ; | |
869 | ; On entry; R2 == accumulator value (initially 0) | |
870 | ; | |
871 | ; On exit; R0 == pointer to block to send | |
872 | ; R1 == size of block to send | |
873 | ; CS if this is the last block, else CC | |
874 | ; | |
875 | ; Use; Sends a block of data to another application. | |
876 | ||
877 | .sl__send adr r0,sl__writeList ;Point to my saver routine | |
878 | mov r1,r10 ;Pass the document handle | |
879 | mov r2,r12 ;Pass my workspace too | |
880 | b xsave_send ;And get another block | |
881 | ||
882 | FNltorg | |
883 | ||
884 | ; --- sl__failed --- | |
885 | ; | |
886 | ; On entry; R0 == pointer to error, or 0 | |
887 | ; R1 == 1 | |
888 | ; | |
889 | ; On exit; -- | |
890 | ; | |
891 | ; Use; Terminates a save job, and reports an error. | |
892 | ||
893 | .sl__failed stmfd r13!,{r0-r2,r14} ;Save some registers | |
894 | bl xsave_failed ;Tell xsave it's finished | |
895 | cmp r0,#0 ;Is there an actual error? | |
896 | addne r2,r0,#4 ;Point to error text | |
897 | adrne r0,FNliterr(1,"slSFE") | |
898 | blne msgs_error ;Translate and substitute | |
899 | movne r1,#1 ;Display just an OK button | |
900 | blne errorBox ;Yes -- report it then | |
901 | ldmfd r13!,{r0-r2,pc}^ ;Return to caller | |
902 | ||
903 | FNltorg | |
904 | ||
905 | ; --- sl__replace --- | |
906 | ; | |
907 | ; On entry; R0 == filename | |
908 | ; R1 == safeness flag | |
909 | ; R2 == pointer to current name, or 0 | |
910 | ; | |
911 | ; On exit; -- | |
912 | ; | |
913 | ; Use; CS to save, CC to cancel | |
914 | ||
915 | .sl__replace stmfd r13!,{r0-r2,r14} ;Save some registers | |
916 | cmp r1,#0 ;Is the file marked as safe? | |
917 | beq sl__replace10 ;No -- then don't ask | |
918 | ||
919 | movs r1,r2 ;Is there a current name? | |
920 | beq sl__replace05 ;No -- can't do this check | |
921 | bl str_icmp ;Compare the file names | |
922 | beq sl__replace10 ;The same name -- don't ask | |
923 | ||
924 | .sl__replace05 bl res_exists ;Does the file exist? | |
925 | bcc sl__replace10 ;No -- then don't ask | |
926 | ||
927 | ; --- Ask the user if this is right --- | |
928 | ||
929 | mov r2,r0 ;Get the filename pointer | |
930 | adr r0,FNlitsz("slRPP") ;Point to the prompt message | |
931 | bl msgs_lookup ;Translate the message | |
932 | bl str_buffer ;Find a handy string buffer | |
933 | bl str_subst ;Build the prompt string | |
934 | adr r1,sl__exWarn ;Point to the buttons def | |
935 | bl warning ;Display the warning box | |
936 | ldmccfd r13!,{r0-r2,r14} ;If no, abort the job | |
937 | bicccs pc,r14,#C_flag ;Tell caller it's all off | |
938 | ||
939 | .sl__replace10 ldmfd r13!,{r0-r2,r14} ;Restore registers | |
940 | orrs pc,r14,#C_flag ;And let it all go ahead | |
941 | ||
942 | .sl__exWarn FNbutton("slRPL") | |
943 | FNbuttons_cancel | |
944 | FNbuttons_end | |
945 | ||
946 | FNltorg | |
947 | ||
948 | ;----- Write out a dump file ------------------------------------------------ | |
949 | ||
950 | ; --- sl__svdDone --- | |
951 | ; | |
952 | ; On entry; -- | |
953 | ; | |
954 | ; On exit; -- | |
955 | ; | |
956 | ; Use; Handles the save box closing. We allow loads of dump files | |
957 | ; again. | |
958 | ||
959 | .sl__svdDone stmfd r13!,{r14} ;Save some registers | |
960 | ldr r14,[r12,#sl__flags] ;Load the flags word | |
961 | bic r14,r14,#slFlag__saving ;Turn off the saving flag | |
962 | str r14,[r12,#sl__flags] ;Save the flags back | |
963 | ldmfd r13!,{pc}^ ;And return to caller | |
964 | ||
965 | FNltorg | |
966 | ||
967 | ; --- sl__saveDump --- | |
968 | ; | |
969 | ; On entry; R0 == pointer to file name | |
970 | ; R1 == safeness flag | |
971 | ; | |
972 | ; On exit; -- | |
973 | ; | |
974 | ; Use; Saves a dump of the current SWI names | |
975 | ||
976 | .sl__saveDump stmfd r13!,{r0-r5,r14} ;Save some registers | |
977 | add r2,r12,#sl__dumpFile ;Point to current name | |
978 | bl sl__replace ;Do we actually do this? | |
979 | movcc r0,#0 ;If not, return null error | |
980 | bcc sl__saved90 ;To cancel the save op | |
981 | ||
982 | mov r1,r0 ;Point to the filename | |
983 | mov r0,#10 ;Save memory as a file | |
984 | ldr r2,FNlitw(&FFD) ;Save as a data file | |
985 | add r14,r12,#sl__anchor ;Point to dump anchor | |
986 | ldmia r14,{r4,r5} ;Load base and size | |
987 | add r5,r4,r5 ;Turn size into limit | |
988 | swi "XOS_File" ;Try to save the file | |
989 | bvs sl__saved90 ;If it failed, abort | |
990 | ||
991 | ldr r14,[r13,#4] ;Load the safeness flag | |
992 | cmp r14,#0 ;Is the flag safe? | |
993 | beq sl__saved50 ;No -- skip onwards then | |
994 | ||
995 | ; --- Do special things when file saved properly --- | |
996 | ||
997 | ldr r14,[r12,#sl__flags] ;Yes -- load flags then | |
998 | bic r14,r14,#slFlag__modified ;Clear the modified bit | |
999 | str r14,[r12,#sl__flags] ;And store the flags back | |
1000 | ||
1001 | bl sl__setDumpName ;Go and set the name | |
1002 | ||
1003 | .sl__saved50 ldmfd r13!,{r0-r5,pc}^ ;Return to caller | |
1004 | ||
1005 | .sl__saved90 add r13,r13,#4 ;Don't restore R0 on exit | |
1006 | ldmfd r13!,{r1-r5,r14} ;Restore registers | |
1007 | orrs pc,r14,#V_flag ;And return with V set | |
1008 | ||
1009 | FNltorg | |
1010 | ||
1011 | ; --- sl__sendDump --- | |
1012 | ; | |
1013 | ; On entry; -- | |
1014 | ; | |
1015 | ; On exit; R0 == pointer to block to send | |
1016 | ; R1 == size of block | |
1017 | ; CS for last block, CC otherwise | |
1018 | ; | |
1019 | ; Use; Sends the SWI dump block to another application | |
1020 | ||
1021 | .sl__sendDump add r0,r12,#sl__anchor ;Find the anchor block | |
1022 | ldmia r0,{r0,r1} ;Load the values out | |
1023 | orrs pc,r14,#C_flag ;And return the only block | |
1024 | ||
1025 | FNltorg | |
1026 | ||
1027 | ; --- sl__svdFail --- | |
1028 | ; | |
1029 | ; On entry; R0 == pointer to error, or 0 | |
1030 | ; R1 == 1 | |
1031 | ; | |
1032 | ; On exit; -- | |
1033 | ; | |
1034 | ; Use; Terminates a save job, and reports an error. | |
1035 | ||
1036 | .sl__svdFail stmfd r13!,{r0-r2,r14} ;Save some registers | |
1037 | cmp r0,#0 ;Is there an actual error? | |
1038 | addne r2,r0,#4 ;Point to error text | |
1039 | adrne r0,FNliterr(1,"slSDE") | |
1040 | blne msgs_error ;Translate and substitute | |
1041 | movne r1,#1 ;Display just an OK button | |
1042 | blne errorBox ;Yes -- report it then | |
1043 | ldmfd r13!,{r0-r2,pc}^ ;Return to caller | |
1044 | ||
1045 | FNltorg | |
1046 | ||
1047 | ;----- Writing out a list of SWIs ------------------------------------------- | |
1048 | ||
1049 | ; --- sl__writeList --- | |
1050 | ; | |
1051 | ; On entry; -- | |
1052 | ; | |
1053 | ; On exit; -- | |
1054 | ; | |
1055 | ; Use; Writes the list of SWIs to the current xsave output. | |
1056 | ||
1057 | .sl__writeList stmfd r13!,{r0-r10,r14} ;Save some registers | |
1058 | ||
1059 | ; --- Make sure we can do this --- | |
1060 | ||
1061 | ldr r14,[r12,#sl__anchor] ;Load the block anchor | |
1062 | cmp r14,#0 ;Is it created currently? | |
1063 | adreq r0,FNliterr(1,"slNSS") | |
1064 | bleq msgs_error ;Translate the error | |
1065 | beq sl__wl90 ;And return the error | |
1066 | ldr r14,[r12,#sl__format] ;Load the format anchor | |
1067 | cmp r14,#0 ;Is it created currently? | |
1068 | adreq r0,FNliterr(1,"slNFD") | |
1069 | bleq msgs_error ;Translate the error | |
1070 | beq sl__wl90 ;And return the error | |
1071 | ||
1072 | ; --- Get on with saving then --- | |
1073 | ||
1074 | swi "Hourglass_On" ;Start an hourglass going | |
1075 | ||
1076 | ; --- Set up initial registers --- | |
1077 | ||
1078 | ldr r9,[r10,#0] ;Load the block base | |
1079 | mov r0,r10 ;Point to the anchor | |
1080 | bl flex_size ;Get the block size | |
1081 | add r10,r9,r0 ;Find the format limit | |
1082 | adr r8,FNlitsz("*UNDEFINED*") ;No module name defined yet | |
1083 | mov r7,r8 ;No prefix string yet either | |
1084 | mov r6,r8 ;And no actual SWI name | |
1085 | mvn r5,#NOT(-1) ;No SWI number defined either | |
1086 | ||
1087 | ; --- Write out the preamble --- | |
1088 | ||
1089 | bl sl__doString ;Write out this format | |
1090 | bvs sl__wl90 ;If it failed, bail out | |
1091 | ||
1092 | ; --- We've found the module header --- | |
1093 | ; | |
1094 | ; Now we set up for the main loop, by remembering the index | |
1095 | ; into the format string; we then embark on the first item | |
1096 | ; in the SWI list. | |
1097 | ||
1098 | mov r4,r9 ;Remember this position | |
1099 | ldr r3,[r12,#sl__anchor] ;Load the anchor base address | |
1100 | mov r2,#0 ;Start at the beginning | |
1101 | ||
1102 | ; --- The main output loop --- | |
1103 | ||
1104 | .sl__wl15 add r1,r3,r2 ;Work out address of block | |
1105 | ldr r5,[r1,#4] ;Load the SWI chunk number | |
1106 | bic r5,r5,#&ff000000 ;Clear the flags bits | |
1107 | add r8,r1,#8 ;Point to the module name | |
1108 | mov r9,r4 ;Start from preamble position | |
1109 | bl sl__doString ;Write out this format string | |
1110 | bvs sl__wl90 ;If it failed, bail out | |
1111 | ||
1112 | ; --- Written the header -- now do the SWIs --- | |
1113 | ||
1114 | mov r2,r9 ;Remeber format index | |
1115 | mov r7,r8 ;Work out prefix string pos | |
1116 | .sl__wl20 ldrb r14,[r7],#1 ;Load next byte | |
1117 | cmp r14,#0 ;Is this end of module name? | |
1118 | bne sl__wl20 ;No -- keep going round | |
1119 | ||
1120 | mov r6,r7 ;Work out SWI name position | |
1121 | .sl__wl25 ldrb r14,[r6],#1 ;Load next byte from string | |
1122 | cmp r14,#0 ;Is this the end yet? | |
1123 | bne sl__wl25 ;No -- keep going | |
1124 | .sl__wl26 ldrb r14,[r6,#0] ;Load the first byte | |
1125 | cmp r14,#0 ;Is it a null string? | |
1126 | beq sl__wl30 ;Yes -- move on to next mod | |
1127 | cmp r14,#1 ;Is this a dummy SWI? | |
1128 | addeq r6,r6,#1 ;Yes -- move pointer on | |
1129 | addeq r5,r5,#1 ;And move on the SWI counter | |
1130 | beq sl__wl26 ;And start again | |
1131 | ||
1132 | mov r9,r2 ;Point to format string | |
1133 | bl sl__doString ;Write this string out | |
1134 | bvs sl__wl90 ;If it failed, bail out | |
1135 | add r5,r5,#1 ;Bump up the SWI number | |
1136 | b sl__wl25 ;And go round for more | |
1137 | ||
1138 | ; --- Finished a module --- | |
1139 | ||
1140 | .sl__wl30 ldr r2,[r1,#0] ;Load the size word | |
1141 | sub r14,r1,r3 ;Work out old offset | |
1142 | add r2,r14,r2 ;Add it onto previous offset | |
1143 | ldr r14,[r12,#sl__used] ;Load current size of block | |
1144 | cmp r2,r14 ;Is this the last one? | |
1145 | bcc sl__wl15 ;No -- do this module too | |
1146 | ||
1147 | ; --- Do the end bit of the file --- | |
1148 | ||
1149 | bl sl__doString ;Write out the postamble | |
1150 | bvs sl__wl90 ;If it failed, bail out | |
1151 | ||
1152 | swi "Hourglass_Off" ;Turn off the hourglass | |
1153 | ldmfd r13!,{r0-r10,pc}^ ;Return to caller | |
1154 | ||
1155 | ; --- It failed -- return an error | |
1156 | ||
1157 | .sl__wl90 swi "Hourglass_Off" ;Turn off the hourglass | |
1158 | add r13,r13,#4 ;Don't restore R0 | |
1159 | ldmfd r13!,{r1-r10,r14} ;Restore registers | |
1160 | orrs pc,r14,#V_flag ;And return the error | |
1161 | ||
1162 | FNltorg | |
1163 | ||
1164 | ; --- sl__doString --- | |
1165 | ; | |
1166 | ; On entry; R5 == current SWI number | |
1167 | ; R6 == pointer to current SWI postfix | |
1168 | ; R7 == pointer to current SWI prefix | |
1169 | ; R8 == pointer to current module name | |
1170 | ; R9 == pointer to format string input | |
1171 | ; R10 == pointer to end of format string | |
1172 | ; | |
1173 | ; On exit; R1, R2, R4 and R6-R10 may be flex relocated | |
1174 | ; R0 corrupted | |
1175 | ; R9 == pointer to format string when processing stopped | |
1176 | ; May return an error | |
1177 | ; | |
1178 | ; Use; Outputs a string, based on a format with the following | |
1179 | ; syntax: | |
1180 | ; | |
1181 | ; All characters are echoed directly except `%' which is | |
1182 | ; an escape for the following character. Escape codes defined | |
1183 | ; are: | |
1184 | ; | |
1185 | ; %s == current SWI name | |
1186 | ; %m == current module name | |
1187 | ; %n == current SWI number | |
1188 | ; %x == current X SWI number (i.e. SWI number OR &20000) | |
1189 | ; %% == end of formatting section | |
1190 | ||
1191 | .sl__doString stmfd r13!,{r3,r14} ;Save some registers | |
1192 | FNflex_save("r1,r2,r4") ;Save caller's registers | |
1193 | sub r13,r13,#128 ;Make a small buffer | |
1194 | orr r3,r5,#&20000 ;Get the X version number | |
1195 | ||
1196 | .sl__dostr10 cmp r9,r10 ;Are we at the end yet? | |
1197 | bcs sl__dostr50 ;Yes -- return then | |
1198 | ldrb r0,[r9],#1 ;Load next byte from string | |
1199 | cmp r0,#ASC("%") ;Is this a magic `%' sign? | |
1200 | beq sl__dostr20 ;Yes -- do clever things | |
1201 | ||
1202 | bl sl__byte ;Write this byte out | |
1203 | b sl__dostr10 ;And continue formatting | |
1204 | ||
1205 | ; --- Handle an escape character --- | |
1206 | ||
1207 | .sl__dostr20 ldrb r0,[r9],#1 ;Load next byte from string | |
1208 | orr r0,r0,#&20 ;Make sure char is lowercase | |
1209 | cmp r0,#ASC("s") ;Is this a SWI name? | |
1210 | adreq r0,FNlitsz("%5_%4") ;Yes -- point to skeleton | |
1211 | cmp r0,#ASC("m") ;Or the module name? | |
1212 | adreq r0,FNlitsz("%6") ;Yes -- point to skeleton | |
1213 | cmp r0,#ASC("n") ;Or the SWI number? | |
1214 | adreq r0,FNlitsz("%x3") ;Yes -- point to skeleton | |
1215 | cmp r0,#ASC("x") ;Or the SWI X number? | |
1216 | adreq r0,FNlitsz("%x1") ;Yes -- point to skeleton | |
1217 | cmp r0,#ASC("d") ;Or a date string? | |
1218 | beq sl__dostr40 ;Yes -- process specially | |
1219 | cmp r0,#ASC("p") ;Or a literal percent? | |
1220 | adreq r0,FNlitsz("%%") ;Yes -- point to skeleton | |
1221 | cmp r0,#ASC("%") ;Or a percent sign? | |
1222 | addeq r9,r9,#1 ;Yes -- skip a newline char | |
1223 | beq sl__dostr50 ;Yes -- handle that | |
1224 | ||
1225 | cmp r0,#256 ;Do we have an address? | |
1226 | bcc sl__dostr10 ;No -- go round for more then | |
1227 | ||
1228 | mov r1,r13 ;Build string in it | |
1229 | bl str_subst ;Build output string | |
1230 | mov r2,r0 ;Point to the string | |
1231 | .sl__dostr30 ldrb r0,[r2],#1 ;Load next byte | |
1232 | cmp r0,#32 ;Is it the terminator? | |
1233 | blcs sl__byte ;No -- output it then | |
1234 | bcs sl__dostr30 ;And loop back round again | |
1235 | b sl__dostr10 ;Carry on with the string | |
1236 | ||
1237 | FNltorg | |
1238 | ||
1239 | ; --- Handle a date format string --- | |
1240 | ||
1241 | .sl__dostr40 stmfd r13!,{r3} ;I need this register | |
1242 | sub r13,r13,#8 ;Make time buffer on stack | |
1243 | mov r14,#3 ;Get the subreason code | |
1244 | strb r14,[r13,#0] ;Save that in the block | |
1245 | mov r1,r13 ;Point to the buffer | |
1246 | mov r0,#14 ;Get the main reason code | |
1247 | swi "OS_Word" ;Read the current time | |
1248 | ||
1249 | ldrb r0,[r9,#0] ;Load the next byte ready | |
1250 | cmp r0,#ASC("[") ;Is this an argument? | |
1251 | adrne r0,FNlitsz("slDFMT") ;No -- point to default | |
1252 | blne msgs_lookup ;Translate nicely | |
1253 | movne r3,r0 ;And put it in the right reg | |
1254 | bne sl__dostr45 ;And skip onwards a bit | |
1255 | ||
1256 | ; --- Read the format string argument --- | |
1257 | ||
1258 | mov r1,r11 ;Point to a spare buffer | |
1259 | add r9,r9,#1 ;Skip past the `[' char | |
1260 | .a ldrb r14,[r9],#1 ;Load the next byte | |
1261 | cmp r14,#ASC("]") ;Is that the end yet? | |
1262 | cmpne r14,#&0D ;Check return for safety | |
1263 | moveq r14,#0 ;Yes -- terminate string | |
1264 | strb r14,[r1],#1 ;Store the byte away | |
1265 | bne a ;Loop until all done | |
1266 | mov r3,r11 ;Point to the format string | |
1267 | ||
1268 | ; --- Now read the actual string --- | |
1269 | ||
1270 | .sl__dostr45 mov r0,r13 ;Point to the time block | |
1271 | add r1,r13,#12 ;Point to output buffer | |
1272 | mov r2,#128 ;Get the buffer size | |
1273 | swi "OS_ConvertDateAndTime" ;Translate the string | |
1274 | add r13,r13,#8 ;Don't need the time any more | |
1275 | ldmfd r13!,{r3} ;Restore register I saved | |
1276 | mov r2,r13 ;Point to buffer start | |
1277 | b sl__dostr30 ;Now output this string | |
1278 | ||
1279 | ; --- Finished reading the input --- | |
1280 | ||
1281 | .sl__dostr50 add r13,r13,#128 ;Reclaim my little buffer | |
1282 | FNflex_load("r1,r2,r4") ;Restore caller's pointers | |
1283 | ldmfd r13!,{r3,r14} ;Restore other registers | |
1284 | bics pc,r14,#V_flag ;Return without an error | |
1285 | ||
1286 | ; --- Write byte in R0 to output --- | |
1287 | ||
1288 | .sl__byte mov r1,r14 ;Look after return address | |
1289 | FNflex_save("r6-r10") ;Save lots of values | |
1290 | bl xsave_byte ;Write this byte out | |
1291 | FNflex_load("r6-r10") ;Restore our registers | |
1292 | movvcs pc,r1 ;If OK, return to caller | |
1293 | ||
1294 | add r13,r13,#128 ;Reclaim my little buffer | |
1295 | FNflex_load("r1,r2,r4") ;Restore caller's pointers | |
1296 | ldmfd r13!,{r3,r14} ;Restore other registers | |
1297 | orrs pc,r14,#V_flag ;And return the error | |
1298 | ||
1299 | FNltorg | |
1300 | ||
1301 | ;----- Loading modules ------------------------------------------------------ | |
1302 | ||
1303 | ; --- sl__loadMod --- | |
1304 | ; | |
1305 | ; On entry; R1 == pointer to filename | |
1306 | ; | |
1307 | ; On exit; May return an error | |
1308 | ; | |
1309 | ; Use; Loads a module and adds its SWIs to the current list. | |
1310 | ||
1311 | .sl__loadMod stmfd r13!,{r0-r2,r14} ;Save some registers | |
1312 | add r2,r12,#sl__module ;Point to anchor for this | |
1313 | bl load_file ;Try to load the file | |
1314 | strvs r0,[r13,#0] ;If failed, return error | |
1315 | ldmfd r13!,{r0-r2,pc} ;Return to caller | |
1316 | ||
1317 | FNltorg | |
1318 | ||
1319 | ; --- sl__ibMod --- | |
1320 | ; | |
1321 | ; On entry; R1 == estimated file size | |
1322 | ; | |
1323 | ; On exit; May return an error | |
1324 | ; | |
1325 | ; Use; Sets up a buffer for RAM loading. | |
1326 | ||
1327 | .sl__ibMod add r2,r12,#sl__module ;Point to anchor | |
1328 | b load_initBuf ;Start the load op | |
1329 | ||
1330 | FNltorg | |
1331 | ||
1332 | ; --- sl__doneMod --- | |
1333 | ; | |
1334 | ; On entry; -- | |
1335 | ; | |
1336 | ; On exit; -- | |
1337 | ; | |
1338 | ; Use; Adds a module to the SWI list. | |
1339 | ||
1340 | .sl__doneMod stmfd r13!,{r0-r2,r14} ;Save some registers | |
1341 | ldr r0,[r12,#sl__module] ;Load the flex anchor | |
1342 | bl sl__scanMod ;Scan the module | |
1343 | bvs sl__doneMod50 ;If it failed, quit now | |
1344 | add r0,r12,#sl__module ;Point to the anchor | |
1345 | bl flex_free ;Free the block | |
1346 | ldmfd r13!,{r0-r2,pc}^ ;And return to caller | |
1347 | ||
1348 | .sl__doneMod50 add r2,r0,#4 ;Look after the error | |
1349 | add r0,r12,#sl__module ;Point to the anchor | |
1350 | bl flex_free ;Free the block | |
1351 | adr r0,FNliterr(1,"slMAA") | |
1352 | bl msgs_error ;Translate and substitute | |
1353 | mov r1,#1 ;Only have one button | |
1354 | bl errorBox ;Report the error | |
1355 | ldmfd r13!,{r0-r2,pc}^ ;And return to caller | |
1356 | ||
1357 | FNltorg | |
1358 | ||
1359 | ; --- sl__lfMod --- | |
1360 | ; | |
1361 | ; On entry; R0 == pointer to error | |
1362 | ; R1 == 1 | |
1363 | ; | |
1364 | ; On exit; -- | |
1365 | ; | |
1366 | ; Use; Reports an error when an attemt to load a module failed. | |
1367 | ||
1368 | .sl__lfMod stmfd r13!,{r0-r2,r14} ;Save some registers | |
1369 | cmp r0,#0 ;Is there a real error? | |
1370 | addne r2,r0,#4 ;Point to error text | |
1371 | adrne r0,FNliterr(1,"slLFM") | |
1372 | blne msgs_error ;Translate and substitute | |
1373 | movne r1,#1 ;Only use one button | |
1374 | blne errorBox ;Report the error | |
1375 | ldmfd r13!,{r0-r2,pc}^ ;And return to caller | |
1376 | ||
1377 | FNltorg | |
1378 | ||
1379 | ;----- Loading dump files --------------------------------------------------- | |
1380 | ||
1381 | ; --- sl__loadDmp --- | |
1382 | ; | |
1383 | ; On entry; R1 == pointer to filename | |
1384 | ; | |
1385 | ; On exit; May return an error | |
1386 | ; | |
1387 | ; Use; Loads a module and adds its SWIs to the current list. | |
1388 | ||
1389 | .sl__loadDmp stmfd r13!,{r0-r2,r14} ;Save some registers | |
1390 | add r0,r12,#sl__anchor ;Point to the anchor | |
1391 | ldr r14,[r12,#sl__anchor] ;Load the current anchor | |
1392 | cmp r14,#0 ;Is it defined currently? | |
1393 | blne flex_free ;Yes -- free the block | |
1394 | add r2,r12,#sl__anchor ;Point to anchor for this | |
1395 | bl load_file ;Try to load the file | |
1396 | strvs r0,[r13,#0] ;On error, return pointer | |
1397 | ldmfd r13!,{r0-r2,pc} ;And return to caller | |
1398 | ||
1399 | FNltorg | |
1400 | ||
1401 | ; --- sl__ibDmp --- | |
1402 | ; | |
1403 | ; On entry; R1 == estimated file size | |
1404 | ; | |
1405 | ; On exit; May return an error | |
1406 | ; | |
1407 | ; Use; Sets up a buffer for RAM loading. | |
1408 | ||
1409 | .sl__ibDmp stmfd r13!,{r0,r14} ;Save some registers | |
1410 | add r0,r12,#sl__anchor ;Point to the anchor | |
1411 | ldr r14,[r12,#sl__anchor] ;Load the current anchor | |
1412 | cmp r14,#0 ;Is it defined currently? | |
1413 | blne flex_free ;Yes -- free the block | |
1414 | ldmfd r13!,{r0,r14} ;Unstack the registers | |
1415 | add r2,r12,#sl__anchor ;Point to anchor | |
1416 | b load_initBuf ;Start the load op | |
1417 | ||
1418 | FNltorg | |
1419 | ||
1420 | ; --- sl__doneDmp --- | |
1421 | ; | |
1422 | ; On entry; R0 == pointer to `filename' | |
1423 | ; | |
1424 | ; On exit; -- | |
1425 | ; | |
1426 | ; Use; Handles a completed load of a dump file. | |
1427 | ||
1428 | .sl__doneDmp stmfd r13!,{r0,r1,r14} ;Save some registers | |
1429 | mov r1,r0 ;Point to the file's name | |
1430 | bl sl__setDumpName ;Set the name up correctly | |
1431 | add r0,r12,#sl__anchor ;Point to the anchor block | |
1432 | bl flex_size ;Read the block's size | |
1433 | str r0,[r12,#sl__used] ;Save the size as used value | |
1434 | str r0,[r12,#sl__size] ;And as the size value | |
1435 | ldr r14,[r12,#sl__flags] ;Load the flags word | |
1436 | bic r14,r14,#slFlag__modified ;Got it from someone else | |
1437 | str r14,[r12,#sl__flags] ;Store the flags back | |
1438 | bl sl__setFlags ;Reset the flags nicely | |
1439 | ldmfd r13!,{r0,r1,pc}^ ;Return to caller | |
1440 | ||
1441 | FNltorg | |
1442 | ||
1443 | ; --- sl__lfDmp --- | |
1444 | ; | |
1445 | ; On entry; R0 == pointer to error | |
1446 | ; R1 == 1 | |
1447 | ; | |
1448 | ; On exit; -- | |
1449 | ; | |
1450 | ; Use; Reports an error when an attemt to load a module failed. | |
1451 | ||
1452 | .sl__lfDmp stmfd r13!,{r0-r2,r14} ;Save some registers | |
1453 | bl sl__setFlags ;Update the flags | |
1454 | cmp r0,#0 ;Is there a real error? | |
1455 | addne r2,r0,#4 ;Point to error text | |
1456 | adrne r0,FNliterr(1,"slLFM") | |
1457 | blne msgs_error ;Translate and substitute | |
1458 | movne r1,#1 ;Only use one button | |
1459 | blne errorBox ;Report the error | |
1460 | ldmfd r13!,{r0-r2,pc}^ ;And return to caller | |
1461 | ||
1462 | FNltorg | |
1463 | ||
1464 | ;----- Format of the SWI table ---------------------------------------------- | |
1465 | ; | |
1466 | ; In order to speed things up, we maintain a table of SWI names in memory, | |
1467 | ; and write this out to a file when the user wants us to. This also means | |
1468 | ; that we can build up a list of SWIs over a period of time, by the user | |
1469 | ; dropping module files onto our icon or window -- this saves having to load | |
1470 | ; large numbers of modules into the RMA. | |
1471 | ; | |
1472 | ; The format is fairly simple. We keep a linked list of module blocks in | |
1473 | ; a flex block. The blocks are sorted by ascending order of SWI chunk base | |
1474 | ; numbers. Each module block looks like this; | |
1475 | ; | |
1476 | ; word; size of this link block | |
1477 | ; word; SWI chunk base number for module and flags in top 8 bits | |
1478 | ; string; name of module which provides these SWIs (null-terminated) | |
1479 | ; string; SWI prefix for following SWI names (null-terminated) | |
1480 | ; string; name of first SWI provided by module (null-terminated) | |
1481 | ; string; name of second SWI provided by module (null-terminated) | |
1482 | ; ... ... | |
1483 | ; string; name of last SWI provided by module (null-terminated) | |
1484 | ; byte; 0 (list terminator) | |
1485 | ; align; to word boundary | |
1486 | ||
1487 | ; --- sl__setDumpName --- | |
1488 | ; | |
1489 | ; On entry; R1 == 0 for default `SWIDump' or pointer to name | |
1490 | ; | |
1491 | ; On exit; -- | |
1492 | ; | |
1493 | ; Use; Sets the name of the current dump file. | |
1494 | ||
1495 | .sl__setDumpName stmfd r13!,{r0-r2,r14} ;Save some registers | |
1496 | movs r0,r1 ;Point to the source string | |
1497 | adreq r0,FNlitsz("SWIDump") ;No string -- use default | |
1498 | add r1,r12,#sl__dumpFile ;Point to the name buffer | |
1499 | mov r2,#256 ;The buffer size | |
1500 | orr r2,r2,#&C0000000 ;Don't do `|'s or `""'s | |
1501 | swi "OS_GSTrans" ;Expand system variables | |
1502 | ldmfd r13!,{r0-r2,pc}^ ;And return to caller | |
1503 | ||
1504 | FNltorg | |
1505 | ||
1506 | ; --- sl__initBlock --- | |
1507 | ; | |
1508 | ; On entry; -- | |
1509 | ; | |
1510 | ; On exit; May return an error | |
1511 | ; | |
1512 | ; Use; Initialises the SWI list block with the currently recognised | |
1513 | ; OS SWIs. | |
1514 | ||
1515 | .sl__initBlock stmfd r13!,{r0-r3,r14} ;Save some registers | |
1516 | ||
1517 | add r0,r12,#sl__anchor ;Point to the anchor | |
1518 | ldr r14,[r12,#sl__anchor] ;Load the current anchor | |
1519 | cmp r14,#0 ;Is it defined currently? | |
1520 | blne flex_free ;Yes -- free the block | |
1521 | ||
1522 | ; --- Reset the dump file name --- | |
1523 | ||
1524 | mov r1,#0 ;Use the default name | |
1525 | bl sl__setDumpName ;Go and do that please | |
1526 | ||
1527 | ; --- Create the flex block --- | |
1528 | ||
1529 | mov r1,#1024 ;Initially make it 1K | |
1530 | bl flex_alloc ;Allocate the block | |
1531 | blcs alloc_error ;If it failed, get an error | |
1532 | bcs sl__initBlk90 ;And abort now | |
1533 | ||
1534 | mov r14,r1 ;Get the size created | |
1535 | mov r1,#0 ;Start output at beginning | |
1536 | stmib r0,{r1,r14} ;Store sizes after anchor | |
1537 | ||
1538 | ; --- Now build the kernel SWIs --- | |
1539 | ; | |
1540 | ; First do OS_WriteI. Then we do the kernel SWIs lower than | |
1541 | ; &100. | |
1542 | ||
1543 | adr r0,FNlitsz("Kernel") ;Point to string `Kernel' | |
1544 | adr r1,FNlitsz("OS") ;Point to string `OS' | |
1545 | mov r2,#&100 ;Get SWI chunk number | |
1546 | bl sl__newLink ;Add in a new link block | |
1547 | bvs sl__initBlk89 ;If it failed, stop going | |
1548 | bcs sl__initBlk05 ;If already done, skip | |
1549 | add r0,r12,#sl__anchor ;Point to the anchor | |
1550 | adr r1,FNlitsz("WriteI") ;Point to string `WriteI' | |
1551 | bl sl__string ;Add it to the block | |
1552 | blvc sl__endLink ;Terminate this link | |
1553 | bvs sl__initBlk89 ;If it failed, stop going | |
1554 | ||
1555 | ; --- Now do the kernel SWIs --- | |
1556 | ||
1557 | .sl__initBlk05 adr r0,FNlitsz("Kernel") ;Point to string `Kernel' | |
1558 | adr r1,FNlitsz("OS") ;Point to string `OS' | |
1559 | mov r2,#&0 ;Get SWI chunk number | |
1560 | bl sl__newLink ;Add in a new link block | |
1561 | bvs sl__initBlk89 ;If it failed, stop going | |
1562 | bcs sl__initBlk17 ;Already there -- skip on | |
1563 | mov r3,#0 ;Start at SWI number 0 | |
1564 | ||
1565 | .sl__initBlk10 mov r0,r3 ;Get the SWI number | |
1566 | mov r1,r11 ;Build string in scratchpad | |
1567 | mov r2,#256 ;And give the block size | |
1568 | swi "OS_SWINumberToString" ;Read the SWI name | |
1569 | swi "XOS_SWINumberFromString" ;Try to convert back | |
1570 | cmp r0,r3 ;Is this what we expected? | |
1571 | bne sl__initBlk13 ;No -- skip to end of loop | |
1572 | ||
1573 | add r0,r12,#sl__anchor ;Point to the anchor | |
1574 | add r1,r11,#3 ;Skip past `OS_' prefix | |
1575 | bl sl__string ;Add it to the list | |
1576 | bvs sl__initBlk89 ;If it failed, stop going | |
1577 | b sl__initBlk15 ;Skip past the next bit | |
1578 | ||
1579 | .sl__initBlk13 add r0,r12,#sl__anchor ;Point to the anchor | |
1580 | mov r1,#1 ;Want one extra byte | |
1581 | bl sl__ensure ;Make sure I've got it | |
1582 | bvs sl__initBlk89 ;If it failed, stop going | |
1583 | mov r14,#1 ;Mark this as nonexistant | |
1584 | strb r14,[r0],#1 ;Store it in the block | |
1585 | ||
1586 | .sl__initBlk15 add r3,r3,#1 ;Bump the SWI number | |
1587 | cmp r3,#&100 ;Reached the end yet? | |
1588 | blt sl__initBlk10 ;No -- go back round then | |
1589 | ||
1590 | ; --- Finished that; end the link block --- | |
1591 | ||
1592 | bl sl__endLink ;Terminate the link block | |
1593 | bvs sl__initBlk89 ;If it failed, stop going | |
1594 | ||
1595 | ; --- Now go through the module list --- | |
1596 | ||
1597 | .sl__initBlk17 mov r1,#0 ;Start on first module | |
1598 | .sl__initBlk20 mov r2,#0 ;Start on first instance | |
1599 | mov r0,#12 ;Enumerate module addresses | |
1600 | swi "XOS_Module" ;Read next module number | |
1601 | bvs sl__initBlk30 ;If error must have finished | |
1602 | mov r0,r3 ;Point to module base address | |
1603 | bl sl__scanMod ;Scan module for SWIs | |
1604 | bvs sl__initBlk90 ;If it failed, stop going | |
1605 | cmp r2,#0 ;Are there more instances? | |
1606 | addne r1,r1,#1 ;Yes -- move to next module | |
1607 | b sl__initBlk20 ;Go handle the next module | |
1608 | ||
1609 | ; --- Finished the module list --- | |
1610 | ||
1611 | .sl__initBlk30 bl sl__setFlags ;Reset the flags | |
1612 | ldmfd r13!,{r0-r3,r14} ;Unstack the registers | |
1613 | bics pc,r14,#V_flag ;And return without error | |
1614 | ||
1615 | ; --- Something went wrong --- | |
1616 | ||
1617 | .sl__initBlk89 mov r3,r0 ;Look after error pointer | |
1618 | add r0,r12,#sl__anchor ;Point to the anchor | |
1619 | bl flex_free ;Free the block | |
1620 | mov r1,#0 ;Clear the anchor pointer | |
1621 | str r1,[r12,#sl__anchor] ;Save it in the block | |
1622 | bl sl__setFlags ;Reset the flags nicely | |
1623 | mov r0,r3 ;And restore error pointer | |
1624 | ||
1625 | .sl__initBlk90 add r13,r13,#4 ;Don't restore R0 on exit | |
1626 | ldmfd r13!,{r1-r3,r14} ;Restore registers | |
1627 | orrs pc,r14,#V_flag ;And return the error | |
1628 | ||
1629 | FNltorg | |
1630 | ||
1631 | ; --- sl__scanMod --- | |
1632 | ; | |
1633 | ; On entry; R0 == pointer to module | |
1634 | ; | |
1635 | ; On exit; May return an error | |
1636 | ; | |
1637 | ; Use; Scans a module, and adds its SWIs to the list. | |
1638 | ||
1639 | .sl__scanMod stmfd r13!,{r0-r4,r14} ;Save some registers | |
1640 | mov r3,r0 ;Look after module base | |
1641 | ||
1642 | ; --- Make sure this module's OK --- | |
1643 | ||
1644 | ldr r0,[r3,#16] ;Load the name offset | |
1645 | ldr r1,[r3,#36] ;Load the SWI name table | |
1646 | ldr r2,[r3,#28] ;And the SWI chunk number | |
1647 | cmp r0,#256*1024 ;Make sure these are valid | |
1648 | cmpcc r1,#256*1024 ;Both offsets please | |
1649 | bcs sl__scanMod80 ;If not, ignore this module | |
1650 | ||
1651 | tst r2,#&FF000000 ;Make sure SWI chunk's OK | |
1652 | tsteq r2,#&0000003f | |
1653 | tsteq r2,#&00020000 | |
1654 | bne sl__scanMod80 ;If not, ignore this module | |
1655 | cmp r2,#&200 ;Is chunk in user range? | |
1656 | bcc sl__scanMod80 ;No -- ignore this module | |
1657 | ||
1658 | ; --- Set the file modified flag --- | |
1659 | ||
1660 | ldr r14,[r12,#sl__flags] ;Load the flags word | |
1661 | orr r14,r14,#slFlag__modified ;Set the flag | |
1662 | str r14,[r12,#sl__flags] ;Save the flags back again | |
1663 | ||
1664 | ; --- We now have a module to add --- | |
1665 | ; | |
1666 | ; For error recovery, we read the current block sizes, so | |
1667 | ; we can reset them if all goes wrong. | |
1668 | ||
1669 | add r0,r3,r0 ;Translate offset to address | |
1670 | add r1,r3,r1 ;For both offsets | |
1671 | add r14,r12,#sl__used ;Point to block size info | |
1672 | ldmia r14,{r3,r4} ;Load the size counts | |
1673 | FNflex_save("r1") ;Look after this pointer | |
1674 | bl sl__newLink ;Add a new link in | |
1675 | FNflex_load("r1") ;Restore pointer afterwards | |
1676 | bvs sl__scanMod90 ;If it failed, return error | |
1677 | ||
1678 | ; --- Now just add the SWI names in --- | |
1679 | ||
1680 | .sl__scanMod10 ldrb r14,[r1],#1 ;Load a SWI prefix byte | |
1681 | cmp r14,#0 ;Is this the end yet? | |
1682 | bne sl__scanMod10 ;No -- keep on going | |
1683 | ||
1684 | ldrb r14,[r1],#0 ;Load the next byte out | |
1685 | cmp r14,#0 ;Is this the double-0? | |
1686 | beq sl__scanMod15 ;Yes -- end right now | |
1687 | add r0,r12,#sl__anchor ;Point to anchor block | |
1688 | FNflex_save("r1") ;Save this pointer away | |
1689 | bl sl__string ;Add string to the list | |
1690 | FNflex_load("r1") ;Restore this pointer | |
1691 | bvs sl__scanMod89 ;If it failed, report error | |
1692 | b sl__scanMod10 ;Keep on adding names | |
1693 | ||
1694 | ; --- Finished that -- wrap everything up --- | |
1695 | ||
1696 | .sl__scanMod15 bl sl__endLink ;Terminate this block | |
1697 | bvs sl__scanMod89 ;If it failed, tidy up | |
1698 | .sl__scanMod80 ldmfd r13!,{r0-r4,r14} ;Restore registers | |
1699 | bics pc,r14,#V_flag ;And return with V clear | |
1700 | ||
1701 | ; --- Failed to do the job --- | |
1702 | ||
1703 | .sl__scanMod89 mov r2,r0 ;Save the error pointer | |
1704 | add r0,r12,#sl__anchor ;Point to the flex anchor | |
1705 | mov r1,r4 ;Get the old size value | |
1706 | bl flex_extend ;Reset the size | |
1707 | stmib r0,{r3,r4} ;Save old index values | |
1708 | mov r0,r2 ;Restore the error pointer | |
1709 | ||
1710 | .sl__scanMod90 add r13,r13,#4 ;Don't restore R0 on exit | |
1711 | ldmfd r13!,{r1-r4,r14} ;Restore the other registers | |
1712 | orrs pc,r14,#V_flag ;And return to caller | |
1713 | ||
1714 | FNltorg | |
1715 | ||
1716 | ; --- sl__newLink --- | |
1717 | ; | |
1718 | ; On entry; R0 == pointer to module name | |
1719 | ; R1 == pointer to SWI prefix | |
1720 | ; R2 == SWI chunk number | |
1721 | ; | |
1722 | ; On exit; May return an error | |
1723 | ; | |
1724 | ; Use; Ensures that a link block for the given module exists. If | |
1725 | ; it doesn't exist already, it is created at the end of the | |
1726 | ; flex block. The index of the last link is returned, so it | |
1727 | ; can be cleared if the actual SWI names can't be added. | |
1728 | ||
1729 | .sl__newLink stmfd r13!,{r0-r7,r14} ;Save some registers | |
1730 | ||
1731 | ; --- Set up for checking loop --- | |
1732 | ||
1733 | mov r3,r0 ;Look after module name | |
1734 | mov r4,r1 ;And the SWI prefix string | |
1735 | FNflex_save("r1,r3") ;Save these for relocation | |
1736 | add r14,r12,#sl__anchor ;Point to the anchor | |
1737 | ldmia r14,{r5,r6} ;Load base and size | |
1738 | ||
1739 | ; --- Wade on through the block --- | |
1740 | ||
1741 | mov r7,#0 ;Start at offset 0 | |
1742 | .sl__newl10 cmp r7,r6 ;Reached the end yet? | |
1743 | bcs sl__newl30 ;Yes -- better stop then | |
1744 | ||
1745 | ; --- See if this is a match --- | |
1746 | ||
1747 | add r14,r5,r7 ;Find current address | |
1748 | ldr r0,[r14,#4] ;Load the SWI chunk number | |
1749 | bic r0,r0,#&ff000000 ;Clear the flags byte | |
1750 | cmp r0,r2 ;Does this match our one? | |
1751 | bne sl__newl15 ;No -- move along then | |
1752 | ||
1753 | add r0,r14,#8 ;Point to the module name | |
1754 | mov r1,r3 ;Point to our module name | |
1755 | bl str_cmp ;Compare the strings | |
1756 | bne sl__newl15 ;No match -- move along then | |
1757 | ||
1758 | .sl__newl13 ldrb r14,[r0],#1 ;Load module name byte | |
1759 | cmp r14,#32 ;Is this the end? | |
1760 | bcs sl__newl13 ;No -- keep going | |
1761 | ||
1762 | mov r1,r4 ;Point to the SWI prefix | |
1763 | bl str_cmp ;Do these match? | |
1764 | beq sl__newl20 ;Yes -- remove this chunk | |
1765 | ||
1766 | .sl__newl15 ldr r14,[r5,r7] ;Load the length of this one | |
1767 | add r7,r7,r14 ;Move on to the next block | |
1768 | b sl__newl10 ;And keep on going | |
1769 | ||
1770 | ; --- Found a match -- remove a chunk --- | |
1771 | ||
1772 | .sl__newl20 add r0,r12,#sl__anchor ;Point to the anchor | |
1773 | ldr r2,[r5,r7] ;Get the block's size | |
1774 | add r1,r7,r2 ;Start at the end of it | |
1775 | rsb r2,r2,#0 ;And reduce block by this | |
1776 | bl flex_midExtend ;Remove this chunk of data | |
1777 | add r6,r6,r2 ;Modify the block size | |
1778 | str r6,[r12,#sl__used] ;Save this size back | |
1779 | ldr r14,[r12,#sl__size] ;Load the total block size | |
1780 | add r14,r14,r2 ;Adjust that value too | |
1781 | str r14,[r12,#sl__size] ;Store my modified value back | |
1782 | ldr r2,[r13,#8] ;Restore caller's SWI base | |
1783 | ||
1784 | ; --- Add a new chunk onto the block --- | |
1785 | ||
1786 | .sl__newl30 str r6,[r12,#sl__last] ;Save the base of this block | |
1787 | ldr r7,[r12,#sl__size] ;Get the block total size | |
1788 | ||
1789 | add r0,r12,#sl__anchor ;Point to anchor and info | |
1790 | mov r1,#8 ;Add in fixed size info | |
1791 | bl sl__ensure ;Make sure there's enough | |
1792 | strvc r2,[r0,#4] ;Save the SWI chunk number | |
1793 | ||
1794 | addvc r0,r12,#sl__anchor ;Point to anchor and info | |
1795 | FNflex_load("r1") ;Unstack module name pointer | |
1796 | blvc sl__string ;Add the string in | |
1797 | FNflex_load("r1") ;Unstack SWI prefix string | |
1798 | blvc sl__string ;Add the string in | |
1799 | ||
1800 | ldmvcfd r13!,{r0-r7,r14} ;Unstack registers | |
1801 | bicvcs pc,r14,#V_flag ;And return to caller | |
1802 | ||
1803 | ; --- It failed -- better tidy up --- | |
1804 | ||
1805 | mov r2,r0 ;Look after error number | |
1806 | add r0,r12,#sl__anchor ;Point to the anchor | |
1807 | mov r1,r7 ;Get the old size back | |
1808 | bl flex_extend ;Reset the block size | |
1809 | stmib r0,{r6,r7} ;Save the old values back | |
1810 | mov r0,r2 ;Get the error pointer | |
1811 | add r13,r13,#4 ;Don't restore R0 on exit | |
1812 | ldmfd r13!,{r1-r7,r14} ;Restore registers | |
1813 | orrs pc,r14,#V_flag ;Return the error | |
1814 | ||
1815 | FNltorg | |
1816 | ||
1817 | ; --- sl__endLink --- | |
1818 | ; | |
1819 | ; On entry; -- | |
1820 | ; | |
1821 | ; On exit; May return an error | |
1822 | ; | |
1823 | ; Use; Terminates a link block. | |
1824 | ||
1825 | .sl__endLink stmfd r13!,{r0,r1,r14} ;Save some registers | |
1826 | add r0,r12,#sl__anchor ;Find the flex block | |
1827 | mov r1,#1 ;Want to add a single byte | |
1828 | bl sl__ensure ;Make sure we've got enough | |
1829 | bvs sl__endl90 ;If it failed, return | |
1830 | ||
1831 | mov r14,#0 ;Get the NULL byte ready | |
1832 | strb r14,[r0,#0] ;Save it at the end nicely | |
1833 | add r0,r12,#sl__anchor ;Find the flex block again | |
1834 | bl sl__align ;Word align output pointer | |
1835 | ||
1836 | ldmia r0,{r0,r14} ;Load block base and size | |
1837 | ldr r1,[r12,#sl__last] ;Load the offset of the block | |
1838 | sub r14,r14,r1 ;Get the last chunk size? | |
1839 | str r14,[r0,r1] ;Save the length word | |
1840 | ||
1841 | ldmfd r13!,{r0,r1,r14} ;And return to caller | |
1842 | bics pc,r14,#V_flag ;Return without error | |
1843 | ||
1844 | .sl__endl90 add r13,r13,#4 ;Don't return R0 on exit | |
1845 | ldmfd r13!,{r1,r14} ;Restore registers | |
1846 | orrs pc,r14,#V_flag ;And return the error | |
1847 | ||
1848 | FNltorg | |
1849 | ||
1850 | ;----- Block management routines -------------------------------------------- | |
1851 | ||
1852 | ; --- sl__ensure --- | |
1853 | ; | |
1854 | ; On entry; R0 == pointer to anchor/size block | |
1855 | ; R1 == number of bytes to add | |
1856 | ; | |
1857 | ; On exit; R0 == pointer to allocated area | |
1858 | ; May return an error | |
1859 | ; | |
1860 | ; Use; Ensures that there are R1 bytes free at the end of the given | |
1861 | ; flex block. | |
1862 | ||
1863 | .sl__ensure stmfd r13!,{r1,r2,r14} ;Save some registers | |
1864 | ldmib r0,{r2,r14} ;Load the base and sizes | |
1865 | add r1,r1,r2 ;Find new total size | |
1866 | str r1,[r0,#4] ;Save this back | |
1867 | add r1,r1,#255 ;Align up to next 256 | |
1868 | bic r1,r1,#255 ;For niceness's sake | |
1869 | cmp r1,r14 ;Do we already have enough | |
1870 | bhi sl__ensure50 ;No -- allocate some more | |
1871 | .sl__ensure10 str r1,[r0,#8] ;Save new total size | |
1872 | ldr r0,[r0,#0] ;Load address of block | |
1873 | add r0,r0,r2 ;Point to first free byte | |
1874 | ldmfd r13!,{r1,r2,r14} ;Unstack registers | |
1875 | bics pc,r14,#V_flag ;And return without error | |
1876 | ||
1877 | .sl__ensure50 bl flex_extend ;Extend the block nicely | |
1878 | bcc sl__ensure10 ;Rejoin program if OK | |
1879 | bl alloc_error ;Get the error message | |
1880 | ldmfd r13!,{r1,r2,pc} ;Return error to caller | |
1881 | ||
1882 | FNltorg | |
1883 | ||
1884 | ; --- sl__string --- | |
1885 | ; | |
1886 | ; On entry; R0 == pointer to flex block and size information | |
1887 | ; R1 == pointer to string | |
1888 | ; | |
1889 | ; On exit; May return an error | |
1890 | ; | |
1891 | ; Use; Adds a string to a flex block. | |
1892 | ||
1893 | .sl__string stmfd r13!,{r0-r3,r14} ;Save some registers | |
1894 | mov r2,r0 ;Look after anchor address | |
1895 | FNflex_save("r1") ;Save the string address | |
1896 | mov r0,r1 ;Point to the string | |
1897 | bl str_len ;Work out the length | |
1898 | add r1,r0,#1 ;Get the required size | |
1899 | mov r0,r2 ;Point to anchor and sizes | |
1900 | bl sl__ensure ;Make sure the space is OK | |
1901 | FNflex_load("r1") ;Restore R1 from stack | |
1902 | blvc str_cpy ;And copy it into the block | |
1903 | strvs r0,[r13,#0] ;Otherwise store the error | |
1904 | ldmfd r13!,{r0-r3,pc} ;And return to caller | |
1905 | ||
1906 | FNltorg | |
1907 | ||
1908 | ; --- sl__align --- | |
1909 | ; | |
1910 | ; On entry; R0 == pointer to flex anchor and size info | |
1911 | ; | |
1912 | ; On exit; -- | |
1913 | ; | |
1914 | ; Use; Word aligns the output pointer of a flex block. | |
1915 | ||
1916 | .sl__align stmfd r13!,{r14} ;Save a register | |
1917 | ldr r14,[r0,#4] ;Load the output offset | |
1918 | add r14,r14,#3 ;Word align this offset | |
1919 | bic r14,r14,#3 ;Mask off bottom bits | |
1920 | str r14,[r0,#4] ;Store new offset back | |
1921 | ldmfd r13!,{pc}^ ;And return to caller | |
1922 | ||
1923 | FNltorg | |
1924 | ||
1925 | ;----- Workspace ------------------------------------------------------------ | |
1926 | ] | |
1927 | PROCws_start | |
1928 | ||
1929 | sl__flags =FNws_word :REM ;Various flags bits | |
1930 | sl__anchor =FNws_word :REM ;Flex anchor for SWI table | |
1931 | sl__used =FNws_word :REM ;Size used in flex block | |
1932 | sl__size =FNws_word :REM ;Actual size of flex block | |
1933 | sl__last =FNws_word :REM ;Offset of last block | |
1934 | sl__modNames =FNws_word :REM ;Block for module names | |
1935 | sl__format =FNws_word :REM ;Format chunk handle | |
1936 | sl__module =FNws_word :REM ;Anchor for loading modules | |
1937 | sl__pollBlock =FNws (256) :REM ;Wimp_Poll data block | |
1938 | sl__dumpFile =FNws (256) :REM ;Full pathname of dump file | |
1939 | ||
1940 | sl__wSize =FNws (0) | |
1941 | ||
1942 | slFlag__block = (1<<0) :REM ;We have a SWI block | |
1943 | slFlag__format = (1<<1) :REM ;There is a format | |
1944 | slFlag__savable = (1<<2) :REM ;We can save a SWI list | |
1945 | slFlag__modified= (1<<3) :REM ;SWI block is unsaved | |
1946 | slFlag__saving = (1<<4) :REM ;We're saving a dump | |
1947 | ||
1948 | [ opt o | |
1949 | ||
1950 | ] | |
1951 | NEXT | |
1952 | ||
1953 | PROCbas_aofSave | |
1954 | END | |
1955 | ||
1956 | REM -- Macros --------------------------------------------------------------- | |
1957 | ||
1958 | DEF FNs(s$) | |
1959 | [ opt 4 | |
1960 | equs s$ | |
1961 | dcb 0 | |
1962 | ] | |
1963 | =0 | |
1964 | DEFFNP(i%):PRINT~i%:=0 |