PDA

View Full Version : [Tutorial] Pokemon BW: Scripting Lessons.


pichu2000
June 26th, 2012, 01:23 AM
Foreward

Hi, everyone!
I've noticed that your latest effort is trying to figure out how scripting works in BW, and I want to add my contribution.
Really, I started researching about two years ago, for a future addition of PPRE, but nothing happened, and my work remained private.
Now, I want to share my knowledge about scripts with you, so let's go!
(This tutorial assumes that you know something about hex and programming)

How Nintendo Links Maps with Scripts.

In a Nintendo DS Pokemon ROM we must distinguish three differents sections of a map.

- Model Structure : 3D Graphic (BW ROM: a/0/0/8)
- Events : NPCS, Warps, Signs (BW ROM: a/1/2/5)
- Scripts: auto-explicative (BW ROM: a/0/5/7)
- Text: auto-explicative (BW ROM: a/0/0/3)

Each of sections are stored in a different archives int the ROM, apparently unlinked - this is not true.
There's actually a table (stored in RAM) that "links" all of these different files.
In a BW rom, this table is saved to the a/0/1/3 file.
Each row of this table (0x30 bytes length) represents a "gamezone".
Example:

00 00 02 00 00 00 0a 03 0b 03 ac 01 fa 03 fa 03 fa 03 fa
03 ff ff 85 01 85 01 04 04 40 00 40 ec 00 00 00 00 0e 03
00 00 00 00 00 00 ee 02 00 00


This represents the "zonedata" of Nuvema Town.
There is a lot of data in this sequence, but need to focus on:
Script Id = 0a 03
Nuvema Town's script file is a/0/5/7.778.
Text Id = ac 01
Nuvema Town's text file is a/0/0/3.428
Event Id = 85 01
Nuvema Town's event file is a/1/2/5.389
We now have scripts, events, and text.
We just need to know how events refer to scripts, and scripts refer to events... How?
Simple: use an Identifier.
Each script, event, and text has a unique ID in its file.
So if we go to a/1/2/5.389 we can find NPC 0, 1, 2, 3 , 4...
Or if we go to a/0/0/3.428 we can find Msg 0, 1, 2, 3, 4...
And if we go to a/0/5/7.778 we can find Script 0, 1, 2, 3, 4...

Is that clear? I hope it is.
Now we analize the a/0/5/7 files, which contain scripts.

Script Structure

In a BW file, like DPP and HGSS, the scripts are divided into two main sections: declarative and command section.

Declarative Sections

Declarative part contains all "offsets" of the scripts (start offset in particular).
Each script offset is saved as a UInt32 (4 bytes), which we call "offsetPad".
To get the real offset, we need to follow this formula: reader.Position + offsetPad.
This section is terminated by 0x13FD.
Example:

0A 00 00 00 08 00 00 00 FD 00 00 00 13 FD

This is a declarative part for a/0/5/7-0, containing 3 scripts.
1st script's offset: 0x0A + 0x04 = 0x0E
2nd script's offset: 0x08 + 0x08 = 0x10
3rd script's offset: 0xFD + 0x0A = 0x107

Command Sections

The command section contains the actual commands that will be executed by scripts.
There are 800+ different commands, but the main structure is this:

UInt16 (2bytes) - Command ID
(Various parameters)


Lesson 1: Simple Message Script

