The <BBP Command
Catapulting the Player

In this lesson we're going to look at an example hack that puts in a custom TSC command.
This is what our command shall be:

<BBPXXXX:YYYY = Bump the main character in direction X with Y upward force. Direction 0000 = left, direction 0002 = right.

<BBP stands for "Big BumP". It will be similar to <MYB except it will launch the character much farther.

There are a few things we have to look at before designing this command. First, you should know how the game handles X-velocity and Y-velocity of the main player.

The X-velocity and Y-velocity are stored in two ram offsets:

49E66C = X-Velocity of main player
49E670 = Y-Velocity of main player

Also, Cave Story uses a coordinate system with point (0,0) as the upper left corner of any room in the game. Down is considered positive on the Y-axis, and right is considered positive on the X-axis.

Cave Story Coordinates

TSC Arguments
The arguments, sometimes known as the parameters, of any TSC command are simply the numbers that the command accepts as input:

TSC Arguments

Notice that I can say something like "<TRA has 4 arguments" and "the random number function has 2 arguments". The word argument has the same meaning for TSC commands and ASM functions. In both cases, arguments are numbers accepted by the TSC command (or function) that control how that command or function behaves.

For our custom commands, remember we need to add certain values to the Script Position to get at the first and second TSC arguments:

Getting the TSC Arguments

The Assembly Part
n the TSC parser, there are actually 2 <FAC commands. The second one is completely useless, but it gives us a rather easy way to branch out of the parser and into our new custom command.

The second <FAC command is at address 424EAF. So, go to 424EAF and put in this code:
Address   Instruction
00424EAF  JMP 004937F4       ;jumps to the address where we're gonna put the <BBP command.
That'll lead us to 4937F4, where there's some free space, and we'll put the <BBP command into that free space. The command directly after the second <FAC command is the <GIT command. So, we need to jump to the address of the <GIT command if one of the letters of the command doesn't match BBP.

Follow along with the comments:
Address   Instruction                         Comments
004937F4  MOV ECX,DWORD PTR DS:[4A5AD8]
004937FA  ADD ECX,DWORD PTR DS:[4A5AE0]       ;set up Script Position and such.
00493800  CMP BYTE PTR DS:[ECX+1],42          ;B
00493804  JNE 00424F33                        ;if letter isn't B, go to 424F33 (address of <GIT command)
0049380A  CMP BYTE PTR DS:[ECX+2],42          ;B
0049380E  JNE 00424F33                        ;if letter isn't B, go to 424F33.
00493814  CMP BYTE PTR DS:[ECX+3],50          ;P
00493818  JNE 00424F33                        ;if letter isn't P, go to 424F33.
0049381E  MOV EDX,DWORD PTR DS:[4A5AE0]       ;store Script Position to EDX
00493824  ADD EDX,4                           ;add 4 to EDX.
00493827  PUSH EDX                            ;Push EDX
00493828  CALL 00421900                       ;Use Ascii to Number function to get first argument.
0049382D  ADD ESP,4                           ;Fix the stack
00493830  CMP EAX,2                           ;If 1st argument is 2, then store 1000 to player's X-velocity.
00493833  JE SHORT 00493841
00493835  MOV DWORD PTR DS:[49E66C],-1000     ;If 1st argument is not 2, then store -1000 to player's X-velocity.
0049383F  JMP SHORT 0049384B
00493841  MOV DWORD PTR DS:[49E66C],1000
0049384B  MOV EDX,DWORD PTR DS:[4A5AE0]       ;store Script Position to EDX
00493851  ADD EDX,9                           ;add 9 to EDX.
00493854  PUSH EDX                            ;Push EDX
00493855  CALL 00421900                       ;Use Ascii to Number function to get 2nd argument.
0049385A  ADD ESP,4                           ;Fix the stack
0049385D  SHL EAX,3                           ;Multiply 2nd argument by 2^3 = 8 (increases upward force by factor of 8)
00493860  NEG EAX                             ;Multiply EAX by -1 (remember negative Y-velocity = upward)
00493862  MOV DWORD PTR DS:[49E670],EAX       ;store EAX into player's Y-velocity
00493867  ADD DWORD PTR DS:[4A5AE0],0D        ;add 0D (hex) = 13 (dec) to Script Position, since <BBPXXXX:YYYY is 13 chars long
0049386E  JMP 004252A7                        ;jump back to beginning of parser
The TSC Part
Create an entity (such as a signpost) that runs event 700 when the player presses down on it.

Here's our TSC code to demonstrate the <BBP command:

TSC BBP

If you're using CaveEditor, all your custom commands will be highlighted in red, since the syntax checker thinks that the new command is "incorrect syntax". It's okay to save the script because we made the new command and we know exactly how to use it.[1]

The Result
Catapulting the Player

Now just read the signpost and choose whether to launch yourself left or right. You can use the <BBP command for cutscenes (automatic player jumping) or for puzzles, transportation across a map, etc.
Hint: Hold down the jump button while <BBP is running to fly higher.

You can make as many custom commands as you want without needing to delete any old ones. For example, if you wanted to place a command directly after <BBP, just replace the JNE 00424F33 parts with JNE (address of your second custom command).

Navigation
Previous Lesson: TSC Hacking
Next Lesson: Local and Global Variables
Table of Contents

[1]In the newest versions of CaveEditor, there is a way to make the editor recognize your new ASM-hacked commands so that nothing will be shown in red. You do this by editing the settings file CaveEditor.txt. Right now, we aren't going to worry about it too much.