2017-12-12 17:50:34 -08:00
# Bugs and Glitches
2017-12-12 17:15:07 -08:00
2017-12-28 08:50:02 -08:00
These are known bugs and glitches in the original Pokémon Crystal game: code that clearly does not work as intended, or that only works in limited circumstances but has the possibility to fail or crash.
2017-12-12 17:15:07 -08:00
2017-12-12 21:28:48 -08:00
## 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 )
2017-12-28 09:49:32 -08:00
- [Confusion damage is affected by type-boosting items and Explosion/Self-Destruct doubling ](#confusion-damage-is-affected-by-type-boosting-items-and-explosionself-destruct-doubling )
2017-12-14 13:28:16 -08:00
- [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 )
2017-12-14 18:45:35 -08:00
- [Lock-On and Mind Reader don't always bypass Fly and Dig ](#lock-on-and-mind-reader-dont-always-bypass-fly-and-dig )
2017-12-14 13:28:16 -08:00
- [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 )
2017-12-14 18:45:35 -08:00
- [AI makes a false assumption about `CheckTypeMatchup` ](#ai-makes-a-false-assumption-about-checktypematchup )
2017-12-14 13:28:16 -08:00
- [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 )
2017-12-12 21:28:48 -08:00
- [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 )
2017-12-17 16:48:04 -08:00
- [Daisy's grooming doesn't always increase happiness ](#daisys-grooming-doesnt-always-increase-happiness )
2017-12-12 21:28:48 -08:00
- [Magikarp in Lake of Rage are shorter, not longer ](#magikarp-in-lake-of-rage-are-shorter-not-longer )
2017-12-28 11:08:29 -08:00
- [Magikarp length limits have a unit conversion error ](#magikarp-length-limits-have-a-unit-conversion-error )
2017-12-14 22:01:57 -08:00
- [Magikarp lengths can be miscalculated ](#magikarp-lengths-can-be-miscalculated )
2017-12-12 21:28:48 -08:00
- [Battle transitions fail to account for the enemy's level ](#battle-transitions-fail-to-account-for-the-enemys-level )
2017-12-14 18:45:35 -08:00
- [Slot machine payout sound effects cut each other off ](#slot-machine-payout-sound-effects-cut-each-other-off )
2017-12-14 21:05:53 -08:00
- [Team Rocket battle music is not used for Executives or Scientists ](#team-rocket-battle-music-is-not-used-for-executives-or-scientists )
2017-12-12 21:28:48 -08:00
- [No bump noise if standing on tile `$3E` ](#no-bump-noise-if-standing-on-tile-3e )
2017-12-13 13:46:31 -08:00
- [Playing Entei's Pokédex cry can distort Raikou's and Suicune's ](#playing-enteis-pokédex-cry-can-distort-raikous-and-suicunes )
2017-12-22 14:52:34 -08:00
- [In-battle “`…`” ellipsis is too high ](#in-battle--ellipsis-is-too-high )
2017-12-22 14:59:50 -08:00
- [Two tiles in the `port` tileset are drawn incorrectly ](#two-tiles-in-the-port-tileset-are-drawn-incorrectly )
2017-12-13 13:46:31 -08:00
- [`LoadMetatiles` wraps around past 128 blocks ](#loadmetatiles-wraps-around-past-128-blocks )
2017-12-12 21:28:48 -08:00
- [Surfing directly across a map connection does not load the new map ](#surfing-directly-across-a-map-connection-does-not-load-the-new-map )
2017-12-21 08:43:41 -08:00
- [`Function6ec1` does not correctly limit object movement ](#function6ec1-does-not-correctly-limit-object-movement )
2017-12-12 21:28:48 -08:00
- [`CheckOwnMon` only checks the first five letters of OT names ](#checkownmon-only-checks-the-first-five-letters-of-ot-names )
2017-12-13 13:46:31 -08:00
- [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 )
2017-12-12 21:28:48 -08:00
- [`HELD_CATCH_CHANCE` has no effect ](#held_catch_chance-has-no-effect )
2017-12-13 13:46:31 -08:00
- [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 )
2017-12-12 21:28:48 -08:00
- [`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 )
2018-01-24 08:17:05 -08:00
- [`CheckBugContestContestantFlag` can read beyond its data table ](#checkbugcontestcontestantflag-can-read-beyond-its-data-table )
2017-12-12 21:28:48 -08:00
- [`ClearWRAM` only clears WRAM bank 1 ](#clearwram-only-clears-wram-bank-1 )
2017-12-12 19:58:20 -08:00
## Thick Club and Light Ball can decrease damage done with boosted (Special) Attack
2017-12-28 09:58:18 -08:00
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
2017-12-12 19:58:20 -08:00
([Video](https://www.youtube.com/watch?v=rGqu3d3pdok& t=450))
2017-12-26 14:47:05 -08:00
This is a bug with `SpeciesItemBoost` in [engine/battle/effect_commands.asm ](/engine/battle/effect_commands.asm ):
2017-12-12 19:58:20 -08:00
```asm
; Double the stat
sla l
rl h
ret
```
**Fix:**
```asm
; Double the stat
sla l
rl h
2017-12-25 10:40:10 -08:00
ld a, HIGH(MAX_STAT_VALUE)
2017-12-12 19:58:20 -08:00
cp h
jr c, .cap
2017-12-25 10:40:10 -08:00
ld a, LOW(MAX_STAT_VALUE)
2017-12-12 19:58:20 -08:00
cp l
ret nc
.cap
2017-12-25 10:40:10 -08:00
ld h, HIGH(MAX_STAT_VALUE)
ld l, LOW(MAX_STAT_VALUE)
2017-12-12 19:58:20 -08:00
ret
```
## Metal Powder can increase damage taken with boosted (Special) Defense
2017-12-28 09:58:18 -08:00
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
2017-12-12 19:58:20 -08:00
([Video](https://www.youtube.com/watch?v=rGqu3d3pdok& t=450))
2017-12-26 14:47:05 -08:00
This is a bug with `DittoMetalPowder` in [engine/battle/effect_commands.asm ](/engine/battle/effect_commands.asm ):
2017-12-12 19:58:20 -08:00
```asm
ld a, c
srl a
add c
ld c, a
ret nc
srl b
ld a, b
and a
jr nz, .done
inc b
.done
scf
rr c
ret
```
**Fix:**
```asm
ld a, c
srl a
add c
ld c, a
ret nc
srl b
ld a, b
and a
jr nz, .done
inc b
.done
scf
rr c
2017-12-25 10:40:10 -08:00
ld a, HIGH(MAX_STAT_VALUE)
2017-12-12 19:58:20 -08:00
cp b
jr c, .cap
2017-12-25 10:40:10 -08:00
ld a, LOW(MAX_STAT_VALUE)
2017-12-12 19:58:20 -08:00
cp c
ret nc
.cap
2017-12-25 10:40:10 -08:00
ld b, HIGH(MAX_STAT_VALUE)
ld c, LOW(MAX_STAT_VALUE)
2017-12-12 19:58:20 -08:00
ret
```
2017-12-12 17:15:07 -08:00
## Belly Drum sharply boosts Attack even with under 50% HP
2017-12-28 09:58:18 -08:00
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
2017-12-12 17:15:07 -08:00
([Video](https://www.youtube.com/watch?v=zuCLMikWo4Y))
2018-01-26 08:36:00 -08:00
This is a bug with `BattleCommand_BellyDrum` in [engine/battle/move_effects/belly_drum.asm ](/engine/battle/move_effects/belly_drum.asm ):
2017-12-12 17:15:07 -08:00
2017-12-12 19:58:20 -08:00
```asm
2017-12-12 17:15:07 -08:00
BattleCommand_BellyDrum: ; 37c1a
; bellydrum
; This command is buggy because it raises the user's attack
; before checking that it has enough HP to use the move.
; Swap the order of these two blocks to fix.
call BattleCommand_AttackUp2
2018-02-03 17:40:21 -08:00
ld a, [wAttackMissed]
2017-12-12 17:15:07 -08:00
and a
jr nz, .failed
2018-02-03 17:40:21 -08:00
callfar GetHalfMaxHP
callfar CheckUserHasEnoughHP
2017-12-12 17:15:07 -08:00
jr nc, .failed
```
**Fix:**
2017-12-12 19:58:20 -08:00
```asm
2017-12-12 17:15:07 -08:00
BattleCommand_BellyDrum: ; 37c1a
; bellydrum
2018-02-03 17:40:21 -08:00
callfar GetHalfMaxHP
callfar CheckUserHasEnoughHP
2017-12-12 17:15:07 -08:00
jr nc, .failed
call BattleCommand_AttackUp2
2018-02-03 17:40:21 -08:00
ld a, [wAttackMissed]
2017-12-12 17:15:07 -08:00
and a
jr nz, .failed
```
2017-12-28 09:49:32 -08:00
## Confusion damage is affected by type-boosting items and Explosion/Self-Destruct doubling
2017-12-28 09:58:18 -08:00
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
2017-12-28 09:49:32 -08:00
([Video](https://twitter.com/crystal_rby/status/874626362287562752))
*To do:* Identify specific code causing this bug and fix it.
2017-12-14 13:28:16 -08:00
## Moves that lower Defense can do so after breaking a Substitute
2017-12-28 09:58:18 -08:00
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
2017-12-14 13:28:16 -08:00
([Video](https://www.youtube.com/watch?v=OGwKPRJLaaI))
This bug affects Acid, Iron Tail, and Rock Smash.
2017-12-26 22:29:15 -08:00
This is a bug with `DefenseDownHit` in [data/moves/effects.asm ](/data/moves/effects.asm ):
2017-12-14 13:28:16 -08:00
```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
2017-12-28 09:58:18 -08:00
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
2017-12-14 13:28:16 -08:00
([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
2017-12-28 09:58:18 -08:00
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
2017-12-14 13:28:16 -08:00
([Video](https://www.youtube.com/watch?v=1v9x4SgMggs))
2017-12-26 14:47:05 -08:00
This is a bug with `CheckPlayerHasUsableMoves` in [engine/battle/core.asm ](/engine/battle/core.asm ):
2017-12-14 13:28:16 -08:00
```asm
.done
; Bug: this will result in a move with PP Up confusing the game.
2018-02-03 17:40:21 -08:00
and a ; should be "and PP_MASK"
2017-12-14 13:28:16 -08:00
ret nz
.force_struggle
2018-02-22 08:13:29 -08:00
ld hl, BattleText_MonHasNoMovesLeft
2017-12-14 13:28:16 -08:00
call StdBattleTextBox
ld c, 60
call DelayFrames
xor a
ret
```
2018-02-03 17:40:21 -08:00
**Fix:** Change `and a` to `and PP_MASK` .
2017-12-14 13:28:16 -08:00
## A Pokémon that fainted from Pursuit will have its old status condition when revived
2017-12-28 09:58:18 -08:00
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
2017-12-14 13:28:16 -08:00
([Video](https://www.youtube.com/watch?v=tiRvw-Nb2ME))
*To do:* Identify specific code causing this bug and fix it.
2017-12-14 18:45:35 -08:00
## Lock-On and Mind Reader don't always bypass Fly and Dig
2017-12-28 09:58:18 -08:00
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
2017-12-14 18:45:35 -08:00
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.
2017-12-26 14:47:05 -08:00
This is a bug with `CheckHiddenOpponent` in [engine/battle/effect_commands.asm ](/engine/battle/effect_commands.asm ):
2017-12-19 16:04:56 -08:00
```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.
2017-12-14 18:45:35 -08:00
2017-12-14 13:28:16 -08:00
## Beat Up can desynchronize link battles
2017-12-28 09:58:18 -08:00
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
2017-12-14 13:28:16 -08:00
([Video](https://www.youtube.com/watch?v=202-iAsrIa8))
2018-01-26 08:36:00 -08:00
This is a bug with `BattleCommand_BeatUp` in [engine/battle/move_effects/beat_up.asm ](/engine/battle/move_effects/beat_up.asm ):
2017-12-14 13:28:16 -08:00
```asm
.got_mon
ld a, [wd002]
2018-02-03 17:40:21 -08:00
ld hl, wPartyMonNicknames
2017-12-14 13:28:16 -08:00
call GetNick
ld a, MON_HP
call GetBeatupMonLocation
ld a, [hli]
or [hl]
jp z, .beatup_fail ; fainted
ld a, [wd002]
ld c, a
2018-02-03 17:40:21 -08:00
ld a, [wCurBattleMon]
2017-12-14 13:28:16 -08:00
; BUG: this can desynchronize link battles
; Change "cp [hl]" to "cp c" to fix
cp [hl]
2018-02-03 17:40:21 -08:00
ld hl, wBattleMonStatus
2017-12-14 13:28:16 -08:00
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
2017-12-28 09:58:18 -08:00
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
2017-12-14 13:28:16 -08:00
([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.
2018-01-26 08:36:00 -08:00
This is a bug with `BattleCommand_Present` in [engine/battle/move_effects/present.asm ](/engine/battle/move_effects/present.asm ):
2017-12-14 13:28:16 -08:00
```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))
2017-12-26 14:47:05 -08:00
This is a bug with `AI_Smart_MeanLook` in [engine/battle/ai/scoring.asm ](/engine/battle/ai/scoring.asm ):
2017-12-14 13:28:16 -08:00
```asm
; 80% chance to greatly encourage this move if the enemy is badly poisoned (buggy).
2018-02-03 17:40:21 -08:00
; Should check wPlayerSubStatus5 instead.
ld a, [wEnemySubStatus5]
2017-12-14 13:28:16 -08:00
bit SUBSTATUS_TOXIC, a
jr nz, .asm_38e26
```
2018-02-03 17:40:21 -08:00
**Fix:** Change `wEnemySubStatus5` to `wPlayerSubStatus5` .
2017-12-14 13:28:16 -08:00
2017-12-14 18:45:35 -08:00
## AI makes a false assumption about `CheckTypeMatchup`
2017-12-26 14:47:05 -08:00
In [engine/battle/effect_commands.asm ](/engine/battle/effect_commands.asm ):
2017-12-14 18:45:35 -08:00
```asm
BattleCheckTypeMatchup: ; 347c8
2018-02-03 17:40:21 -08:00
ld hl, wEnemyMonType1
2017-12-14 18:45:35 -08:00
ld a, [hBattleTurn]
and a
jr z, CheckTypeMatchup
2018-02-03 17:40:21 -08:00
ld hl, wBattleMonType1
2017-12-14 18:45:35 -08:00
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.
2017-12-14 13:28:16 -08:00
## NPC use of Full Heal or Full Restore does not cure Nightmare status
([Video](https://www.youtube.com/watch?v=rGqu3d3pdok& t=322))
2017-12-26 14:47:05 -08:00
This is a bug with `AI_HealStatus` in [engine/battle/ai/items.asm ](/engine/battle/ai/items.asm ):
2017-12-14 13:28:16 -08:00
```asm
AI_HealStatus: ; 384e0
2018-02-03 17:40:21 -08:00
ld a, [wCurOTMon]
ld hl, wOTPartyMon1Status
2017-12-14 13:28:16 -08:00
ld bc, PARTYMON_STRUCT_LENGTH
call AddNTimes
xor a
ld [hl], a
2018-02-03 17:40:21 -08:00
ld [wEnemyMonStatus], a
2017-12-14 13:28:16 -08:00
; Bug: this should reset SUBSTATUS_NIGHTMARE too
; Uncomment the lines below to fix
2018-02-03 17:40:21 -08:00
; ld hl, wEnemySubStatus1
2017-12-14 13:28:16 -08:00
; res SUBSTATUS_NIGHTMARE, [hl]
2018-02-03 17:40:21 -08:00
ld hl, wEnemySubStatus5
2017-12-14 13:28:16 -08:00
res SUBSTATUS_TOXIC, [hl]
ret
; 384f7
```
2018-02-03 17:40:21 -08:00
**Fix:** Uncomment `ld hl, wEnemySubStatus1` and `res SUBSTATUS_NIGHTMARE, [hl]` .
2017-12-14 13:28:16 -08:00
2017-12-12 19:58:20 -08:00
## HP bar animation is slow for high HP
2017-12-12 17:15:07 -08:00
([Video](https://www.youtube.com/watch?v=SE-BfsFgZVM))
2017-12-26 14:47:05 -08:00
This is a bug with `LongAnim_UpdateVariables` in [engine/battle/anim_hp_bar.asm ](/engine/battle/anim_hp_bar.asm ):
2017-12-12 17:15:07 -08:00
2017-12-12 19:58:20 -08:00
```asm
2017-12-12 17:15:07 -08:00
; This routine is buggy. The result from ComputeHPBarPixels is stored
; in e. However, the pop de opcode deletes this result before it is even
; used. The game then proceeds as though it never deleted that output.
; To fix, uncomment the line below.
call ComputeHPBarPixels
; ld a, e
pop bc
pop de
pop hl
ld a, e ; Comment or delete this line to fix the above bug.
ld hl, wCurHPBarPixels
cp [hl]
jr z, .loop
ld [hl], a
and a
ret
```
**Fix:** Move `ld a, e` to right after `call ComputeHPBarPixels` .
2017-12-12 19:58:20 -08:00
## HP bar animation off-by-one error for low HP
([Video](https://www.youtube.com/watch?v=9KyNVIZxJvI))
2017-12-14 16:04:44 -08:00
This is a bug with `ShortHPBar_CalcPixelFrame` in [engine/anim_hp_bar.asm ](/engine/anim_hp_bar.asm ):
2017-12-12 19:58:20 -08:00
```asm
ld b, 0
2018-02-03 17:40:21 -08:00
; This routine is buggy. If [wCurHPAnimMaxHP] * [wCurHPBarPixels] is
; divisible by HP_BAR_LENGTH_PX, the loop runs one extra time.
; To fix, uncomment the line below.
2017-12-12 19:58:20 -08:00
.loop
ld a, l
2018-02-03 17:40:21 -08:00
sub HP_BAR_LENGTH_PX
2017-12-12 19:58:20 -08:00
ld l, a
ld a, h
sbc $0
ld h, a
; jr z, .done
jr c, .done
inc b
jr .loop
```
**Fix:** Uncomment `jr z, .done` .
2017-12-12 17:15:07 -08:00
## Experience underflow for level 1 Pokémon with Medium-Slow growth rate
([Video](https://www.youtube.com/watch?v=SXH8u0plHrE))
This can bring Pokémon straight from level 1 to 100 by gaining just a few experience points.
2018-02-03 17:40:21 -08:00
This is a bug with `CalcExpAtLevel` in [engine/experience.asm ](/engine/experience.asm ):
2017-12-12 17:15:07 -08:00
2017-12-12 19:58:20 -08:00
```asm
2017-12-12 17:15:07 -08:00
CalcExpAtLevel: ; 50e47
; (a/b)*n**3 + c*n**2 + d*n - e
2018-02-03 17:40:21 -08:00
ld a, [wBaseGrowthRate]
2017-12-12 17:15:07 -08:00
add a
add a
ld c, a
ld b, 0
ld hl, GrowthRates
add hl, bc
```
**Fix:**
2017-12-12 19:58:20 -08:00
```asm
2017-12-12 17:15:07 -08:00
CalcExpAtLevel: ; 50e47
; (a/b)*n**3 + c*n**2 + d*n - e
ld a, d
cp 1
jr nz, .UseExpFormula
; Pokémon have 0 experience at level 1
xor a
ld hl, hProduct
ld [hli], a
ld [hli], a
ld [hli], a
ld [hl], a
ret
.UseExpFormula
2018-02-03 17:40:21 -08:00
ld a, [wBaseGrowthRate]
2017-12-12 17:15:07 -08:00
add a
add a
ld c, a
ld b, 0
ld hl, GrowthRates
add hl, bc
```
## Five-digit experience gain is printed incorrectly
([Video](https://www.youtube.com/watch?v=o54VjpAEoO8))
2018-02-03 17:40:21 -08:00
This is a bug with `Text_ABoostedStringBuffer2ExpPoints` and `Text_StringBuffer2ExpPoints` in [data/text/common_2.asm ](/data/text/common_2.asm ):
2017-12-12 17:15:07 -08:00
2017-12-12 19:58:20 -08:00
```asm
2017-12-12 17:15:07 -08:00
Text_ABoostedStringBuffer2ExpPoints::
2018-01-18 15:34:20 -08:00
text_start
2017-12-12 17:15:07 -08:00
line "a boosted"
cont "@"
2018-02-03 17:40:21 -08:00
deciram wStringBuffer2, 2, 4
2017-12-12 17:15:07 -08:00
text " EXP. Points!"
prompt
Text_StringBuffer2ExpPoints::
2018-01-18 15:34:20 -08:00
text_start
2017-12-12 17:15:07 -08:00
line "@"
2018-02-03 17:40:21 -08:00
deciram wStringBuffer2, 2, 4
2017-12-12 17:15:07 -08:00
text " EXP. Points!"
prompt
```
2018-02-03 17:40:21 -08:00
**Fix:** Change both `deciram wStringBuffer2, 2, 4` to `deciram wStringBuffer2, 2, 5` .
2017-12-12 19:58:20 -08:00
2017-12-12 17:15:07 -08:00
## BRN/PSN/PAR do not affect catch rate
2018-02-05 10:03:05 -08:00
This is a bug with `PokeBallEffect` in [engine/item_effects.asm ](/engine/item_effects.asm ):
2017-12-12 17:15:07 -08:00
2017-12-12 19:58:20 -08:00
```asm
2017-12-12 17:15:07 -08:00
; This routine is buggy. It was intended that SLP and FRZ provide a higher
; catch rate than BRN/PSN/PAR, which in turn provide a higher catch rate than
; no status effect at all. But instead, it makes BRN/PSN/PAR provide no
; benefit.
; Uncomment the line below to fix this.
ld b, a
2018-02-03 17:40:21 -08:00
ld a, [wEnemyMonStatus]
2017-12-12 17:15:07 -08:00
and 1 < < FRZ | SLP
ld c, 10
jr nz, .addstatus
2018-02-03 17:40:21 -08:00
; ld a, [wEnemyMonStatus]
2017-12-12 17:15:07 -08:00
and a
ld c, 5
jr nz, .addstatus
ld c, 0
.addstatus
ld a, b
add c
jr nc, .max_1
ld a, $ff
.max_1
```
2018-02-03 17:40:21 -08:00
**Fix:** Uncomment `ld a, [wEnemyMonStatus]` .
2017-12-12 17:15:07 -08:00
## Moon Ball does not boost catch rate
2017-12-14 16:04:44 -08:00
This is a bug with `MoonBallMultiplier` in [items/item_effects.asm ](/items/item_effects.asm ):
2017-12-12 17:15:07 -08:00
2017-12-12 19:58:20 -08:00
```asm
2017-12-12 17:15:07 -08:00
MoonBallMultiplier:
; This function is buggy.
; Intent: multiply catch rate by 4 if mon evolves with moon stone
; Reality: no boost
...
; Moon Stone's constant from Pokémon Red is used.
; No Pokémon evolve with Burn Heal,
; so Moon Balls always have a catch rate of 1× .
push bc
ld a, BANK(EvosAttacks)
call GetFarByte
cp MOON_STONE_RED ; BURN_HEAL
pop bc
ret nz
```
**Fix:** Change `MOON_STONE_RED` to `MOON_STONE` .
## Love Ball boosts catch rate for the wrong gender
2017-12-14 16:04:44 -08:00
This is a bug with `LoveBallMultiplier` in [items/item_effects.asm ](/items/item_effects.asm ):
2017-12-12 17:15:07 -08:00
2017-12-12 19:58:20 -08:00
```asm
2017-12-12 17:15:07 -08:00
LoveBallMultiplier:
; This function is buggy.
; Intent: multiply catch rate by 8 if mons are of same species, different sex
; Reality: multiply catch rate by 8 if mons are of same species, same sex
...
ld a, d
pop de
cp d
pop bc
ret nz ; for the intended effect, this should be "ret z"
```
**Fix:** Change `ret nz` to `ret z` .
## Fast Ball only boosts catch rate for three Pokémon
2017-12-14 16:04:44 -08:00
This is a bug with `FastBallMultiplier` in [items/item_effects.asm ](/items/item_effects.asm ):
2017-12-12 17:15:07 -08:00
2017-12-12 19:58:20 -08:00
```asm
2017-12-12 17:15:07 -08:00
FastBallMultiplier:
; This function is buggy.
; Intent: multiply catch rate by 4 if enemy mon is in one of the three
; FleeMons tables.
; Reality: multiply catch rate by 4 if enemy mon is one of the first three in
; the first FleeMons table.
...
inc hl
cp -1
jr z, .next
cp c
jr nz, .next ; for the intended effect, this should be "jr nz, .loop"
sla b
jr c, .max
```
**Fix:** Change `jr nz, .next` to `jr nz, .loop` .
2017-12-12 18:29:53 -08:00
## Dragon Scale, not Dragon Fang, boosts Dragon-type moves
2017-12-12 17:15:07 -08:00
2017-12-28 09:58:18 -08:00
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
2018-02-03 17:40:21 -08:00
This is a bug with `ItemAttributes` in [data/items/attributes.asm ](/data/items/attributes.asm ):
2017-12-12 17:15:07 -08:00
2017-12-12 19:58:20 -08:00
```asm
2018-02-03 19:57:57 -08:00
; DRAGON_FANG
2017-12-12 17:15:07 -08:00
item_attribute 100, 0, 0, CANT_SELECT, ITEM, ITEMMENU_NOUSE, ITEMMENU_NOUSE
...
2018-02-03 19:57:57 -08:00
; DRAGON_SCALE
2017-12-12 17:15:07 -08:00
item_attribute 2100, HELD_DRAGON_BOOST, 10, CANT_SELECT, ITEM, ITEMMENU_NOUSE, ITEMMENU_NOUSE
```
2018-02-03 19:57:57 -08:00
**Fix:** Move `HELD_DRAGON_BOOST` to the `DRAGON_FANG` attributes and `0` to `DRAGON_SCALE` .
2017-12-12 17:15:07 -08:00
2017-12-17 16:48:04 -08:00
## Daisy's grooming doesn't always increase happiness
2017-12-12 17:15:07 -08:00
2018-02-04 09:03:31 -08:00
This is a bug with `HaircutOrGrooming` in [engine/events/specials_2.asm ](/engine/events/specials_2.asm ):
2017-12-12 17:15:07 -08:00
2017-12-12 19:58:20 -08:00
```asm
2017-12-12 17:15:07 -08:00
; Bug: Subtracting $ff from $ff fails to set c.
; This can result in overflow into the next data array.
2018-01-22 21:11:23 -08:00
; In the case of getting a grooming from Daisy, we bleed
2017-12-12 17:15:07 -08:00
; into CopyPokemonName_Buffer1_Buffer3, which passes
; $d0 to ChangeHappiness and returns $73 to the script.
; The end result is that there is a 0.4% chance your
; Pokemon's happiness will not change at all.
.loop
sub [hl]
jr c, .ok
inc hl
inc hl
inc hl
jr .loop
.ok
inc hl
ld a, [hli]
2018-02-03 17:40:21 -08:00
ld [wScriptVar], a
2017-12-12 17:15:07 -08:00
ld c, [hl]
call ChangeHappiness
ret
...
2018-02-04 08:46:53 -08:00
INCLUDE "data/events/happiness_probabilities.asm"
2017-12-12 17:15:07 -08:00
CopyPokemonName_Buffer1_Buffer3: ; 746e
2018-02-03 17:40:21 -08:00
ld hl, wStringBuffer1
ld de, wStringBuffer3
2018-01-20 09:25:55 -08:00
ld bc, MON_NAME_LENGTH
2017-12-12 17:15:07 -08:00
jp CopyBytes
```
2018-02-04 08:46:53 -08:00
In [data/events/happiness_probabilities.asm ](/data/events/happiness_probabilities.asm ):
2018-01-26 11:36:59 -08:00
```asm
HappinessData_DaisysGrooming: ; 746b
db $ff, 2, HAPPINESS_GROOMING ; 99.6% chance
```
2017-12-12 17:15:07 -08:00
**Fix:**
2017-12-12 19:58:20 -08:00
```asm
2018-01-26 11:36:59 -08:00
HappinessData_DaisysGrooming: ; 746b
2018-01-22 21:11:23 -08:00
db $80, 2, HAPPINESS_GROOMING ; 50% chance
db $ff, 2, HAPPINESS_GROOMING ; 50% chance
2017-12-12 17:15:07 -08:00
```
2017-12-12 19:58:20 -08:00
## Magikarp in Lake of Rage are shorter, not longer
2017-12-26 14:47:05 -08:00
This is a bug with `LoadEnemyMon.CheckMagikarpArea` in [engine/battle/core.asm ](/engine/battle/core.asm ):
2017-12-12 19:58:20 -08:00
```asm
.CheckMagikarpArea:
2018-02-03 17:40:21 -08:00
; The "jr z" checks are supposed to be "jr nz".
; Instead, all maps in GROUP_LAKE_OF_RAGE (Mahogany area)
; and Routes 20 and 44 are treated as Lake of Rage.
2017-12-12 19:58:20 -08:00
; This also means Lake of Rage Magikarp can be smaller than ones
2018-02-03 17:40:21 -08:00
; caught elsewhere rather than the other way around.
; Intended behavior enforces a minimum size at Lake of Rage.
; The real behavior prevents a minimum size in the Lake of Rage area.
2017-12-12 19:58:20 -08:00
2018-02-03 17:40:21 -08:00
; Moreover, due to the check not being translated to feet+inches, all Magikarp
; smaller than 4'0" may be caught by the filter, a lot more than intended.
ld a, [wMapGroup]
2017-12-12 19:58:20 -08:00
cp GROUP_LAKE_OF_RAGE
jr z, .Happiness
2018-02-03 17:40:21 -08:00
ld a, [wMapNumber]
2017-12-12 19:58:20 -08:00
cp MAP_LAKE_OF_RAGE
jr z, .Happiness
```
**Fix:** Change both `jr z, .Happiness` to `jr nz, .Happiness` .
2017-12-28 11:08:29 -08:00
## Magikarp length limits have a unit conversion error
2017-12-28 10:17:43 -08:00
This is a bug with `LoadEnemyMon.CheckMagikarpArea` in [engine/battle/core.asm ](/engine/battle/core.asm ):
```asm
; Get Magikarp's length
2018-02-03 17:40:21 -08:00
ld de, wEnemyMonDVs
ld bc, wPlayerID
2017-12-28 10:17:43 -08:00
callfar CalcMagikarpLength
2018-02-03 17:40:21 -08:00
; No reason to keep going if length > 1536 mm (i.e. if HIGH(length) > 6 feet)
2017-12-28 10:17:43 -08:00
ld a, [wMagikarpLength]
2018-02-03 17:40:21 -08:00
cp HIGH(1536) ; should be "cp 5", since 1536 mm = 5'0", but HIGH(1536) = 6
2017-12-28 10:17:43 -08:00
jr nz, .CheckMagikarpArea
; 5% chance of skipping both size checks
call Random
cp 5 percent
jr c, .CheckMagikarpArea
2018-02-03 17:40:21 -08:00
; Try again if length >= 1616 mm (i.e. if LOW(length) >= 3 inches)
2017-12-28 10:17:43 -08:00
ld a, [wMagikarpLength + 1]
2018-02-03 17:40:21 -08:00
cp LOW(1616) ; should be "cp 3", since 1616 mm = 5'3", but LOW(1616) = 80
2017-12-28 10:17:43 -08:00
jr nc, .GenerateDVs
; 20% chance of skipping this check
call Random
cp 20 percent - 1
jr c, .CheckMagikarpArea
2018-02-03 17:40:21 -08:00
; Try again if length >= 1600 mm (i.e. if LOW(length) >= 2 inches)
2017-12-28 10:17:43 -08:00
ld a, [wMagikarpLength + 1]
2018-02-03 17:40:21 -08:00
cp LOW(1600) ; should be "cp 2", since 1600 mm = 5'2", but LOW(1600) = 64
2017-12-28 10:17:43 -08:00
jr nc, .GenerateDVs
```
2017-12-28 11:08:29 -08:00
**Fix:** Change the three `cp` instructions to use their commented values.
2017-12-28 10:17:43 -08:00
2017-12-14 22:01:57 -08:00
## Magikarp lengths can be miscalculated
2017-12-26 21:09:12 -08:00
This is a bug with `CalcMagikarpLength.BCLessThanDE` in [engine/events/magikarp.asm ](/engine/events/magikarp.asm ):
2017-12-14 22:01:57 -08:00
```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` .
2017-12-12 19:58:20 -08:00
## Battle transitions fail to account for the enemy's level
([Video](https://www.youtube.com/watch?v=eij_1060SMc))
2018-02-03 17:40:21 -08:00
This is a bug with `StartTrainerBattle_DetermineWhichAnimation` in [engine/battle/battle_transition.asm ](/engine/battle/battle_transition.asm ):
2017-12-12 19:58:20 -08:00
2017-12-12 20:05:30 -08:00
```asm
2017-12-12 19:58:20 -08:00
StartTrainerBattle_DetermineWhichAnimation: ; 8c365 (23:4365)
; The screen flashes a different number of times depending on the level of
; your lead Pokemon relative to the opponent's.
2018-02-03 17:40:21 -08:00
; BUG: wBattleMonLevel and wEnemyMonLevel are not set at this point, so whatever
2017-12-12 19:58:20 -08:00
; values happen to be there will determine the animation.
ld de, 0
2018-02-03 17:40:21 -08:00
ld a, [wBattleMonLevel]
2017-12-12 19:58:20 -08:00
add 3
2018-02-03 17:40:21 -08:00
ld hl, wEnemyMonLevel
2017-12-12 19:58:20 -08:00
cp [hl]
jr nc, .okay
set 0, e
.okay
2018-01-26 11:36:59 -08:00
ld a, [wEnvironment]
2017-12-12 19:58:20 -08:00
cp CAVE
jr z, .okay2
2018-01-26 11:36:59 -08:00
cp ENVIRONMENT_5
2017-12-12 19:58:20 -08:00
jr z, .okay2
cp DUNGEON
jr z, .okay2
set 1, e
.okay2
ld hl, .StartingPoints
add hl, de
ld a, [hl]
ld [wJumptableIndex], a
ret
; 8c38f (23:438f)
.StartingPoints: ; 8c38f
db 1, 9
db 16, 24
; 8c393
```
*To do:* Fix this bug.
2017-12-14 18:45:35 -08:00
## 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
2018-02-03 17:40:21 -08:00
ld a, [wSlotsDelay]
2017-12-14 18:45:35 -08:00
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` .
2017-12-14 21:05:53 -08:00
## Team Rocket battle music is not used for Executives or Scientists
2018-02-03 17:40:21 -08:00
This is a bug with `PlayBattleMusic` in [engine/battle/start_battle.asm ](/engine/battle/start_battle.asm ):
2017-12-14 21:05:53 -08:00
```asm
2018-02-03 17:40:21 -08:00
; They should have included EXECUTIVEM, EXECUTIVEF, and SCIENTIST too...
2017-12-14 21:05:53 -08:00
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
```
2017-12-12 17:15:07 -08:00
## No bump noise if standing on tile `$3E`
2017-12-14 16:04:44 -08:00
This is a bug with `DoPlayerMovement.CheckWarp` in [engine/player_movement.asm ](/engine/player_movement.asm ):
2017-12-12 17:15:07 -08:00
2017-12-12 19:58:20 -08:00
```asm
2017-12-12 17:15:07 -08:00
; Bug: Since no case is made for STANDING here, it will check
; [.edgewarps + $ff]. This resolves to $3e at $8035a.
; This causes wd041 to be nonzero when standing on tile $3e,
; making bumps silent.
2018-02-03 17:40:21 -08:00
ld a, [wWalkingDirection]
2017-12-21 09:11:35 -08:00
; cp STANDING
; jr z, .not_warp
2017-12-12 17:15:07 -08:00
ld e, a
ld d, 0
ld hl, .EdgeWarps
add hl, de
2018-02-03 17:40:21 -08:00
ld a, [wPlayerStandingTile]
2017-12-12 17:15:07 -08:00
cp [hl]
jr nz, .not_warp
ld a, 1
ld [wd041], a
2018-02-03 17:40:21 -08:00
ld a, [wWalkingDirection]
2017-12-21 09:11:35 -08:00
; This is in the wrong place.
2017-12-12 17:15:07 -08:00
cp STANDING
jr z, .not_warp
```
**Fix:**
2017-12-12 19:58:20 -08:00
```asm
2018-02-03 17:40:21 -08:00
ld a, [wWalkingDirection]
2017-12-12 17:15:07 -08:00
cp STANDING
jr z, .not_warp
ld e, a
ld d, 0
ld hl, .EdgeWarps
add hl, de
2018-02-03 17:40:21 -08:00
ld a, [wPlayerStandingTile]
2017-12-12 17:15:07 -08:00
cp [hl]
jr nz, .not_warp
ld a, 1
ld [wd041], a
2018-02-03 17:40:21 -08:00
ld a, [wWalkingDirection]
2017-12-12 17:15:07 -08:00
```
2017-12-13 13:46:31 -08:00
## Playing Entei's Pokédex cry can distort Raikou's and Suicune's
([Video](https://www.youtube.com/watch?v=z305e4sIO24))
2018-01-21 15:00:23 -08:00
The exact cause is unknown, but a workaround exists for `DexEntryScreen_MenuActionJumptable.Cry` in [engine/pokedex/pokedex.asm ](/engine/pokedex/pokedex.asm ):
2017-12-13 13:46:31 -08:00
```asm
.Cry: ; 40340
call Pokedex_GetSelectedMon
ld a, [wd265]
call GetCryIndex
ld e, c
ld d, b
2018-01-16 20:47:45 -08:00
call PlayCry
2017-12-13 13:46:31 -08:00
ret
```
**Workaround:**
```asm
.Cry: ; 40340
ld a, [CurPartySpecies]
2018-01-16 20:47:45 -08:00
call PlayMonCry
2017-12-13 13:46:31 -08:00
ret
```
2017-12-22 14:52:34 -08:00
## 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 ):
2017-12-23 09:08:34 -08:00
![image ](/docs/images/hp_exp_bar_border.png )
2017-12-22 14:52:34 -08:00
**Fix:** Lower the ellipsis by two pixels:
2017-12-23 09:08:34 -08:00
![image ](/docs/images/hp_exp_bar_border_fix.png )
2017-12-22 14:52:34 -08:00
2017-12-22 14:59:50 -08:00
## Two tiles in the `port` tileset are drawn incorrectly
2017-12-22 15:01:06 -08:00
This is a mistake with the left-hand warp carpet corner tiles in [gfx/tilesets/port.png ](/gfx/tilesets/port.png ):
2017-12-22 14:59:50 -08:00
2017-12-23 09:08:34 -08:00
![image ](/docs/images/port.png )
2017-12-22 14:59:50 -08:00
**Fix:** Adjust them to match the right-hand corner tiles:
2017-12-23 09:08:34 -08:00
![image ](/docs/images/port_fix.png )
2017-12-22 14:59:50 -08:00
2017-12-13 13:46:31 -08:00
## `LoadMetatiles` wraps around past 128 blocks
This bug prevents you from using blocksets with more than 128 blocks.
2017-12-12 20:05:30 -08:00
2017-12-14 16:07:06 -08:00
In [home/map.asm ](/home/map.asm ):
2017-12-12 20:05:30 -08:00
```asm
2018-02-03 17:40:21 -08:00
; Set hl to the address of the current metatile data ([wTilesetBlocksAddress] + (a) tiles).
2017-12-12 20:05:30 -08:00
; This is buggy; it wraps around past 128 blocks.
; To fix, uncomment the line below.
add a ; Comment or delete this line to fix the above bug.
ld l, a
ld h, 0
; add hl, hl
add hl, hl
add hl, hl
add hl, hl
2018-02-03 17:40:21 -08:00
ld a, [wTilesetBlocksAddress]
2017-12-12 20:05:30 -08:00
add l
ld l, a
2018-02-03 17:40:21 -08:00
ld a, [wTilesetBlocksAddress + 1]
2017-12-12 20:05:30 -08:00
adc h
ld h, a
```
**Fix:** Delete `add a` and uncomment `add hl, hl` .
2017-12-12 19:58:20 -08:00
## Surfing directly across a map connection does not load the new map
([Video](https://www.youtube.com/watch?v=XFOWvMNG-zw))
*To do:* Identify specific code causing this bug and fix it.
2017-12-21 08:43:41 -08:00
## `Function6ec1` does not correctly limit object movement
2018-02-03 17:40:21 -08:00
This bug is why the Lapras in [maps/UnionCaveB2F.asm ](/maps/UnionCaveB2F.asm ), which uses `SPRITEMOVEDATA_SWIM_WANDER` , is not restricted by its `1, 1` movement radius.
2017-12-21 08:43:41 -08:00
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` .
2017-12-12 17:15:07 -08:00
## `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.
2017-12-14 16:07:06 -08:00
In [engine/search.asm ](/engine/search.asm ):
2017-12-12 17:15:07 -08:00
2017-12-12 19:58:20 -08:00
```asm
2017-12-12 17:15:07 -08:00
; check OT
; This only checks five characters, which is fine for the Japanese version,
; but in the English version the player name is 7 characters, so this is wrong.
2018-02-03 17:40:21 -08:00
ld hl, wPlayerName
2017-12-12 17:15:07 -08:00
2018-02-02 19:55:38 -08:00
rept NAME_LENGTH_JAPANESE + -2 ; should be PLAYER_NAME_LENGTH + -2
2017-12-12 17:15:07 -08:00
ld a, [de]
cp [hl]
jr nz, .notfound
cp "@"
jr z, .found ; reached end of string
inc hl
inc de
endr
ld a, [de]
cp [hl]
jr z, .found
```
2018-02-02 19:55:38 -08:00
**Fix:** Change `rept NAME_LENGTH_JAPANESE + -2` to `rept PLAYER_NAME_LENGTH + -2` .
2017-12-12 17:15:07 -08:00
2017-12-13 13:46:31 -08:00
## 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.
2018-02-05 10:03:05 -08:00
This is a bug with `PokeBallEffect` in [engine/item_effects.asm ](/engine/item_effects.asm ):
2017-12-19 16:04:56 -08:00
```asm
2018-02-03 17:40:21 -08:00
ld hl, wEnemySubStatus5
2017-12-19 16:04:56 -08:00
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.
2018-02-03 17:40:21 -08:00
; To fix, do not set [wTempEnemyMonSpecies] to DITTO.
2017-12-19 16:04:56 -08:00
bit SUBSTATUS_TRANSFORMED, a
jr nz, .ditto
jr .not_ditto
.ditto
ld a, DITTO
2018-02-03 17:40:21 -08:00
ld [wTempEnemyMonSpecies], a
2017-12-19 16:04:56 -08:00
jr .load_data
.not_ditto
set SUBSTATUS_TRANSFORMED, [hl]
ld hl, wEnemyBackupDVs
2018-02-03 17:40:21 -08:00
ld a, [wEnemyMonDVs]
2017-12-19 16:04:56 -08:00
ld [hli], a
2018-02-03 17:40:21 -08:00
ld a, [wEnemyMonDVs + 1]
2017-12-19 16:04:56 -08:00
ld [hl], a
.load_data
2018-02-03 17:40:21 -08:00
ld a, [wTempEnemyMonSpecies]
ld [wCurPartySpecies], a
ld a, [wEnemyMonLevel]
ld [wCurPartyLevel], a
farcall LoadEnemyMon
2017-12-19 16:04:56 -08:00
pop af
2018-02-03 17:40:21 -08:00
ld [wEnemySubStatus5], a
2017-12-19 16:04:56 -08:00
```
**Fix:**
```asm
2018-02-03 17:40:21 -08:00
ld hl, wEnemySubStatus5
2017-12-19 16:04:56 -08:00
ld a, [hl]
push af
set SUBSTATUS_TRANSFORMED, [hl]
bit SUBSTATUS_TRANSFORMED, a
jr nz, .load_data
ld hl, wEnemyBackupDVs
2018-02-03 17:40:21 -08:00
ld a, [wEnemyMonDVs]
2017-12-19 16:04:56 -08:00
ld [hli], a
2018-02-03 17:40:21 -08:00
ld a, [wEnemyMonDVs + 1]
2017-12-19 16:04:56 -08:00
ld [hl], a
.load_data
2018-02-03 17:40:21 -08:00
ld a, [wTempEnemyMonSpecies]
ld [wCurPartySpecies], a
ld a, [wEnemyMonLevel]
ld [wCurPartyLevel], a
farcall LoadEnemyMon
2017-12-19 16:04:56 -08:00
pop af
2018-02-03 17:40:21 -08:00
ld [wEnemySubStatus5], a
2017-12-19 16:04:56 -08:00
```
2017-12-13 13:46:31 -08:00
## Using a Park Ball in normal battles has a corrupt animation
([Video](https://www.youtube.com/watch?v=v1ErZdLCIyU))
2018-02-05 10:03:05 -08:00
This is a bug with `PokeBallEffect` in [engine/item_effects.asm ](/engine/item_effects.asm ):
2017-12-13 13:46:31 -08:00
```asm
.room_in_party
xor a
ld [wWildMon], a
2018-02-03 17:40:21 -08:00
ld a, [wCurItem]
2017-12-13 13:46:31 -08:00
cp PARK_BALL
call nz, ReturnToBattle_UseBall
```
**Fix:**
```asm
.room_in_party
xor a
ld [wWildMon], a
2018-02-03 17:40:21 -08:00
ld a, [wBattleType]
2017-12-13 13:46:31 -08:00
cp BATTLETYPE_CONTEST
call nz, ReturnToBattle_UseBall
```
2017-12-12 17:15:07 -08:00
## `HELD_CATCH_CHANCE` has no effect
2018-02-05 10:03:05 -08:00
This is a bug with `PokeBallEffect` in [engine/item_effects.asm ](/engine/item_effects.asm ):
2017-12-12 17:15:07 -08:00
2017-12-12 19:58:20 -08:00
```asm
2018-02-03 17:40:21 -08:00
; BUG: farcall overwrites a, and GetItemHeldEffect takes b anyway.
; This is probably the reason the HELD_CATCH_CHANCE effect is never used.
2017-12-12 17:15:07 -08:00
; Uncomment the line below to fix.
2018-02-03 17:40:21 -08:00
ld d, a
push de
ld a, [wBattleMonItem]
; ld b, a
farcall GetItemHeldEffect
2017-12-12 17:15:07 -08:00
ld a, b
cp HELD_CATCH_CHANCE
2018-02-03 17:40:21 -08:00
pop de
ld a, d
jr nz, .max_2
add c
jr nc, .max_2
ld a, $ff
.max_2
2017-12-12 17:15:07 -08:00
```
**Fix:** Uncomment `ld b, a` .
2017-12-13 13:46:31 -08:00
## Only the first three `EvosAttacks` evolution entries can have Stone compatibility reported correctly
2017-12-14 16:04:44 -08:00
This is a bug with `PlacePartyMonEvoStoneCompatibility.DetermineCompatibility` in [engine/party_menu.asm ](/engine/party_menu.asm ):
2017-12-13 13:46:31 -08:00
```asm
.DetermineCompatibility: ; 50268
2018-02-03 17:40:21 -08:00
ld de, wStringBuffer1
2017-12-13 13:46:31 -08:00
ld a, BANK(EvosAttacksPointers)
ld bc, 2
call FarCopyBytes
2018-02-03 17:40:21 -08:00
ld hl, wStringBuffer1
2017-12-13 13:46:31 -08:00
ld a, [hli]
ld h, [hl]
ld l, a
2018-02-03 17:40:21 -08:00
ld de, wStringBuffer1
2017-12-13 13:46:31 -08:00
ld a, BANK(EvosAttacks)
2018-01-26 11:36:59 -08:00
ld bc, 10
2017-12-13 13:46:31 -08:00
call FarCopyBytes
```
2018-02-03 17:40:21 -08:00
**Fix:** Change `ld bc, 10` to `ld bc, wStringBuffer2 - wStringBuffer1` to support up to six Stone entries.
2017-12-13 13:46:31 -08:00
2017-12-12 17:15:07 -08:00
## `ScriptCall` can overflow `wScriptStack` and crash
2017-12-14 16:07:06 -08:00
In [engine/scripting.asm ](/engine/scripting.asm ):
2017-12-12 17:15:07 -08:00
2017-12-12 19:58:20 -08:00
```asm
2017-12-12 17:15:07 -08:00
ScriptCall:
; Bug: The script stack has a capacity of 5 scripts, yet there is
; nothing to stop you from pushing a sixth script. The high part
; of the script address can then be overwritten by modifications
2018-02-03 17:40:21 -08:00
; to wScriptDelay, causing the script to return to the rst/interrupt
2017-12-12 17:15:07 -08:00
; space.
push de
ld hl, wScriptStackSize
ld e, [hl]
inc [hl]
ld d, $0
ld hl, wScriptStack
add hl, de
add hl, de
add hl, de
pop de
2018-02-03 17:40:21 -08:00
ld a, [wScriptBank]
2017-12-12 17:15:07 -08:00
ld [hli], a
2018-02-03 17:40:21 -08:00
ld a, [wScriptPos]
2017-12-12 17:15:07 -08:00
ld [hli], a
2018-02-03 17:40:21 -08:00
ld a, [wScriptPos + 1]
2017-12-12 17:15:07 -08:00
ld [hl], a
ld a, b
2018-02-03 17:40:21 -08:00
ld [wScriptBank], a
2017-12-12 17:15:07 -08:00
ld a, e
2018-02-03 17:40:21 -08:00
ld [wScriptPos], a
2017-12-12 17:15:07 -08:00
ld a, d
2018-02-03 17:40:21 -08:00
ld [wScriptPos + 1], a
2017-12-12 17:15:07 -08:00
ret
```
2018-01-26 11:36:59 -08:00
*To do:* Fix this bug.
2017-12-12 17:15:07 -08:00
## `LoadSpriteGFX` does not limit the capacity of `UsedSprites`
2017-12-14 16:07:06 -08:00
In [engine/overworld.asm ](/engine/overworld.asm ):
2017-12-12 17:15:07 -08:00
2017-12-12 19:58:20 -08:00
```asm
2017-12-12 17:15:07 -08:00
LoadSpriteGFX: ; 14306
2017-12-21 09:11:35 -08:00
; Bug: b is not preserved, so it's useless as a next count.
; Uncomment the lines below to fix.
2017-12-12 17:15:07 -08:00
2018-02-03 17:40:21 -08:00
ld hl, wUsedSprites
2017-12-12 17:15:07 -08:00
ld b, SPRITE_GFX_LIST_CAPACITY
.loop
ld a, [hli]
and a
jr z, .done
push hl
call .LoadSprite
pop hl
ld [hli], a
dec b
jr nz, .loop
.done
ret
.LoadSprite:
2017-12-21 09:11:35 -08:00
; push bc
2017-12-12 17:15:07 -08:00
call GetSprite
2017-12-21 09:11:35 -08:00
; pop bc
2017-12-12 17:15:07 -08:00
ld a, l
ret
; 1431e
```
2017-12-21 09:11:35 -08:00
**Fix:** Uncomment `push bc` and `pop bc` .
2017-12-12 17:15:07 -08:00
## `ChooseWildEncounter` doesn't really validate the wild Pokémon species
2017-12-14 16:07:06 -08:00
In [engine/wildmons.asm ](/engine/wildmons.asm ):
2017-12-12 17:15:07 -08:00
2017-12-12 19:58:20 -08:00
```asm
2017-12-12 17:15:07 -08:00
ChooseWildEncounter: ; 2a14f
...
ld a, b
2018-02-03 17:40:21 -08:00
ld [wCurPartyLevel], a
2017-12-12 17:15:07 -08:00
ld b, [hl]
; ld a, b
call ValidateTempWildMonSpecies
jr c, .nowildbattle
ld a, b ; This is in the wrong place.
cp UNOWN
jr nz, .done
...
ValidateTempWildMonSpecies: ; 2a4a0
; Due to a development oversight, this function is called with the wild Pokemon's level, not its species, in a.
```
**Fix:**
2017-12-12 19:58:20 -08:00
```asm
2017-12-12 17:15:07 -08:00
ld a, b
2018-02-03 17:40:21 -08:00
ld [wCurPartyLevel], a
2017-12-12 17:15:07 -08:00
ld b, [hl]
ld a, b
call ValidateTempWildMonSpecies
jr c, .nowildbattle
cp UNOWN
jr nz, .done
```
## `TryObjectEvent` arbitrary code execution
2017-12-14 16:07:06 -08:00
In [engine/events.asm ](/engine/events.asm ):
2017-12-12 17:15:07 -08:00
2017-12-12 19:58:20 -08:00
```asm
2017-12-12 17:15:07 -08:00
; Bug: If IsInArray returns nc, data at bc will be executed as code.
push bc
ld de, 3
ld hl, .pointers
call IsInArray
jr nc, .nope_bugged
pop bc
inc hl
ld a, [hli]
ld h, [hl]
ld l, a
jp hl
.nope_bugged
; pop bc
xor a
ret
```
**Fix:** Uncomment `pop bc` .
2018-01-24 08:17:05 -08:00
## `CheckBugContestContestantFlag` can read beyond its data table
2017-12-12 17:15:07 -08:00
2017-12-26 21:09:12 -08:00
In [engine/events/bug_contest/contest_2.asm ](/engine/events/bug_contest/contest_2.asm ):
2017-12-12 17:15:07 -08:00
2017-12-12 19:58:20 -08:00
```asm
2018-01-24 08:17:05 -08:00
CheckBugContestContestantFlag: ; 139ed
2017-12-12 17:15:07 -08:00
; Checks the flag of the Bug Catching Contestant whose index is loaded in a.
2018-01-26 11:36:59 -08:00
; Bug: If a >= NUM_BUG_CONTESTANTS when this is called,
; it will read beyond the table.
2017-12-12 17:15:07 -08:00
ld hl, BugCatchingContestantEventFlagTable
ld e, a
ld d, 0
add hl, de
add hl, de
ld e, [hl]
inc hl
ld d, [hl]
ld b, CHECK_FLAG
call EventFlagAction
ret
; 139fe
2018-01-26 11:36:59 -08:00
INCLUDE "data/events/bug_contest_flags.asm"
2017-12-12 17:15:07 -08:00
```
2018-01-26 11:36:59 -08:00
However, `a < NUM_BUG_CONTESTANTS` should always be true, so in practice this is not a problem.
2017-12-12 17:15:07 -08:00
## `ClearWRAM` only clears WRAM bank 1
2017-12-14 16:07:06 -08:00
In [home/init.asm ](/home/init.asm ):
2017-12-12 17:15:07 -08:00
2017-12-12 19:58:20 -08:00
```asm
2017-12-12 17:15:07 -08:00
ClearWRAM:: ; 25a
; Wipe swappable WRAM banks (1-7)
; Assumes CGB or AGB
ld a, 1
.bank_loop
push af
ld [rSVBK], a
xor a
2017-12-26 20:18:05 -08:00
ld hl, WRAM1_Begin
ld bc, WRAM1_End - WRAM1_Begin
2017-12-12 17:15:07 -08:00
call ByteFill
pop af
inc a
cp 8
jr nc, .bank_loop ; Should be jr c
ret
; 270
```
**Fix:** Change `jr nc, .bank_loop` to `jr c, .bank_loop` .