First, we'll start with something of simple: we wanna a overworld say a simple message, like "Hello, world!".
So, after we open our file to edit, go to offset of the our script (Lesson 0 - Declarative Part) and start writing. (I'll use red for commands and blue for parameters)
So, the first command we need to insert is:

002E

This command represents the beginning of the script.
It doesn't have any parameters. We'll call it StartScript.
After, we should want to "hear" the famous 'click' sound when talking to someone.
So, we then add that and have:

StartScript
A600 4705

This new command plays a generic sound, in this case 4705, which is the 'click' sound. If you want another sound, you can change the parameter. We will call this command PlaySound.

Now, we want to talk to a well-mannered person, so we want him/her to face us when speaking.
To do this, we'll use:

StartScript
PlaySound CLICK
7400


This command forces the person to face the player. We'll call it FacePlayer.

Now the for the actual message:

StartScript
PlaySound CLICK
FacePlayer
3D00 0004 0000 0000 0000


This command is a little more complex. There are a lot of different commands for showing a message, but this is the simplest. Now we'll analized each parameter.
0004 : Constant.
We always need to insert it. 0000 : Message Id.
Differently from GBA games, we don't insert the offset of the message.
In fact, each map is linked with a file of Msg.Narc ( a/0/0/3) that contains an ordered sequence of "messages". So the parameter tells us that the message is the 0x0 message in linked msg-file.
(Later I'll give you all the association of the script-message files, I promise) 0000 : Top/Bottom View.
Indicates where the message is show on the screen. (0000 = Bottom, 0001 = Top) 0000 : Type of Border.
Indicates which type of border the message has. (0000 = Simple)
Now we have finally inserted message, but we need other commands to close the script.
First:

StartScript
PlaySound CLICK
FacePlayer
Message MSGCONST ID=0 BOTTOM NORMAL
3200


This command forces the message to remain open until you click a botton.
We'll call it WaitButton.

StartScript
PlaySound CLICK
FacePlayer
Message MSGCONST ID=0 BOTTOM NORMAL
WaitButton
3E00


This command closes the message. We'll call it CloseMessage.

StartScript
PlaySound CLICK
FacePlayer
Message MSGCONST ID=0 BOTTOM NORMAL
WaitButton
CloseMessage
3000


I don't know what this command does, but you always need to insert it after CloseMessage.

StartScript
PlaySound CLICK
FacePlayer
Message MSGCONST ID=0 BOTTOM NORMAL
WaitButton
CloseMessage
3000
2F00


This command closes the script. We'll call it EndScript.

The last command is 0200, which ends the entire routine. So, we'll call it End.
We now have this sequence of commands to put in our Hex Editor:

2E00 A600 4705 7400 3D00 0004 0000 0000 0000 3200 3E00 3000 2F00 0200


The "human-friendly" version of the script is:

StartScript
PlaySound CLICK
FacePlayer
Message MSGCONST ID=0 BOTTOM NORMAL
WaitButton
CloseMessage
3000
EndScript
End


Lesson 2: Simple Message Script with variations.

There are lost of different message commands, which gives very powerful ways to say things.
Let's begin.

003D (Message)

We already saw this command, but now we look more closely at it.
The last parameter, what we called NORMAL, can be changed to give another whole aspect to the box.
Here there's a list of values that we can use: 0000 : NORMAL. 0001 : ANGRY.
003C

This command has a similar syntax to Message, but there is a new parameter, called NPCID, that represents the person to which the box's arrow points to.
We'll call it DirectedMessage .
The format of the command is:

DirectedMessage MSGCONST ID=0 NPCID BOTTOM NORMAL

We can use this command when we want that other people speak during script.

0034

This command is more simple than the other two.
It shows a message in a grey box, used mostly when you received an item.
We'll call it EventGreyMessage.
The format of the command is:

EventGreyMessage MSGID BOTTOM

Important: To close this message, we need to use 0036, instead of CloseMessage.
We'll call this command CloseEventMessage.

0038

It shows a message without arrow, used mostly when we don't know who's speaking.
We'll call it BubbleMessage.
The format of the command is:

BubbleMessage MSGID BOTTOM

Important: To close this message, we need to use 0039, instead of CloseMessage.
We'll call this command CloseBubbleMessage.

003A

With this command, we show a bubblemessage at specific coordinates.
We'll call it ShowMessageAt.
The format of the command is:

ShowMessageAt MSGID X Y

Note: The (0,0) position is on upper-left point of screen.

0043

Shows a message with a colored border, used mostly when we read a city's sign or target.
We'll call it BorderedMessage.
The format of the command is:

BorderedMessage MSGID COLOR

The color values are: 0000 : PINK. 0001 : BROWN. 0002 : BLUE. 0003 : GREEN.
Important: To close this message, we need to use 0044, instead of CloseMessage.
We'll call this command CloseBorderedMessage.

0045

Show a strange transparent message, like a destroyed paper.
We'll call it PaperMessage.
The format of the command is:

PaperMessage MSGID X

This command needs some more research.

Important: To close this message, we need to use 0046, instead of CloseMessage.
We'll call this command ClosePaperMessage.

0048

This command is the same as DirectedMessage.
The only difference is another last parameter, that is always 0.
We shouldn't use it, for now.

0049

This command is similar to DirectedMessage, but with an important differences: the message changes based on if we are playing Black or White.
So we'll call it DoubleMessage

The format of command is:

DoubleMessage MSGCONST MSGIDBLACK MSGIDWHITE NPCID BOTTOM NORMAL

004A

This shows an angry Message, when we want the person to "shout",
We'll call it AngryMessage.
The format of the command is:

AngryMessage MSGID BOTTOM

Important: To close this message, we need to use 004B, instead of CloseMessage.
We'll call this command CloseAngryMessage.

All of these commands we can use with our simple message scripts, just remember the close ht messages with the correct command!
Today's lessons are finish
Next, we'll see messages that contain variables (Like Hiro's name and other types)
Stay tuned!

pichu2000

Team Fail
June 26th, 2012, 07:21 AM
Wow... There's a ton of science behind simple messages. Perhaps when you have the time to fix it up, perhaps you can show in-game screenshots of some of the messages' types.

IAL32
June 26th, 2012, 08:17 AM
Very cool man, the guide is very detailed and useful.

miksy91
June 26th, 2012, 11:02 AM
This is a really nice scripting guide here and I can tell you had hard time writing all this. Anyway, I've to say it's still pretty difficult to understand what you wrote before Lesson 1; how the scripts are called and all that.
Perhaps someone could help you out with this (translating your findings into good english I mean) so that you could even make a proper, well-explained compendium out of it (Example: http://hax.iimarck.us/files/scriptingcodes_eng.htm).

pichu2000
June 26th, 2012, 01:47 PM
This is a really nice scripting guide here and I can tell you had hard time writing all this. Anyway, I've to say it's still pretty difficult to understand what you wrote before Lesson 1; how the scripts are called and all that.
Perhaps someone could help you out with this (translating your findings into good english I mean) so that you could even make a proper, well-explained compendium out of it (Example: http://hax.iimarck.us/files/scriptingcodes_eng.htm).

Hmm, I know that my English isn't perfect, and if someone could translate my work (from Italian to English) I can explain easily my findings...
But I haven't much time to make a full compendium for now, so I can release these "little" lessons...
I'm very glad if someone can help me!

Hopeless Masquerade
June 26th, 2012, 05:25 PM
Hmm, I know that my English isn't perfect, and if someone could translate my work (from Italian to English) I can explain easily my findings...
But I haven't much time to make a full compendium for now, so I can release these "little" lessons...
I'm very glad if someone can help me!

I don't really know very much Italian, but I'd definitely be willing to help clean up your English, if you'd like.

Anyways, this is some really interesting stuff here!

pichu2000
June 27th, 2012, 01:43 AM
Thanks agentgeo, I appreciate it...
I added a better explanation on how scripts is linked with events and maps...
I hope now It's more clear xD.

DriveTheGamer
January 21st, 2015, 08:32 AM
How I can calculate that the End command is 02 00?