ref: 10eb426e40f48df3ae9b40e3ea3aa7e92f890090
parent: c85587d973df6565f2863493acb9f9af88518662
author: Remy Oukaour <remy.oukaour@gmail.com>
date: Tue Dec 12 17:58:20 EST 2017
Document more bugs
--- a/battle/ai/items.asm
+++ b/battle/ai/items.asm
@@ -749,7 +749,7 @@
Function384d5: ; This appears to be unused
call AIUsedItemSound
call AI_HealStatus
- ld a, X_SPEED
+ ld a, FULL_HEAL_RED ; X_SPEED
jp PrintText_UsedItemOn_AND_AIUpdateHUD
; 384e0
@@ -761,6 +761,10 @@
xor a
ld [hl], a
ld [EnemyMonStatus], a
+ ; Bug: this should reset SUBSTATUS_NIGHTMARE too
+ ; Uncomment the lines below to fix
+ ; ld hl, EnemySubStatus1
+ ; res SUBSTATUS_NIGHTMARE, [hl]
ld hl, EnemySubStatus5
res SUBSTATUS_TOXIC, [hl]
ret
--- a/battle/ai/scoring.asm
+++ b/battle/ai/scoring.asm
@@ -1876,7 +1876,8 @@
pop hl
jp z, AIDiscourageMove
-; 80% chance to greatly encourage this move if the enemy is badly poisoned (weird).
+; 80% chance to greatly encourage this move if the enemy is badly poisoned (buggy).
+; Should check PlayerSubStatus5 instead.
ld a, [EnemySubStatus5]
bit SUBSTATUS_TOXIC, a
jr nz, .asm_38e26
--- a/battle/core.asm
+++ b/battle/core.asm
@@ -5998,7 +5998,7 @@
swap a
and $f
ld b, a
- ld d, $5
+ ld d, NUM_MOVES + 1
xor a
.loop
dec d
@@ -6011,7 +6011,9 @@
jr .loop
.done
- and a ; This is probably a bug, and will result in a move with PP Up confusing the game.
+ ; Bug: this will result in a move with PP Up confusing the game.
+ ; Replace with "and $3f" to fix.
+ and a
ret nz
.force_struggle
--- a/constants/item_constants.asm
+++ b/constants/item_constants.asm
@@ -272,6 +272,7 @@
; leftovers from red
SAFARI_BALL EQU $08 ; MOON_STONE
MOON_STONE_RED EQU $0A ; BURN_HEAL
+FULL_HEAL_RED EQU $34 ; X_SPEED
MAIL_MSG_LENGTH EQU $20
--- a/docs/bugs.md
+++ b/docs/bugs.md
@@ -1,6 +1,96 @@
# Bugs and Glitches
+## Thick Club and Light Ball can decrease damage done with boosted (Special) Attack
+
+([Video](https://www.youtube.com/watch?v=rGqu3d3pdok&t=450))
+
+This is a bug with `SpeciesItemBoost` in [battle/effect_commands.asm](battle/effect_commands.asm):
+
+```asm
+; Double the stat
+ sla l
+ rl h
+ ret
+```
+
+**Fix:**
+
+```asm
+; Double the stat
+ sla l
+ rl h
+
+ ld a, 999 / $100
+ cp h
+ jr c, .cap
+ ld a, 999 % $100
+ cp l
+ ret nc
+
+.cap
+ ld h, 999 / $100
+ ld l, 999 % $100
+ ret
+```
+
+
+## Metal Powder can increase damage taken with boosted (Special) Defense
+
+([Video](https://www.youtube.com/watch?v=rGqu3d3pdok&t=450))
+
+This is a bug with `DittoMetalPowder` in [battle/effect_commands.asm](battle/effect_commands.asm):
+
+```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, 999 / $100
+ cp b
+ jr c, .cap
+ ld a, 999 % $100
+ cp c
+ ret nc
+
+.cap
+ ld b, 999 / $100
+ ld c, 999 % $100
+ ret
+```
+
+
## Belly Drum sharply boosts Attack even with under 50% HP
([Video](https://www.youtube.com/watch?v=zuCLMikWo4Y))
@@ -7,7 +97,7 @@
This is a bug with `BattleCommand_BellyDrum` in [battle/effect_commands.asm](battle/effect_commands.asm):
-```
+```asm
BattleCommand_BellyDrum: ; 37c1a
; bellydrum
; This command is buggy because it raises the user's attack
@@ -25,7 +115,7 @@
**Fix:**
-```
+```asm
BattleCommand_BellyDrum: ; 37c1a
; bellydrum
callab GetHalfMaxHP
@@ -39,13 +129,13 @@
```
-## HP bar animation is slower with more HP
+## HP bar animation is slow for high HP
([Video](https://www.youtube.com/watch?v=SE-BfsFgZVM))
This is a bug with `LongAnim_UpdateVariables` in [engine/anim_hp_bar.asm](engine/anim_hp_bar.asm):
-```
+```asm
; 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.
@@ -67,6 +157,32 @@
**Fix:** Move `ld a, e` to right after `call ComputeHPBarPixels`.
+## HP bar animation off-by-one error for low HP
+
+([Video](https://www.youtube.com/watch?v=9KyNVIZxJvI))
+
+This is a bug with `ShortHPBar_CalcPixelFrame` in [engine/anim_hp_bar.asm](engine/anim_hp_bar.asm):
+
+```asm
+ ld b, 0
+; This routine is buggy. If [wCurHPAnimMaxHP] * [wCurHPBarPixels] is divisible
+; by 48, the loop runs one extra time. To fix, uncomment the line below.
+.loop
+ ld a, l
+ sub 6 * 8
+ 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`.
+
+
## Experience underflow for level 1 Pokémon with Medium-Slow growth rate
([Video](https://www.youtube.com/watch?v=SXH8u0plHrE))
@@ -75,7 +191,7 @@
This is a bug with `CalcExpAtLevel` in [main.asm](main.asm):
-```
+```asm
CalcExpAtLevel: ; 50e47
; (a/b)*n**3 + c*n**2 + d*n - e
ld a, [BaseGrowthRate]
@@ -89,7 +205,7 @@
**Fix:**
-```
+```asm
CalcExpAtLevel: ; 50e47
; (a/b)*n**3 + c*n**2 + d*n - e
ld a, d
@@ -121,7 +237,7 @@
This is a bug with `Text_ABoostedStringBuffer2ExpPoints` and `Text_StringBuffer2ExpPoints` in [text/common_2.asm](text/common_2.asm):
-```
+```asm
Text_ABoostedStringBuffer2ExpPoints::
text ""
line "a boosted"
@@ -138,9 +254,86 @@
prompt
```
-**Fix:** Change `deciram StringBuffer2, 2, 4` to `deciram StringBuffer2, 2, 5`.
+**Fix:** Change both `deciram StringBuffer2, 2, 4` to `deciram StringBuffer2, 2, 5`.
+## NPC use of Full Heal or Full Restore does not cure Nightmare status
+
+([Video](https://www.youtube.com/watch?v=rGqu3d3pdok&t=322)
+
+This is a bug with `AI_HealStatus` in [battle/ai/items.asm](battle/ai/items.asm):
+
+```asm
+AI_HealStatus: ; 384e0
+ ld a, [CurOTMon]
+ ld hl, OTPartyMon1Status
+ ld bc, PARTYMON_STRUCT_LENGTH
+ call AddNTimes
+ xor a
+ ld [hl], a
+ ld [EnemyMonStatus], a
+ ; Bug: this should reset SUBSTATUS_NIGHTMARE too
+ ; Uncomment the lines below to fix
+ ; ld hl, EnemySubStatus1
+ ; res SUBSTATUS_NIGHTMARE, [hl]
+ ld hl, EnemySubStatus5
+ res SUBSTATUS_TOXIC, [hl]
+ ret
+; 384f7
+```
+
+**Fix:** Uncomment `ld hl, EnemySubStatus1` and `res SUBSTATUS_NIGHTMARE, [hl]`.
+
+
+## "Smart" AI encourages Mean Look if its own Pokémon is badly poisoned
+
+([Video](https://www.youtube.com/watch?v=cygMO-zHTls))
+
+This is a bug with `AI_Smart_MeanLook` in [battle/ai/scoring.asm](battle/ai/scoring.asm):
+
+```asm
+; 80% chance to greatly encourage this move if the enemy is badly poisoned (buggy).
+; Should check PlayerSubStatus5 instead.
+ ld a, [EnemySubStatus5]
+ bit SUBSTATUS_TOXIC, a
+ jr nz, .asm_38e26
+```
+
+**Fix:** Change `EnemySubStatus5` to `PlayerSubStatus5`.
+
+
+## A Disabled, PP Up–enhanced move may not trigger automatic Struggling
+
+([Video](https://www.youtube.com/watch?v=1v9x4SgMggs))
+
+This is a bug with `CheckPlayerHasUsableMoves` in [battle/core.asm](battle/core.asm):
+
+```asm
+.done
+ ; Bug: this will result in a move with PP Up confusing the game.
+ ; Replace with "and $3f" to fix.
+ and a
+ ret nz
+
+.force_struggle
+ ld hl, BattleText_PkmnHasNoMovesLeft
+ call StdBattleTextBox
+ ld c, 60
+ call DelayFrames
+ xor a
+ ret
+```
+
+**Fix:** Change `and a` to `and $3f`.
+
+
+## Counter and Mirror Coat still work if the opponent uses an item
+
+([Video](https://www.youtube.com/watch?v=uRYyzKRatFk))
+
+*To do:* Identify specific code causing this bug and fix it.
+
+
## Present damage is incorrect in link battles
([Video](https://www.youtube.com/watch?v=XJaQoKtrEuw))
@@ -149,7 +342,7 @@
This is a bug with `BattleCommand_Present` in [battle/effects/present.asm](battle/effects/present.asm):
-```
+```asm
BattleCommand_Present: ; 37874
; present
@@ -172,7 +365,7 @@
**Fix:**
-```
+```asm
BattleCommand_Present: ; 37874
; present
@@ -188,7 +381,7 @@
This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm):
-```
+```asm
.statuscheck
; 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
@@ -220,7 +413,7 @@
This is a bug with `MoonBallMultiplier` in [items/item_effects.asm](items/item_effects.asm):
-```
+```asm
MoonBallMultiplier:
; This function is buggy.
; Intent: multiply catch rate by 4 if mon evolves with moon stone
@@ -246,7 +439,7 @@
This is a bug with `LoveBallMultiplier` in [items/item_effects.asm](items/item_effects.asm):
-```
+```asm
LoveBallMultiplier:
; This function is buggy.
; Intent: multiply catch rate by 8 if mons are of same species, different sex
@@ -268,7 +461,7 @@
This is a bug with `FastBallMultiplier` in [items/item_effects.asm](items/item_effects.asm):
-```
+```asm
FastBallMultiplier:
; This function is buggy.
; Intent: multiply catch rate by 4 if enemy mon is in one of the three
@@ -294,7 +487,7 @@
This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm):
-```
+```asm
ld a, [CurItem]
cp FRIEND_BALL
jr nz, .SkipBoxMonFriendBall
@@ -311,7 +504,7 @@
This is a bug with `ItemAttributes` in [items/item_attributes.asm](items/item_attributes.asm):
-```
+```asm
; DRAGON FANG
item_attribute 100, 0, 0, CANT_SELECT, ITEM, ITEMMENU_NOUSE, ITEMMENU_NOUSE
@@ -328,7 +521,7 @@
This is a bug with `MassageOrHaircut` in [event/special.asm](event/special.asm):
-```
+```asm
; Bug: Subtracting $ff from $ff fails to set c.
; This can result in overflow into the next data array.
; In the case of getting a massage from Daisy, we bleed
@@ -366,7 +559,7 @@
**Fix:**
-```
+```asm
Data_DaisyMassage: ; 746b
db $80, 2, HAPPINESS_MASSAGE ; 50% chance
db $ff, 2, HAPPINESS_MASSAGE ; 50% chance
@@ -373,11 +566,82 @@
```
+## Magikarp in Lake of Rage are shorter, not longer
+
+This is a bug with `LoadEnemyMon.CheckMagikarpArea` in [battle/core.asm](battle/core.asm):
+
+```asm
+.CheckMagikarpArea:
+; The z checks are supposed to be nz
+; Instead, all maps in GROUP_LAKE_OF_RAGE (mahogany area)
+; and routes 20 and 44 are treated as Lake of Rage
+
+; 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 size flooring in the Lake of Rage area
+ ld a, [MapGroup]
+ cp GROUP_LAKE_OF_RAGE
+ jr z, .Happiness
+ ld a, [MapNumber]
+ cp MAP_LAKE_OF_RAGE
+ jr z, .Happiness
+```
+
+**Fix:** Change both `jr z, .Happiness` to `jr nz, .Happiness`.
+
+
+## Battle transitions fail to account for the enemy's level
+
+([Video](https://www.youtube.com/watch?v=eij_1060SMc))
+
+This is a bug with `StartTrainerBattle_DetermineWhichAnimation` in [engine/battle_start.asm](engine/battle_start.asm):
+
+```
+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: BattleMonLevel and EnemyMonLevel are not set at this point, so whatever
+; values happen to be there will determine the animation.
+ ld de, 0
+ ld a, [BattleMonLevel]
+ add 3
+ ld hl, EnemyMonLevel
+ cp [hl]
+ jr nc, .okay
+ set 0, e
+.okay
+ ld a, [wPermission]
+ cp CAVE
+ jr z, .okay2
+ cp PERM_5
+ 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.
+
+
## No bump noise if standing on tile `$3E`
This is a bug with `DoPlayerMovement.CheckWarp` in [engine/player_movement.asm](engine/player_movement.asm):
-```
+```asm
; Bug: Since no case is made for STANDING here, it will check
; [.edgewarps + $ff]. This resolves to $3e at $8035a.
; This causes wd041 to be nonzero when standing on tile $3e,
@@ -401,7 +665,7 @@
**Fix:**
-```
+```asm
ld a, [WalkingDirection]
cp STANDING
jr z, .not_warp
@@ -419,6 +683,13 @@
```
+## 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.
+
+
## `CheckOwnMon` only checks the first five letters of OT names
([Video](https://www.youtube.com/watch?v=GVTTmReM4nQ))
@@ -427,7 +698,7 @@
[engine/search.asm](engine/search.asm):
-```
+```asm
; 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.
@@ -463,7 +734,7 @@
This is a bug with `PokeBall` in [items/item_effects.asm](items/item_effects.asm):
-```
+```asm
; BUG: callba overwrites a,
; and GetItemHeldEffect takes b anyway.
@@ -487,7 +758,7 @@
[engine/scripting.asm](engine/scripting.asm):
-```
+```asm
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
@@ -525,7 +796,7 @@
[engine/overworld.asm](engine/overworld.asm):
-```
+```asm
LoadSpriteGFX: ; 14306
; Bug: b is not preserved, so
; it's useless as a next count.
@@ -560,7 +831,7 @@
[engine/wildmons.asm](engine/wildmons.asm):
-```
+```asm
ChooseWildEncounter: ; 2a14f
...
@@ -583,7 +854,7 @@
**Fix:**
-```
+```asm
ld a, b
ld [CurPartyLevel], a
ld b, [hl]
@@ -599,7 +870,7 @@
[engine/events.asm](engine/events.asm):
-```
+```asm
; Bug: If IsInArray returns nc, data at bc will be executed as code.
push bc
ld de, 3
@@ -627,7 +898,7 @@
[event/bug_contest_2.asm](event/bug_contest_2.asm):
-```
+```asm
Special_CheckBugContestContestantFlag: ; 139ed
; Checks the flag of the Bug Catching Contestant whose index is loaded in a.
@@ -665,7 +936,7 @@
[home/init.asm](home/init.asm):
-```
+```asm
ClearWRAM:: ; 25a
; Wipe swappable WRAM banks (1-7)
; Assumes CGB or AGB
@@ -693,7 +964,7 @@
[tilesets/animations.asm](tilesets/animations.asm):
-```
+```asm
GetForestTreeFrame: ; fc54c
; Return 0 if a is even, or 2 if odd.
and a
@@ -722,7 +993,7 @@
**Fix:**
-```
+```asm
GetForestTreeFrame: ; fc54c
; Return 0 if a is even, or 2 if odd.
and 1
--- a/engine/anim_hp_bar.asm
+++ b/engine/anim_hp_bar.asm
@@ -382,7 +382,10 @@
and a
jr z, .return_zero
call AddNTimes
+
ld b, 0
+; This routine is buggy. If [wCurHPAnimMaxHP] * [wCurHPBarPixels] is divisible
+; by 48, the loop runs one extra time. To fix, uncomment the line below.
.loop
ld a, l
sub 6 * 8
@@ -390,6 +393,7 @@
ld a, h
sbc $0
ld h, a
+ ; jr z, .done
jr c, .done
inc b
jr .loop
--- a/engine/battle_start.asm
+++ b/engine/battle_start.asm
@@ -196,9 +196,10 @@
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.
+; The screen flashes a different number of times depending on the level of
+; your lead Pokemon relative to the opponent's.
+; BUG: BattleMonLevel and EnemyMonLevel are not set at this point, so whatever
+; values happen to be there will determine the animation.
ld de, 0
ld a, [BattleMonLevel]
add 3