From cfde5831f7d0d4cd9eb3d25dbc8415a5a3b8b721 Mon Sep 17 00:00:00 2001 From: culix Date: Mon, 22 Dec 2025 09:13:32 -0700 Subject: [PATCH 1/2] docs - replace `
` trailing slashes with `
` no trailing slash according to https://validator.w3.org/, this is more correct --- docs/manual/index.html | 168 ++++++++++++++++++++--------------------- 1 file changed, 84 insertions(+), 84 deletions(-) diff --git a/docs/manual/index.html b/docs/manual/index.html index c73f9b68..f29ea5c6 100644 --- a/docs/manual/index.html +++ b/docs/manual/index.html @@ -12,7 +12,7 @@

Asar

-

Asar is 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.


@@ -186,7 +186,7 @@

Asar

asar.exe --version C:/homebrew/my_game/main.asm
- -v
--verbose + -v
--verbose Input Enables verbose mode.
asar.exe -v C:/homebrew/my_game/main.asm
@@ -201,15 +201,15 @@

Asar

--pause-mode={mode} Input - Sets Asar's pause mode, specifying when Asar should pause the application before exit, where {mode} can be one of the following:
- never: Don't pause the application (default).
- on-error: Pause the application if an error was thrown.
- on-warning: Pause the application if an error or a warning was thrown.
+ Sets Asar's pause mode, specifying when Asar should pause the application before exit, where {mode} can be one of the following:
+ never: Don't pause the application (default).
+ on-error: Pause the application if an error was thrown.
+ on-warning: Pause the application if an error or a warning was thrown.
always: Always pause the application.
asar.exe --pause-mode=always C:/homebrew/my_game/main.asm
- -I{path}
--include {path} + -I{path}
--include {path} Input Adds an include search path for file-based commands to Asar. Normally, commands like incsrc, incbin etc. look for files relative to the ASM file that is currently being compiled. If those files aren't found, an error is thrown, unless you specify include search paths, in which case Asar will look for the file in each respective directory before throwing an error. For example, imagine you compiled the file
C:/homebrew/my_game.asm
@@ -229,7 +229,7 @@

Asar

C:/homebrew/my_game/main.asm C:/homebrew/my_game/bin/my_game.sfc - -D{identifier}[=value]
--define {identifier}[=value] + -D{identifier}[=value]
--define {identifier}[=value] Input Adds a define to Asar. When no value is provided, the define is set to an empty string. See section Defines for details.
asar.exe -Ddebug -Dskip_title_screen=0
@@ -240,16 +240,16 @@ 

Asar

--symbols={format} Input - Specifies the format of the symbols output file generated by Asar. The following values are supported for {format}:
- none: Don't generate a symbols file (default).
- wla: Generate a symbols file in the WLA format. This format additionally includes an address-to-line mapping which can be used by some debuggers to provide source-level debugging.
+ Specifies the format of the symbols output file generated by Asar. The following values are supported for {format}:
+ none: Don't generate a symbols file (default).
+ wla: Generate a symbols file in the WLA format. This format additionally includes an address-to-line mapping which can be used by some debuggers to provide source-level debugging.
nocash: Generate a symbols file in the no$sns format.
asar.exe --symbols=wla C:/homebrew/my_game/main.asm
--symbols-path={path} Output - Specifies the path and file name to use for generating the symbols output file. By default, the path is the path of [rom_file] and the file name is the base name of [rom_file] with an extension of .sym. Ignored when --symbols is set to none.
+ Specifies the path and file name to use for generating the symbols output file. By default, the path is the path of [rom_file] and the file name is the base name of [rom_file] with an extension of .sym. Ignored when --symbols is set to none.
Note that relative paths here are relative from the current working directory, not relative from {asm_file} or [rom_file].
asar.exe --symbols=wla
 	--symbols-path=C:/homebrew/my_game/symbols/main.symbols
@@ -270,7 +270,7 @@ 

Asar

--fix-checksum={on/off} Input - Overrides Asar's default behavior of enabling or disabling checksum generation based on context. When set to on, Asar always generates a checksum. When set to off, Asar never generates a checksum.
+ Overrides Asar's default behavior of enabling or disabling checksum generation based on context. When set to on, Asar always generates a checksum. When set to off, Asar never generates a checksum.
asar.exe --fix-checksum=on C:/homebrew/my_game/main.asm
@@ -301,12 +301,12 @@

Asar

