Sign Up connects you to ROM Hackers around the world.
Search all tutorials.
Induction To Pokémon Scripting Pt.1

Induction To Pokémon Scripting Pt.1

Posted By: On August 19, 2012
Comments: 2
Views: 22722
5 Ratings

Welcome to another part of the Complete ROM Hacking Guide. Today we will be looking at an introduction to Scripting. Hopefully you've been reading the rest of the guides and have found this one because you want to learn how to Script. Before reading further I suggest if you haven't already to read the Introduction To ROM Hacking guide. This will give you a good overview of what ROM Hacking is all about and how to get started. I also suggest reading the range of my available Mapping Guides, to give you an overview of mapping and using Advance Map. So without further ado, let's get going with scripting.

There are a lot of Scripting guides available out there which details all the available commands you can use. What they don't always do is tell you what's going on, why or how something works, or even how to compile a script. They simply contain a huge list of commands with example scripts of what they do. In short I don't feel they teach the fundamentals of scripting very well. If you know exactly what a script is, how it works and what you can do with it you will be able to scope out your hacks events very easily.

Throughout this Scripting Guide and all the following parts, I'll be detailing how to make good scripts and provide a full reference of what each command will do. With scripting it's simply understanding the fundamentals and then adding the commands you want to use. But before we go on we should know what a "script" actually is.

Scripts & The Pokémon Engine
When you make a Game Engine it's important to think of the key things it will do in the game. What will be the most common things that happen throughout the game. The amount of code required to display a piece of text on the screen is a lot, and would be very time consuming to write the code for every piece of text to show. GameFreak realised this and they created a number of surface engines to control the Core Game engine of the Pokémon Games. Scripting is one of them, and allows long and complex tasks to be accomplished very quickly.

In the first guide, Introduction To ROM Hacking I mentioned about how the Pokémon Engine worked in terms of surface level hacking aspects. Well Scripting is also another form of surface level hacking aspects which has a very close relationship with the Pokémon Engine itself. Before I can explain what this relationship is you need to understand how major functions of the engine work.

Scripting in the Pokémon engine is designed so that the engine can be easily controlled using a set of functions. The Pokémon engine was designed so that it contains all the core functions, and then has other engines which sit on top of it to do the controlling. Let's look at an analogy.

Imagine you are the boss of a huge organisation. Your organisation currently employees over 1 million people to do various jobs around the different departments. You as the boss, decide we need a new magazine series. This command gets issued to the media department. Then, someone working in the media department says "I want a logo to be printed 40 times onto the front of this magazine", what happens within the organisation? There would be a printing department, a quality control department, an art department and all sorts. To start with the *boss issued the initial request to the media department, which gets passed onto the art department. They then design a logo for the magazine and have a draft version created. They pass this onto the quality control department which checks if the logo is good enough and up to the company standards. Once it is, it gets sent over to the printing department. After it's printed it get's sent out to customers and there we have it. But what does this have to do with Scripting at all?

Functions & The Scripting Engine
Well it's a hard analogy to figure out so I'll explain. When you create a script you tell the Scripting engine what you want to do exactly. You write down exactly a set of instructions and specifics and give it directly to the Scripting engine. Once this is done the scripting engine will read those instructions and pass them on to the Core Pokémon Engine to do the real work that's involved. What kind of real work? The processing of data, the moving and sorting of different parts of data, the memory and control operations that take place and all the "under the hood" operations that we as Scripters don't necessarily have to perform. Once the Core Engine finishes processing the commands, it issues back to the Scripting Engine that it's finished. Then things go on and on like this. In the long run every scripting command that we will give to the engine is a "shortcut" to perform many complex tasks which are very commonly needed throughout a Pokémon game. But wait a second, what is a Scripting Command?

Scripting Commands
The Scripting engine has a bunch of functions we can use, and these are the commands themselves. Understanding the concept of a command is simple. If someone instructs you to do something by saying "Walk down the road for 2 miles" then you will do it. You know what that means as it's a language we as humans understand. Well, the reason we need to have Scripting commands is because computers don't understand human spoken language. They are logical machines and only operate in a logical way, hence they take direct instructions and orders. Scripting commands are in itself a language which I like to call PokéScript.

So hopefully you have an idea of how the Scripting engine works with the Pokémon Engine. Rather than making this into a huge passage about Scripting commands, let's actually make our first ever script and you can see some Scripting commands in action. This will allow you to gain first hand how a script works.

