• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • Forum moderator applications are now open! Click here for details.
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

Research: Battle Scripts

JPAN

pokemon rom researcher
104
Posts
15
Years
  • Seen Jul 2, 2016
While researching abilities, I came across something peculiar. In some abilities, a pointer to a ROM area (usually around x1d0000) was loaded, but no runnable code was present. Also, it appeared that some pointers were present, but were unaligned and as such nearly useless for referencing. The structure of that data was somewhat familiar. At first, I thought they were strings, then random data. But it looked too much like a script, although it made no sense as a regular script. So, I decided to follow up on that data.

In fact, that data was indeed a script, but not a regular one. This script was a special kind, run by a separate code, similar in much to the regular script one. Code replication was not on gamefreak's mind, as four similar routines pop up on the code (as far as I've found them). One such example is the routine at 0x08015c74
Code:
ROM:08015C74 battle_script_call                      ; DATA XREF: ROM:off_801BC64o
ROM:08015C74                 PUSH    {LR}
ROM:08015C76                 LDR     R0, =0x2023BC8
ROM:08015C78                 LDR     R0, [R0]
ROM:08015C7A                 CMP     R0, #0
ROM:08015C7C                 BNE     loc_8015C90
ROM:08015C7E                 LDR     R1, =battle_script_commands
ROM:08015C80                 LDR     R0, =0x2023D74
ROM:08015C82                 LDR     R0, [R0]
ROM:08015C84                 LDRB    R0, [R0]
ROM:08015C86                 LSL     R0, R0, #2
ROM:08015C88                 ADD     R0, R0, R1
ROM:08015C8A                 LDR     R0, [R0]
ROM:08015C8C                 BL      sub_81E3BA8   ;simple bx r0
ROM:08015C90
ROM:08015C90 loc_8015C90                             ; CODE XREF: ROM:08015C7Cj
ROM:08015C90                 POP     {R0}
ROM:08015C92                 BX      R0
Where battle_script_commands is the location 0x0825011C where all commands are located. As far as I know, there are 248 different commands (0x00 to 0xf7) available, but I've only just started studying them. so far, it seems that basic operations are included (add, sub, mov), but some more complex (and battle related) are as well.
I will "decompile" the script for the rainy weather effect for you here, by dividing it in sections. That script is located at 0x081d927f
Code:
39 20 00 or 39 0020
10 c1 00 or 10 00c1
3a
45 07 0a 00 00 00 00 or 45 07 0a 00000000
41 dc 92 1d 08 or 41 081d92dc
3f
 
and at 081d92dc
2e db 3f 02 02 00 or 2e 02023fdb 00
e7
2f db 3f 02 02 01 or 2f 02023fdb 01
2d db 3f 02 02 cc 3b 02 02 01 e2 92 1d 08 or 2d 02023fdb 02023bcc 01 081d92e2
3c
Now, this is just a bunch of numbers, so to make sense of it, here's it spelled out:
Code:
pause 0x20  (only calls itself 20 times, doing nothing else)
 
printString 0xc1 (prints the battle message. sets the value to be print and stores a byte to tell that something needs to be print. Waits until no more characters are written on the screen to continue)
 
nop
 
battleAnimation 0x7 0xa 0x0 (displays a certain battle animation, but a limited set of them. 0xa is the raindrop screen. 0x7 is a check, but I don't know of what. 0x0 is an address to be used for checking a byte, but I don't know what for yet)
 
call 081d92dc (calls the other script for execution)
 
exit (or not quite. see end of post)
 
------------------------------------------------------
 
setbyte 0x02023fdb 0x0 (sets the value at that specific address to 0)
 
checkform (a specific check that verifies the (cast)form of the pokemon involved.)
 
add 0x02023fdb 0x1 (adds the given byte (0x1) to the contents of the given address)
 
if (0x02023fdb 0x02023bcc) equal to 0x1 goto 0x081d92e2 (this conditional branch checks 0x1 bytes starting at each position are totaly equal. if not, jump to given address)
 
return (simply return from the function)

If you want to know what are the printing strings in the command, go to 0x3fdf3c and check position (number - 0xc) of that table. 0x0 to 0xc are reserved to display buffers (like your pokemon name, an attack name or a trainer name)
For the battle print address, note that this is one of (possibly) several graphical functions, so it offers little content. some will crash if tried.
Code:
01, nothing
02, disappear and pokemon enter (possibly substitute removal)
03, create substitute
04 turns you into a pokeblock, crash
05 knock off item
06 warp
07 berry item heal
08 disappearing 
09 charge
0a rain
0b sun
0c sandstorm
0d hail
0e ?? (absorb-like)
0f hit
10 item up
11 wiggle a bit
12 confusion applied effect
13 awesome blast animation
14 focus energy pumping
15 health recover
16 screen darken recover
17 astonish drops
18 scary face + astonish
19 transform into enemy pokemon (front sprite)
1a turns you into a rock
1b waiting waggle
1c level up shine on your battle display
1d come back animation
1e other come back animation
1f capture pokemon in pokeball
20 turns you into a pokeball, crash.
21 switch (trainer away)

