summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/bugs_and_glitches.md338
-rw-r--r--docs/design_flaws.md11
-rw-r--r--docs/event_commands.md2
-rw-r--r--docs/text_commands.md4
4 files changed, 330 insertions, 25 deletions
diff --git a/docs/bugs_and_glitches.md b/docs/bugs_and_glitches.md
index ad6114c77..7a7d80250 100644
--- a/docs/bugs_and_glitches.md
+++ b/docs/bugs_and_glitches.md
@@ -15,12 +15,16 @@ Some fixes are mentioned as breaking compatibility with link battles. This can b
## Contents
+- [Perish Song and Spikes can leave a Pokémon with 0 HP and not faint](#perish-song-and-spikes-can-leave-a-pokémon-with-0-hp-and-not-faint)
- [Thick Club and Light Ball can make (Special) Attack wrap around above 1024](#thick-club-and-light-ball-can-make-special-attack-wrap-around-above-1024)
- [Metal Powder can increase damage taken with boosted (Special) Defense](#metal-powder-can-increase-damage-taken-with-boosted-special-defense)
- [Reflect and Light Screen can make (Special) Defense wrap around above 1024](#reflect-and-light-screen-can-make-special-defense-wrap-around-above-1024)
+- [Glacier Badge may not boost Special Defense depending on the value of Special Attack](#glacier-badge-may-not-boost-special-defense-depending-on-the-value-of-special-attack)
- [Moves with a 100% secondary effect chance will not trigger it in 1/256 uses](#moves-with-a-100-secondary-effect-chance-will-not-trigger-it-in-1256-uses)
- [Belly Drum sharply boosts Attack even with under 50% HP](#belly-drum-sharply-boosts-attack-even-with-under-50-hp)
+- [Berserk Gene's confusion lasts for 256 turns or the previous Pokémon's confusion count](#berserk-genes-confusion-lasts-for-256-turns-or-the-previous-Pokémons-confusion-count)
- [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)
+- [Saves corrupted by mid-save shutoff are not handled](#saves-corrupted-by-mid-save-shutoff-are-not-handled)
- [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)
@@ -31,9 +35,11 @@ Some fixes are mentioned as breaking compatibility with link battles. This can b
- [Beat Up may fail to raise Substitute](#beat-up-may-fail-to-raise-substitute)
- [Beat Up may trigger King's Rock even if it failed](#beat-up-may-trigger-kings-rock-even-if-it-failed)
- [Present damage is incorrect in link battles](#present-damage-is-incorrect-in-link-battles)
+- [A Transformed Pokémon can use Sketch and learn otherwise unobtainable moves](#a-transformed-pokémon-can-use-sketch-and-learn-otherwise-unobtainable-moves)
- ["Smart" AI encourages Mean Look if its own Pokémon is badly poisoned](#smart-ai-encourages-mean-look-if-its-own-pokémon-is-badly-poisoned)
- [AI makes a false assumption about `CheckTypeMatchup`](#ai-makes-a-false-assumption-about-checktypematchup)
- [NPC use of Full Heal or Full Restore does not cure Nightmare status](#npc-use-of-full-heal-or-full-restore-does-not-cure-nightmare-status)
+- [NPC use of Full Heal does not cure confusion status](#npc-use-of-full-heal-does-not-cure-confusion-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)
@@ -74,6 +80,54 @@ Some fixes are mentioned as breaking compatibility with link battles. This can b
- [`BattleAnimCmd_ClearObjs` only clears the first 6⅔ objects](#battleanimcmd_clearobjs-only-clears-the-first-6-objects)
+## Perish Song and Spikes can leave a Pokémon with 0 HP and not faint
+
+*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
+
+([Video](https://www.youtube.com/watch?v=1IiPWw5fMf8&t=85))
+
+**Fix:** Edit `CheckFaint_PlayerThenEnemy` and `CheckFaint_EnemyThenPlayer` in [engine/battle/core.asm](https://github.com/pret/pokecrystal/blob/master/engine/battle/core.asm):
+
+```diff
+ jp HandleEncore
+
++HasAnyoneFainted:
++ call HasPlayerFainted
++ call nz, HasEnemyFainted
++ ret
++
+ CheckFaint_PlayerThenEnemy:
++.faint_loop
++ call .Function
++ ret c
++ call HasAnyoneFainted
++ ret nz
++ jr .faint_loop
++
++.Function:
+ call HasPlayerFainted
+ jr nz, .PlayerNotFainted
+ call HandlePlayerMonFaint
+ ...
+```
+
+```diff
+ CheckFaint_EnemyThenPlayer:
++.faint_loop
++ call .Function
++ ret c
++ call HasAnyoneFainted
++ ret nz
++ jr .faint_loop
++
++.Function:
+ call HasEnemyFainted
+ jr nz, .EnemyNotFainted
+ call HandleEnemyMonFaint
+ ...
+```
+
+
## Thick Club and Light Ball can make (Special) Attack wrap around above 1024
*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
@@ -167,6 +221,34 @@ This bug existed for all battles in Gold and Silver, and was only fixed for sing
(This fix also affects Thick Club, Light Ball, and Metal Powder, as described above, but their specific fixes in the above bugs allow more accurate damage calculations.)
+## Glacier Badge may not boost Special Defense depending on the value of Special Attack
+
+As Pryce's dialog ("That BADGE will raise the SPECIAL stats of POKéMON.") implies, Glacier Badge is intended to boost both Special Attack and Special Defense. However, due to BoostStat overwriting `a` when boosting Special Attack, the Special Defense boost will not happen if the unboosted Special Attack stat is either 0-205 or 433-660.
+
+**Fix:** Edit `BadgeStatBoosts.CheckBadge` in [engine/battle/core.asm](https://github.com/pret/pokecrystal/blob/master/engine/battle/core.asm):
+
+```diff
+ .CheckBadge:
+ ld a, b
+ srl b
++ push af
+ call c, BoostStat
++ pop af
+ inc hl
+ inc hl
+ ; Check every other badge.
+ srl b
+ dec c
+ jr nz, .CheckBadge
+ ; Check GlacierBadge again for Special Defense.
+-; This check is buggy because it assumes that a is set by the "ld a, b" in the above loop,
+-; but it can actually be overwritten by the call to BoostStat.
+ srl a
+ call c, BoostStat
+ ret
+```
+
+
## Moves with a 100% secondary effect chance will not trigger it in 1/256 uses
*Fixing this bug **may** break compatibility with standard Pokémon Crystal for link battles.*
@@ -242,6 +324,39 @@ This bug existed for all battles in Gold and Silver, and was only fixed for sing
```
+## Berserk Gene's confusion lasts for 256 turns or the previous Pokémon's confusion count
+
+*Fixing this bug will break compatibility with standard Pokémon Crystal for link battles.*
+
+([Video](https://youtube.com/watch?v=Pru3mohq20A))
+
+**Fix:** Edit `HandleBerserkGene` in [engine/battle/core.asm](https://github.com/pret/pokecrystal/blob/master/engine/battle/core.asm):
+
+```diff
+ HandleBerserkGene:
+ ...
+ ld a, BATTLE_VARS_SUBSTATUS3
+ call GetBattleVarAddr
+ push af
+ set SUBSTATUS_CONFUSED, [hl]
++ ld a, [hBattleTurn]
++ and a
++ ld hl, wEnemyConfuseCount
++ jr z, .set_confuse_count
++ ld hl, wPlayerConfuseCount
++.set_confuse_count
++ call BattleRandom
++ and %11
++ add a, 2
++ ld [hl], a
+ ld a, BATTLE_VARS_MOVE_ANIM
+ call GetBattleVarAddr
+ ...
+```
+
+This makes the Berserk Gene use the regular confusion duration (2-5 turns).
+
+
## 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.*
@@ -250,11 +365,15 @@ This bug existed for all battles in Gold and Silver, and was only fixed for sing
**Fix:**
-First, edit [hram.asm](https://github.com/pret/pokecrystal/blob/master/hram.asm):
+First, edit [wram.asm](https://github.com/pret/pokecrystal/blob/master/wram.asm):
```diff
- hClockResetTrigger:: db ; ffeb
-+hIsConfusionDamage:: db ; ffec
+ wTurnEnded:: db ; c6b4
+
+- ds 1
++wIsConfusionDamage:: db ; c6b5
+
+ wPlayerStats:: ; c6b6
```
Then edit four routines in [engine/battle/effect_commands.asm](https://github.com/pret/pokecrystal/blob/master/engine/battle/effect_commands.asm):
@@ -267,7 +386,7 @@ Then edit four routines in [engine/battle/effect_commands.asm](https://github.co
pop af
ld e, a
+ ld a, TRUE
-+ ldh [hIsConfusionDamage], a
++ ld [wIsConfusionDamage], a
ret
```
@@ -277,7 +396,7 @@ Then edit four routines in [engine/battle/effect_commands.asm](https://github.co
...
.skip_zero_damage_check
+ xor a ; Not confusion damage
-+ ldh [hIsConfusionDamage], a
++ ld [wIsConfusionDamage], a
+ ; fallthrough
+
+ConfusionDamageCalc:
@@ -293,7 +412,7 @@ Then edit four routines in [engine/battle/effect_commands.asm](https://github.co
; Item boosts
+
+; Item boosts don't apply to confusion damage
-+ ldh a, [hIsConfusionDamage]
++ ld a, [wIsConfusionDamage]
+ and a
+ jr nz, .DoneItem
+
@@ -332,6 +451,109 @@ Then edit four routines in [engine/battle/effect_commands.asm](https://github.co
```
+## Saves corrupted by mid-save shutoff are not handled
+
+([Video 1](https://www.youtube.com/watch?v=ukqtK0l6bu0), [Video 2](https://www.youtube.com/watch?v=c2zHd1BPtvc))
+
+**Fix:** Edit `MoveMonWOMail_InsertMon_SaveGame` and `_SaveGameData` in [engine/menus/save.asm](https://github.com/pret/pokecrystal/blob/master/engine/menus/save.asm):
+
+```diff
+ MoveMonWOMail_InsertMon_SaveGame:
+ ...
+ ld a, TRUE
+ ld [wSaveFileExists], a
+ farcall StageRTCTimeForSave
+ farcall BackupMysteryGift
+- call ValidateSave
++ call InvalidateSave
+ call SaveOptions
+ call SavePlayerData
+ call SavePokemonData
+ call SaveChecksum
+- call ValidateBackupSave
++ call ValidateSave
++ call InvalidateBackupSave
+ call SaveBackupOptions
+ call SaveBackupPlayerData
+ call SaveBackupPokemonData
+ call SaveBackupChecksum
++ call ValidateBackupSave
+ farcall BackupPartyMonMail
+ farcall BackupMobileEventIndex
+ farcall SaveRTC
+ ...
+```
+
+```diff
+ _SaveGameData:
+ ...
+ ld a, TRUE
+ ld [wSaveFileExists], a
+ farcall StageRTCTimeForSave
+ farcall BackupMysteryGift
+- call ValidateSave
++ call InvalidateSave
+ call SaveOptions
+ call SavePlayerData
+ call SavePokemonData
+ call SaveBox
+ call SaveChecksum
+- call ValidateBackupSave
++ call ValidateSave
++ call InvalidateBackupSave
+ call SaveBackupOptions
+ call SaveBackupPlayerData
+ call SaveBackupPokemonData
+ call SaveBackupChecksum
++ call ValidateBackupSave
+ call UpdateStackTop
+ farcall BackupPartyMonMail
+ farcall BackupMobileEventIndex
+ farcall SaveRTC
+ ...
+```
+
+Then create two new routines, `InvalidateSave` and `InvalidateBackupSave`:
+
+```diff
+ ValidateSave:
+ ld a, BANK(sCheckValue1) ; aka BANK(sCheckValue2)
+ call GetSRAMBank
+ ld a, SAVE_CHECK_VALUE_1
+ ld [sCheckValue1], a
+ ld a, SAVE_CHECK_VALUE_2
+ ld [sCheckValue2], a
+ jp CloseSRAM
+
++InvalidateSave:
++ ld a, BANK(sCheckValue1) ; aka BANK(sCheckValue2)
++ call GetSRAMBank
++ xor a
++ ld [sCheckValue1], a
++ ld [sCheckValue2], a
++ jp CloseSRAM
+```
+
+```diff
+ ValidateBackupSave:
+ ld a, BANK(sBackupCheckValue1) ; aka BANK(sBackupCheckValue2)
+ call GetSRAMBank
+ ld a, SAVE_CHECK_VALUE_1
+ ld [sBackupCheckValue1], a
+ ld a, SAVE_CHECK_VALUE_2
+ ld [sBackupCheckValue2], a
+ jp CloseSRAM
+
++InvalidateBackupSave:
++ ld a, BANK(sBackupCheckValue1) ; aka BANK(sBackupCheckValue2)
++ call GetSRAMBank
++ xor a
++ ld [sBackupCheckValue1], a
++ ld [sBackupCheckValue2], a
++ jp CloseSRAM
+```
+
+
## 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.*
@@ -615,6 +837,23 @@ This bug existed for all battles in Gold and Silver, and was only fixed for sing
```
+## A Transformed Pokémon can use Sketch and learn otherwise unobtainable moves
+
+([Video](https://www.youtube.com/watch?v=AFiBxAOkCGI))
+
+**Fix:** Edit `BattleCommand_Sketch` in [engine/battle/move_effects/sketch.asm](https://github.com/pret/pokecrystal/blob/master/engine/battle/move_effects/sketch.asm):
+
+```diff
+-; If the opponent is transformed, fail.
++; If the user is transformed, fail.
+- ld a, BATTLE_VARS_SUBSTATUS5_OPP
++ ld a, BATTLE_VARS_SUBSTATUS5
+ call GetBattleVarAddr
+ bit SUBSTATUS_TRANSFORMED, [hl]
+ jp nz, .fail
+```
+
+
## "Smart" AI encourages Mean Look if its own Pokémon is badly poisoned
([Video](https://www.youtube.com/watch?v=cygMO-zHTls))
@@ -641,10 +880,8 @@ This bug existed for all battles in Gold and Silver, and was only fixed for sing
ld hl, wEnemyMonType1
ldh a, [hBattleTurn]
and a
- jr z, CheckTypeMatchup
+ jr z, CheckTypeMatchup
ld hl, wBattleMonType1
-+ ld a, BATTLE_VARS_MOVE_TYPE
-+ call GetBattleVar ; preserves hl, de, and bc
CheckTypeMatchup:
-; 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
@@ -652,6 +889,8 @@ This bug existed for all battles in Gold and Silver, and was only fixed for sing
-; 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.
++ ld a, BATTLE_VARS_MOVE_TYPE
++ call GetBattleVar ; preserves hl, de, and bc
push hl
push de
push bc
@@ -677,12 +916,67 @@ This bug existed for all battles in Gold and Silver, and was only fixed for sing
xor a
ld [hl], a
ld [wEnemyMonStatus], a
-- ; Bug: this should reset SUBSTATUS_NIGHTMARE too
-- ; Uncomment the lines below to fix
+- ; Bug: this should reset SUBSTATUS_NIGHTMARE
+- ; Uncomment the 2 lines below to fix
- ; ld hl, wEnemySubStatus1
- ; res SUBSTATUS_NIGHTMARE, [hl]
+ ld hl, wEnemySubStatus1
+ res SUBSTATUS_NIGHTMARE, [hl]
+ ; Bug: this should reset SUBSTATUS_CONFUSED
+ ; Uncomment the 2 lines below to fix
+ ; ld hl, wEnemySubStatus3
+ ; res SUBSTATUS_CONFUSED, [hl]
+ ld hl, wEnemySubStatus5
+ res SUBSTATUS_TOXIC, [hl]
+ ret
+```
+
+
+## NPC use of Full Heal does not cure confusion status
+
+**Fix:** Edit `EnemyUsedFullRestore`, `EnemyUsedFullHeal`, and `AI_HealStatus` in [engine/battle/ai/items.asm](https://github.com/pret/pokecrystal/blob/master/engine/battle/ai/items.asm):
+
+```diff
+ EnemyUsedFullRestore:
+ call AI_HealStatus
+ ld a, FULL_RESTORE
+ ld [wCurEnemyItem], a
+- ld hl, wEnemySubStatus3
+- res SUBSTATUS_CONFUSED, [hl]
+ xor a
+ ld [wEnemyConfuseCount], a
+```
+
+```diff
+ EnemyUsedFullHeal:
+ call AIUsedItemSound
+ call AI_HealStatus
+ ld a, FULL_HEAL
++ ld [wCurEnemyItem], a
++ xor a
++ ld [wEnemyConfuseCount], a
+ jp PrintText_UsedItemOn_AND_AIUpdateHUD
+```
+
+```diff
+ AI_HealStatus:
+ 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
+ ; Uncomment the 2 lines below to fix
+ ; ld hl, wEnemySubStatus1
+ ; res SUBSTATUS_NIGHTMARE, [hl]
+- ; Bug: this should reset SUBSTATUS_CONFUSED
+- ; Uncomment the 2 lines below to fix
+- ; ld hl, wEnemySubStatus3
+- ; res SUBSTATUS_CONFUSED, [hl]
++ ld hl, wEnemySubStatus3
++ res SUBSTATUS_CONFUSED, [hl]
ld hl, wEnemySubStatus5
res SUBSTATUS_TOXIC, [hl]
ret
@@ -780,10 +1074,10 @@ This can bring Pokémon straight from level 1 to 100 by gaining just a few exper
([Video](https://www.youtube.com/watch?v=o54VjpAEoO8))
-**Fix:** Edit `Text_ABoostedStringBuffer2ExpPoints` and `Text_StringBuffer2ExpPoints` in [data/text/common_2.asm](https://github.com/pret/pokecrystal/blob/master/data/text/common_2.asm):
+**Fix:** Edit `_BoostedExpPointsText` and `_ExpPointsText` in [data/text/common_2.asm](https://github.com/pret/pokecrystal/blob/master/data/text/common_2.asm):
```diff
- Text_ABoostedStringBuffer2ExpPoints::
+ _BoostedExpPointsText::
text_start
line "a boosted"
cont "@"
@@ -792,7 +1086,7 @@ This can bring Pokémon straight from level 1 to 100 by gaining just a few exper
text " EXP. Points!"
prompt
- Text_StringBuffer2ExpPoints::
+ _ExpPointsText::
text_start
line "@"
- text_decimal wStringBuffer2, 2, 4
@@ -1036,7 +1330,7 @@ CopyPokemonName_Buffer1_Buffer3:
jr nc, .GenerateDVs
```
-**Better fix:** Rewrite the whole system to use millimeters instead of feet and inches, since they have better precision (1 in = 25.4 mm); and only convert from metric to imperial units for display purposes (or don't, of course).
+**Better fix:** Rewrite the whole system to use millimeters instead of feet and inches, since they have better precision (1 in = 25.4 mm); and only convert from metric to imperial units for display purposes (or don't, of course).
## Magikarp lengths can be miscalculated
@@ -1233,7 +1527,7 @@ Finally, edit [engine/battle/read_trainer_party.asm](https://github.com/pret/pok
([Video](https://www.youtube.com/watch?v=ojq3xqfRF6I))
-**Fix:** Edit `Slots_PayoutAnim` in [engine/games/slot_machine.asm](https://github.com/pret/pokecrystal/blob/master/engine/games/slot_machine.asm):
+**Fix:** Edit `SlotsAction_PayoutAnim` in [engine/games/slot_machine.asm](https://github.com/pret/pokecrystal/blob/master/engine/games/slot_machine.asm):
```diff
.okay
@@ -1383,7 +1677,7 @@ If you want to make sure `hInMenu` always has a defined value in the move select
...
jp .loop
-
+
.quit
+ pop af
+ ldh [hInMenu], a
@@ -1442,12 +1736,12 @@ First, edit `UsedSurfScript` in [engine/events/overworld.asm](https://github.com
writetext UsedSurfText ; "used SURF!"
waitbutton
closetext
-
+
callasm .empty_fn ; empty function
-
+
readmem wBuffer2
writevar VAR_MOVEMENT
-
+
special ReplaceKrisSprite
special PlayMapMusic
-; step into the water (slow_step DIR, step_end)
@@ -1784,8 +2078,9 @@ This supports up to six entries.
ld de, 3
ld hl, .pointers
call IsInArray
- jr nc, .nope
+- jr nc, .nope
pop bc
++ jr nc, .nope
inc hl
ld a, [hli]
@@ -1795,7 +2090,6 @@ This supports up to six entries.
.nope
- ; pop bc
-+ pop bc
xor a
ret
```
diff --git a/docs/design_flaws.md b/docs/design_flaws.md
index bcabff901..f1a672346 100644
--- a/docs/design_flaws.md
+++ b/docs/design_flaws.md
@@ -216,6 +216,17 @@ INCBIN "gfx/footprints/wartortle.1bpp"
Edit `Pokedex_LoadAnyFootprint`:
```diff
+ ld a, [wTempSpecies]
+ dec a
+ and %111
+ swap a ; * $10
++ add a, a
+ ld l, a
+ ld h, 0
+ add hl, de
+ ld de, Footprints
+ add hl, de
+
- push hl
ld e, l
ld d, h
diff --git a/docs/event_commands.md b/docs/event_commands.md
index c06d5c587..63f2819ab 100644
--- a/docs/event_commands.md
+++ b/docs/event_commands.md
@@ -298,7 +298,7 @@ If <code><i>item_id</i></code> = `USE_SCRIPT_VAR`, then it uses `[wScriptVar]` i
## `$54`: `waitbutton`
-## `$55`: `buttonsound`
+## `$55`: `promptbutton`
## `$56`: <code>pokepic <i>mon_id</i></code>
diff --git a/docs/text_commands.md b/docs/text_commands.md
index 13a905213..91d7538c8 100644
--- a/docs/text_commands.md
+++ b/docs/text_commands.md
@@ -35,7 +35,7 @@ Draw a box.
Write text at (1, 16).
-## `$06`: `text_waitbutton`
+## `$06`: `text_promptbutton`
Wait for button press; show arrow.
@@ -71,7 +71,7 @@ Play `SFX_DEX_FANFARE_50_79`.
Print *n* `"…"`s, pausing for 10 frames after each; interrupt if A or B is pressed.
-## `$0D`: `text_linkwaitbutton`
+## `$0D`: `text_linkpromptbutton`
Wait for button press; show arrow.