Skip to content

Forked Functional Extension Specification

AsteriskAmpersand edited this page Oct 8, 2021 · 4 revisions

Forked Functional Extensions:

The compiler and decompiler use a default database of known function types This database can be extended on a per project or per file basis through the use of Functional Extensions and Forked Functional Extensions We call this F-Extensions and F-Extensions-Y respectively.

F-Extensions hold the rules for decompiling a function type and any indicated segment elements into a syntax of the form:

FuncionCheckValue{
	FUNCTION_NAME(parameters)
}

or

FuncionCheckValue{
	FUNCTION_NAME(parameters).SUBFUNCTION_NAME(more_parameters)
}

and so on to any arbitrary depth, intersped by periods, as long as parameter uses are not repeated.

F-Extensions can be in-lined by omitting the brackets and replacing the for a colon.

FuncionCheckValue : FUNCTION_NAME(parameters).SUBFUNCTION_NAME(more_parameters)

For example by default 0x0E has syntax:

0x0E{
	vertical_distance_to_target().leq(parameter1)
}

or in in-line form

0x0E : vertical_distance_to_target().leq(parameter1)

In this example "vertical_distance_to_target().leq " are a literal, parameter1 is an f-extension keyword to access a segment property. The actual decompilation is always prepended by the "self." and during decompilation parameters are resolved to the literal so the code would decompile (assuming parameter1 is 5 in said node) into: "self.vertical_distance_to_target() <= 5"

The composition syntax can also be seen in the default library:

Function type 0x76 is defined as:

0x76{
	part(parameter1).is_broken(parameter2)
}

and decompiles to:

	"self.part(parameter1).is_broken(parameter2)"

Forked F-Extensions (F-Extensions-Y)

An extension of this approach is forked F-Extensions, we label them F-Extensions-Y:

FunctionCheckValue{
	parameter == constant: F-Extension
	parameter == constant, parameter == constant: F-Extension
	...
}

Additionaly we can specify a prepending:

	>FUNCTION_NAME
	parameter == constant: F-Extension

or

	>FUNCTION_NAME()
	parameter == constant: F-Extension

which will prepend FUNCTION_NAME or FUNCTION_NAME() to all forks of the expresion intersped with a period. If the F-Extension is parenthesized the period is omitted.

The rules are used to decompile and compile in the order given (rules higher up take priority over rules further down). It's recommended to put more specific rules at the top and more general rules lower down.

A concrete example: For example by default 0x13 has syntax:

0x13{
	parameter1 == 0: below_area()
	parameter1 == 1: below_area()
}

In this example depending on the value of parameter1 the function can decompile to either:

	"self.below_area()"

or

	"self.below_area()"

When using forked F-Extensions the variables used to determine the forking are off-bounds on the declaration of the function for that line. Thus in the example above neither of the expressions on the right could legally use parameter1.

A more complex example can be found in the rules for 0x2E, the status check:

0x2E{
	>target
	parameter1 == 0x5: helpless_0()
	parameter1 == 0x6: helpless_1()
	...
	parameter1 == 0x2D: mudded()
	status(parameter1)
}

Notice that the last line is a fall through (it has no condition). Thus if no rule pattern matches before, it will default to the last line. Had we omitted the last line the decompiler and compiler will treat the function type as unknown if they ever find a parameter set that does not match any case (self.function_26)

In the previous case the fallthrough decompiles to self.target.status(12) if parameter1 is 12 and it does not match an existing rule.

If, hypothetically we wanted the fallthrough to be limited to the prepending we can use the "otherwise pass" keyword

0x2E{
	>target
	parameter1 == 0x5: helpless_0()
	parameter1 == 0x6: helpless_1()
	...
	parameter1 == 0x2D: mudded()
	othewise pass 
}

This will instead produce self.target(). The terminator otherwise pass will add parenthesis to the prepending if it's missing them for grammatical reasons.

Top Level Directive - Use Hex

It's possible to specify whether constants will be in hex or in dec as a top level directive

Use Hex

It's important to note that it's possible to use hex in dec mode by prepending 0x, however it's not possible to declare dec values in hex mode.

The default F-Extensions-Y file used by the compiler uses this directive.

0x0E : vertical_distance_to_target().leq(parameter1)

Hex values can start with any arbitrary number of 0s, thus:

Use Hex

0E : vertical_distance_to_target().leq(parameter1)

is valid F-Extension-Y code

F-Extension-Y Segment Keywords

The following is an exhaustive list of all F-Extension-Y Segment accessor keywords. We provide no guarantee that any outside parameter1 and paramete2 will not change in the future:

endRandom
flowControl
branchingControl
unkn1
unkn2
functionType
parameter1
unkn3
unkn4
unkn5
unkn6
parameter2
nodeEndingData
extRefThkID
extRefNodeID
localRefNodeID
unkn7
unkn8
unkn9
unkn10
unkn11
actionID
actionUnkn0
actionUnkn1
actionUnkn2
unkn12
actionUnkn3
actionUnkn4
unknExtra0
unknExtra1
unknExtra2

Despite being in the list for completeness, accessing functionType at any point on a .fexty file will cause a compilation error.

Enumerations

It's possible to allow a translating enumeration to be used during the decompilation and compilation process. Examples of the syntax are:

2F: target_is({em_enum:parameter1})
...
BF: in_map({st_enum:parameter1}).in_area(parameter2)

The enums are hard-coded as part of the compiler for complexity reasons. Currently there's the large monster enum (em_enum) which uses the monster internal ID, and the stage enum (st_enum).

This syntax is also used for expressing floating point fields through the cast-to-float (float_cast), for example:

1000: precise_location({float_cast : parameter1})

Details

When defined at project level override those at individual file level. Any explicit import will shadow those on the default library. Only full line comments are allowed. Full line comments are specified by writing # at the start of the line. Function types 80 to A7 are off-limits. This are handled specially by the compiler and decompiler as they correspond to operations on registers.

Compilation

F-Extension-Y files are data files that require compilation: -Compiling a single or multiple .fexty files produces a .py file -A project will use .py files if supplied to the de/compiler or on the project folder.

Closing Notes

F-Extension-Y files shouldn't be edited often. They directly interact with the decompiler from the start (they are directly used after the intermediate representation when converting segments to code), and they are used during the Syntax Analysis of the compilation process.

The default F-Extension-Y file is part of the compiler core and will be open to pull requests for expansion.

General Tutorials

General Tutorials

Animation Tutorials

Animation Tutorials

Audio Tutorials:

Audio Tutorials

IDs:

File & In Game IDs

Model Tutorials:

Model Tutorials

Effects Tutorials:

EFX Tutorials

FSM Tutorials

FSM Editing

MRL3 Tutorials:

MRL3 Tutorials

NPC Editing:

NPC Editing

Map Editing:

Map Editing

Plugins and Memory Editing:

Plugins and Memory Editing

Quest Editing:

Quest Editing

Monster AI Editing:

Monster AI Editing

Texture Tutorials:

General Texture Tutorials
Specific Texture Tutorials

TIML Editing

TIML Editing

Asterisk's Plugin Notes:

Asterisk's Plugin Notes

Miscellaneous Tutorials:

Miscellaneous Tutorials

Outdated Tutorials:

Outdated Tutorials
Clone this wiki locally