Skip to content

Patch Files

See Writing a Patch for a basic walkthrough. This page collects the exact local and global patch forms.

SyntaxDescription
% commentSingle-line comment.
/%
...
%/
Multi-line comment. Everything between the delimiters is replaced with a single space.
@ $Pointer {
...
}
Patch the named structure.
@ $Pointer {
[40]
...
}
Begin writing at an offset within the structure.
@ $Pointer {
[40] ...
[60] ...
}
Write at several offsets. Each offset must begin on a new line.
@ $Pointer [40] {
[10] ...
[20] ...
}
Set a base offset. The writes begin at $Pointer[50] and $Pointer[60].
.ConstantLocal or global constant, enum value, or structure-specific constant.
*ScriptVariableEncoded script variable.
~ExpressionValue or data generated by a Star Rod expression.
#directiveImport, declaration, alias, export, or another compiler instruction.

Function patches contain MIPS assembly. Script patches contain event-script commands. Strings use message markup. Other structures interpret their contents according to their registered type.

Creates a structure and begins reading its body. The structure may be patched again by name later in the file.

Imports every patch from a file in the relevant import/ directory. Battle imports may also use the import/enemy/ directory. Imports are valid in map, battle, move, and similar overlay patches, not in global patches.

An optional namespace qualifies every imported name:

#import MyFile.bpat FileNamespace

The imported structures have names such as $FileNamespace:PointerName. Nested imports produce nested names such as $Outer:Inner:OriginalName.

An import may pass named options to the imported file. Add a body containing one Name=Value assignment per line:

#import Configurable.mpat Shared {
Mode=Hard
IncludeExtraData=true
TableVal=20
}

Option names and comparisons are case-insensitive. Each value must be a single token. A constant may be supplied as a value and is resolved before it is passed to the imported file.

The imported file may use the following preprocessor directives:

DirectiveDescription
##[IF:Name]Include the following branch when the option is defined.
##[IF:Name:Value]Include the following branch when the option has the specified value.
##[IFNOT:Name]Include the following branch when the option is not defined.
##[IFNOT:Name:Value]Include the following branch when the option does not have the specified value. An undefined option also satisfies this condition.
##[ELSEIF:Name]Begin another branch selected when the option is defined and no earlier branch matched.
##[ELSEIF:Name:Value]Begin another branch selected when the option has the specified value and no earlier branch matched.
##[ELSEIFNOT:Name]Begin another branch selected when the option is not defined and no earlier branch matched.
##[ELSEIFNOT:Name:Value]Begin another branch selected when the option does not have the specified value and no earlier branch matched.
##[ELSE]Begin the fallback branch.
##[ENDIF]End the conditional.
##[VALUE:Name]Replace the directive with the option value.

Conditionals may be nested. Every IF or IFNOT must have a matching ENDIF, and ELSEIF, ELSEIFNOT, and ELSE apply to the nearest open conditional. VALUE may appear within a declaration or body line; using an undefined value in an active branch is an error.

For example, Configurable.mpat could select a structure and substitute a value passed by the importing patch:

##[IF:Mode:Hard]
#new:Data $ModeData {
2
}
##[ELSE]
#new:Data $ModeData {
1
}
##[ENDIF]
#new:Data $Table {
##[VALUE:TableVal]
}

Options are scoped to a single import. A nested import receives its own option body; values can be forwarded explicitly with ##[VALUE:Name].

Creates a constant for the current patch. Global constants must be defined in a global patch or enum file.

Adds another name for an existing structure.

Clears the region occupied by an existing local structure so the space may be reused.

Reserves a region of RAM in a local overlay. New structures will not be placed there. Only one region may be reserved in a patch file.

Files under $mod/globals/patch/ are applied directly to the ROM and compiled into every build.

Existing data is addressed with a type and ROM address:

@Data XXXX
@Function XXXX
@Hook XXXX
@Script:Global XXXX
@Script:Map XXXX
@Script:Battle XXXX

@Fill repeats its body from the first address to the second, truncating the last repetition if necessary:

@Fill XXXX YYYY

New global structures use the same typed declaration model:

#new:Data $Name
#new:Function $Name
#new:Script:Global $Name
#new:Script:Map $Name
#new:Script:Battle $Name

#reserve XXXX $Name reserves XXXX bytes of RAM and stores the resulting address in $Name.

DirectiveDescription
#export:Function $GlobalFunctionCreate and export a global structure.
#export .NewConstName XXXXCreate and export a global constant.
#export $GlobalPointerExport an existing structure.
#export .ExistingConstNameExport an existing constant.

For structures, #export: is a shorthand for creating a globally visible #new: declaration.