Trying to figure out why a certain Pokemon Red/Blue glitch occurs. Why do the programmers use the sbc instruction here?

Viewed 121

I'm trying to understand a strange bug that happens in Pokemon Red/Blue where if you try using the move Recover when you're exactly 255 hp below your max HP, the move will fail.

The code I am looking at is a disassembly that can be found here. The specific code in question is under the .healEffect label.

I think I've figured out, code-wise, why this is happening. Let's say your max HP is 703, and you are currently at 448. The machine compares your HP values to make sure you aren't trying to heal at full HP. However, the programmers used the "cp" instruction, which is only for 8-bit numbers, cutting off the highest bit. I assume this was just simply programmer error.

703 = 00000010 10111111
448 = 00000001 11000000
Removing the highest bit, your max becomes 191 and current becomes 192. This isn't possible, so a carry is triggered.

Now where I am confused is why the sbc instruction is used. sbc is called, and the machine performs current HP - max HP - carry. Using the example above, this results in 0, meaning you're at full HP in the machine's eyes, and the move fails.

The cp instruction I can explain as just programmer error. But why on earth use sbc here? sbc is meant to be used for multi-word arithmetic, but HP is a 16-bit number. I'm struggling to think of a situation where sbc is called for in this situation.

Any ideas?

1 Answers

To check for equality you don't need the carry, you can simply check the two bytes separately. The carry is useful if you want to do "less/greater" which this code clearly intends to. As such the bug is the jp z which should be jp nc to mean "if you can subtract the max from the current without producing a carry that means current is at least as big as max so the operation is not allowed"

Related