Skip to content

feat: sltool dte decompile writes a mission as Luau source - #1131

Merged
vdmkenny merged 2 commits into
mainfrom
feat/mission-decompile-text
Oct 12, 2026
Merged

vdmkenny merged 2 commits into
mainfrom
feat/mission-decompile-text

Conversation

@vdmkenny

Copy link
Copy Markdown
Collaborator

The second step of the text path in #1126: sltool dte decompile <mission> writes a mission as Luau source, and docs/formats/mission-source.md specifies the form.

  • Records are global declarations named after their display names: ships and the markers, flight groups, squads, formations, curves, globals, parts with their code, and triggers with theirs. The script is Mission source: the script as statements, and back to the same bytes #1127's statements in Luau syntax.
  • The game's values are written by the names the scripting API gives them, from the tables the game runs on: ship types, pilots, orders, conditions, head movements and the game's variables (source/vocabulary.zig). A value the game doesn't name, such as a mod's, stays a number. A trigger's function names its event's values after the condition catalogue's labels, such as hull_damage.
  • The source leaves out what the game works out again, and parks what it never reads, such as editor data in the triggers and ships, as unknown and unused. New finding: the game reads nothing of the operand tables, sections 1, 22 and 26. mission_build_part_tables hands their entry to mission_fill_part, which pops it unread. It is documented in dte.md and annotated in Ghidra's names table, with mission_fill_part's third argument.
  • The listing now asks the vocabulary which parameter takes an order, instead of matching SetAI's label itself.

All 44 shipped missions decompile. Building the text again, and the round trip to the same mission, come with sltool dte build, the next step.

It is about 1550 lines, half of them the specification and tests. The records, the script text and the names are only useful together.

Closes #1130

Mission source starts with reading missions as text: each record a
global declaration named after its display name, the script as Luau
statements, and the game's values by the names the scripting API gives
them, from the same tables the game runs on. docs/formats/mission-source.md
specifies the form.

The source leaves out what the game works out again and parks what it
never reads, such as the operand tables: mission_build_part_tables
hands their entry to mission_fill_part, which pops it unread. Every
shipped mission decompiles; building the text again comes next.

Closes #1130
names.Word holds the words mission source gives itself, its
constructors, functions, index forms and the opcodes written as calls,
so the writers print them typed and the parser to come reads the same
list. One infix table gives each operator's symbol and binding, the
writer shares one list helper, and the listing asks the vocabulary for
a parameter directly.
@vdmkenny
vdmkenny merged commit 38e85b5 into main Oct 12, 2026
4 checks passed
@vdmkenny
vdmkenny deleted the feat/mission-decompile-text branch October 12, 2026 23:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Mission source: sltool dte decompile writes a mission as Luau

1 participant