Author Topic: ROM Hacking: Scripting - Part 1  (Read 8263 times)

MediumTheWhale

  • *
  • Posts: 12
  • I am the Whale God, my name is Medium.
    • View Profile
ROM Hacking: Scripting - Part 1
« on: January 09, 2017, 09:48:58 PM »
So I kinda wanted a place where I could post all of the scripts that I have made. I think that some of you might find this very interesting, I'll be explaining each script from the top down. Before I begin, the script editor that I use is called eXtreme Script Editor (XSE) which was developed by HackMew, also most of the scripts I write are all for Pokemon Fire Red, some of these scripts will not work for Ruby, Sapphire or Emerald. Okay, so the first thing I'll get into is:

-POINTERS-

In order to use pointers effectively I use a dynamic offset which is essentially free space inside a ROM. I find free space using a program called Free Space Finder (FSF) which was developed by the same person who made the Script Editor that I use. Essentially, pointers are the names for each function, so like @lul @kappa @1234567890. However pointers can't have spaces so pointers like these will not work: @Scripting isn't as hard as you think @Kappa Ross @It's cold as shit outside Kappa

This is what pointers would look like when in a script:

Code: [Select]
#dynamic 0x(Offset)

#org @start
msgbox @1 0x2
end

#org @1
= Hello!
Alright thats how the pointers look like, now let me explain the functions that I added, starting from the top.

#org @start just marks the beginning of this script, personally every pointer I start of with I name @start
msgbox is self explanatory, it calls a message box, I assigned pointer @1 to this message box so it will call #org @1 0x2 is the type of box, I'll give you the list of the different types later on.
end this should be self explanatory. LUL
#org @1 This is what the msgbox @1 0x2 is calling, it will output the text 'Hello!' - Note: The text you want to be displayed has to have a '=' sign before it.

That's about it for the pointers... What's next?

-MSGBOX-

Right, have a look at this script:

Code: [Select]
#dynamic 0x(Offset)

#org @start
lock
faceplayer
msgbox @1 0x6
release
end

#org @1
= Hello!\nMy name is Medium!
Okay couple of new things, let's jump in.

lock This locks the player from moving.
faceplayer Makes the NPC face the player.
msgbox 0x6 This is just a normal message box except it doesn't lock the player automatically, nor does it make the NPC face the player.
release Releases the player from the lock, and the NPC is freed from faceplayer.
In the message that I typed, "Hello!\nMy name is Medium!", you'll notice that I typed '\n' randomly there, that was not a typo. \n Simply creates a new line where the text that follows it will be displayed. It will look like this in-game:

Quote
Hello!
My name is Medium!

Let me get you that list of message boxes as well as a list of the text add-ons:

-Message Boxes-

Spoiler: show
0x2
A normal msgbox, has lock and faceplayer already in it.
0x3
msgbox that displays the text in black by default with no lock or faceplayer effect, it is used primarily for signs.
0x4
This msgbox does not close, you need to add the command closeonkeypress in order to close it.
0x5
This is a msgbox that displays a Yes/No text box.
0x6
A normal msgbox with no lock or faceplayer effect. It's the main msgbox that I use, even for the most basic of scripts.


-Add Ons-

Heres a list of the add-ons:
Spoiler: show
\c
Used to recolor text from it's default, however there is a much easier way to change the color of the text, I'll get into it blow the list.
\h
This is used for hex values... Ignore them, you're not SethBling LUL
\n
I already explained this one, if you weren't following then go back and re-read everything
\l
exactly what \n does except you can only call it after you use \n.
\p
Creates a new text box, I'll give an example below
\v
This is used to display stored text, primarily player name and rival name, like the \c one there is a better way to call them


Alright let's get into the ones I need to explain in more depth, first off

\c
Code: [Select]
#dynamic 0x(Offset)

#org @start
lock
faceplayer
msgbox @1 0x6
release
end

#org @1
= \c\h01\h02You have received a pokémon!

\c\h01\h02 will display the text in black.

The new way to type colors is much more simple, instead of that mess you just type:
Code: [Select]
[black_fr]You have received a pokémon! This'll display it in black.

Heres the full list of colors:

