summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorInfernoGear <32606575+InfernoGear@users.noreply.github.com>2021-03-31 20:18:09 -0500
committerInfernoGear <32606575+InfernoGear@users.noreply.github.com>2021-03-31 20:18:09 -0500
commit88aadd8ca17d9036f70ae74394a8307ba3e92511 (patch)
treec41673dbe05def2a656547f3ff00dde47d96dd1d
parent07ab98e12461eee13708893b6a1524008cb9ff81 (diff)
Learning GB ASM, figured this out the other day.
-rw-r--r--Fix-the-1-255-miss-bug.md50
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