REM REM swiList.bs REM REM Build SWI name include files REM REM © 1995 Straylight REM REM -- Standard header ------------------------------------------------------ ON ERROR ERROR 0,"*** ERROR: "+REPORT$+" ["+STR$(ERL)+"]" LIBRARY "libs:BAS" PROCbas_init PROCbas_aofInit(&8000) V_flag=1<<28 C_flag=1<<29 FOR o=4 TO 6 STEP 2 [ opt o FNpass ;----- Revision history ----------------------------------------------------- ; ; Version By Change ; ; 1.xx MDW Old version written in C using STEEL. ; ; 2.00 MDW Rewrite from scratch in assembler using Sapphire. ; Keep SWI names in flex block, allow user format ; files, and add SWIs from modules dropped onto icon. ; ; 2.01 MDW Replaced format file loading with a chunk file, to ; support multiple programming languages. Added ; submenu to `Save list' for selecting which language ; to use. ; ; 2.02 MDW Added %d format specifier to output generation time/ ; date in given style. Also added revision history ;-) ; ; 2.03 MDW Added confirm on quit option, and prevented saving ; a dump from SWIList back into itself. ; ; 2.04 MDW Tidied up initialisation a little, and made it ; register the heap routines as allocators for smaller ; WimpSlot. ; ; 2.05 MDW Fiddled help message generation a little to (a) ; do message translation of the format names and (b) ; use %0 rather than the less pretty %9 in the help ; skeleton. ; ; 2.06 MDW Added full pathname for dump save, so you don't have ; to dig up the application to save the dump each time. ; ; 2.07 MDW Used SEH for error handling, instead of raw except- ; level stuff. ;----- External dependencies ------------------------------------------------ ; --- Sapphire library --- FNget ("sapphire:alloc") FNget ("sapphire:buttons") FNget ("sapphire:chunk") FNget ("sapphire:defHandler") FNget ("sapphire:errorBox") FNget ("sapphire:event") FNget ("sapphire:fastMove") FNget ("sapphire:flex") FNget ("sapphire:heap") FNget ("sapphire:help") FNget ("sapphire:hour") FNget ("sapphire:ibicon") FNget ("sapphire:libOpts") FNget ("sapphire:menu") FNget ("sapphire:menuDefs") FNget ("sapphire:msgs") FNget ("sapphire:note") FNget ("sapphire:progInfo") FNget ("sapphire:ptr") FNget ("sapphire:report") FNget ("sapphire:res") FNget ("sapphire:resources") FNget ("sapphire:sapphire") FNget ("sapphire:seh") FNget ("sapphire:string") FNget ("sapphire:warning") FNget ("sapphire:choices.choices") FNget ("sapphire:xfer.load") FNget ("sapphire:xfer.saveAs") FNget ("sapphire:xfer.save") FNget ("sapphire:xfer.xsave") ; --- Link-time generated strings --- FNimport("cright") FNimport("version") ;----- Initialisation ------------------------------------------------------- FNarea ("Client$$Code","CODE,READONLY") ; --- main --- ; ; On entry; -- ; ; On exit; Via OS_Exit ; ; Use; Allows saving of header files containing SWI name-number ; mappings. .main FNentry adr r0,FNlitsz("SWIList") ;Point to application name mov r1,#sl__wSize ;Get my workspace size mov r2,#0 ;Default stack size bl sapphire_init ;Start up the library bl sl__preInit ;Do pre-initialisation stuff bl sapphire_libInit ;Initialise rest of library bl sl__init ;Initialise me bl seh_throwErrors ;Make errors throw exceptions bl report_catchAll ;And catch exceptions .sl__pollLoop mov r0,#1 ;Don't have idle events add r1,r12,#sl__pollBlock ;Point to the poll block bl event_poll ;Handle an event blcc sl__unknowns ;Handle unknown events blcc defHandler ;Pass it on if unrecognised b sl__pollLoop ;And carry on round forever FNltorg ; --- sl__preInit --- ; ; On entry; -- ; ; On exit; R0-R10 corrupted ; ; Use; Does initialisation of things before the main Sapphire ; library awakes. .sl__preInit stmfd r13!,{r14} ;Save a register away bl resources_init ;Use shared resource DLL bl hour_init ;Wake up the hourglass system bl hour_on ;And turn it on ldr r0,[r11,#sapph_appName] ;Find the application name bl heap_init ;Initialise the resizing heap bl heap_useHeap ;Register it as an allocator adr r0,sl__sapphOpts ;Point to options block bl libOpts_register ;Register the options ldmfd r13!,{pc}^ ;Return to caller when done .sl__sapphOpts FNlibOpt("MENU") dcd 8192 FNlibOpts_end FNltorg ; --- sl__init --- ; ; On entry; -- ; ; On exit; -- ; ; Use; Initialises SWIList's workspace. .sl__init stmfd r13!,{r14} ;Save some registers bl sl__initWS ;Set up my workspace bl sl__loadFormat ;Load the user's format file bl sl__initList ;Create the SWI list bl sl__iconBar ;Create my icon bl sl__setFlags ;Finally set the flags up ldmfd r13!,{pc}^ ;And return to caller FNltorg ; --- sl__initWS --- ; ; On entry; -- ; ; On exit; R0-R10 corrupted ; ; Use; Initialises the application's workspace. .sl__initWS stmfd r13!,{r14} ;Save the link register mov r14,#0 ;Zero the anchor pointer str r14,[r12,#sl__flags] ;Clear the flags initially str r14,[r12,#sl__anchor] ;Say we have no block yet str r14,[r12,#sl__modNames] ;No module name table str r14,[r12,#sl__format] ;No format loaded yet ldmfd r13!,{pc}^ ;And return to caller FNltorg ; --- sl__loadFormat --- ; ; On entry; -- ; ; On exit; R0-R10 corrupted ; ; Use; Loads SWIList's format file. .sl__loadFormat stmfd r13!,{r14} ;Save the link register ; --- Enable the Choices support --- mov r0,#1 ;Enable `Choices' support bl choices_useChoices ;Allow read-only use nicely ; --- Create the format chunk file --- bl chunk_create ;Create a chunk file swivs "OS_GenerateError" ;Be unhappy if it fails str r0,[r12,#sl__format] ;Save this away ; --- Now do the actual load operation --- adr r0,FNlitsz("Format") ;Point to the leafname mov r1,r11 ;Build name in scratchpad mov r2,#0 ;I want to read the file bl choices_find ;Translate the name mov r1,r0 ;Point to the name sub r13,r13,#4 ;Make a flex anchor mov r2,r13 ;Point to this anchor bl load_file ;Load the file into it ldrvc r0,[r12,#sl__format] ;Find the format handle movvc r1,r13 ;And point to the anchor blvc chunk_read ;Add that to the chunks mov r0,r13 ;Point to that anchor again bl flex_free ;Get rid of the block add r13,r13,#4 ;And restore the stack ; --- Set flag if any format chunks found --- ldr r0,[r12,#sl__format] ;Find the format handle mov r1,#0 ;Start enumerating bl chunk_enum ;Are there any chunks? ldrcc r14,[r12,#sl__flags] ;Yes -- get the flags orrcc r14,r14,#slFlag__format ;Set the format flag strcc r14,[r12,#sl__flags] ;And save them back again ldmfd r13!,{pc}^ ;Return to caller when done FNltorg ; --- sl__initList --- ; ; On entry; -- ; ; On exit; R0-R10 corrupted ; ; Use; Initialises the SWI table, either by loading a saved dump ; or by scanning the modules in memory. .sl__initList stmfd r13!,{r14} ;Save the link register adr r0,FNlitsz("SWIDump") ;Point to the leafname mov r1,r11 ;Build name in scratchpad mov r2,#0 ;I want to read the file bl choices_find ;Translate the name mov r1,r0 ;Point to the name bl sl__loadDmp ;Load the default dump blvc sl__doneDmp ;If OK, set the rest up blvs sl__initBlock ;Otherwise, scan the modules ldmfd r13!,{pc}^ ;Return to caller when done FNltorg ; --- sl__iconBar --- ; ; On entry; -- ; ; On exit; -- ; ; Use; Sets up the icon bar icon. .sl__iconBar stmfd r13!,{r0-r6,r14} ;Save some registers adr r0,FNlitsz("!swilist") ;Point to sprite to use mov r1,#0 ;No text buffer here mvn r2,#NOT(-1) ;Put icon on the left mov r3,#0 ;Normal priority please adr r4,sl__ibEvents ;Point to event handler mov r5,#0 ;Pass no document handle mov r6,r12 ;Pass workspace pointer bl ibicon_create ;Create the icon nicely swivs "OS_GenerateError" ;If it failed, halt program ldmfd r13!,{r0-r6,pc}^ ;And return to caller FNltorg ; --- sl__ibEvents --- ; ; On entry; R0 == event code ; ; On exit; -- ; ; Use; Handles events for the icon bar icon. .sl__ibEvents cmp r0,#(sl__ibe10-sl__ibe00)/4 addcc pc,pc,r0,lsl #2 ;Dispatch through branch tbl movs pc,r14 ;Ignore unknown events .sl__ibe00 movs pc,r14 ;Ignore Select clicks b sl__ibMenu ;Handle a menu click movs pc,r14 ;Ignore Adjust clicks b sl__ibLoad ;Handle a load/save request b sl__ibLoad ;We treat them all the same b sl__ibHelp ;Handle a help request .sl__ibe10 ; --- Handle a menu click --- .sl__ibMenu stmfd r13!,{r0-r3,r14} ;Save some registers adr r0,sl__imDef ;Point to the menu definition adr r1,sl__imEvents ;Point to menu handler code mov r2,r10 ;Pass it the doc handle mov r3,r12 ;And my workspace address bl menu_create ;Display the menu nicely ldmfd r13!,{r0-r3,pc}^ ;And return to caller .sl__imDef FNmenu("SWIList") FNmenu_item("slINF") FNmenu_subWarn FNmenu_ruleOff FNmenu_item("slSVL") FNmenu_r12Data FNmenu_iShade(sl__flags,slFlag__savable) FNmenu_subWarn FNmenu_noWarn FNmenu_item("slSVD") FNmenu_r12Data FNmenu_iShade(sl__flags,slFlag__block) FNmenu_subWarn FNmenu_noWarn FNmenu_item("slSCN") FNmenu_item("slRFM") FNmenu_subWarn FNmenu_ruleOff FNmenu_item("slQUT") FNmenu_end ; --- Handle a help request --- .sl__ibHelp stmfd r13!,{r0,r14} ;Save some registers adr r0,FNlitsz("slhIB") ;Point to a message tag bl msgs_lookup ;Translate the tag bl help_add ;And add it to the help ldmfd r13!,{r0,pc}^ ;Return to caller ; --- Handle a load event --- .sl__ibLoad stmfd r13!,{r0-r2,r14} ;Save some registers bl event_last ;Find the last event ldr r0,[r1,#40] ;Load the filetype ldr r14,FNlitw(&FFA) ;Get the module filetype cmp r0,r14 ;Do these match beq sl__ibLdMod ;Yes -- handle that then ldr r14,FNlitw(&FFD) ;Get the data filetype cmp r0,r14 ;Do these match beq sl__ibLdDump ;Yes -- handle that then ldmfd r13!,{r0-r2,pc}^ ;Return to caller ; --- Handle loading a module --- .sl__ibLdMod adr r0,sl__lMod ;Point to load block mov r1,r10 ;Get document handle mov r2,r12 ;And workspace address bl load ;Do the load operation ldmfd r13!,{r0-r2,pc}^ ;And return when done .sl__lMod b sl__ibMod b load_killBuf b load_extendBuf b load_doneBuf b sl__loadMod b sl__doneMod b sl__lfMod ; --- Handle loading a dump --- .sl__ibLdDump ldr r14,[r12,#sl__flags] ;Load the flags word tst r14,#slFlag__saving ;Are we saving currently? bne sl__ild50 ;Yes -- moan at user then adr r0,sl__lDmp ;Point to load block mov r1,r10 ;Get document handle mov r2,r12 ;And workspace address bl load ;Yes -- start a load op ldmfd r13!,{r0-r2,pc}^ ;And return to caller .sl__ild50 adr r0,FNliterr(1,"slCSII") ;Point to error block bl msgs_error ;Translate the message mov r1,#1 ;Only display OK button bl errorBox ;Display the error ldmfd r13!,{r0-r2,pc}^ ;And return to caller .sl__lDmp b sl__ibDmp b load_killBuf b load_extendBuf b load_doneBuf b sl__loadDmp b sl__doneDmp b sl__lfDmp FNltorg ; --- sl__imEvents --- ; ; On entry; R0 == event code ; R1 == item number ; ; On exit; -- ; ; Use; Handles events from the icon bar menu. .sl__imEvents cmp r0,#mEvent_help ;A help request, perchance? beq sl__imHelp ;Yes -- deliver help on it cmp r0,#mEvent_select ;Is this a select event? cmpne r0,#mEvent_subMenu ;Or a submenu opening? movnes pc,r14 ;No -- ignore the event cmp r1,#(sl__ime10-sl__ime00)/4 addcc pc,pc,r1,lsl #2 ;Dispatch by item number movs pc,r14 ;Ignore unknown item numbers .sl__ime00 b sl__imInfo ;Display the info box b sl__imSave ;Save the SWI list b sl__imDump ;Save a SWI dump b sl__initBlock ;Reset the block b sl__imRefresh ;Refresh a particular module b sl__imQuit ;Close down the program .sl__ime10 ; --- Send a help message --- .sl__imHelp stmfd r13!,{r0,r14} ;Save some registers adr r0,FNlitsz("slhIM") ;Find the message base tag bl menu_help ;Give help on the item ldmfd r13!,{r0,pc}^ ;And return to caller ; --- Display the info window --- .sl__imInfo stmfd r13!,{r0-r2,r14} ;Save some registers adr r0,FNlitsz("slPUR") ;Point to purpose message bl msgs_lookup ;Translate message tag ldr r1,FNlitw(cright) ;Find the copyright string ldr r2,FNlitw(version) ;And the version string bl progInfo ;Display the box movvs r1,#1 ;If it failed, display error blvs errorBox ;In a pretty error box ldmfd r13!,{r0-r2,pc}^ ;And return to caller FNltorg ; --- Dislplay the menu of formats --- .sl__imSave cmp r0,#mEvent_subMenu ;Make sure this is a submenu movnes pc,r14 ;No -- not interested stmfd r13!,{r0-r5,r14} ;Save some registers adr r0,sl__fmtTitle ;Point to the title mov r1,#0 ;No handler for that bl menu_create ;Set that up to display ldr r4,[r12,#sl__format] ;Load the format chunk file mov r1,#0 ;Read first chunk name .loop mov r0,r4 ;Pop it in R0 for a bit bl chunk_enum ;Get the next chunk ldmcsfd r13!,{r0-r5,pc}^ ;Return when finished str r2,[r1,#4] ;Save pointer to name mov r2,r1 ;Point to the anchor mov r5,r1 ;Look after continuation adr r0,sl__fmtMenu ;Point to menu skeleton adr r1,sl__fmtHandler ;Point to handler routine mov r3,r12 ;Pass workspace in R12 bl menu_create ;Add that to the list mov r1,r5 ;Get the continuation value b loop ;And go back to the loop .sl__fmtTitle FNmenu("slSVFT") FNmenu_end .sl__fmtMenu FNmenu_itemInd(4) FNmenu_subWarn FNmenu_end FNltorg ; --- Dislplay the dump box --- .sl__imDump stmfd r13!,{r0-r5,r14} ;Save some registers ldr r0,[r12,#sl__used] ;Load the actual block size ldr r1,FNlitw(&ffd) ;Output as a data file add r2,r12,#sl__dumpFile ;Point to the dump file name adr r3,sl__dumpDef ;Point to handler block mov r4,r10 ;Pass document handle mov r5,r12 ;And pass the workspace addr bl saveAs ;Try to do the save op bvs sl__imd90 ;Tidy up if it failed ldr r14,[r12,#sl__flags] ;Load the current flags orr r14,r14,#slFlag__saving ;Say we're now saving str r14,[r12,#sl__flags] ;Save the flags back again ldmfd r13!,{r0-r5,pc}^ ;And return to caller .sl__imd90 mov r1,#1 ;If it failed, report error bl errorBox ;In a nice error box ldmfd r13!,{r0-r5,pc}^ ;And return to caller .sl__dumpDef FNs ("slSDT") ;Title for the save box b sl__svdDone ;Handle box closing b sl__saveDump ;Save to a disk file b sl__sendDump ;Send to another application movs pc,r14 ;Ignore completion b sl__svdFail ;Tidy up after a failure FNltorg ; --- Display a menu of modules to refresh --- .sl__imRefresh cmp r0,#mEvent_subMenu ;Is this a submenu? movnes pc,r14 ;No -- go away then stmfd r13!,{r0-r7,r14} ;Save some registers ; --- Free the old title block --- ldr r0,[r12,#sl__modNames] ;Load the pointer cmp r0,#0 ;Is the block allocated? blne free ;Yes -- deallocate it them movne r14,#0 ;And clear the pointer out strne r14,[r12,#sl__modNames] ;Done that ; --- Enumerate interesting modules --- mov r6,#0 ;Size of block required mov r1,#0 ;Start at the beginning ; --- Read the next module --- .loop mov r0,#12 ;Enumerate module names mov r2,#0 ;Not interested in instances swi "XOS_Module" ;Read the next module bvs sl__imRefAlloc ;No more -- go to next phase ; --- Update the arguments for next call --- cmp r2,#0 ;Is there another instance? addne r1,r1,#1 ;No -- update manually ; --- See whether this module was interesting --- ldr r14,[r3,#&20] ;Load the SWI handler offset cmp r14,#0 ;Does this look sensible? addne r6,r6,#8 ;Yes -- add another word b loop ;Get more modules ; --- Allocate the block --- .sl__imRefAlloc mov r0,r6 ;Get the required size bl alloc ;Allocate the block blcs alloc_error ;If it failed, point to error bcs sl__imRefError ;And handle that str r0,[r12,#sl__modNames] ;Store pointer for later mov r7,r0 ;Point to the block start ; --- Set up the title block --- adr r0,sl__rfmTitle ;Point to the title block adr r1,sl__rfmKernel ;Point to event handler mov r2,r10 ;Pass my R10 value mov r3,r12 ;And my R12 value bl menu_create ;Create the title ; --- Initialise for module scanning --- mov r6,#0 ;Current module number ; --- Read the next module --- .loop mov r0,#12 ;Enumerate module names mov r1,r6 ;Get next module number mov r2,#0 ;And next module name swi "XOS_Module" ;Read the next module ldmvsfd r13!,{r0-r7,pc}^ ;Return when done ; --- Update the arguments for next call --- cmp r2,#0 ;Is there another instance? moveq r6,r1 ;Yes -- store it normally addne r6,r1,#1 ;No -- update manually ; --- See whether this module was interesting --- ldr r14,[r3,#&20] ;Load the SWI handler offset cmp r14,#0 ;Does this look sensible? beq loop ;No -- loop round for more ; --- Add the menu item for this module --- ldr r14,[r3,#&10] ;Load the module name offset add r14,r3,r14 ;Add this on to the base stmia r7!,{r3,r14} ;Store base and name string adr r0,sl__rfmItem ;Point to the menu block adr r1,sl__rfmModule ;Point to the handler sub r2,r7,#8 ;Point to name pointer mov r3,r12 ;And get my workspace addr bl menu_create ;Add to the current menu b loop ;Keep on looping ; --- Report an error --- .sl__imRefError add r2,r0,#4 ;Point to error message adr r0,FNliterr(1,"slMLE") ;Point to skeleton bl str_error ;Mangle the message mov r1,#1 ;Just an OK button bl errorBox ;Report the message ldmfd r13!,{r0-r7,pc}^ ;And return to caller ; --- Refresh module title --- .sl__rfmTitle FNmenu("slMDS") ;FNmenu_item("slKNL") ;Not implemented FNmenu_end ; --- Refresh module items --- .sl__rfmItem FNmenu_itemInd(4) FNmenu_end FNltorg ; --- Quit the application --- .sl__imQuit stmfd r13!,{r14} ;Save return address away bl sl__okToQuit ;Make sure it's all right swics "OS_Exit" ;Yes -- just kill everything ldmfd r13!,{pc}^ ;Otherwise ignore the request FNltorg ; --- sl__rfmKernel --- ; ; On entry; -- ; ; On exit; -- ; ; Use; Refreshes the kernel SWIs table. .sl__rfmKernel movs pc,r14 ;Not implemented FNltorg ; --- sl__rfmModule --- ; ; On entry; -- ; ; On exit; -- ; ; Use; Refreshes a particular module. .sl__rfmModule stmfd r13!,{r0,r1,r14} ;Save link ldr r0,[r10,#0] ;Load module base bl sl__scanMod ;Scan the module movvs r1,#1 ;If it failed blvs errorBox ;Report the error ldmfd r13!,{r0,r1,pc}^ ;And return to caller FNltorg ; --- sl__setFlags --- ; ; On entry; -- ; ; On exit; -- ; ; Use; Sets up the flags from the flex anchors we have. .sl__setFlags stmfd r13!,{r0,r14} ;Save some registers ldr r0,[r12,#sl__flags] ;Load the flags word ldr r14,[r12,#sl__anchor] ;Load the block anchor cmp r14,#0 ;Is that defined? orrne r0,r0,#slFlag__block ;Yes -- set the flag biceq r0,r0,#slFlag__block ;No -- clear it tstne r0,#slFlag__format ;Is there a format chunk? orrne r0,r0,#slFlag__savable ;Yes -- set savable flag biceq r0,r0,#slFlag__savable ;No -- clear it then str r0,[r12,#sl__flags] ;Save modified flags ldmfd r13!,{r0,pc}^ ;And return to caller FNltorg ; --- sl__unknowns --- ; ; On entry; R0 == event code ; R1 == pointer to event data ; ; On exit; CS if event interesting, else CC ; R2-R10 corrupted ; ; Use; Handles interesting messages (e.g. PreQuit) .sl__unknowns cmp r0,#17 ;Is this a User_Message? cmpne r0,#18 ;Or a User_Message_Recorded? movnes pc,r14 ;No -- ignore it then ldr r2,[r1,#16] ;Load the event code cmp r2,#8 ;Is this a pre-quit message? movnes pc,r14 ;No -- not interested then ; --- Handle a PreQuit message --- orrs r14,r14,#C_flag ;We claim this event now stmfd r13!,{r14} ;Save return address bl sl__okToQuit ;Ask user if required ldmcsfd r13!,{pc}^ ;If OK then continue normally stmfd r13!,{r0-r2} ;Save some more registers mov r0,r11 ;Point to scratchpad ldr r2,[r1,#0] ;Load the message size bl fastMove ;Copy the message data over ldr r14,[r0,#8] ;Load his reference number str r14,[r0,#12] ;Set this as a reply to it mov r1,r0 ;Point to my copy mov r0,#19 ;Send this as an acknowledge ldr r2,[r1,#4] ;Load his task handle out swi "Wimp_SendMessage" ;Send the message back ldmfd r13!,{r0-r2,pc}^ ;Now return to caller FNltorg ; --- sl__okToQuit --- ; ; On entry; -- ; ; On exit; CS if we're allowed to quit, else CC ; ; Use; Works out if we're allowed to quit the application. If it ; isn't sure, it pops up a warning box and asks. .sl__okToQuit stmfd r13!,{r0,r1,r14} ;Save some registers ldr r14,[r12,#sl__flags] ;Load the flags word out tst r14,#slFlag__modified ;Has the block been changed? beq sl__otq90 ;No -- then skip onwards adr r0,FNlitsz("slOTQ") ;Point to warning messae bl msgs_lookup ;Translate the tag adr r1,sl__quitButts ;Point to buttons block bl warning ;Pop up the warning box ldmfd r13!,{r0,r1,r14} ;Unstack the registers orrcss pc,r14,#C_flag ;If OK, set the C flag bicccs pc,r14,#C_flag ;Otherwise clear it .sl__otq90 ldmfd r13!,{r0,r1,r14} ;Unstack the registers orrs pc,r14,#C_flag ;Set C -- we're OK .sl__quitButts FNbutton("slQUTB") FNbuttons_cancel FNbuttons_end FNltorg ;----- Save a SWI file ------------------------------------------------------ ; --- sl__fmtHandler --- ; ; On entry; R0 == menu event ; R1 == menu item ; R10 == pointer to chunk name ; ; On exit; -- ; ; Use; Handles events on the save menu. .sl__fmtHandler cmp r0,#mEvent_help ;Is this a help request? beq sl__fmtHelp ;Yes -- give help then cmp r0,#mEvent_subMenu ;Is this a submenu? cmpne r0,#mEvent_select ;Or a click? movnes pc,r14 ;No -- ignore this stmfd r13!,{r0-r5,r14} ;Save some registers ldr r0,[r12,#sl__used] ;Load the actual block size ldr r1,FNlitw(&fff) ;Output as a data file adr r2,FNlitsz("swis") ;Point to the dummy name adr r3,sl__saveDef ;Point to handler block mov r4,r10 ;Pass document handle mov r5,r12 ;And pass the workspace addr bl saveAs ;Try to do the save op movvs r1,#1 ;If it failed, report error blvs errorBox ;In a nice error box ldmfd r13!,{r0-r5,pc}^ ;And return to caller .sl__saveDef FNs ("slSVT") ;Title for the save box movs pc,r14 ;Don't care when it closes b sl__saveFile ;Save to a disk file b sl__send ;Send to another application b xsave_done ;Tell xsave it's all done b sl__failed ;Tidy up after a failure .sl__fmtHelp stmfd r13!,{r0-r2,r14} ;Save some registers ldr r0,[r10,#4] ;Find the format chunk name bl msgs_lookup ;Translate in case of tag mov r1,r0 ;Point to the result mov r0,r11 ;Point to scratchpad bl str_cpy ;Copy the string over .loop ldrb r14,[r0,#-1]! ;Load last byte of string subs r14,r14,#ASC(".") ;Is it part of an ellipsis? streqb r14,[r0,#0] ;Yes -- nobble that byte beq loop ;And try again adr r0,FNlitsz("slhSVF") ;Point to help message tag bl msgs_lookup ;Translate the message bl str_buffer ;Find an output buffer mov r2,r11 ;Point to scratchpad string bl str_subst ;And build the help string bl help_add ;Add this to help message ldmfd r13!,{r0-r2,pc}^ ;Return to caller FNltorg ; --- sl__saveFile --- ; ; On entry; R0 == pointer to file name ; R1 == safe flag ; ; On exit; -- ; ; Use; Saves the SWI block to a file. .sl__saveFile stmfd r13!,{r0-r5,r14} ;Save some registers mov r2,#0 ;No current name for this bl sl__replace ;Do we replace the file? movcc r0,#0 ;No -- return null error bcc sl__sf20 ;But cancel the save op ; --- Get on with saving the file --- .sl__sf10 mov r3,r0 ;Look after the file name adr r0,sl__writeList ;Point to saver routine mov r1,r10 ;Pass it the document handle mov r2,r12 ;And my workspace pointer ldr r4,FNlitw(&FFF) ;Pass the filetype over bl xsave_save ;Try to save the file bvs sl__sf20 ;If failed, abort now ; --- Now retrostamp the file --- mov r0,#17 ;Read info on the file mov r1,r3 ;Point to the filename swi "XOS_File" ;Read info on the file movvc r0,#1 ;Now we set the info bicvc r2,r2,#&FF ;Leave filetype alone orrvc r2,r2,#&3A ;Put in our dummy datestamp ldrvc r3,FNlitw(&BD896000) ;Set up rest of datestamp swivc "XOS_File" ;Now retrostamp it nicely ldmvcfd r13!,{r0-r5,pc}^ ;If it worked OK, return ; --- It failed --- .sl__sf20 add r13,r13,#4 ;Don't restore R0 on exit ldmfd r13!,{r1-r5,r14} ;Unstack saved registers orrs pc,r14,#V_flag ;And return to caller FNltorg ; --- sl__send --- ; ; On entry; R2 == accumulator value (initially 0) ; ; On exit; R0 == pointer to block to send ; R1 == size of block to send ; CS if this is the last block, else CC ; ; Use; Sends a block of data to another application. .sl__send adr r0,sl__writeList ;Point to my saver routine mov r1,r10 ;Pass the document handle mov r2,r12 ;Pass my workspace too b xsave_send ;And get another block FNltorg ; --- sl__failed --- ; ; On entry; R0 == pointer to error, or 0 ; R1 == 1 ; ; On exit; -- ; ; Use; Terminates a save job, and reports an error. .sl__failed stmfd r13!,{r0-r2,r14} ;Save some registers bl xsave_failed ;Tell xsave it's finished cmp r0,#0 ;Is there an actual error? addne r2,r0,#4 ;Point to error text adrne r0,FNliterr(1,"slSFE") blne msgs_error ;Translate and substitute movne r1,#1 ;Display just an OK button blne errorBox ;Yes -- report it then ldmfd r13!,{r0-r2,pc}^ ;Return to caller FNltorg ; --- sl__replace --- ; ; On entry; R0 == filename ; R1 == safeness flag ; R2 == pointer to current name, or 0 ; ; On exit; -- ; ; Use; CS to save, CC to cancel .sl__replace stmfd r13!,{r0-r2,r14} ;Save some registers cmp r1,#0 ;Is the file marked as safe? beq sl__replace10 ;No -- then don't ask movs r1,r2 ;Is there a current name? beq sl__replace05 ;No -- can't do this check bl str_icmp ;Compare the file names beq sl__replace10 ;The same name -- don't ask .sl__replace05 bl res_exists ;Does the file exist? bcc sl__replace10 ;No -- then don't ask ; --- Ask the user if this is right --- mov r2,r0 ;Get the filename pointer adr r0,FNlitsz("slRPP") ;Point to the prompt message bl msgs_lookup ;Translate the message bl str_buffer ;Find a handy string buffer bl str_subst ;Build the prompt string adr r1,sl__exWarn ;Point to the buttons def bl warning ;Display the warning box ldmccfd r13!,{r0-r2,r14} ;If no, abort the job bicccs pc,r14,#C_flag ;Tell caller it's all off .sl__replace10 ldmfd r13!,{r0-r2,r14} ;Restore registers orrs pc,r14,#C_flag ;And let it all go ahead .sl__exWarn FNbutton("slRPL") FNbuttons_cancel FNbuttons_end FNltorg ;----- Write out a dump file ------------------------------------------------ ; --- sl__svdDone --- ; ; On entry; -- ; ; On exit; -- ; ; Use; Handles the save box closing. We allow loads of dump files ; again. .sl__svdDone stmfd r13!,{r14} ;Save some registers ldr r14,[r12,#sl__flags] ;Load the flags word bic r14,r14,#slFlag__saving ;Turn off the saving flag str r14,[r12,#sl__flags] ;Save the flags back ldmfd r13!,{pc}^ ;And return to caller FNltorg ; --- sl__saveDump --- ; ; On entry; R0 == pointer to file name ; R1 == safeness flag ; ; On exit; -- ; ; Use; Saves a dump of the current SWI names .sl__saveDump stmfd r13!,{r0-r5,r14} ;Save some registers add r2,r12,#sl__dumpFile ;Point to current name bl sl__replace ;Do we actually do this? movcc r0,#0 ;If not, return null error bcc sl__saved90 ;To cancel the save op mov r1,r0 ;Point to the filename mov r0,#10 ;Save memory as a file ldr r2,FNlitw(&FFD) ;Save as a data file add r14,r12,#sl__anchor ;Point to dump anchor ldmia r14,{r4,r5} ;Load base and size add r5,r4,r5 ;Turn size into limit swi "XOS_File" ;Try to save the file bvs sl__saved90 ;If it failed, abort ldr r14,[r13,#4] ;Load the safeness flag cmp r14,#0 ;Is the flag safe? beq sl__saved50 ;No -- skip onwards then ; --- Do special things when file saved properly --- ldr r14,[r12,#sl__flags] ;Yes -- load flags then bic r14,r14,#slFlag__modified ;Clear the modified bit str r14,[r12,#sl__flags] ;And store the flags back bl sl__setDumpName ;Go and set the name .sl__saved50 ldmfd r13!,{r0-r5,pc}^ ;Return to caller .sl__saved90 add r13,r13,#4 ;Don't restore R0 on exit ldmfd r13!,{r1-r5,r14} ;Restore registers orrs pc,r14,#V_flag ;And return with V set FNltorg ; --- sl__sendDump --- ; ; On entry; -- ; ; On exit; R0 == pointer to block to send ; R1 == size of block ; CS for last block, CC otherwise ; ; Use; Sends the SWI dump block to another application .sl__sendDump add r0,r12,#sl__anchor ;Find the anchor block ldmia r0,{r0,r1} ;Load the values out orrs pc,r14,#C_flag ;And return the only block FNltorg ; --- sl__svdFail --- ; ; On entry; R0 == pointer to error, or 0 ; R1 == 1 ; ; On exit; -- ; ; Use; Terminates a save job, and reports an error. .sl__svdFail stmfd r13!,{r0-r2,r14} ;Save some registers cmp r0,#0 ;Is there an actual error? addne r2,r0,#4 ;Point to error text adrne r0,FNliterr(1,"slSDE") blne msgs_error ;Translate and substitute movne r1,#1 ;Display just an OK button blne errorBox ;Yes -- report it then ldmfd r13!,{r0-r2,pc}^ ;Return to caller FNltorg ;----- Writing out a list of SWIs ------------------------------------------- ; --- sl__writeList --- ; ; On entry; -- ; ; On exit; -- ; ; Use; Writes the list of SWIs to the current xsave output. .sl__writeList stmfd r13!,{r0-r10,r14} ;Save some registers ; --- Make sure we can do this --- ldr r14,[r12,#sl__anchor] ;Load the block anchor cmp r14,#0 ;Is it created currently? adreq r0,FNliterr(1,"slNSS") bleq msgs_error ;Translate the error beq sl__wl90 ;And return the error ldr r14,[r12,#sl__format] ;Load the format anchor cmp r14,#0 ;Is it created currently? adreq r0,FNliterr(1,"slNFD") bleq msgs_error ;Translate the error beq sl__wl90 ;And return the error ; --- Get on with saving then --- swi "Hourglass_On" ;Start an hourglass going ; --- Set up initial registers --- ldr r9,[r10,#0] ;Load the block base mov r0,r10 ;Point to the anchor bl flex_size ;Get the block size add r10,r9,r0 ;Find the format limit adr r8,FNlitsz("*UNDEFINED*") ;No module name defined yet mov r7,r8 ;No prefix string yet either mov r6,r8 ;And no actual SWI name mvn r5,#NOT(-1) ;No SWI number defined either ; --- Write out the preamble --- bl sl__doString ;Write out this format bvs sl__wl90 ;If it failed, bail out ; --- We've found the module header --- ; ; Now we set up for the main loop, by remembering the index ; into the format string; we then embark on the first item ; in the SWI list. mov r4,r9 ;Remember this position ldr r3,[r12,#sl__anchor] ;Load the anchor base address mov r2,#0 ;Start at the beginning ; --- The main output loop --- .sl__wl15 add r1,r3,r2 ;Work out address of block ldr r5,[r1,#4] ;Load the SWI chunk number bic r5,r5,#&ff000000 ;Clear the flags bits add r8,r1,#8 ;Point to the module name mov r9,r4 ;Start from preamble position bl sl__doString ;Write out this format string bvs sl__wl90 ;If it failed, bail out ; --- Written the header -- now do the SWIs --- mov r2,r9 ;Remeber format index mov r7,r8 ;Work out prefix string pos .sl__wl20 ldrb r14,[r7],#1 ;Load next byte cmp r14,#0 ;Is this end of module name? bne sl__wl20 ;No -- keep going round mov r6,r7 ;Work out SWI name position .sl__wl25 ldrb r14,[r6],#1 ;Load next byte from string cmp r14,#0 ;Is this the end yet? bne sl__wl25 ;No -- keep going .sl__wl26 ldrb r14,[r6,#0] ;Load the first byte cmp r14,#0 ;Is it a null string? beq sl__wl30 ;Yes -- move on to next mod cmp r14,#1 ;Is this a dummy SWI? addeq r6,r6,#1 ;Yes -- move pointer on addeq r5,r5,#1 ;And move on the SWI counter beq sl__wl26 ;And start again mov r9,r2 ;Point to format string bl sl__doString ;Write this string out bvs sl__wl90 ;If it failed, bail out add r5,r5,#1 ;Bump up the SWI number b sl__wl25 ;And go round for more ; --- Finished a module --- .sl__wl30 ldr r2,[r1,#0] ;Load the size word sub r14,r1,r3 ;Work out old offset add r2,r14,r2 ;Add it onto previous offset ldr r14,[r12,#sl__used] ;Load current size of block cmp r2,r14 ;Is this the last one? bcc sl__wl15 ;No -- do this module too ; --- Do the end bit of the file --- bl sl__doString ;Write out the postamble bvs sl__wl90 ;If it failed, bail out swi "Hourglass_Off" ;Turn off the hourglass ldmfd r13!,{r0-r10,pc}^ ;Return to caller ; --- It failed -- return an error .sl__wl90 swi "Hourglass_Off" ;Turn off the hourglass add r13,r13,#4 ;Don't restore R0 ldmfd r13!,{r1-r10,r14} ;Restore registers orrs pc,r14,#V_flag ;And return the error FNltorg ; --- sl__doString --- ; ; On entry; R5 == current SWI number ; R6 == pointer to current SWI postfix ; R7 == pointer to current SWI prefix ; R8 == pointer to current module name ; R9 == pointer to format string input ; R10 == pointer to end of format string ; ; On exit; R1, R2, R4 and R6-R10 may be flex relocated ; R0 corrupted ; R9 == pointer to format string when processing stopped ; May return an error ; ; Use; Outputs a string, based on a format with the following ; syntax: ; ; All characters are echoed directly except `%' which is ; an escape for the following character. Escape codes defined ; are: ; ; %s == current SWI name ; %m == current module name ; %n == current SWI number ; %x == current X SWI number (i.e. SWI number OR &20000) ; %% == end of formatting section .sl__doString stmfd r13!,{r3,r14} ;Save some registers FNflex_save("r1,r2,r4") ;Save caller's registers sub r13,r13,#128 ;Make a small buffer orr r3,r5,#&20000 ;Get the X version number .sl__dostr10 cmp r9,r10 ;Are we at the end yet? bcs sl__dostr50 ;Yes -- return then ldrb r0,[r9],#1 ;Load next byte from string cmp r0,#ASC("%") ;Is this a magic `%' sign? beq sl__dostr20 ;Yes -- do clever things bl sl__byte ;Write this byte out b sl__dostr10 ;And continue formatting ; --- Handle an escape character --- .sl__dostr20 ldrb r0,[r9],#1 ;Load next byte from string orr r0,r0,#&20 ;Make sure char is lowercase cmp r0,#ASC("s") ;Is this a SWI name? adreq r0,FNlitsz("%5_%4") ;Yes -- point to skeleton cmp r0,#ASC("m") ;Or the module name? adreq r0,FNlitsz("%6") ;Yes -- point to skeleton cmp r0,#ASC("n") ;Or the SWI number? adreq r0,FNlitsz("%x3") ;Yes -- point to skeleton cmp r0,#ASC("x") ;Or the SWI X number? adreq r0,FNlitsz("%x1") ;Yes -- point to skeleton cmp r0,#ASC("d") ;Or a date string? beq sl__dostr40 ;Yes -- process specially cmp r0,#ASC("p") ;Or a literal percent? adreq r0,FNlitsz("%%") ;Yes -- point to skeleton cmp r0,#ASC("%") ;Or a percent sign? addeq r9,r9,#1 ;Yes -- skip a newline char beq sl__dostr50 ;Yes -- handle that cmp r0,#256 ;Do we have an address? bcc sl__dostr10 ;No -- go round for more then mov r1,r13 ;Build string in it bl str_subst ;Build output string mov r2,r0 ;Point to the string .sl__dostr30 ldrb r0,[r2],#1 ;Load next byte cmp r0,#32 ;Is it the terminator? blcs sl__byte ;No -- output it then bcs sl__dostr30 ;And loop back round again b sl__dostr10 ;Carry on with the string FNltorg ; --- Handle a date format string --- .sl__dostr40 stmfd r13!,{r3} ;I need this register sub r13,r13,#8 ;Make time buffer on stack mov r14,#3 ;Get the subreason code strb r14,[r13,#0] ;Save that in the block mov r1,r13 ;Point to the buffer mov r0,#14 ;Get the main reason code swi "OS_Word" ;Read the current time ldrb r0,[r9,#0] ;Load the next byte ready cmp r0,#ASC("[") ;Is this an argument? adrne r0,FNlitsz("slDFMT") ;No -- point to default blne msgs_lookup ;Translate nicely movne r3,r0 ;And put it in the right reg bne sl__dostr45 ;And skip onwards a bit ; --- Read the format string argument --- mov r1,r11 ;Point to a spare buffer add r9,r9,#1 ;Skip past the `[' char .a ldrb r14,[r9],#1 ;Load the next byte cmp r14,#ASC("]") ;Is that the end yet? cmpne r14,#&0D ;Check return for safety moveq r14,#0 ;Yes -- terminate string strb r14,[r1],#1 ;Store the byte away bne a ;Loop until all done mov r3,r11 ;Point to the format string ; --- Now read the actual string --- .sl__dostr45 mov r0,r13 ;Point to the time block add r1,r13,#12 ;Point to output buffer mov r2,#128 ;Get the buffer size swi "OS_ConvertDateAndTime" ;Translate the string add r13,r13,#8 ;Don't need the time any more ldmfd r13!,{r3} ;Restore register I saved mov r2,r13 ;Point to buffer start b sl__dostr30 ;Now output this string ; --- Finished reading the input --- .sl__dostr50 add r13,r13,#128 ;Reclaim my little buffer FNflex_load("r1,r2,r4") ;Restore caller's pointers ldmfd r13!,{r3,r14} ;Restore other registers bics pc,r14,#V_flag ;Return without an error ; --- Write byte in R0 to output --- .sl__byte mov r1,r14 ;Look after return address FNflex_save("r6-r10") ;Save lots of values bl xsave_byte ;Write this byte out FNflex_load("r6-r10") ;Restore our registers movvcs pc,r1 ;If OK, return to caller add r13,r13,#128 ;Reclaim my little buffer FNflex_load("r1,r2,r4") ;Restore caller's pointers ldmfd r13!,{r3,r14} ;Restore other registers orrs pc,r14,#V_flag ;And return the error FNltorg ;----- Loading modules ------------------------------------------------------ ; --- sl__loadMod --- ; ; On entry; R1 == pointer to filename ; ; On exit; May return an error ; ; Use; Loads a module and adds its SWIs to the current list. .sl__loadMod stmfd r13!,{r0-r2,r14} ;Save some registers add r2,r12,#sl__module ;Point to anchor for this bl load_file ;Try to load the file strvs r0,[r13,#0] ;If failed, return error ldmfd r13!,{r0-r2,pc} ;Return to caller FNltorg ; --- sl__ibMod --- ; ; On entry; R1 == estimated file size ; ; On exit; May return an error ; ; Use; Sets up a buffer for RAM loading. .sl__ibMod add r2,r12,#sl__module ;Point to anchor b load_initBuf ;Start the load op FNltorg ; --- sl__doneMod --- ; ; On entry; -- ; ; On exit; -- ; ; Use; Adds a module to the SWI list. .sl__doneMod stmfd r13!,{r0-r2,r14} ;Save some registers ldr r0,[r12,#sl__module] ;Load the flex anchor bl sl__scanMod ;Scan the module bvs sl__doneMod50 ;If it failed, quit now add r0,r12,#sl__module ;Point to the anchor bl flex_free ;Free the block ldmfd r13!,{r0-r2,pc}^ ;And return to caller .sl__doneMod50 add r2,r0,#4 ;Look after the error add r0,r12,#sl__module ;Point to the anchor bl flex_free ;Free the block adr r0,FNliterr(1,"slMAA") bl msgs_error ;Translate and substitute mov r1,#1 ;Only have one button bl errorBox ;Report the error ldmfd r13!,{r0-r2,pc}^ ;And return to caller FNltorg ; --- sl__lfMod --- ; ; On entry; R0 == pointer to error ; R1 == 1 ; ; On exit; -- ; ; Use; Reports an error when an attemt to load a module failed. .sl__lfMod stmfd r13!,{r0-r2,r14} ;Save some registers cmp r0,#0 ;Is there a real error? addne r2,r0,#4 ;Point to error text adrne r0,FNliterr(1,"slLFM") blne msgs_error ;Translate and substitute movne r1,#1 ;Only use one button blne errorBox ;Report the error ldmfd r13!,{r0-r2,pc}^ ;And return to caller FNltorg ;----- Loading dump files --------------------------------------------------- ; --- sl__loadDmp --- ; ; On entry; R1 == pointer to filename ; ; On exit; May return an error ; ; Use; Loads a module and adds its SWIs to the current list. .sl__loadDmp stmfd r13!,{r0-r2,r14} ;Save some registers add r0,r12,#sl__anchor ;Point to the anchor ldr r14,[r12,#sl__anchor] ;Load the current anchor cmp r14,#0 ;Is it defined currently? blne flex_free ;Yes -- free the block add r2,r12,#sl__anchor ;Point to anchor for this bl load_file ;Try to load the file strvs r0,[r13,#0] ;On error, return pointer ldmfd r13!,{r0-r2,pc} ;And return to caller FNltorg ; --- sl__ibDmp --- ; ; On entry; R1 == estimated file size ; ; On exit; May return an error ; ; Use; Sets up a buffer for RAM loading. .sl__ibDmp stmfd r13!,{r0,r14} ;Save some registers add r0,r12,#sl__anchor ;Point to the anchor ldr r14,[r12,#sl__anchor] ;Load the current anchor cmp r14,#0 ;Is it defined currently? blne flex_free ;Yes -- free the block ldmfd r13!,{r0,r14} ;Unstack the registers add r2,r12,#sl__anchor ;Point to anchor b load_initBuf ;Start the load op FNltorg ; --- sl__doneDmp --- ; ; On entry; R0 == pointer to `filename' ; ; On exit; -- ; ; Use; Handles a completed load of a dump file. .sl__doneDmp stmfd r13!,{r0,r1,r14} ;Save some registers mov r1,r0 ;Point to the file's name bl sl__setDumpName ;Set the name up correctly add r0,r12,#sl__anchor ;Point to the anchor block bl flex_size ;Read the block's size str r0,[r12,#sl__used] ;Save the size as used value str r0,[r12,#sl__size] ;And as the size value ldr r14,[r12,#sl__flags] ;Load the flags word bic r14,r14,#slFlag__modified ;Got it from someone else str r14,[r12,#sl__flags] ;Store the flags back bl sl__setFlags ;Reset the flags nicely ldmfd r13!,{r0,r1,pc}^ ;Return to caller FNltorg ; --- sl__lfDmp --- ; ; On entry; R0 == pointer to error ; R1 == 1 ; ; On exit; -- ; ; Use; Reports an error when an attemt to load a module failed. .sl__lfDmp stmfd r13!,{r0-r2,r14} ;Save some registers bl sl__setFlags ;Update the flags cmp r0,#0 ;Is there a real error? addne r2,r0,#4 ;Point to error text adrne r0,FNliterr(1,"slLFM") blne msgs_error ;Translate and substitute movne r1,#1 ;Only use one button blne errorBox ;Report the error ldmfd r13!,{r0-r2,pc}^ ;And return to caller FNltorg ;----- Format of the SWI table ---------------------------------------------- ; ; In order to speed things up, we maintain a table of SWI names in memory, ; and write this out to a file when the user wants us to. This also means ; that we can build up a list of SWIs over a period of time, by the user ; dropping module files onto our icon or window -- this saves having to load ; large numbers of modules into the RMA. ; ; The format is fairly simple. We keep a linked list of module blocks in ; a flex block. The blocks are sorted by ascending order of SWI chunk base ; numbers. Each module block looks like this; ; ; word; size of this link block ; word; SWI chunk base number for module and flags in top 8 bits ; string; name of module which provides these SWIs (null-terminated) ; string; SWI prefix for following SWI names (null-terminated) ; string; name of first SWI provided by module (null-terminated) ; string; name of second SWI provided by module (null-terminated) ; ... ... ; string; name of last SWI provided by module (null-terminated) ; byte; 0 (list terminator) ; align; to word boundary ; --- sl__setDumpName --- ; ; On entry; R1 == 0 for default `SWIDump' or pointer to name ; ; On exit; -- ; ; Use; Sets the name of the current dump file. .sl__setDumpName stmfd r13!,{r0-r2,r14} ;Save some registers movs r0,r1 ;Point to the source string adreq r0,FNlitsz("SWIDump") ;No string -- use default add r1,r12,#sl__dumpFile ;Point to the name buffer mov r2,#256 ;The buffer size orr r2,r2,#&C0000000 ;Don't do `|'s or `""'s swi "OS_GSTrans" ;Expand system variables ldmfd r13!,{r0-r2,pc}^ ;And return to caller FNltorg ; --- sl__initBlock --- ; ; On entry; -- ; ; On exit; May return an error ; ; Use; Initialises the SWI list block with the currently recognised ; OS SWIs. .sl__initBlock stmfd r13!,{r0-r3,r14} ;Save some registers add r0,r12,#sl__anchor ;Point to the anchor ldr r14,[r12,#sl__anchor] ;Load the current anchor cmp r14,#0 ;Is it defined currently? blne flex_free ;Yes -- free the block ; --- Reset the dump file name --- mov r1,#0 ;Use the default name bl sl__setDumpName ;Go and do that please ; --- Create the flex block --- mov r1,#1024 ;Initially make it 1K bl flex_alloc ;Allocate the block blcs alloc_error ;If it failed, get an error bcs sl__initBlk90 ;And abort now mov r14,r1 ;Get the size created mov r1,#0 ;Start output at beginning stmib r0,{r1,r14} ;Store sizes after anchor ; --- Now build the kernel SWIs --- ; ; First do OS_WriteI. Then we do the kernel SWIs lower than ; &100. adr r0,FNlitsz("Kernel") ;Point to string `Kernel' adr r1,FNlitsz("OS") ;Point to string `OS' mov r2,#&100 ;Get SWI chunk number bl sl__newLink ;Add in a new link block bvs sl__initBlk89 ;If it failed, stop going bcs sl__initBlk05 ;If already done, skip add r0,r12,#sl__anchor ;Point to the anchor adr r1,FNlitsz("WriteI") ;Point to string `WriteI' bl sl__string ;Add it to the block blvc sl__endLink ;Terminate this link bvs sl__initBlk89 ;If it failed, stop going ; --- Now do the kernel SWIs --- .sl__initBlk05 adr r0,FNlitsz("Kernel") ;Point to string `Kernel' adr r1,FNlitsz("OS") ;Point to string `OS' mov r2,#&0 ;Get SWI chunk number bl sl__newLink ;Add in a new link block bvs sl__initBlk89 ;If it failed, stop going bcs sl__initBlk17 ;Already there -- skip on mov r3,#0 ;Start at SWI number 0 .sl__initBlk10 mov r0,r3 ;Get the SWI number mov r1,r11 ;Build string in scratchpad mov r2,#256 ;And give the block size swi "OS_SWINumberToString" ;Read the SWI name swi "XOS_SWINumberFromString" ;Try to convert back cmp r0,r3 ;Is this what we expected? bne sl__initBlk13 ;No -- skip to end of loop add r0,r12,#sl__anchor ;Point to the anchor add r1,r11,#3 ;Skip past `OS_' prefix bl sl__string ;Add it to the list bvs sl__initBlk89 ;If it failed, stop going b sl__initBlk15 ;Skip past the next bit .sl__initBlk13 add r0,r12,#sl__anchor ;Point to the anchor mov r1,#1 ;Want one extra byte bl sl__ensure ;Make sure I've got it bvs sl__initBlk89 ;If it failed, stop going mov r14,#1 ;Mark this as nonexistant strb r14,[r0],#1 ;Store it in the block .sl__initBlk15 add r3,r3,#1 ;Bump the SWI number cmp r3,#&100 ;Reached the end yet? blt sl__initBlk10 ;No -- go back round then ; --- Finished that; end the link block --- bl sl__endLink ;Terminate the link block bvs sl__initBlk89 ;If it failed, stop going ; --- Now go through the module list --- .sl__initBlk17 mov r1,#0 ;Start on first module .sl__initBlk20 mov r2,#0 ;Start on first instance mov r0,#12 ;Enumerate module addresses swi "XOS_Module" ;Read next module number bvs sl__initBlk30 ;If error must have finished mov r0,r3 ;Point to module base address bl sl__scanMod ;Scan module for SWIs bvs sl__initBlk90 ;If it failed, stop going cmp r2,#0 ;Are there more instances? addne r1,r1,#1 ;Yes -- move to next module b sl__initBlk20 ;Go handle the next module ; --- Finished the module list --- .sl__initBlk30 bl sl__setFlags ;Reset the flags ldmfd r13!,{r0-r3,r14} ;Unstack the registers bics pc,r14,#V_flag ;And return without error ; --- Something went wrong --- .sl__initBlk89 mov r3,r0 ;Look after error pointer add r0,r12,#sl__anchor ;Point to the anchor bl flex_free ;Free the block mov r1,#0 ;Clear the anchor pointer str r1,[r12,#sl__anchor] ;Save it in the block bl sl__setFlags ;Reset the flags nicely mov r0,r3 ;And restore error pointer .sl__initBlk90 add r13,r13,#4 ;Don't restore R0 on exit ldmfd r13!,{r1-r3,r14} ;Restore registers orrs pc,r14,#V_flag ;And return the error FNltorg ; --- sl__scanMod --- ; ; On entry; R0 == pointer to module ; ; On exit; May return an error ; ; Use; Scans a module, and adds its SWIs to the list. .sl__scanMod stmfd r13!,{r0-r4,r14} ;Save some registers mov r3,r0 ;Look after module base ; --- Make sure this module's OK --- ldr r0,[r3,#16] ;Load the name offset ldr r1,[r3,#36] ;Load the SWI name table ldr r2,[r3,#28] ;And the SWI chunk number cmp r0,#256*1024 ;Make sure these are valid cmpcc r1,#256*1024 ;Both offsets please bcs sl__scanMod80 ;If not, ignore this module tst r2,#&FF000000 ;Make sure SWI chunk's OK tsteq r2,#&0000003f tsteq r2,#&00020000 bne sl__scanMod80 ;If not, ignore this module cmp r2,#&200 ;Is chunk in user range? bcc sl__scanMod80 ;No -- ignore this module ; --- Set the file modified flag --- ldr r14,[r12,#sl__flags] ;Load the flags word orr r14,r14,#slFlag__modified ;Set the flag str r14,[r12,#sl__flags] ;Save the flags back again ; --- We now have a module to add --- ; ; For error recovery, we read the current block sizes, so ; we can reset them if all goes wrong. add r0,r3,r0 ;Translate offset to address add r1,r3,r1 ;For both offsets add r14,r12,#sl__used ;Point to block size info ldmia r14,{r3,r4} ;Load the size counts FNflex_save("r1") ;Look after this pointer bl sl__newLink ;Add a new link in FNflex_load("r1") ;Restore pointer afterwards bvs sl__scanMod90 ;If it failed, return error ; --- Now just add the SWI names in --- .sl__scanMod10 ldrb r14,[r1],#1 ;Load a SWI prefix byte cmp r14,#0 ;Is this the end yet? bne sl__scanMod10 ;No -- keep on going ldrb r14,[r1],#0 ;Load the next byte out cmp r14,#0 ;Is this the double-0? beq sl__scanMod15 ;Yes -- end right now add r0,r12,#sl__anchor ;Point to anchor block FNflex_save("r1") ;Save this pointer away bl sl__string ;Add string to the list FNflex_load("r1") ;Restore this pointer bvs sl__scanMod89 ;If it failed, report error b sl__scanMod10 ;Keep on adding names ; --- Finished that -- wrap everything up --- .sl__scanMod15 bl sl__endLink ;Terminate this block bvs sl__scanMod89 ;If it failed, tidy up .sl__scanMod80 ldmfd r13!,{r0-r4,r14} ;Restore registers bics pc,r14,#V_flag ;And return with V clear ; --- Failed to do the job --- .sl__scanMod89 mov r2,r0 ;Save the error pointer add r0,r12,#sl__anchor ;Point to the flex anchor mov r1,r4 ;Get the old size value bl flex_extend ;Reset the size stmib r0,{r3,r4} ;Save old index values mov r0,r2 ;Restore the error pointer .sl__scanMod90 add r13,r13,#4 ;Don't restore R0 on exit ldmfd r13!,{r1-r4,r14} ;Restore the other registers orrs pc,r14,#V_flag ;And return to caller FNltorg ; --- sl__newLink --- ; ; On entry; R0 == pointer to module name ; R1 == pointer to SWI prefix ; R2 == SWI chunk number ; ; On exit; May return an error ; ; Use; Ensures that a link block for the given module exists. If ; it doesn't exist already, it is created at the end of the ; flex block. The index of the last link is returned, so it ; can be cleared if the actual SWI names can't be added. .sl__newLink stmfd r13!,{r0-r7,r14} ;Save some registers ; --- Set up for checking loop --- mov r3,r0 ;Look after module name mov r4,r1 ;And the SWI prefix string FNflex_save("r1,r3") ;Save these for relocation add r14,r12,#sl__anchor ;Point to the anchor ldmia r14,{r5,r6} ;Load base and size ; --- Wade on through the block --- mov r7,#0 ;Start at offset 0 .sl__newl10 cmp r7,r6 ;Reached the end yet? bcs sl__newl30 ;Yes -- better stop then ; --- See if this is a match --- add r14,r5,r7 ;Find current address ldr r0,[r14,#4] ;Load the SWI chunk number bic r0,r0,#&ff000000 ;Clear the flags byte cmp r0,r2 ;Does this match our one? bne sl__newl15 ;No -- move along then add r0,r14,#8 ;Point to the module name mov r1,r3 ;Point to our module name bl str_cmp ;Compare the strings bne sl__newl15 ;No match -- move along then .sl__newl13 ldrb r14,[r0],#1 ;Load module name byte cmp r14,#32 ;Is this the end? bcs sl__newl13 ;No -- keep going mov r1,r4 ;Point to the SWI prefix bl str_cmp ;Do these match? beq sl__newl20 ;Yes -- remove this chunk .sl__newl15 ldr r14,[r5,r7] ;Load the length of this one add r7,r7,r14 ;Move on to the next block b sl__newl10 ;And keep on going ; --- Found a match -- remove a chunk --- .sl__newl20 add r0,r12,#sl__anchor ;Point to the anchor ldr r2,[r5,r7] ;Get the block's size add r1,r7,r2 ;Start at the end of it rsb r2,r2,#0 ;And reduce block by this bl flex_midExtend ;Remove this chunk of data add r6,r6,r2 ;Modify the block size str r6,[r12,#sl__used] ;Save this size back ldr r14,[r12,#sl__size] ;Load the total block size add r14,r14,r2 ;Adjust that value too str r14,[r12,#sl__size] ;Store my modified value back ldr r2,[r13,#8] ;Restore caller's SWI base ; --- Add a new chunk onto the block --- .sl__newl30 str r6,[r12,#sl__last] ;Save the base of this block ldr r7,[r12,#sl__size] ;Get the block total size add r0,r12,#sl__anchor ;Point to anchor and info mov r1,#8 ;Add in fixed size info bl sl__ensure ;Make sure there's enough strvc r2,[r0,#4] ;Save the SWI chunk number addvc r0,r12,#sl__anchor ;Point to anchor and info FNflex_load("r1") ;Unstack module name pointer blvc sl__string ;Add the string in FNflex_load("r1") ;Unstack SWI prefix string blvc sl__string ;Add the string in ldmvcfd r13!,{r0-r7,r14} ;Unstack registers bicvcs pc,r14,#V_flag ;And return to caller ; --- It failed -- better tidy up --- mov r2,r0 ;Look after error number add r0,r12,#sl__anchor ;Point to the anchor mov r1,r7 ;Get the old size back bl flex_extend ;Reset the block size stmib r0,{r6,r7} ;Save the old values back mov r0,r2 ;Get the error pointer add r13,r13,#4 ;Don't restore R0 on exit ldmfd r13!,{r1-r7,r14} ;Restore registers orrs pc,r14,#V_flag ;Return the error FNltorg ; --- sl__endLink --- ; ; On entry; -- ; ; On exit; May return an error ; ; Use; Terminates a link block. .sl__endLink stmfd r13!,{r0,r1,r14} ;Save some registers add r0,r12,#sl__anchor ;Find the flex block mov r1,#1 ;Want to add a single byte bl sl__ensure ;Make sure we've got enough bvs sl__endl90 ;If it failed, return mov r14,#0 ;Get the NULL byte ready strb r14,[r0,#0] ;Save it at the end nicely add r0,r12,#sl__anchor ;Find the flex block again bl sl__align ;Word align output pointer ldmia r0,{r0,r14} ;Load block base and size ldr r1,[r12,#sl__last] ;Load the offset of the block sub r14,r14,r1 ;Get the last chunk size? str r14,[r0,r1] ;Save the length word ldmfd r13!,{r0,r1,r14} ;And return to caller bics pc,r14,#V_flag ;Return without error .sl__endl90 add r13,r13,#4 ;Don't return R0 on exit ldmfd r13!,{r1,r14} ;Restore registers orrs pc,r14,#V_flag ;And return the error FNltorg ;----- Block management routines -------------------------------------------- ; --- sl__ensure --- ; ; On entry; R0 == pointer to anchor/size block ; R1 == number of bytes to add ; ; On exit; R0 == pointer to allocated area ; May return an error ; ; Use; Ensures that there are R1 bytes free at the end of the given ; flex block. .sl__ensure stmfd r13!,{r1,r2,r14} ;Save some registers ldmib r0,{r2,r14} ;Load the base and sizes add r1,r1,r2 ;Find new total size str r1,[r0,#4] ;Save this back add r1,r1,#255 ;Align up to next 256 bic r1,r1,#255 ;For niceness's sake cmp r1,r14 ;Do we already have enough bhi sl__ensure50 ;No -- allocate some more .sl__ensure10 str r1,[r0,#8] ;Save new total size ldr r0,[r0,#0] ;Load address of block add r0,r0,r2 ;Point to first free byte ldmfd r13!,{r1,r2,r14} ;Unstack registers bics pc,r14,#V_flag ;And return without error .sl__ensure50 bl flex_extend ;Extend the block nicely bcc sl__ensure10 ;Rejoin program if OK bl alloc_error ;Get the error message ldmfd r13!,{r1,r2,pc} ;Return error to caller FNltorg ; --- sl__string --- ; ; On entry; R0 == pointer to flex block and size information ; R1 == pointer to string ; ; On exit; May return an error ; ; Use; Adds a string to a flex block. .sl__string stmfd r13!,{r0-r3,r14} ;Save some registers mov r2,r0 ;Look after anchor address FNflex_save("r1") ;Save the string address mov r0,r1 ;Point to the string bl str_len ;Work out the length add r1,r0,#1 ;Get the required size mov r0,r2 ;Point to anchor and sizes bl sl__ensure ;Make sure the space is OK FNflex_load("r1") ;Restore R1 from stack blvc str_cpy ;And copy it into the block strvs r0,[r13,#0] ;Otherwise store the error ldmfd r13!,{r0-r3,pc} ;And return to caller FNltorg ; --- sl__align --- ; ; On entry; R0 == pointer to flex anchor and size info ; ; On exit; -- ; ; Use; Word aligns the output pointer of a flex block. .sl__align stmfd r13!,{r14} ;Save a register ldr r14,[r0,#4] ;Load the output offset add r14,r14,#3 ;Word align this offset bic r14,r14,#3 ;Mask off bottom bits str r14,[r0,#4] ;Store new offset back ldmfd r13!,{pc}^ ;And return to caller FNltorg ;----- Workspace ------------------------------------------------------------ ] PROCws_start sl__flags =FNws_word :REM ;Various flags bits sl__anchor =FNws_word :REM ;Flex anchor for SWI table sl__used =FNws_word :REM ;Size used in flex block sl__size =FNws_word :REM ;Actual size of flex block sl__last =FNws_word :REM ;Offset of last block sl__modNames =FNws_word :REM ;Block for module names sl__format =FNws_word :REM ;Format chunk handle sl__module =FNws_word :REM ;Anchor for loading modules sl__pollBlock =FNws (256) :REM ;Wimp_Poll data block sl__dumpFile =FNws (256) :REM ;Full pathname of dump file sl__wSize =FNws (0) slFlag__block = (1<<0) :REM ;We have a SWI block slFlag__format = (1<<1) :REM ;There is a format slFlag__savable = (1<<2) :REM ;We can save a SWI list slFlag__modified= (1<<3) :REM ;SWI block is unsaved slFlag__saving = (1<<4) :REM ;We're saving a dump [ opt o ] NEXT PROCbas_aofSave END REM -- Macros --------------------------------------------------------------- DEF FNs(s$) [ opt 4 equs s$ dcb 0 ] =0 DEFFNP(i%):PRINT~i%:=0