The way of the hacker
Either the cheat finder didn't feel "real" enough for you, or you want to get some "hands-on" knowledge, but you feel you're now ready to call yourself a Hacker. You pull out a black hoodie over your head and write your plan on a whiteboard:
SCAN THE RAM
-> Look up for HP value in RAM
-> Flag all bytes with the HP value
CHANGE HP VALUE IN GAME
SCAN THE RAM
-> Check the flagged bytes in RAM
-> Keep the flagged bytes that got the new HP value
IF MORE THAN ONE FLAGGED BYTE
-> Repeat from "CHANGE HP VALUE IN GAME"
ELSE IF NO FLAGGED BYTE
-> Clearly we did something wrong
ELSE
-> The last flagged byte is the result
PRINT THE LAST FLAGGED BYTE
You feel like you could humanly do most of these things, but the part about scanning the RAM suddenly feels like you may have ordered more than you can chew: you came for reverse-engineering, not for writing a GameBoy emulator1!
Attention!
All fields of study have a depth of accumulated knowledge that can seem arcane to people non-familiar to it. Reverse-engineering being a science of research, your curiosity will often be put to the test as you have to familiarize yourself with this knowledge.
You run your favorite emulator again. You would like to run the same as me because a voice in your head tells you that I've probably got an emulator that can dump the RAM2. The voice in your head is so annoying that you just missed something while playing, and your Pokémon fainted. You look around the menus: your emulator got a "Savestate" feature that allows you to restore your game as it was a few minutes ago. You click on "Load Savestate", and the game goes back to its previous state, restoring all the emulated parts of the GameBoy. A lightbulb goes on in your head, and you thank the voice for helping you find a solution. As the voice confirms the pleasure was all hers, you make many savestates, and add the value to look for next to each of them. You add new lines to your whiteboard:
SAVESTATE_1 => 19 HP => 0x13
SAVESTATE_2 => 15 HP => 0x0F
SAVESTATE_3 => 11 HP => 0x0B
SAVESTATE_4 => 7 HP => 0x07
SAVESTATE_5 => 3 HP => 0x03
SAVESTATE_6 => 19 HP => 0x13
That should be enough! Now, how about writing some code?
Attention!
Each emulator got their own savestate format. While the following method SHOULD work with any format, if your emulator of choice compresses the savestates, it may be impossible to find consistency in the bytes addresses.
But if you ever wrote a GameBoy emulator, thank you for your service!
I do, and I've been using it since around 1999!