asar.exe C:/homebrew/my_game/main.asm
-
+
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.
+ 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
 
@@ -316,7 +316,7 @@ 

Standard Includes

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 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.
+ 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
@@ -329,7 +329,7 @@ 

Standard Defines


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). -

+

@@ -1503,7 +1503,7 @@

Standard Defines

Architecture Compiles code for the Super FX architecture.
-
+
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
@@ -1601,12 +1601,12 @@ 

spcblock

dw $0000,$6004 ; execution_address (exec_start label position)
-
+
Return to top

Mapping Modes

- Asar supports a number of different mapping modes. They control the address translation used by Asar during compilation (aka where in the output file Asar writes to). Historically, SNES cartridges used a number of different mappers to address data in ROM. Those mappers can be supported by using the respective mapping mode in Asar. It's possible, but not recommended, to use different mapping modes on the same ROM. Detailed explanations on each mapping mode are beyond the scope of this manual, so please check the SNES Dev Manual or other specialized resources for that.
- NOTE: Changing the mapper after having previously set it will generate warning Wmapper_already_set.

+ Asar supports a number of different mapping modes. They control the address translation used by Asar during compilation (aka where in the output file Asar writes to). Historically, SNES cartridges used a number of different mappers to address data in ROM. Those mappers can be supported by using the respective mapping mode in Asar. It's possible, but not recommended, to use different mapping modes on the same ROM. Detailed explanations on each mapping mode are beyond the scope of this manual, so please check the SNES Dev Manual or other specialized resources for that.
+ NOTE: Changing the mapper after having previously set it will generate warning Wmapper_already_set.

@@ -1646,7 +1646,7 @@

spcblock

-
Command norom 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 input ROM. If that isn't possible, Asar defaults to lorom.
lorom
 org $008000
@@ -1655,7 +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.

+ 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

@@ -1722,7 +1722,7 @@

math round

!some_number #= 0.75

namespace nested

namespace nested {on/off}
- The namespace nested command enables (on) or disables (off) nested namespaces. The default is off. See section Namespaces for details.

+ The namespace nested command enables (on) or disables (off) nested namespaces. The default is off. See section Namespaces for details.

Return to top

Code Formatting

@@ -1732,7 +1732,7 @@

Comments

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
 	
@@ -1912,7 +1912,7 @@ 

pushbase/pullbase

lda #5+6*2 ; the same as "lda #17" lda #(5+6)*2 ; the same as "lda #22"
- Math statements in Asar support the following operators:

+ Math statements in Asar support the following operators:

+  : Addition (Also valid as prefix, but a no-op)
 -  : Subtraction (Or negation prefix)
@@ -1926,7 +1926,7 @@ 

pushbase/pullbase

^ : Bitwise XOR (Note: not exponentials) ~ : Bitwise NOT (Prefix) <: : Bitshift right 16, shorthand for isolating address bank (Prefix) -** : Exponentials (2**4 = 2*2*2*2 = pow(2, 4) in C)

+** : Exponentials (2**4 = 2*2*2*2 = pow(2, 4) in C)

Note that whitespace is not supported inside math statements, but the multi-line operator \ can be used to split them into multiple lines. Using math in labels can be useful when you want to apply an offset to the label:
lda .Data+3	; Will load $03 into A
@@ -1940,7 +1940,7 @@ 

pushbase/pullbase

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 accessed 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
 		
@@ -2059,13 +2059,13 @@ 

+/- Labels

+: ; C - note that +/- labels can also include an optional colon in their declaration dex bpl -- ; Branches to "A"
- +/- labels are useful in a number of situations. For example: inside a long routine with multiple short loops, where even a sub label like .Loop would get repetitive. +/- labels aren't bound to any scope, which means they can technically be used across different scopes. Just like sub labels, +/- labels are converted to main labels internally. Unlike sub labels, they can not be referenced from code directly since their names depend on where in the code they're used, making it impractical to directly refer to them. This is by design. They can, however, be accessed via the Asar DLL API, and their full name may appear in error messages printed by Asar. The naming format used for them is
- :pos_x_y
- for + labels and
- :neg_x_y
- for - labels, where
- x = number of chained +/-
- and
+ +/- labels are useful in a number of situations. For example: inside a long routine with multiple short loops, where even a sub label like .Loop would get repetitive. +/- labels aren't bound to any scope, which means they can technically be used across different scopes. Just like sub labels, +/- labels are converted to main labels internally. Unlike sub labels, they can not be referenced from code directly since their names depend on where in the code they're used, making it impractical to directly refer to them. This is by design. They can, however, be accessed via the Asar DLL API, and their full name may appear in error messages printed by Asar. The naming format used for them is
+ :pos_x_y
+ for + labels and
+ :neg_x_y
+ for - labels, where
+ x = number of chained +/-
+ and
y = instance of this label within all +/- labels of the same name (starting from 0 for + labels and from 1 for - labels).
lorom
 org $008000