Our First Script
So the time has come! Most of the talking is over and we are going to begin by making a Script! But first you will need some things. Throughout this guide we will be using Advance Map + XSE to do all our Scripting stuff. Luckily Advance Map allows you to open any script from an event right in XSE from within Advance Map. But before you can do this they need to be linked together. Open up PGE and proceed to download Advance Map 1.92 and XSE. XSE stands for eXtreme Script Editor, and is the preferred Scripting Development Environment for creating scripts for your Pokémon Hacks. Once both apps have downloaded, proceed to open Advance Map. You will need to go to the Settings menu -> Choose Script Editor.

From here you will need to browse to the PGE folder inside the Program Files folder and find the XSE.exe file. This will allow you to choose your Script Editor as XSE. When prompted by Advance Map about offsets, select Yes. You have now linked Advance Map and XSE together.

Viewing Scripts In XSE Using Advance Map
As mentioned above this is a neat feature of Advance Map which allows you to view any script from a hack which is linked to an event. For now open up a clean FireRed ROM in Advance Map and proceed to Pallet Town. If you don't know how to do this, refer to the Mapping guide part 1. Once on Pallet Town switch to the Events tab to view all the events for this map.

This is what the Events view will look like for Pallet Town. For a more in-depth look at the the Event view read Mapping Guide Part 2. For now, we want to simply double click on the fat guy on the bottom right of the map. This will open XSE, auto open the ROM that's in Advance Map and load up the script for the fat guy. This is the quickest way to open your ROM in XSE, and doesn't require you to open XSE at all as Advance Map does all the work. Simply Double Click on any Person, Signpost or Script tile to open it's Script in XSE.

Welcome To XSE!
Below we have the main XSE interface screen which shows everything we will need to use today.

Let's look at each individual part of the interface giving a rough overview of what each area and option does.

In the Red area we have is the main Script Editor area. This is where your script and any script we view will go. On the left we have the line number for the script.

In the blue area we have a small Notepad which lets you save notes for any purpose.

In the orange area is a useful calculator which sports the standard functions as well as converting from Hex to Decimal, which is very useful while scripting.

Finally we have the Toolbar which shows the main tools that come with XSE. On the very left of the Toolbar we have the address of the ROM that is currently opened. Next to this is the Open button allowing you to open either another ROM or another script. The Save button will let you save the current script to a file for future reference. In the next section we have the Compile button which is the most important button in XSE. It allows you to write the script to the ROM. We then have the Debug button which will check your Script by doing a "fake" compile to make sure no errors exist. XSE has the option to show a log after compiling and debugging a script. Having the Show Log button ticked is recommended seeing as it contains some really useful features which we will cover later on.

Finally on the next section we have the Offset of the decompiled script. What we did when we "viewed" and existing script is we decompiled it. More on decompiling later. The button next to this offset is the decompile button which will simply reload the script at that given offset. The final button allows you to tick whether the script that's being decompiled or created is a Level script or not. We will cover these scripts at a later date as well.

So let's start editing this script we have in view.... Heh It's not that easy! This script is a compiled script and shouldn't be edited blindly! We have to create a brand new script for us to use. Why can't we simply edit an already compiled script? It's due to the size of this script and it's position in the ROM. Making this script larger in size would overwrite important data and other parts of another script because the new script would be larger than the allocated size of a script. For now we will be making a new script from scratch, so remove this script from view.

Deleting The Current Script From View
In the current XSE view we have the script for the fat guy in Pallet Town. Well for now, we don't want to look at this script as looking at decompiled scripts first makes things much more confusing for us. For now, simply delete the whole script by using Crtl + A to select it all and then backspace to delete it. This gives us a fresh view where we can start to make a brand new script.

Script Structures
Every script you create will have a basic structure such as the following:

Starts with an offset, then you write the commands you want and then end it. Offset? What is that?

In order to understand Offsets you need to understand the data structures used within a Pokémon GBA ROM. Because this is ROM Hacking we are editing a compiled piece of code which means everything is put into place. Everything has it's own "position" in the ROMs Data Structure. The GBA has limited space in the ROM so everything is built up next to each other to save as much space as possible.

