code:
#!/bin/bash
if [ ! -d ".git" ]; then
	#not running in git repo, so can't use git commands :-)
	echo "No .git repo found - skipping sanity checks"
	exit 0
fi

WARNING='\033[93m'
WARNING='\033[93m'
ENDC='\033[0m'

myprint() {
	while read data; do
		echo -n -e "[$1]$WARNING"
		echo "$data"
	done
}

GREP="git grep -n --color"
# Check for missing right angle bracket: <</if>
$GREP "<</[^>]*>[^>]" -- 'game/*'  | myprint "MissingClosingAngleBracket"
$GREP "<<[^>()]*>[^()<>"$'\r]*\r'"\?$" -- 'game/*' | myprint "MissingClosingAngleBracket"
# Check for missing left angle bracket: </if>>
$GREP "\([^<]\|^\)</\?\(if\|else\|case\|set\|print\|elseif\)" -- 'game/*' | myprint "MissingOpeningAngleBracket2"
# Check for accidental assignment.  e.g.:   <<if $foo = "hello">>
$GREP "<<[ ]*if[^>=]*[^><\!=]=[^=][^>]*>>" -- 'game/*' | myprint "AccidentalAssignmentInIf"
# Check for accidental assignment.  e.g.:   <<elseif $foo = "hello">>
$GREP "<<[ ]*elseif[^>=]*[^><\!=]=[^=][^>]*>>" -- 'game/*' | myprint "AccidentalAssignmentInElseIf"
# Check for missing ".  e.g.:   <<if $foo == "hello>>
# $GREP -e "<<[^\"<>]*\"[^\"<>]*>>" -- 'game/*' | myprint "MissingSpeechMark"
# Check for missing ".  e.g.:   <<if $foo = "hello)
# $GREP -e "<<[^\"<>]*\([^\"<>]*\"[^><\"]*\"\| [<>] \)*\"\([^\"<>]*\"[^><\"]*\"\| [<>] \)*\([^\"<>]\| [<>] \)*>>" --and --not -e "*[^']*" -- 'game/*' | myprint "MissingSpeechMark2"
# Check for colours like: @@color:red   - should be @@.red
$GREP -e "@@color:" --and --not -e  "@@color:rgb([0-9 ]\+,[0-9 ]\+,[0-9 ]\+)" -- "game/*" | myprint "UseCssColors"
# Check for missing $ in activeSlave or PC
$GREP "<<[ ]*[^\$><_\[]*\(activeSlave\|PC\)[.]"  -- "game/*" | myprint "MissingDollar"
# Check for closing bracket without opening bracket.  e.g.:  <<if foo)>>	  (but  <<case "foo")>>   is valid, so ignore those
$GREP -e "<<[ a-zA-Z]\+\([^()<>]\|[^()<>][<>][^()<>]\)*)" --and --not -e "<< *case"  -- "game/*" | myprint "MissingOpeningBracket"
# Check for opening bracket without closing bracket.  e.g.:  <<if (foo>>
$GREP -e "<<[ a-zA-Z]\([^<>]\|[^<>][<>][^<>]\)\+(\([^()<>]\|[^<>()][<>][^<>()]\|([^<>()]*])\)*>>" -- "game/*" | myprint "MissingClosingBracket"
# Check for two closing brackets but one opening bracket.  e.g.:  <<if (foo))>>
$GREP -e "<<[ a-zA-Z]\+[^()<>]*([^()]*)[^()]*)[^()<>]*>>"  -- "game/*" | myprint "MissingOpeningBracket2"
# Check for one closing bracket but two opening brackets.  e.g.:  <<if ((foo)>>
$GREP -e "<<[ a-zA-Z]\+[^()<>]*([^()]*([^()]*)[^()<>]*>>"  -- "game/*" | myprint "MissingClosingBracket2"
$GREP -e "<<.*[(][^<>)]*[(][^<>)]*)\?[^<>)]*>>" -- "game/*" | myprint "MissingClosingBracket3"
# Check for missing >>.  e.g.:   <<if $foo
$GREP "<<[^<>]*[^,\"\[{"$'\r]\r'"\?$" -- 'game/*' | myprint "MissingClosingAngleBrackets"
# Check for too many >>>.  e.g.: <</if>>>
$GREP "<<[^<>\"]*[<>]\?[^<>\"]*>>>" -- "game/*" | myprint "TooManyAngleBrackets"
# Check for too many <<<.  e.g.: <<</if>>
$GREP "<<<[^<>\"]*[<>]\?[^<>\"]*>>" -- "game/*" | myprint "TooManyAngleBrackets2"
# Check for wrong capitalisation on 'activeslave' and other common typos
$GREP  "\(csae\|[a-z] She \|attepmts\|youreslf\|advnaces\|canAcheive\|setBellySize\|SetbellySize\|setbellySize\|bellypreg\|pregBelly\|bellyimplant\|bellyfluid\|pronounCaps\|carress\)" -- 'game/*' | myprint "SpellCheck"
$GREP  "\(recieve\|recieves\)" -- 'game/*' | myprint "PregmodderCannotSpellReceive"
$GREP "\$slave\[" -- 'game/*' | myprint "ShouldBeSlaves"
# Check for strange spaces e.g.  $slaves[$i]. lips
$GREP "\$slaves\[\$i\]\. " -- 'game/*' | myprint "MissingPropertyAfterSlaves"
# Check, e.g., <<//if>>
$GREP "<</[a-zA-Z]*[^a-zA-Z<>]\+[a-zA-Z]*>>" -- 'game/*' | myprint "DoubleSlash"
# Check, e.g.  <<else $foo==4
$GREP "<<else >\?[^>]" -- 'game/*' | myprint "ShouldBeElseIf"
# Check, e.g., =to
$GREP "=to" -- 'game/*' | myprint "EqualAndTo"
# Check, e.g.  <<set foo == 4>>
$GREP "<<set[^{>=]*==" -- 'game/*' | myprint "DoubleEqualsInSet"
# Check for, e.g   <<if slaves[foo]>>
$GREP "<<\([^>]\|[^>]>[^>]\)*[^$]slaves\[" -- 'game/*' | myprint "MissingDollar"
# Check for missing $ or _ in variable name:
$GREP -e "<<[a-zA-Z]\([^>\"]\|[^>]>[^>]\|\"[^\"]*\"\)* [a-zA-Z]\+ * =" -- game/* | myprint "MissingDollar2"
# Check for missing command, e.g.  <<foo =
$GREP -e "<<[a-zA-Z]* = *" -- game/* | myprint "BadCommand"
# Check for duplicate words, e.g. with with
$GREP -e  " \(\b[a-zA-Z][a-zA-Z]\+\) \1\b " --and --not -e " her her " --and --not -e " you you " --and --not -e " New New " --and --not -e "Slave Slave " --and --not -e " that that " --and --not -e " in in " --and --not -e " is is " -- 'game/*' | myprint "Duplicate words"
# Check for obsolete SugarCube macros
$GREP -E "<<display |<<click|<<.*\.contains" -- game/* | myprint "ObsoleteMacro"
# Check for double articles
$GREP -E "\Wa an\W" -- game/* | myprint "DoubleArticle"
# Check for incorrect articles
$GREP -i -E "\Wa (a|e|i|o|u)." -- game/* | grep -a -i -vE "\Wa (un|eu|us|ut|on|ur|in)." | grep -a -i -vE "(&|<<s>>|UM)." | myprint "IncorrectArticle"
$GREP -i -E "\Wan (b|c|d|f|g|j|k|l|m|n|p|q|r|s|t|v|w|x|y|z)\w." -- game/* | grep -a -i -vE "[A-Z]{3}" | myprint "IncorrectArticle"
# Check for $ sign mid-word
$GREP -i "\w$\w" -- game/* | myprint "VarSignMidWord"
# check for $ sign at beginning of macro
$GREP '<<\s*\$' -- 'game/*'  | myprint "VarSignAtMacroStart"
# check for missing ; before statement
$GREP 'if $ ' -- 'game/*'  | myprint "missing ; before statement"
$GREP 'elseif $ ' -- 'game/*'  | myprint "missing ; before statement"
# Check that we do not have any variables that we use only once.   e.g.	 $onlyUsedOnce
# Ignore  *Nationalities
(
cd game/
find . -name "*.twee" -exec cat '{}' ';' | tr -c '$a-zA-Z' '\n'  | sed -n '/^[$]/p' | sort | uniq -u | sed 's/^[$]/-e[$]/' | sed 's/$/\\\\W/' | xargs -r  git grep -n --color | myprint "OnlyUsedOnce"
find . -name "*.twee" -exec cat '{}' ';' | tr -c '.$a-zA-Z[]_' '\n' | sed 's/SugarCube\.State\.variables\./$/g' | sed -n -e 's/^[$]\(PC\|activeSlave\|\(slaves\|tanks\)\[[^]]*\]*\)[.]\([a-zA-Z]\+\).*$/[.]\3/p' | sort | uniq -u |sed 's/^\(.*\)$/-e\1\\\\\b/'  | xargs -r git grep -n --color | myprint "SlaveAttributeUsedOnce"
$GREP "\$\(PC\|activeSlave\|slaves\|tanks\)[.][^a-zA-Z]" | myprint "UnexpectedCharAfterDot"

#Find all the variables listed in init.twee
VARIABLELIST=$(cat base-system/init.twee | tr -c '$a-zA-Z' '\n'  | sed -n '/^[$]/p' | sort | uniq)
# Find all variables anywhere.  Commented out because the output is too noisy currently
#VARIABLELIST=$(find . -name "*.twee" -exec cat '{}' ';' | tr -c '$a-zA-Z' '\n'  | sed -n '/^[$]/p' | sort | uniq)
MISSINGFROMVERSIONUPDATE=$(for variable in $VARIABLELIST; do grep -q "$variable" base-system/version-update.twee || echo "$variable"; done)
echo -e "base-system/version-update.twee$ENDC: $(echo $MISSINGFROMVERSIONUPDATE)" | myprint "MissingFromVersionUpdate"
)

git ls-files "game/*.twee" | xargs -d '\n'  ./devTools/check.py

path: sanityCheck


code:
/*CSS override*/
/*Remove comments to apply*/
/*#stats {
	top: 256px;
}

body.has-images #story-caption {
	margin-top: calc(278px - 2.5em);
}*/

repo_name: GayKitten/degrees

license: mit


code:
*.pal text eol=crlf
*.sh text eol=lf
*.s text eol=lf
*.txt text eol=lf
Makefile text eol=lf
*.mk text eol=lf
*.c text eol=lf
*.h text eol=lf
*.pl text eol=lf
*.inc text eol=lf
*.sha1 text eol=lf
*.json text eol=lf
*.sed text eol=lf
*.cpp text eol=lf
.gitattributes text eol=lf
.gitignore text eol=lf
*.hpp text eol=lf
*.md text eol=lf
*.ps1 text eol=crlf
*.yml text eol=lf

*.png binary
*.bin binary

*.h linguist-language=C
*.inc linguist-language=Assembly

repo_name: Lunos/pokeemerald

path: .gitattributes


code:
<!--- Provide a general summary of your changes in the Title above -->

## Description
<!--- Describe your changes in detail -->

## **Discord contact info**
<!--- formatted as name#numbers, e.g. PikalaxALT#5823 -->
<!--- Contributors must join https://discord.gg/d5dubZ3 -->