@@ -2113,16 +2113,16 @@ 

Macro Labels

; ERROR! ?MacroMainLabel is undefined, because we're not inside %do_something() anymore. dl ?MacroMainLabel
Prefixing a macro label definition (except for macro label assignments and macro +/- labels) with a # will define the macro label without modifying existing label hierarchies, but there is probably no practical use for this, so it should be avoided. - Like all other labels, macro labels are converted to main labels internally and prefixed with an identifier of
- :macro_x_
+ Like all other labels, macro labels are converted to main labels internally and prefixed with an identifier of
+ :macro_x_
where x = total macro call instance. They can't be referenced in code directly, except inside their respective macro and using the respective macro label syntax seen above. They can, however, be accessed via the Asar DLL API, and their full name may appear in error messages printed by Asar.

Structs

Structs are an advanced form of labels with the purpose of making access into structured data blocks easier. The general syntax is as follows
struct {identifier} {snes_address}
 	[label...]
 endstruct [align num]
- where identifier can contain any of the following characters:
- a-z A-Z 0-9 _
+ 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
pushpc
 base snes_address
@@ -2143,8 +2143,8 @@

Structs

lda $7E0103		; $7E0100+1+2
The final address is calculated by taking the start of the struct ($7E0100) and adding to that all the skips preceding the .PosY label (1 and 2). Aside from accessing structs directly, it's also possible to access them as arrays. A simple example:
lda ObjectList[2].PosY
- The final address in this case is calculated by the equation:
- struct_start + (array_index * struct_size) + label_offset
+ The final address in this case is calculated by the equation:
+ struct_start + (array_index * struct_size) + label_offset
So in this case, our final address is $7E0100 + (2 * 7) + (1 + 2) = $7E0111. When using structs this way, the optional align parameter becomes relevant. This parameter controls the struct's alignment. Simply put, when setting a struct's alignment, Asar makes sure that its size is always a multiple of that alignment, increasing the size as necessary to make it a multiple. Let's take another look at the example above with an added alignment:
struct ObjectList $7E0100
 	.Type: skip 1
@@ -2166,7 +2166,7 @@ 

Structs

endstruct align 16
its original size becomes 17. Since a final size of 16 would now be too small to contain the entire struct, the alignment instead makes the struct's final size become 32 (the first multiple of 16 that 17 bytes fit into), so in our example of
lda ObjectList[2].PosY
- we now end up with a final address of $7E0100 + (2 * 32) + (1 + 2) = $7E0143.

+ we now end up with a final address of $7E0100 + (2 * 32) + (1 + 2) = $7E0143.

Another feature that is unique to structs is the possibility of extending previously defined structs with new data. The general syntax for this is as follows:
struct {extension_identifier} extends {parent_identifier}
 	[label...]
@@ -2188,16 +2188,16 @@ 

Structs

endstruct
The struct ObjectList now contains a child struct Properties which can be accessed like so:
lda ObjectList.Properties.FlipX
- Since extension structs are added at the end of their parent structs, the offset of .FlipX in this example is calculated as
- parent_struct_start_address + parent_struct_size + extension_struct_label_offset,
+ Since extension structs are added at the end of their parent structs, the offset of .FlipX in this example is calculated as
+ parent_struct_start_address + parent_struct_size + extension_struct_label_offset,
in other words, our final address is $7E0100 + 7 + (1 + 2) = $7E0109. Note that extending a struct also changes its size, so in this example, the final size of the ObjectList struct becomes 12. Extended structs can also be accessed as arrays. This works on the parent struct, as well as the extension struct.
lda ObjectList[2].Properties.FlipX
lda ObjectList.Properties[2].FlipX
- In the first example, our final address is calculated as
- parent_struct_start_address + (combined_struct_size * array_index) + parent_struct_size + extension_struct_label_offset,
- whereas in the second example, it's calculated as
- parent_struct_start_address + parent_struct_size + (extension_struct_size * array_index) + extension_struct_label_offset,
- so we end up with final addresses of $7E0100 + (12 * 2) + 7 + (1 + 2) = $7E0122 and $7E0100 + 7 + (5 * 2) + (1 + 2) = $7E0114.

