Architectures

Asar supports a number of different target architectures for code compilation. They can be activated via the command arch {name}. Going into detail on any of the supported architectures is beyond the scope of this manual. For that, it's recommended to check the SNES Dev Manual or other specialized resources. Asar tries as much as possible to always stick to the known conventions and specifications of each respective architecture (with a few notable exceptions that are hopefully all covered somewhere in this manual).

Supported architectures

  • 65816: Compiles code for the 65C816, used by the main SNES CPU and by SA-1. This is the default architecture. It supports the syntax recommended by WDC, with the exception of the MVN and MVP instructions. See the instruction list page for details.
  • spc700: Compiles code for the SPC700 CPU, the audio coprocessor in the SNES. Follows the format the SNES Dev Manual recommends, with the exception of mov (x)+,a and mov a,(x)+, which are moved to mov (x+),a and mov a,(x+). See also the spcblock section for an alternative way of assembling SPC700 code.
  • superfx: Compiles code for the SuperFX coprocessor.

All of Asar's features should be compatible with all of the supported target architectures, but it's not recommended to mix labels between different architectures as that will lead to undefined behavior. Opcodes in Asar are case-insensitive, which means that LDA and lda will be treated equally.

arch 65816
lda $00

arch spc700
mov a,$00

Opcode Length Specification

By appending .b, .w or .l to an opcode, you can specify that opcode's length. This is recommended in cases where the length could be ambiguous.

lda #0      ; Could be either lda #$00 or lda #$0000
lda.b #0    ; Always lda #$00
lda.w #0    ; Always lda #$0000

When no length is specified, Asar tries to guess the length based on the operand. Note that Asar does not use the standard <> for length specifications to avoid ambiguity with other uses of these symbols (such as in macros or math statements). Opcode length specifications are currently supported for the 65c816 and SPC700 architectures.

Pseudo Opcodes

Pseudo opcodes are a convenience method of repeatedly using opcodes that don't take an operand. Instead of using the opcode multiple times, the following syntax can be used:

{opcode} #{num}

This assembles opcode num times in succession. This means that

nop #3

inx #2

is the same as

nop
nop
nop

inx
inx

spcblock

SPC blocks are a convenient way of defining command data meant to be sent to the SPC700 in games using well-known SPC engines (though at this time, only the N-SPC engine is supported). The general format looks like this:

spcblock {target_address} [{engine_type}]
    [spc700_instructions...]
endspcblock [execute {execution_address}]

Inside an spcblock, arch spc700 is automatically active (see above for details). The target_address parameter specifies the target address (in ARAM) for the command data. The optional execute parameter tells Asar to generate a "start execution" command immediately after this SPC block, with execution_address as the ARAM address to start execution at. The engine_type parameter specifies which SPC engine to use. When omitted, the default value of nspc is used. The following engine types are supported:

nspc

This engine type implements the format used by the N-SPC engine found in most Nintendo games, as well as by the SPC700's initial program loader. The output format is:

dw <block_length>
dw <target_address>
<instructions...>
[dw $0000, <execution_address>]

Example usage:

                                   ; assembles to:
spcblock $6000 nspc                ; dw $0007 (length of the spcblock contents)
                                   ; dw $6000 (target address)
    db $00,$01,$02,$03             ; db $00,$01,$02,$03,$04
    exec_start:                    ;
    mov $33,#$44                   ; db $8f,$44,$33
endspcblock execute exec_start     ; dw $0000, $6004  (execution_address)