Touched
Resident ASMAGICIAN
- 625
- Posts
- 10
- Years
- Age 123
- Seen Feb 1, 2018
I don't think the title was all that clear, but it was the best I could come up with. In case you're wondering what I meant, I mean this:
This function allows you to enter some text for a predefined purpose, and then add a callback to handle the result.
It is reused quite a bit around the game for the following purposes:
I seem to recall there being a few other types in RSE (That secret code person in Rustboro). However, these don't seem to be present in FireRed - but there are empty slots.
Basically the function would have a C signature resembling the following:
The first parameter is the most interesting, in my opinion. It holds a value that is evaluated by a switch statement that tells the rest of the function what text to render, what picture to display, etc. The table for the functions that handle each case is at 0809DA04, and is pointed to at 0809DA00 (so you should be able to repoint it, if you so desire). Basically the switch currently has 7 cases, and a default handler. Here is what they do (in fire red):
If you try anything beyond 4, you'll crash the game, so these appear to be empty slots. However, after 7, the default handler kicks in and you'll be jumped to 0809D9F8. This seems to just call the callback immediately, though I didn't research it much. The compare opcode for this switch is at 0809D9EC:
So if you expand that table, you'll need to change the byte at 0809D9EC to the new size.
The second argument is a pointer to the block of memory where the result will be stored.
The third argument, the image just controls what image is displayed (The player in the image above). If you choose 0 for the type, 0 will show the male player, 1 will show the female player, and other numbers will choose other player animations (fishing, pokeball, surfing, etc.). These animations freeze, however. For the nickname Pokemon, this number is the species. For anything else, it appears to do nothing.
The fourth parameter is usually zero, and I haven't found out what it does yet.
The callback is a pointer to the function that will be called after the naming is done. I just use 080568E0 if I call it from a script, this is a function that returns to the OW and resumes script execution. If you want to do extra stuff, just create your own callback and branch to that function afterwards.
The last argument seems to be another controlling parameter. In the nickname function, it appears to be set to some (decrypted) information from the Pokemon data structure, which will apparently control the gender symbol (and maybe other things)?
Now that I've got the description out of the way, lets look at an example routine:
I'm not quite sure about the calling convention for ARM, but it appears that registers r0-r3 are used, any remaining arguments are pushed in normal order to the stack (as opposed to the reverse order of cdecl). If anyone has more information on this, please let me know.
So that heavily commented piece of code will rename the player. I guess you could do more with it if you changed the destination parameter to be a script buffer or something. This routine works from a script, so you could potentially do something like you see in GSC, where you have to name your rival later in the game.
The next step would be to try and expand that table of pointers and/or replace the useless (?) slots with something more useful. Also, I'd like to look at the individual cases and see what is common between them (maybe they all call a similar rendering function or something) - that way it'd be easy to create our own name screen types.
![[PokeCommunity.com] Fun with the naming function [PokeCommunity.com] Fun with the naming function](https://i60.tinypic.com/29vjix0.png)
This function allows you to enter some text for a predefined purpose, and then add a callback to handle the result.
It is reused quite a bit around the game for the following purposes:
- Naming the player in the intro
- Naming the rival
- Nicknaming Pokemon
- (Re)Naming a PC Box
I seem to recall there being a few other types in RSE (That secret code person in Rustboro). However, these don't seem to be present in FireRed - but there are empty slots.
Basically the function would have a C signature resembling the following:
Code:
void name_screen(uint8_t type, uint32_t *dest, uint16_t image, uint16_t arg1, uint32_t *callback, uint32_t arg2);
The first parameter is the most interesting, in my opinion. It holds a value that is evaluated by a switch statement that tells the rest of the function what text to render, what picture to display, etc. The table for the functions that handle each case is at 0809DA04, and is pointed to at 0809DA00 (so you should be able to repoint it, if you so desire). Basically the switch currently has 7 cases, and a default handler. Here is what they do (in fire red):
Code:
0 Name the player
1 Name a PC box
2 Nickname Pokemon
3 Same as 2, apparently
4 Name the rival
If you try anything beyond 4, you'll crash the game, so these appear to be empty slots. However, after 7, the default handler kicks in and you'll be jumped to 0809D9F8. This seems to just call the callback immediately, though I didn't research it much. The compare opcode for this switch is at 0809D9EC:
Code:
ROM:0809D9EC CMP R0, #7
ROM:0809D9EE BHI def_809D9F8 @ default case
So if you expand that table, you'll need to change the byte at 0809D9EC to the new size.
The second argument is a pointer to the block of memory where the result will be stored.
The third argument, the image just controls what image is displayed (The player in the image above). If you choose 0 for the type, 0 will show the male player, 1 will show the female player, and other numbers will choose other player animations (fishing, pokeball, surfing, etc.). These animations freeze, however. For the nickname Pokemon, this number is the species. For anything else, it appears to do nothing.
The fourth parameter is usually zero, and I haven't found out what it does yet.
The callback is a pointer to the function that will be called after the naming is done. I just use 080568E0 if I call it from a script, this is a function that returns to the OW and resumes script execution. If you want to do extra stuff, just create your own callback and branch to that function afterwards.
The last argument seems to be another controlling parameter. In the nickname function, it appears to be set to some (decrypted) information from the Pokemon data structure, which will apparently control the gender symbol (and maybe other things)?
Now that I've got the description out of the way, lets look at an example routine:
Code:
.thumb
.align 2
main:
push {r0-r4, lr}
ldr r0, .RETURN
@ Push any two registers to the stack so we can safely modify it
push {r4-r5}
@ We're going to add two values
sub sp, #0x8
@ Add the argument to stack. This is usually zero
@ It holds Pokemon attributes for the nickname function
mov r0, #0x0
str r0, [sp, #0x0]
@ Load the callback onto the stack. The resume function
@ Returns to the overworld and continues script execution
ldr r0, .RESUME
str r0, [sp, #0x4]
@ Load the other parameters
ldr r4, .NAMECHOOSE
@ Name screen type. Used in switch statement
mov r0, #0x0
@ Argument for name screen. Used to change picture next to name
mov r2, #0x0
@ Another argument. Unknown
mov r3, #0x0
@ A pointer to where the result should be stored
ldr r1, .PLAYERDATA
ldr r1, [r1]
@ Call the naming function
bl call_via_r4
@ Restore the stack to it's former state
add sp, #0x8
pop {r4-r5}
pop {r0-r4, pc}
call_via_r4:
bx r4
pop {pc}
.align 2
.NAMECHOOSE: .word 0x0809D954 + 1
.RESUME: .word 0x080568E0 + 1
.PLAYERDATA: .word 0x0300500C
.RETURN: .word 0x08130C64 +1
I'm not quite sure about the calling convention for ARM, but it appears that registers r0-r3 are used, any remaining arguments are pushed in normal order to the stack (as opposed to the reverse order of cdecl). If anyone has more information on this, please let me know.
So that heavily commented piece of code will rename the player. I guess you could do more with it if you changed the destination parameter to be a script buffer or something. This routine works from a script, so you could potentially do something like you see in GSC, where you have to name your rival later in the game.
The next step would be to try and expand that table of pointers and/or replace the useless (?) slots with something more useful. Also, I'd like to look at the individual cases and see what is common between them (maybe they all call a similar rendering function or something) - that way it'd be easy to create our own name screen types.