+ In the first example, our final address is calculated as
+ parent_struct_start_address + (combined_struct_size * array_index) + parent_struct_size + extension_struct_label_offset,
+ whereas in the second example, it's calculated as
+ parent_struct_start_address + parent_struct_size + (extension_struct_size * array_index) + extension_struct_label_offset,
+ so we end up with final addresses of $7E0100 + (12 * 2) + 7 + (1 + 2) = $7E0122 and $7E0100 + 7 + (5 * 2) + (1 + 2) = $7E0114.

A few further things to note when using structs in Asar:
  • It's possible to extend a single struct with multiple extension structs. However, this can be counter-intuitive. The size of the extended struct becomes the size of the parent struct plus the size of its largest extension struct, rather than the size of the parent struct plus the sizes of each of its extension structs. This also means that when accessing those extension structs, they all start at the same offset relative to the parent struct. This can be confusing and is often not what's actually intended, so for code clarity, it's recommended to only extend structs with at most a single other struct.
  • @@ -2206,10 +2206,10 @@

    Structs

  • An extension struct can't be extended itself.

Namespaces

- Namespaces are a feature which makes it easier to avoid name conflicts between different labels without having to give them long or cryptic names. They work similarly to C++ namespaces and accomplish this by automatically adding a prefix to all labels declared or accessed within them. This prefix consists of an identifier, followed by an underscore _ . Namespaces can be stacked if desired by enabling the namespace nested setting. When you try to access a label from within a namespace and Asar doesn't find it in there, it automatically looks in the upper namespaces (up to the global namespace). Use
+ Namespaces are a feature which makes it easier to avoid name conflicts between different labels without having to give them long or cryptic names. They work similarly to C++ namespaces and accomplish this by automatically adding a prefix to all labels declared or accessed within them. This prefix consists of an identifier, followed by an underscore _ . Namespaces can be stacked if desired by enabling the namespace nested setting. When you try to access a label from within a namespace and Asar doesn't find it in there, it automatically looks in the upper namespaces (up to the global namespace). Use
namespace {identifier}
- to enter a namespace, where identifier can contain any of the following characters:
- a-z A-Z 0-9 _
+ to enter a namespace, where identifier can contain any of the following characters:
+ a-z A-Z 0-9 _
Use
namespace off
to leave the current namespace (or immediately return to the global namespace when nested namespaces are not enabled). @@ -2311,8 +2311,8 @@

Global labels

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:
- a-z A-Z 0-9 _
+ where identifier is a unique identifier that can contain any of the following characters:
+ a-z A-Z 0-9 _
The space on both sides of the = is required, which means that !identifier=value will not work. Since defines are really just placeholders for text, they can contain anything - labels, math formulas, even other defines.
!x = $00
 		
@@ -2328,7 +2328,7 @@ 

Global labels

!phr = "pha : phx : phy" ; keeps whitespace !phr ; Treated as "pha : phx : phy"
- 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.

+ 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.

@@ -2370,7 +2370,7 @@

Global labels

!define ?= 1 ; !define now contains "10" -
Operator

+
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"
 		
@@ -2405,7 +2405,7 @@ 

Nested Defines

print "Building in mode: !modenamestring"

Built-in Defines

- Aside from user defines, Asar also supports a number of built-in defines. These defines are read-only and any attempt to modify them will throw an error.

+ Aside from user defines, Asar also supports a number of built-in defines. These defines are read-only and any attempt to modify them will throw an error.

@@ -2426,7 +2426,7 @@

Built-in Defines

warn "This patch might not behave correctly due to a bug in Asar versions prior to 1.60." endif -
Define

+
Return to top

Macros

@@ -2441,8 +2441,8 @@

Built-in Defines

[command1] [command2...] endmacro
- where all the identifiers can contain any of the following characters:
- a-z A-Z 0-9 _
+ 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 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). @@ -2511,8 +2511,8 @@

Built-in Defines

Functions

