RISC OS Build service

File Format

Introduction

JFPatch files can contain up to 8 distinct sections, of which 2 are required and must be present:

Section
(† ⇒ required)
Meaning
Header † Describes what the file is going to do
Pre Pre-assembly basic code which is to bo included
Workspace Describes the workspace blocks to be used
Module Describes the module header
Macros Describes the macro definitions
Code † The actual code to be assembled (may include patch offsets)
Post Post-assembly, prior to exiting for testing, and running code
End End inclusion, after assembly, but before the auto-included routines.

The required sections - the Header and the Code sections - are described first, below..

Example JFPatch files

Example usage, together with example API code, can be found in a supporting repository.

Header section

The header describes what the patch file is going to do. Entries are separated by one or more spaces, and are case insensitive:

Field
(† ⇒ required)
Meaning
APP Specify application name
The name will be used in system vars to create the correct code Files required (!Create, !Run, !Help, and WSWI-Help may be copied)
IN † Input file (MUST preceed OUT)
If -, no input file will be used.
If preceeded by *, the module whose name is given will be extracted from memory and processed.
OUT † Output file (ignored if TYPE is AOF and file is in j directory)
TYPE † Type of file to generated. Values which may be supplied:
Type name Meaning
Module Relocatable Module, offsets start at 0, typed Module
Util Utility code, offsets start at 0, typed Utility
Utility As 'Util'
Absolute Absolute code, offsets start at &8000, typed Absolute
Code Direct code, base address is as allocated in memory; load and exec address of the file will be the base address
Memory Stored to memory, ie no output file
AOF AOF format file
AOFModule An AOF format file, but with a Module header.
VER Code version number in the form 1.00a.
Each time the code is assembled this will be incremented, but the file you are editing will not change. This is so that you can check in a general way, not how many times it has been tested, but how many times it has been returned to.
MAX Maximum amount of memory to reserve in bytes (or suffix with K) for the generated code
PC Start PC for file if not default
{ Start comment. See Code section for description.

If filenames are not full paths then the same path as the patch file is assumed, unless APP is specified, in which case, all references will be from that system variable (<name>$Dir).

Code section

Code lines are identified by a line outside DEFINE blocks which begins with a line starting with . (full stop), # or @.

Code sections may be prefixed by symbols as the first character on the line:

First Character Meaning
% Literal basic command, eg % PRINT "HELLO"
These may be used if additional debug is needed during assembly, or to add more complex processing, such as generated data tables.
@ Change assembly offset
Changes the assembly offset to an offset in the input file. The only use for this is when you are patching an input file. You may use endofcode to indicate that the code should be assembled after all other code. endofcode is always word aligned.
# Pre-assembler directive
Allows you to do many special things. See later for more information.
{ Start comment
These comments are not included in the output file, and serve only to comment the code in large blocks (or remove sections of code) rather than using ;. These comments are not nestable. End comments with space followed by }, or } alone on a line.
; Embedded comment line.
These are unlike ;'s within code lines because they are stripped of all :'s which may cause errors in the assembly.
. Routine or data start.
These are just the same as basic labels.
> Code routine start.
These are preceeded with a C style routine name (if CodePrefix is enabled). Otherwise they are identical to . labels.
$ Local label.
Labels a point locally, which is only available to the routine within which it occurs (ie from . label to the next . label, or #Post/#End)

All lines which are not prefixed by these characters are checked for being predefined macros before being passed on to the basic assembler.

Labels

It is recommended that you use purely textual names for both routines and local labels (numerical initial characters are not allowed), ` prefixed names for variables - ie numbers or strings, and _ prefixed names for local labels which are local to a group of routines. eg .decimal, $`textstring, ._filename. This is merely a recommendation, and is not coded into the file format.

Local labels are defined as for normal labels, but instead of a . prefix, $ is used. To reference such labels within the code, use the same form (ie $variable name. These will be expanded during compilation.

Whilst compiling AOF code any lines with a | in are checked for exports or imports. Exports are achieved by using labels in the usual way:

will export the label label. To rename the label when exported you can use :

Label definitions in AOF may also be suffixed by ENTRY to indicate that they are to be declared as the entrypoint, in the form:

To refer to a label you can use either BL (or XBL) or one of the EQU commands:

Dependant on the EQU used, the correct import type should be selected. Calculations may be performed on labels, but you may NOT add labels together :

Predefined macros

These are used in much the same manner as standard instuctions, and may for the most part be considered as normal instructions. Where ## is given, the instruction may be given a conditional code:

Macro Meaning
LADR##
Long ADR
Long address assignment with an address range of 64k, rather than the 4k usually given by ADR. 2 instructions will always be assembled.
Usage:
LMOV##
Long move
When MOV gives up and says 'argh, no more...' LMOV will do it's best to perform the specified function. Multiple instuctions will be used, variably according to the number given. Therefore, it is imperitive that the value is not an unassigned label (ie no forward references). You may also use -ve numbers.
Usage:
LADD##
Long addition
The complement to long move, long add performs addition on registers using multiple instructions.
Usage:
XSWI##
XBL##
Extended SWI
Extended BL
These are used to pass parameters to a SWI call or routine in a similar way to SYS and CALL in BASIC. As in BASIC, values may be ignore, by using , on it's own. Note that these values are all set in order, so if you want r0=r1 and r1=r0, you can't do it this way. You can preceed the value with # to do an explicit MOV when you have used a variable instead of a number. Preceeding a reference by ^ will use ADR to get it's address rather than it's absolute value.
Usage:
Usage:
(here, value may be a number or register prefixed by r, a or v)
XLDMFD
Extended unstack.
Sometimes you will need to return from a routine with, either the registers preserved, or with VS and r0 pointing to an error string. By using XLDMFD, you can exit from a routine using just one line.
REM
REMP
Remark for debugging
Permanent remark (not removed by #REM OFF)
Whilst debugging you will find it extremely useful to be able to display messages about the progress of the code. REM includes an inline set of routines to display a message. Within the string, a group of control codes may be used:
Control Meaning
%% Display a percent symbol.
%r# Display register # in decimal (# is the register number in hex)
%&# Display register # in hex
%$# Display the string pointered to by register #
%a# Display register # as an output character (OS_WriteC it)
%E# Display error message pointed to by register #
%R Display all registers in hex
%I Ignored
%C Don't append newline to the end of the string, if you want to split the message over sections of code
%c## embed a control character, ## in decimal. Useful if you are displaying things in the desktop, eg %c04 for text cursor.
All messages will by terminated by newline, unless %C specified. If you specify streaming in the front-end, output will be streamed. If #REM OFF is specified, REM's will be embedded in the BASIC as ; comments.
Usage:
Note: All registers preserved, flags altered.
DIV
Divide routine (very sub-optimal)
Result is returned in top.
Usage:
Note: Large amounts of code assembled.
RES
Reserve space
If you need to reserve a lagrge block of memory, this is the easiest way to do it. The space will be initialised to 0.
Usage:
MODE##
Set processor mode
Sometimes it is imperitive to use a particular processor mode. You are required to change to SVC mode in CallBack's so that r14_svc is preserved, and this macro gives you an easy means of doing this.
Usage:
(reg1 and reg2 default to r8 and r9, and contain the flags
Usage:
reg1 and reg2 default to r8 and r9, and contain the flags reg3 is the stack pointer to use
LDRW##
STRW##
LDRBW##
STRBW##
Load register from workspace
Store register in workspace
Load register with byte from workspace
Store register as byte in workspace
These are used by the Workspace module. If the registers are mapped correctly, then these will perform operations on workspaces just as LDR/STR do on inline addresses.
Usage:
ADRW##
Address in workspace
This works like its inline counterpart, but used long adds, so has an infinite range.
Usage:
SWAP##
Swap two registers
How may times have you had the two registers around the wrong way? This gets around that with three lines of code (no temporary register).
Usage:
Note: Do not confuse with the SWP ARM3 instruction.
EQUZ
EQUZA
Equate string with zero suffix
Equate string with zero suffix, then align
Much easier than using EQUS "blah, blah"+CHR$0.
Usage:
ERR
Define an error block
Defines an error block, in the form of a 32bit error number and a message.
Usage:
NOP##
No operation
This is often used to remove lines from patched code, or to delay whilst register bank resync takes place. One instruction is assembled.
Usage:
REMF##
REMFP##
FIXME: Not documented
GETBIT##
SETBIT##
CLRBIT##
FIXME: Not documented
SETV##
SETC##
SETN##
SETZ##
FIXME: Not documented

Pre-assembler directives

Pre-assembler directives are prefixed by # and consist of a command followed by arguments:

Directive Meaning
#REM
Enables/disables REM debug comments (not REMP though).
Usage:
#CODEPREFIX
Enables/disables prefixes to sections of code.
The name of routines followed by a SWINV code to indicate the length of the name will be embedded prior to the start of the routine if this is enabled.
Usage:
#LOAD
Load a file in line into the code
Usage:
If length is -1, then just the length of the file will be reserved
#POST
Start of post assembly section; whatever follows is post assembly code
This code can be used for testing the routines you have written so that you can be sure that they work before running the complete code.
Usage:
#END
End of code; whatever follows will be appended varbatum to the file.
Usage:
#COND
Conditional assembly, see later
#CHECK
Verification of code validity, see later
#LIBRARY
Install library routines, see later
#INCLUDE
Install a local file, see later
#HERE
Locate objects, see later
#MAPWS
Map workspace block to a register
This changes the default mapping for a workspace block.
Usage:
if no register is specifed, the default is used.
#AREA
Begin an AOF area for the following code
This declares the start of a named AOF area.
Usage:
The area flags are a space separated list of flags for the area:
Flag Meaning
CODE Area is for Code (otherwise it is a Data area)
32BIT Area contains 32bit code (otherwise it contains 26bit code)
READONLY Area is read only (otherwise it is writeable)
STACKCHECK Area is contains stack checked code (otherwise it is not stack limit checking)

boolean can be one of ON, TRUE, ENABLED, OFF, FALSE, DISABLED or =file to take the value from a particular file.

Conditional assembly

Conditional assembly allows you to cater for different possible configurations of the code so that it may be set up by the user to do different things.

Conditional assembly can take place in two forms. The first, default, form is for the pre-assembler to remove all non-required code, leaving just that which is required to be assembled. This is called external conditional assembly because the conditionals are evaluated externally to the code.

The second form is inline conditional assembly. This is where all the code is created in the BASIC file, and the conditionals are evaluated at assembly time. The external method is useful for debugging, whilst the inline method is more useful if the code has options which the user may select.

Conditionals in both forms are nestable, though you may become confused when trying to read such code:

The directives are:

Directive Meaning
#COND INLINE
Selects inline conditional assembly
#COND EXTERNAL
Selects external conditional assembly
#COND SET
Sets a condition variable to a value
Usage:
#COND varname
Sets a condition variable according to user reply
In External mode, this will display a error box type message In Inline mode, the messages will be printed on the screen and a OS_Confirm used to get the reply.
Usage:
#COND OF
Starts a conditional assembly structure
The following code within this structure will be assembled if the named condition variable is true.
Usage:
#COND ELSE
Else clause in structure
#COND END
End conditional assembly structure
#COND ENDIF
ditto

Checking the validity of code

When you are writing patches, it is useful to perform check on the code you are acting on to ensure that it is the correct version. The checks are :

Directive Meaning
CHECK STRING
Check that a particular address contains a ctrl terminated string.
Usage:
Note: The string may be enclosed in quotes.
CHECK WORD
Check that a particular word contains a particular value
Usage:
CHECK LEN
Check that the length of the file is a certain value
Usage:

Including libraries of routines

Library files are used when it is rather pointless to code the same thing over and over again. They are held within the JFPatch directory in the file Libraries. The only library provided is the Strings library - a set of routines I have collected, modified and written (the string comparison routines are my own work, and though probably not optimal, suffice for the most part).

The syntax of the library inclusion command is :

filename is an absolute filename if there is a path, otherwise the JFPatch.Libraries directory is searched. routine may be * if you want all libraries to be included in a file - not recommended.

The # symbol means that the libraries will be included at this point in the code. Otherwise, a #HERE LIBRARIES directive will need to be issued.

The library files themselves consist of a first line which should be:

Followed by the routines in the library. Local labels may be used, but externally referenced variables may not due to the manner in which the inclusion occurs. Inclusion is from the first ; before the . prefix of the routine name to the line before the first ; before the next . (or the next . if there is no ;). See the Summary file for more details, and refer to Strings for examples. FIXME

Including code files

Just as library routines can be included in your code, so can files be included in the code. These can be used where you can't be bothered to code a section a number of times, but it is too specific for a full library.

The syntax of the include command is :

NOTE: This is still an experimental function. Please report problems or queries to Justin. (Note in 2020: He doesn't know how well this works)

Here directives (object location)

At some future point there may be more HERE directives to include pre-defined things (I'm not sure what yet, but in AOF there seems to be a lot of scope for that sort of thing...) Currently, however only two directives exist :

Directive Meaning
#HERE FOOTER
Embed the Footer file at this point
This might be used as DoggySoft use to place "Anything after this point is probably a virus")
#HERE LIBRARIES
Embed all previously defined libraries
You should probably not need to use this unless you are very organised. I use LIBRARY filename,#[routine] in preference.

Pre-assembly section

The pre-assembly section is used to define constants to be used, and other various actions which occur to the programmer. Usually #CHECK and #COND set up directives are included here. The section is preceeded by PRE, and terminated by END PRE.

The only pre-assembler directives which make any sense are the #COND and #CHECK directives.

If you are assembling AOF code you may assign constants here by using the form :

Post-assembly section

This section is used for code which should be run after the code has been assembled. The section is enclosed by #Post and #End (or the end of the file). All the code given will be passed directly to Basic, unless it is prefixed by a # symbol. In which case, the following apply:

Directive Meaning
#RUN
Runs a particular file
If the file specified is <CODE> (note: upper case), then the output file is run. If <THISDIR> is included, then it is replaced by the directory the Patch file is in.
Usage:
#WIMPRUN
Performs the same as RUN, except that the file is Filer_Run.
#EXAMINE
Used to examine memory to check that it is what you expect it to be.
Usually this is used after executing the code. The output is saved to a file and loaded as a text file.
Usage:
#CAPTURE
Captures all output into a spool file.
This is usually used where the output cannot be captured in a TaskWindow.
Usage:
Default is ON
#END
End section, start End section

End section

All text in the end section will be appended to the file and never be executed, unless it is called as a PROCedure or FuNction.

This is useful for including information about the author, or program. However, it's real purpose is to allow functions to be used as macros.

Workspace

What is the point of using workspace blocks ? Well, it's easier to see a reference:

It is easier see that it means get the task handle from workspace than:

Begin a workspace block with DEFINE WORKSPACE and end it with END WORKSPACE. Within these blocks, you should use the following commands :

Directive Meaning
NAME
Sets the name of the block
PREFIX
Allows you to specify a prefix to use within this block
A variable named x0 with a prefix of win becomes winx0. When used, ` prefixes to the original name are retained, so `x0 would become `winx0.
DEFAULT
Sets the default register to use for the workspace.

All other lines are treated in one of two ways. The first of these is the offset format, and the second is the relative format. Both give the same structure types, but the offset format gives the absolute offsets into the block. It is not recommended that you mix blocks.

Offset format

This can be used when you know all the offsets will be fixed, or if the lengths of the blocks are so awkward that you can't be bothered to do it by reference. In this form, the definitions are :

  offset  identifier[  comment]

where offset is either a decimal number, or a hex number prefixed by &.

Relative format

This is a much more powerful format for creating workspace structures, and is similar (though in no way compatible) to that used by ObjAsm. In this form, the definitions are :

  [=]variable  type[repetitions][  comment]

where type is :

type Meaning
! an integer word (ie 4 bytes)
% a byte
$ a string (repetitions is the number of characters including terminator)
^ a structure reference in the form
     ^name[  repetitions]

repetitions is the number of times the space is repeated (ie four words would be !4).

Within this structure, blocks may be repeated, or "unioned" by using brackets to group the items. Placing a ( alone on a line begins a grouping, ) alone ends a grouping, and ) followed by a number sets a number repetitions for the block.

Within a grouping, | on its own on a line sets a union. This means that the relative pointer is reset to the start of that group so that an alternate set of names may be given. This is used in ObjAsm OSLib header files to define things like the Wimp_SendMessage blocks where the data is dependant on the code.

Such unions should be of equal length under the current version, or if not, the last union MUST be the largest. Later versions may remove this constraint, but should not be relied upon.

Using workspace

To use workspace within the code, use [ LDR|STR ][B]W or ADRW commands. To find the length of a block of workspace, use `len_name.

Module section

Modules are easy to write. You may not think that now, but after using JFPatch for some time to create modules, you will find that modules are so simple to program that you may have to get a life to fill the time you would have spent struggling... Only kidding people...

Module definitions are enclosed by DEFINE MODULE and END MODULE. Within these statements, the fields are:

Field Meaning
NAME Module name as used in *Modules command (default=Untitled)
VERSION Version number to use in help string (default=1.00, or the version in the header.
AUTHOR Author name to use in help string (default=not used)
HELP Name to use in *Help Modules (default=NAME)
EXTRA Extra text to append after the date in *Help Modules (default=none)
INIT Initialisation address or label (default=no code)
FINAL Finalisation address or label (default=no code)
START Start address or label (default=no code)
SERVICE Service handler label
SERVICES Begin services definition (instead of a user handler
EVENTS Begin events definition
VECTORS Begin vectors definition
COMMANDS Begin OSCLI/Help/Configure commands definition
SWIHANDLER SWI handler code (default=handled automatically)
SWIS Begin SWI call definition
WORKSPACE Length of workspace to claim in r12, prefix with * to initialise 0
WIMPSWIS Begin WimpSWIVe handler definition (WimpSWIVe © Andrew Clover)
PREFILTER Begin a Pre-Poll filter definition
POSTFILTER Begin a Post-Poll filter definition
RECTFILTER Begin a Pre-Rectangle redraw filter definition
POSTRECTFILTER Begin a Post-Rectangle redraw filter definition
COPYFILTER Begin a Copy region filter definition
POSTICONFILTER Begin a Post-icon redraw filter definition
MESSAGEFILE Declare the name of the messages file to use for commands (default=none)
RESOURCES Begin a ResourceFS files definition
IMAGEFS Begin an Image Filing System definition
FS Begin a full Filing System definition

The only one which really ought to be defined is NAME, although all are optional.

Init, final and service code

Whilst you may not have defined some of these, they may be created for you by JFPatch to implement other features. The cases are as follows :

Fields used Meaning
Workspace used Init used to claim workspace, Final used to release it
Filters used Init used to register, Final used to deregister, Service used to claim on FilterManager start up.
WimpSWIs used Init used to claim, Final used to release.
Services used Service handler caught before 'Service' entry.
Vectors used Init used to claim, Final used to release.
Events used Init used to claim, Final used to release.

Module workspace (private word)

Within each module there is a private word which is usually used to store the address of the modules workspace. Because of the way in JFPatch works (ie. creating it's own handlers), it is easier for these handlers to pass the address of the workspace to your routines, rather than a pointer to the workspace's address. This only applies if workspace is claimed; otherwise, r12 is a pointer to your private word just as normal.

If workspace is claimed, the following will have r12 pointing to the private space :

Commands will NOT receive r12 -> workspace, but r12 -> private word, which contains the pointer to the workspace. Therefore, you should use

to get the pointer to the workspace. This is VERY important, otherwise you'll overwrite lots of very important pieces of data in the system heap.

Services

Services can be handled manually with the 'Service' entry, but a much easier way exists to do this by means of a definition block. Lines are in the form:

  service   code

Where service can be a decimal or hex number, or any string from the !JFPatch.Resources.Services file. This contains the service names (approximately) as given in OSLib header files. The block should be ended with:

  End Services

Vectors

Vectors can be claimed and released manually using init and final code, but by using a definition block many of the problems you may come across are removed and things look a bit clearer. The lines are of the form :

  vector   code

Where vector can be a decimal or hex number, or any string from the !JFPatch.Resources.Vectors file. This contains the vector names (approximately) as given in OSLib header files. The block should be ended with :

  End Vectors

Events

Whilst you can trap events using the Vectors call or manually, it's probably easier to have these in a seperate section. The lines are of the form :

  event   code

Where event is a decimal or hex number, or a string from the !JFPatch.Resources.Events file. This contains the vector names as given in OSLib headers files except that I've prepended the module name if there is one. The block should end with :

  End Events

Commands

Commands are denoted by COMMANDS to start, and END COMMANDS to end. Entries within this block, the fields are :

Field Meaning
NAME The command name
CODE Code to execute when called (default= no code)
MAX Maximum number of parameters which may be passed
MIN Minimum number of parameters which may be passed
TYPE Type of command (default=COMMAND). Options : FS, CONFIG
FLAGS Value of the command flags. Overrides the max, min and type settings.
SYNTAX Syntax of the command (defaults to no message)
HELP Help on the command (defaults to no message)

SYNTAX and HELP may be followed by a single line, or alternatively by .... In the latter form (three . characters), the next lines will be taken as being the message, terminating when the indentation reduce past that at the first line. To embed control strings, use GSTrans format.

Note again that r12 is not passed as the workspace, but as a pointer to the private word if the workspace is set.

SWIs

SWI blocks, like command blocks are surrounded by SWIs and END SWIs. Within this block, the following two fields are allowed:

Field Meaning
BASE Sets the base number of the SWI calls, prefix with & for hex
PREFIX Sets the prefix for all the calls. Omit the trailling _.

All other lines should be in the form :

  number   alias   code

WimpSWIs

WimpSWIve is a gorgeous little module written by Andrew Clover which allows you to replace certain Wimp calls with other, much nicer calls :-) For more information, read the WSWI-Help documentation in Applics. Again, the section is surrounded by WIMPSWIS and END WIMPSWIS. And the fields are :

Field Meaning
SWI Full name of WimpSWI to replace
PRE Pre-handler code (before real call being called)
POST Post-handler code (after real call being called)

Either the Pre-Handler or the post handler may be prefixed by the ^ symbol. In which case, the code will have the high priority bit set. Mixed priority SWI handlers are not allowed, and you must use two seperate definitions if you wish to do that.

Filters

Filters are one of the most useful of the features of RO3 (to the programmer at least). Filters allow you to trap calls Wimp_Poll in much the same way that WimpSWIs do for the other calls. There are two types of Filters which can be used, Pre- and Post-poll filters. These are in seperate sections, delimited by opening and closing block statements. The filters which can be registered are:

The fields within each of the blocks are declared with the following definitions:

Field Meaning
NAME Name for the filter (for the list)
CODE Filter handler code
MASK Wimp_Poll mask as a number (only post-filters)
ACCEPT An alternate way of specifying the filter mask by giving names of poll reasons to accept (only post-filters)
TASK Task name to apply filter to (or - for all tasks)
METHOD How filter registration should be performed.
Method Meaning
ERROR If the task requested is not present, report an error and fail to initialise. This is the default.
MULTIPLE Register filters on tasks as they start up.

Post-filters must have either MASK or ACCEPT specified. ACCEPT commands must be given on seperate lines, and the names are :

Primary name Secondary name Tertiary name
Null
Redraw
OpenWindow
CloseWindow
PointerLeaving
PointerEntering
MouseClick
UserDragBox DragDropped
KeyPress KeyPressed
Menu MenuSelection
Scroll ScrollRequest
LoseCaret
GainCaret
PollWord
UserMsg UserMessage Message
UserMsgRec UserMessageRecorded MessageRec
UserMsgAck UserMessageAcknowledged MessageAck

Resources

Resources can be registered with ResourceFS when the module initialises by defining them in the Resources definition. The fields within the RESOURCES block take the form:

    local-filename    resourcefs-filename

Note: It is possible that the Resources registration is non-functional at present.

ImageFSs

The entry points and registrations for an ImageFS filesystem can be registered with the ImageFS block. The following fields are defined in the definition:

Field Meaning
TYPE
FILETYPE
Sets filetype which is handled by the ImageFS, which may be a hex value prefixed by &, or a type name (or bare hex filetype)
FLAGS Flags to set for the filesystem. Flags are space separated list of names, and may be prefixed by a - character to indicate the the flag is not set. The flags field may be specified multiple times, and will accumulate flags (or subtract them, if the - prefix is used. Flags currently known are:
Flag name Meaning
TELLFSWHENFLUSHING
TELLWHENFLUSHING
Sets bit 27 of the flags word
OPEN Entry point for ImageFS_Open
CLOSE Entry point for ImageFS_Close
GET
GETBYTES
Entry point for ImageFS_GetBytes
PUT
PUTBYTES
Entry point for ImageFS_PutBytes
ARGS Entry point for ImageFS_Args
FILE Entry point for ImageFS_File
FUNC Entry point for ImageFS_Func

Full FSs

The entry points and registrations for a full filesystem can be registered with the FS block. The following fields are defined in the definition:

Field
(† ⇒ required)
Meaning
NAME † Name of the filing system
STARTUP Text to print on filing system selection
NUMBER † Sets the filing system number for the filing system
FILES Number of open files supported by the filing system, or INFINITE if not limited
FLAGS † Flags to set for the filesystem. Flags are supplied as a space separated list of names, and may be prefixed by a - character to indicate that the flag is clear. The flags field may be specified multiple times, and will accumulate flags (or subtract them, if the - prefix is used. Flags currently known are:
Flag name Meaning
SPECIALFIELDS Sets bit 31 in the flags
INTERACTIVESTREAMS
INTERACTIVE
Sets bit 30 in the flags
NULLFILENAMES Sets bit 29 in the flags
ALWAYSOPENFILES Sets bit 28 in the flags
TELLFSWHENFLUSHING
TELLWHENFLUSHING
Sets bit 27 in the flags
SUPPORTSFILE9 Sets bit 26 in the flags
SUPPORTSFUNC20 Sets bit 25 in the flags
SUPPORTSFUNC18 Sets bit 24 in the flags
SUPPORTSIMAGEFS Sets bit 23 in the flags
USEURDLIB Sets bit 22 in the flags
NODIRECTORIES
NODIRS
Sets bit 21 in the flags
NEVERLOAD
USEOPENGETCLOSE
Sets bit 20 in the flags
NEVERSAVE
USEOPENPUTCLOSE
Sets bit 19 in the flags
USEFUNC9 Sets bit 18 in the flags
READONLY Sets bit 16 in the flags
SUPPORTSFILE34 Sets bit 0 in the extra flags
SUPPORTSCAT Sets bit 1 in the extra flags
SUPPORTSEX Sets bit 2 in the extra flags
OPEN Entry point for FS_Open
CLOSE Entry point for FS_Close
GET
GETBYTES
Entry point for FS_GetBytes
PUT
PUTBYTES
Entry point for FS_PutBytes
ARGS Entry point for FS_Args
FILE Entry point for FS_File
FUNC Entry point for FS_Func
GBPB Entry point for FS_GBPB

Note: The extra flags setting may be broken in the current implementation.

Macros section

The macros section declares macros - templated blocks of instructions - which are to be used within the assembly. The macros are not widely used and probably contain many bugs. The macro section is started with DEFINE MACROS and ended with END MACROS. The fields within the section are:

Field
(† ⇒ required)
Meaning
COMMAND Name of the macro, to be used in place of the instruction mnemonic
CONDS Which condition codes are allowed for this macro, as a space separated list, or a special word:
Cond Meaning
ALL All conditions are allowed
NEVER No conditions are allowed
INVERT All condition codes are allowed by inserting an inverted condition instruction to branch over the macro code
TEMPS Number of temporary registers required
MASK Parameters template for the macro. The template consists of a string which has substitution characters used to declare what parameters are passed to the macro. The substitutions are prefixed by @ and take the form:
Substitution Meaning
@rname Names a single register parameter. name is a single character name for this parameter.
@gname Names a group of registers, in the form {registers}. name is a single character name for this parameter.
@cname Names a constant value prefixed by a # character. name is a single character name for this parameter.
@tname Names a register that may be used as a temporary. name is a single character name for this parameter. Not currently implemented.
CODE Begins the code to use for the macro, which ends at an END CODE. Within the CODE block, the names @[r|g|c]name may be used to substitute in the invocation.

Macros are not well used within JFPatch code, so there will be bugs, and it may not work as described or as expected.