Spoiler: show
White - [white_fr]
Black - [black_fr]
Gray - [grey_fr]
Red - [red_fr]
Orange - [orange_fr]
Green - [green_fr]
Light Green - [lightgreen_fr]
Blue - [blue_fr]
Light Blue - [lightblue_fr]
Light Blue 2 - [lightblue2_fr]
Cyan - [cyan_fr]
Light Blue 3 - [lightblue3_fr]
Navy Blue - [navyblue_fr]
Dark Navy Blue - [darknavyblue_fr]


Second add-on

\p

Code: [Select]
#dynamic 0x(Offset)

#org @start
lock
faceplayer
msgbox @1 0x6
release
end

#org @1
= \p...\p...\p...\pKappa

This will display like this

Quote
...
...
...
Kappa
I think you can understand that already right? Yes you can, let's move on LUL

\v

Code: [Select]
#dynamic 0x(Offset)

#org @start
lock
faceplayer
msgbox @1 0x6
release
end

#org @1
= \v\h01!\n\v\h06 was around here somewhere...

\v\h01 is the player's name, and \v\h06 is the rival's name. The better way to type these is equally as simple as the color commands:

Quote
[player]!\n[rival] was around here somewhere...

Simple right? This is basically all there is to msgbox and the add-ons. Let's get into some more interesting stuff...

-Flags-

Flags are for events that you want to happen only once. So say you have flag 0x200, and want an NPC to say something specific once. this is how I would do it:

Code: [Select]
#dynamic 0x000000

#org @start
lock
faceplayer
checkflag 0x200
if 0x1 goto @end
msgbox @1 0x6
setflag 0x200
release
end

#org @end
msgbox @2 0x6
release
end

#org @1
= This world... It is\nuseless in this form...\pBut soon... yes, soon\nI will shape it\pIN MY IMAGE!

#org @2
= You.. You heard\nNOTHING!

Let's talk about them codes, starting with:

checkflag 0x200 it does exactly as it's name implies it checks if the flag 0x200 is set, a quick note: All the Pokemon games already have flags in them, I'll give you a list of the ones in Fire Red/Leaf Green so you can avoid them after I am done explaining the script.
if 0x1 goto @end This is an if statement, if you've programmed/scripted ANYTHING before you'll know what these are, if you haven't let me give you a quick explanation, they essentially check if something meets a certain requirement or, in this case, if something is true. 0x1 is what true means in this program, goto sends you to a pointer and does not return.
setflag 0x200 does exactly as the name implies and sets the flag that it was assigned.