Functions in Asar can be considered the math equivalent of macros. They are a convenient way of wrapping commonly used math statements, can include parameters and can be called in all places where math is supported. Use the following syntax to define a function:
function {identifier}([parameter1_identifier[, parameter2_identifier...]]) = {some_math_statement}
- where all the identifiers can contain any of the following characters
- a-z A-Z 0-9 _
+ where all the identifiers can contain any of the following characters
+ a-z A-Z 0-9 _
and where some_math_statement can be any math statement supported by Asar (including the use of other functions). Use a parameter's name to expand it inside a function.
function kilobytes_to_bytes(kb) = kb*1024
 function megabytes_to_kilobytes(mb) = mb*1024
@@ -2533,7 +2533,7 @@ 

Built-in Defines

Function definitions must be on a single line and can't include whitespace in their math statements, except when using the multi line operator \, which can be used to split long function definitions into multiple lines.

Built-in Functions

- Aside from user-defined functions mentioned above, Asar also supports a number of built-in functions. Some built-in functions take string parameters, which must be wrapped in double quotes.

+ Aside from user-defined functions mentioned above, Asar also supports a number of built-in functions. Some built-in functions take string parameters, which must be wrapped in double quotes.

@@ -2660,7 +2660,7 @@

Built-in Functions

- @@ -2707,7 +2707,7 @@

Built-in Functions

- -
Function
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.
+
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 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)
!banks_used #= ceil(!data_size/65536)
defined(identifier)Takes an identifier as a string parameter and returns 1 if a define with that identifier exists, 0 otherwise.
+
Takes an identifier as a string parameter and returns 1 if a define with that identifier exists, 0 otherwise.
NOTE: Don't include the ! in the identifier as Asar will otherwise try to expand it as a define before calling the function.
if defined("include_guard") == 0
 	!include_guard = 1	
@@ -2782,7 +2782,7 @@ 

Built-in Functions

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.
function read1(x) = _read1(x+$010000)
While user-defined functions can't use string parameters themselves, passthrough of string parameters to built-in functions is supported. @@ -2797,7 +2797,7 @@

if/elseif/else/endif

if {condition}
 	{codeblock}
 endif
- To construct condition statements, you can also make use of a number of comparison operators specific to conditionals. They return 1 if their respective comparison is true and 0 otherwise.

+ To construct condition statements, you can also make use of a number of comparison operators specific to conditionals. They return 1 if their respective comparison is true and 0 otherwise.

@@ -2831,8 +2831,8 @@

if/elseif/else/endif

-
Operator !a Returns 1 if a is 0, and 0 otherwise. Note: this is deprecated and will be removed in a future version. Please use if not(a) instead.

- You can use logical operators to chain multiple conditions.

+
+ You can use logical operators to chain multiple conditions.

@@ -2846,7 +2846,7 @@

if/elseif/else/endif

-
Operator a && b 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.
!mode = 0	; Supported modes: 0, 1, 2, 3
 !verbose = 0	; Set to 1 to enable verbose mode
@@ -2900,7 +2900,7 @@ 

while

!counter #= !counter+1 endwhile
- 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.

+ 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. @@ -2938,7 +2938,7 @@

Tables

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).
+ 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).
Format of left-to-right table files:
{character}={value}
 [character=value...]
@@ -2947,7 +2947,7 @@

Tables

[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
'{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.
+ 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.
; Contents of table1.txt:
 ;A=1A
@@ -3059,7 +3059,7 @@ 

incbin

incbin {filename} pullpc
- In this case there is no hard limitation on the size of your file.

+ In this case there is no hard limitation on the size of your file.

Return to top

Includes

@@ -3157,7 +3157,7 @@

freespace/freecode/freedata

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. -

+

@@ -3187,7 +3187,7 @@

freespace/freecode/freedata

-
Parameter value 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, 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. @@ -3218,15 +3218,15 @@

autoclean

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:
    + 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.
  • - When used with a dl:
    + When used with a dl:
    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 an address pointing to the expanded area of the ROM (banks $10+) at the current pc. If it does, Asar checks whether that address 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 just an address:
    + 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.
@@ -3293,7 +3293,7 @@

prot

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:
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:

+ where text_or_function can be either a string delimited by double quotes or one of the print-specific functions below:

@@ -3321,19 +3321,19 @@

print

- - -
Function
freespaceusePrints the total number of bytes used by commands that acquire freespace (such as freespace, freecode, freedata etc.).
+
Prints the total number of bytes used by commands that acquire freespace (such as freespace, freecode, freedata etc.).
You can use the command
reset freespaceuse
to reset this value.
bytesPrints the total number of bytes written to the output ROM.
+
Prints the total number of bytes written to the output ROM.
You can use the command
reset bytes
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

@@ -3399,7 +3399,7 @@

check bankcross

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.

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

From b1ac50d9d65a39ee4fee3adfca4892e26f9d4a73 Mon Sep 17 00:00:00 2001 From: culix Date: Mon, 22 Dec 2025 09:14:47 -0700 Subject: [PATCH 2/2] docs - replace other trailing slashes in html --- docs/manual/index.html | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/manual/index.html b/docs/manual/index.html index f29ea5c6..02775a3b 100644 --- a/docs/manual/index.html +++ b/docs/manual/index.html @@ -3,7 +3,7 @@ Asar User Manual - + @@ -15,7 +15,7 @@

Asar

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.

-
+

Table of Contents

  • @@ -163,7 +163,7 @@

    Asar

-
+

Usage

	asar.exe [options] {asm_file} [rom_file]
Warning Name
@@ -326,7 +326,7 @@

Standard Defines

stddefined5 = " $60,$50,$40 "Return to top -
+

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).

