Touched
Resident ASMAGICIAN
- 625
- Posts
- 10
- Years
- Age 123
- Seen Feb 1, 2018
Most games have a HUD, which allows players to check vital status information, such as health, money, etc. The Pokemon series has no need for this information, as it's all packed away in the start menu. However, with the mechanics of the game being altered, one could feasibly implement a hunger and thirst system, or a fatigue system. These mechanics would need a HUD of some sort in order to be properly implemented.
Since the HUD is usually displayed on the map, and not on any menus, I sought the map rendering routine. I found it at 0805ABB0. This routine does some checks every frame to see if the camera has moved, and updates the appropriate area of the display if it has. However, for the purposes of this research, we have no interest in the body of this routine. We are only interested in the part that returns the function (the branch at 0805AC7E).
So we'd like to inject a routine that loads our HUD after the map updates.
From the looks of the code around the call to this function, this function is a void (doesn't return anything), therefore we can just use r1 without fear of overwriting anything.
Where 0xDEADBEEF is the offset of your new routine. This code then assembles to
That code is going to be 8 bytes. 4 bytes for both opcodes and another 4 for that symbol. So we can overwrite the instructions here: 0805AC9A. One problem - this isn't word aligned. So we need to align that symbol properly. Just pad it with 0s:
Now we can insert at 0805AC9A. Remember to replace the fake offset with your new routine. I chose 087FF000. Also remember to set the Thumb bit.
Now we need to restore functionality to this routine, be adding the opcodes we overwrote. So here is a skeleton routine that you must insert at the offset you chose:
Now the next thing is we must be careful not to do too much in this function to prevent lag. So using this skeleton, I wrote some stuff to the OAM at a fixed pair of coordinates, on the highest priority, and got this:
So it works. Now I just have to work on loading custom graphics and whatever into the VRAM. Right now, overworlds will flicker, but this is just because I'm overwriting OBJ1 in the OAM. I'll update more when I have it.
Since the HUD is usually displayed on the map, and not on any menus, I sought the map rendering routine. I found it at 0805ABB0. This routine does some checks every frame to see if the camera has moved, and updates the appropriate area of the display if it has. However, for the purposes of this research, we have no interest in the body of this routine. We are only interested in the part that returns the function (the branch at 0805AC7E).
Code:
ROM:0805AC7E loc_805AC7E ; CODE XREF: ROM:0805AC52j
ROM:0805AC7E LDR R0, =0x3000E90
ROM:0805AC80 MOVS R1, R7
ROM:0805AC82 MOV R2, R8
ROM:0805AC84 BL sub_805A5D4
ROM:0805AC88 LDR R1, =0x300506C
ROM:0805AC8A LDRH R0, [R1]
ROM:0805AC8C SUBS R0, R0, R7
ROM:0805AC8E STRH R0, [R1]
ROM:0805AC90 LDR R1, =0x3005068
ROM:0805AC92 LDRH R0, [R1]
ROM:0805AC94 MOV R2, R8
ROM:0805AC96 SUBS R0, R0, R2
ROM:0805AC98 STRH R0, [R1]
ROM:0805AC9A POP {R3}
ROM:0805AC9C MOV R8, R3
ROM:0805AC9E POP {R4-R7}
ROM:0805ACA0 POP {R0}
ROM:0805ACA2 BX R0
So we'd like to inject a routine that loads our HUD after the map updates.
From the looks of the code around the call to this function, this function is a void (doesn't return anything), therefore we can just use r1 without fear of overwriting anything.
Code:
ldr r1, =0xDEADBEEF
bx r1
Where 0xDEADBEEF is the offset of your new routine. This code then assembles to
Code:
01 49 08 47 EF BE AD DE
That code is going to be 8 bytes. 4 bytes for both opcodes and another 4 for that symbol. So we can overwrite the instructions here: 0805AC9A. One problem - this isn't word aligned. So we need to align that symbol properly. Just pad it with 0s:
Code:
01 49 08 47 00 00 EF BE AD DE
Now we can insert at 0805AC9A. Remember to replace the fake offset with your new routine. I chose 087FF000. Also remember to set the Thumb bit.
Now we need to restore functionality to this routine, be adding the opcodes we overwrote. So here is a skeleton routine that you must insert at the offset you chose:
Code:
.thumb
.align 2
main:
bl main_func
pop {r3}
mov r8, r3
pop {r4-r7}
pop {r0}
bx r0
main_func:
mov r0, r0 @nop
@ Render HUD here
Now the next thing is we must be careful not to do too much in this function to prevent lag. So using this skeleton, I wrote some stuff to the OAM at a fixed pair of coordinates, on the highest priority, and got this:
![[PokeCommunity.com] Heads-up Display [PokeCommunity.com] Heads-up Display](https://i59.tinypic.com/2hqe688.png)
![[PokeCommunity.com] Heads-up Display [PokeCommunity.com] Heads-up Display](https://i62.tinypic.com/2rqg8ev.png)
![[PokeCommunity.com] Heads-up Display [PokeCommunity.com] Heads-up Display](https://i62.tinypic.com/2vnqbkw.png)
So it works. Now I just have to work on loading custom graphics and whatever into the VRAM. Right now, overworlds will flicker, but this is just because I'm overwriting OBJ1 in the OAM. I'll update more when I have it.