+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