← News

FantASM 2.1.0 is available

September 18, 2026FantASM

FantASM 2.1.0 is available to download. !virtual places code at an address it does not yet occupy, ALIGN pads to a boundary, and an expression takes every comparison !assert already spelt. Underneath, the whole diagnostic register — messages, hints, the -v/-vv log — is reworded to one house style.

The documentation has been rewritten to match, with new pages on virtual origins, building in pieces and pass structure.

Breaking

  • _hl_ is no longer a register spelling. ld a,_hl_ assembled as ld a,(hl), a workaround from a time when the expression parser could not read the bracketed form. Write (hl).
  • A hex build is refused where it would have written the wrong addresses. A gap, a backward ORG, or a banked program produced a file whose bytes were adjacent whatever their addresses, with exit 0 and nothing said. Those builds now fail with E1085 or E1149. A banked program has no hex form at all — use nex or sna.
  • For a program embedding the crate — SymbolProvider now requires SymbolView. The seven methods an output writer reads moved to a trait of their own. An embedder implementing SymbolProvider implements SymbolView as well; no assembled output differs.

Added

  • !virtual <address>!endvirtual assembles a block for an address it is not placed at: labels and $ resolve at that address, its bytes staying inline in the image. , <page> names the 8K page its labels are recorded in; , ? says the page is not knowable at build time.
  • page ?, <slot> marks a slot as holding a page the OS allocates, so every record for code in that window carries page -1 and a debugger arms on the address alone.
  • ALIGN <boundary> [, <fill>] pads to the next multiple of a boundary, settled where the line lands, not where it was written.
  • !watch <register> <comparison> <value> records a register and a bound into the SLD, for a debugger to break wherever in execution it first holds.
  • A STRUCT member may reserve bytesname DS 8, or BLOCK.
  • Every comparison and logical operator !assert already spelt==, !=, <=, >=, &&, || and unary ! — is now legal in any expression, IF included.
  • fantasm --surface prints what the language contains as JSON, for an editor, highlighter or linter to read instead of restating it.

Object output and the linker, experimental. -f obj writes a relocatable object, fantasm ar collects objects into an archive, fantasm link joins them into a bin, hex, sna or nex, and fantasm dump prints what an object or archive holds. SECTION names a piece and where it may go; EXTERN is the other half of GLOBAL.

Fixed

9 fixes, and the worst of each group:

  • 3 wrong output, silently — bytes written out of address order landed at the wrong addresses in a bin or hex file; a gap was dropped from a hex file entirely; a STRUCT field initialiser naming a label held the address from before its MODULE or !library body was placed.
  • 4 sources that should have assembled, or should not haveIF here != $9000 assembled its block on a warning instead of failing outright; a STRUCT member the assembler refused was reported a second time against an unrelated line; --gc-modules/--gc-libraries could discard a live body sharing an address with a discarded one; a STRUCT field initialiser could not name a label defined below the instance.
  • 1 diagnosticW1068/W1069 reported <none>:0 for the line that emitted.
  • 1 in the documentation_line was documented nowhere.

36 new diagnostic codes, 1143 to 1179, none withdrawn. Test coverage expanded from 1,432 to 1,762 tests.

Every change is in the full changelog under [2.1.0].

Get it from the Downloads page.