diff --git a/docs/manual/index.html b/docs/manual/index.html index 4fd516fe..d7133514 100644 --- a/docs/manual/index.html +++ b/docs/manual/index.html @@ -12,7 +12,7 @@

Asar

-

A multi-architecture SNES assembler by Alcaro, modelled after xkas v0.06 by byuu.
+

Asar is a multi-architecture SNES assembler by Alcaro, modelled after xkas v0.06 by byuu.
This manual was written by RPG Hacker, so if you find something that is wrong or weird, make sure to blame me instead of Alcaro.

As a general rule, the manual uses {} to denote required parameters and [] to denote optional parameters (where optional parameters ending in ... mean "zero or more" of that parameter). Everything else refers to keywords/names.


@@ -294,7 +294,8 @@

Asar

[rom_file] Input, output - Path to the ROM file that is modified by Asar. If this file doesn't exist yet, Asar creates a new ROM file instead. When omitted, Asar checks if asm_file_name.sfc or asm_file_name.smc exists and uses the one it finds. When zero or two ROMs with that filename are found, Asar defaults to the .sfc extension. As a convention, Asar always treats .smc files as headered and .sfc files as unheadered ROMs. This means that headered .sfc files or unheadered .smc files cannot be used with Asar unless their extension is changed. This is by design and meant to encourage compliance with the convention. + Path to the ROM file that is modified by Asar. If this file doesn't exist yet, Asar creates a new ROM file instead. When omitted, Asar checks if asm_file_name.sfc or asm_file_name.smc exists and uses the one it finds. When zero or two ROMs with that filename are found, Asar defaults to the .sfc extension.

+ As a convention, Asar always treats .smc files as headered and .sfc files as unheadered ROMs. This means that headered .sfc files or unheadered .smc files cannot be used with Asar unless their extension is changed. This is by design and meant to encourage compliance with the convention.
asar.exe C:/homebrew/my_game/main.asm C:/homebrew/my_game/bin/my_game.sfc
asar.exe C:/homebrew/my_game/main.asm C:/homebrew/my_game/bin/my_game.smc
asar.exe C:/homebrew/my_game/main.asm
@@ -303,7 +304,9 @@

Asar


For convenience, double-clicking the Asar executable will prompt you to enter paths to an ASM file and a ROM file and thus allow you to directly use Asar without passing any command line arguments to it.

Standard Includes

- Aside from passing include search paths to Asar via the command line, it's possible to also do so via a file called stdincludes.txt. When a file with this name exists next to the Asar executable, Asar automatically opens it and adds every line in it as an include search path (trailing and leading whitespace on a line is ignored, as are lines containing only whitespace). Absolute and relative paths are supported. Relative paths are considered relative to the TXT file. The purpose of this file is to make it easier to distribute standard code libraries for use with Asar by making it possible to just unpack the contents of a ZIP file or similar directly into the Asar directory. Note that include search paths passed in via the command line get priority over paths parsed from this TXT file. See section Includes for details on include search paths.
+ Aside from passing include search paths to Asar via the command line, it's possible to also do so via a file called stdincludes.txt. When a file with this name exists next to the Asar executable, Asar automatically opens it and adds every line in it as an include search path (trailing and leading whitespace on a line is ignored, as are lines containing only whitespace). Absolute and relative paths are supported. Relative paths are considered relative to the TXT file.

+ + The purpose of this file is to make it easier to distribute standard code libraries for use with Asar by making it possible to just unpack the contents of a ZIP file or similar directly into the Asar directory. Note that include search paths passed in via the command line get priority over paths parsed from this TXT file. See section Includes for details on include search paths.
All of the examples below are valid:
C:/asm/stdlib
 
@@ -311,7 +314,9 @@ 

Standard Includes

../../my_game/libraries test/

Standard Defines

- Aside from passing additional defines to Asar via the command line, it's possible to also do so via a file called stddefines.txt. When a file with this name exists next to the Asar executable, Asar automatically opens it and adds every line in it as an additional define. The syntax is similar to Asar's regular define syntax, with a few notable differences. There are no spaces required around the =, the ! of the identifier is optional, whitespace around the identifier is ignored, so is whitespace around the value (unless the value is delimited by double quotes, in which case any whitespace inside is kept in the define), the value itself is optional (when left out, it is set to an emptry string). Lines containing only whitespace are ignored. The purpose of this file is to make it easier to distribute standard code libraries for use with Asar by making it possible to just unpack the contents of a ZIP file or similar directly into the Asar directory. See section Defines for details on defines.
+ Aside from passing additional defines to Asar via the command line, it's possible to also do so via a file called stddefines.txt. When a file with this name exists next to the Asar executable, Asar automatically opens it and adds every line in it as an additional define. The syntax is similar to Asar's regular define syntax, with a few notable differences. There are no spaces required around the =, the ! of the identifier is optional, whitespace around the identifier is ignored, so is whitespace around the value (unless the value is delimited by double quotes, in which case any whitespace inside is kept in the define), the value itself is optional (when left out, it is set to an empty string). Lines containing only whitespace are ignored.

+ + The purpose of this file is to make it easier to distribute standard code libraries for use with Asar by making it possible to just unpack the contents of a ZIP file or similar directly into the Asar directory. See section Defines for details on defines.
All of the examples below are valid:
!stddefined1=1
  stddefined2=1
@@ -881,7 +886,7 @@ 

Standard Defines

XCN A
- Compiles code for the SPC700 architecture. 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 the spcblock section for an alternative way of assembling SPC700 code. + Compiles code for the SPC700 architecture. Follows the format the SNES Dev Manual recommends, with the exception of mov (x)+,a and mov a,(x)+, which have been changed to mov (x+),a and mov a,(x+). See the spcblock section for an alternative way of assembling SPC700 code. Super FX @@ -1506,13 +1511,18 @@

Standard Defines

arch spc700 mov a,$00

Number Literals

- Asar supports decimal, hexadecimal and binary number literals. Hexadecimal literals use $ as a prefix, binary literals use % as a prefix. Number literals can be made positive or negative by prefixing a + or a - (without a sign, positive is assumed). They can also be prefixed with a ~ to get their unary complement (a 32-bit integer with all the bits inverted). + Asar supports decimal, hexadecimal and binary number literals. + + Number literals can be made positive or negative by prefixing a + or a - (without a sign, positive is assumed). They can also be prefixed with a ~ to get their unary complement (a 32-bit integer with all the bits inverted).
lda $00
 clc
 adc #-10
 and #%01111111
 lda #~$80	; Equal to lda #$FFFFFF7F
- Aditionally, Asar supports character literals by delimiting a single ASCII character with '. Asar will automatically convert them to the integer value currently mapped to them (by default their ASCII value). They can be used in all places where number literals can be used. See section Tables for details on ASCII character mapping. + Additionally, Asar supports character literals by delimiting a single ASCII character with '. Asar will automatically convert them to the integer value currently mapped to them (by default their ASCII value). They can be used in all places where number literals can be used. See section Tables for details on ASCII character mapping.
lda #'a'
 sta $00
 
@@ -1540,9 +1550,9 @@ 

Pseudo Opcodes

rep

rep {num} : {code}
-

Warning: this command is deprecated due to conflicting with the 65816 assembly REP instruction. In most cases, you can achieve the same effect with a for loop.

+

Warning: this command is deprecated due to conflicting with the 65816 assembly REP instruction. In most cases, you can achieve the same effect with a for loop.

- The rep command lets you compile any bit of code num times. It functions similarly to pseudo opcodes, but without being limited to certain opcodes only. Instead, you can repeat almost any bit of code supported by Asar, even macro calls. Note that in xkas compatibility mode, rep 0 will compile the following code once, whereas rep -1 (or any number < 0) won't compile the following code at all. This is to keep compatibility with old patches, which occasionally used the rep command as a replacement for conditionals. Also note that stacking multiple rep commands is not supported (only the most recent rep will take effect). + The rep command lets you compile any bit of code num times. It functions similarly to pseudo opcodes, but without being limited to certain opcodes only. Instead, you can repeat almost any bit of code supported by Asar, even macro calls. Note that in xkas compatibility mode, rep 0 will compile the following code once, whereas rep -1 (or any number < 0) won't compile the following code at all. This is to keep compatibility with old patches, which occasionally used the rep command as a replacement for conditionals. Also note that stacking multiple rep commands is not supported (only the most recent rep will take effect).
macro writeval(val)
 	db <val>
 endmacro