@@ -1603,7 +1603,7 @@

spcblock


Return to top
-
+

Mapping Modes

Asar supports a number of different mapping modes. They control the address translation used by Asar during compilation (aka where in the output file Asar writes to). Historically, SNES cartridges used a number of different mappers to address data in ROM. Those mappers can be supported by using the respective mapping mode in Asar. It's possible, but not recommended, to use different mapping modes on the same ROM. Detailed explanations on each mapping mode are beyond the scope of this manual, so please check the SNES Dev Manual or other specialized resources for that.
NOTE: Changing the mapper after having previously set it will generate warning Wmapper_already_set.

@@ -1657,7 +1657,7 @@

spcblock

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

Compatibility settings determine how Asar operates in certain situations. They can be changed via a number of commands.

xkas

@@ -1724,7 +1724,7 @@

namespace nested

namespace nested {on/off}
The namespace nested command enables (on) or disables (off) nested namespaces. The default is off. See section Namespaces for details.

Return to top
-
+

Code Formatting

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. @@ -1765,7 +1765,7 @@

Single-Line Operator

lda #00 sta $00 Return to top
-
+

Program Counter

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

@@ -1897,7 +1897,7 @@

pushbase/pullbase

base off Return to top
-
+

Math

Math is supported in all opcodes, functions and labels. By default, Asar uses left-to-right math for backwards-compatibility with xkas which means that it ignores operator precedence.
lda #6*2+5	; the same as "lda #17"
@@ -1935,7 +1935,7 @@ 

pushbase/pullbase

db $00,$01,$02 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

@@ -2306,7 +2306,7 @@

Global labels

Note that # acts the same way as it does for regular labels.
Note that you cannot use the global command with sublabels or macro labels. Outside of a namespace, global acts just like a regular label definition.
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 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}
@@ -2428,7 +2428,7 @@

Built-in Defines


Return to top
-
+

Macros

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:
-
+

Functions

Functions in Asar can be considered the math equivalent of macros. They are a convenient way of wrapping commonly used math statements, can include parameters and can be called in all places where math is supported. Use the following syntax to define a function:
function {identifier}([parameter1_identifier[, parameter2_identifier...]]) = {some_math_statement}
@@ -2789,7 +2789,7 @@

Built-in Functions

function readfilenormalized(filename, pos) = readfile4(filename, pos)/2147483648.0
 db readfilenormalizd("datafile.bin", 0)
Return to top
-
+

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

@@ -2913,7 +2913,7 @@

for

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.

Return to top
-
+

Binary Data

Asar supports a number of commands which allow you to insert binary data directly into the ROM.

Tables

@@ -3061,7 +3061,7 @@

incbin

pullpc In this case there is no hard limitation on the size of your file.

Return to top
-
+

Includes

Includes make it possible for your code to reference other files. This can be done for a number of reasons. The most common scenarios are to split code into multiple source files (see incsrc) or to separate code from data (see incbin). Whenever using a command or function referencing another file, Asar tries to locate that file by applying a set of rules to the file path in a specific order:
    @@ -3145,7 +3145,7 @@

    includeonce

    jsl MyOtherRoutine 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.

@@ -3287,7 +3287,7 @@

prot

; ... db $FF Return to top
-
+

Text Output

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

print

@@ -3363,7 +3363,7 @@

assert

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

@@ -3391,7 +3391,7 @@

check bankcross

print pc ; Will print 818001 when using LoROM mapper 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).