← News

FantASM 1.9.0 is available

August 22, 2026FantASM

FantASM 1.9.0 is available to download. One project file can now build several images, the language server finally knows what machine you’re targeting, and there are four breaking changes — read those first.

The documentation has been rewritten alongside it.

Breaking changes

  • Invalid address or bank is now E1082, not E1049. 1049 named both that error and the unused label warning, so looking it up found whichever entry came first. The warning keeps the number.
  • NEX entry point … has no code is now W1083, not W1060. Same story: 1060 named both that warning and reserved word used as a macro name. The error keeps the number.
  • [assembler] format now takes effect. It was parsed and ignored, so a project file saying format = "nex" produced whatever the output extension implied. Check any project file whose format and output extension disagree; -f still wins.
  • Assembler::parsed_lines() and the ParsedLine type are removed. Only a Rust program embedding FantASM is affected — the command line is unchanged.

Several images from one project file

A program that is more than one file — a payload and the loader that incbins it, or a release and a debug variant — can now be declared once and built in one run:

[[target]]
name = "loader"
main = "src/loader.asm"
output = "build/game.nex"
depends = ["payload"]

One fantasm builds every target in dependency order. --only NAME builds one and what it depends on; --all adds targets marked default = false. A target that fails skips its dependents and nothing else, naming each skipped one with its reason. Dependency cycles are refused (E1077), as is an incbin of a target’s output left out of depends (E1078), or two targets writing the same file. A project file with no [[target]] is unaffected.

See Building Several Images.

Also new

  • The language server takes a target from the editor, via initializationOptions{"target": "zxnext"}. A Next project no longer shows E1016 on every Z80N instruction.
  • --gc-modules with --test says when a routine only a !test calls has been swept (W1084), instead of leaving the test to fail with Execution timed out or failed to halt.
  • A print in a !rhai block files a diagnostic, so it shows in your editor rather than only in the language server’s output pane.
  • Digit separators65_536, 0b1010_1010, $FF_FF.
  • EQU holds and joins textBANNER equ __NAME__ + " v" + __VERSION__ — and SIZEOF answers its length in the bytes db would emit.
  • A --no- form for every valueless flag, so a setting turned on in [assembler] can be turned off from the command line. The last flag given wins.
  • #if exists, completing the #-prefixed conditionals, and IF takes an expression rather than only IF <constant> = <value>.
  • A failing --test names the test and what it expected against what it got, without needing -v.

Fixed

The ones that were wrong output, silently:

  • A label called page or bank was silently replaced by the builtin of that name, so call page assembled a call to the current page number instead of to your label.
  • A constant or label named after a directive — message, end, block, hex — worked in some operand positions and not others: call message assembled while ld hl,message was E1005.
  • --sld recorded a MODULE body where it was written rather than where it was placed, so a breakpoint inside a module went to ROM and never hit.
  • !nex bank <n> was ignored for every bank but 10, 5, 2 and the one currently selected.
  • !message discarded anything after its template, so !message "T States: ", _tstates printed the string and dropped the value.

The full changelog has the rest. Test coverage expanded from 575 to 742 tests.

New documentation

The docs have been rewritten and restructured — including a page on using FantASM as a library from Rust, and how assembly works, which explains why most surprising behaviour is the gather/decide/emit pipeline showing through. Code samples throughout are now highlighted with the same grammar the 0x1DE editor extension uses.

Get it from the Downloads page.