summaryrefslogtreecommitdiff
path: root/docs/bugs_and_glitches.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/bugs_and_glitches.md')
-rw-r--r--docs/bugs_and_glitches.md762
1 files changed, 594 insertions, 168 deletions
diff --git a/docs/bugs_and_glitches.md b/docs/bugs_and_glitches.md
index 287b0324c..b38ec12ee 100644
--- a/docs/bugs_and_glitches.md
+++ b/docs/bugs_and_glitches.md
@@ -1,11 +1,62 @@
# Bugs and Glitches
+## Contents
+
+- [Thick Club and Light Ball can decrease damage done with boosted (Special) Attack](#thick-club-and-light-ball-can-decrease-damage-done-with-boosted-special-attack)
+- [Metal Powder can increase damage taken with boosted (Special) Defense](#metal-powder-can-increase-damage-taken-with-boosted-special-defense)
+- [Belly Drum sharply boosts Attack even with under 50% HP](#belly-drum-sharply-boosts-attack-even-with-under-50-hp)
+- [Moves that lower Defense can do so after breaking a Substitute](#moves-that-lower-defense-can-do-so-after-breaking-a-substitute)
+- [Counter and Mirror Coat still work if the opponent uses an item](#counter-and-mirror-coat-still-work-if-the-opponent-uses-an-item)
+- [A Disabled but PP Up–enhanced move may not trigger Struggle](#a-disabled-but-pp-upenhanced-move-may-not-trigger-struggle)
+- [A Pokémon that fainted from Pursuit will have its old status condition when revived](#a-pokémon-that-fainted-from-pursuit-will-have-its-old-status-condition-when-revived)
+- [Lock-On and Mind Reader don't always bypass Fly and Dig](#lock-on-and-mind-reader-dont-always-bypass-fly-and-dig)
+- [Beat Up can desynchronize link battles](#beat-up-can-desynchronize-link-battles)
+- [Present damage is incorrect in link battles](#present-damage-is-incorrect-in-link-battles)
+- ["Smart" AI encourages Mean Look if its own Pokémon is badly poisoned](#smart-ai-encourages-mean-look-if-its-own-pokémon-is-badly-poisoned)
+- [AI makes a false assumption about `CheckTypeMatchup`](#ai-makes-a-false-assumption-about-checktypematchup)
+- [NPC use of Full Heal or Full Restore does not cure Nightmare status](#npc-use-of-full-heal-or-full-restore-does-not-cure-nightmare-status)
+- [HP bar animation is slow for high HP](#hp-bar-animation-is-slow-for-high-hp)
+- [HP bar animation off-by-one error for low HP](#hp-bar-animation-off-by-one-error-for-low-hp)
+- [Experience underflow for level 1 Pokémon with Medium-Slow growth rate](#experience-underflow-for-level-1-pokémon-with-medium-slow-growth-rate)
+- [Five-digit experience gain is printed incorrectly](#five-digit-experience-gain-is-printed-incorrectly)
+- [BRN/PSN/PAR do not affect catch rate](#brnpsnpar-do-not-affect-catch-rate)
+- [Moon Ball does not boost catch rate](#moon-ball-does-not-boost-catch-rate)
+- [Love Ball boosts catch rate for the wrong gender](#love-ball-boosts-catch-rate-for-the-wrong-gender)
+- [Fast Ball only boosts catch rate for three Pokémon](#fast-ball-only-boosts-catch-rate-for-three-pokémon)
+- [Dragon Scale, not Dragon Fang, boosts Dragon-type moves](#dragon-scale-not-dragon-fang-boosts-dragon-type-moves)
+- [Daisy's grooming doesn't always increase happiness](#daisys-grooming-doesnt-always-increase-happiness)
+- [Magikarp in Lake of Rage are shorter, not longer](#magikarp-in-lake-of-rage-are-shorter-not-longer)
+- [Magikarp lengths can be miscalculated](#magikarp-lengths-can-be-miscalculated)
+- [Battle transitions fail to account for the enemy's level](#battle-transitions-fail-to-account-for-the-enemys-level)
+- [Slot machine payout sound effects cut each other off](#slot-machine-payout-sound-effects-cut-each-other-off)
+- [Team Rocket battle music is not used for Executives or Scientists](#team-rocket-battle-music-is-not-used-for-executives-or-scientists)
+- [No bump noise if standing on tile `$3E`](#no-bump-noise-if-standing-on-tile-3e)
+- [Playing Entei's Pokédex cry can distort Raikou's and Suicune's](#playing-enteis-pokédex-cry-can-distort-raikous-and-suicunes)
+- [In-battle “`…`” ellipsis is too high](#in-battle--ellipsis-is-too-high)
+- [Two tiles in the `port` tileset are drawn incorrectly](#two-tiles-in-the-port-tileset-are-drawn-incorrectly)
+- [`LoadMetatiles` wraps around past 128 blocks](#loadmetatiles-wraps-around-past-128-blocks)
+- [Surfing directly across a map connection does not load the new map](#surfing-directly-across-a-map-connection-does-not-load-the-new-map)
+- [`Function6ec1` does not correctly limit object movement](#function6ec1-does-not-correctly-limit-object-movement)
+- [`CheckOwnMon` only checks the first five letters of OT names](#checkownmon-only-checks-the-first-five-letters-of-ot-names)
+- [Catching a Transformed Pokémon always catches a Ditto](#catching-a-transformed-pokémon-always-catches-a-ditto)
+- [Using a Park Ball in normal battles has a corrupt animation](#using-a-park-ball-in-normal-battles-has-a-corrupt-animation)
+- [`HELD_CATCH_CHANCE` has no effect](#held_catch_chance-has-no-effect)
+- [Only the first three `EvosAttacks` evolution entries can have Stone compatibility reported correctly](#only-the-first-three-evosattacks-evolution-entries-can-have-stone-compatibility-reported-correctly)
+- [`ScriptCall` can overflow `wScriptStack` and crash](#scriptcall-can-overflow-wscriptstack-and-crash)
+- [`LoadSpriteGFX` does not limit the capacity of `UsedSprites`](#loadspritegfx-does-not-limit-the-capacity-of-usedsprites)
+- [`ChooseWildEncounter` doesn't really validate the wild Pokémon species](#choosewildencounter-doesnt-really-validate-the-wild-pokémon-species)
+- [`TryObjectEvent` arbitrary code execution](#tryobjectevent-arbitrary-code-execution)
+- [`Special_CheckBugContestContestantFlag` can read beyond its data table](#special_checkbugcontestcontestantflag-can-read-beyond-its-data-table)
+- [`ClearWRAM` only clears WRAM bank 1](#clearwram-only-clears-wram-bank-1)
+- [`GetForestTreeFrame` works, but it's still bad](#getforesttreeframe-works-but-its-still-bad)
+
+
## Thick Club and Light Ball can decrease damage done with boosted (Special) Attack
([Video](https://www.youtube.com/watch?v=rGqu3d3pdok&t=450))
-This is a bug with `SpeciesItemBoost` in [battle/effect_commands.asm](battle/effect_commands.asm):
+This is a bug with `SpeciesItemBoost` in [battle/effect_commands.asm](/battle/effect_commands.asm):
```asm
; Double the stat
@@ -39,7 +90,7 @@ This is a bug with `SpeciesItemBoost` in [battle/effect_commands.asm](battle/eff
([Video](https://www.youtube.com/watch?v=rGqu3d3pdok&t=450))
-This is a bug with `DittoMetalPowder` in [battle/effect_commands.asm](battle/effect_commands.asm):
+This is a bug with `DittoMetalPowder` in [battle/effect_commands.asm](/battle/effect_commands.asm):
```asm
ld a, c
@@ -95,7 +146,7 @@ This is a bug with `DittoMetalPowder` in [battle/effect_commands.asm](battle/eff
([Video](https://www.youtube.com/watch?v=zuCLMikWo4Y))
-This is a bug with `BattleCommand_BellyDrum` in [battle/effect_commands.asm](battle/effect_commands.asm):
+This is a bug with `BattleCommand_BellyDrum` in [battle/effect_commands.asm](/battle/effect_commands.asm):
```asm
BattleCommand_BellyDrum: ; 37c1a
@@ -129,11 +180,256 @@ BattleCommand_BellyDrum: ; 37c1a
```
+## Moves that lower Defense can do so after breaking a Substitute
+
+([Video](https://www.youtube.com/watch?v=OGwKPRJLaaI))
+
+This bug affects Acid, Iron Tail, and Rock Smash.
+
+This is a bug with `DefenseDownHit` in [battle/moves/move_effects.asm](/battle/moves/move_effects.asm):
+
+```asm
+DefenseDownHit:
+ checkobedience
+ usedmovetext
+ doturn
+ critical
+ damagestats
+ damagecalc
+ stab
+ damagevariation
+ checkhit
+ effectchance
+ hittarget
+ failuretext
+ checkfaint
+ criticaltext
+ supereffectivetext
+ checkdestinybond
+ buildopponentrage
+ effectchance ; bug: duplicate effectchance shouldn't be here
+ defensedown
+ statdownmessage
+ endmove
+```
+
+**Fix:** Delete the second `effectchance`.
+
+
+## Counter and Mirror Coat still work if the opponent uses an item
+
+([Video](https://www.youtube.com/watch?v=uRYyzKRatFk))
+
+*To do:* Identify specific code causing this bug and fix it.
+
+
+## A Disabled but PP Up–enhanced move may not trigger Struggle
+
+([Video](https://www.youtube.com/watch?v=1v9x4SgMggs))
+
+This is a bug with `CheckPlayerHasUsableMoves` in [battle/core.asm](/battle/core.asm):
+
+```asm
+.done
+ ; Bug: this will result in a move with PP Up confusing the game.
+ ; Replace with "and $3f" to fix.
+ and a
+ ret nz
+
+.force_struggle
+ ld hl, BattleText_PkmnHasNoMovesLeft
+ call StdBattleTextBox
+ ld c, 60
+ call DelayFrames
+ xor a
+ ret
+```
+
+**Fix:** Change `and a` to `and $3f`.
+
+
+## A Pokémon that fainted from Pursuit will have its old status condition when revived
+
+([Video](https://www.youtube.com/watch?v=tiRvw-Nb2ME))
+
+*To do:* Identify specific code causing this bug and fix it.
+
+
+## Lock-On and Mind Reader don't always bypass Fly and Dig
+
+This bug affects Attract, Curse, Foresight, Mean Look, Mimic, Nightmare, Spider Web, Transform, and stat-lowering effects of moves like String Shot or Bubble during the semi-invulnerable turn of Fly or Dig.
+
+This is a bug with `CheckHiddenOpponent` in [battle/effect_commands.asm](/battle/effect_commands.asm):
+
+```asm
+CheckHiddenOpponent: ; 37daa
+; BUG: This routine should account for Lock-On and Mind Reader.
+ ld a, BATTLE_VARS_SUBSTATUS3_OPP
+ call GetBattleVar
+ and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND
+ ret
+```
+
+*To do:* Fix this bug.
+
+
+## Beat Up can desynchronize link battles
+
+([Video](https://www.youtube.com/watch?v=202-iAsrIa8))
+
+This is a bug with `BattleCommand_BeatUp` in [battle/effect_commands.asm](/battle/effect_commands.asm):
+
+```asm
+.got_mon
+ ld a, [wd002]
+ ld hl, PartyMonNicknames
+ call GetNick
+ ld a, MON_HP
+ call GetBeatupMonLocation
+ ld a, [hli]
+ or [hl]
+ jp z, .beatup_fail ; fainted
+ ld a, [wd002]
+ ld c, a
+ ld a, [CurBattleMon]
+ ; BUG: this can desynchronize link battles
+ ; Change "cp [hl]" to "cp c" to fix
+ cp [hl]
+ ld hl, BattleMonStatus
+ jr z, .active_mon
+ ld a, MON_STATUS
+ call GetBeatupMonLocation
+.active_mon
+ ld a, [hl]
+ and a
+ jp nz, .beatup_fail
+```
+
+**Fix:** Change `cp [hl]` to `cp c`.
+
+
+## Present damage is incorrect in link battles
+
+([Video](https://www.youtube.com/watch?v=XJaQoKtrEuw))
+
+This bug existed for all battles in Gold and Silver, and was only fixed for single-player battles in Crystal to preserve link compatibility.
+
+This is a bug with `BattleCommand_Present` in [battle/effects/present.asm](/battle/effects/present.asm):
+
+```asm
+BattleCommand_Present: ; 37874
+; present
+
+ ld a, [wLinkMode]
+ cp LINK_COLOSSEUM
+ jr z, .colosseum_skippush
+ push bc
+ push de
+.colosseum_skippush
+
+ call BattleCommand_Stab
+
+ ld a, [wLinkMode]
+ cp LINK_COLOSSEUM
+ jr z, .colosseum_skippop
+ pop de
+ pop bc
+.colosseum_skippop
+```
+
+**Fix:**
+
+```asm
+BattleCommand_Present: ; 37874
+; present
+
+ push bc
+ push de
+ call BattleCommand_Stab
+ pop de
+ pop bc
+```
+
+
+## "Smart" AI encourages Mean Look if its own Pokémon is badly poisoned
+
+([Video](https://www.youtube.com/watch?v=cygMO-zHTls))
+
+This is a bug with `AI_Smart_MeanLook` in [battle/ai/scoring.asm](/battle/ai/scoring.asm):
+
+```asm
+; 80% chance to greatly encourage this move if the enemy is badly poisoned (buggy).
+; Should check PlayerSubStatus5 instead.
+ ld a, [EnemySubStatus5]
+ bit SUBSTATUS_TOXIC, a
+ jr nz, .asm_38e26
+```
+
+**Fix:** Change `EnemySubStatus5` to `PlayerSubStatus5`.
+
+
+## AI makes a false assumption about `CheckTypeMatchup`
+
+In [battle/effect_commands.asm](/battle/effect_commands.asm):
+
+```asm
+BattleCheckTypeMatchup: ; 347c8
+ ld hl, EnemyMonType1
+ ld a, [hBattleTurn]
+ and a
+ jr z, CheckTypeMatchup
+ ld hl, BattleMonType1
+CheckTypeMatchup: ; 347d3
+; There is an incorrect assumption about this function made in the AI related code: when
+; the AI calls CheckTypeMatchup (not BattleCheckTypeMatchup), it assumes that placing the
+; offensive type in a will make this function do the right thing. Since a is overwritten,
+; this assumption is incorrect. A simple fix would be to load the move type for the
+; current move into a in BattleCheckTypeMatchup, before falling through, which is
+; consistent with how the rest of the code assumes this code works like.
+ push hl
+ push de
+ push bc
+ ld a, BATTLE_VARS_MOVE_TYPE
+ call GetBattleVar
+ ld d, a
+```
+
+*To do:* Fix this bug.
+
+
+## NPC use of Full Heal or Full Restore does not cure Nightmare status
+
+([Video](https://www.youtube.com/watch?v=rGqu3d3pdok&t=322))
+
+This is a bug with `AI_HealStatus` in [battle/ai/items.asm](/battle/ai/items.asm):
+
+```asm
+AI_HealStatus: ; 384e0
+ ld a, [CurOTMon]
+ ld hl, OTPartyMon1Status
+ ld bc, PARTYMON_STRUCT_LENGTH
+ call AddNTimes
+ xor a
+ ld [hl], a
+ ld [EnemyMonStatus], a
+ ; Bug: this should reset SUBSTATUS_NIGHTMARE too
+ ; Uncomment the lines below to fix
+ ; ld hl, EnemySubStatus1
+ ; res SUBSTATUS_NIGHTMARE, [hl]
+ ld hl, EnemySubStatus5
+ res SUBSTATUS_TOXIC, [hl]
+ ret
+; 384f7
+```
+
+**Fix:** Uncomment `ld hl, EnemySubStatus1` and `res SUBSTATUS_NIGHTMARE, [hl]`.
+
+
## HP bar animation is slow for high HP
([Video](https://www.youtube.com/watch?v=SE-BfsFgZVM))
-This is a bug with `LongAnim_UpdateVariables` in [engine/anim_hp_bar.asm](engine/anim_hp_bar.asm):
+This is a bug with `LongAnim_UpdateVariables` in [engine/anim_hp_bar.asm](/engine/anim_hp_bar.asm):
```asm
; This routine is buggy. The result from ComputeHPBarPixels is stored
@@ -161,7 +457,7 @@ This is a bug with `LongAnim_UpdateVariables` in [engine/anim_hp_bar.asm](engine
([Video](https://www.youtube.com/watch?v=9KyNVIZxJvI))
-This is a bug with `ShortHPBar_CalcPixelFrame` in [engine/anim_hp_bar.asm](engine/anim_hp_bar.asm):
+This is a bug with `ShortHPBar_CalcPixelFrame` in [engine/anim_hp_bar.asm](/engine/anim_hp_bar.asm):
```asm
ld b, 0
@@ -189,7 +485,7 @@ This is a bug with `ShortHPBar_CalcPixelFrame` in [engine/anim_hp_bar.asm](engin
This can bring Pokémon straight from level 1 to 100 by gaining just a few experience points.
-This is a bug with `CalcExpAtLevel` in [main.asm](main.asm):
+This is a bug with `CalcExpAtLevel` in [main.asm](/main.asm):
```asm
CalcExpAtLevel: ; 50e47
@@ -235,7 +531,7 @@ CalcExpAtLevel: ; 50e47
([Video](https://www.youtube.com/watch?v=o54VjpAEoO8))
-This is a bug with `Text_ABoostedStringBuffer2ExpPoints` and `Text_StringBuffer2ExpPoints` in [text/common_2.asm](text/common_2.asm):
+This is a bug with `Text_ABoostedStringBuffer2ExpPoints` and `Text_StringBuffer2ExpPoints` in [text/common_2.asm](/text/common_2.asm):
```asm
Text_ABoostedStringBuffer2ExpPoints::
@@ -257,129 +553,9 @@ Text_StringBuffer2ExpPoints::
**Fix:** Change both `deciram StringBuffer2, 2, 4` to `deciram StringBuffer2, 2, 5`.
-## NPC use of Full Heal or Full Restore does not cure Nightmare status
-
-([Video](https://www.youtube.com/watch?v=rGqu3d3pdok&t=322))
-
-This is a bug with `AI_HealStatus` in [battle/ai/items.asm](battle/ai/items.asm):
-
-```asm
-AI_HealStatus: ; 384e0
- ld a, [CurOTMon]
- ld hl, OTPartyMon1Status
- ld bc, PARTYMON_STRUCT_LENGTH
- call AddNTimes
- xor a
- ld [hl], a
- ld [EnemyMonStatus], a
- ; Bug: this should reset SUBSTATUS_NIGHTMARE too
- ; Uncomment the lines below to fix
- ; ld hl, EnemySubStatus1
- ; res SUBSTATUS_NIGHTMARE, [hl]
- ld hl, EnemySubStatus5
- res SUBSTATUS_TOXIC, [hl]
- ret
-; 384f7
-```
-
-**Fix:** Uncomment `ld hl, EnemySubStatus1` and `res SUBSTATUS_NIGHTMARE, [hl]`.
-
-
-## "Smart" AI encourages Mean Look if its own Pokémon is badly poisoned
-
-([Video](https://www.youtube.com/watch?v=cygMO-zHTls))
-
-This is a bug with `AI_Smart_MeanLook` in [battle/ai/scoring.asm](battle/ai/scoring.asm):
-
-```asm
-; 80% chance to greatly encourage this move if the enemy is badly poisoned (buggy).
-; Should check PlayerSubStatus5 instead.
- ld a, [EnemySubStatus5]
- bit SUBSTATUS_TOXIC, a
- jr nz, .asm_38e26
-```
-
-**Fix:** Change `EnemySubStatus5` to `PlayerSubStatus5`.
-
-
-## A Disabled, PP Up–enhanced move may not trigger automatic Struggling
-
-([Video](https://www.youtube.com/watch?v=1v9x4SgMggs))
-
-This is a bug with `CheckPlayerHasUsableMoves` in [battle/core.asm](battle/core.asm):
-
-```asm
-.done
- ; Bug: this will result in a move with PP Up confusing the game.
- ; Replace with "and $3f" to fix.
- and a
- ret nz
-
-.force_struggle
- ld hl, BattleText_PkmnHasNoMovesLeft
- call StdBattleTextBox
- ld c, 60
- call DelayFrames
- xor a
- ret
-```
-
-**Fix:** Change `and a` to `and $3f`.
-
-
-## Counter and Mirror Coat still work if the opponent uses an item
-
-([Video](https://www.youtube.com/watch?v=uRYyzKRatFk))
-
-*To do:* Identify specific code causing this bug and fix it.
-
-
-## Present damage is incorrect in link battles
-
-([Video](https://www.youtube.com/watch?v=XJaQoKtrEuw))
-
-This bug existed for all battles in Gold and Silver, and was only fixed for single-player battles in Crystal to preserve link compatibility.
-
-This is a bug with `BattleCommand_Present` in [battle/effects/present.asm](battle/effects/present.asm):
-
-```asm
-BattleCommand_Present: ; 37874
-; present
-
- ld a, [wLinkMode]
- cp LINK_COLOSSEUM
- jr z, .colosseum_skippush
- push bc
- push de
-.colosseum_skippush
-
- call BattleCommand_Stab
-
- ld a, [wLinkMode]
- cp LINK_COLOSSEUM
- jr z, .colosseum_skippop
- pop de
- pop bc
-.colosseum_skippop
-```
-
-**Fix:**
-
-```asm
-BattleCommand_Present: ; 37874
-; present
-
- push bc
- push de
- call BattleCommand_Stab
- pop de
- pop bc
-```
-
-
## BRN/PSN/PAR do not affect catch rate
-This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm):
+This is a bug with `PokeBall` in [items/item_effects.asm](/items/item_effects.asm):
```asm
.statuscheck
@@ -411,7 +587,7 @@ This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm
## Moon Ball does not boost catch rate
-This is a bug with `MoonBallMultiplier` in [items/item_effects.asm](items/item_effects.asm):
+This is a bug with `MoonBallMultiplier` in [items/item_effects.asm](/items/item_effects.asm):
```asm
MoonBallMultiplier:
@@ -437,7 +613,7 @@ MoonBallMultiplier:
## Love Ball boosts catch rate for the wrong gender
-This is a bug with `LoveBallMultiplier` in [items/item_effects.asm](items/item_effects.asm):
+This is a bug with `LoveBallMultiplier` in [items/item_effects.asm](/items/item_effects.asm):
```asm
LoveBallMultiplier:
@@ -459,7 +635,7 @@ LoveBallMultiplier:
## Fast Ball only boosts catch rate for three Pokémon
-This is a bug with `FastBallMultiplier` in [items/item_effects.asm](items/item_effects.asm):
+This is a bug with `FastBallMultiplier` in [items/item_effects.asm](/items/item_effects.asm):
```asm
FastBallMultiplier:
@@ -483,26 +659,9 @@ FastBallMultiplier:
**Fix:** Change `jr nz, .next` to `jr nz, .loop`.
-## Friend Ball catches sent to the PC overwrite the wrong Pokémon's happiness
-
-This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm):
-
-```asm
- ld a, [CurItem]
- cp FRIEND_BALL
- jr nz, .SkipBoxMonFriendBall
- ; Bug: overwrites the happiness of the first mon in the box!
- ld a, FRIEND_BALL_HAPPINESS
- ld [sBoxMon1Happiness], a
-.SkipBoxMonFriendBall:
-```
-
-`sBoxMon1Happiness` is written *before* the Friend Ball Pokémon is deposited.
-
-
## Dragon Scale, not Dragon Fang, boosts Dragon-type moves
-This is a bug with `ItemAttributes` in [items/item_attributes.asm](items/item_attributes.asm):
+This is a bug with `ItemAttributes` in [items/item_attributes.asm](/items/item_attributes.asm):
```asm
; DRAGON FANG
@@ -517,9 +676,9 @@ This is a bug with `ItemAttributes` in [items/item_attributes.asm](items/item_at
**Fix:** Move `HELD_DRAGON_BOOST` to the `DRAGON FANG` attributes and `0` to `DRAGON SCALE`.
-## Daisy's massages don't always increase happiness
+## Daisy's grooming doesn't always increase happiness
-This is a bug with `MassageOrHaircut` in [event/special.asm](event/special.asm):
+This is a bug with `MassageOrHaircut` in [event/special.asm](/event/special.asm):
```asm
; Bug: Subtracting $ff from $ff fails to set c.
@@ -568,7 +727,7 @@ Data_DaisyMassage: ; 746b
## Magikarp in Lake of Rage are shorter, not longer
-This is a bug with `LoadEnemyMon.CheckMagikarpArea` in [battle/core.asm](battle/core.asm):
+This is a bug with `LoadEnemyMon.CheckMagikarpArea` in [battle/core.asm](/battle/core.asm):
```asm
.CheckMagikarpArea:
@@ -592,11 +751,32 @@ This is a bug with `LoadEnemyMon.CheckMagikarpArea` in [battle/core.asm](battle/
**Fix:** Change both `jr z, .Happiness` to `jr nz, .Happiness`.
+## Magikarp lengths can be miscalculated
+
+This is a bug with `CalcMagikarpLength.BCLessThanDE` in [event/magikarp.asm](/event/magikarp.asm):
+
+```asm
+.BCLessThanDE: ; fbc9a
+; Intention: Return bc < de.
+; Reality: Return b < d.
+ ld a, b
+ cp d
+ ret c
+ ret nc ; whoops
+ ld a, c
+ cp e
+ ret
+; fbca1
+```
+
+**Fix:** Delete `ret nc`.
+
+
## Battle transitions fail to account for the enemy's level
([Video](https://www.youtube.com/watch?v=eij_1060SMc))
-This is a bug with `StartTrainerBattle_DetermineWhichAnimation` in [engine/battle_start.asm](engine/battle_start.asm):
+This is a bug with `StartTrainerBattle_DetermineWhichAnimation` in [engine/battle_start.asm](/engine/battle_start.asm):
```asm
StartTrainerBattle_DetermineWhichAnimation: ; 8c365 (23:4365)
@@ -637,9 +817,61 @@ StartTrainerBattle_DetermineWhichAnimation: ; 8c365 (23:4365)
*To do:* Fix this bug.
+## Slot machine payout sound effects cut each other off
+
+([Video](https://www.youtube.com/watch?v=ojq3xqfRF6I))
+
+This is a bug with `Slots_PayoutAnim` in [engine/slot_machine.asm](/engine/slot_machine.asm):
+
+```asm
+.okay
+ ld [hl], e
+ dec hl
+ ld [hl], d
+ ld a, [wcf64]
+ and $7
+ ret z ; ret nz would be more appropriate
+ ld de, SFX_GET_COIN_FROM_SLOTS
+ call PlaySFX
+ ret
+```
+
+**Fix:** Change `ret z` to `ret nz`.
+
+
+## Team Rocket battle music is not used for Executives or Scientists
+
+This is a bug with `PlayBattleMusic` in [main.asm](/main.asm):
+
+```asm
+ ; really, they should have included admins and scientists here too...
+ ld de, MUSIC_ROCKET_BATTLE
+ cp GRUNTM
+ jr z, .done
+ cp GRUNTF
+ jr z, .done
+```
+
+**Fix:**
+
+```asm
+ ld de, MUSIC_ROCKET_BATTLE
+ cp GRUNTM
+ jr z, .done
+ cp GRUNTF
+ jr z, .done
+ cp EXECUTIVEM
+ jr z, .done
+ cp EXECUTIVEF
+ jr z, .done
+ cp SCIENTIST
+ jr z, .done
+```
+
+
## No bump noise if standing on tile `$3E`
-This is a bug with `DoPlayerMovement.CheckWarp` in [engine/player_movement.asm](engine/player_movement.asm):
+This is a bug with `DoPlayerMovement.CheckWarp` in [engine/player_movement.asm](/engine/player_movement.asm):
```asm
; Bug: Since no case is made for STANDING here, it will check
@@ -648,6 +880,8 @@ This is a bug with `DoPlayerMovement.CheckWarp` in [engine/player_movement.asm](
; making bumps silent.
ld a, [WalkingDirection]
+ ; cp STANDING
+ ; jr z, .not_warp
ld e, a
ld d, 0
ld hl, .EdgeWarps
@@ -659,6 +893,7 @@ This is a bug with `DoPlayerMovement.CheckWarp` in [engine/player_movement.asm](
ld a, 1
ld [wd041], a
ld a, [WalkingDirection]
+ ; This is in the wrong place.
cp STANDING
jr z, .not_warp
```
@@ -683,9 +918,60 @@ This is a bug with `DoPlayerMovement.CheckWarp` in [engine/player_movement.asm](
```
-## `LoadMetatiles` wrap around past 128 blocks
+## Playing Entei's Pokédex cry can distort Raikou's and Suicune's
-[home/map.asm](home/map.asm):
+([Video](https://www.youtube.com/watch?v=z305e4sIO24))
+
+The exact cause is unknown, but a workaround exists for `DexEntryScreen_MenuActionJumptable.Cry` in [engine/pokedex.asm](/engine/pokedex.asm):
+
+```asm
+.Cry: ; 40340
+ call Pokedex_GetSelectedMon
+ ld a, [wd265]
+ call GetCryIndex
+ ld e, c
+ ld d, b
+ call PlayCryHeader
+ ret
+```
+
+**Workaround:**
+
+```asm
+.Cry: ; 40340
+ ld a, [CurPartySpecies]
+ call PlayCry
+ ret
+```
+
+
+## In-battle “`…`” ellipsis is too high
+
+This is a mistake with the “`…`” tile in [gfx/battle/hp_exp_bar_border.png](/gfx/battle/hp_exp_bar_border.png):
+
+![image](/docs/images/hp_exp_bar_border.png)
+
+**Fix:** Lower the ellipsis by two pixels:
+
+![image](/docs/images/hp_exp_bar_border_fix.png)
+
+
+## Two tiles in the `port` tileset are drawn incorrectly
+
+This is a mistake with the left-hand warp carpet corner tiles in [gfx/tilesets/port.png](/gfx/tilesets/port.png):
+
+![image](/docs/images/port.png)
+
+**Fix:** Adjust them to match the right-hand corner tiles:
+
+![image](/docs/images/port_fix.png)
+
+
+## `LoadMetatiles` wraps around past 128 blocks
+
+This bug prevents you from using blocksets with more than 128 blocks.
+
+In [home/map.asm](/home/map.asm):
```asm
; Set hl to the address of the current metatile data ([TilesetBlocksAddress] + (a) tiles).
@@ -716,13 +1002,29 @@ This is a bug with `DoPlayerMovement.CheckWarp` in [engine/player_movement.asm](
*To do:* Identify specific code causing this bug and fix it.
+## `Function6ec1` does not correctly limit object movement
+
+This bug is why the Lapras in Union Cave, which uses `SPRITEMOVEDATA_LAPRAS`, is not restricted by its `1, 1` movement radius.
+
+In [engine/npc_movement.asm](/engine/npc_movement.asm):
+
+```asm
+ ld hl, OBJECT_FLAGS1
+ add hl, bc
+ bit 4, [hl] ; lost, uncomment next line to fix
+; jr nz, .resume
+```
+
+**Fix:** Uncomment `jr nz, .resume`.
+
+
## `CheckOwnMon` only checks the first five letters of OT names
([Video](https://www.youtube.com/watch?v=GVTTmReM4nQ))
This bug can allow you to talk to Eusine in Celadon City and encounter Ho-Oh with only traded legendary beasts.
-[engine/search.asm](engine/search.asm):
+In [engine/search.asm](/engine/search.asm):
```asm
; check OT
@@ -756,9 +1058,108 @@ endr
**Fix:** Change `rept NAME_LENGTH_JAPANESE +- 2` to `rept PLAYER_NAME_LENGTH +- 2`.
+## Catching a Transformed Pokémon always catches a Ditto
+
+This bug can affect Mew or Pokémon other than Ditto that used Transform via Mirror Move or Sketch.
+
+This is a bug with `PokeBall` in [items/item_effects.asm](/items/item_effects.asm):
+
+```asm
+ ld hl, EnemySubStatus5
+ ld a, [hl]
+ push af
+ set SUBSTATUS_TRANSFORMED, [hl]
+
+; This code is buggy. Any wild Pokémon that has Transformed will be
+; caught as a Ditto, even if it was something else like Mew.
+; To fix, do not set [TempEnemyMonSpecies] to DITTO.
+ bit SUBSTATUS_TRANSFORMED, a
+ jr nz, .ditto
+ jr .not_ditto
+
+.ditto
+ ld a, DITTO
+ ld [TempEnemyMonSpecies], a
+ jr .load_data
+
+.not_ditto
+ set SUBSTATUS_TRANSFORMED, [hl]
+ ld hl, wEnemyBackupDVs
+ ld a, [EnemyMonDVs]
+ ld [hli], a
+ ld a, [EnemyMonDVs + 1]
+ ld [hl], a
+
+.load_data
+ ld a, [TempEnemyMonSpecies]
+ ld [CurPartySpecies], a
+ ld a, [EnemyMonLevel]
+ ld [CurPartyLevel], a
+ callba LoadEnemyMon
+
+ pop af
+ ld [EnemySubStatus5], a
+```
+
+**Fix:**
+
+```asm
+ ld hl, EnemySubStatus5
+ ld a, [hl]
+ push af
+ set SUBSTATUS_TRANSFORMED, [hl]
+
+ bit SUBSTATUS_TRANSFORMED, a
+ jr nz, .load_data
+
+ ld hl, wEnemyBackupDVs
+ ld a, [EnemyMonDVs]
+ ld [hli], a
+ ld a, [EnemyMonDVs + 1]
+ ld [hl], a
+
+.load_data
+ ld a, [TempEnemyMonSpecies]
+ ld [CurPartySpecies], a
+ ld a, [EnemyMonLevel]
+ ld [CurPartyLevel], a
+ callba LoadEnemyMon
+
+ pop af
+ ld [EnemySubStatus5], a
+```
+
+
+## Using a Park Ball in normal battles has a corrupt animation
+
+([Video](https://www.youtube.com/watch?v=v1ErZdLCIyU))
+
+This is a bug with `ParkBall` in [items/item_effects.asm](/items/item_effects.asm):
+
+```asm
+.room_in_party
+ xor a
+ ld [wWildMon], a
+ ld a, [CurItem]
+ cp PARK_BALL
+ call nz, ReturnToBattle_UseBall
+```
+
+**Fix:**
+
+```asm
+.room_in_party
+ xor a
+ ld [wWildMon], a
+ ld a, [BattleType]
+ cp BATTLETYPE_CONTEST
+ call nz, ReturnToBattle_UseBall
+```
+
+
## `HELD_CATCH_CHANCE` has no effect
-This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm):
+This is a bug with `PokeBall` in [items/item_effects.asm](/items/item_effects.asm):
```asm
; BUG: callba overwrites a,
@@ -780,9 +1181,32 @@ This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm
**Fix:** Uncomment `ld b, a`.
+## Only the first three `EvosAttacks` evolution entries can have Stone compatibility reported correctly
+
+This is a bug with `PlacePartyMonEvoStoneCompatibility.DetermineCompatibility` in [engine/party_menu.asm](/engine/party_menu.asm):
+
+```asm
+.DetermineCompatibility: ; 50268
+ ld de, StringBuffer1
+ ld a, BANK(EvosAttacksPointers)
+ ld bc, 2
+ call FarCopyBytes
+ ld hl, StringBuffer1
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld de, StringBuffer1
+ ld a, BANK(EvosAttacks)
+ ld bc, $a
+ call FarCopyBytes
+```
+
+**Fix:** Change `ld bc, $a` to `ld bc, $10` to support up to five Stone entries.
+
+
## `ScriptCall` can overflow `wScriptStack` and crash
-[engine/scripting.asm](engine/scripting.asm):
+In [engine/scripting.asm](/engine/scripting.asm):
```asm
ScriptCall:
@@ -820,12 +1244,12 @@ ScriptCall:
## `LoadSpriteGFX` does not limit the capacity of `UsedSprites`
-[engine/overworld.asm](engine/overworld.asm):
+In [engine/overworld.asm](/engine/overworld.asm):
```asm
LoadSpriteGFX: ; 14306
-; Bug: b is not preserved, so
-; it's useless as a next count.
+; Bug: b is not preserved, so it's useless as a next count.
+; Uncomment the lines below to fix.
ld hl, UsedSprites
ld b, SPRITE_GFX_LIST_CAPACITY
@@ -844,18 +1268,20 @@ LoadSpriteGFX: ; 14306
ret
.LoadSprite:
+ ; push bc
call GetSprite
+ ; pop bc
ld a, l
ret
; 1431e
```
-`GetSprite` modifies `b`. Surround it with `push bc`/`pop bc` to fix.
+**Fix:** Uncomment `push bc` and `pop bc`.
## `ChooseWildEncounter` doesn't really validate the wild Pokémon species
-[engine/wildmons.asm](engine/wildmons.asm):
+In [engine/wildmons.asm](/engine/wildmons.asm):
```asm
ChooseWildEncounter: ; 2a14f
@@ -894,7 +1320,7 @@ ValidateTempWildMonSpecies: ; 2a4a0
## `TryObjectEvent` arbitrary code execution
-[engine/events.asm](engine/events.asm):
+In [engine/events.asm](/engine/events.asm):
```asm
; Bug: If IsInArray returns nc, data at bc will be executed as code.
@@ -922,7 +1348,7 @@ ValidateTempWildMonSpecies: ; 2a4a0
## `Special_CheckBugContestContestantFlag` can read beyond its data table
-[event/bug_contest_2.asm](event/bug_contest_2.asm):
+In [event/bug_contest_2.asm](/event/bug_contest_2.asm):
```asm
Special_CheckBugContestContestantFlag: ; 139ed
@@ -960,7 +1386,7 @@ BugCatchingContestantEventFlagTable: ; 139fe
## `ClearWRAM` only clears WRAM bank 1
-[home/init.asm](home/init.asm):
+In [home/init.asm](/home/init.asm):
```asm
ClearWRAM:: ; 25a
@@ -988,7 +1414,7 @@ ClearWRAM:: ; 25a
## `GetForestTreeFrame` works, but it's still bad
-[tilesets/animations.asm](tilesets/animations.asm):
+In [tilesets/animations.asm](/tilesets/animations.asm):
```asm
GetForestTreeFrame: ; fc54c