@@ -1589,7 +1599,7 @@ 

spcblock

db $8F,$44,$33 ; mov $33,#$44 dw $0000,$6004 ; execution_address (exec_start label position) -
+

Return to top @@ -1637,7 +1647,7 @@

spcblock

Disable Asar's address translation; the SNES address is equal to the PC address. Can be combined with base and macros to implement your own address translation.
- When no mapping mode is specified, Asar tries to determine the mapping mode from the output ROM. If that isn't possible, Asar defaults to lorom. + When no mapping mode is specified, Asar tries to determine the mapping mode from the input ROM. If that isn't possible, Asar defaults to lorom.
lorom
 org $008000
 db $FF		; Will write to PC address 0x000000
@@ -1645,6 +1655,7 @@ 

spcblock

hirom org $008000 db $FF ; Will write to PC address 0x008000
+ Once you have set your mapping mode, Asar provides the built-in functions pctosnes() and snestopc() to translate between addresses.

Return to top

Compatibility Settings

@@ -1683,7 +1694,7 @@

warn xkas

The warn xkas command determines whether Asar should throw warnings on behavior that is known to be different between xkas and Asar. Use warn xkas on to enable these warnings and warn xkas off to disable them. It's recommended to only enable them when not using xkas compatibility mode. Note that some behavioral changes throw warnings or errors regardless of this setting.

math pri

math pri {on/off}
- The math pri command tells Asar which order of operations to use in math experssions. When set to off (default), Asar uses left-to-right math, just like xkas v0.06. When set to on, Asar follows the conventional order of operations (exponentiation before multiplication & division, multiplication & division before addition & subtraction etc.). Parentheses can be used in either mode and tell Asar to calculate the expression inside first. For most intents and purposes, working with this flag enabled is more practical and predictable. It is disabled by default solely for the purpose of xkas backwards compatibility, unless asar 1.9 or a higher version is specified at the start of the file, which will change the default to math pri on. This command will be removed in Asar 2.0, after which math pri on will be the only possible behavior. + The math pri command tells Asar which order of operations to use in math expressions. When set to off (default), Asar uses left-to-right math, just like xkas v0.06. When set to on, Asar follows the conventional order of operations (exponentiation before multiplication & division, multiplication & division before addition & subtraction etc.). Parentheses can be used in either mode and tell Asar to calculate the expression inside first. For most intents and purposes, working with this flag enabled is more practical and predictable. It is disabled by default solely for the purpose of xkas backwards compatibility, unless asar 1.9 or a higher version is specified at the start of the file, which will change the default to math pri on. This command will be removed in Asar 2.0, after which math pri on will be the only possible behavior.
math pri off
 db 1+(6/3)*5	; db 15
 
@@ -1691,7 +1702,7 @@ 

math pri

db 1+(6/3)*5 ; db 11

math round

math round {on/off}
- The math round command tells Asar which rounding behavior to use in math expressions. When set to on (default), Asar truncates all numbers immediately, whereas when set to off, Asar only truncates numbers whenever they need to be cast to an integer type. Note that having this flag enabled will make it practically impossible to work with floating point numbers since calculations will lead to unexpected and impractical results. It is the default setting solely for the purpose of xkas backwards compatibility. When writing patches specifially for Asar, it is recommended to always disable this flag. If you specify a minimum supported Asar version using asar 1.9 or higher, the default will be math round off. This command will be removed in Asar 2.0, after which math round off will be the only possible behavior. + The math round command tells Asar which rounding behavior to use in math expressions. When set to on (default), Asar truncates all numbers immediately, whereas when set to off, Asar only truncates numbers whenever they need to be cast to an integer type. Note that having this flag enabled will make it practically impossible to work with floating point numbers since calculations will lead to unexpected and impractical results. It is the default setting solely for the purpose of xkas backwards compatibility. When writing patches specifically for Asar, it is recommended to always disable this flag. If you specify a minimum supported Asar version using asar 1.9 or higher, the default will be math round off. This command will be removed in Asar 2.0, after which math round off will be the only possible behavior.
math round on
 ; 1.75 is immediately truncated to 1, resulting in (3/4)+1
 ; 3/4 would result in 0.75, which is immediately truncated to 0, resulting in 0+1
@@ -1718,10 +1729,12 @@ 

namespace nested

Comments

You can use ; to add comments to your code, making it easier to read and understand for other people. Everything from the ; to the end of the line is silently ignored by Asar.
	lda $00		; Asar only sees the lda $00 and ignores everything else
- Previously, there were exceptions to this rule in the form of lines starting with ;@, which are assembled normally. This functionality is deprecated, Asar 2.0 will treat these lines as regular comments. The purpose of this feature was to add code to your patch that can be used with both xkas and Asar. In xkas, lines with ;@ will simply be ignored, whereas in Asar, they would be assembled. If you don't care about backwards-compatibility, you can also just use @, which will make your patch only assemble with Asar and fail with xkas. (This too is deprecated.) Aditionally, when Asar finds any unknown command on a line starting with ;@ or @, it will only throw a warning instead of an error. This can, at least in theory, be used to include optional features from newer Asar versions and still have your patch be compatible with older Asar versions. See section Compatibility Settings for details on xkas compatibility. + Previously, there were exceptions to this rule in the form of lines starting with ;@, which are assembled normally. This functionality is deprecated, Asar 2.0 will treat these lines as regular comments. The purpose of this feature was to add code to your patch that can be used with both xkas and Asar. In xkas, lines with ;@ will simply be ignored, whereas in Asar, they would be assembled. If you don't care about backwards-compatibility, you can also just use @, which will make your patch only assemble with Asar and fail with xkas. (This too is deprecated.) Additionally, when Asar finds any unknown command on a line starting with ;@ or @, it will only throw a warning instead of an error. This can, at least in theory, be used to include optional features from newer Asar versions and still have your patch be compatible with older Asar versions. See section Compatibility Settings for details on xkas compatibility.

