- Introduction
- Basic Syntax
- Strings
- #raw
- Dynamic labels
- Inline labels
- Preprocessor
- Goodies
- High level structures
- User interface
Introduction
Red Alien is mostly compatible with XSE and PKSV, but adds features of its own. All of these are valid Red Alien code:
-
XSE like
// Original Source: // http://www.pokecommunity.com/showthread.php?t=164276 #include "stdlib/std.rbh" #dynamic 0x800000 #org @start lock faceplayer checkflag 0x200 if 0x1 goto @done msgbox @1 0x6 setflag 0x200 release end #org @done msgbox @2 0x6 clearflag 0x200 release end #org @1 = sup1 #org @2 = sup2
-
PKSV like
// Original Source: // http://www.pokecommunity.com/showthread.php?t=195659 // I had to add these includes, since there are no // implicit constants, and renamed PICHU to PKMN_PICHU #include "stdlib/std.rbh" #include "stdlib/stdpoke.rbh" #dynamic 0x740000 #org @main lock faceplayer checkflag 0x200 if 0x1 jump @haveit message @want callstd MSG_YESNO if 0x1 jump @pushedyes jump @pushedno #org @haveit message @howsit callstd MSG_NORMAL release end #org @pushedyes setflag 0x200 giveegg PKMN_PICHU message @herego callstd MSG_NORMAL release end #org @pushedno message @dontwant callstd MSG_NORMAL release end #org @want = Hey, do you want this Pichu egg? #org @herego = Here you go!\nPlease raise it well. #org @howsit = I hope Pichu is doing well! #org @dontwant = Oh, ok. Maybe someone else will take it.
-
Red Alien only
// A little demo of features #include "stdlib/std.rbh" #dyn 0x800000 #define THAT_GUY 2 #org @main checkflag EM_BADGE1 if 0 jump :ya_noob // Wild PKSV/C-style labels appeared msgbox @good 6 // Wild XSE compatibility appeared! if ( ! EM_BADGE2 ) { loadpointer :bg2_bad callstd 6 } else { loadpointer :bg2_good callstd 6 } jump :end :ya_noob loadpointer :msg_nuv // yes, it's using a label for the msg callstd 6 :end disappear THAT_GUY // It's a PKSV command with a constant! end :msg_nuv // It's a multi-line string! = So, man, are you a total nuv?\n = You didn't even get the first\l = medal kid. #raw 0xFF // I won't eat your bytes, but you'll have to terminate your strings // Unless you use #org @whatever :bg2_bad = But you didn't get the 2nd\none...\hFF // This one doesn't need a terminating byte because what's next // will be padded (#org). :bg2_good = But you did get the 2nd\none... #org @good // It's an ugly-ass traditional string! = You are good man\pYou are pretty good.\pI think we should go have something to drink
Basic Syntax
To write a script, the first thing you need to tell the compiler is where you want your script written. To do so, use the #org directive:
#org <address>eg.:
#org 0xA00000
After that, you can write commands. You can find a list of commands in the asc/data/commands.txt file. You can also edit that file to modify or add commands, if you have the knowledge to do so.
The syntax for commands is simply:
<command> [args] ...
(The argument name will vary for each command). eg.:
lock
setflag 0x4000 0x1
You probably want to end your scripts with an end command.
Strings
Text strings are used for messages. To write a text
string, the first character of the line must be an
equals sign (=
). Everything that follows
up until the newline will be part of the string.
Comments might or might not be detected on that line
(so don't write them there!).
Text strings won't be automatically terminated. This means that if there is garbage after a string, it won't end properly. If you are using dynamic labels (explained later), or putting your scripts on empty (FF) space, this will not affect you negatively. This also means that you can split your strings over multiple lines.
You can write special characters inside strings, to write line breaks, for example. Here's a list:
\l (FA) - newline with scroll \p (FB) - change paragraph \c (FC) - colors \v (FD) - buffers \n (FE) - jump to 2nd line \hXX - byte XX
Example:
#org 0x800000
message 0x900000
callstd 6
message 0xA00000
callstd 6
end
#org 0x900000
= This is a simple string.
#org 0xA00000
= This is a longer string.\nI better split it over\l
= more lines, to help readability.
#raw
The #raw
directive is used to write
plain bytes to the ROM. It takes one argument, the
byte to write. It's usually used for movement
bytecode. Example:
#dynamic 0x800000
#org @main
applymovement 2 @movs
pauseevent 0
end
#org @movs
#raw 0x02 'look left
#raw 0xFE
That is actually equivalent to:
#dynamic 0x800000
#org @main
applymovement 2 @movs
pauseevent 0
end
#org @movs
=\x02\xFE
But with the first one you can use #define
'd
constants (explained later).
#dynamic 0x800000
#org @main
applymovement 2 @movs
pauseevent 0
end
#define look_left #raw 0x02
#org @movs
look_left
#raw 0xFE
Equivalents for different sizes are also available as
#byte
,
#hword
and
#word
.
Dynamic labels
Red Alien, like most script compilers, can help you
with the job of finding a suitable place for your scripts
using the #dynamic
directive.
The syntax for it is just #dynamic <base_address>
,
where said base address is the starting address where
the compiler will start looking for space. The most common
address used for it is 0x800000 (#dynamic 0x800000
).
After #dynamic
has been used, you can use
@labels instead of addresses. A @label is a name you
give to a piece of code or data in your script, which
the compiler will replace with an actual address
at compile time. It must start with an at (@) and
be floowed by extra non-whitespace symbols, eg.:
@000
, @poop
@!--()
.
Even though, I recommend sticking to letters, numbers
and underscores.
All @labels used in command arguments must be defined in an #org location somewhere in the code.
Example:
#dyn 0x800000
#org @main
message @sup
callstd 6
end
#org @sup
= Hi!
The compiler will output the addresses it has assigned to each @label at the end.
Inline labels
Like PKSV, and similarly to the C programming language or Assembler, Red Alien supports inline labels, called :labels from now on.
A :label can appear anywhere after an #org
directive. It will take the address of the element that
follows it, and it can be used anywhere else in the code
to refer to the point where it sits.
This allows for lots of control and tight code.
Example:
#include "stdlib/std.rbh"
#dyn 0x800000
#org @main
checkflag 0x867
if 0 jump :ya_noob // yes, it's using a :label for the msg too
msgbox :good 6
jump :end
:ya_noob
message :msg_nuv
callstd 6
:end
disappear 2
end
:msg_nuv
= So, man, are you a total nuv?\n
= You didn't even get the first\l
= medal kid.\xFF
// That \xFF terminates the string
// It separates it from the :good one
:good
= You are good man\p
= You are pretty good.\p
= I think we should go have a drink.
Preprocessor
You can #define
stuff, you can #include
stuff, and you can #ifdef
/#ifndef
then
#endif
. If you know a C-based language you will
probably be familiar with these.
#define
does macros as defined in the pks2 standard.
Arguments to the macro will replace the $# args:
#define msgbox loadptr $1 ; callstd $2
msgbox @lmao 6
Will become:
loadptr @lmao ; callstd 6
Red Alien doesn't define any constants by default. You can include standard library headers to get them. Example:
#include "stdlib/std.rbh"
#include "stdlib/stdpoke.rbh"
#include "stdlib/stditems.rbh"
#include "stdlib/stdattacks.rbh"
#include "stdlib/stdmoves.rbh"
#define KID 5
#dynamic 0x800000
#org @main
message @msg
callstd MSG_NORMAL
disappear KID
end
#org @msg
= I'm going to disappear!
The msgbox macro shown above is defined in std.rbh
High level structures
Red Alien brings C-like syntax for loops and branches because why not.
if/else
if ( condition ) { commands ... }You can also have an else:
if ( condition ) { commands ... } else { commands ... }
Brackets are required, you cannot do else if
without nesting.
The condition can be:
- a flag (eg
if ( 0x400 ) { ... }
) - a comparison between a variable and a constant (eg
if ( 0x4000 != 5 ) { ... }
)
The first will compile down to a checkflag, and the second to a compare.
while
Same as if and else, except that it loops (use a jump/goto to break or continue).while ( condition ) { commands ... }
Example:
#dyn 0x800000
#org @main
if(0x3000) {
while(0x4000 < 3) {
message @text
callstd 6
addvar 0x4000 1
}
} else {
message @text2
callstd 6
}
end
#org @text
= lalalalalala
#org @text2
= lelelelelele
User interface
Red Alien can be used with a graphical user interface (GUI) à la XSE, or with a command line interface (CLI), à la gcc.
GUI - The Graphical User Interface
If you are a Windows user, just double click asc-qt.exe
after downloading. You can also bind it with AM, going to
Settings → Choose script editor, then answering "No" when asked about
spaces or colons. You can also bind it with Blue Spider, and
probably MEH.
If you are an Arch Linux user, you can install red-alien-git
from the AUR. If you are a Linux user from another distro, you'll
have to download the code from github, install the dependencies
listed in the README.txt using your package manager, and run asc-qt.
The hacky loader.exe used to bind it with AM seems broken ATM. You
can use MEH, Blue Spider, or run Red Alien using Wine as well (boo!).
There is a compile option, a debug option, and a decompile option. The debug option compiles without actually writing to the ROM, so that you can check if a script compiles without actually using it, or see which addresses would #dynamic give in case you actually compiled it onto the ROM. The decompile option will ask for an address and do what the name implies.
Press F1 for the builtin command help.
The text input helper
You can press Ctrl-B for a text input helper.
The information line at the bottom shows how many pixels the current line will take on screen if showed in a normal text-box. You must add \n, \l and \p as needed.
CLI - The Command Line Interface
The steps until getting to the executable are the same as with the GUI, but you will run asc-cli (or asc-cli.exe) instead. You can run it with no arguments to get general help, or using the -h option for detailed help on each mode. Eg.:
> asc-cli c -h usage: asc-cli c [-h] rom script positional arguments: rom path to ROM image script path to pokemon script optional arguments: -h, --help show this help message and exit