Within computing, the engine needs to know where it can find the data it needs to process, and this is done by giving it a direct position. Think of an Offset like an Address the ROM as a large block of flats. Each flat has it's own number and we know the people that live in Flat 56, or Flat 33. The same is said for this data structure. Each Address or Offset points to that position in the ROM. Doesn't make sense? Well all you need to know is, all of the core engine processes of the Pokémon Engine, and all computers in general are programmed to read from the beginning of a data structure which starts at 0, and then an additional amount. This additional amount is called the Offset, as it Offsets the position to something else.

Offsets might be a new thing for you right now, but to save going into huge detail you should check out this article on Wikipedia about Offsets. For now in a nutshell: every piece of data has a position that it's stored inside the ROM. You will learn to use Offsets a lot later on because we will be working with them all the time, seeing as all ROM Hacking is based on the size of a piece of data and it's Offset.

Script Offsets & Compilers
So you should have learnt the basics of what an Offset is now, so we can start talking about compilers. All scripts need to be compiled into a language which the ROM can understand. When we hear our language such as "How are you?", our brain will translate and compile this into an instruction that we understand. This happens completely on an unconscious level but the result is, we would respond with "I'm fine thanks, and you?" Or somewhere along those lines. The point you need to understand is, we as human beings know this stuff already, but the computer only knows what you tell it. The compilers job is to convert the script into the language the ROM understands, and place it at the correct Offset. That's basically all the compiler will do.

Know that we know we have to compile our scripts, we need to know how to make sure the compiler uses the correct Offset. We can do this using XSE very easily by using a Compiler Directive.

Compiler Directives
A compiler itself is a tool used by Programmers to make their programs run on a given system. It is also used by us scripters to compile our scripts into the GBA. Well, it also has some "options" that can be triggered while you compile the script. These are called Compiler Directives and allow you to take control of some aspects of the compilers behaviour. The main scope of a compiler is to put your script into the ROM. Let's look at 2 of the most used Compiler Directives which you will be using ALL the time.

Every Compiler Directive starts with an # symbol which is part of telling the compiler that it's a Compiler Directive and not a command.

I mentioned earlier that every script has a structure starting with the Offset of the script. This offset is the first line and is declared using the Compiler Directive #org. #org is used to place the script at the given Offset in the rom. So for example...

#org 0x100000

This piece of script will place the commands which follows it at the Offset 0x100000. I should also mention that when dealing with Offsets in a GBA ROM, they are mainly done in Hexadecimal which is a different kind of numbering system to Decimal.

Hexadecimal VS Decimal
Decimal is a numbering system which has a range of 0-9. From this we can create numbers like 54, 472822 and 4892912728. Any number inside this number will never be anything different than 0,1,2,3,4,5,6,7,8 or 9.

Hexadecimal is a numbering system which has a range of 0-F. This is 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F. Might seem a bit stupid so far if you are not used to working in Hexadecimal but after a while it will click. The base numbering system of all computers is based around numbering systems that have 2,8,16 and 32 different numbers in their range. For now though, whenever I prefix a number with 0x it means it is a Hexadecimal number. This is the same for other numbers you see prefixed with 0x.

Heres a small tip: you should never need to think about an Offset in anything other than Hexadecimal.

Now that you know about Hex Offsets, we can start to progress with our script. So the Offset I decided to use is 0x100000, but I need to think of something first. This is a brand new script I'm creating which I intend to place into the ROM. But, how do I know that the position at 0x100000 is free and available to use? If this was someones Flat, I couldn't just move in and start replacing them and their stuff! That's where Free Space comes in.

Data Sizes & Free Space
Free Space is a position in the ROM which is not used or referenced by any other part of the ROM. This means it can be used without causing damage or overwriting some important data. It's extremely important to consider while scripting that ever command you make takes up some space in the ROM, and that data is already placed throughout the ROMs. In the old days of Scripting when XSE didn't exist, we needed to calculate the size of our scripts and then find an available Offset which has enough space. Scripts are also stored in Blocks in full. This means that you can't have 1 piece of a single script scattered throughout the ROM. What you can do however, is have multiple script blocks which reference each other throughout the ROM. We will be looking at this later. For now, we can be happy that XSE introduced us to a new tool; dynamic offsets.

Dynamic Offsets
When dealing with huge scripts which have multiple parts and all sorts of other data to go with them, it gets harder to maintain. That's why we now have Dynamic Offsets which do a number of things to benefit us as scripters.