Here's that list of the flags in FR/LG:
Spoiler: show
0x1
0x2
0x3
0x4
0x5
0x6
0x2B
0x2C
0x2E
0x2F
0x30
0x31
0x32
0x33
0x34
0x35
0x36
0x37
0x39
0x3D
0x3E
0x3F
0x40
0x41
0x42
0x43
0x44
0x45
0x46
0x47
0x48
0x49
0x4A
0x4B
0x4C
0x4D
0x50
0x52
0x54
0x58
0x59
0x5C
0x5D
0x5F
0x62
0x63
0x64
0x65
0x66
0x67
0x68
0x69
0x6A
0x6B
0x72
0x75
0x7A
0x7B
0x7C
0x7D
0x7E
0x80
0x81
0x82
0x84
0x85
0x86
0x88
0x8B
0x8C
0x8D
0x8E
0x91
0x92
0x93
0x94
0x95
0x96
0x97
0x98
0x99
0x9A
0x9B
0x9C
0x9E
0x9F
0xA0
0xA1
0xA2
0xAA
0xAD
0xAE
0xB1
0xB2
0xB3
0xB4
0xD5
0xD6
0xD7
0xDC
0xEA
0x109
0x10A
0x10B
0x118
0x119
0x11A
0x11B
0x120
0x121
0x124
0x125
0x126
0x127
0x128
0x129
0x142
0x143
0x144
0x163
0x16A
0x16E
0x16F
0x188
0x189
0x190
0x191
0x192
0x1A7
0x1A8
0x1B6
0x1B7
0x1B8
0x1CE
0x1CF
0x1D0
0x219
0x21A
0x21F
0x230
0x231
0x232
0x233
0x234
0x235
0x236
0x237
0x238
0x239
0x23A
0x23B
0x23C
0x23D
0x23F
0x240
0x241
0x243
0x244
0x245
0x246
0x247
0x248
0x249
0x24A
0x24B
0x24D
0x24E
0x24F
0x250
0x251
0x252
0x253
0x254
0x255
0x256
0x257
0x258
0x259
0x25B
0x25E
0x263
0x264
0x265
0x266
0x267
0x268
0x269
0x26A
0x26B
0x26C
0x26D
0x26E
0x26F
0x270
0x271
0x272
0x273
0x274
0x275
0x276
0x278
0x27A
0x27B
0x27C
0x27D
0x27E
0x27F
0x280
0x281
0x282
0x283
0x284
0x285
0x286
0x287
0x288
0x289
0x28A
0x28B
0x28C
0x28D
0x290
0x291
0x292
0x293
0x294
0x295
0x296
0x297
0x298
0x29A
0x29B
0x29C
0x29D
0x29E
0x29F
0x2A0
0x2A1
0x2A2
0x2A3
0x2A5
0x2A6
0x2BB
0x2BC
0x2BD
0x2BE
0x2BF
0x2C0
0x2C1
0x2C2
0x2C3
0x2C4
0x2C5
0x2C6
0x2C7
0x2C8
0x2C9
0x2CA
0x2CB
0x2CC
0x2CD
0x2CE
0x2CF
0x2D0
0x2D1
0x2D2
0x2D3
0x2D4
0x2D5
0x2D6
0x2D7
0x2D8
0x2D9
0x2DA
0x2DB
0x2DC
0x2DD
0x2E1
0x2E2
0x2E3
0x2E4
0x2E5
0x2EC
0x2ED
0x2EE
0x2EF
0x2F0
0x2F1
0x2F2
0x2F3
0x2F4
0x2F5
0x2F6
0x2F7
0x2F8
0x2F9
0x2FA
0x2FB
0x2FC
0x2FD
0x2FE
0x2FF
0x4B0
0x4B1
0x4B2
0x4B3
0x4B4
0x4B5
0x4B6
0x4B7
0x4B8
0x4B9
0x4BA
0x4BB
0x4BC
0x805
0x807
0x820
0x821
0x822
0x823
0x824
0x825
0x826
0x827
0x828
0x829
0x82C
0x82D
0x82F
0x830
0x834
0x83E
0x841
0x842
0x844
0x845
0x846
0x847
0x848
0x849
0x84A
0x84B
0x890
0x891
0x892
0x893
0x894
0x895
0x896
0x897
0x898
0x899
0x89A
0x89B
0x89C
0x89D
0x89E
0x89F
0x8A0
0x8A1
0x8A2
0x8A3
0x8A4
0x8A5
0x8A6
0x8A7
0x8A8
0x8A9
0x8AA
0x8AB
0x8AC
0x8AD
0x8AE
0x8AF
0x8B0
0x8B1
0x8B2
0x8B3
0x8B4
0x8B5
0x8B6
0x8B7
0x8B8
0x8B9
0x8BA
0x8BB
0x8BC
0x8BD
0x8BE
0x8BF
0x8C0
0x8C1
0x8C2

I think thats it for flags, so lets go to an actual command:

-GivePokemon-

This is a long one:

Code: [Select]
#dynamic 0x000000

#org @start
lock
faceplayer
checkflag 0x000
if 0x1 goto @done
msgbox @1 0x5
compare LASTRESULT 0x1
if 0x1 goto @take
msgbox @2
release
end

#org @done
msgbox @6 0x6
release
end

#org @take
givepokemon 0x4 0x5 0x0 0x0 0x0 0x0
fanfare 0x13E
msgbox @3 0x4
waitfanfare
closeonkeypress
setflag 0x000
msgbox @4 0x5
comapre LASTRESULT 0x1
if 0x1 call @name
msgbox @5 0x6
release
end

#org @name
call 0x1A74EB
return

#org @1
= Hello, I have this\npokémon I can't\ptake care of...\nwill you please take it?

#org @2
= Oh... Alright someone\nelse will...

#org @3
= You have received Charmander!

#org @4
= Would you like to\ngive Charmander a name?

#org @5
= Take good care of\ncharmander!

#org @6
= Are you taking good\ncare of Charmander?
A lot to cover...
If you didn't read what the different message boxes did, go back and read them, it'll save me some time explaining the ones used here.

