pokecrystal/docs/bugs_and_glitches.md

1535 lines
37 KiB
Markdown
Raw Normal View History

2017-12-13 01:50:34 +00:00
# Bugs and Glitches
2017-12-13 01:15:07 +00: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-13 01:15:07 +00: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)
- [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)
- [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 Upenhanced 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-15 02:45:35 +00:00
- [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)
2017-12-15 02:45:35 +00:00
- [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)
2017-12-18 00:48:04 +00:00
- [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 length limits have a unit conversion error](#magikarp-length-limits-have-a-unit-conversion-error)
- [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)
2018-02-26 16:51:16 +00:00
- [A "HOF Master!" title for 201-Time Famers is defined but inaccessible](#a-hof-master-title-for-201-time-famers-is-defined-but-inaccessible)
2017-12-15 02:45:35 +00:00
- [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)
2017-12-22 22:52:34 +00:00
- [In-battle “`…`” ellipsis is too high](#in-battle--ellipsis-is-too-high)
2017-12-22 22:59:50 +00:00
- [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)
2017-12-21 16:43:41 +00:00
- [`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)
2018-02-26 18:41:48 +00:00
- [`EVOLVE_STAT` can break Stone compatibility reporting](#evolve_stat-can-break-stone-compatibility-reporting)
- [`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)
- [`CheckBugContestContestantFlag` can read beyond its data table](#checkbugcontestcontestantflag-can-read-beyond-its-data-table)
- [`ClearWRAM` only clears WRAM bank 1](#clearwram-only-clears-wram-bank-1)
2017-12-13 03:58:20 +00:00
## Thick Club and Light Ball can decrease damage done with boosted (Special) Attack
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
2017-12-13 03:58:20 +00:00
([Video](https://www.youtube.com/watch?v=rGqu3d3pdok&t=450))
This is a bug with `SpeciesItemBoost` in [engine/battle/effect_commands.asm](/engine/battle/effect_commands.asm):
2017-12-13 03:58:20 +00:00
```asm
; Double the stat
sla l
rl h
ret
```
**Fix:**
```asm
; Double the stat
sla l
rl h
ld a, HIGH(MAX_STAT_VALUE)
2017-12-13 03:58:20 +00:00
cp h
jr c, .cap
ld a, LOW(MAX_STAT_VALUE)
2017-12-13 03:58:20 +00:00
cp l
ret nc
.cap
ld h, HIGH(MAX_STAT_VALUE)
ld l, LOW(MAX_STAT_VALUE)
2017-12-13 03:58:20 +00:00
ret
```
## Metal Powder can increase damage taken with boosted (Special) Defense
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
2017-12-13 03:58:20 +00:00
([Video](https://www.youtube.com/watch?v=rGqu3d3pdok&t=450))
This is a bug with `DittoMetalPowder` in [engine/battle/effect_commands.asm](/engine/battle/effect_commands.asm):
2017-12-13 03:58:20 +00: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
ld a, HIGH(MAX_STAT_VALUE)
2017-12-13 03:58:20 +00:00
cp b
jr c, .cap
ld a, LOW(MAX_STAT_VALUE)
2017-12-13 03:58:20 +00:00
cp c
ret nc
.cap
ld b, HIGH(MAX_STAT_VALUE)
ld c, LOW(MAX_STAT_VALUE)
2017-12-13 03:58:20 +00:00
ret
```
2017-12-13 01:15:07 +00:00
## Belly Drum sharply boosts Attack even with under 50% HP
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
2017-12-13 01:15:07 +00:00
([Video](https://www.youtube.com/watch?v=zuCLMikWo4Y))
This is a bug with `BattleCommand_BellyDrum` in [engine/battle/move_effects/belly_drum.asm](/engine/battle/move_effects/belly_drum.asm):
2017-12-13 01:15:07 +00:00
2017-12-13 03:58:20 +00:00
```asm
2017-12-13 01:15:07 +00: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
ld a, [wAttackMissed]
2017-12-13 01:15:07 +00:00
and a
jr nz, .failed
callfar GetHalfMaxHP
callfar CheckUserHasEnoughHP
2017-12-13 01:15:07 +00:00
jr nc, .failed
```
**Fix:**
2017-12-13 03:58:20 +00:00
```asm
2017-12-13 01:15:07 +00:00
BattleCommand_BellyDrum: ; 37c1a
; bellydrum
callfar GetHalfMaxHP
callfar CheckUserHasEnoughHP
2017-12-13 01:15:07 +00:00
jr nc, .failed
call BattleCommand_AttackUp2
ld a, [wAttackMissed]
2017-12-13 01:15:07 +00:00
and a
jr nz, .failed
```
## Confusion damage is affected by type-boosting items and Explosion/Self-Destruct doubling
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
([Video](https://twitter.com/crystal_rby/status/874626362287562752))
*To do:* Identify specific code causing this bug and fix it.
## Moves that lower Defense can do so after breaking a Substitute
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
([Video](https://www.youtube.com/watch?v=OGwKPRJLaaI))
This bug affects Acid, Iron Tail, and Rock Smash.
This is a bug with `DefenseDownHit` in [data/moves/effects.asm](/data/moves/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
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
([Video](https://www.youtube.com/watch?v=uRYyzKRatFk))
*To do:* Identify specific code causing this bug and fix it.
## A Disabled but PP Upenhanced move may not trigger Struggle
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
([Video](https://www.youtube.com/watch?v=1v9x4SgMggs))
This is a bug with `CheckPlayerHasUsableMoves` in [engine/battle/core.asm](/engine/battle/core.asm):
```asm
.done
; Bug: this will result in a move with PP Up confusing the game.
and a ; should be "and PP_MASK"
ret nz
.force_struggle
ld hl, BattleText_MonHasNoMovesLeft
call StdBattleTextBox
ld c, 60
call DelayFrames
xor a
ret
```
**Fix:** Change `and a` to `and PP_MASK`.
## A Pokémon that fainted from Pursuit will have its old status condition when revived
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
([Video](https://www.youtube.com/watch?v=tiRvw-Nb2ME))
*To do:* Identify specific code causing this bug and fix it.
2017-12-15 02:45:35 +00:00
## Lock-On and Mind Reader don't always bypass Fly and Dig
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
2017-12-15 02:45:35 +00: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.
This is a bug with `CheckHiddenOpponent` in [engine/battle/effect_commands.asm](/engine/battle/effect_commands.asm):
2017-12-20 00:04:56 +00: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-15 02:45:35 +00:00
## Beat Up can desynchronize link battles
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
([Video](https://www.youtube.com/watch?v=202-iAsrIa8))
This is a bug with `BattleCommand_BeatUp` in [engine/battle/move_effects/beat_up.asm](/engine/battle/move_effects/beat_up.asm):
```asm
.got_mon
ld a, [wd002]
ld hl, wPartyMonNicknames
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, [wCurBattleMon]
; BUG: this can desynchronize link battles
; Change "cp [hl]" to "cp c" to fix
cp [hl]
ld hl, wBattleMonStatus
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
*Fixing this bug will break compatibility with standard Pokémon Crystal for 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 [engine/battle/move_effects/present.asm](/engine/battle/move_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 [engine/battle/ai/scoring.asm](/engine/battle/ai/scoring.asm):
```asm
; 80% chance to greatly encourage this move if the enemy is badly poisoned (buggy).
; Should check wPlayerSubStatus5 instead.
ld a, [wEnemySubStatus5]
bit SUBSTATUS_TOXIC, a
jr nz, .asm_38e26
```
**Fix:** Change `wEnemySubStatus5` to `wPlayerSubStatus5`.
2017-12-15 02:45:35 +00:00
## AI makes a false assumption about `CheckTypeMatchup`
In [engine/battle/effect_commands.asm](/engine/battle/effect_commands.asm):
2017-12-15 02:45:35 +00:00
```asm
BattleCheckTypeMatchup: ; 347c8
ld hl, wEnemyMonType1
2017-12-15 02:45:35 +00:00
ld a, [hBattleTurn]
and a
jr z, CheckTypeMatchup
ld hl, wBattleMonType1
2017-12-15 02:45:35 +00: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.
## 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 [engine/battle/ai/items.asm](/engine/battle/ai/items.asm):
```asm
AI_HealStatus: ; 384e0
ld a, [wCurOTMon]
ld hl, wOTPartyMon1Status
ld bc, PARTYMON_STRUCT_LENGTH
call AddNTimes
xor a
ld [hl], a
ld [wEnemyMonStatus], a
; Bug: this should reset SUBSTATUS_NIGHTMARE too
; Uncomment the lines below to fix
; ld hl, wEnemySubStatus1
; res SUBSTATUS_NIGHTMARE, [hl]
ld hl, wEnemySubStatus5
res SUBSTATUS_TOXIC, [hl]
ret
; 384f7
```
**Fix:** Uncomment `ld hl, wEnemySubStatus1` and `res SUBSTATUS_NIGHTMARE, [hl]`.
2017-12-13 03:58:20 +00:00
## HP bar animation is slow for high HP
2017-12-13 01:15:07 +00:00
([Video](https://www.youtube.com/watch?v=SE-BfsFgZVM))
This is a bug with `LongAnim_UpdateVariables` in [engine/battle/anim_hp_bar.asm](/engine/battle/anim_hp_bar.asm):
2017-12-13 01:15:07 +00:00
2017-12-13 03:58:20 +00:00
```asm
2017-12-13 01:15:07 +00: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-13 03:58:20 +00:00
## HP bar animation off-by-one error for low HP
([Video](https://www.youtube.com/watch?v=9KyNVIZxJvI))
2017-12-15 00:04:44 +00:00
This is a bug with `ShortHPBar_CalcPixelFrame` in [engine/anim_hp_bar.asm](/engine/anim_hp_bar.asm):
2017-12-13 03:58:20 +00:00
```asm
ld b, 0
; 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-13 03:58:20 +00:00
.loop
ld a, l
sub HP_BAR_LENGTH_PX
2017-12-13 03:58:20 +00: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-13 01:15:07 +00: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.
This is a bug with `CalcExpAtLevel` in [engine/experience.asm](/engine/experience.asm):
2017-12-13 01:15:07 +00:00
2017-12-13 03:58:20 +00:00
```asm
2017-12-13 01:15:07 +00:00
CalcExpAtLevel: ; 50e47
; (a/b)*n**3 + c*n**2 + d*n - e
ld a, [wBaseGrowthRate]
2017-12-13 01:15:07 +00:00
add a
add a
ld c, a
ld b, 0
ld hl, GrowthRates
add hl, bc
```
**Fix:**
2017-12-13 03:58:20 +00:00
```asm
2017-12-13 01:15:07 +00: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
ld a, [wBaseGrowthRate]
2017-12-13 01:15:07 +00: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))
This is a bug with `Text_ABoostedStringBuffer2ExpPoints` and `Text_StringBuffer2ExpPoints` in [data/text/common_2.asm](/data/text/common_2.asm):
2017-12-13 01:15:07 +00:00
2017-12-13 03:58:20 +00:00
```asm
2017-12-13 01:15:07 +00:00
Text_ABoostedStringBuffer2ExpPoints::
text_start
2017-12-13 01:15:07 +00:00
line "a boosted"
cont "@"
deciram wStringBuffer2, 2, 4
2017-12-13 01:15:07 +00:00
text " EXP. Points!"
prompt
Text_StringBuffer2ExpPoints::
text_start
2017-12-13 01:15:07 +00:00
line "@"
deciram wStringBuffer2, 2, 4
2017-12-13 01:15:07 +00:00
text " EXP. Points!"
prompt
```
**Fix:** Change both `deciram wStringBuffer2, 2, 4` to `deciram wStringBuffer2, 2, 5`.
2017-12-13 03:58:20 +00:00
2017-12-13 01:15:07 +00:00
## BRN/PSN/PAR do not affect catch rate
2018-02-05 18:03:05 +00:00
This is a bug with `PokeBallEffect` in [engine/item_effects.asm](/engine/item_effects.asm):
2017-12-13 01:15:07 +00:00
2017-12-13 03:58:20 +00:00
```asm
2017-12-13 01:15:07 +00: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
ld a, [wEnemyMonStatus]
2017-12-13 01:15:07 +00:00
and 1 << FRZ | SLP
ld c, 10
jr nz, .addstatus
; ld a, [wEnemyMonStatus]
2017-12-13 01:15:07 +00: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
```
**Fix:** Uncomment `ld a, [wEnemyMonStatus]`.
2017-12-13 01:15:07 +00:00
## Moon Ball does not boost catch rate
2017-12-15 00:04:44 +00:00
This is a bug with `MoonBallMultiplier` in [items/item_effects.asm](/items/item_effects.asm):
2017-12-13 01:15:07 +00:00
2017-12-13 03:58:20 +00:00
```asm
2017-12-13 01:15:07 +00: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-15 00:04:44 +00:00
This is a bug with `LoveBallMultiplier` in [items/item_effects.asm](/items/item_effects.asm):
2017-12-13 01:15:07 +00:00
2017-12-13 03:58:20 +00:00
```asm
2017-12-13 01:15:07 +00: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-15 00:04:44 +00:00
This is a bug with `FastBallMultiplier` in [items/item_effects.asm](/items/item_effects.asm):
2017-12-13 01:15:07 +00:00
2017-12-13 03:58:20 +00:00
```asm
2017-12-13 01:15:07 +00: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-13 02:29:53 +00:00
## Dragon Scale, not Dragon Fang, boosts Dragon-type moves
2017-12-13 01:15:07 +00:00
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
This is a bug with `ItemAttributes` in [data/items/attributes.asm](/data/items/attributes.asm):
2017-12-13 01:15:07 +00:00
2017-12-13 03:58:20 +00:00
```asm
2018-02-04 03:57:57 +00:00
; DRAGON_FANG
2017-12-13 01:15:07 +00:00
item_attribute 100, 0, 0, CANT_SELECT, ITEM, ITEMMENU_NOUSE, ITEMMENU_NOUSE
...
2018-02-04 03:57:57 +00:00
; DRAGON_SCALE
2017-12-13 01:15:07 +00:00
item_attribute 2100, HELD_DRAGON_BOOST, 10, CANT_SELECT, ITEM, ITEMMENU_NOUSE, ITEMMENU_NOUSE
```
2018-02-04 03:57:57 +00:00
**Fix:** Move `HELD_DRAGON_BOOST` to the `DRAGON_FANG` attributes and `0` to `DRAGON_SCALE`.
2017-12-13 01:15:07 +00:00
2017-12-18 00:48:04 +00:00
## Daisy's grooming doesn't always increase happiness
2017-12-13 01:15:07 +00:00
2018-02-04 17:03:31 +00:00
This is a bug with `HaircutOrGrooming` in [engine/events/specials_2.asm](/engine/events/specials_2.asm):
2017-12-13 01:15:07 +00:00
2017-12-13 03:58:20 +00:00
```asm
2017-12-13 01:15:07 +00:00
; Bug: Subtracting $ff from $ff fails to set c.
; This can result in overflow into the next data array.
2018-01-23 05:11:23 +00:00
; In the case of getting a grooming from Daisy, we bleed
2017-12-13 01:15:07 +00: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]
ld [wScriptVar], a
2017-12-13 01:15:07 +00:00
ld c, [hl]
call ChangeHappiness
ret
...
INCLUDE "data/events/happiness_probabilities.asm"
2017-12-13 01:15:07 +00:00
CopyPokemonName_Buffer1_Buffer3: ; 746e
ld hl, wStringBuffer1
ld de, wStringBuffer3
2018-01-20 17:25:55 +00:00
ld bc, MON_NAME_LENGTH
2017-12-13 01:15:07 +00:00
jp CopyBytes
```
In [data/events/happiness_probabilities.asm](/data/events/happiness_probabilities.asm):
2018-01-26 19:36:59 +00:00
```asm
HappinessData_DaisysGrooming: ; 746b
db $ff, 2, HAPPINESS_GROOMING ; 99.6% chance
```
2017-12-13 01:15:07 +00:00
**Fix:**
2017-12-13 03:58:20 +00:00
```asm
2018-01-26 19:36:59 +00:00
HappinessData_DaisysGrooming: ; 746b
2018-01-23 05:11:23 +00:00
db $80, 2, HAPPINESS_GROOMING ; 50% chance
db $ff, 2, HAPPINESS_GROOMING ; 50% chance
2017-12-13 01:15:07 +00:00
```
2017-12-13 03:58:20 +00:00
## Magikarp in Lake of Rage are shorter, not longer
This is a bug with `LoadEnemyMon.CheckMagikarpArea` in [engine/battle/core.asm](/engine/battle/core.asm):
2017-12-13 03:58:20 +00:00
```asm
.CheckMagikarpArea:
; 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-13 03:58:20 +00:00
; This also means Lake of Rage Magikarp can be smaller than ones
; 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-13 03:58:20 +00: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-13 03:58:20 +00:00
cp GROUP_LAKE_OF_RAGE
jr z, .Happiness
ld a, [wMapNumber]
2017-12-13 03:58:20 +00:00
cp MAP_LAKE_OF_RAGE
jr z, .Happiness
```
**Fix:** Change both `jr z, .Happiness` to `jr nz, .Happiness`.
## Magikarp length limits have a unit conversion error
This is a bug with `LoadEnemyMon.CheckMagikarpArea` in [engine/battle/core.asm](/engine/battle/core.asm):
```asm
; Get Magikarp's length
ld de, wEnemyMonDVs
ld bc, wPlayerID
callfar CalcMagikarpLength
; No reason to keep going if length > 1536 mm (i.e. if HIGH(length) > 6 feet)
ld a, [wMagikarpLength]
cp HIGH(1536) ; should be "cp 5", since 1536 mm = 5'0", but HIGH(1536) = 6
jr nz, .CheckMagikarpArea
; 5% chance of skipping both size checks
call Random
cp 5 percent
jr c, .CheckMagikarpArea
; Try again if length >= 1616 mm (i.e. if LOW(length) >= 3 inches)
ld a, [wMagikarpLength + 1]
cp LOW(1616) ; should be "cp 3", since 1616 mm = 5'3", but LOW(1616) = 80
jr nc, .GenerateDVs
; 20% chance of skipping this check
call Random
cp 20 percent - 1
jr c, .CheckMagikarpArea
; Try again if length >= 1600 mm (i.e. if LOW(length) >= 2 inches)
ld a, [wMagikarpLength + 1]
cp LOW(1600) ; should be "cp 2", since 1600 mm = 5'2", but LOW(1600) = 64
jr nc, .GenerateDVs
```
**Fix:** Change the three `cp` instructions to use their commented values.
## Magikarp lengths can be miscalculated
2017-12-27 05:09:12 +00:00
This is a bug with `CalcMagikarpLength.BCLessThanDE` in [engine/events/magikarp.asm](/engine/events/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`.
2017-12-13 03:58:20 +00:00
## 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/battle_transition.asm](/engine/battle/battle_transition.asm):
2017-12-13 03:58:20 +00:00
2017-12-13 04:05:30 +00:00
```asm
2017-12-13 03:58:20 +00: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.
; BUG: wBattleMonLevel and wEnemyMonLevel are not set at this point, so whatever
2017-12-13 03:58:20 +00:00
; values happen to be there will determine the animation.
ld de, 0
ld a, [wBattleMonLevel]
2017-12-13 03:58:20 +00:00
add 3
ld hl, wEnemyMonLevel
2017-12-13 03:58:20 +00:00
cp [hl]
jr nc, .okay
set 0, e
.okay
2018-01-26 19:36:59 +00:00
ld a, [wEnvironment]
2017-12-13 03:58:20 +00:00
cp CAVE
jr z, .okay2
2018-01-26 19:36:59 +00:00
cp ENVIRONMENT_5
2017-12-13 03:58:20 +00: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.
2018-02-26 16:51:16 +00:00
## A "HOF Master!" title for 201-Time Famers is defined but inaccessible
([Video](https://www.youtube.com/watch?v=iHkWubvxmSg))
This is a bug with `HallOfFame` in [engine/events/halloffame.asm](/engine/events/halloffame.asm):
```asm
ld hl, wHallOfFameCount
ld a, [hl]
cp HOF_MASTER_COUNT - 1 ; should be HOF_MASTER_COUNT
jr nc, .ok
inc [hl]
.ok
```
**Fix:** Change `HOF_MASTER_COUNT - 1` to `HOF_MASTER_COUNT`.
2017-12-15 02:45:35 +00: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
ld a, [wSlotsDelay]
2017-12-15 02:45:35 +00: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`.
## Team Rocket battle music is not used for Executives or Scientists
This is a bug with `PlayBattleMusic` in [engine/battle/start_battle.asm](/engine/battle/start_battle.asm):
```asm
; They should have included EXECUTIVEM, EXECUTIVEF, and SCIENTIST 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
```
2017-12-13 01:15:07 +00:00
## No bump noise if standing on tile `$3E`
2017-12-15 00:04:44 +00:00
This is a bug with `DoPlayerMovement.CheckWarp` in [engine/player_movement.asm](/engine/player_movement.asm):
2017-12-13 01:15:07 +00:00
2017-12-13 03:58:20 +00:00
```asm
2017-12-13 01:15:07 +00: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.
ld a, [wWalkingDirection]
2017-12-21 17:11:35 +00:00
; cp STANDING
; jr z, .not_warp
2017-12-13 01:15:07 +00:00
ld e, a
ld d, 0
ld hl, .EdgeWarps
add hl, de
ld a, [wPlayerStandingTile]
2017-12-13 01:15:07 +00:00
cp [hl]
jr nz, .not_warp
ld a, 1
ld [wd041], a
ld a, [wWalkingDirection]
2017-12-21 17:11:35 +00:00
; This is in the wrong place.
2017-12-13 01:15:07 +00:00
cp STANDING
jr z, .not_warp
```
**Fix:**
2017-12-13 03:58:20 +00:00
```asm
ld a, [wWalkingDirection]
2017-12-13 01:15:07 +00:00
cp STANDING
jr z, .not_warp
ld e, a
ld d, 0
ld hl, .EdgeWarps
add hl, de
ld a, [wPlayerStandingTile]
2017-12-13 01:15:07 +00:00
cp [hl]
jr nz, .not_warp
ld a, 1
ld [wd041], a
ld a, [wWalkingDirection]
2017-12-13 01:15:07 +00: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 23:00:23 +00:00
The exact cause is unknown, but a workaround exists for `DexEntryScreen_MenuActionJumptable.Cry` in [engine/pokedex/pokedex.asm](/engine/pokedex/pokedex.asm):
```asm
.Cry: ; 40340
call Pokedex_GetSelectedMon
ld a, [wd265]
call GetCryIndex
ld e, c
ld d, b
call PlayCry
ret
```
**Workaround:**
```asm
.Cry: ; 40340
ld a, [CurPartySpecies]
call PlayMonCry
ret
```
2017-12-22 22:52:34 +00: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 17:08:34 +00:00
![image](/docs/images/hp_exp_bar_border.png)
2017-12-22 22:52:34 +00:00
**Fix:** Lower the ellipsis by two pixels:
2017-12-23 17:08:34 +00:00
![image](/docs/images/hp_exp_bar_border_fix.png)
2017-12-22 22:52:34 +00:00
2017-12-22 22:59:50 +00:00
## Two tiles in the `port` tileset are drawn incorrectly
2017-12-22 23:01:06 +00: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 22:59:50 +00:00
2017-12-23 17:08:34 +00:00
![image](/docs/images/port.png)
2017-12-22 22:59:50 +00:00
**Fix:** Adjust them to match the right-hand corner tiles:
2017-12-23 17:08:34 +00:00
![image](/docs/images/port_fix.png)
2017-12-22 22:59:50 +00:00
## `LoadMetatiles` wraps around past 128 blocks
This bug prevents you from using blocksets with more than 128 blocks.
2017-12-13 04:05:30 +00:00
In [home/map.asm](/home/map.asm):
2017-12-13 04:05:30 +00:00
```asm
; Set hl to the address of the current metatile data ([wTilesetBlocksAddress] + (a) tiles).
2017-12-13 04:05:30 +00: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
ld a, [wTilesetBlocksAddress]
2017-12-13 04:05:30 +00:00
add l
ld l, a
ld a, [wTilesetBlocksAddress + 1]
2017-12-13 04:05:30 +00:00
adc h
ld h, a
```
**Fix:** Delete `add a` and uncomment `add hl, hl`.
2017-12-13 03:58:20 +00: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 16:43:41 +00:00
## `Function6ec1` does not correctly limit object movement
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 16:43:41 +00: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-13 01:15:07 +00: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.
In [engine/search.asm](/engine/search.asm):
2017-12-13 01:15:07 +00:00
2017-12-13 03:58:20 +00:00
```asm
2017-12-13 01:15:07 +00: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.
ld hl, wPlayerName
2017-12-13 01:15:07 +00:00
rept NAME_LENGTH_JAPANESE + -2 ; should be PLAYER_NAME_LENGTH + -2
2017-12-13 01:15:07 +00: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
```
**Fix:** Change `rept NAME_LENGTH_JAPANESE + -2` to `rept PLAYER_NAME_LENGTH + -2`.
2017-12-13 01:15:07 +00: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 18:03:05 +00:00
This is a bug with `PokeBallEffect` in [engine/item_effects.asm](/engine/item_effects.asm):
2017-12-20 00:04:56 +00:00
```asm
ld hl, wEnemySubStatus5
2017-12-20 00:04:56 +00: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.
; To fix, do not set [wTempEnemyMonSpecies] to DITTO.
2017-12-20 00:04:56 +00:00
bit SUBSTATUS_TRANSFORMED, a
jr nz, .ditto
jr .not_ditto
.ditto
ld a, DITTO
ld [wTempEnemyMonSpecies], a
2017-12-20 00:04:56 +00:00
jr .load_data
.not_ditto
set SUBSTATUS_TRANSFORMED, [hl]
ld hl, wEnemyBackupDVs
ld a, [wEnemyMonDVs]
2017-12-20 00:04:56 +00:00
ld [hli], a
ld a, [wEnemyMonDVs + 1]
2017-12-20 00:04:56 +00:00
ld [hl], a
.load_data
ld a, [wTempEnemyMonSpecies]
ld [wCurPartySpecies], a
ld a, [wEnemyMonLevel]
ld [wCurPartyLevel], a
farcall LoadEnemyMon
2017-12-20 00:04:56 +00:00
pop af
ld [wEnemySubStatus5], a
2017-12-20 00:04:56 +00:00
```
**Fix:**
```asm
ld hl, wEnemySubStatus5
2017-12-20 00:04:56 +00:00
ld a, [hl]
push af
set SUBSTATUS_TRANSFORMED, [hl]
bit SUBSTATUS_TRANSFORMED, a
jr nz, .load_data
ld hl, wEnemyBackupDVs
ld a, [wEnemyMonDVs]
2017-12-20 00:04:56 +00:00
ld [hli], a
ld a, [wEnemyMonDVs + 1]
2017-12-20 00:04:56 +00:00
ld [hl], a
.load_data
ld a, [wTempEnemyMonSpecies]
ld [wCurPartySpecies], a
ld a, [wEnemyMonLevel]
ld [wCurPartyLevel], a
farcall LoadEnemyMon
2017-12-20 00:04:56 +00:00
pop af
ld [wEnemySubStatus5], a
2017-12-20 00:04:56 +00:00
```
## Using a Park Ball in normal battles has a corrupt animation
([Video](https://www.youtube.com/watch?v=v1ErZdLCIyU))
2018-02-05 18:03:05 +00:00
This is a bug with `PokeBallEffect` in [engine/item_effects.asm](/engine/item_effects.asm):
```asm
.room_in_party
xor a
ld [wWildMon], a
ld a, [wCurItem]
cp PARK_BALL
call nz, ReturnToBattle_UseBall
```
**Fix:**
```asm
.room_in_party
xor a
ld [wWildMon], a
ld a, [wBattleType]
cp BATTLETYPE_CONTEST
call nz, ReturnToBattle_UseBall
```
2017-12-13 01:15:07 +00:00
## `HELD_CATCH_CHANCE` has no effect
2018-02-05 18:03:05 +00:00
This is a bug with `PokeBallEffect` in [engine/item_effects.asm](/engine/item_effects.asm):
2017-12-13 01:15:07 +00:00
2017-12-13 03:58:20 +00:00
```asm
; BUG: farcall overwrites a, and GetItemHeldEffect takes b anyway.
; This is probably the reason the HELD_CATCH_CHANCE effect is never used.
2017-12-13 01:15:07 +00:00
; Uncomment the line below to fix.
ld d, a
push de
ld a, [wBattleMonItem]
; ld b, a
farcall GetItemHeldEffect
2017-12-13 01:15:07 +00:00
ld a, b
cp HELD_CATCH_CHANCE
pop de
ld a, d
jr nz, .max_2
add c
jr nc, .max_2
ld a, $ff
.max_2
2017-12-13 01:15:07 +00:00
```
**Fix:** Uncomment `ld b, a`.
## Only the first three `EvosAttacks` evolution entries can have Stone compatibility reported correctly
2017-12-15 00:04:44 +00:00
This is a bug with `PlacePartyMonEvoStoneCompatibility.DetermineCompatibility` in [engine/party_menu.asm](/engine/party_menu.asm):
```asm
.DetermineCompatibility: ; 50268
ld de, wStringBuffer1
ld a, BANK(EvosAttacksPointers)
ld bc, 2
call FarCopyBytes
ld hl, wStringBuffer1
ld a, [hli]
ld h, [hl]
ld l, a
ld de, wStringBuffer1
ld a, BANK(EvosAttacks)
2018-01-26 19:36:59 +00:00
ld bc, 10
call FarCopyBytes
```
**Fix:** Change `ld bc, 10` to `ld bc, wStringBuffer2 - wStringBuffer1` to support up to six Stone entries.
2018-02-26 18:41:48 +00:00
## `EVOLVE_STAT` can break Stone compatibility reporting
This is a bug with `PlacePartyMonEvoStoneCompatibility.DetermineCompatibility` in [engine/party_menu.asm](/engine/party_menu.asm):
```asm
.loop2
ld a, [hli]
and a
jr z, .nope
inc hl
inc hl
cp EVOLVE_ITEM
jr nz, .loop2
```
**Fix:**
```asm
.loop2
ld a, [hli]
and a
jr z, .nope
cp EVOLVE_STAT
jr nz, .not_four_bytes
inc hl
.not_four_bytes
inc hl
inc hl
cp EVOLVE_ITEM
jr nz, .loop2
```
2017-12-13 01:15:07 +00:00
## `ScriptCall` can overflow `wScriptStack` and crash
In [engine/scripting.asm](/engine/scripting.asm):
2017-12-13 01:15:07 +00:00
2017-12-13 03:58:20 +00:00
```asm
2017-12-13 01:15:07 +00: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
; to wScriptDelay, causing the script to return to the rst/interrupt
2017-12-13 01:15:07 +00: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
ld a, [wScriptBank]
2017-12-13 01:15:07 +00:00
ld [hli], a
ld a, [wScriptPos]
2017-12-13 01:15:07 +00:00
ld [hli], a
ld a, [wScriptPos + 1]
2017-12-13 01:15:07 +00:00
ld [hl], a
ld a, b
ld [wScriptBank], a
2017-12-13 01:15:07 +00:00
ld a, e
ld [wScriptPos], a
2017-12-13 01:15:07 +00:00
ld a, d
ld [wScriptPos + 1], a
2017-12-13 01:15:07 +00:00
ret
```
2018-01-26 19:36:59 +00:00
*To do:* Fix this bug.
2017-12-13 01:15:07 +00:00
## `LoadSpriteGFX` does not limit the capacity of `UsedSprites`
In [engine/overworld.asm](/engine/overworld.asm):
2017-12-13 01:15:07 +00:00
2017-12-13 03:58:20 +00:00
```asm
2017-12-13 01:15:07 +00:00
LoadSpriteGFX: ; 14306
2017-12-21 17:11:35 +00:00
; Bug: b is not preserved, so it's useless as a next count.
; Uncomment the lines below to fix.
2017-12-13 01:15:07 +00:00
ld hl, wUsedSprites
2017-12-13 01:15:07 +00: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 17:11:35 +00:00
; push bc
2017-12-13 01:15:07 +00:00
call GetSprite
2017-12-21 17:11:35 +00:00
; pop bc
2017-12-13 01:15:07 +00:00
ld a, l
ret
; 1431e
```
2017-12-21 17:11:35 +00:00
**Fix:** Uncomment `push bc` and `pop bc`.
2017-12-13 01:15:07 +00:00
## `ChooseWildEncounter` doesn't really validate the wild Pokémon species
In [engine/wildmons.asm](/engine/wildmons.asm):
2017-12-13 01:15:07 +00:00
2017-12-13 03:58:20 +00:00
```asm
2017-12-13 01:15:07 +00:00
ChooseWildEncounter: ; 2a14f
...
ld a, b
ld [wCurPartyLevel], a
2017-12-13 01:15:07 +00: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-13 03:58:20 +00:00
```asm
2017-12-13 01:15:07 +00:00
ld a, b
ld [wCurPartyLevel], a
2017-12-13 01:15:07 +00:00
ld b, [hl]
ld a, b
call ValidateTempWildMonSpecies
jr c, .nowildbattle
cp UNOWN
jr nz, .done
```
## `TryObjectEvent` arbitrary code execution
In [engine/events.asm](/engine/events.asm):
2017-12-13 01:15:07 +00:00
2017-12-13 03:58:20 +00:00
```asm
2017-12-13 01:15:07 +00: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`.
## `CheckBugContestContestantFlag` can read beyond its data table
2017-12-13 01:15:07 +00:00
2017-12-27 05:09:12 +00:00
In [engine/events/bug_contest/contest_2.asm](/engine/events/bug_contest/contest_2.asm):
2017-12-13 01:15:07 +00:00
2017-12-13 03:58:20 +00:00
```asm
CheckBugContestContestantFlag: ; 139ed
2017-12-13 01:15:07 +00:00
; Checks the flag of the Bug Catching Contestant whose index is loaded in a.
2018-01-26 19:36:59 +00:00
; Bug: If a >= NUM_BUG_CONTESTANTS when this is called,
; it will read beyond the table.
2017-12-13 01:15:07 +00: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 19:36:59 +00:00
INCLUDE "data/events/bug_contest_flags.asm"
2017-12-13 01:15:07 +00:00
```
2018-01-26 19:36:59 +00:00
However, `a < NUM_BUG_CONTESTANTS` should always be true, so in practice this is not a problem.
2017-12-13 01:15:07 +00:00
## `ClearWRAM` only clears WRAM bank 1
In [home/init.asm](/home/init.asm):
2017-12-13 01:15:07 +00:00
2017-12-13 03:58:20 +00:00
```asm
2017-12-13 01:15:07 +00: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
ld hl, WRAM1_Begin
ld bc, WRAM1_End - WRAM1_Begin
2017-12-13 01:15:07 +00: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`.