1. Dynamically assigns the script to Free Space. This means that when using the right Compiler Directive, your script's data gets placed at the nearest convenient free space in the ROM. This means that unless you want to manage every piece of data in your ROM Hack you don't need to worry about finding Free Space for new scripts.

2. Naming script blocks. This lets you assign a name to a script clock such as "displayText" or "giveMasterBall". These names will be present in the uncompiled script and help greatly in the management and building of your script. It also means you don't have to deal with Hexadecimal Offsets all the time to create your scripts.

The Compiler Directive for this is #dynamic 0xstartoffset. The start Offset is where the compiler will begin to search from. On a default FireRed ROM, it's safe to start searching from 0x800000 to leave plenty of free space. So let's combine this with our previous script and add a dynamic name.

#dynamic 0x800000
#org @begin

Every dynamic name we create for our script should begin with the @ symbol. This tells the compiler that it needs to assign this dynamic name an Offset when it compiles. Pretty simple, right? So we have setup a Dynamic offset to search from, and then given the beginning of our script the name "begin". Time to create our first working script!

Creating A Script Line by Line
We will be creating our own simple "Hello World!" script which, once finished will make the fat guy say "Hello World!". First off let's begin by adding our first 2 lines. You should get in the habit of adding them both into every script you create.

#dynamic 0x800000
#org @begin

Next up, we need to have some kind of message display on the screen. Have a guess at the command we need for that.

The command we will be using is message, and I made a nice box to give the data. From now on every new command I introduce will be presented in this box. Then I'll elaborate on each part below it like this. So as you can see the name is message, but also can be used as msgbox. It will display a text box with the given text. The text is given in Offset form, so we will need to create that text later. This is where we get onto something a bit new; parameters.


A parameter is something that goes hand in hand with all scripting commands, and allows these commands to be executed in different ways. Seeing as the scripting engine was designed to be able to be used in as many ways as possible it features a parameter system. A parameter is similar to a Compiler Directive in terms that its used to control how the function operates. In fact, the script will not even compile without the correct parameters in use.

In the case of the message function, it takes only 2 parameters. This is the way we give the data to the message function so it knows what to display and how. The first parameter given is the text Offset. This is a piece of text that will be stored somewhere in the ROM. the second parameter is the text box type to display it as. There are various text box types which can be used, but for now we will stick with the msg_face option, which makes an Overworld Sprite face the player upon displaying this text. This should be used for every script which is given to an OW sprite.

So let's update our script.

#dynamic 0x800000
#org @begin
messsage @hello msg_face

Now we have the new line of code added to our script, but it needs something extra.Notice how we assigned the Offset for the text to be dynamic. We need to create a new script block using the #org directive. So, have a guess at what it would look like. Apply your knowledge from above to create the start of the new block for our text.

#org @hello

Just like our *"begin" block this one is structure in the same way. The only difference is that this is text and not a script. So how do we structure a text block? It's simple.

Just start with the dynamic offset using the #org directive, and then on the following line ad an=The text goes here. So it would look like below.

#org @hello
= The *text goes here

Simple, huh? I hope you have been able to follow this far in as scripting is considered one of the harder aspects of hacking. As long as you understand that this is how we create a text block for our script, then let's add this block into our script like below, with the correct text though.

#dynamic 0x800000
#org @begin
messsage @hello msg_face

#org @hello
= Hello World!

Our script is almost finished, but first you might of noticed I left a space in-between the 2 blocks. This is because these are separate blocks and need to be kept separate for the compiler to understand this. It also helps you as a scripter to be able to read your scripts easily.

So, there is one final touch needed to this script before we can actually compile it and test it in our ROM. Is that true? But we have our commands for displaying a message, and we added the needed text as well. So what could be missing? Lets look back at our scripting structure to see whats missing.

Well, we have our Offset created for the main script and the text, we have our commands for displaying the message, but we don't have anything that is visible to the compiler that we want to end this script now. Remember I said that computers only do what you tell them. The compiler can't assume you want to end this script here, so we have to tell it to end it by using a new but very simple command.

This is an extremely simple command and tells the script to end now. That's all there is too it. So, add it to the script we have made so far like so.

#dynamic 0x800000
#org @begin
messsage @hello msg_face

#org @hello
= Hello World!

There we have it! This is our completed Hello World! script ready to be compiled into the ROM. So feel free to copy and paste this into your XSE window, or do the preferred method and write it out line by line from memory or by looking. This will help your brain to learn scripting without needing to check on all the commands. Your XSE window should resemble something like below.