Also note that comments starting with ;[[ are reserved for multi-line comments in a future version of Asar. You should either change the beginning or make sure that there's a ]] (the comment terminator) at the end of the line.

Brackets

- Brackets, { and }, may be used to help organize your code structurally. They're treated as commands by the assembler, which means they follow the same rules as other commands, but they otherwise have no effect on code assembly and are silently ignored. Since brackets have no effect on code assembly, they don't even have to match, either. It's entirely up to the coder whether, how and in what quantity brackets are used.
+ Brackets, { and }, may be used to help organize your code structurally. They're treated as commands by the assembler, which means they follow the same rules as other commands, but they otherwise have no effect on code assembly and are silently ignored.

+ + Since brackets have no effect on code assembly, they don't even have to match, either. It's entirely up to the coder whether, how and in what quantity brackets are used.
	lda $00
 	beq .IsZero
 	
@@ -1733,7 +1746,12 @@ 

Brackets

.IsZero rts

Multi-Line Operators

- The , and the \ operator are formatting operators which make it possible to split commands in Asar into multiple lines. Both are put at the end of a line and work very similarly with only one key difference. During execution, Asar will concatenate subsequent lines to lines ending with either operator and treat them as a single line. When using the comma operator, the comma itself will actually remain a part of the concatenated string, whereas when using the backslash operator, the backslash itself will be removed from the concatenated string. When using the backslash operator, please note that all whitespace following it is ignored, whereas all whitespace preceeding it is preserved. This is by design, since some commands in Asar require spaces to work, whereas other commands (like math commands) only work without spaces. + The , and the \ operator are formatting operators which make it possible to split commands in Asar into multiple lines. During execution, Asar will concatenate subsequent lines to lines ending with either operator and treat them as a single line. Both are put at the end of a line and work very similarly with only one key difference: +
    +
  • When using the , comma operator, the comma itself will actually remain a part of the concatenated string +
  • When using the \ backslash operator, the backslash itself will be removed from the concatenated string. +
+ When using the backslash operator, please note that all whitespace following it is ignored, whereas all whitespace preceding it is preserved. This is by design, since some commands in Asar require spaces to work, whereas other commands (like math commands) only work without spaces.
%some_macro(!arg1, !arg2, !arg3,
 	!arg4, !arg5, !arg6)
 ; This will be treated as "%some_macro(!arg1, !arg2, !arg3, !arg4, !arg5, !arg6)"
@@ -1747,7 +1765,7 @@ 

Multi-Line Operators

; This will be treated as "function func(param) = ((param*param)+1000)/256"

Single-Line Operator

- Contrary to the multi-line operators, the single-line operator : is a formatting operator which makes it possible to treat a single line of code as multiple lines. It requires a space before and after usage to differentiate it from the : used with certain commands. When used between different commands, Asar interprets it similarly to a new line and treats each command as being on a separate line. This can be used to link multiple commands together into functional blocks and make the code more readable. + Contrary to the multi-line operators, the single-line operator : is a formatting operator which makes it possible to treat a single line of code as multiple lines. It requires a space before and after usage to differentiate it from the : used with certain commands. When used between different commands, Asar interprets it similarly to a new line and treats each command as being on a separate line. This can be used to link multiple commands together into functional blocks and make the code more readable.
lda #$00 : sta $00
 		
 ; Treated as:
@@ -1759,13 +1777,13 @@ 

Single-Line Operator

The program counter (short: pc) refers to the position in the ROM at which Asar currently writes assembled code and/or data. It advances automatically whenever Asar writes to the ROM and is affected by the current mapping mode, as well as a number of special commands. Note that all commands affecting the pc that take an address expect an SNES address and thus are also affected by the current mapping mode.

org

org {snes_address}
- The org command directly sets the pc to snes_address. Most commonly used inside patches to specify which code to hijack or which data to overwrite. + The org command directly sets the pc to snes_address. Most commonly used inside patches to specify which code to hijack or which data to overwrite.
org $008000
 MainEntryPoint:
 	; ...

base

base {snes_address/off}
- The base command makes Asar act as though the pc was currently set to snes_address without actually setting it; base off deactivates this behavior. This can be useful for writing code that you plan to execute from another location (such as RAM). + The base command makes Asar act as though the pc was currently set to snes_address without actually setting it; base off deactivates this behavior. This can be useful for writing code that you plan to execute from another location (such as RAM).
org $008000
 MainEntryPoint:
 	; Some code which copies SomeRamRoutine to $7E0000 goes here
@@ -1781,7 +1799,7 @@ 

base

skip

skip {num_bytes}
 skip align {alignment} [offset {offset}]
- The skip command moves the pc by num_bytes bytes. By specifying a negative value, the pc can be moved backwards. When alignment is given, skips to the next multiple of alignment, plus offset if it is specified. Note that the alignment must be a power of 2, if specified. Offset can also be negative, in that case it's treated exactly like alignment+offset. The seeked-to position will always be after the current SNES position, but it might be before the next multiple of alignment: see the last example. + The skip command moves the pc by num_bytes bytes. By specifying a negative value, the pc can be moved backwards. When alignment is given, skips to the next multiple of alignment, plus offset if it is specified. Note that the alignment must be a power of 2, if specified. Offset can also be negative, in that case it's treated exactly like alignment+offset. The seeked-to position will always be after the current SNES position, but it might be before the next multiple of alignment: see the last example.
org $008000
 skip 5
 ; pc is now at $008005
@@ -1796,14 +1814,14 @@ 

skip

warnpc

warnpc {snes_address}
- DEPRECATED: you can achieve the exact same thing with assert pc() <= {snes_address}. - The warnpc command checks if the current pc is > snes_address. If that's the case, it throws an error. This is useful for detecting overflow errors. + DEPRECATED: you can achieve the exact same thing with assert pc() <= {snes_address}.

+ The warnpc command checks if the current pc is > snes_address. If that's the case, it throws an error. This is useful for detecting overflow errors.
org $008000
 incbin datafile.bin
 warnpc $008100		; Throws an error if datafile.bin is larger than $100 bytes.

bank

bank {data_bank/noassume/auto}
- The bank command makes Asar's label optimizer act as though the current data bank was set to data_bank. Consider the following example: + The bank command makes Asar's label optimizer act as though the current data bank was set to data_bank. Consider the following example:
bank $FF
 		
 lda DataTable,x
@@ -1842,7 +1860,7 @@ 

optimize address

This command changes how aggressive Asar's label optimizer is. With optimize address default, references to labels will be shortened to 2 bytes only if the label is in the current data bank. With optimize address ram, additionally labels between $7E:0000-$7E:1FFF will be shortened to 2 bytes if the current data bank has RAM mirrors ($00-$3F and $80-$BF). With optimize address mirrors, additionally labels between $00-3F:2000-7FFF (that is, $00:2000-$00:7FFF all the way up to $3F:2000-$3F:7FFF) will be shortened to 2 bytes whenever the current data bank has RAM mirrors. Note that in freespace, the current bank will be assumed from whether the freespace was started as freecode or freedata, not where the freespace was actually placed in the end.

pushpc/pullpc

- The pushpc command pushes the current pc to the stack, the pullpc command restores the pc by pulling its value from the stack. This can be useful for inserting code in another location and then continuing at the original location. + The pushpc command pushes the current pc to the stack, the pullpc command restores the pc by pulling its value from the stack. This can be useful for inserting code in another location and then continuing at the original location.
org $008000
 		
 Main:
@@ -1859,7 +1877,7 @@ 

pushpc/pullpc

bra Main

pushbase/pullbase

- The pushbase command pushes the current base to the stack, the pullbase command restores the base by pulling its value from the stack. + The pushbase command pushes the current base to the stack, the pullbase command restores the base by pulling its value from the stack.
base $7E2000
 		
 InsideRam:
@@ -1922,14 +1940,14 @@ 

pushbase/pullbase

.Data db $00,$01,$02 - db $03,$02,$03
+ db $03,$04,$05
Return to top

Labels

Labels are used to represent a position in the ROM and allow you to code without having to constantly update branches and jumps/calls. They can be used with any opcode, but were specifically designed to be used with branches, jumps, calls, pointer tables etc. When used with branches, they're automatically converted to offsets.

Main Labels

[#]{identifier}:
- Main labels are the top-most level of labels supported by Asar. They're global and thus can be directly acessed from anywhere. Their identifier can contain any of the following characters
+ Main labels are the top-most level of labels supported by Asar. They're global and thus can be directly accessed from anywhere. Their identifier can contain any of the following characters
a-z A-Z 0-9 _
org $008000
 		
@@ -1938,7 +1956,11 @@ 

Main Labels

jmp Main ; Equal to jmp $8000
An alternate form of defining main labels is by directly assigning a value to them. A common use-case for this is to make a label point to an existing address inside a ROM. Syntax:
{identifier} = {snes_address}
- where snes_address can be a number or any math statement evaluating to an SNES address. Note that defining a main label this way does not start a new sub label group. + where snes_address can be a number or any math statement evaluating to an SNES address: +
ImportantValue = $7E0200
+OtherImportantValue = ImportantValue+$04
Note that math statements cannot have spaces around the operands (as mentioned in math): +
ImportantValue = $7E0200
+; OtherImportantValue = ImportantValue + $04 ; this will NOT work; math statements cannot have spaces
Defining a main label by assigning a value does not start a new sub label group.
Main:
 ; ...
 
@@ -2108,10 +2130,10 @@ 

Structs

endstruct [align num]
where identifier can contain any of the following characters:
a-z A-Z 0-9 _
- The snes_address parameter can be any number literal or math statement evaluating to an SNES address. This address marks the start of the struct. The label parameter should be any number of labels, ideally coupled with skip commands. These labels become offsets into the struct. Internally, the struct command will do something similar to this + The snes_address parameter can be any number literal or math statement evaluating to an SNES address. This address marks the start of the struct. The label parameter should be any number of labels, ideally coupled with skip commands. These labels become offsets into the struct. Internally, the struct command will do something similar to this
pushpc
 base snes_address
- whereas the endstruct command will do something similar to this + whereas the endstruct command will do something similar to this
base off
 pullpc
Take a look at the simple example below: @@ -2122,7 +2144,7 @@

Structs

.SizeX: skip 1 .SizeY: skip 1 endstruct
- This defines a struct called ObjectList at location $7E0100 with a size of 7 (the sum of all skip commands). You can access into this struct like so: + This defines a struct called ObjectList at location $7E0100 with a size of 7 (the sum of all skip commands). You can access into this struct like so:
lda ObjectList.PosY
This is equal to:
lda $7E0103		; $7E0100+1+2
@@ -2187,7 +2209,7 @@

Structs

Namespaces

@@ -2293,7 +2315,7 @@

Global labels

Return to top

Defines

- Asar supports a define system that functions similarly to defines in other programming languages, such as C++. Defines are identifiers that you can assign any kind of text to and use in other places as substitues for that text. During compilation, Asar replaces each define it encounters with the respective text assigned to it. Defines are prefixed with a ! and declared as follows:
+ Asar supports a define system that functions similarly to defines in other programming languages, such as C++. Defines are identifiers that you can assign any kind of text to and use in other places as substitutes for that text. During compilation, Asar replaces each define it encounters with the respective text assigned to it. Defines are prefixed with a ! and declared as follows:
!{identifier} = {value}
!{identifier} = "{value}"
where identifier is a unique identifier that can contain any of the following characters:
@@ -2310,10 +2332,10 @@

Global labels

lda !x ; Treated as "lda $12$34" (will throw error) -!phr = "pha : phx : phy" +!phr = "pha : phx : phy" ; keeps whitespace !phr ; Treated as "pha : phx : phy" - To assign text containing whitespace to a define, you must delimit it with two " as shown above with !phr. Besides the regular define operator =, Asar also supports a number of additional define operators with slightly different functionality.

+ To assign text containing whitespace to a define, you must delimit it (surround it) with two ", as shown above with !phr. Besides the regular define operator =, Asar also supports a number of additional define operators with slightly different functionality.

@@ -2343,7 +2365,7 @@

Global labels

- + @@ -2356,7 +2378,7 @@

Global labels

; !define now contains "10"
Operator
#=Evalutes the text as though it was a math expression, calculates its result and assigns it to the define. The math is done in-place on the same line the operator is used on and is affected by all of Asar's math settings (such as prioritization rules and rouding behavior).Evaluates the text as though it was a math expression, calculates its result and assigns it to the define. The math is done in-place on the same line the operator is used on and is affected by all of Asar's math settings (such as prioritization rules and rounding behavior).
!define = 10
 !anotherdefine #= !define+1
 ; !anotherdefine now contains "11"

- Similarly to C's ifdef and undef, Asar allows you to check for a define's existence using the defined("{identifier}") function and to delete a define using the undef "{identifier}" command. Make sure to leave the ! out of the identifier when using these functions, as Asar would otherwise try to resolve the defines. + Similarly to C's ifdef and undef, Asar allows you to check for a define's existence using the defined("{identifier}") function and to delete a define using the undef "{identifier}" command. Make sure to leave the ! out of the identifier when using these functions, as Asar would otherwise try to resolve the defines.
!define = "hello"
 		
 if defined("define")
@@ -2370,7 +2392,7 @@ 

Global labels

endif
Note that Asar tries to replace defines wherever possible, even inside strings. In some occasions, this might be undesirable. See section Tables for details on how to escape certain characters.

Nested Defines

- By default, the define parser in Asar considers every supported character in a connected string to be a part of the define's name. This may not always be desired as it can lead to a certain define becoming inaccessible in a certain situation. In cases like that, the {} operator makes it possible to still use those defines by resovling everything inside the braces immediately. + By default, the define parser in Asar considers every supported character in a connected string to be a part of the define's name. This may not always be desired as it can lead to a certain define becoming inaccessible in a certain situation. In cases like that, the {} operator makes it possible to still use those defines by resolving everything inside the braces immediately.
!hex = $
 		
 db !hexFF     ; Error - define !hexFF not found
@@ -2418,7 +2440,7 @@ 

Built-in Defines

Macros are a mechanism for recording a sequence of commands that can be used in other places. The main purpose of this is to include commonly used code in multiple places without actually having to rewrite or copy that code every time. Instead you can move it into a macro and write it only once. Macros, in concept, work similarly to defines in that they are a text-replacement mechanism, but they have a few key differences:
  • Macros only record a sequence of commands rather than any kind of text.
  • -
  • A macro call is itself considered a command and thus needs to go on its on line (or separated via the single-line operator ). This means that unlike a define, a macro can't just be used whereever.
  • +
  • A macro call is itself considered a command and thus needs to go on its on line (or separated via the single-line operator ). This means that unlike a define, a macro can't just be used wherever.
  • Macros can include parameters, which are identifiers that are replaced by a text value whenever the respective macro is called. For simplicity, you could consider parameters a macro-specific version of defines.
Use the following syntax to define a macro: @@ -2428,7 +2450,7 @@

Built-in Defines

endmacro
where all the identifiers can contain any of the following characters:
a-z A-Z 0-9 _
- Use the syntax <parameter_identifier> to expand a parameter inside a macro. This works just like placing a !define_identifier anyhwere else in the code. Macros can be recursive (macros calling themselves) and/or nested up to 512 levels deep. This limit only serves the purpose of preventing infinite recursion. The first and last line of the macro definition need to go on their own lines (the single-line operator is not supported here). To call a macro that has already been defined, use the syntax + Use the syntax <parameter_identifier> to expand a parameter inside a macro. This works just like placing a !define_identifier anywhere else in the code. Macros can be recursive (macros calling themselves) and/or nested up to 512 levels deep. This limit only serves the purpose of preventing infinite recursion. The first and last line of the macro definition need to go on their own lines (the single-line operator is not supported here). To call a macro that has already been defined, use the syntax
%{identifier}([parameter1[, parameter2...]])
where each individual parameter may be wrapped in double quotes (which is required for parameters that contain any whitespace).
macro mov(target, source)
@@ -2530,7 +2552,8 @@ 

Built-in Functions

read2(pos[, default]) read3(pos[, default]) read4(pos[, default])
- Read one/two/three/four byte(s) from the output ROM at SNES location pos. Mainly intended for detecting the presence of certain hijacks/patches in a ROM. Throws an error when given an invalid address, unless the optional parameter default is provided in which case it is returned. + Read one/two/three/four byte(s) from the input ROM at SNES location pos. Mainly intended for detecting the presence of certain hijacks/patches in a ROM. Throws an error when given an invalid address, unless the optional parameter default is provided in which case it is returned.

+ Note that read() functions will never read or detect changes that you make or data that you write; they only read from the input ROM.
if read1($00FFD5) == $23
 	!is_sa1_rom = 1
 else
@@ -2542,7 +2565,7 @@ 

Built-in Functions

readfile2(filename, pos[, default]) readfile3(filename, pos[, default]) readfile4(filename, pos[, default])
- Read one/two/three/four byte(s) from file filename at position pos (see section Includes for details on Asar's handling of file names). Throws an error when the referenced file doesn't exist or the given position is out-of-bounds, unless the optional parameter default is provided in which case it is returned. + Read one/two/three/four byte(s) from file filename at position pos (see section Includes for details on Asar's handling of file names). Throws an error when the referenced file doesn't exist or the given position is out-of-bounds, unless the optional parameter default is provided in which case it is returned.
!readresult = readfile4("datafile.bin", 0, $FFFFFFFF)
 				
 if !readresult != $FFFFFFFF
@@ -2555,7 +2578,7 @@ 

Built-in Functions

canread3(pos) canread4(pos) canread(pos, num)
- Returns 1 if reading one/two/three/four/num bytes from the output ROM at SNES location pos would succeed and 0 otherwise. + Returns 1 if reading one/two/three/four/num bytes from the input ROM at SNES location pos would succeed and 0 otherwise.
if canread1($00FFD5) == 1
 	print "Detected ROM type: $",hex(read1($00FFD5))
 else
@@ -2568,7 +2591,7 @@ 

Built-in Functions

canreadfile3(filename, pos) canreadfile4(filename, pos) canreadfile(filename, pos, num)
- Returns 1 if reading one/two/three/four/num bytes from file filename at position pos would succeed and 0 otherwise (see section Includes for details on Asar's handling of file names). + Returns 1 if reading one/two/three/four/num bytes from file filename at position pos would succeed and 0 otherwise (see section Includes for details on Asar's handling of file names).
if canreadfile4("datafile.bin", 512) == 1
 	print "Read $",hex(readfile4("datafile.bin", 512))," from datafile.bin at position 512."
 else
@@ -2577,7 +2600,7 @@ 

Built-in Functions

filesize(filename) - Returns the size of file filename. Throws an error if the file doesn't exist. + Returns the size of file filename. Throws an error if the file doesn't exist.
!fsize #= filesize("datafile.bin")
 !fpos = 0
 
@@ -2592,7 +2615,7 @@ 

Built-in Functions

getfilestatus(filename) - Checks the status of file filename. Returns 0 if the file exists and can be read from, returns 1 if the file doesn't exist and returns 2 if the file exists, but can't be read from for any other reason (like being read-protected, being locked etc.). + Checks the status of file filename. Returns 0 if the file exists and can be read from; returns 1 if the file doesn't exist; and returns 2 if the file exists, but can't be read from for any other reason (like being read-protected, being locked etc.).
assert getfilestatus("datafile.bin") != 1, "datafile.bin doesn't seem to exist"
@@ -2645,7 +2668,7 @@

Built-in Functions

select(statement, true, false) Returns false if statement is 0 and true otherwise. Can be considered an if/else conditional that is usable within functions.
- NOTE: Asar always evaluates all parameters of a function before calling it, so if, for example, you pass an expression that divides by zero to select() as true, Asar will throw a division by zero error even if statement evalutes to 0 and thus false would be returned. To work around this, you can use the safediv() function in place of a regular division. + NOTE: Asar always evaluates all parameters of a function before calling it, so if, for example, you pass an expression that divides by zero to select() as true, Asar will throw a division by zero error even if statement evaluates to 0 and thus false would be returned. To work around this, you can use the safediv() function in place of a regular division.
function sprite_size() = select(!extra_bytes_enabled, 16+4, 16)
@@ -2764,6 +2787,7 @@

Built-in Functions

realbase() Returns the current address in the ROM being written to. This is not the same as the value of a nearby label when the base command is active: it returns the actual address the code will end up at. +

All built-in functions can be overridden by user-defined functions. Prepending an underscore (for example: _read1()) leads to the original function, which can be used to make an overridden function call its original function. @@ -2776,7 +2800,7 @@

Built-in Functions

Conditional Compilation

Conditional compilation allows you to only compile specific sections of code when certain conditions are met. This can be used in a number of ways, but is most commonly used in conjunction with defines to make code easily customizable and/or provide some simple configuration options to end users.

if/elseif/else/endif

- The most basic form of conditionals are if conditionals. They are given a math statement and only compile their enclosed code if that statement evaluates to a value greater than 0. + The most basic form of conditionals are if conditionals. They are given a math statement and only compile their enclosed code if that statement evaluates to a value greater than 0.
if {condition}
 	{codeblock}
 endif
@@ -2830,7 +2854,7 @@

if/elseif/else/endif

Returns 1 if both of a and b evaluate to 1
- Evaluation is lazy which means that the compiler will stop evaluating a condition as soon as the result can be determined (for example, in the condition 0 && my_function(), my_function() will never be called). Note that only one kind of logical operator can be used in a single condition, but conditionals themselves can be nested to an arbitrary depth, which can be used as a workaround here. Optionally, if conditionals can contain an arbitrary number of elseif branches as well as a single else branch. The compiler checks the if and all elseif branches in succession until a single condition evaluates to > 0 - if none does, the code inside the else branch is compiled. + Evaluation is lazy which means that the compiler will stop evaluating a condition as soon as the result can be determined (for example, in the condition 0 && my_function(), my_function() will never be called). Note that only one kind of logical operator can be used in a single condition, but conditionals themselves can be nested to an arbitrary depth, which can be used as a workaround here. Optionally, if conditionals can contain an arbitrary number of elseif branches as well as a single else branch. The compiler checks the if and all elseif branches in succession until a single condition evaluates to > 0 - if none does, the code inside the else branch is compiled.
!mode = 0	; Supported modes: 0, 1, 2, 3
 !verbose = 0	; Set to 1 to enable verbose mode
 
@@ -2848,14 +2872,14 @@ 

if/elseif/else/endif

else error "Unsupported mode! Please choose 0, 1, 2 or 3!" endif
- Alternatively, if conditionals can also be constructed on a single line via the following syntax: + Alternatively, if conditionals can also be constructed on a single line via the following syntax:
if {condition} : {codeblock}[ : codeblock...] : endif
- Note that else or elseif are unsupported when using this syntax. The endif used to be optional, but this functionality is deprecated. It's recommended to always add the endif at the end of the line. + Note that else or elseif are unsupported when using this syntax. The endif used to be optional, but this functionality is deprecated. It's recommended to always add the endif at the end of the line.
PressedY:
 	if !fireballs_enabled : %PlaySoundEffect(!fireball_sfx) : jsr ShootFireball : endif
 	rtl
 		
- If you plan to use labels in if commands, note that there's certain restrictions that apply. More specifically, only static labels can be used. That is, only labels whose address can't change between Asar's passes, as demonstrated by the following example: + If you plan to use labels in if commands, note that there's certain restrictions that apply. More specifically, only static labels can be used. That is, only labels whose address can't change between Asar's passes, as demonstrated by the following example:
FirstLabel = $018000
 		
 freecode
@@ -2872,7 +2896,7 @@ 

if/elseif/else/endif

if SecondLabel == 0 endif

while

- A special variation of if conditionals are while loops. Instead of compiling their enclosed code only once, they compile it repeatedly until their condition evaluates to <= 0. Typically, this would be used with a define that is modified inside the loop. This can be useful for generating data tables. + A special variation of if conditionals are while loops. Instead of compiling their enclosed code only once, they compile it repeatedly until their condition evaluates to <= 0. Typically, this would be used with a define that is modified inside the loop. This can be useful for generating data tables.
!counter = 0
 		
 while !counter < $10
@@ -2886,7 +2910,7 @@ 

while

Note that while loops can also end with endif, but this is deprecated. Be warned as improper use of while loops can lead to infinite loops and thus a dead-lock of the compiler, as Asar won't attempt to detect those.

for

- For loops repeat the contents a specified number of times. In the for loop body, you have access to a loop counter as a define. The range is specified as start-inclusive and end-exclusive. + for loops repeat the contents a specified number of times. In the for loop body, you have access to a loop counter as a define. The range is specified as start-inclusive and end-exclusive. For example:
for i = 1..5
@@ -2894,7 +2918,7 @@ 

for

db 2*!i endfor

This will write the bytes 01 02 02 04 03 06 04 08.

-

You can also put for loops on a single line, however in this case due to the order in which Asar parses defines, you will not be able to use the loop counter. E.g. for i = 0..10 : nop : endfor.

+

You can also put for loops on a single line, however in this case due to the order in which Asar parses defines, you will not be able to use the loop counter. E.g. for i = 0..10 : nop : endfor.

Return to top

Binary Data

@@ -2904,7 +2928,7 @@

Tables

dw {value}[,value...]
dl {value}[,value...]
dd {value}[,value...]
- Table commands let you insert a number or a list of numbers directly into the ROM as raw bytes. Use db for 8-bit numbers, dw for 16-bit numbers, dl for 24-bit numbers and dd for 32-bit numbers respectively, where value can be a number literal, a math statement, a label or an ASCII string delimited by double quotes. When using dw, dl or dd, each number is converted to little-endian. Big numbers are truncated to smaller integers as needed. + Table commands let you insert a number or a list of numbers directly into the ROM as raw bytes. Use db for 8-bit numbers, dw for 16-bit numbers, dl for 24-bit numbers and dd for 32-bit numbers respectively, where value can be a number literal, a math statement, a label or an ASCII string delimited by double quotes. When using dw, dl or dd, each number is converted to little-endian. Big numbers are truncated to smaller integers as needed.
org $0189AB
 Label:
 
@@ -2918,7 +2942,7 @@ 

Tables

dl $01,$0203,$04050607,Label,"ABC" ; $01 $00 $00 $00 $03 $02 $00 $00 $07 $06 $05 $04 $AB $89 $01 $00 $41 $00 $00 $00 $42 $00 $00 $00 $43 $00 $00 $00 dd $01,$0203,$04050607,Label,"ABC"
- By default, each character in an ASCII string used in in a table maps onto the respective ASCII value. This mapping can be customized via the table command: + By default, each character in an ASCII string used in in a table maps onto the respective ASCII value. This mapping can be customized via the table command:
table {filename}[,rtl/ltr]

Note: this command is deprecated and will be removed in Asar 2.0, see below (direct character assignment syntax) for the replacement.

Where filename specifies the path to a table file (enclose in double quotes to use file names with spaces, see section Includes for details on Asar's handling of file names) and ltr/rtl specifies whether that file is in left-to-right or right-to left format (default: left-to-right).
@@ -2928,7 +2952,7 @@

Tables

Format of right-to-left table files:
{value}={character}
 [value=character...]
- where character represents an ASCII character and value represents a hexadecimal number literal (without a prefix) to map to that ASCII character. Note that the table command initializes the mapping to garbage, so when using it, it's recommended to provide mappings for all ASCII characters. It's also possible to directly map characters inline without using a table file by using the syntax + where character represents an ASCII character and value represents a hexadecimal number literal (without a prefix) to map to that ASCII character. Note that the table command initializes the mapping to garbage, so when using it, it's recommended to provide mappings for all ASCII characters. It's also possible to directly map characters inline without using a table file by using the syntax
'{character}' = {value}
where value can be any number literal or math statement. This will be the only way to set the table in Asar 2.0.
To reset the current table mapping to a direct ASCII mapping, use the command cleartable. Additionally, the pushtable command lets you push the current table mapping to the stack, whereas the pulltable command lets you restore the mapping from the stack. @@ -2990,7 +3014,7 @@

fillbyte/fill

fillbyte {byte}
fill {num}
 fill align {alignment} [offset {offset}]
- The fillbyte and fill commands let you write a specific byte value to the ROM multiple times. The byte parameter of fillbyte specifies which value to write, wheres fill writes that value to the output ROM num times. If alignment is specified, the value will be written repeatedly until the SNES address has the specified alignment, similar to skip align. + The fillbyte and fill commands let you write a specific byte value to the ROM multiple times. The byte parameter of fillbyte specifies which value to write, wheres fill writes that value to the output ROM num times. If alignment is specified, the value will be written repeatedly until the SNES address has the specified alignment, similar to skip align.
fillbyte $FF
 ; This writes $FF $FF $FF $FF $FF $FF $FF $FF
 fill 8
@@ -3002,7 +3026,7 @@ 

fillbyte/fill

padbyte/pad

padbyte {byte}
pad {snes_address}
- The padbyte and pad commands let you write a specific byte value to the ROM until the pc reaches a certain SNES address. The byte parameter of padbyte specifies which value to write, wheres pad writes that value to the output ROM until the pc reaches snes_address. + The padbyte and pad commands let you write a specific byte value to the ROM until the pc reaches a certain SNES address. The byte parameter of padbyte specifies which value to write, wheres pad writes that value to the output ROM until the pc reaches snes_address.
org $008000
 padbyte $FF
 ; This writes $FF $FF $FF $FF
@@ -3010,7 +3034,7 @@ 

padbyte/pad

It's also possible to write 16-bit, 24-bit or 32-bit values with the pad command by using padword, padlong or paddword instead of padbyte. Note that the snes_address parameter of pad still specifies the end offset of the write in those cases. Values might get truncated as needed to exactly reach the specified end offset.

incbin

incbin {filename}[:range_start..range_end]
- The incbin command copies a binary file directly into the output ROM. The filename parameter specifies which file to copy (enclose in double quotes to use file names with spaces, see section Includes for details on Asar's handling of file names) and the optional range_start and range_end parameters are math expressions which specify a range of data to copy from the file (a range_end of 0 copies data until the end of the file; not specifying a range copies the entire file). The older form of this command used - as the separator of start and end, which caused ambiguities and was thus deprecated. + The incbin command copies a binary file directly into the output ROM. The filename parameter specifies which file to copy (enclose in double quotes to use file names with spaces, see section Includes for details on Asar's handling of file names) and the optional range_start and range_end parameters are math expressions which specify a range of data to copy from the file (a range_end of 0 copies data until the end of the file; not specifying a range copies the entire file). The older form of this command used - as the separator of start and end, which caused ambiguities and was thus deprecated.
; datafile.bin contains the following bytes:
 ; $00 $01 $02 $03 $04 $05 $06 $07 $08 $09 $0A $0B $0C $0D $0E $0F
 
@@ -3035,7 +3059,7 @@ 

incbin

incbin {filename} pullpc
- with the exception that incbin gains special permission to cross bank borders. In this case, the size limit of the included file is 65536 bytes due to how freespace works. For files with a size of 32767 or lower, no alignment is enforced. When label_name_or_sness_address is set to an SNES address, the code behaves identically to + with the exception that incbin gains special permission to cross bank borders. In this case, the size limit of the included file is 65536 bytes due to how freespace works. For files with a size of 32767 or lower, no alignment is enforced. When label_name_or_sness_address is set to an SNES address, the code behaves identically to
pushpc
 
 org {snes_address}
@@ -3066,7 +3090,11 @@ 

incbin

incsrc

incsrc {filename}
- The incsrc command makes Asar assemble the file referenced by the filename parameter (enclose in double quotes to use file names with spaces, see section Includes for details on Asar's handling of file names). The file is assembled in-place which means that Asar instantly switches to the new file and only returns to the previous file once assembling the new file has finished. All of Asar's state (labels, defines, functions, pc etc.) is shared between files. When including other files, there is a recursion limit of 512 levels. This limit only serves the purpose of preventing infinite recursion. For an easier understanding of incsrc, you can visualize it as a command which pastes the contents of another file directly into the current file (although that's not actually how it's implemented and there are differences in the way relative file paths are handled). + The incsrc command makes Asar assemble the file referenced by the filename parameter (enclose in double quotes to use file names with spaces, see section Includes for details on Asar's handling of file names). The file is assembled in-place which means that Asar instantly switches to the new file and only returns to the previous file once assembling the new file has finished.

+ + For an easier understanding of incsrc, you can visualize it as a command which pastes the contents of another file directly into the current file (although that's not actually how it's implemented and there are differences in the way relative file paths are handled).

+ + All of Asar's state (labels, defines, functions, pc etc.) is shared between files. When including other files, there is a recursion limit of 512 levels. This limit only serves the purpose of preventing infinite recursion.
; Contents of routine.asm:
 ;AnotherRoutine:
 ;	lda #$FF
@@ -3082,7 +3110,11 @@ 

incsrc

include/includefrom

include
includefrom {filename}
- The include and includefrom commands specify that a file is only to be included in another file and not to be assembled directly. When a user tries to assemble a file containing include or includefrom directly, an error is thrown. The includefrom command behaves identically to the include command with the exception that it is passed the name of the file it is meant to be included from (note that Asar doesn't verify whether it's actually included from that file, it only checks whether it's included from another file at all). When making use of include or includefrom, they must be the first command within their respective file and can't be used in combination with the asar or xkas command in the same file. + The include and includefrom commands specify that a file is only to be included in another file and not to be assembled directly. When a user tries to assemble a file containing include or includefrom directly, an error is thrown.

+ + The includefrom command behaves identically to the include command with the exception that it is passed the name of the file it is meant to be included from (note that Asar doesn't verify whether it's actually included from that file, it only checks whether it's included from another file at all).

+ + When making use of include or includefrom, they must be the first command within their respective file and can't be used in combination with the asar or xkas command in the same file.
; Contents of shared.asm:
 ;includefrom main.asm
 ;
@@ -3102,7 +3134,7 @@ 

include/includefrom

endif

includeonce

includeonce
- The includeonce command places an include guard on the file that is currently being assembled. This prevents it from being assembled again in the same pass. This is intended for shared files which may be included from multiple source files, but should only be assembled once to prevent redefinition errors etc. + The includeonce command places an include guard on the file that is currently being assembled. This prevents it from being assembled again in the same pass. This is intended for shared files which may be included from multiple source files, but should only be assembled once to prevent redefinition errors etc.
; Contents of shared.asm:
 ;
 ;includeonce
@@ -3122,12 +3154,16 @@ 

includeonce

Return to top

Freespace

- Freespace is a concept that comes into play when extending an existing ROM. To insert new code or data into a ROM, the ROM must contain enough continuous unused space for everything to fit into. Space like that is referred to as freespace. Many tools attempt to find freespace in a ROM by looking for continuous blocks of a certain value (most commonly $00). This method on its own isn't reliable as freespace finders could erroneously detect binary data or code with a certain pattern as freespace. For this reason, the RATS format was invented to protect data inserted into a ROM (see SMW Wiki for details on the RATS format). When placing RATS tags at the beginning of occupied memory blocks inside a ROM, freespace finders can search for them to know which parts of the ROM not to overwrite. Asar supports a number of commands for working with freespace directly, including freespace finders with automatic RATS tag generation. + Freespace is a concept that comes into play when extending an existing ROM. To insert new code or data into a ROM, the ROM must contain enough continuous unused space for everything to fit into. Space like that is referred to as freespace.

+ + Many tools attempt to find freespace in a ROM by looking for continuous blocks of a certain value (most commonly $00). This method on its own isn't reliable as freespace finders could erroneously detect binary data or code with a certain pattern as freespace. For this reason, the RATS format was invented to protect data inserted into a ROM (see SMW Wiki for details on the RATS format). When placing RATS tags at the beginning of occupied memory blocks inside a ROM, freespace finders can search for them to know which parts of the ROM not to overwrite.

+ + Asar supports a number of commands for working with freespace directly, including freespace finders with automatic RATS tag generation.

freespace/freecode/freedata

freespace {ram/noram}[,align][,cleaned][,static][,value]
freecode [align][,cleaned][,static][,value]
freedata [align][,cleaned][,static][,value]
- The freespace command makes Asar search the output ROM for a freespace area large enough to contain the following section of code/data. If such an area is found, the pc is placed at its beginning and a RATS tag automatically written. If no such area is found, an error is thrown. The parameters control what kind of freespace to look for. + The freespace command makes Asar search the output ROM for a freespace area large enough to contain the following section of code/data. If such an area is found, the pc is placed at its beginning and a RATS tag automatically written. If no such area is found, an error is thrown. The parameters control what kind of freespace to look for.

@@ -3159,7 +3195,9 @@

freespace/freecode/freedata

A number literal or math statement specifying the byte value to look for when searching for freespace (default: $00). To find freespace, Asar will look for continuous areas of this value. When using autoclean on this freespace, this is also the value the area will be cleaned to. Note that specifying the byte like this is deprecated. You should use the separate freespacebyte command instead.

- The freecode command is an alias of freespace ram, whreas the freedata command is an alias of freespace noram. There are a few things to note when working with freespace in Asar. First of all, if Asar places two freespace areas within the same bank, it will use 24-bit addressing in cases where they reference each other, despite 16-bit addressing being possible in theory. This can be worked around by only using a single freespace area instead. It's not recommended to explicitly use 16-bit addressing in these cases as the two freespace areas are not guaranteed to always end up in the same bank for all users. Secondly, when Asar places two freespace areas close to each other, a few bytes will be wasted between them for technical reasons. In most practical scenarios, the amount of wasted space should be reasonably small (< 1% of the code size), nevertheless this once again can be worked around by only using a single freespace area instead. Lastly, the number of freespace areas a single Asar patch can place is limited to a maximum of 125. + The freecode command is an alias of freespace ram, whereas the freedata command is an alias of freespace noram.

+ + There are a few things to note when working with freespace in Asar. First of all, if Asar places two freespace areas within the same bank, it will use 24-bit addressing in cases where they reference each other, despite 16-bit addressing being possible in theory. This can be worked around by only using a single freespace area instead. It's not recommended to explicitly use 16-bit addressing in these cases as the two freespace areas are not guaranteed to always end up in the same bank for all users. Secondly, when Asar places two freespace areas close to each other, a few bytes will be wasted between them for technical reasons. In most practical scenarios, the amount of wasted space should be reasonably small (< 1% of the code size), nevertheless this once again can be worked around by only using a single freespace area instead. Lastly, the number of freespace areas a single Asar patch can place is limited to a maximum of 125.
; Let's assume this to be some location in the ROM originally containing
 ;lda #$10
 ;sta $1F
@@ -3184,11 +3222,11 @@ 

freespacebyte

autoclean

autoclean jml/jsl/dl {label}
autoclean {snes_address}
- The autoclean command makes it possible for Asar to automatically clean up and reuse all of the freespace allocated by a patch when applying that patch again. The purpose of this is to prevent freespace leaks. Normally, applying a patch including a freespace (or similar) command to the same ROM multiple times would allocate a new freespace area each time. Since Asar automatically protects allocated freespace via RATS tags, all freespace areas previously allocated by the same patch would leak and become unusable, making the output ROM run out of freespace eventually. The autoclean command can prevent this by freeing up freespace areas previously allocated by the patch before allocating new ones. How it accomplishes this depends on how it is used: + The autoclean command makes it possible for Asar to automatically clean up and reuse all of the freespace allocated by a patch when applying that patch again. The purpose of this is to prevent freespace leaks. Normally, applying a patch including a freespace (or similar) command to the same ROM multiple times would allocate a new freespace area each time. Since Asar automatically protects allocated freespace via RATS tags, all freespace areas previously allocated by the same patch would leak and become unusable, making the output ROM run out of freespace eventually. The autoclean command can prevent this by freeing up freespace areas previously allocated by the patch before allocating new ones. How it accomplishes this depends on how it is used:
  • When used with a jml or jsl:
    - The label parameter must be a label pointing to inside a freespace area. When the patch is applied and the autoclean is encountered, Asar checks whether the output ROM contains a jml/jsl at the current pc. If it does, Asar checks whether the jml/jsl points to the expanded area of the ROM (banks $10+). If it does, Asar checks whether the jml/jsl points to an area protected by a RATS tag (including the RATS tag itself). If it does, Asar cleans up that area and removes the RATS tag. + The label parameter must be a label pointing to inside a freespace area. When the patch is applied and the autoclean is encountered, Asar checks whether the output ROM contains a jml/jsl at the current pc. If it does, Asar checks whether the jml/jsl points to the expanded area of the ROM (banks $10+). If it does, Asar checks whether the jml/jsl points to an area protected by a RATS tag (including the RATS tag itself). If it does, Asar cleans up that area and removes the RATS tag.
  • When used with a dl:
    @@ -3196,14 +3234,14 @@

    autoclean

  • When used with just an address:
    - The snes_address parameter must be any label, number literal or math statement evaluating to an SNES address pointing to inside a freespace area. When the patch is applied and the autoclean is encountered, Asar checks whether that address points to the expanded area of the ROM (banks $10+). If it does, Asar checks whether it points to an area protected by a RATS tag (including the RATS tag itself). If it does, Asar cleans up that area and removes the RATS tag. + The snes_address parameter must be any label, number literal or math statement evaluating to an SNES address pointing to inside a freespace area. When the patch is applied and the autoclean is encountered, Asar checks whether that address points to the expanded area of the ROM (banks $10+). If it does, Asar checks whether it points to an area protected by a RATS tag (including the RATS tag itself). If it does, Asar cleans up that area and removes the RATS tag.
- When using autoclean with a jml, jsl or dl, Asar will also assemble the respective line of code at the current pc. For simplicity, you can treat the autoclean command like a modifier in those cases. A few more things to note when using the autoclean command: + When using autoclean with a jml, jsl or dl, Asar will also assemble the respective line of code at the current pc. For simplicity, you can treat the autoclean command like a modifier in those cases. A few more things to note when using the autoclean command:
    -
  • The autoclean command itself may not be used inside a freespace area. To automatically clean up freespace that is only referenced within another freespace area, you can use the prot command.
  • -
  • It is safe to have multiple autoclean commands pointing to the same freespace area.
  • -
  • You can not use autoclean with a label pointing to the very end of a freespace area.
  • +
  • The autoclean command itself may not be used inside a freespace area. To automatically clean up freespace that is only referenced within another freespace area, you can use the prot command.
  • +
  • It is safe to have multiple autoclean commands pointing to the same freespace area.
  • +
  • You can not use autoclean with a label pointing to the very end of a freespace area.
; Let's assume this to be some location in the ROM containing a function pointer table or similar
 org $00A5F2
@@ -3221,7 +3259,7 @@ 

autoclean

rtl

prot

prot {label}[,label...]
- The prot command makes it possible for Asar to automatically clean up a freespace area that is only referenced within another freespace area and thus can't be cleaned via an autoclean directly. It must be used at the beginning of a freespace area (right after the freespace command), where the label parameter must be a label pointing to inside a freespace area (you can pass up to 85 labels separated by commas to a single prot). When a freespace area containing a prot is cleaned by an autoclean, all freespace areas referenced by the prot are also cleaned up. + The prot command makes it possible for Asar to automatically clean up a freespace area that is only referenced within another freespace area and thus can't be cleaned via an autoclean directly. It must be used at the beginning of a freespace area (right after the freespace command), where the label parameter must be a label pointing to inside a freespace area (you can pass up to 85 labels separated by commas to a single prot). When a freespace area containing a prot is cleaned by an autoclean, all freespace areas referenced by the prot are also cleaned up.
org $0194BC
 	autoclean jsl MyNewFunction
 	
@@ -3260,7 +3298,7 @@ 

prot

Text Output

Text output functions allow you to communicate certain information, states, warnings, errors etc. to end users of your code.

print

- The print command lets you output general-purpose text to the user. Most commonly this is used to inform the user about certain states or to output debug information. Usage: + The print command lets you output general-purpose text to the user. Most commonly this is used to inform the user about certain states or to output debug information. Usage:
print {text_or_function}[,text_or_function...]
where text_or_function can be either a string delimited by double quotes or one of the print-specific functions below:

@@ -3303,37 +3341,41 @@

print

to reset this value.

+ You can chain as many strings or functions as you need to a single print command: +
print "You need to know about:", hex(read1(PlayerHealth)), " and ", dec(10+20), ", and ", hex(read1(PlayerMana))

warn

- The warn command lets you output a warning message to the user. Usage: + The warn command lets you output a warning message to the user. Usage:
warn [text_or_function...]
- where custom_warning_text can be a custom warning text and uses the same format as the print command. A warning does not cause compilation to fail, so it can be used to inform the user about potential dangers. Warning messages are printed to stderr by default, but are printed to stdout if the Asar executable is renamed to xkas.exe. This is intended for compatibility purposes. + where text_or_function can be a custom warning text and uses the same format as the print command. A warning does not cause compilation to fail, so it can be used to inform the user about potential dangers. Warning messages are printed to stderr by default, but are printed to stdout if the Asar executable is renamed to xkas.exe. This is intended for compatibility purposes.
if read1($00FFD5) == $23
 	warn "SA-1 compatibility of this patch is untested, use with caution!"
 endif

error

- The error command lets you output an error message to the user. Usage: + The error command lets you output an error message to the user. Usage:
error [text_or_function...]
- where custom_error_text can be a custom error text and uses the same format as the print command. An error causes compilation to fail, so it should be used to inform the user about irrecoverable error states. Error messages are printed to stderr by default, but are printed to stdout if the Asar executable is renamed to xkas.exe. This is intended for compatibility purposes. + where text_or_function can be a custom error text and uses the same format as the print command. An error causes compilation to fail, so it should be used to inform the user about irrecoverable error states. Error messages are printed to stderr by default, but are printed to stdout if the Asar executable is renamed to xkas.exe. This is intended for compatibility purposes.
if read1($00FFD5) == $23
 	error "This patch is not SA-1 compatible!"
 endif

assert

- An assert can be considered a short version of the code + An assert lets you check or test whether something is true, and raise an error if it isn't. An assert can be considered a short version of the code
if {condition}
 else
 	error [text_or_function...]
 endif
and is used via the syntax
assert {condition}[,text_or_function...]
- where custom_error_text can be a custom error text and uses the same format as the print command. If condition evaluates to <= 0, an error is thrown, otherwise nothing happens. -
assert read1($00FFD5) != $23,"This patch is not SA-1 compatible!"
+ where text_or_function can be a custom error text and uses the same format as the print command. If condition evaluates to <= 0, an error is thrown, otherwise nothing happens. +
assert read1($00FFD5) != $23,"This patch is not SA-1 compatible!"
+assert read2(Header.Checksum) == Checksum, "0x", hex(Header.Checksum), "==", hex(read2(Header.Checksum))
+        
Return to top

Checks

Checks allow Asar to monitor certain states and throw warnings or errors when certain criteria are met. This can be helpful for catching or preventing certain problems.

check title

check title "{title}"
- The check title command verifies that the title stored in the output ROM is identical to title. If it isn't, an error is thrown (unless --no-title-check is passed to the application, in which case only a warning is thrown - see section Usage for details). The purpose of this command is to assure that patches are applied to the correct output ROM. + The check title command verifies that the title stored in the input ROM is identical to title. If it isn't, an error is thrown (unless --no-title-check is passed to the application, in which case only a warning is thrown - see section Usage for details). The purpose of this command is to assure that patches are applied to the correct input ROM.
; This patch is only for a Super Mario World ROM
 check title "SUPER MARIOWORLD     "
 
@@ -3358,7 +3400,11 @@ 

check bankcross

Return to top

Warnings

- Warnings are messages that Asar outputs to inform the user about potentially unintended or risky code that isn't critical and thus doesn't cause assembly to fail on its own. These messages can be useful for detecting potential problems in the code, but in some situations may be undesirable. For this reason, Asar supports a few methods of explicitly enabling or disabling certain warnings (see section Usage for details on how to configure warnings via the command line). Additionally, there are warnings which may be useful in some situations, but would be intrusive in most other situations. They are disabled by default and have to be enabled explicitly to be used. Commands that enable or disable warnings refer to them via their names. The easiest way of finding the name of a specific warning is to look at the console output of a patch producing it. Asar will always output the warning name along with the respective warning. Warnings also have ID numbers, but those are deprecated and will be removed in Asar 2.0. It is recommended to use the warning names instead (which are more descriptive anyways). + Warnings are messages that Asar outputs to inform the user about potentially unintended or risky code that isn't critical and thus doesn't cause assembly to fail on its own. These messages can be useful for detecting potential problems in the code, but in some situations may be undesirable. For this reason, Asar supports a few methods of explicitly enabling or disabling certain warnings (see section Usage for details on how to configure warnings via the command line).

+ + Additionally, there are warnings which may be useful in some situations, but would be intrusive in most other situations. They are disabled by default and have to be enabled explicitly to be used.

+ + Commands that enable or disable warnings refer to them via their names. The easiest way of finding the name of a specific warning is to look at the console output of a patch producing it. Asar will always output the warning name along with the respective warning. Warnings also have ID numbers, but those are deprecated and will be removed in Asar 2.0. It is recommended to use the warning names instead (which are more descriptive anyway).

Disabled Warnings

This is a list of all warnings that are disabled by default and have to be enabled explicitly.

@@ -3368,7 +3414,9 @@

Disabled Warnings

- +
Wimplicitly_sized_immediateThrown when opcodes are sized implicitly and Asar has to assume a size. An opcode is considered to be sized explicitly when either a length specifier is used or a simple hex constant that can be assumed to be of a specific size (that is, a hex constant with either two or four digits). Opcodes that don't support multiple sizes are always considered to be sized explicitly. Everything else is considered to be sized implicitly and will throw this warning when enabled.Thrown when opcodes are sized implicitly and Asar has to assume a size. An opcode is considered to be sized explicitly when either a length specifier is used or a simple hex constant that can be assumed to be of a specific size (that is, a hex constant with either two or four digits).
+ + Opcodes that don't support multiple sizes are always considered to be sized explicitly. Everything else is considered to be sized implicitly and will throw this warning when enabled.
Wcheck_memory_file