diff options
author | InfernoGear <32606575+InfernoGear@users.noreply.github.com> | 2021-03-31 20:18:09 -0500 |
---|---|---|
committer | InfernoGear <32606575+InfernoGear@users.noreply.github.com> | 2021-03-31 20:18:09 -0500 |
commit | 88aadd8ca17d9036f70ae74394a8307ba3e92511 (patch) | |
tree | c41673dbe05def2a656547f3ff00dde47d96dd1d | |
parent | 07ab98e12461eee13708893b6a1524008cb9ff81 (diff) |
Learning GB ASM, figured this out the other day.
-rw-r--r-- | Fix-the-1-255-miss-bug.md | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/Fix-the-1-255-miss-bug.md b/Fix-the-1-255-miss-bug.md new file mode 100644 index 0000000..89e4836 --- /dev/null +++ b/Fix-the-1-255-miss-bug.md @@ -0,0 +1,50 @@ +In Generation I, due to a slight quirk of how the accuracy code works, there's a +1/255 chance of missing any move, meaning that 100% accuracy moves have a chance of 255/256 for hitting, or 99.609375%, and not 100%. + +This tutorial shows how Generation II fixes this issue. + +(Code backported from Pokémon Crystal.) + +## Contents +- [Skip if move accuracy is 100%](#1-skip-if-move-accuracy-is-100%) +- [Explaining the fix](#2-explaining-the-fix) + +## 1. Skip if move accuracy is 100% +In [engine/battle/core.asm](https://github.com/pret/pokered/blob/master/engine/battle/core.asm), we can go to the label `.doAccuracyCheck` to see the following: +` +.doAccuracyCheck +; if the random number generated is greater than or equal to the scaled accuracy, the move misses +; note that this means that even the highest accuracy is still just a 255/256 chance, not 100% + call BattleRandom + cp b + jr nc, .moveMissed + ret +` + +Here's where we insert the proper code. + +```diff +.doAccuracyCheck +; if the random number generated is greater than or equal to the scaled accuracy, the move misses +; note that this means that even the highest accuracy is still just a 255/256 chance, not 100% + ++ ; The following snippet is taken from Pokemon Crystal, it fixes the above bug. ++ ld a, b ++ cp $FF ; Is the value $FF? ++ jr z, .Hit ; If so, we need not calculate, just so we can fix this bug. + + call BattleRandom + cp b + jr nc, .moveMissed + ret +``` + +As you can see, we've added only 3 lines of code. This fixes this bug, Gen II style. Now, let's talk about what exactly this does. + +## 2. Explaining the fix +For anyone with GB Z80 experience, feel free to skip this part, but for anyone uninformed, I'll try my best to explain with my limited knowledge. + +`ld a, b` loads the contents of register b into register a. This is done because b holds the move accuracy of the Pokémon currently using the move. +`cp $FF` just compares a to $FF, technically by subtracting $FF from a. +`jr z, .Hit` jumps ahead to the label `.Hit` IF the Zero flag is set. Due to how cp works, this will be set if the compared value and a are equal. In other words... branch to .Hit if equal. Therefore, if move accuracy is $FF, therefore 100%, then it doesn't bother calculating if the move will miss: after all, the move's accuracy IS 100%. This occurs after other move accuracy calculations, so those will come into effect as well. + +Enjoy!
\ No newline at end of file |