So, with this we are ready to compile the script and insert it into the ROM! But before we jump the gun, it's good to make sure we have no errors. To do this we need to make use of the Debug feature built into XSE.

Physical Debugging
Debugging is a massively helpful tool which automatically checks all the syntax of your code to make sure you haven't made any typing errors. Syntax is the requirement of how you write and layout your scripts and code. If you have a syntax error in a script which has 1000+ lines, you would be in a bad position without the Debugger.

The Debugger in XSE will simply and only check the spelling and layout of your commands. It will not check that the script 'works' like it should do. In the future you will be making some scripts which can contain some rather complex logic. The Compiler will not be able to check this logic, only the syntax and spelling of your scripts. Keep this in mind when you come across a logical error.

For now, press the Debug button to check the spelling and layout of your script.

Uh oh! My script has a syntax error somewhere! You will see that the error is very helpful and will tell me that there is an unknown keyword "messsage" at line 3. This means I can go straight to line 3 and will immediately know what the problem is and can fix it. I misspelt message with 3 s!

Now that I've corrected that I'll run the Debugger again to make sure.

Here we go. Remember the Toolbar option for "Show Log"? Well this is the compiler log, one of the most useful features of the XSE compiler. Right now it looks like we compiled the script and its successfully gone into the ROM. The only thing to tell it part is the ROM path will lead to a Debug Test rom instead of our real ROM. Well because this was just a debug, it is showing the debugger output which would show once it's been compiled. It lists lots of information about the script which we don't need to be concerned with right now. We can close this window since it was only a Debug test. Keep in mind that, if you forget to debug then when you press the Compile button, it will also do a syntax debug for you as well. It's just more safer to do the debug only before compiling.

That's what I call a "Physical" debug as it will debug simply what you see and what the compiler sees. No logic involved at all. This is where we do a Logical Debug, something I like to do when creating complex scripts.

Logical Debugging
As I mentioned earlier, the compiler has no idea what you are trying to create in your script. It just sees the commands you are using and makes sure they are correct and have no spelling errors or missing parameters. Logical Debugging requires you to know what your script is supposed to do. If you know what its supposed to do then you can follow through it executing the script in your head. This will require that you know what each command is going to do and how each command will behave with the given parameters. You will learn to do this in time and will have to resort to logical debugging when you come across a script which "won't work".

As this script is simple we don't need to logically debug it, It's just important that you know about Logical Debugging and keep it in mind for the future.

Compiling Our script!
Yep! It's finally that time where we compile our first script and insert it into the ROM! So using the guide of the Toolbar further up, click the compile button. You will be greeted with the compile log to say our script has been successfully been compiled.

There we go. This time the ROM path leads to the real ROM we are using. The script has now been compiled. But don't close this window yet! The most important and useful feature of XSE is the ability to show the list of Dynamic Offsets which it used to compile too. It will list them at the bottom of the log, and even give you the option to copy the offset into your clipboard for easy pasting later. It's very important that you take note of these Offsets otherwise you will lose the position of this script in the ROM if you don't take note of the main scripts offset. In this case it's easy to remember but when you get to offsets such as 0xAB57F1 it might be harder to remember this one. In this case our main script is @begin, so highlight that in the list and press the copy button.

The compiler log can now safely be closed. That's it for the XSE part of this script. It's time to move over to Advance Map again.

Giving The Fat Guy Our Script
So, load up Advance Map once more and make your way to the main Pallet Town map again.

Make sure the fat guy is selected and scroll down the Event options pane on the right to find the Script Offset field. You can guess it, this is the Offset of the script we just created. Thanks to XSE this should be copied into our clipboard. Simply highlight it and replace it with our new Offset.

Once done, save the map and load it up in the emulator.

There we have it! Our new script in action and working in the ROM!

I hope you enjoyed this short introduction to Scripting. The future parts will be containing some much more useful and advanced commands and things you can do with scripts!

From now and the time of the next part to the guide, why not enter the Monthly Scripting Contest and try your hand at an advanced script? Why not look at the Command list in XSE and see if you can learn some new commands and use them?

Until then, good luck and I hope you enjoy Scripting!

This is brilliant! Are you posting a part 2 anytime soon?
This is a great tutorial about scriptingSmile
You did great work on this scripting tutorialSmile