compare LASTRESULT 0x1 Because msgbox 0x5 is a Yes/No message box, we need to run the compare function in order to actually make it do something, LASTRESULT is used for this particular message box it essentially means yes or no, or true or false.
givepokemon 0x4 0x5 0x0 0x0... This is what gives you the pokemon. 0x4 is the code for charmander, 0x5 is the level, the first 0x0 is for an item, currently it has none, the rest 0x0's are buffers.
fanfare 0x13E this is the jingle that plays when you receive the pokémon.
waitfanfare waits for the jingle to finish before the next line is ran.
closeonkeypress because the message box that I use above is of the type 0x4 I need to run closeonkeypress in order to close it.
call 0x1A74EB this one is in the if statement that is called after msgbox @4 0x5 if you didn't cat it. It's exactly like goto except it expects it to return. 0x1A74EB is the pokémon naming screen, which is why we called this pointer @name.
return This returns the script to the previous pointer/function. Must be used if you use call.

Is that it? If you spot a line that I didn't cover let me know, but I think that's it. On to the next one:

-GiveItem-

Script:
Code: [Select]
#dynamic 0x71A300

#org @start
lock
faceplayer
checkflag 0x9
if 0x1 goto @done
msgbox @1 0x5
compare LASTRESULT 0x1
if 0x1 goto @take
msgbox @2 0x6
release
end

#org @done
msgbox @2 0x6
release
end

#org @take
giveitem 0xD 0x3 MSG_OBTAIN
msgbox @2 0x6
setflag 0x9
release
end

#org @1
= I come from the\nPokémart in Viridian.\pWhy not take this free\nsample?

#org @2
= Do visit us in Viridian!
You should already know what most of this stuff means, so I'll start with...

giveitem 0xD 0x3 MSG_OBTAIN giveitem is self explanatory, 0xD is the item, which is a potion. 0x3 is the amount that is going to be given. MSG_OBTAIN does everything that fanfare, waitfanfare and closeonkeypress do in the givepokemon command, which is why we have less msgboxes and less commands.

That's all for the giveitem command. What's next?

-Special-

Script:
Code: [Select]
#dynamic 0x71A500

#org @start
lock
faceplayer
msgbox @1 0x4
closeonkeypress
fadescreen 0x1
fanfare 0x100
special 0x0
waitfanfare
fadescreen 0x0
msgbox @2 0x6
release
end

#org @1
= Your pokémon look tired.\nI'll heal them up!

#org @2
= All healed up\nand ready to go!
A few things to explain here, first off

fadescreen 0x1/0x0 fadescreen is self explanatory, 0x1 is the type, this one fades from normal to black. 0x0 is black to normal.
special 0x0 Think of special as a sort of call, it calls a script that has the value/type 0x0 (0x0 is the special type for restoring your pokemon).

I used two tpes of fadescreen here, here is the full list:
Spoiler: show
0x0 - fade from black to normal
0x1 – fade from normal to black
0x2 – fade from white to normal
0x3 – fade from normal to white


Next!

-CountPokemon-

This one should be easy to figure out so I'm just gonna give you a piece of some of the code I've used.

Code: [Select]
countpokemon
compare 0x800D 0x6
if 0x1 goto @pointer
Essentially this is how you run the countpokemon command, compare 0x800D to 0x6. 0x6 being the amount of pokemon it's looking out for. from there I think you understand right? If not let me know, I'll try explaining it in more depth in the next update! I will leave you off with the full script however, so if your having trouble thinking of ways on how to use it, or why you would use it, you can look at this and go from there:

Code: [Select]
#dynamic 0x71A400

#org @start
lock
faceplayer
checkflag 0x10
if 0x1 goto @done
msgbox @1 0x5
compare LASTRESULT 0x1
if 0x1 goto take
msgbox @2 0x6
release
end

#org @done
msgbox @3 0x6
release
end

#org @take
countpokemon
compare 0x800D 0x6
if 0x1 goto @carry
givepokemon 0x9E 0x5 0x0 0x0 0x0 0x0
fanfare
msgbox @4 0x4
waitfanfare
closeonkeypress
setflag 0x10
msgbox @5 0x5
compare LASTRESULT 0x1
if 0x1 call @name
msgbox @3 0x6
release
end

#org @carry
msgbox @6 0x6
release
end

#org @name
call
return

#org @1
= I have this pokémon\nI can't take care of...\pWill you please take it?

#org @2
= Oh, someone else will..

#org @3
= Takce care of Totodile!

#org @4
= You have received a Totodile!

#org @5
= Would you like to give Totodile\na name?

#org @6
= Your party is full!\nCome back when you have room!
« Last Edit: January 13, 2017, 04:33:36 PM by MediumTheWhale »