But you may ask, this is fun and all, but what good is it for?
Well, besides some abilities, almost all attacks seem to use this to display and cause effects. there is a table of pointers that is referenced by the attack effect table that seem to be responsible for the graphical part of the attacks and respective effects. So, technically, with this, we can create custom effects and display custom messages as well as change animations for attacks, allowing a greater control over battles.

But still there is much to be done. I posted 11 out of 248 different commands, and one of the ones I posted I'm not too sure it is correct ("exit" did indeed seem to exit command execution, but it loaded a special pointer and placed it in the execution box, so it may be a "return and wait" kind of command instead. Next time it activated was with an attack command, but items also seem to work). So, I'll leave this here for now, hoping someone who knows what to do with this information find it useful.

Edit: While not that many, I seem to have found several useful commands that actually explain a lot of the whys we had regarding Battle mechanics. I'll post below all commands I have found to this moment, as well as what they do (or at least part of what they do):
Edit: While not that many, I seem to have found several useful commands that actually explain a lot of the whys we had regarding Battle mechanics. I'll post below all commands I have found to this moment, as well as what they do (or at least part of what they do):
Code:
02 - Used attack display (no arguments)
This command loads the recently used attack that called it, closes the attack window and displays the message "(poke) used (attack).
Code:
04 - Critical calculator (no arguments)
This command checks the pokemon current status, items and attack effect byte to increase critical ratio, then generates a random number to represent critical. if true, a critical byte will be set in the RAM.
Code:
05 -Base damage calculator (no arguments)
This command creates the real base damage for the attack. If not set, the attack will make zero to near zero damage.
Code:
06 -Type damage calculator (no arguments)
This command calculates STAB bonus and general attack effectiveness. All type-related checks are done in this command.
Code:
09 - Battle animation display (no arguments)
This command makes more than that, but its complexity can only show us results.This code calls the attack animations according to the attack it has.
Code:
0B -Health bar decrease (side to apply)
This command decrease the health bar for the amount in the damage variable. May decrease your own, your opponents or both.
Code:
0C -Health value decrease (side to apply)
While 0B offers the graphical interface, it's 0c that does "the dirty work". So, using only 0b will result in not decreasing health, and using only 0c will leave the health bar as it was until you open a menu, or 0b is called.
Code:
0D -Critical message display (no arguments)
This command only purpose seems to be the display of the "Critical hit" message. Checks if a critical occured and displays it if so.
Code:
10 - Message display (halfword value of the message to print)
This command is the generic print-message command.
Code:
12 - Super Effective Message display (halfword time to wait after display)
This command prints the super effective or not very effective message when needed.
Code:
1A - Faint Animation display (side to apply to)
This command makes the pokemon go down in the screen, to make it disappear.
Code:
23 - Battle Ending functions (1 byte ??)
This command runs itself from 0 to 6 times. Each time, it does something different. But mainly, this code asks for battle ending, including exp calculations and display.
Code:
24 - Wild battle identifier (no arguments)
This command checks if there is a pokemon to be used next, or not. If a wild battle is in place, this code calls the last checks to end the battle
Code:
26 - ??? (1 byte to store)
Stores the given byte to the memory address before the script pointer. Used by next function
Code:
27 - jump if stored byte (word pointer to jump to)
Jumps to the given address if the earlier function stored a byte different than 0 on the loacation
Code:
28 - goto (word pointer)
Simple goto, jumps to the location given.
Code:
29,2a and 2b - Jump if (byte if mask, word pointer to where value is stored, byte, halfword or word to compare to, word destination pointer)
A set of branches, that only vary in the size of the middle argument (represented in order). 0 is jump if equal, 1 is jump if not equal, 2 is jump if higher, 3 is jump if less or equal, 4 is jump if AND of both values is not zero and 5 is jump if AND of both value is zero.
Code:
2c,2d - Jump if array (word first array, word second array, byte compare size, word pointer to go to)
Jumps if a simple, any sized, piece of data meets the condition. Any sized here means it's used for comparing areas of memory usually larger than 4 bytes, but can be used to compare two memory positions of any size.
Code:
2e - Store byte (word address, byte to store)
Stores the byte in the address.
Code:
2f - Add byte (word address, byte to add)
Adds the byte to the address' contents.
Code:
30 - Subtract byte (word address, byte to subtract)
Subtracts the byte to the address' contents.
Code:
31 - Copy Array  (word first array, word second array, byte copy size)
Copies [size] bytes from the second array to the first.
Code:
32 - Add Array  (word destination array, word source array, byte size, word pointer to add)
Adds the bytes pointed by the add pointer to the ones at the source array, and stores the results in the destination array.
Code:
33,34 and 35 - ORR (word address, byte, halfword or word to ORR contents with)
A set of ORR functions (flag setters), that only vary in the size of the middle argument (represented in order). ORRs value in that pointer and stores it back
Code:
36,37 and 38 - NOT (word address, byte, halfword or word to bitwise negate contents with)
A set of NOT functions, that only vary in the size of the middle argument (represented in order). Negates the  value in that pointer and stores it back
Code:
39 - Pause (halfword time to wait)
This function will be called [wait] times, checking only if the time has passed. When that happens, erases wait byte and continues execution.
Code:
3A - Wait (no arguments)
This function waits for an event that has set 0x2023BC8 to occur. As it almost never is set, we can safely use it as a "nop" command to check execution proprieties
Code:
3C, 3D - return (no arguments)
This function returns to the script that called the current script. There are differences between the two, but they do mainly that.
Code:
3f - End (no arguments)
This function seems to end the execution of the script, called at battle end and after each non-lethal attack. Seems to return to normal code execution.
Code:
41 - Call (word pointer to call to)
Calls another battle script into execution, saving the old next pointer on the call stack.
Code:
45 - Animation print (byte bank, byte animation, word pointer to a value)
This function prints several battle animations, such as substitute(key above). In the end, not much is known, but it seems likely that more functions like this exist (altough 9 seems to be the one handling all that)
Code:
4c- Pokemon Data switch (byte bank)
Replaces the pokemon currently in [bank] side of the battle by a pre-selected one (your case, the one you pressed switch or used baton pass on)
Code:
4d - Pokemon Battle Data switch (byte bank)
Using the above switches the pokemon inner data, but this switch is where all battle relevant data is swapped. HP, pp, attacks, stats... Everything is recreated based on the pokemon introduced on the last command.
Code:
4e - Pokemon and Health bar display(byte bank)
The graphic representation of the two above commands, this one prints the new pokemon by switching it out and redraws the healt bar accordingly.
Code:
53 - Trainer display(byte side)
Allows for the trainer in either corner to come out into the field. What it doesn't allow is for that trainer to go away...
Code:
55 - Level up/item get song (no arguments)
Plays the mentioned sound
Code:
56 -Pokemon faint cry (byte side)
Plays the Pokemon fainting (low pitched) cry
Code:
57 -Flee (not sure, but seems like none)
Flees the scene. Not sure if it does more than that.
Code:
5c -Flash Animation (byte bank)
The flash animation that happens when you're hit.
Code:
61 -Pokemon Switch animation (byte side to switch)
Changes the pokemon according to the 4c and 4d loaded data. If applied to the rival pokemon, the pokeball bar always appears.
Code:
91 -Give money (none)
Gives the halfword worth of money deposited at 0x02023E7E and displays the "obtained X [poke]" message from PayDay use. The money is really added to the normal ammount
Code:
EF - Pokemon capture (none)
This is the code responsible for capturing a pokemon. This code will calculate the rates of capture based on the ball used (stored at 0x2023D68). If the item stored is null or invalid (over 0xc), the catch rate is 0.