code:
*.exe
*.o
*.i
*.elf
*.gba
*.sgm
*.sa1
*.ss[0-9]
*.sg1
*.1bpp
*.4bpp
*.8bpp
*.gbapal
*.lz
*.rl
*.latfont
*.hwjpnfont
*.fwjpnfont
sound/**/*.bin
sound/songs/midi/*.s
tools/agbcc
*.map
*.ld
*.bat
*.dump
*.sa*
Thumbs.db
build/
.DS_Store
*.ddump
.idea/
porymap.project.cfg
.vscode/
*.a
.fuse_hidden*
*.sna

path: .gitignore


code:
language: generic
dist: bionic
sudo: false
env:
  global:
    - DEVKITPRO=$HOME
    - DEVKITARM=$DEVKITPRO/devkitARM
addons:
  apt:
    packages:
      - gcc-multilib
      - linux-libc-dev
cache:
  apt: true
install:
  - pushd $HOME
  - travis_retry wget https://github.com/devkitPro/buildscripts/releases/download/devkitARM_r52/devkitARM_r52-linux.tar.xz
  - tar xJf devkitARM*.tar.xz
  - travis_retry wget https://github.com/devkitPro/devkitarm-rules/releases/download/v1.0.0/devkitarm-rules-1.0.0.tar.xz
  - tar xJf devkitarm-rules-*.tar.xz -C $DEVKITARM
  - travis_retry git clone https://github.com/pret/agbcc.git
  - cd agbcc && ./build.sh && ./install.sh $TRAVIS_BUILD_DIR
  - popd
matrix:
  include:
    - os: linux
      addons:
        apt:
          sources:
              - ubuntu-toolchain-r-test
          packages:
            - g++-7
      env: _="Build"
      script:
        - make -j2 tools CXX=g++-7
        - make -j2 compare
        - make -j2 modern
after_success:
  - .travis/calcrom/webhook.sh pokeemerald


code:
#!/usr/bin/perl

use IPC::Cmd qw[ run ];

(@ARGV == 1)
    or die "ERROR: no map file specified.\n";
open(my $file, $ARGV[0])
    or die "ERROR: could not open file '$ARGV[0]'.\n";

my $src = 0;
my $asm = 0;
my $srcdata = 0;
my $data = 0;
while (my $line = <$file>)
{
    if ($line =~ /^ \.(\w+)\s+0x[0-9a-f]+\s+(0x[0-9a-f]+) (\w+)\/.+\.o/)
    {
        my $section = $1;
        my $size = hex($2);
        my $dir = $3;

        if ($section =~ /text/)
        {
            if ($dir eq 'src')
            {
                $src += $size;
            }
            elsif ($dir eq 'asm')
            {
                $asm += $size;
            }
        }
        elsif ($section =~ /rodata/)
        {
            if ($dir eq 'src')
            {
                $srcdata += $size;
            }
            elsif ($dir eq 'data')
            {
                $data += $size;
            }
        }
    }
}

(my $elffname = $ARGV[0]) =~ s/\.map/.elf/;

# Note that the grep filters out all branch labels. It also requires a minimum
# line length of 5, to filter out a ton of generated symbols (like AcCn). No
# settings to nm seem to remove these symbols. Finally, nm prints out a separate
# entry for whenever a name appears in a file, not just where it's defined. uniq
# removes all the duplicate entries.
#
#
# You'd expect this to take a while, because of uniq. It runs in under a second,
# though. Uniq is pretty fast!
my $base_cmd = "nm $elffname | awk '{print \$3}' | grep '^[^_].\\{4\\}' | uniq";

# This looks for Unknown_, Unknown_, or sub_, followed by just numbers. Note that
# it matches even if stuff precedes the unknown, like sUnknown/gUnknown.
my $undoc_cmd = "grep '[Uu]nknown_[0-9a-fA-F]*\\|sub_[0-9a-fA-F]*'";

# This looks for every symbol with an address at the end of it. Some things are
# given a name based on their type / location, but still have an unknown purpose.
# For example, FooMap_EventScript_FFFFFFF.
my $partial_doc_cmd = "grep '_[0-28][0-9a-fA-F]\\{5,6\\}'";

my $count_cmd = "wc -l";

# It sucks that we have to run this three times, but I can't figure out how to get
# stdin working for subcommands in perl while still having a timeout. It's decently
# fast anyway.
my $total_syms_as_string;
(run (
    command => "$base_cmd | $count_cmd",
    buffer => \$total_syms_as_string,
    timeout => 60
))
    or die "ERROR: Error while getting all symbols: $?";

my $undocumented_as_string;
(run (
    command => "$base_cmd | $undoc_cmd | $count_cmd",
    buffer => \$undocumented_as_string,
    timeout => 60
))
    or die "ERROR: Error while filtering for undocumented symbols: $?";

my $partial_documented_as_string;
(run (
    command => "$base_cmd | $partial_doc_cmd | $count_cmd",
    buffer => \$partial_documented_as_string,
    timeout => 60
))
    or die "ERROR: Error while filtering for partial symbols: $?";

# Performing addition on a string converts it to a number. Any string that fails
# to convert to a number becomes 0. So if our converted number is 0, but our string
# is nonzero, then the conversion was an error.
my $undocumented = $undocumented_as_string + 0;
(($undocumented != 0) and ($undocumented_as_string ne "0"))
    or die "ERROR: Cannot convert string to num: '$undocumented_as_string'";

my $partial_documented = $partial_documented_as_string + 0;
(($partial_documented != 0) and ($partial_documented_as_string ne "0"))
	or die "ERROR: Cannot convert string to num: '$partial_documented_as_string'";

my $total_syms = $total_syms_as_string + 0;
(($total_syms != 0) and ($total_syms_as_string ne "0"))
    or die "ERROR: Cannot convert string to num: '$total_syms_as_string'";

($total_syms != 0)
    or die "ERROR: No symbols found.";

my $total = $src + $asm;
my $srcPct = sprintf("%.4f", 100 * $src / $total);
my $asmPct = sprintf("%.4f", 100 * $asm / $total);

# partial_documented is double-counting the unknown_* and sub_* symbols.
$partial_documented = $partial_documented - $undocumented;

my $documented = $total_syms - ($undocumented + $partial_documented);
my $docPct = sprintf("%.4f", 100 * $documented / $total_syms);
my $partialPct = sprintf("%.4f", 100 * $partial_documented / $total_syms);
my $undocPct = sprintf("%.4f", 100 * $undocumented / $total_syms);

if ($asm == 0)
{
    print "Code decompilation is 100% complete\n"
}
else
{
    print "$total total bytes of code\n";
    print "$src bytes of code in src ($srcPct%)\n";
    print "$asm bytes of code in asm ($asmPct%)\n";
}
print "\n";

if ($partial_documented == 0 && $undocumented == 0)
{
    print "Documentation is 100% complete\n"
}
else
{
    print "$total_syms total symbols\n";
    print "$documented symbols documented ($docPct%)\n";
    print "$partial_documented symbols partially documented ($partialPct%)\n";
    print "$undocumented symbols undocumented ($undocPct%)\n";
}

print "\n";
my $dataTotal = $srcdata + $data;
my $srcDataPct = sprintf("%.4f", 100 * $srcdata / $dataTotal);
my $dataPct = sprintf("%.4f", 100 * $data / $dataTotal);

if ($data == 0)
{
    print "Data porting to C is 100% complete\n"
}
else
{
    print "$dataTotal total bytes of data\n";
    print "$srcdata bytes of data in src ($srcDataPct%)\n";
    print "$data bytes of data in data ($dataPct%)\n";
}


code:
#!/bin/bash -ex

# Only run this script if it's the master branch build.
if [[ "$TRAVIS_BRANCH" != "master" || "$TRAVIS_PULL_REQUEST" != "false" ]]; then
  exit 0
fi

build_name=$1
map_file=$build_name.map
if [ ! -f $map_file ]; then
  echo "$map_file does not exist!"
  exit 1
fi

output=$(perl $(dirname "$0")/calcrom.pl $build_name.map | sed -E ':a;N;$!ba;s/\r{0,1}\n/\\n/g')
curl -d "{\"username\": \"$CALCROM_DISCORD_WEBHOOK_USERNAME\", \"avatar_url\": \"$CALCROM_DISCORD_WEBHOOK_AVATAR_URL\", \"content\":\"\`\`\`$build_name progress:\\n$output\`\`\`\"}" -H "Content-Type: application/json" -X POST $CALCROM_DISCORD_WEBHOOK_URL


code:
# Prerequisites

| Linux | macOS | Windows 10
| - | - | -
| none | [Xcode Command Line Tools Package][xcode] | [Windows Terminal][terminal] and [Windows Subsystem for Linux (WSL)][wsl]

[xcode]: https://developer.apple.com/library/archive/technotes/tn2339/_index.html
[terminal]: https://docs.microsoft.com/windows/terminal/get-started
[wsl]: https://docs.microsoft.com/windows/wsl/install-win10

Independently from the specific OS, make sure that the `gcc`, `g++`, `make`, `git`, and `libpng-dev` packages or their equivalents are installed and accessible to the development tools that are used by the project (this means that, for example, on Windows, the packages have to be installed in the WSL environment). The package names and installation methods may vary with each OS.

Install the devkitARM toolchain of devkitPro as per [the instructions on their wiki](https://devkitpro.org/wiki/devkitPro_pacman). On Windows, follow the Linux instructions inside WSL as any steps about the Windows installer do not apply.

**Debian-based distro users:** This applies to Debian, Ubuntu, and similar distros, including in WSL. If necessary, install the `libarchive13`, `pkg-config`, and `gdebi-core` packages to be able to install devkitPro.

**Windows 10 users:** WSL 2 is available in the 1903 release (build 18362) and later, therefore existing WSL 1 and [prerelease WSL](https://docs.microsoft.com/windows/wsl/install-legacy) users are recommended to update. Right-click the Start button or press `Win`+`X`, choose Run, and run `ms-settings:about` to determine the Windows version. Also check Windows Update to make sure your installation is up-to-date.

**Windows 7 and 8.1 users:** pret is no longer focusing on support in pokeemerald for [old versions of Windows](https://support.microsoft.com/help/13853) so consider upgrading to a current release of Windows 10 or try a third-party guide like [this one](https://www.pokecommunity.com/showthread.php?t=425246) instead.

# Installation

To set up the repository:

	git clone https://github.com/pret/pokeemerald
	git clone https://github.com/pret/agbcc

	cd ./agbcc
	./build.sh
	./install.sh ../pokeemerald

	cd ../pokeemerald

To build **pokeemerald.gba** for the first time and confirm it matches the official ROM image:

	make compare

If an OK is returned, then the installation went smoothly.

**Windows users:** Consider adding exceptions for the `pokeemerald` and `agbcc` folders in Windows Security using [these instructions](https://support.microsoft.com/help/4028485). This prevents Microsoft Defender from scanning them which might improve performance while building.

# Start

To build **pokeemerald.gba** with your changes:

	make

**macOS users:** If the base tools are not found in new Terminal sessions after the first successful build, run `echo "if [ -f ~/.bashrc ]; then . ~/.bashrc; fi" >> ~/.bash_profile` once to prevent the issue from occurring again. Verify that the `devkitarm-rules` package is installed as well; if not, install it by running `sudo dkp-pacman -S devkitarm-rules`.

# Building guidance

## Parallel builds

See [the GNU docs](https://www.gnu.org/software/make/manual/html_node/Parallel.html) and [this Stack Exchange thread](https://unix.stackexchange.com/questions/208568) for more information.

To speed up building, run:

	make -j$(nproc)

`nproc` is not available on macOS. The alternative is `sysctl -n hw.ncpu` ([relevant Stack Overflow thread](https://stackoverflow.com/questions/1715580)).

## Debug info

To build **pokeemerald.elf** with enhanced debug info:

	make DINFO=1

## devkitARM's C compiler

This project supports the `arm-none-eabi-gcc` compiler included with devkitARM r52. To build this target, simply run:

	make modern

## Other toolchains

To build using a toolchain other than devkitARM, override the `TOOLCHAIN` environment variable with the path to your toolchain, which must contain the subdirectory `bin`.

	make TOOLCHAIN="/path/to/toolchain/here"

The following is an example:

	make TOOLCHAIN="/usr/local/arm-none-eabi"

To compile the `modern` target with this toolchain, the subdirectories `lib`, `include`, and `arm-none-eabi` must also be present.

# Useful additional tools

* [porymap](https://github.com/huderlem/porymap) for viewing and editing maps
* [poryscript](https://github.com/huderlem/poryscript) for scripting ([VS Code extension](https://marketplace.visualstudio.com/items?itemName=karathan.poryscript))
* [Tilemap Studio](https://github.com/Rangi42/tilemap-studio) for viewing and editing tilemaps


code:
TOOLCHAIN := $(DEVKITARM)
COMPARE ?= 0

ifeq ($(CC),)
HOSTCC := gcc
else
HOSTCC := $(CC)
endif

ifeq ($(CXX),)
HOSTCXX := g++
else
HOSTCXX := $(CXX)
endif

ifneq (,$(wildcard $(TOOLCHAIN)/base_tools))
include $(TOOLCHAIN)/base_tools
else
export PATH := $(TOOLCHAIN)/bin:$(PATH)
PREFIX := arm-none-eabi-
OBJCOPY := $(PREFIX)objcopy
export CC := $(PREFIX)gcc
export AS := $(PREFIX)as
endif
export CPP := $(PREFIX)cpp
export LD := $(PREFIX)ld

ifeq ($(OS),Windows_NT)
EXE := .exe
else
EXE :=
endif

TITLE       := POKEMON EMER
GAME_CODE   := BPEE
MAKER_CODE  := 01
REVISION    := 0
MODERN      ?= 0

SHELL := /bin/bash -o pipefail

ELF = $(ROM:.gba=.elf)
MAP = $(ROM:.gba=.map)

C_SUBDIR = src
GFLIB_SUBDIR = gflib
ASM_SUBDIR = asm
DATA_SRC_SUBDIR = src/data
DATA_ASM_SUBDIR = data
SONG_SUBDIR = sound/songs
MID_SUBDIR = sound/songs/midi
SAMPLE_SUBDIR = sound/direct_sound_samples
CRY_SUBDIR = sound/direct_sound_samples/cries

C_BUILDDIR = $(OBJ_DIR)/$(C_SUBDIR)
GFLIB_BUILDDIR = $(OBJ_DIR)/$(GFLIB_SUBDIR)
ASM_BUILDDIR = $(OBJ_DIR)/$(ASM_SUBDIR)
DATA_ASM_BUILDDIR = $(OBJ_DIR)/$(DATA_ASM_SUBDIR)
SONG_BUILDDIR = $(OBJ_DIR)/$(SONG_SUBDIR)
MID_BUILDDIR = $(OBJ_DIR)/$(MID_SUBDIR)

ASFLAGS := -mcpu=arm7tdmi --defsym MODERN=$(MODERN)

ifeq ($(MODERN),0)
CC1             := tools/agbcc/bin/agbcc$(EXE)
override CFLAGS += -mthumb-interwork -Wimplicit -Wparentheses -Werror -O2 -fhex-asm -g
ROM := pokeemerald.gba
OBJ_DIR := build/emerald
LIBPATH := -L ../../tools/agbcc/lib
else
CC1              = $(shell $(CC) --print-prog-name=cc1) -quiet
override CFLAGS += -mthumb -mthumb-interwork -O2 -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -fno-toplevel-reorder -Wno-pointer-to-int-cast -g
ROM := pokeemerald_modern.gba
OBJ_DIR := build/modern
LIBPATH := -L "$(dir $(shell $(CC) -mthumb -print-file-name=libgcc.a))" -L "$(dir $(shell $(CC) -mthumb -print-file-name=libc.a))"
endif

CPPFLAGS := -iquote include -iquote $(GFLIB_SUBDIR) -Wno-trigraphs -DMODERN=$(MODERN)
ifeq ($(MODERN),0)
CPPFLAGS += -I tools/agbcc/include -I tools/agbcc
endif

LDFLAGS = -Map ../../$(MAP)

LIB := $(LIBPATH) -lgcc -lc -L../../libagbsyscall -lagbsyscall

SHA1 := $(shell { command -v sha1sum || command -v shasum; } 2>/dev/null) -c
GFX := tools/gbagfx/gbagfx$(EXE)
AIF := tools/aif2pcm/aif2pcm$(EXE)
MID := tools/mid2agb/mid2agb$(EXE)
SCANINC := tools/scaninc/scaninc$(EXE)
PREPROC := tools/preproc/preproc$(EXE)
RAMSCRGEN := tools/ramscrgen/ramscrgen$(EXE)
FIX := tools/gbafix/gbafix$(EXE)
MAPJSON := tools/mapjson/mapjson$(EXE)
JSONPROC := tools/jsonproc/jsonproc$(EXE)

TOOLDIRS := $(filter-out tools/agbcc tools/binutils,$(wildcard tools/*))
TOOLBASE = $(TOOLDIRS:tools/%=%)
TOOLS = $(foreach tool,$(TOOLBASE),tools/$(tool)/$(tool)$(EXE))

MAKEFLAGS += --no-print-directory

# Clear the default suffixes
.SUFFIXES:
# Don't delete intermediate files
.SECONDARY:
# Delete files that weren't built properly
.DELETE_ON_ERROR:

# Secondary expansion is required for dependency variables in object rules.
.SECONDEXPANSION:

.PHONY: all rom clean compare tidy tools mostlyclean clean-tools $(TOOLDIRS) libagbsyscall modern

infoshell = $(foreach line, $(shell $1 | sed "s/ /__SPACE__/g"), $(info $(subst __SPACE__, ,$(line))))

# Build tools when building the rom
# Disable dependency scanning for clean/tidy/tools
ifeq (,$(filter-out all rom compare modern libagbsyscall,$(MAKECMDGOALS)))
$(call infoshell, $(MAKE) tools)
else
NODEP := 1
endif

C_SRCS_IN := $(wildcard $(C_SUBDIR)/*.c $(C_SUBDIR)/*/*.c $(C_SUBDIR)/*/*/*.c)
C_SRCS := $(foreach src,$(C_SRCS_IN),$(if $(findstring .inc.c,$(src)),,$(src)))
C_OBJS := $(patsubst $(C_SUBDIR)/%.c,$(C_BUILDDIR)/%.o,$(C_SRCS))

