RISC OS Open
Safeguarding the past, present and future of RISC OS for everyone
ROOL
Home | News | Downloads | Bugs | Bounties | Forum | Documents | Photos | Contact us
Account

File formats: Utility

category: File formats

Programmer's Reference Manuals
» Filetypes
» Utility

Utility files

Transient Utility files (filetype &FFC) contain position independent code which is loaded into the RMA and executed in User Mode.
The purpose of a Utility is for when you want to run a small utility and then return back to the program environment that you were in prior to calling the Utility (unlike loading an Absolute program which would normally replace the current program).

On entry to a transient Utility, the registers are as follows:

Entry conditions
R0 Pointer to first character of command the line
R1 Pointer to first character of the command tail (will be a control character if no parameters given)
R12 Pointer to 1024 bytes of workspace
R13 Pointer to end of workspace, for stack
R14 Return address

A transient Utility is entered in User Mode with interrupts enabled. You should only call X form SWIs, and if there is an error, you should exit by setting the V flag and pointing R0 to an error block.

The operating system provides you with 1024 bytes of workspace, which includes the stack descending downwards from the end of the workspace. If more space is required, it should be claimed from the RMA.

You must exit the transient Utility with MOV PC, R14 (after freeing any RMA claims). As you are never the “current program”, you must not call OS_Exit.

Denoting a Utility as being 32 bit safe

Aemulor may trigger problems with some Utilities. If the Utility is known to be 32 bit safe, it should be marked as such by appending the four bytes ‘3’ ‘2’ ‘O’ (upper case ‘o’) and ‘K’ (in that order!) to the end of the file.

This can be achieved by adding this to the end of the Utility source:

    DCS "32OK"

Please note, this does not mean that the Utility is 32-bit only; it should be used to indicate that the Utility will operate correctly on both 26- and 32-bit architectures.

RISC OS Ltd (RISC OS 4/6) Utility header

RISC OS Ltd has defined a header for Utility programs.
This is documented here for completeness, though please note that RISC OS 5 does not make use of such a header, and Aemulor would still require the “32OK” word at the end of the file.

ROLtd Utility Header
+0 Branch to entry point (to skip over header)
+4 First magic value &79766748 (“Hgvy”)
+8 Second magic value &216C6776 (“vgl!”)
+12 Read only size (or 0 to mean the size of the file)
+16 Read/write size (or 0 to mean the size of the file)
+20 Either 26 or 32 depending on whether built for 26 bit or 32 bit systems

The two magic values are ROT13 for “Utility!”.

Example

This is a simple but potentially very useful Utility that will list all open files, plus provide information on the file status.

The output looks like this:

*ListOpen
255 RW     SDFS::RISCOSpi.$.!Boot.Loader
254 R   U  devices#bulk;size16385:$.USB6
253  W! U  devices#bulk;size16385:$.USB6
252 R      Resources:$.Fonts.Homerton.Medium.Outlines0
251  W! U  devices#endpoint1;interface0;alternate0;bulk;size32768:$.USB7
250 R   U  devices#endpoint2;interface0;alternate0;bulk;size32768:$.USB7
*

The status indicators are:

  • R – file opened with Read access
  • W – file opened with Write access
  • ! – file has been written to
  • E – file is at EOF
  • U – file is unbuffered
  • X – data has been lost
REM >makeListOpen
REM
REM Creates a transient Utility that lists all open files
REM
REM Rick Murray, 2014/10/31
REM This code is licenced as "whatever, dude". I'm not bothered.
REM It's for a RISC OS Open wiki example. So have fun with it.

DIM code% 320, L% -1