I'll return with more as I find them
 
Last edited:

jakerman999

looking for spriters
52
Posts
16
Years
So I guess the only way to test this is by studying the format, then trying to replicate it with different command sequences.

This is the first time I regret moving to Linux, I'll have to setup a slave windows-box and try some of this.
 

Full Metal

C(++) Developer.
810
Posts
16
Years
Have you found the command for removing HP?
I believe that would be essential to any new moves, and will likely be in most of them.
 

JPAN

pokemon rom researcher
104
Posts
15
Years
  • Seen Jul 2, 2016
Been a while, huh? I'll be really busy the next month, so I won't be here long. I'll post the research I have so far in this field.
I have finished documenting all of the Attack effects, and the results are a bit disappointing. Many commands are very specific for a single attack or effect, many being simple setters. I'll present the results.
Fun fact: It took me about 1 month on-off time to document the workings of 75% of the codes, but 2 1/2 months to put it in a readeable TXT format.

Note that this is not yet a complete research. Hopefully, more will be added when found.
I will divide this in sections, starting with the battle RAM locations that have been studied, and then going then into a summary of the available (found) commands.

For those who are interested in only making new scripts, the summary of the commands should be enough (second spoiler tag). The RAM section is important to understand the workings of the engine and battle in general, as well as what changes are needed to simulate other effects.

RAM Structures
Spoiler:


Command Listing
Spoiler:
 
91
Posts
8
Years
  • Age 34
  • Seen Apr 27, 2022
This is a lot of information for me, I´m working in some project but I have a issue with bugs in the battles, and I think this info can help me, but Im not an expert so I ask you:
I have 2 bugs in battles
No. 1. It rains in all battles
No. 2. When I shift pokemon during th battle, they get some bad status like poison or sleep, randomly

How can I fix that with your info?
 
417
Posts
9
Years
  • Age 33
  • Seen Nov 20, 2016
This is a lot of information for me, I´m working in some project but I have a issue with bugs in the battles, and I think this info can help me, but Im not an expert so I ask you:
I have 2 bugs in battles
No. 1. It rains in all battles
No. 2. When I shift pokemon during th battle, they get some bad status like poison or sleep, randomly

How can I fix that with your info?
If you don't know how battle data works, the better way to solve something like this is to look through your backups for the most recent file without the bug, use something like the HxD compare feature to find where the differences are between the broken and non-broken ROM, then look at what those changes did/make sure you did what you intended.
 
Back
Top