diff --git a/docs/manual/index.html b/docs/manual/index.html index c73f9b68..02775a3b 100644 --- a/docs/manual/index.html +++ b/docs/manual/index.html @@ -3,7 +3,7 @@
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.
asar.exe [options] {asm_file} [rom_file]
|
|||||||||||||||||||
-v--verbose |
+ -v--verbose |
Input | Enables verbose mode. |
@@ -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. |
|
|||||||||||||||
-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
@@ -229,7 +229,7 @@ AsarC:/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. | |
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.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
@@ -326,10 +326,10 @@ Standard Defines
stddefined5 = " $60,$50,$40 "
Return to top
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).
- | Architecture | @@ -1503,7 +1503,7 @@Compiles code for the Super FX architecture. |
|---|
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)
- Wmapper_already_set.Wmapper_already_set.| Command | @@ -1646,7 +1646,7 @@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. |
|---|
lorom
org $008000
@@ -1655,9 +1655,9 @@ 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.pctosnes() and snestopc() to translate between addresses.namespace nested {on/off}
- The namespace nested command enables (on) or disables (off) nested namespaces. The default is off. See section Namespaces for details.namespace nested command enables (on) or disables (off) nested namespaces. The default is off. See section Namespaces for details.;@, 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.
lda $00
beq .IsZero
@@ -1765,7 +1765,7 @@ Single-Line Operator
lda #00
sta $00
Return to toplda #6*2+5 ; the same as "lda #17"
@@ -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:+ : 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)lda .Data+3 ; Will load $03 into A
@@ -1935,12 +1935,12 @@ pushbase/pullbase
db $00,$01,$02
db $03,$04,$05
Return to top[#]{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 charactersa-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:neg_x_yx = number of chained +/-.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:neg_x_yx = number of chained +/-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_:macro_x_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.
struct {identifier} {snes_address}
[label...]
endstruct [align num]
- where identifier can contain any of the following characters:a-z A-Z 0-9 _identifier can contain any of the following characters:a-z A-Z 0-9 _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 @@ 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_offsetstruct_start + (array_index * struct_size) + label_offset$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.$7E0100 + (2 * 32) + (1 + 2) = $7E0143.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 asparent_struct_start_address + parent_struct_size + extension_struct_label_offset,.FlipX in this example is calculated asparent_struct_start_address + parent_struct_size + extension_struct_label_offset,$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 asparent_struct_start_address + (combined_struct_size * array_index) + parent_struct_size + extension_struct_label_offset,parent_struct_start_address + parent_struct_size + (extension_struct_size * array_index) + extension_struct_label_offset,$7E0100 + (12 * 2) + 7 + (1 + 2) = $7E0122 and $7E0100 + 7 + (5 * 2) + (1 + 2) = $7E0114.parent_struct_start_address + (combined_struct_size * array_index) + parent_struct_size + extension_struct_label_offset,parent_struct_start_address + parent_struct_size + (extension_struct_size * array_index) + extension_struct_label_offset,$7E0100 + (12 * 2) + 7 + (1 + 2) = $7E0122 and $7E0100 + 7 + (5 * 2) + (1 + 2) = $7E0114._ . 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 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). Usenamespace {identifier}
- to enter a namespace, where identifier can contain any of the following characters:a-z A-Z 0-9 _identifier can contain any of the following characters:a-z A-Z 0-9 _namespace off
to leave the current namespace (or immediately return to the global namespace when nested namespaces are not enabled).
@@ -2306,13 +2306,13 @@ # acts the same way as it does for regular labels.global command with sublabels or macro labels. Outside of a namespace, global acts just like a regular label definition.! 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 _identifier is a unique identifier that can contain any of the following characters:a-z A-Z 0-9 _!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.", as shown above with !phr. Besides the regular define operator =, Asar also supports a number of additional define operators with slightly different functionality.| Operator | @@ -2370,7 +2370,7 @@
|---|
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"
| Define | @@ -2426,9 +2426,9 @@
|---|
a-z A-Z 0-9 _a-z A-Z 0-9 _<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).
@@ -2507,12 +2507,12 @@ function {identifier}([parameter1_identifier[, parameter2_identifier...]]) = {some_math_statement}
- where all the identifiers can contain any of the following charactersa-z A-Z 0-9 _a-z A-Z 0-9 _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.
| Function | @@ -2660,7 +2660,7 @@|||||
|---|---|---|---|---|---|
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. |
|
|
|
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. |
|
_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.
function readfilenormalized(filename, pos) = readfile4(filename, pos)/2147483648.0
db readfilenormalizd("datafile.bin", 0)
Return to topif {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.| Operator | @@ -2831,8 +2831,8 @@!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. |
|---|
| Operator | @@ -2846,7 +2846,7 @@a && b |
Returns 1 if both of a and b evaluate to 1 |
|---|
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.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 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.
@@ -2913,7 +2913,7 @@ 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.
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.
- Wherefilename 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).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).{character}={value}
[character=value...]
@@ -2947,7 +2947,7 @@ 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.value can be any number literal or math statement. This will be the only way to set the table in Asar 2.0.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,9 +3059,9 @@ incbin
incbin {filename}
pullpc
- In this case there is no hard limitation on the size of your file.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.
- | Parameter | @@ -3187,7 +3187,7 @@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. |
|---|
freecode command is an alias of freespace ram, whereas the freedata command is an alias of freespace noram.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:
jml or jsl:jml or jsl: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.
dl:dl: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.
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.
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:text_or_function can be either a string delimited by double quotes or one of the print-specific functions below:| Function | @@ -3321,19 +3321,19 @@||
|---|---|---|
freespaceuse |
- Prints 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
to reset this value. |
bytes |
- Prints 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
to reset this value. |
print command:
print "You need to know about:", hex(read1(PlayerHealth)), " and ", dec(10+20), ", and ", hex(read1(PlayerMana))
| Warning Name |
|---|