FOR l% = 8 TO 10 STEP 2
  P% = code%
  [ OPT     l%

  .begin
    ; RISC OS 4/6 Utility header
    B       start
    EQUD    &79766748
    EQUD    &216C6776
    EQUD    end - begin
    EQUD    0
    EQUD    32

  .start
    MOV     R8, #255     ; start at file handle 255 and work backwards
  .checkfile
    ; Read info on this handle
    MOV     R0, #254     ; OS_Args 254 -> read info on file handle
    MOV     R1, R8
    SWI     "XOS_Args"   ; can only call X form SWIs in Utilities
    MOVVS   PC, R14      ; bomb out upon an error here

    ; Validate it
    MOV     R7, R0       ; stash the stream status word in R7
    TST     R7, #2048    ; check this is a valid handle
    BNE     nextfile     ; if not, try the next one

    ; Output first the file handle number
    MOV     R0, R8
    MOV     R1, R12
    MOV     R2, #4       ; range is 0-255 (unsigned) only
    SWI     "XOS_ConvertCardinal1"
    MOVVS   PC, R14

    ; Work out how long the string is to right-align it
    SUBS    R6, R1, R0   ; R6 = terminator - buffer start
    SWILE   (&20100+32)  ; OS_WriteI for space padding
    SUBS    R6, R6, #1
    SWILE   (&20100+32)  ; padding
    SUBS    R6, R6, #1
    SWILE   (&20100+32)  ; padding
    SWI     "XOS_Write0" ; write the handle value
    SWI     (&20100+32)  ; separator space
    MOVVS   PC, R14

    ; Now we want to write flags (or not) as
    ;   RW!EUX
    ;   ||||||
    ;   |||||'- data lost
    ;   ||||'-- unbuffered
    ;   |||'--- at EOF
    ;   ||'---- file has been written to
    ;   |'----- file has write access
    ;   '------ file has read access
    TST     R7, #(1<<6)  ; bit 6 = Read access
    MOVNE   R0, #ASC("R")
    MOVEQ   R0, #ASC(" ")
    SWI     "XOS_WriteC"
    TST     R7, #(1<<7)  ; bit 7 = Write access
    MOVNE   R0, #ASC("W")
    MOVEQ   R0, #ASC(" ")
    SWI     "XOS_WriteC"
    TST     R7, #(1<<8)  ; bit 8 = has been written to
    MOVNE   R0, #ASC("!")
    MOVEQ   R0, #ASC(" ")
    SWI     "XOS_WriteC"
    TST     R7, #(1<<9)  ; bit 9 = at EOF
    MOVNE   R0, #ASC("E")
    MOVEQ   R0, #ASC(" ")
    SWI     "XOS_WriteC"
    TST     R7, #(1<<10) ; bit 10 = unbuffered stream
    MOVNE   R0, #ASC("U")
    MOVEQ   R0, #ASC(" ")
    SWI     "XOS_WriteC"
    TST     R7, #(1<<13) ; bit 13 (ho! ho!) = data lost
    MOVNE   R0, #ASC("X")
    MOVEQ   R0, #ASC(" ")
    SWI     "XOS_WriteC"
    SWI     (&20100+32)  ; separator space
    MOVVS   PC, R14

    ; Now determine the file NAME associated with this handle
    MOV     R0, #7       ; OS_Args 7 -> read pathname of open file
    MOV     R1, R8       ; (PRM 2-58)
    MOV     R2, R12      ; pointer to buffer
    MOV     R5, #512     ; workspace is 1024 so assume okay to give 512
    SWI     "XOS_Args"
    MOVVS   PC, R14

    ; poke a null word at the end in case 512 bytes wasn't enough!
    MOV     R2, #0       ; null
    MOV     R3, R12      ; point to workspace
    ADD     R3, R3, #512 ; add 512
    STR     R2, [R3]     ; stick the null there

    ; Write the pathname, and a newline
    MOV     R0, R12
    SWI     "XOS_Write0"
    SWI     "XOS_NewLine"
    MOVVS   PC, R14

  .nextfile
    SUBS    R8, R8, #1   ; for as long as there are file handles
    BPL     checkfile    ; check 'em

    ; otherwise, we're done here
    MOV     PC, R14

    ; flag ourselves as 32 bit okay
    ALIGN   ; just in case(!)
    EQUS    "32OK"

  .end
  ]
NEXT

SYS "OS_File", 10, "$.ListOpen", &FFC,, code%, P%

END

See also

  • Absolute files?
Revised on August 31, 2016 00:04:29 by Alan Robertson (52) (49.192.12.193)
Edit | Back in time (3 revisions) | See changes | History | Views: Print | Source | Linked from: File Types, File Formats, File Types (français), Addressing the end-of-life of AArch32

Search the Wiki

Social

Follow us on and

ROOL Store

Buy RISC OS Open merchandise here, including SD cards for Raspberry Pi and more.

Donate! Why?

Help ROOL make things happen – please consider donating!

RISC OS IPR

RISC OS is an Open Source operating system owned by RISC OS Developments Ltd and licensed primarily under the Apache 2.0 license.

Navigation

  • Home Page
  • All Pages
  • Recently Revised
  • Authors
  • Feeds
Site design © RISC OS Open Limited 2018 except where indicated
The RISC OS Open Instiki theme is based on Insitki's default layout

Valid XHTML 1.0  |  Valid CSS

Instiki 0.19.1(MML+)
This site runs on Rails

Hosted by Arachsys