GFLIB_SRCS := $(wildcard $(GFLIB_SUBDIR)/*.c)
GFLIB_OBJS := $(patsubst $(GFLIB_SUBDIR)/%.c,$(GFLIB_BUILDDIR)/%.o,$(GFLIB_SRCS))

C_ASM_SRCS += $(wildcard $(C_SUBDIR)/*.s $(C_SUBDIR)/*/*.s $(C_SUBDIR)/*/*/*.s)
C_ASM_OBJS := $(patsubst $(C_SUBDIR)/%.s,$(C_BUILDDIR)/%.o,$(C_ASM_SRCS))

ASM_SRCS := $(wildcard $(ASM_SUBDIR)/*.s)
ASM_OBJS := $(patsubst $(ASM_SUBDIR)/%.s,$(ASM_BUILDDIR)/%.o,$(ASM_SRCS))

# get all the data/*.s files EXCEPT the ones with specific rules
REGULAR_DATA_ASM_SRCS := $(filter-out $(DATA_ASM_SUBDIR)/maps.s $(DATA_ASM_SUBDIR)/map_events.s, $(wildcard $(DATA_ASM_SUBDIR)/*.s))

DATA_ASM_SRCS := $(wildcard $(DATA_ASM_SUBDIR)/*.s)
DATA_ASM_OBJS := $(patsubst $(DATA_ASM_SUBDIR)/%.s,$(DATA_ASM_BUILDDIR)/%.o,$(DATA_ASM_SRCS))

SONG_SRCS := $(wildcard $(SONG_SUBDIR)/*.s)
SONG_OBJS := $(patsubst $(SONG_SUBDIR)/%.s,$(SONG_BUILDDIR)/%.o,$(SONG_SRCS))

MID_SRCS := $(wildcard $(MID_SUBDIR)/*.mid)
MID_OBJS := $(patsubst $(MID_SUBDIR)/%.mid,$(MID_BUILDDIR)/%.o,$(MID_SRCS))

OBJS     := $(C_OBJS) $(GFLIB_OBJS) $(C_ASM_OBJS) $(ASM_OBJS) $(DATA_ASM_OBJS) $(SONG_OBJS) $(MID_OBJS)
OBJS_REL := $(patsubst $(OBJ_DIR)/%,%,$(OBJS))

SUBDIRS  := $(sort $(dir $(OBJS)))

AUTO_GEN_TARGETS :=

$(shell mkdir -p $(SUBDIRS))

all: rom

tools: $(TOOLDIRS)

$(TOOLDIRS):
	@$(MAKE) -C $@ CC=$(HOSTCC) CXX=$(HOSTCXX)

rom: $(ROM)
ifeq ($(COMPARE),1)
	@$(SHA1) rom.sha1
endif

# For contributors to make sure a change didn't affect the contents of the ROM.
compare: ; @$(MAKE) COMPARE=1

clean: mostlyclean clean-tools

clean-tools:
	@$(foreach tooldir,$(TOOLDIRS),$(MAKE) clean -C $(tooldir);)

mostlyclean: tidy
	rm -f $(SAMPLE_SUBDIR)/*.bin
	rm -f $(CRY_SUBDIR)/*.bin
	rm -f $(MID_SUBDIR)/*.s
	find . \( -iname '*.1bpp' -o -iname '*.4bpp' -o -iname '*.8bpp' -o -iname '*.gbapal' -o -iname '*.lz' -o -iname '*.rl' -o -iname '*.latfont' -o -iname '*.hwjpnfont' -o -iname '*.fwjpnfont' \) -exec rm {} +
	rm -f $(DATA_ASM_SUBDIR)/layouts/layouts.inc $(DATA_ASM_SUBDIR)/layouts/layouts_table.inc
	rm -f $(DATA_ASM_SUBDIR)/maps/connections.inc $(DATA_ASM_SUBDIR)/maps/events.inc $(DATA_ASM_SUBDIR)/maps/groups.inc $(DATA_ASM_SUBDIR)/maps/headers.inc
	find $(DATA_ASM_SUBDIR)/maps \( -iname 'connections.inc' -o -iname 'events.inc' -o -iname 'header.inc' \) -exec rm {} +
	rm -f $(AUTO_GEN_TARGETS)
	@$(MAKE) clean -C libagbsyscall

tidy:
	rm -f $(ROM) $(ELF) $(MAP)
	rm -r $(OBJ_DIR)
ifeq ($(MODERN),0)
	@$(MAKE) tidy MODERN=1
endif

ifneq ($(MODERN),0)
$(C_BUILDDIR)/berry_crush.o: override CFLAGS += -Wno-address-of-packed-member
endif

include graphics_file_rules.mk
include map_data_rules.mk
include spritesheet_rules.mk
include json_data_rules.mk
include songs.mk

%.s: ;
%.png: ;
%.pal: ;
%.aif: ;

%.1bpp: %.png  ; $(GFX) $< $@
%.4bpp: %.png  ; $(GFX) $< $@
%.8bpp: %.png  ; $(GFX) $< $@
%.gbapal: %.pal ; $(GFX) $< $@
%.gbapal: %.png ; $(GFX) $< $@
%.lz: % ; $(GFX) $< $@
%.rl: % ; $(GFX) $< $@
$(CRY_SUBDIR)/%.bin: $(CRY_SUBDIR)/%.aif ; $(AIF) $< $@ --compress
sound/%.bin: sound/%.aif ; $(AIF) $< $@

ifeq ($(MODERN),0)
$(C_BUILDDIR)/libc.o: CC1 := tools/agbcc/bin/old_agbcc
$(C_BUILDDIR)/libc.o: CFLAGS := -O2

$(C_BUILDDIR)/siirtc.o: CFLAGS := -mthumb-interwork

$(C_BUILDDIR)/agb_flash.o: CFLAGS := -O -mthumb-interwork
$(C_BUILDDIR)/agb_flash_1m.o: CFLAGS := -O -mthumb-interwork
$(C_BUILDDIR)/agb_flash_mx.o: CFLAGS := -O -mthumb-interwork

$(C_BUILDDIR)/m4a.o: CC1 := tools/agbcc/bin/old_agbcc

$(C_BUILDDIR)/record_mixing.o: CFLAGS += -ffreestanding
$(C_BUILDDIR)/librfu_intr.o: CC1 := tools/agbcc/bin/agbcc_arm
$(C_BUILDDIR)/librfu_intr.o: CFLAGS := -O2 -mthumb-interwork -quiet
else
$(C_BUILDDIR)/librfu_intr.o: CFLAGS := -mthumb-interwork -O2 -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -fno-toplevel-reorder -Wno-pointer-to-int-cast
endif

ifeq ($(NODEP),1)
$(C_BUILDDIR)/%.o: c_dep :=
else
$(C_BUILDDIR)/%.o: c_dep = $(shell [[ -f $(C_SUBDIR)/$*.c ]] && $(SCANINC) -I include -I tools/agbcc/include -I gflib $(C_SUBDIR)/$*.c)
endif

ifeq ($(DINFO),1)
override CFLAGS += -g
endif

$(C_BUILDDIR)/%.o : $(C_SUBDIR)/%.c $$(c_dep)
	@$(CPP) $(CPPFLAGS) $< -o $(C_BUILDDIR)/$*.i
	@$(PREPROC) $(C_BUILDDIR)/$*.i charmap.txt | $(CC1) $(CFLAGS) -o $(C_BUILDDIR)/$*.s
	@echo -e ".text\n\t.align\t2, 0\n" >> $(C_BUILDDIR)/$*.s
	$(AS) $(ASFLAGS) -o $@ $(C_BUILDDIR)/$*.s

ifeq ($(NODEP),1)
$(GFLIB_BUILDDIR)/%.o: c_dep :=
else
$(GFLIB_BUILDDIR)/%.o: c_dep = $(shell [[ -f $(GFLIB_SUBDIR)/$*.c ]] && $(SCANINC) -I include -I tools/agbcc/include -I gflib $(GFLIB_SUBDIR)/$*.c)
endif

$(GFLIB_BUILDDIR)/%.o : $(GFLIB_SUBDIR)/%.c $$(c_dep)
	@$(CPP) $(CPPFLAGS) $< -o $(GFLIB_BUILDDIR)/$*.i
	@$(PREPROC) $(GFLIB_BUILDDIR)/$*.i charmap.txt | $(CC1) $(CFLAGS) -o $(GFLIB_BUILDDIR)/$*.s
	@echo -e ".text\n\t.align\t2, 0\n" >> $(GFLIB_BUILDDIR)/$*.s
	$(AS) $(ASFLAGS) -o $@ $(GFLIB_BUILDDIR)/$*.s

ifeq ($(NODEP),1)
$(C_BUILDDIR)/%.o: c_asm_dep :=
else
$(C_BUILDDIR)/%.o: c_asm_dep = $(shell [[ -f $(C_SUBDIR)/$*.s ]] && $(SCANINC) -I "" $(C_SUBDIR)/$*.s)
endif

$(C_BUILDDIR)/%.o: $(C_SUBDIR)/%.s $$(c_asm_dep)
	$(AS) $(ASFLAGS) -o $@ $<

# The dep rules have to be explicit or else missing files won't be reported.
# As a side effect, they're evaluated immediately instead of when the rule is invoked.
# It doesn't look like $(shell) can be deferred so there might not be a better way.

ifeq ($(NODEP),1)
$(ASM_BUILDDIR)/%.o: $(ASM_SUBDIR)/%.s
	$(AS) $(ASFLAGS) -o $@ $<
else
define ASM_DEP
$1: $2 $$(shell $(SCANINC) -I include -I "" $2)
	$$(AS) $$(ASFLAGS) -o $$@ $$<
endef
$(foreach src, $(ASM_SRCS), $(eval $(call ASM_DEP,$(patsubst $(ASM_SUBDIR)/%.s,$(ASM_BUILDDIR)/%.o, $(src)),$(src))))
endif

ifeq ($(NODEP),1)
$(DATA_ASM_BUILDDIR)/%.o: $(DATA_ASM_SUBDIR)/%.s
	$(PREPROC) $< charmap.txt | $(CPP) -I include | $(AS) $(ASFLAGS) -o $@
else
define DATA_ASM_DEP
$1: $2 $$(shell $(SCANINC) -I include -I "" $2)
	$$(PREPROC) $$< charmap.txt | $$(CPP) -I include | $$(AS) $$(ASFLAGS) -o $$@
endef
$(foreach src, $(REGULAR_DATA_ASM_SRCS), $(eval $(call DATA_ASM_DEP,$(patsubst $(DATA_ASM_SUBDIR)/%.s,$(DATA_ASM_BUILDDIR)/%.o, $(src)),$(src))))
endif

$(SONG_BUILDDIR)/%.o: $(SONG_SUBDIR)/%.s
	$(AS) $(ASFLAGS) -I sound -o $@ $<

$(OBJ_DIR)/sym_bss.ld: sym_bss.txt
	$(RAMSCRGEN) .bss $< ENGLISH > $@

$(OBJ_DIR)/sym_common.ld: sym_common.txt $(C_OBJS) $(wildcard common_syms/*.txt)
	$(RAMSCRGEN) COMMON $< ENGLISH -c $(C_BUILDDIR),common_syms > $@

$(OBJ_DIR)/sym_ewram.ld: sym_ewram.txt
	$(RAMSCRGEN) ewram_data $< ENGLISH > $@

ifeq ($(MODERN),0)
LD_SCRIPT := ld_script.txt
LD_SCRIPT_DEPS := $(OBJ_DIR)/sym_bss.ld $(OBJ_DIR)/sym_common.ld $(OBJ_DIR)/sym_ewram.ld
else
LD_SCRIPT := ld_script_modern.txt
LD_SCRIPT_DEPS :=
endif

$(OBJ_DIR)/ld_script.ld: $(LD_SCRIPT) $(LD_SCRIPT_DEPS)
	cd $(OBJ_DIR) && sed "s#tools/#../../tools/#g" ../../$(LD_SCRIPT) > ld_script.ld

$(ELF): $(OBJ_DIR)/ld_script.ld $(OBJS) libagbsyscall
	cd $(OBJ_DIR) && $(LD) $(LDFLAGS) -T ld_script.ld -o ../../$@ $(OBJS_REL) $(LIB)
	$(FIX) $@ -t"$(TITLE)" -c$(GAME_CODE) -m$(MAKER_CODE) -r$(REVISION) --silent

$(ROM): $(ELF)
	$(OBJCOPY) -O binary $< $@
	$(FIX) $@ -p --silent

modern: ; @$(MAKE) MODERN=1

libagbsyscall:
	@$(MAKE) -C libagbsyscall TOOLCHAIN=$(TOOLCHAIN)

path: Makefile


code:
# Pokémon Emerald

[![Build Status][travis-badge]][travis]

[travis]: https://travis-ci.org/pret/pokeemerald
[travis-badge]: https://travis-ci.org/pret/pokeemerald.svg?branch=master

This is a decompilation of Pokémon Emerald.

It builds the following ROM:

* [**pokeemerald.gba**](https://datomatic.no-intro.org/index.php?page=show_record&s=23&n=1961) `sha1: f3ae088181bf583e55daf962a92bb46f4f1d07b7`

To set up the repository, see [INSTALL.md](INSTALL.md).

## See also

Other disassembly and/or decompilation projects:
* [**Pokémon Red and Blue**](https://github.com/pret/pokered)
* [**Pokémon Gold and Silver (Space World '97 demo)**](https://github.com/pret/pokegold-spaceworld)
* [**Pokémon Yellow**](https://github.com/pret/pokeyellow)
* [**Pokémon Trading Card Game**](https://github.com/pret/poketcg)
* [**Pokémon Pinball**](https://github.com/pret/pokepinball)
* [**Pokémon Stadium**](https://github.com/pret/pokestadium)
* [**Pokémon Gold and Silver**](https://github.com/pret/pokegold)
* [**Pokémon Crystal**](https://github.com/pret/pokecrystal)
* [**Pokémon Ruby and Sapphire**](https://github.com/pret/pokeruby)
* [**Pokémon Pinball: Ruby & Sapphire**](https://github.com/pret/pokepinballrs)
* [**Pokémon FireRed and LeafGreen**](https://github.com/pret/pokefirered)
* [**Pokémon Mystery Dungeon: Red Rescue Team**](https://github.com/pret/pmd-red)

## Contacts

You can find us on [Discord](https://discord.gg/d5dubZ3) and [IRC](https://kiwiirc.com/client/irc.freenode.net/?#pret).


code:
	.include "asm/macros/asm.inc"
	.include "asm/macros/function.inc"
	.include "asm/macros/movement.inc"
	.include "asm/macros/window.inc"
	.include "asm/macros/pokemon_data.inc"
	.include "asm/macros/ec.inc"
	.include "asm/macros/map.inc"
	.include "asm/macros/field_effect_script.inc"
	.include "asm/macros/trainer_hill.inc"
	.include "asm/macros/battle_tent.inc"
	.include "asm/macros/battle_frontier/apprentice.inc"
	.include "asm/macros/battle_frontier/battle_arena.inc"
	.include "asm/macros/battle_frontier/battle_dome.inc"
	.include "asm/macros/battle_frontier/battle_factory.inc"
	.include "asm/macros/battle_frontier/battle_palace.inc"
	.include "asm/macros/battle_frontier/battle_pike.inc"
	.include "asm/macros/battle_frontier/battle_pyramid.inc"
	.include "asm/macros/battle_frontier/battle_tower.inc"
	.include "asm/macros/battle_frontier/frontier_util.inc"

	.macro region_map_entry x, y, width, height, name
	.byte \x
	.byte \y
	.byte \width
	.byte \height
	.4byte gMapName_\name
	.endm

	.macro obj_tiles address, uncompressed_size, tag = 0
	.4byte \address
	.2byte \uncompressed_size
	.2byte \tag
	.endm

	.macro null_obj_tiles
	obj_tiles 0, 0, 0
	.endm

	.macro obj_pal address, tag
	.4byte \address
	.2byte \tag
	.2byte 0@ padding
	.endm

	.macro null_obj_pal
	obj_pal 0, 0
	.endm

	.macro paired_pals tag, address
	.2byte \tag
	.2byte 0 @ padding
	.4byte \address
	.endm

@ For object animation frames.
	.macro obj_frame_tiles address, uncompressed_size
	.4byte \address
	.2byte \uncompressed_size
	.2byte 0 @ padding
	.endm

	.macro spr_template tile_tag, pal_tag, oam, anims, images, affine_anims, callback
	.2byte \tile_tag
	.2byte \pal_tag
	.4byte \oam
	.4byte \anims
	.4byte \images
	.4byte \affine_anims
	.4byte \callback
	.endm

@ Berry trees have a table defining the palette slot used for each of their 5
@ stages. However, the first 2 stages always use the same slots regardless of
@ the type of tree and the slots of the last 3 stages always equal each other.
	.macro berry_tree_palette_slot_table slot
	.byte 3, 4, \slot, \slot, \slot
	.endm

	.macro subsprite x, y, priority, tile_num_offset, size
	.byte \x
	.byte \y
	.2byte ((\priority) << 14) | ((\tile_num_offset) << 4) | SPRITE_SIZE_\size
	.endm

	.macro obj_image_anim_frame pic_id, duration, flags = 0
	.2byte \pic_id
	.byte (\flags) | (\duration)
	.byte 0 @ padding
	.endm

	.macro obj_image_anim_loop count
	.2byte 0xfffd
	.byte \count
	.byte 0 @ padding
	.endm

	.macro obj_image_anim_jump target_index
	.2byte 0xfffe
	.byte \target_index
	.byte 0 @ padding
	.endm

	.macro obj_image_anim_end
	.2byte 0xffff
	.2byte 0 @ padding
	.endm

	.macro obj_rot_scal_anim_frame delta_x_scale, delta_y_scale, delta_angle, duration
	.2byte \delta_x_scale
	.2byte \delta_y_scale
	.byte \delta_angle
	.byte \duration
	.2byte 0 @ padding
	.endm

	.macro obj_rot_scal_anim_loop count
	.2byte 0x7ffd
	.2byte \count
	.4byte 0 @ padding
	.endm

	.macro obj_rot_scal_anim_jump target_index
	.2byte 0x7ffe
	.2byte \target_index
	.4byte 0 @ padding
	.endm

	.macro obj_rot_scal_anim_end unknown=0
	.2byte 0x7fff
	.2byte \unknown
	.fill 4 @ padding
	.endm

	.macro door_anim_frame unknown, offset
	.byte \unknown
	.byte 0 @ padding
	.2byte \offset
	.endm

	.macro door_anim_gfx metatile_num, unknown, unknown2, tile_addr, palette_addr
	.2byte \metatile_num
	.byte \unknown
	.byte \unknown2
	.4byte \tile_addr
	.4byte \palette_addr
	.endm


code:
	.macro inc x
	.set \x, \x + 1
	.endm

	.macro enum_start x=0
	.set __enum__, \x
	.endm

	.macro enum constant
	.equiv \constant, __enum__
	inc __enum__
	.endm


code:
	.macro if_random_less_than param0:req, param1:req
	.byte 0x0
	.byte \param0
	.4byte \param1
	.endm

	.macro if_random_greater_than param0:req, param1:req
	.byte 0x1
	.byte \param0
	.4byte \param1
	.endm

	.macro if_random_equal param0:req, param1:req
	.byte 0x2
	.byte \param0
	.4byte \param1
	.endm

	.macro if_random_not_equal param0:req, param1:req
	.byte 0x3
	.byte \param0
	.4byte \param1
	.endm

	.macro score param0:req
	.byte 0x4
	.byte \param0
	.endm

	.macro if_hp_less_than battler:req, param1:req, param2:req
	.byte 0x5
	.byte \battler
	.byte \param1
	.4byte \param2
	.endm

	.macro if_hp_more_than battler:req, param1:req, param2:req
	.byte 0x6
	.byte \battler
	.byte \param1
	.4byte \param2
	.endm

	.macro if_hp_equal battler:req, param1:req, param2:req
	.byte 0x7
	.byte \battler
	.byte \param1
	.4byte \param2
	.endm

	.macro if_hp_not_equal battler:req, param1:req, param2:req
	.byte 0x8
	.byte \battler
	.byte \param1
	.4byte \param2
	.endm

	.macro if_status battler:req, status1:req, param2:req
	.byte 0x9
	.byte \battler
	.4byte \status1
	.4byte \param2
	.endm

	.macro if_not_status battler:req, status1:req, param2:req
	.byte 0xa
	.byte \battler
	.4byte \status1
	.4byte \param2
	.endm

	.macro if_status2 battler:req, status2:req, param2:req
	.byte 0xb
	.byte \battler
	.4byte \status2
	.4byte \param2
	.endm

	.macro if_not_status2 battler:req, status2:req, param2:req
	.byte 0xc
	.byte \battler
	.4byte \status2
	.4byte \param2
	.endm

	.macro if_status3 battler:req, status3:req, param2:req
	.byte 0xd
	.byte \battler
	.4byte \status3
	.4byte \param2
	.endm

	.macro if_not_status3 battler:req, status3:req, param2:req
	.byte 0xe
	.byte \battler
	.4byte \status3
	.4byte \param2
	.endm

	.macro if_side_affecting battler:req, sidestatus:req, param2:req
	.byte 0xf
	.byte \battler
	.4byte \sidestatus
	.4byte \param2
	.endm

	.macro if_not_side_affecting battler:req, sidestatus:req, param2:req
	.byte 0x10
	.byte \battler
	.4byte \sidestatus
	.4byte \param2
	.endm

	.macro if_less_than param0:req, param1:req
	.byte 0x11
	.byte \param0
	.4byte \param1
	.endm

	.macro if_more_than param0:req, param1:req
	.byte 0x12
	.byte \param0
	.4byte \param1
	.endm

	.macro if_equal param0:req, param1:req
	.byte 0x13
	.byte \param0
	.4byte \param1
	.endm

	.macro if_not_equal param0:req, param1:req
	.byte 0x14
	.byte \param0
	.4byte \param1
	.endm

	.macro if_less_than_ptr param0:req, param1:req
	.byte 0x15
	.4byte \param0
	.4byte \param1
	.endm

	.macro if_more_than_ptr param0:req, param1:req
	.byte 0x16
	.4byte \param0
	.4byte \param1
	.endm

	.macro if_equal_ptr param0:req, param1:req
	.byte 0x17
	.4byte \param0
	.4byte \param1
	.endm

	.macro if_not_equal_ptr param0:req, param1:req
	.byte 0x18
	.4byte \param0
	.4byte \param1
	.endm

	.macro if_move param0:req, param1:req
	.byte 0x19
	.2byte \param0
	.4byte \param1
	.endm

	.macro if_not_move param0:req, param1:req
	.byte 0x1a
	.2byte \param0
	.4byte \param1
	.endm

	.macro if_in_bytes param0:req, param1:req
	.byte 0x1b
	.4byte \param0
	.4byte \param1
	.endm

	.macro if_not_in_bytes param0:req, param1:req
	.byte 0x1c
	.4byte \param0
	.4byte \param1
	.endm

	.macro if_in_hwords param0:req, param1:req
	.byte 0x1d
	.4byte \param0
	.4byte \param1
	.endm

	.macro if_not_in_hwords param0:req, param1:req
	.byte 0x1e
	.4byte \param0
	.4byte \param1
	.endm

	.macro if_user_has_attacking_move param0:req
	.byte 0x1f
	.4byte \param0
	.endm

	.macro if_user_has_no_attacking_moves param0:req
	.byte 0x20
	.4byte \param0
	.endm

	.macro get_turn_count
	.byte 0x21
	.endm

	.macro get_type param0:req
	.byte 0x22
	.byte \param0
	.endm

	.macro get_considered_move_power
	.byte 0x23
	.endm

	.macro get_how_powerful_move_is
	.byte 0x24
	.endm

	.macro get_last_used_bank_move battler:req
	.byte 0x25
	.byte \battler
	.endm

	.macro if_equal_ param0:req, param1:req
	.byte 0x26
	.byte \param0
	.4byte \param1
	.endm

	.macro if_not_equal_ param0:req, param1:req
	.byte 0x27
	.byte \param0
	.4byte \param1
	.endm

	.macro if_user_goes param0:req, param1:req
	.byte 0x28
	.byte \param0
	.4byte \param1
	.endm

	.macro if_user_doesnt_go param0:req, param1:req
	.byte 0x29
	.byte \param0
	.4byte \param1
	.endm

	.macro nullsub_2A
	.byte 0x2a
	.endm

	.macro nullsub_2B
	.byte 0x2b
	.endm

	.macro count_usable_party_mons battler:req
	.byte 0x2c
	.byte \battler
	.endm

	.macro get_considered_move
	.byte 0x2d
	.endm

	.macro get_considered_move_effect
	.byte 0x2e
	.endm

	.macro get_ability battler:req
	.byte 0x2f
	.byte \battler
	.endm

	.macro get_highest_type_effectiveness
	.byte 0x30
	.endm

	.macro if_type_effectiveness param0:req, param1:req
	.byte 0x31
	.byte \param0
	.4byte \param1
	.endm

	.macro nullsub_32
	.byte 0x32
	.endm

	.macro nullsub_33
	.byte 0x33
	.endm

	.macro if_status_in_party battler:req, status1:req, param2:req
	.byte 0x34
	.byte \battler
	.4byte \status1
	.4byte \param2
	.endm

	.macro if_status_not_in_party battler:req, status1:req, param2:req
	.byte 0x35
	.byte \battler
	.4byte \status1
	.4byte \param2
	.endm

	.macro get_weather
	.byte 0x36
	.endm

	.macro if_effect param0:req, param1:req
	.byte 0x37
	.byte \param0
	.4byte \param1
	.endm

	.macro if_not_effect param0:req, param1:req
	.byte 0x38
	.byte \param0
	.4byte \param1
	.endm

	.macro if_stat_level_less_than battler:req, stat:req, param2:req, param3:req
	.byte 0x39
	.byte \battler
	.byte \stat
	.byte \param2
	.4byte \param3
	.endm

	.macro if_stat_level_more_than battler:req, stat:req, param2:req, param3:req
	.byte 0x3a
	.byte \battler
	.byte \stat
	.byte \param2
	.4byte \param3
	.endm

	.macro if_stat_level_equal battler:req, stat:req, param2:req, param3:req
	.byte 0x3b
	.byte \battler
	.byte \stat
	.byte \param2
	.4byte \param3
	.endm

	.macro if_stat_level_not_equal battler:req, stat:req, param2:req, param3:req
	.byte 0x3c
	.byte \battler
	.byte \stat
	.byte \param2
	.4byte \param3
	.endm

	.macro if_can_faint param0:req
	.byte 0x3d
	.4byte \param0
	.endm

	.macro if_cant_faint param0:req
	.byte 0x3e
	.4byte \param0
	.endm

	.macro if_has_move battler:req, param1:req, param2:req
	.byte 0x3f
	.byte \battler
	.2byte \param1
	.4byte \param2
	.endm

	.macro if_doesnt_have_move battler:req, param1:req, param2:req
	.byte 0x40
	.byte \battler
	.2byte \param1
	.4byte \param2
	.endm

	.macro if_has_move_with_effect battler:req, param1:req, param2:req
	.byte 0x41
	.byte \battler
	.byte \param1
	.4byte \param2
	.endm

	.macro if_doesnt_have_move_with_effect battler:req, param1:req, param2:req
	.byte 0x42
	.byte \battler
	.byte \param1
	.4byte \param2
	.endm

	.macro if_any_move_disabled_or_encored battler:req, param1:req, param2:req
	.byte 0x43
	.byte \battler
	.byte \param1
	.4byte \param2
	.endm

	.macro if_curr_move_disabled_or_encored param0:req, param1:req
	.byte 0x44
	.byte \param0
	.4byte \param1
	.endm

	.macro flee
	.byte 0x45
	.endm

	.macro if_random_safari_flee param0:req
	.byte 0x46
	.4byte \param0
	.endm

	.macro watch
	.byte 0x47
	.endm

	.macro get_hold_effect battler:req
	.byte 0x48
	.byte \battler
	.endm

	.macro get_gender battler:req
	.byte 0x49
	.byte \battler
	.endm

	.macro is_first_turn_for battler:req
	.byte 0x4a
	.byte \battler
	.endm

	.macro get_stockpile_count battler:req
	.byte 0x4b
	.byte \battler
	.endm

	.macro is_double_battle
	.byte 0x4c
	.endm

	.macro get_used_held_item battler:req
	.byte 0x4d
	.byte \battler
	.endm

	.macro get_move_type_from_result
	.byte 0x4e
	.endm

	.macro get_move_power_from_result
	.byte 0x4f
	.endm

	.macro get_move_effect_from_result
	.byte 0x50
	.endm

	.macro get_protect_count battler:req
	.byte 0x51
	.byte \battler
	.endm

	.macro nullsub_52
	.byte 0x52
	.endm

	.macro nullsub_53
	.byte 0x53
	.endm

	.macro nullsub_54
	.byte 0x54
	.endm

	.macro nullsub_55
	.byte 0x55
	.endm

	.macro nullsub_56
	.byte 0x56
	.endm

	.macro nullsub_57
	.byte 0x57
	.endm

	.macro call param0:req
	.byte 0x58
	.4byte \param0
	.endm

	.macro goto param0:req
	.byte 0x59
	.4byte \param0
	.endm

	.macro end
	.byte 0x5a
	.endm

	.macro if_level_cond param0:req, param1:req
	.byte 0x5b
	.byte \param0
	.4byte \param1
	.endm

	.macro if_target_taunted param0:req
	.byte 0x5c
	.4byte \param0
	.endm

	.macro if_target_not_taunted param0:req
	.byte 0x5d
	.4byte \param0
	.endm

	.macro if_target_is_ally param0:req
	.byte 0x5e
	.4byte \param0
	.endm

	.macro is_of_type battler:req, type:req
	.byte 0x5f
	.byte \battler
	.byte \type
	.endm

	.macro check_ability battler:req, ability:req
	.byte 0x60
	.byte \battler
	.byte \ability
	.endm

	.macro if_flash_fired battler:req, param1:req
	.byte 0x61
	.byte \battler
	.4byte \param1
	.endm

	.macro if_holds_item battler:req, param1:req, param2:req
	.byte 0x62
	.byte \battler
	.2byte \param1
	.4byte \param2
	.endm

@ useful script macros
	.macro get_curr_move_type
	get_type AI_TYPE_MOVE
	.endm

	.macro get_user_type1
	get_type AI_TYPE1_USER
	.endm

	.macro get_user_type2
	get_type AI_TYPE2_USER
	.endm

	.macro get_target_type1
	get_type AI_TYPE1_TARGET
	.endm

	.macro get_target_type2
	get_type AI_TYPE2_TARGET
	.endm

	.macro if_ability battler:req, ability:req, ptr:req
	check_ability \battler, \ability
	if_equal 1, \ptr
	.endm

	.macro if_no_ability battler:req, ability:req, ptr:req
	check_ability \battler, \ability
	if_equal 0, \ptr
	.endm

	.macro if_type battler:req, type:req, ptr:req
	is_of_type \battler, \type
	if_equal 1, \ptr
	.endm

	.macro if_no_type battler:req, type:req, ptr:req
	is_of_type \battler, \type
	if_equal 0, \ptr
	.endm

	.macro if_target_faster ptr:req
	if_user_goes 1, \ptr
	.endm

	.macro if_user_faster ptr:req
	if_user_goes 0, \ptr
	.endm

	.macro if_double_battle ptr:req
	is_double_battle
	if_equal 1, \ptr
	.endm

	.macro if_not_double_battle ptr:req
	is_double_battle
	if_equal 0, \ptr
	.endm

	.macro if_any_move_disabled battler:req, ptr:req
	if_any_move_disabled_or_encored \battler, 0, \ptr
	.endm

	.macro if_any_move_encored battler:req, ptr:req
	if_any_move_disabled_or_encored \battler, 1, \ptr
	.endm


code:
@ commands

	.macro loadspritegfx tag:req
	.byte 0x0
	.2byte \tag
	.endm

	.macro unloadspritegfx tag:req
	.byte 0x1
	.2byte \tag
	.endm

.macro createsprite template:req, anim_battler:req, subpriority_offset:req, argv:vararg
	.byte 0x02
	.4byte \template
	.if \anim_battler == ANIM_TARGET
	.byte 0x80 | (\subpriority_offset & 0x7F)
	.else
	.byte (\subpriority_offset & 0x7F)
	.endif
	.byte (.Lsprite_\@_2 - .Lsprite_\@_1) / 2
.Lsprite_\@_1:
	.2byte \argv
.Lsprite_\@_2:
	.endm

	.macro createvisualtask addr:req, priority:req, argv:vararg
	.byte 0x03
	.4byte \addr
	.byte \priority
	.byte (.Lcreatetask_\@_2 - .Lcreatetask_\@_1) / 2
.Lcreatetask_\@_1:
	.2byte \argv
.Lcreatetask_\@_2:
	.endm

	.macro delay param0:req
	.byte 0x4
	.byte \param0
	.endm

	.macro waitforvisualfinish
	.byte 0x5
	.endm

	.macro hang1
	.byte 0x6
	.endm

	.macro hang2
	.byte 0x7
	.endm

	.macro end
	.byte 0x8
	.endm

	.macro playse se:req
	.byte 0x9
	.2byte \se
	.endm

	.macro monbg battler:req
	.byte 0xa
	.byte \battler
	.endm

	.macro clearmonbg battler:req
	.byte 0xb
	.byte \battler
	.endm

	.macro setalpha eva:req, evb:req
	.byte 0x0C
	.2byte ((\evb) << 8) | (\eva)
	.endm

	.macro blendoff
	.byte 0xd
	.endm

	.macro call param0:req
	.byte 0xe
	.4byte \param0
	.endm

	.macro return
	.byte 0xf
	.endm

	.macro setarg param0:req, param1:req
	.byte 0x10
	.byte \param0
	.2byte \param1
	.endm

	.macro choosetwoturnanim param0:req, param1:req
	.byte 0x11
	.4byte \param0
	.4byte \param1
	.endm

	.macro jumpifmoveturn param0:req, ptr:req
	.byte 0x12
	.byte \param0
	.4byte \ptr
	.endm

	.macro goto ptr:req
	.byte 0x13
	.4byte \ptr
	.endm

	.macro fadetobg bg:req
	.byte 0x14
	.byte \bg
	.endm

	.macro restorebg
	.byte 0x15
	.endm

	.macro waitbgfadeout
	.byte 0x16
	.endm

	.macro waitbgfadein
	.byte 0x17
	.endm

	.macro changebg bg:req
	.byte 0x18
	.byte \bg
	.endm

	.macro playsewithpan se:req, pan:req
	.byte 0x19
	.2byte \se
	.byte \pan
	.endm

	.macro setpan pan:req
	.byte 0x1a
	.byte \pan
	.endm

	.macro panse_1B se:req, param1:req, param2:req, param3:req, param4:req
	.byte 0x1b
	.2byte \se
	.byte \param1
	.byte \param2
	.byte \param3
	.byte \param4
	.endm

	.macro loopsewithpan se:req, pan:req, wait:req, times:req
	.byte 0x1c
	.2byte \se
	.byte \pan
	.byte \wait
	.byte \times
	.endm

	.macro waitplaysewithpan se:req, pan:req, wait:req
	.byte 0x1d
	.2byte \se
	.byte \pan
	.byte \wait
	.endm

	.macro setbldcnt param0:req
	.byte 0x1e
	.2byte \param0
	.endm

	.macro createsoundtask addr:req, argv:vararg
	.byte 0x1F
	.4byte \addr
	.byte (.Lcreatetask_1F_\@_2 - .Lcreatetask_1F_\@_1) / 2
.Lcreatetask_1F_\@_1:
	.2byte \argv
.Lcreatetask_1F_\@_2:
	.endm

	.macro waitsound
	.byte 0x20
	.endm

	.macro jumpargeq param0:req, param1:req, ptr:req
	.byte 0x21
	.byte \param0
	.2byte \param1
	.4byte \ptr
	.endm

	.macro monbg_22 battler:req
	.byte 0x22
	.byte \battler
	.endm

	.macro clearmonbg_23 battler:req
	.byte 0x23
	.byte \battler
	.endm

	.macro jumpifcontest ptr:req
	.byte 0x24
	.4byte \ptr
	.endm

	.macro fadetobgfromset param0:req, param1:req, param2:req
	.byte 0x25
	.byte \param0
	.byte \param1
	.byte \param2
	.endm

	.macro panse_26 se:req, param1:req, param2:req, param3:req, param4:req
	.byte 0x26
	.2byte \se
	.byte \param1
	.byte \param2
	.byte \param3
	.byte \param4
	.endm

	.macro panse_27 se:req, param1:req, param2:req, param3:req, param4:req
	.byte 0x27
	.2byte \se
	.byte \param1
	.byte \param2
	.byte \param3
	.byte \param4
	.endm

	.macro monbgprio_28 battler:req
	.byte 0x28
	.byte \battler
	.endm

	.macro monbgprio_29
	.byte 0x29
	.endm

	.macro monbgprio_2A battler:req
	.byte 0x2a
	.byte \battler
	.endm

	.macro invisible battler:req
	.byte 0x2b
	.byte \battler
	.endm

	.macro visible battler:req
	.byte 0x2c
	.byte \battler
	.endm

	.macro doublebattle_2D battler:req
	.byte 0x2d
	.byte \battler
	.endm

	.macro doublebattle_2E battler:req
	.byte 0x2e
	.byte \battler
	.endm

	.macro stopsound
	.byte 0x2f
	.endm

@ useful macros
	.macro jumpreteq value:req, ptr:req
	jumpargeq ARG_RET_ID, \value, \ptr
	.endm

	.macro jumprettrue ptr:req
	jumpreteq TRUE, \ptr
	.endm

	.macro jumpretfalse ptr:req
	jumpreteq FALSE, \ptr
	.endm


code:
	@ TRUE if the player has talked to the Apprentice and answered their level mode question
	.macro apprentice_gavelvlmode
	setvar VAR_0x8004, APPRENTICE_FUNC_GAVE_LVLMODE
	special CallApprenticeFunction
	.endm

	@ Set the level mode the Apprentice should battle in
	.macro apprentice_setlvlmode lvlmode:req
	setvar VAR_0x8004, APPRENTICE_FUNC_SET_LVLMODE
	setorcopyvar VAR_0x8005, \lvlmode
	addvar VAR_0x8005, 1  @ Apprentice lvl mode is +1 from regular lvl mode value
	special CallApprenticeFunction
	.endm

	@ Question was answered, increment the number of questions answered
	.macro apprentice_answeredquestion
	setvar VAR_0x8004, APPRENTICE_FUNC_ANSWERED_QUESTION
	special CallApprenticeFunction
	.endm

	@ Show the response selection box to answer the Apprentice question. Menus are defined as APPRENTICE_ASK_*
	.macro apprentice_menu  which:req
	setvar VAR_0x8004, APPRENTICE_FUNC_MENU
	setvar VAR_0x8005, \which
	special CallApprenticeFunction
	waitstate
	.endm

	@ Shuffle and set the Apprentice party mons to pick between from their list of possible party species
	.macro apprentice_shufflespecies
	setvar VAR_0x8004, APPRENTICE_FUNC_SHUFFLE_SPECIES
	special CallApprenticeFunction
	.endm

	@ Randomize the question data (e.g. moves to pick between) and shuffle the order to ask them in
	.macro apprentice_randomizequestions
	setvar VAR_0x8004, APPRENTICE_FUNC_RANDOMIZE_QUESTIONS
	special CallApprenticeFunction
	.endm

	@ Print the APPRENTICE_MSG_* text for the current Apprentice
	.macro apprentice_msg  waitbuttonpress:req, which:req
	setvar VAR_0x8004, APPRENTICE_FUNC_PRINT_MSG
	setvar VAR_0x8005, \waitbuttonpress
	setvar VAR_0x8006, \which
	special CallApprenticeFunction
	waitstate
	.endm

	@ Clear the data for the current Player Apprentice
	.macro apprentice_reset
	setvar VAR_0x8004, APPRENTICE_FUNC_RESET
	special CallApprenticeFunction
	.endm

	@ Always returns TRUE. No side effect. May have been for debug or dummied for some other reason
	.macro apprentice_shouldcheckgone
	setvar VAR_0x8004, APPRENTICE_FUNC_CHECK_GONE
	special CallApprenticeFunction
	.endm

	@ Return the APPRENTICE_QUESTION_* value for the current question to ask
	.macro apprentice_getquestion
	setvar VAR_0x8004, APPRENTICE_FUNC_GET_QUESTION
	special CallApprenticeFunction
	.endm

	@ Get the number of mons that have been chosen for the Apprentice's party so far
	.macro apprentice_getnumpartymons
	setvar VAR_0x8004, APPRENTICE_FUNC_GET_NUM_PARTY_MONS
	special CallApprenticeFunction
	.endm

	@ Set the Apprentice party mon at the given slot. VAR_0x8005 is used implicitly as which of the 2 mons was selected
	.macro apprentice_setpartymon  slot:req
	copyvar VAR_0x8006, \slot
	setvar VAR_0x8004, APPRENTICE_FUNC_SET_PARTY_MON
	special CallApprenticeFunction
	.endm

	@ Allocate and set up data to track about the question
	.macro apprentice_initquestion  which:req
	setvar VAR_0x8004, APPRENTICE_FUNC_INIT_QUESTION_DATA
	setvar VAR_0x8005, \which
	special CallApprenticeFunction
	.endm

	@ Free allocated question data
	.macro apprentice_freequestion
	setvar VAR_0x8004, APPRENTICE_FUNC_FREE_QUESTION_DATA
	special CallApprenticeFunction
	.endm

	@ Buffer some APPRENTICE_BUFF_* string to the given stringvar (0 for STR_VAR_1, 1 for STR_VAR_2, 2 for STR_VAR_3)
	.macro apprentice_buff  stringvar:req, tobuff:req
	setvar VAR_0x8004, APPRENTICE_FUNC_BUFFER_STRING
	setvar VAR_0x8005, \stringvar
	.if \tobuff >= VARS_START
	copyvar VAR_0x8006, \tobuff
	.else
	setvar VAR_0x8006, \tobuff
	.endif
	special CallApprenticeFunction
	.endm

	@ Set which move to use that the player chose (implicitly VAR_0x8005)
	.macro apprentice_setmove
	setvar VAR_0x8004, APPRENTICE_FUNC_SET_MOVE
	special CallApprenticeFunction
	.endm

	@ Set which mon the Apprentice should lead with
	.macro apprentice_setleadmon  monId:req
	copyvar VAR_0x8005, \monId
	setvar VAR_0x8004, APPRENTICE_FUNC_SET_LEAD_MON
	special CallApprenticeFunction
	.endm

	@ Open the Bag Menu for the player to choose an item to recommend as a held item
	.macro apprentice_openbag
	setvar VAR_0x8004, APPRENTICE_FUNC_OPEN_BAG
	special CallApprenticeFunction
	waitstate
	.endm

	@ Try and set the recommended held item. FALSE if the item has been recommended before, as Battle Frontier forbids using the same held item for multiple party mons
	.macro apprentice_trysetitem
	setvar VAR_0x8004, APPRENTICE_FUNC_TRY_SET_HELD_ITEM
	special CallApprenticeFunction
	.endm

	@ Save the current Player Apprentice to the saveblock to make room for a new Apprentice
	.macro apprentice_save
	setvar VAR_0x8004, APPRENTICE_FUNC_SAVE
	special CallApprenticeFunction
	.endm

	@ Set the object event gfx for the Apprentice based on their trainer class
	.macro apprentice_setgfx
	setvar VAR_0x8004, APPRENTICE_FUNC_SET_GFX
	special CallApprenticeFunction
	.endm

	@ Always returns TRUE. No side effect. May have been for debug or dummied for some other reason
	.macro apprentice_shouldleave
	setvar VAR_0x8004, APPRENTICE_FUNC_SHOULD_LEAVE
	special CallApprenticeFunction
	.endm

	@ Shift the other saved Apprentices over to make room for saving a new Apprentice
	.macro apprentice_shiftsaved
	setvar VAR_0x8004, APPRENTICE_FUNC_SHIFT_SAVED
	special CallApprenticeFunction
	.endm


code:
	@ Initialize the Battle Arena challenge
	.macro arena_init
	setvar VAR_0x8004, BATTLE_ARENA_FUNC_INIT
	special CallBattleArenaFunction
	.endm

	@ Unused. Get the value of some ARENA_DATA_*. See GetArenaData for the data types that can be retrieved
	.macro arena_get data:req
	setvar VAR_0x8004, BATTLE_ARENA_FUNC_GET_DATA
	setvar VAR_0x8005, \data
	special CallBattleArenaFunction
	.endm

	@ Set some ARENA_DATA_* to val. See SetArenaData for the data types that can be set
	.macro arena_set data:req, val:req
	setvar VAR_0x8004, BATTLE_ARENA_FUNC_SET_DATA
	setvar VAR_0x8005, \data
	.if \val >= VARS_START
	copyvar VAR_0x8006, \val
	.else
	setvar VAR_0x8006, \val
	.endif
	special CallBattleArenaFunction
	.endm

	@ Save the game and set the challenge status
	.macro arena_save challengeStatus:req
	setvar VAR_0x8004, BATTLE_ARENA_FUNC_SAVE
	setvar VAR_0x8005, \challengeStatus
	special CallBattleArenaFunction
	.endm

	@ Unused. Set the prize item to give from one of two lists of possible prizes, depending on streak.
	.macro arena_setprize
	setvar VAR_0x8004, BATTLE_ARENA_FUNC_SET_PRIZE
	special CallBattleArenaFunction
	.endm

	@ Unused. Give the set prize item to the player. TRUE if room in Bag for prize, FALSE otherwise
	.macro arena_giveprize
	setvar VAR_0x8004, BATTLE_ARENA_FUNC_GIVE_PRIZE
	special CallBattleArenaFunction
	.endm

	@ Buffer the opponents name to STR_VAR_1
	.macro arena_gettrainername
	setvar VAR_0x8004, BATTLE_ARENA_FUNC_GET_TRAINER_NAME
	special CallBattleArenaFunction
	.endm


code:
	@ Initialize the Battle Dome challenge
	.macro dome_init
	setvar VAR_0x8004, BATTLE_DOME_FUNC_INIT
	special CallBattleDomeFunction
	.endm

	@ Get the value of some DOME_DATA_*. See GetDomeData for the data types that can be retrieved
	.macro dome_get data:req
	setvar VAR_0x8004, BATTLE_DOME_FUNC_GET_DATA
	setvar VAR_0x8005, \data
	special CallBattleDomeFunction
	.endm

	@ Set some DOME_DATA_* to val. See SetDomeData for the data types that can be set
	.macro dome_set data:req, val=0xFFFF
	setvar VAR_0x8004, BATTLE_DOME_FUNC_SET_DATA
	setvar VAR_0x8005, \data
	.if \val != 0xFFFF
	setvar VAR_0x8006, \val
	.endif
	special CallBattleDomeFunction
	.endm

	@ Buffer the name of the current round to gStringVar1
	.macro dome_getroundtext
	setvar VAR_0x8004, BATTLE_DOME_FUNC_GET_ROUND_TEXT
	special CallBattleDomeFunction
	.endm

	@ Buffer the name of the opponent to gStringVar2 and the name of the round to gStringVar1
	.macro dome_getopponentname
	setvar VAR_0x8004, BATTLE_DOME_FUNC_GET_OPPONENT_NAME
	special CallBattleDomeFunction
	.endm

	@ Choose which of the opponents mons to use in battle and load them into the enemy party
	.macro dome_initopponentparty
	setvar VAR_0x8004, BATTLE_DOME_FUNC_INIT_OPPONENT_PARTY
	special CallBattleDomeFunction
	.endm

	@ Show the page that gives information on the next opponent
	.macro dome_showopponentinfo
	setvar VAR_0x8004, BATTLE_DOME_FUNC_SHOW_OPPONENT_INFO
	special CallBattleDomeFunction
	.endm

	@ Displays the tourney tree for the current tourney
	.macro dome_showtourneytree
	setvar VAR_0x8004, BATTLE_DOME_FUNC_SHOW_TOURNEY_TREE
	special CallBattleDomeFunction
	.endm

	@ Displays the tourney tree for the results of the previous tourney. Before the player enters their first tourney this is a random tourney generated by dome_initresultstree
	.macro dome_showprevtourneytree
	setvar VAR_0x8004, BATTLE_DOME_FUNC_SHOW_PREV_TOURNEY_TREE
	special CallBattleDomeFunction
	.endm

	@ Sets gTrainerBattleOpponent_A to the trainer ID of the next opponent
	.macro dome_setopponent
	setvar VAR_0x8004, BATTLE_DOME_FUNC_SET_OPPONENT_ID
	special CallBattleDomeFunction
	.endm

	@ Set the object event gfx id for the opponent
	.macro dome_setopponentgfx
	setvar VAR_0x8004, BATTLE_DOME_FUNC_SET_OPPONENT_GFX
	special CallBattleDomeFunction
	.endm

	@ A non-interactive version of the tourney tree shown when a round is completed
	.macro dome_showstatictourneytree
	setvar VAR_0x8004, BATTLE_DOME_FUNC_SHOW_STATIC_TOURNEY_TREE
	special CallBattleDomeFunction
	.endm

	@ Decides the winners of NPC vs NPC matches, and eliminates either the player or their opponent depending on the playerStatus (DOME_PLAYER_*)
	.macro dome_resolvewinners playerStatus:req
	setvar VAR_0x8004, BATTLE_DOME_FUNC_RESOLVE_WINNERS
	setvar VAR_0x8005, \playerStatus
	special CallBattleDomeFunction
	.endm

	@ Save the game and set the challenge status
	.macro dome_save challengeStatus:req
	setvar VAR_0x8004, BATTLE_DOME_FUNC_SAVE
	setvar VAR_0x8005, \challengeStatus
	special CallBattleDomeFunction
	.endm

	@ Unused. Increment the win streaks for the current challenge by one
	.macro dome_incrementstreaks
	setvar VAR_0x8004, BATTLE_DOME_FUNC_INCREMENT_STREAK
	special CallBattleDomeFunction
	.endm

	@ Sets the facility trainer/mon set pointers
	.macro dome_settrainers
	setvar VAR_0x8004, BATTLE_DOME_FUNC_SET_TRAINERS
	special CallBattleDomeFunction
	.endm

	@ If any moves were copied using Sketch during the challenge then restore them to Sketch
	.macro dome_resetsketch
	setvar VAR_0x8004, BATTLE_DOME_FUNC_RESET_SKETCH
	special CallBattleDomeFunction
	.endm

	@ Reset the held items of the mons that just battled to what they were prior to battling
	.macro dome_restorehelditems
	setvar VAR_0x8004, BATTLE_DOME_FUNC_RESTORE_HELD_ITEMS
	special CallBattleDomeFunction
	.endm

	@ Reduce the players party to the selected mons, used to reduce down to the 2 selected for battle
	.macro dome_reduceparty
	setvar VAR_0x8004, BATTLE_DOME_FUNC_REDUCE_PARTY
	special CallBattleDomeFunction
	.endm

	@ Compares the initial tournament ranking (seed) of the player to opponent A. Returns 1 if the player's seed is better, 2 if the opponent's seed is better.
	.macro dome_compareseeds
	setvar VAR_0x8004, BATTLE_DOME_FUNC_COMPARE_SEEDS
	special CallBattleDomeFunction
	.endm

	@ Buffer the name of the winner for the last Dome challenge to STR_VAR_1
	.macro dome_getwinnersname
	setvar VAR_0x8004, BATTLE_DOME_FUNC_GET_WINNER_NAME
	special CallBattleDomeFunction
	.endm

	@ Performs a random tourney to initialize the results board before the player has entered a challenge
	.macro dome_initresultstree
	setvar VAR_0x8004, BATTLE_DOME_FUNC_INIT_RESULTS_TREE
	special CallBattleDomeFunction
	.endm

	@ Generates the tourney trainers and their parties, and seeds them in the tourney tree
	.macro dome_inittrainers
	setvar VAR_0x8004, BATTLE_DOME_FUNC_INIT_TRAINERS
	special CallBattleDomeFunction
	.endm


code:
	@ Initialize the Battle Factory challenge
	.macro factory_init
	setvar VAR_0x8004, BATTLE_FACTORY_FUNC_INIT
	special CallBattleFactoryFunction
	.endm

	@ Get the value of some FACTORY_DATA_*. See GetBattleFactoryData for the data types that can be retrieved
	.macro factory_get data:req
	setvar VAR_0x8004, BATTLE_FACTORY_FUNC_GET_DATA
	setvar VAR_0x8005, \data
	special CallBattleFactoryFunction
	.endm

	@ Set some FACTORY_DATA_* to val. See SetBattleFactoryData for the data types that can be set
	.macro factory_set data:req, val=0xFFFF
	setvar VAR_0x8004, BATTLE_FACTORY_FUNC_SET_DATA
	setvar VAR_0x8005, \data
	.if \val == 0xFFFF
	@ argument not provided
	.elseif \val >= VARS_START
	copyvar VAR_0x8006, \val
	.else
	setvar VAR_0x8006, \val
	.endif
	special CallBattleFactoryFunction
	.endm

	@ Save the game and set the challenge status
	.macro factory_save challengeStatus:req
	setvar VAR_0x8004, BATTLE_FACTORY_FUNC_SAVE
	setvar VAR_0x8005, \challengeStatus
	special CallBattleFactoryFunction
	.endm

	@ Select the initial rental mons for the challenge
	.macro factory_rentmons
	setvar VAR_0x8004, BATTLE_FACTORY_FUNC_SELECT_RENT_MONS
	special CallBattleFactoryFunction
	.endm

	@ Select a mon to swap for from the previously defeated team
	.macro factory_swapmons
	setvar VAR_0x8004, BATTLE_FACTORY_FUNC_SWAP_RENT_MONS
	special CallBattleFactoryFunction
	.endm

	@ Allows FACTORY_DATA_WIN_STREAK_SWAPS to be incremented once
	.macro factory_setswapped
	setvar VAR_0x8004, BATTLE_FACTORY_FUNC_SET_SWAPPED
	special CallBattleFactoryFunction
	.endm

	@ Update gEnemyParty with the next set of rental mons
	.macro factory_setopponentmons
	setvar VAR_0x8004, BATTLE_FACTORY_FUNC_SET_OPPONENT_MONS
	special CallBattleFactoryFunction
	.endm

	@ Populate gPlayerParty and gEnemyParty with the rental mons. Only needed when resuming a challenge, otherwise only factory_setopponentmons and factory_rentmons/factory_swapmons are needed
	.macro factory_setparties arg:req
	setvar VAR_0x8004, BATTLE_FACTORY_FUNC_SET_PARTIES
	setvar VAR_0x8005, \arg
	special CallBattleFactoryFunction
	.endm

	@ Set the object event gfx for the opponent trainer
	.macro factory_setopponentgfx
	setvar VAR_0x8004, BATTLE_FACTORY_FUNC_SET_OPPONENT_GFX
	special CallBattleFactoryFunction
	.endm

	@ Generate the mons for the opponents team
	.macro factory_generateopponentmons
	setvar VAR_0x8004, BATTLE_FACTORY_FUNC_GENERATE_OPPONENT_MONS
	special CallBattleFactoryFunction
	.endm

	@ Generate the random 6 mons to choose from for the initial rental
	.macro factory_generaterentalmons
	setvar VAR_0x8004, BATTLE_FACTORY_FUNC_GENERATE_RENTAL_MONS
	special CallBattleFactoryFunction
	.endm

	@ Return the pokemon type most common in the opponents team, or NUMBER_OF_MON_TYPES if there is no standout type
	.macro factory_getopponentmontype
	setvar VAR_0x8004, BATTLE_FACTORY_FUNC_GET_OPPONENT_MON_TYPE
	special CallBattleFactoryFunction
	.endm

	@ Return the FACTORY_STYLE_* dependent on what types of moves the opponents team has, or FACTORY_NUM_STYLES if multiple styles tie for the same amount of moves
	.macro factory_getopponentstyle
	setvar VAR_0x8004, BATTLE_FACTORY_FUNC_GET_OPPONENT_STYLE
	special CallBattleFactoryFunction
	.endm

	@ Restore the held items for the players party to what they were pre-battle
	.macro factory_resethelditems
	setvar VAR_0x8004, BATTLE_FACTORY_FUNC_RESET_HELD_ITEMS
	special CallBattleFactoryFunction
	.endm


code:
	@ Initialize the Battle Palace challenge
	.macro palace_init
	setvar VAR_0x8004, BATTLE_PALACE_FUNC_INIT
	special CallBattlePalaceFunction
	.endm

	@ Get the value of some PALACE_DATA_*. See GetPalaceData for the data types that can be retrieved
	.macro palace_get data:req
	setvar VAR_0x8004, BATTLE_PALACE_FUNC_GET_DATA
	setvar VAR_0x8005, \data
	special CallBattlePalaceFunction
	.endm

	@ Set some PALACE_DATA_* to val. See SetPalaceData for the data types that can be set
	.macro palace_set data:req, val:req
	setvar VAR_0x8004, BATTLE_PALACE_FUNC_SET_DATA
	setvar VAR_0x8005, \data
	setvar VAR_0x8006, \val
	special CallBattlePalaceFunction
	.endm

	@ Get the id of the comment to be made while being led through the corridor
	.macro palace_getcomment
	setvar VAR_0x8004, BATTLE_PALACE_FUNC_GET_COMMENT_ID
	special CallBattlePalaceFunction
	.endm

	@ Unused. Choose and set the opponent gfx id. The equivalent macro from Battle Tower is used instead
	.macro palace_setopponent
	setvar VAR_0x8004, BATTLE_PALACE_FUNC_SET_OPPONENT
	special CallBattlePalaceFunction
	.endm

	@ Buffer the opponents intro speech to gStringVar4. Also used by Battle Arena and Factory
	.macro palace_getopponentintro
	setvar VAR_0x8004, BATTLE_PALACE_FUNC_GET_OPPONENT_INTRO
	special CallBattlePalaceFunction
	.endm

	@ Increments the current win streak by 1
	.macro palace_incrementstreak
	setvar VAR_0x8004, BATTLE_PALACE_FUNC_INCREMENT_STREAK
	special CallBattlePalaceFunction
	.endm

	@ Save the game and set the challenge status
	.macro palace_save challengeStatus:req
	setvar VAR_0x8004, BATTLE_PALACE_FUNC_SAVE
	setvar VAR_0x8005, \challengeStatus
	special CallBattlePalaceFunction
	.endm

	@ Unused. Set the prize item to give from one of two lists of possible prizes, depending on streak.
	.macro palace_setprize
	setvar VAR_0x8004, BATTLE_PALACE_FUNC_SET_PRIZE
	special CallBattleArenaFunction
	.endm

	@ Unused. Give the set prize item to the player. TRUE if room in Bag for prize, FALSE otherwise
	.macro palace_giveprize
	setvar VAR_0x8004, BATTLE_PALACE_FUNC_GIVE_PRIZE
	special CallBattleArenaFunction
	.endm


code:
	@ Set sRoomType to the next PIKE_ROOM_* id
	.macro pike_setnextroom
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_SET_ROOM_TYPE
	special CallBattlePikeFunction
	.endm

	@ Get the value of some PIKE_DATA_*. See GetBattlePikeData for the data types that can be retrieved
	.macro pike_get data:req
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_GET_DATA
	setvar VAR_0x8005, \data
	special CallBattlePikeFunction
	.endm

	@ Set some PIKE_DATA_* to val. See SetBattlePikeData for the data types that can be set
	.macro pike_set data:req, val:req
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_SET_DATA
	setvar VAR_0x8005, \data
	.if \val >= VARS_START
	copyvar VAR_0x8006, \val
	.else
	setvar VAR_0x8006, \val
	.endif
	special CallBattlePikeFunction
	.endm

	@ TRUE if the next room is the last (15th) room, FALSE otherwise
	.macro pike_isfinalroom
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_IS_FINAL_ROOM
	special CallBattlePikeFunction
	.endm

	@ Set the object event gfx for the room being entered
	.macro pike_setroomobjects
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_SET_ROOM_OBJECTS
	special CallBattlePikeFunction
	.endm

	@ Get the current room type (sRoomType)
	.macro pike_getroomtype
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_GET_ROOM_TYPE
	special CallBattlePikeFunction
	.endm

	@ Sets a bool that's never read
	.macro pike_inwildmonroom
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_SET_IN_WILD_MON_ROOM
	special CallBattlePikeFunction
	.endm

	@ Clears a bool that's never read
	.macro pike_exitwildmonroom
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_CLEAR_IN_WILD_MON_ROOM
	special CallBattlePikeFunction
	.endm

	@ Save the game and set the challenge status
	.macro pike_save challengeStatus:req
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_SAVE
	setvar VAR_0x8005, \challengeStatus
	special CallBattlePikeFunction
	.endm

	@ Returns the PIKE_STATUS_* to be afflicted for the status room
	.macro pike_getstatus
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_GET_ROOM_STATUS
	special CallBattlePikeFunction
	.endm

	@ Returns the PIKE_STATUSMON_* that attacks the player for the status room
	.macro pike_getstatusmon
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_GET_ROOM_STATUS_MON
	special CallBattlePikeFunction
	.endm

	@ Randomly heals either one or two party mons and returns the number of mons healed
	.macro pike_healonetwomons
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_HEAL_ONE_TWO_MONS
	special CallBattlePikeFunction
	.endm

	@ Buffers a message for the lone NPC in the NPC room to gStringVar4
	.macro pike_getnpcmsg
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_BUFFER_NPC_MSG
	special CallBattlePikeFunction
	.endm

	@ Flashes the screen 3 times for when the Dusclops/Kirlia attacks the player
	.macro pike_flashscreen
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_STATUS_SCREEN_FLASH
	special CallBattlePikeFunction
	.endm

	@ TRUE if the player is currently in a Battle Pike challenge map
	.macro pike_inchallenge
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_IS_IN
	special CallBattlePikeFunction
	.endm

	@ Set which room to give a hint about. TRUE if its the Pike Queens room next
	.macro pike_sethintroom
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_SET_HINT_ROOM
	special CallBattlePikeFunction
	.endm

	@ Get PIKE_ROOM_(LEFT/CENTER/RIGHT) for which room to give a hint about
	.macro pike_gethintroomid
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_GET_HINT_ROOM_ID
	special CallBattlePikeFunction
	.endm

	@ Get the PIKE_HINT_* to give about the next room
	.macro pike_gethint
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_GET_ROOM_TYPE_HINT
	special CallBattlePikeFunction
	.endm

	@ Reset the frontier trainer ids for the start of the challenge
	.macro pike_cleartrainerids
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_CLEAR_TRAINER_IDS
	special CallBattlePikeFunction
	.endm

	@ Buffer the opponents battle intro speech to gStringVar4. \trainer 0 for Trainer A, 1 for Trainer B
	.macro pike_gettrainerintro trainer:req
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_GET_TRAINER_INTRO
	setvar VAR_0x8005, \trainer
	special CallBattlePikeFunction
	.endm

	@ Get the status of the Pike Queen (Not ready, Silver/Gold streak before symbols, Silver/Gold streak after symbols)
	.macro pike_getbrainstatus
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_GET_QUEEN_FIGHT_TYPE
	special CallBattlePikeFunction
	.endm

	@ Heal 0-2 party mons depending on which room was chosen for the Pike Queen battle. Return the number healed
	.macro pike_prequeenheal
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_HEAL_MONS_BEFORE_QUEEN
	special CallBattlePikeFunction
	.endm

	@ When \set is TRUE, prevent healing rooms from appearing (for 1st room or when party is full health). \set FALSE to re-enable healing rooms
	.macro pike_nohealing set:req
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_SET_HEAL_ROOMS_DISABLED
	setvar VAR_0x8005, \set
	special CallBattlePikeFunction
	.endm

	@ TRUE if the party is full health (full HP, PP, and no status), FALSE otherwise
	.macro pike_ispartyfullhealth
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_IS_PARTY_FULL_HEALTH
	special CallBattlePikeFunction
	.endm

	@ Save the party held items in pikeHeldItemsBackup
	.macro pike_savehelditems
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_SAVE_HELD_ITEMS
	special CallBattlePikeFunction
	.endm

	@ Restore the party held items from pikeHeldItemsBackup
	.macro pike_resethelditems
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_RESET_HELD_ITEMS
	special CallBattlePikeFunction
	.endm

	@ Initialize the Battle Pike challenge
	.macro pike_init
	setvar VAR_0x8004, BATTLE_PIKE_FUNC_INIT
	special CallBattlePikeFunction
	.endm


code:
	@ Initialize the Battle Pyramid challenge
	.macro pyramid_init
	setvar VAR_0x8004, BATTLE_PYRAMID_FUNC_INIT
	special CallBattlePyramidFunction
	.endm

	@ Get the value of some PYRAMID_DATA_*. See GetBattlePyramidData for the data types that can be retrieved
	.macro pyramid_get data:req
	setvar VAR_0x8004, BATTLE_PYRAMID_FUNC_GET_DATA
	setvar VAR_0x8005, \data
	special CallBattlePyramidFunction
	.endm

	@ Set some PYRAMID_DATA_* to val. See SetBattlePyramidData for the data types that can be set
	.macro pyramid_set data:req, val:req
	setvar VAR_0x8004, BATTLE_PYRAMID_FUNC_SET_DATA
	setvar VAR_0x8005, \data
	setvar VAR_0x8006, \val
	special CallBattlePyramidFunction
	.endm

	@ Save the game and set the challenge status
	.macro pyramid_save challengeStatus:req
	setvar VAR_0x8004, BATTLE_PYRAMID_FUNC_SAVE
	setvar VAR_0x8005, \challengeStatus
	special CallBattlePyramidFunction
	.endm

	@ Set the prize item to give from one of two lists of possible prizes, depending on streak.
	.macro pyramid_setprize
	setvar VAR_0x8004, BATTLE_PYRAMID_FUNC_SET_PRIZE
	special CallBattlePyramidFunction
	.endm

	@ Unused. Give the set prize item to the player. TRUE if room in Bag for prize, FALSE otherwise
	.macro pyramid_giveprize
	setvar VAR_0x8004, BATTLE_PYRAMID_FUNC_GIVE_PRIZE
	special CallBattlePyramidFunction
	.endm

	@ Set the random values for the floor (used to determine object positions, e.g.), and clear trainer flags
	.macro pyramid_seedfloor
	setvar VAR_0x8004, BATTLE_PYRAMID_FUNC_SEED_FLOOR
	special CallBattlePyramidFunction
	.endm

	@ Set the item to pick up depending on the random seed and quantity (always 1) to the arguments for STD_FIND_ITEM
	.macro pyramid_setitem
	setvar VAR_0x8004, BATTLE_PYRAMID_FUNC_SET_ITEM
	special CallBattlePyramidFunction
	.endm

	@ Hide the picked-up item (technically it moves the item far offscreen)
	.macro pyramid_hideitem
	setvar VAR_0x8004, BATTLE_PYRAMID_FUNC_HIDE_ITEM
	special CallBattlePyramidFunction
	.endm

	@ Set the facility trainers to gBattleFrontierTrainers
	.macro pyramid_settrainers
	setvar VAR_0x8004, BATTLE_PYRAMID_FUNC_SET_TRAINERS
	special CallBattlePyramidFunction
	.endm

	@ Show the post-battle hint text
	.macro pyramid_showhint
	setvar VAR_0x8004, BATTLE_PYRAMID_FUNC_SHOW_HINT_TEXT
	special CallBattlePyramidFunction
	.endm

	@ VAR_RESULT is 1 if player is on a Pyramid floor, 2 if on the Pyramid peak, 0 otherwise
	.macro pyramid_inchallenge
	setvar VAR_0x8004, BATTLE_PYRAMID_FUNC_IS_IN
	special CallBattlePyramidFunction
	.endm

	@ Update the light around the player. 2 different modes, for setting or incrementing light. See PYRAMID_LIGHT_*
	.macro pyramid_updatelight radius:req, mode:req, sound=0xFFFF
	setvar VAR_0x8004, BATTLE_PYRAMID_FUNC_UPDATE_LIGHT
	setvar VAR_0x8005, \radius
	setvar VAR_0x8006, \mode
	.if \sound != 0xFFFF
	setvar VAR_0x8007, \sound
	.endif
	special CallBattlePyramidFunction
	.endm

	@ Reset the held items to what they were at the start of the challenge
	.macro pyramid_clearhelditems
	setvar VAR_0x8004, BATTLE_PYRAMID_FUNC_CLEAR_HELD_ITEMS
	special CallBattlePyramidFunction
	.endm

	@ Set the palette depending on current floor number
	.macro pyramid_setfloorpal
	setvar VAR_0x8004, BATTLE_PYRAMID_FUNC_SET_FLOOR_PALETTE
	special CallBattlePyramidFunction
	.endm

	@ Reset sketched moves and update the party order in the saveblock
	.macro pyramid_resetparty
	setvar VAR_0x8004, BATTLE_PYRAMID_FUNC_RESTORE_PARTY
	special CallBattlePyramidFunction
	.endm


code:
	@ Initialize the Battle Tower challenge
	.macro tower_init
	setvar VAR_0x8004, BATTLE_TOWER_FUNC_INIT
	special CallBattleTowerFunc
	.endm

	@ Get the value of some TOWER_DATA_*. See GetTowerData for the data types that can be retrieved
	.macro tower_get data:req
	setvar VAR_0x8004, BATTLE_TOWER_FUNC_GET_DATA
	setvar VAR_0x8005, \data
	special CallBattleTowerFunc
	.endm

	@ Set some TOWER_DATA_* to val. See SetTowerData for the data types that can be set
	.macro tower_set data:req, val=0xFFFF
	setvar VAR_0x8004, BATTLE_TOWER_FUNC_SET_DATA
	setvar VAR_0x8005, \data
	.if \val != 0xFFFF
	setvar VAR_0x8006, \val
	.endif
	special CallBattleTowerFunc
	.endm

	@ Choose and set the gfx for the next opponent. Also used by Battle Tents
	.macro tower_setopponent
	setvar VAR_0x8004, BATTLE_TOWER_FUNC_SET_OPPONENT
	special CallBattleTowerFunc
	.endm

	@ Increments the battle number and returns the new one. Also clears E-Reader trainer if defeated, and saves the current win streak
	.macro tower_setbattlewon
	setvar VAR_0x8004, BATTLE_TOWER_FUNC_SET_BATTLE_WON
	special CallBattleTowerFunc
	.endm

	@ Try to award ribbons for completing 56th straight Battle Tower win. VAR_RESULT is TRUE if ribbons were awarded.
	.macro tower_giveribbons
	setvar VAR_0x8004, BATTLE_TOWER_FUNC_GIVE_RIBBONS
	special CallBattleTowerFunc
	.endm

	@ Save the game and set the challenge status
	.macro tower_save challengeStatus:req
	setvar VAR_0x8004, BATTLE_TOWER_FUNC_SAVE
	setvar VAR_0x8005, \challengeStatus
	special CallBattleTowerFunc
	.endm

	@ Buffer the opponent's easy chat intro speech to STR_VAR_4
	.macro tower_getopponentintro opponent:req
	setvar VAR_0x8004, BATTLE_TOWER_FUNC_GET_OPPONENT_INTRO
	setvar VAR_0x8005, \opponent
	special CallBattleTowerFunc
	.endm

	@ Load the parties, gfx, and other data (like Apprentice id) for the multi partner candidates
	.macro tower_loadpartners
	setvar VAR_0x8004, BATTLE_TOWER_FUNC_LOAD_PARTNERS
	special CallBattleTowerFunc
	.endm

	@ Print message from potential multi partner. msgId is any PARTNER_MSGID_*
	.macro tower_dopartnermsg msgId:req
	setvar VAR_0x8004, BATTLE_TOWER_FUNC_PARTNER_MSG
	setvar VAR_0x8005, \msgId
	special CallBattleTowerFunc
	.endm

	@ Receives/loads the opponent data for a link multi challenge. Returns 6 when finished, and finishes immediately if not doing a link multi battle.
	.macro tower_loadlinkopponents
	setvar VAR_0x8004, BATTLE_TOWER_FUNC_LOAD_LINK_OPPONENTS
	special CallBattleTowerFunc
	.endm

	@ Attempts to close link connection. Used when finishing a link multi challenge.
	.macro tower_closelink
	setvar VAR_0x8004, BATTLE_TOWER_FUNC_TRY_CLOSE_LINK
	special CallBattleTowerFunc
	.endm

	@ Set VAR_OBJ_GFX_ID_E to the gfx id of the selected multi partner
	.macro tower_setpartnergfx
	setvar VAR_0x8004, BATTLE_TOWER_FUNC_SET_PARTNER_GFX
	special CallBattleTowerFunc
	.endm

	@ Set the data used for the post-challenge Battle Tower interview
	.macro tower_setinterviewdata
	setvar VAR_0x8004, BATTLE_TOWER_FUNC_SET_INTERVIEW_DATA
	special CallBattleTowerFunc
	.endm


code:
	@ Get the status (CHALLENGE_STATUS_*) of the current challenge and store the result in VAR_TEMP_0
	.macro frontier_getstatus
	setvar VAR_0x8004, FRONTIER_UTIL_FUNC_GET_STATUS
	special CallFrontierUtilFunc
	.endm

	@ Get the value of some FRONTIER_DATA_*. See GetFrontierData for the data types that can be retrieved
	.macro frontier_get data:req
	setvar VAR_0x8004, FRONTIER_UTIL_FUNC_GET_DATA
	setvar VAR_0x8005, \data
	special CallFrontierUtilFunc
	.endm

	@ Set the value of some FRONTIER_DATA_*. Some data types do not need a val argument because the value is set directly from somewhere else. See SetFrontierData for the data types that can be set
	.macro frontier_set data:req, val=0xFFFF
	setvar VAR_0x8004, FRONTIER_UTIL_FUNC_SET_DATA
	setvar VAR_0x8005, \data
	.if \val == 0xFFFF
	@ no value provided
	.elseif \val >= VARS_START
	copyvar VAR_0x8006, \val
	.else
	setvar VAR_0x8006, \val
	.endif
	special CallFrontierUtilFunc
	.endm

	@ Load the selected mons into gSelectedOrderFromParty and reduce the players party to these mons
	.macro frontier_setpartyorder partySize:req
	setvar VAR_0x8004, FRONTIER_UTIL_FUNC_SET_PARTY_ORDER
	setvar VAR_0x8005, \partySize
	special CallFrontierUtilFunc
	.endm

	@ Performs a soft reset
	.macro frontier_reset
	setvar VAR_0x8004, FRONTIER_UTIL_FUNC_SOFT_RESET
	special CallFrontierUtilFunc
	.endm

	@ Loads gBattleFrontierTrainers into gFacilityTrainers
	.macro frontier_settrainers
	setvar VAR_0x8004, FRONTIER_UTIL_FUNC_SET_TRAINERS
	special CallFrontierUtilFunc
	.endm

	@ Sets the selected party mons in the saveblock
	.macro frontier_saveparty
	setvar VAR_0x8004, FRONTIER_UTIL_FUNC_SAVE_PARTY
	special CallFrontierUtilFunc
	.endm

	@ Shows the results window for the given facility and mode. Facilities with only 1 mode dont provide the mode argument
	.macro frontier_results facility:req, mode=0xFF
	setvar VAR_0x8004, FRONTIER_UTIL_FUNC_RESULTS_WINDOW
	setvar VAR_0x8005, \facility
	.if \mode != 0xFF
	setvar VAR_0x8006, \mode
	.endif
	special CallFrontierUtilFunc
	.endm

	@ Checks if the Battle Frontier TV special should air, and if so attempts to set it up
	.macro frontier_checkairshow
	setvar VAR_0x8004, FRONTIER_UTIL_FUNC_CHECK_AIR_TV_SHOW
	special CallFrontierUtilFunc
	.endm

	@ Get the status of the Frontier Brain (Not ready, Silver/Gold streak before symbols, Silver/Gold streak after symbols)
	.macro frontier_getbrainstatus
	setvar VAR_0x8004, FRONTIER_UTIL_FUNC_GET_BRAIN_STATUS
	special CallFrontierUtilFunc
	.endm

	@ TRUE if the opponent is a Frontier Brain, FALSE otherwise
	.macro frontier_isbrain
	setvar VAR_0x8004, FRONTIER_UTIL_FUNC_IS_BRAIN
	special CallFrontierUtilFunc
	.endm

	@ Awards battle points depending on the current challenge
	.macro frontier_givepoints
	setvar VAR_0x8004, FRONTIER_UTIL_FUNC_GIVE_BATTLE_POINTS
	special CallFrontierUtilFunc
	.endm

	@ Returns 0-2 for the number of facility symbols the player has
	.macro frontier_getsymbols
	setvar VAR_0x8004, FRONTIER_UTIL_FUNC_GET_FACILITY_SYMBOLS
	special CallFrontierUtilFunc
	.endm

	@ Awards a frontier symbol depending on the current challenge
	.macro frontier_givesymbol
	setvar VAR_0x8004, FRONTIER_UTIL_FUNC_GIVE_FACILITY_SYMBOL
	special CallFrontierUtilFunc
	.endm

	@ TRUE if the given battleType is set in gBattleTypeFlags, FALSE otherwise
	.macro frontier_isbattletype battleType:req
	setvar VAR_0x8004, FRONTIER_UTIL_FUNC_CHECK_BATTLE_TYPE
	setvar VAR_0x8005, \battleType
	special CallFrontierUtilFunc
	.endm

	@ TRUE if there are insufficient eligible party mons to participate in the challenge, and buffers caught ineligible species to STR_VAR_1. FALSE otherwise. The return value is stored in VAR_0x8004 instead, and the current level mode is expected to be in VAR_RESULT
	.macro frontier_checkineligible
	setvar VAR_0x8004, FRONTIER_UTIL_FUNC_CHECK_INELIGIBLE
	special CallFrontierUtilFunc
	.endm

	@ Validates the visiting E-Reader trainer. 0 if valid, 1 if not
	.macro frontier_checkvisittrainer
	setvar VAR_0x8004, FRONTIER_UTIL_FUNC_CHECK_VISIT_TRAINER
	special CallFrontierUtilFunc
	.endm

	@ Increments the current win streak by 1
	.macro frontier_incrementstreak
	setvar VAR_0x8004, FRONTIER_UTIL_FUNC_INCREMENT_STREAK
	special CallFrontierUtilFunc
	.endm

	@ Resets the party held items to what they were upon entering the challenge
	.macro frontier_restorehelditems
	setvar VAR_0x8004, FRONTIER_UTIL_FUNC_RESTORE_HELD_ITEMS
	special CallFrontierUtilFunc
	.endm

	@ Move the recorded battle to save data
	.macro frontier_savebattle
	setvar VAR_0x8004, FRONTIER_UTIL_FUNC_SAVE_BATTLE
	special CallFrontierUtilFunc
	.endm

	@ Buffer the name of gTrainerBattleOpponent_A in STR_VAR_1 (0) or STR_VAR_2 (1)
	.macro frontier_gettrainername stringVar:req
	setvar VAR_0x8004, FRONTIER_UTIL_FUNC_BUFFER_TRAINER_NAME
	setvar VAR_0x8005, \stringVar
	special CallFrontierUtilFunc
	.endm

	@ If any moves were copied using Sketch during the challenge then restore them to Sketch
	.macro frontier_resetsketch
	setvar VAR_0x8004, FRONTIER_UTIL_FUNC_RESET_SKETCH_MOVES
	special CallFrontierUtilFunc
	.endm

	@ Set the object event gfx of the Frontier Brain for the current facility
	.macro frontier_setbrainobj
	setvar VAR_0x8004, FRONTIER_UTIL_FUNC_SET_BRAIN_OBJECT
	special CallFrontierUtilFunc
	.endm