Topics

UTTORI ASM · IN DEVELOPMENT

Macros

Define and call reusable source macros with local labels and arguments.

On this page

SNES behavior

Macros emit commands, not values:

macro SetBrightness(level)
  lda #<level>
  sta $2100
endmacro

%SetBrightness($0F)

Headers use macro Name(arg, arg) and calls use %Name(value, value). Arguments are comma-split with quoted text preserved. Inside the body, <parameter> inserts the supplied source text. !<parameter> treats the argument as a define name.

Variadic macros put ... or the single-character ellipsis … last:

macro EmitBytes(required, ...)
  db <required>
  if sizeof(...) > 0
    db <...[0]>
  endif
endmacro

%EmitBytes($10, $20, $30)

sizeof(...) is the extra-argument count and <...[expression]> selects one extra argument. The expression can use defines. Out-of-range indices are errors. The older <!a> form for alphabetic variadic positions is accepted but deprecated.

Macro bodies can contain conditionals, while, for, define assignments, and macro-local labels. Duplicate macro definitions are rejected. See variadic_syntax.asm, macrolabels.asm, and macro-engine.ts.

6502 family behavior

Native macros emit commands, not values:

macro SetByte(addr, value)
  lda #<value>
  sta <addr>
endmacro

%SetByte($10, $42)

ca65 macros use dotted headers, \parameter substitution, and bare invocation:

.macro emit value
  .byte \value
.endmacro
emit $22

Variadic native macros, sizeof(...), and macro-local ? labels follow the shared SNES macro engine. ca65 .local and .exitmacro are rejected with a macro-compatibility diagnostic. Token-list/string macros are not implemented.