From 7ffe9415cfd3a13b235ab6e8094f30f3be8a5087 Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Tue, 31 Oct 2023 12:47:51 -0400 Subject: [PATCH 01/37] Fix fast options --- engine/menus/options.asm | 1 + 1 file changed, 1 insertion(+) diff --git a/engine/menus/options.asm b/engine/menus/options.asm index e2c02e428..8206606d3 100644 --- a/engine/menus/options.asm +++ b/engine/menus/options.asm @@ -1,4 +1,5 @@ DisplayOptionMenu_: + call JoypadLowSensitivity call InitOptionsMenu .optionMenuLoop call JoypadLowSensitivity From 8f54868c9b7326101cd5b312b1257047dc844b4b Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Tue, 31 Oct 2023 12:50:04 -0400 Subject: [PATCH 02/37] Fix scripted encounter animations before obtaining a pokemon --- engine/battle/battle_transitions.asm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/engine/battle/battle_transitions.asm b/engine/battle/battle_transitions.asm index b0289d7e4..cff940014 100644 --- a/engine/battle/battle_transitions.asm +++ b/engine/battle/battle_transitions.asm @@ -91,6 +91,9 @@ GetBattleTransitionID_WildOrTrainer: ret GetBattleTransitionID_CompareLevels: + ld a, [wPartyCount] + cp 0 + jr z, .highLevelEnemy ld hl, wPartyMon1HP .faintedLoop ld a, [hli] From 33916b9cb20f71a08e5a2f2f7faf1b1c13462550 Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Tue, 31 Oct 2023 13:02:09 -0400 Subject: [PATCH 03/37] inline documentation for fork --- engine/battle/battle_transitions.asm | 3 +++ engine/menus/options.asm | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/engine/battle/battle_transitions.asm b/engine/battle/battle_transitions.asm index cff940014..76d48a12f 100644 --- a/engine/battle/battle_transitions.asm +++ b/engine/battle/battle_transitions.asm @@ -91,9 +91,12 @@ GetBattleTransitionID_WildOrTrainer: ret GetBattleTransitionID_CompareLevels: + ; This section fixes undefined behavior in the Pikachu cutscene + ; Due to not yet having obtained a pokemon ld a, [wPartyCount] cp 0 jr z, .highLevelEnemy + ; end of source modification ld hl, wPartyMon1HP .faintedLoop ld a, [hli] diff --git a/engine/menus/options.asm b/engine/menus/options.asm index 8206606d3..9a42468ac 100644 --- a/engine/menus/options.asm +++ b/engine/menus/options.asm @@ -1,5 +1,9 @@ DisplayOptionMenu_: + ; This line fixes the Fast Options glitch + ; The code as written applies any direction button presses done simultaneous with selecting the menu + ; To each option while rendering the menu call JoypadLowSensitivity + ; end of source modification call InitOptionsMenu .optionMenuLoop call JoypadLowSensitivity From 1a5da8f1a63e7e9a4bd7faccdfd840490e719a9d Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Tue, 31 Oct 2023 15:54:25 -0400 Subject: [PATCH 04/37] Fix poke doll sequence break --- engine/items/item_effects.asm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/engine/items/item_effects.asm b/engine/items/item_effects.asm index c495f991d..ea45c1116 100644 --- a/engine/items/item_effects.asm +++ b/engine/items/item_effects.asm @@ -1751,6 +1751,10 @@ ItemUsePokedoll: dec a jp nz, ItemUseNotTime ld a, $01 + ; Bugfix for Poke Doll Enabling a Sequence Break in Lavender Tower + ; Marks the result of battles where poke doll is used as a loss + ld [wBattleResult], a + ; end of source modification ld [wEscapedFromBattle], a jp PrintItemUseTextAndRemoveItem From b6f4d28a161782c2a0d12404bf5a1f9b9c9e2bf6 Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Wed, 1 Nov 2023 18:21:17 -0400 Subject: [PATCH 05/37] Do the bugfix patches as an if def flag --- Makefile | 4 ++++ README.md | 5 +++++ engine/battle/battle_transitions.asm | 3 ++- engine/items/item_effects.asm | 3 ++- engine/menus/options.asm | 3 ++- engine/menus/save.asm | 3 +++ 6 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 5eb584b18..88a17a499 100644 --- a/Makefile +++ b/Makefile @@ -87,6 +87,10 @@ ifeq ($(DEBUG),1) RGBASMFLAGS += -E endif +ifeq ($(BUGFIX),1) +RGBASMFLAGS += -D _BUGFIX +endif + $(pokeyellow_debug_obj): RGBASMFLAGS += -D _DEBUG $(pokeyellow_vc_obj): RGBASMFLAGS += -D _YELLOW_VC diff --git a/README.md b/README.md index d772f3298..571107916 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,11 @@ It builds the following ROMs: To set up the repository, see [**INSTALL.md**](INSTALL.md). +## Bugfix Patch + +This version includes the ability to optionally compile with a set of bugfix patches: + +`make BUGFIX=1` ## See also diff --git a/engine/battle/battle_transitions.asm b/engine/battle/battle_transitions.asm index 76d48a12f..05b08f8d5 100644 --- a/engine/battle/battle_transitions.asm +++ b/engine/battle/battle_transitions.asm @@ -93,10 +93,11 @@ GetBattleTransitionID_WildOrTrainer: GetBattleTransitionID_CompareLevels: ; This section fixes undefined behavior in the Pikachu cutscene ; Due to not yet having obtained a pokemon +IF DEF(_BUGFIX) ld a, [wPartyCount] cp 0 jr z, .highLevelEnemy - ; end of source modification +ENDC ld hl, wPartyMon1HP .faintedLoop ld a, [hli] diff --git a/engine/items/item_effects.asm b/engine/items/item_effects.asm index ea45c1116..c83e8d39f 100644 --- a/engine/items/item_effects.asm +++ b/engine/items/item_effects.asm @@ -1753,8 +1753,9 @@ ItemUsePokedoll: ld a, $01 ; Bugfix for Poke Doll Enabling a Sequence Break in Lavender Tower ; Marks the result of battles where poke doll is used as a loss +IF DEF(_BUGFIX) ld [wBattleResult], a - ; end of source modification +ENDC ld [wEscapedFromBattle], a jp PrintItemUseTextAndRemoveItem diff --git a/engine/menus/options.asm b/engine/menus/options.asm index 9a42468ac..49ab5d701 100644 --- a/engine/menus/options.asm +++ b/engine/menus/options.asm @@ -2,8 +2,9 @@ DisplayOptionMenu_: ; This line fixes the Fast Options glitch ; The code as written applies any direction button presses done simultaneous with selecting the menu ; To each option while rendering the menu +IF DEF(_BUGFIX) call JoypadLowSensitivity - ; end of source modification +ENDC call InitOptionsMenu .optionMenuLoop call JoypadLowSensitivity diff --git a/engine/menus/save.asm b/engine/menus/save.asm index 359830d91..aacd1adf7 100644 --- a/engine/menus/save.asm +++ b/engine/menus/save.asm @@ -278,6 +278,9 @@ SAVCheckSum: .loop ld a, [hli] add d +IF DEF(_BUGFIX) + rrca +ENDC ld d, a dec bc ld a, b From 5046d68b5a87fdf8e681a2a1a476281843723243 Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Wed, 1 Nov 2023 23:47:17 -0400 Subject: [PATCH 06/37] Add bugfix code for gen 1 miss, gen 1 miss critical, and critical rates --- engine/battle/core.asm | 55 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/engine/battle/core.asm b/engine/battle/core.asm index addff324d..995c5c452 100644 --- a/engine/battle/core.asm +++ b/engine/battle/core.asm @@ -4793,14 +4793,24 @@ CriticalHitTest: ld c, [hl] ; read move id ld a, [de] bit GETTING_PUMPED, a ; test for focus energy - jr nz, .focusEnergyUsed ; bug: using focus energy causes a shift to the right instead of left, - ; resulting in 1/4 the usual crit chance - sla b ; (effective (base speed/2)*2) +; bug: using focus energy causes a shift to the right instead of left, +; resulting in 1/4 the usual crit chance +IF !DEF(_BUGFIX) + jr nz, .focusEnergyUsed + sla b ; regular moves become effective (base speed/2)*2 jr nc, .noFocusEnergyUsed ld b, $ff ; cap at 255/256 jr .noFocusEnergyUsed .focusEnergyUsed - srl b + srl b ; focus energy moves become effective (base speed/2)/2 +ENDC +IF DEF(_BUGFIX) + jr z, .nofocusEnergyUsed + sla b ; (effective (base speed/2)*2) + jr c, .guaranteedCriticalHit + sla b ; (effective (base speed/2)*4) + jr c, .guaranteedCriticalHit +ENDC .noFocusEnergyUsed ld hl, HighCriticalMoves ; table of high critical hit moves .Loop @@ -4809,23 +4819,50 @@ CriticalHitTest: jr z, .HighCritical ; if so, the move about to be used is a high critical hit ratio move inc a ; move on to the next move, FF terminates loop jr nz, .Loop ; check the next move in HighCriticalMoves +; Fixing the focus energy code reveals that the crit rate would still be capped at 50% +; This shift can then simply be removed in a simpler implementation of fixing focus energy +; Which would also fix the 50% cap +; This also removes the additional 2x difference making high critical hit moves x8 +; Making High Critical Hit Chance Moves and Focus Energy a consistent x4 multiplier +IF !DEF(_BUGFIX) srl b ; /2 for regular move (effective (base speed / 2)) +ENDC jr .SkipHighCritical ; continue as a normal move .HighCritical - sla b ; *2 for high critical hit moves + sla b ; *2 for high critical hit moves - effective (base speed/2)*4)) or effective (base speed/2)*2) if bugs fixed +IF !DEF(_BUGFIX) jr nc, .noCarry ld b, $ff ; cap at 255/256 .noCarry - sla b ; *4 for high critical move (effective (base speed/2)*8)) +ENDC +IF DEF(_BUGFIX) + jr c, .guaranteedCriticalHit +ENDC + sla b ; *4 for high critical moves - effective (base speed/2)*8)) or effective (base speed/2)*4) if bugs fixed +IF !DEF(_BUGFIX) jr nc, .SkipHighCritical ld b, $ff +ENDC +IF DEF(_BUGFIX) + jr c, .guaranteedCriticalHit +ENDC .SkipHighCritical +; The original code here can "gen 1 miss" a critical hit even when the chance is guaranteed +IF DEF(_BUGFIX) + ld a, b + inc a ; optimization of "cp $ff" + jr z, .guaranteedCriticalHit +ENDC call BattleRandom ; generates a random value, in "a" rlc a rlc a rlc a cp b ; check a against calculated crit rate ret nc ; no critical hit if no borrow +; adding this label in the bugfix code enables several optimizations +IF DEF(_BUGFIX) +.guaranteedCriticalHit +ENDC ld a, $1 ld [wCriticalHitOrOHKO], a ; set critical hit flag ret @@ -5622,6 +5659,12 @@ MoveHitTest: .doAccuracyCheck ; if the random number generated is greater than or equal to the scaled accuracy, the move misses ; note that this means that even the highest accuracy is still just a 255/256 chance, not 100% +; The following snippet is taken from Pokemon Crystal, it fixes the above bug. +IF DEF(_BUGFIX) + ld a, b + cp $FF ; Is the value $FF? + ret z ; If so, we need not calculate, just so we can fix this bug. +ENDC call BattleRandom cp b jr nc, .moveMissed From 45364c63587e37035d745bdc91ea2a9c24b0d4a4 Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Thu, 2 Nov 2023 17:50:58 -0400 Subject: [PATCH 07/37] Simplify bugfix if defs with else --- engine/battle/core.asm | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/engine/battle/core.asm b/engine/battle/core.asm index 995c5c452..1a7ce4a42 100644 --- a/engine/battle/core.asm +++ b/engine/battle/core.asm @@ -4795,7 +4795,13 @@ CriticalHitTest: bit GETTING_PUMPED, a ; test for focus energy ; bug: using focus energy causes a shift to the right instead of left, ; resulting in 1/4 the usual crit chance -IF !DEF(_BUGFIX) +IF DEF(_BUGFIX) + jr z, .noFocusEnergyUsed + sla b ; (effective (base speed/2)*2) + jr c, .guaranteedCriticalHit + sla b ; (effective (base speed/2)*4) + jr c, .guaranteedCriticalHit +ELSE jr nz, .focusEnergyUsed sla b ; regular moves become effective (base speed/2)*2 jr nc, .noFocusEnergyUsed @@ -4804,13 +4810,6 @@ IF !DEF(_BUGFIX) .focusEnergyUsed srl b ; focus energy moves become effective (base speed/2)/2 ENDC -IF DEF(_BUGFIX) - jr z, .nofocusEnergyUsed - sla b ; (effective (base speed/2)*2) - jr c, .guaranteedCriticalHit - sla b ; (effective (base speed/2)*4) - jr c, .guaranteedCriticalHit -ENDC .noFocusEnergyUsed ld hl, HighCriticalMoves ; table of high critical hit moves .Loop @@ -4830,22 +4829,20 @@ ENDC jr .SkipHighCritical ; continue as a normal move .HighCritical sla b ; *2 for high critical hit moves - effective (base speed/2)*4)) or effective (base speed/2)*2) if bugs fixed -IF !DEF(_BUGFIX) +IF DEF(_BUGFIX) + jr c, .guaranteedCriticalHit +ELSE jr nc, .noCarry ld b, $ff ; cap at 255/256 .noCarry ENDC + sla b ; *4 for high critical moves - effective (base speed/2)*8)) or effective (base speed/2)*4) if bugs fixed IF DEF(_BUGFIX) jr c, .guaranteedCriticalHit -ENDC - sla b ; *4 for high critical moves - effective (base speed/2)*8)) or effective (base speed/2)*4) if bugs fixed -IF !DEF(_BUGFIX) +ELSE jr nc, .SkipHighCritical ld b, $ff ENDC -IF DEF(_BUGFIX) - jr c, .guaranteedCriticalHit -ENDC .SkipHighCritical ; The original code here can "gen 1 miss" a critical hit even when the chance is guaranteed IF DEF(_BUGFIX) From 83497734180e64802bbfe969e841ce861d467ca8 Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Thu, 2 Nov 2023 19:12:20 -0400 Subject: [PATCH 08/37] Badge boost related bugfixes --- engine/battle/core.asm | 23 +++++++++++++++++++++++ engine/battle/effects.asm | 8 ++++++++ engine/items/item_effects.asm | 8 ++++++++ 3 files changed, 39 insertions(+) diff --git a/engine/battle/core.asm b/engine/battle/core.asm index 1a7ce4a42..ab488fb3a 100644 --- a/engine/battle/core.asm +++ b/engine/battle/core.asm @@ -6796,6 +6796,28 @@ ApplyBadgeStatBoosts: ld a, [wLinkState] cp LINK_STATE_BATTLING ret z ; return if link battle +IF DEF(_BUGFIX) + ld a, [wObtainedBadges] + ld b, a + ld hl, wBattleMonAttack +; loop unrolled to fix badge boosts to match in game text +; and the way it was fixed in FRLG + srl b + call c, .applyBoostToStat + ld hl, wBattleMonSpeed + srl b + srl b + call c, .applyBoostToStat + ld hl, wBattleMonDefense + srl b + srl b + call c, .applyBoostToStat + ld hl, wBattleMonSpecial + srl b + srl b + call c, .applyBoostToStat + ret +ELSE ld a, [wObtainedBadges] ld b, a ld hl, wBattleMonAttack @@ -6815,6 +6837,7 @@ ApplyBadgeStatBoosts: dec c jr nz, .loop ret +ENDC ; multiply stat at hl by 1.125 ; cap stat at MAX_STAT_VALUE diff --git a/engine/battle/effects.asm b/engine/battle/effects.asm index f13d679c1..1d1d2438f 100644 --- a/engine/battle/effects.asm +++ b/engine/battle/effects.asm @@ -530,6 +530,10 @@ UpdateStatDone: .applyBadgeBoostsAndStatusPenalties ldh a, [hWhoseTurn] and a +; Prevent reapplication of badge boosts +IF DEF(_BUGFIX) + call z, CalculateModifiedStats +ENDC call z, ApplyBadgeStatBoosts ; whenever the player uses a stat-up move, badge boosts get reapplied again to every stat, ; even to those not affected by the stat-up move (will be boosted further) ld hl, MonsStatsRoseText @@ -720,6 +724,10 @@ UpdateLoweredStatDone: .ApplyBadgeBoostsAndStatusPenalties ldh a, [hWhoseTurn] and a +; Prevent reapplication of badge boosts +IF DEF(_BUGFIX) + call nz, CalculateModifiedStats +ENDC call nz, ApplyBadgeStatBoosts ; whenever the player uses a stat-down move, badge boosts get reapplied again to every stat, ; even to those not affected by the stat-up move (will be boosted further) ld hl, MonsStatsFellText diff --git a/engine/items/item_effects.asm b/engine/items/item_effects.asm index c83e8d39f..eddb1fa36 100644 --- a/engine/items/item_effects.asm +++ b/engine/items/item_effects.asm @@ -1008,7 +1008,15 @@ ItemUseMedicine: ld de, wBattleMonStats ld bc, NUM_STATS * 2 call CopyData ; copy party stats to in-battle stat data +; Fix broken effects of curing burn or paralysis on stats +IF DEF(_BUGFIX) + xor a + ld [wCalculateWhoseStats], a + callfar CalculateModifiedStats + callfar ApplyBadgeStatBoosts +ELSE predef DoubleOrHalveSelectedStats +ENDC jp .doneHealing .healHP From 84c3b8bcd2adb3dba1d97a8d032404b14a921afa Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Thu, 2 Nov 2023 22:23:04 -0400 Subject: [PATCH 09/37] Surge cans bugfix --- .../events/hidden_objects/vermilion_gym_trash2.asm | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/engine/events/hidden_objects/vermilion_gym_trash2.asm b/engine/events/hidden_objects/vermilion_gym_trash2.asm index 1bc0590b1..8a8561095 100644 --- a/engine/events/hidden_objects/vermilion_gym_trash2.asm +++ b/engine/events/hidden_objects/vermilion_gym_trash2.asm @@ -32,12 +32,24 @@ TrashCanRandom: call Random swap a cp 1 * $ff / 3 +IF DEF(_BUGFIX) + ld a, 0 +ELSE ld b, 0 +ENDC ret c cp 2 * $ff / 3 +IF DEF(_BUGFIX) + ld a, 1 +ELSE ld b, 1 +ENDC ret c +IF DEF(_BUGFIX) + ld a, 2 +ELSE ld b, 2 +ENDC ret .four From 001963c24b8956dcedda66ef4a92554149568fd2 Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Fri, 3 Nov 2023 00:29:10 -0400 Subject: [PATCH 10/37] Fixes for trainer fly and more documentation --- .../hidden_objects/vermilion_gym_trash2.asm | 3 +++ engine/overworld/clear_variables.asm | 7 ++++++ home/trainers.asm | 22 ++++++++++++++++++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/engine/events/hidden_objects/vermilion_gym_trash2.asm b/engine/events/hidden_objects/vermilion_gym_trash2.asm index 8a8561095..f9a90a5ae 100644 --- a/engine/events/hidden_objects/vermilion_gym_trash2.asm +++ b/engine/events/hidden_objects/vermilion_gym_trash2.asm @@ -32,6 +32,7 @@ TrashCanRandom: call Random swap a cp 1 * $ff / 3 +; the can index needs to be returned in the a register, not b IF DEF(_BUGFIX) ld a, 0 ELSE @@ -39,12 +40,14 @@ ELSE ENDC ret c cp 2 * $ff / 3 +; the can index needs to be returned in the a register, not b IF DEF(_BUGFIX) ld a, 1 ELSE ld b, 1 ENDC ret c +; the can index needs to be returned in the a register, not b IF DEF(_BUGFIX) ld a, 2 ELSE diff --git a/engine/overworld/clear_variables.asm b/engine/overworld/clear_variables.asm index bbb7c986b..a594c05e0 100644 --- a/engine/overworld/clear_variables.asm +++ b/engine/overworld/clear_variables.asm @@ -17,4 +17,11 @@ ClearVariablesOnEnterMap:: ld hl, wWhichTrade ld bc, wStandingOnWarpPadOrHole - wWhichTrade call FillMemory +; Clear a possible bad game state after Trainer Fly +IF DEF(_BUGFIX) + ld hl, wd730 + set 3, [hl] ; Tells the trainer encounter script to cancel any pending encounters + ld hl, wFlags_0xcd60 + res 0, [hl] ; Clear encountered trainer flag (avoid blocked buttons after a Trainer Fly) +ENDC ret diff --git a/home/trainers.asm b/home/trainers.asm index 468b63f8c..2a95a8270 100644 --- a/home/trainers.asm +++ b/home/trainers.asm @@ -143,6 +143,12 @@ ENDC .trainerEngaging ld hl, wFlags_D733 set 3, [hl] +; Part of bugfixes around trainer fly +IF DEF(_BUGFIX) + ld hl, wd730 + res 0, [hl] ; Clear NPC movement flag to avoid softlock if this trainer doesn't move + res 3, [hl] ; Clear Trainer encounter reset flag +ENDC ld [wEmotionBubbleSpriteIndex], a xor a ; EXCLAMATION_BUBBLE ld [wWhichEmotionBubble], a @@ -158,6 +164,12 @@ ENDC ; display the before battle text after the enemy trainer has walked up to the player's sprite DisplayEnemyTrainerTextAndStartBattle:: +; Part of bugfixes around trainer fly +IF DEF(_BUGFIX) + ld a, [wd730] + and $8 + jp nz, ResetButtonPressedAndMapScript ; Trainer Fly happened, abort this script +ENDC ld a, [wd730] and $1 ret nz ; return if the enemy trainer hasn't finished walking to the player's sprite @@ -220,7 +232,15 @@ ResetButtonPressedAndMapScript:: ldh [hJoyHeld], a ldh [hJoyPressed], a ldh [hJoyReleased], a - ld [wCurMapScript], a ; reset battle status + ld [wCurMapScript], a ; reset battle status +; Part of fixes around trainer fly +IF DEF(_BUGFIX) + ld hl, wd730 + res 0, [hl] ; Clear NPC movement flag to avoid potential softlocks + set 3, [hl] ; Set Trainer encounter reset flag to avoid Mew Glitch + ld hl, wFlags_0xcd60 + res 0, [hl] ; player is no longer engaged by any trainer +ENDC ret ; calls TrainerWalkUpToPlayer From 4915fea111c4e0fd0d8965556aee9f09ae91a777 Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Fri, 3 Nov 2023 23:20:34 -0400 Subject: [PATCH 11/37] Conditionally remove unused code for trainer fly fixes to compile --- home/text_script.asm | 2 ++ home/trainers.asm | 2 ++ home/trainers2.asm | 2 ++ home/yes_no.asm | 2 ++ 4 files changed, 8 insertions(+) diff --git a/home/text_script.asm b/home/text_script.asm index 5e2603206..9212f957b 100644 --- a/home/text_script.asm +++ b/home/text_script.asm @@ -1,6 +1,8 @@ +IF !DEF(_BUGFIX) UnknownText_2812:: ; unreferenced text_far _PokemonText text_end +ENDC ; this function is used to display sign messages, sprite dialog, etc. ; INPUT: [hSpriteIndexOrTextID] = sprite ID or text ID diff --git a/home/trainers.asm b/home/trainers.asm index 2a95a8270..84a35b4dd 100644 --- a/home/trainers.asm +++ b/home/trainers.asm @@ -281,7 +281,9 @@ SpritePositionBankswitch:: CheckForEngagingTrainers:: xor a +IF !DEF(_BUGFIX) call ReadTrainerHeaderInfo ; read trainer flag's bit (unused) +ENDC ld d, h ; store trainer header address in de ld e, l .trainerLoop diff --git a/home/trainers2.asm b/home/trainers2.asm index 78fb64633..b61385bfd 100644 --- a/home/trainers2.asm +++ b/home/trainers2.asm @@ -42,7 +42,9 @@ IsFightingJessieJames:: ld de, JessieJamesPic cp $2e jr c, .dummy +IF !DEF(_BUGFIX) ld de, JessieJamesPic ; possibly meant to add another pic +ENDC .dummy ld hl, wTrainerPicPointer ld a, e diff --git a/home/yes_no.asm b/home/yes_no.asm index 3f5a5a45b..63b20e93c 100644 --- a/home/yes_no.asm +++ b/home/yes_no.asm @@ -26,12 +26,14 @@ YesNoChoicePokeCenter:: lb bc, 8, 12 jr DisplayYesNoChoice +IF !DEF(_BUGFIX) WideYesNoChoice:: ; unused call SaveScreenTilesToBuffer1 ld a, WIDE_YES_NO_MENU ld [wTwoOptionMenuID], a hlcoord 12, 7 lb bc, 8, 13 +ENDC DisplayYesNoChoice:: ld a, TWO_OPTION_MENU From 603e5898320b4a62c7099f10f1032c52d53c23f1 Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Fri, 3 Nov 2023 23:58:50 -0400 Subject: [PATCH 12/37] Add a flag to block intentional save corruption via power off during save --- engine/menus/save.asm | 19 +++++++++++++++++++ ram/sram.asm | 5 ++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/engine/menus/save.asm b/engine/menus/save.asm index aacd1adf7..4d3ea8d92 100644 --- a/engine/menus/save.asm +++ b/engine/menus/save.asm @@ -4,6 +4,12 @@ LoadSAV: call ClearScreen call LoadFontTilePatterns call LoadTextBoxTilePatterns +; tell the user the save is corrupt if they turned off the power while saving +IF DEF(_BUGFIX) + ld a, [sSaveInProgress] + cp 1 + jr c, .badsum +ENDC call LoadSAV0 jr c, .badsum call LoadSAV1 @@ -152,9 +158,22 @@ SaveSAV: and a ret nz .save +; fix the order of text printing so that saving actually happens when the game says it does +; but also load a flag into sSaveInProgress to mark if the game was turned off during saving +IF DEF(_BUGFIX) + ld hl, SavingText + call PrintText + ld a, 1 + ld [sSaveInProgress], a +ENDC call SaveSAVtoSRAM +IF DEF(_BUGFIX) + ld a, 0 + ld [sSaveInProgress], a +ELSE ld hl, SavingText call PrintText +ENDC ld c, 128 call DelayFrames ld hl, GameSavedText diff --git a/ram/sram.asm b/ram/sram.asm index 6cb453711..f66fa1c63 100644 --- a/ram/sram.asm +++ b/ram/sram.asm @@ -22,7 +22,10 @@ sCurBoxData:: ds wBoxDataEnd - wBoxDataStart sTileAnimations:: db sGameDataEnd:: sMainDataCheckSum:: db - +; adding this variable allows us to track whether the user turned off the power while saving +IF DEF(_BUGFIX) +sSaveInProgress:: db +ENDC ; The PC boxes will not fit into one SRAM bank, ; so they use multiple SECTIONs From f13ba97c530ee572fc5b7ebae7f7b4bf58d76237 Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Sat, 4 Nov 2023 01:01:28 -0400 Subject: [PATCH 13/37] Prevent power off and on defeating random number generation by saving random state --- engine/menus/save.asm | 12 +++++++++++- ram/sram.asm | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/engine/menus/save.asm b/engine/menus/save.asm index 4d3ea8d92..e31417bdd 100644 --- a/engine/menus/save.asm +++ b/engine/menus/save.asm @@ -5,10 +5,15 @@ LoadSAV: call LoadFontTilePatterns call LoadTextBoxTilePatterns ; tell the user the save is corrupt if they turned off the power while saving +; and carry random state through power on/off IF DEF(_BUGFIX) ld a, [sSaveInProgress] cp 1 jr c, .badsum + ld a, [sRandomAdd] + ldh [hRandomAdd], a + ld a, [sRandomSub] + ldh [hRandomSub], a ENDC call LoadSAV0 jr c, .badsum @@ -159,12 +164,17 @@ SaveSAV: ret nz .save ; fix the order of text printing so that saving actually happens when the game says it does -; but also load a flag into sSaveInProgress to mark if the game was turned off during saving +; also load a flag into sSaveInProgress to mark if the game was turned off during saving +; and carry random state through power off IF DEF(_BUGFIX) ld hl, SavingText call PrintText ld a, 1 ld [sSaveInProgress], a + ldh a, [hRandomAdd] + ld [sRandomAdd], a + ldh a, [hRandomSub] + ld [sRandomSub], a ENDC call SaveSAVtoSRAM IF DEF(_BUGFIX) diff --git a/ram/sram.asm b/ram/sram.asm index f66fa1c63..98f04aff4 100644 --- a/ram/sram.asm +++ b/ram/sram.asm @@ -25,6 +25,8 @@ sMainDataCheckSum:: db ; adding this variable allows us to track whether the user turned off the power while saving IF DEF(_BUGFIX) sSaveInProgress:: db +sRandomAdd:: db +sRandomSub:: db ENDC ; The PC boxes will not fit into one SRAM bank, From e89b6469df16bbad458cdfd81eecffb0e2d90810 Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Sat, 4 Nov 2023 12:43:46 -0400 Subject: [PATCH 14/37] fix some other known bugs --- engine/battle/animations.asm | 9 +++++++++ engine/battle/core.asm | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/engine/battle/animations.asm b/engine/battle/animations.asm index ffa7e5a82..373c9ee33 100644 --- a/engine/battle/animations.asm +++ b/engine/battle/animations.asm @@ -1969,6 +1969,11 @@ AnimationWavyScreen: ld c, $ff ld hl, WavyScreenLineOffsets .loop +; Fix the wave effect for the top 3 lines of the screen +IF DEF(_BUGFIX) + ld a, [hl] + ldh [hSCX], a +ENDC push hl .innerLoop call WavyScreen_SetSCX @@ -1985,6 +1990,10 @@ AnimationWavyScreen: dec c jr nz, .loop xor a +; Fix the wave effect for the top 3 lines of the screen +IF DEF(_BUGFIX) + ldh [hSCX], a +ENDC ldh [hWY], a call SaveScreenTilesToBuffer2 call ClearScreen diff --git a/engine/battle/core.asm b/engine/battle/core.asm index ab488fb3a..59323d44c 100644 --- a/engine/battle/core.asm +++ b/engine/battle/core.asm @@ -3617,8 +3617,14 @@ CheckPlayerStatusConditions: .MonHurtItselfOrFullyParalysed ld hl, wPlayerBattleStatus1 ld a, [hl] + +IF DEF(_BUGFIX) + ; the original code forgot to clear the invulnerability status of Fly or Dig + and ~((1 << STORING_ENERGY) | (1 << THRASHING_ABOUT) | (1 << CHARGING_UP) | (1 << USING_TRAPPING_MOVE) | (1 << INVULNERABLE)) +ELSE ; clear bide, thrashing, charging up, and trapping moves such as warp (already cleared for confusion damage) and ~((1 << STORING_ENERGY) | (1 << THRASHING_ABOUT) | (1 << CHARGING_UP) | (1 << USING_TRAPPING_MOVE)) +ENDC ld [hl], a ld a, [wPlayerMoveEffect] cp FLY_EFFECT From cfa14cb87cd259455c7d4348baf43f56d2215659 Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Sat, 4 Nov 2023 12:44:05 -0400 Subject: [PATCH 15/37] Switch saved rng to luckytyphlosion's xorshift implementation --- engine/math/random.asm | 47 ++++++++++++++++++++++++++++++++++++++ engine/menus/main_menu.asm | 5 ++++ engine/menus/save.asm | 12 ++++------ ram/sram.asm | 3 +-- ram/wram.asm | 4 ++++ 5 files changed, 61 insertions(+), 10 deletions(-) diff --git a/engine/math/random.asm b/engine/math/random.asm index c8760157b..3292352bb 100644 --- a/engine/math/random.asm +++ b/engine/math/random.asm @@ -1,4 +1,12 @@ Random_:: +IF DEF(_BUGFIX) +; use the more thorough prng to minimize rng correlation effects + call XorshiftRandom + ldh [hRandomAdd], a + call XorshiftRandom + ldh [hRandomSub], a + ret +ELSE ; Generate a random 16-bit value. ldh a, [rDIV] ld b, a @@ -11,3 +19,42 @@ Random_:: sbc b ldh [hRandomSub], a ret +ENDC + +IF DEF(_BUGFIX) +; luckytyphlosion implementation of xorshift prng +XorshiftRandom: + push bc + ldh a, [rDIV] + rra ; shift into carry + ld hl, wRandomSeed + ld a, [hl] ; read in x + ; x << 4 + add a + add a + add a + adc a ; this mixes in 1 bit of rDIV into RNG + xor [hl] + ld b, a ; t = x ^ (x << 4) + ld hl, wRandomSeed + 3 + ld a, [hld] ; read in a ; hl = +2 + ld c, [hl] ; read in z ; hl = +2 + ld [hld], a ; z = a ; hl = +1 + ld a, c + ld c, [hl] ; read in y + ld [hld], a ; y = old z + ld c, a + ld [hl], a ; x = y + ; hl = y + ; vars + ; b contains t + ; a/c contains z + xor b ; z ^ t + rr c ; (z >> 1) + xor c ; z ^ t ^ (z >> 1) + rl b ; (t << 1) + xor b ; z ^ t ^ (z >> 1) ^ (t << 1) + ld [wRandomSeed + 3], a + pop bc + ret +ENDC diff --git a/engine/menus/main_menu.asm b/engine/menus/main_menu.asm index ce0b12c58..2d3fe26fd 100644 --- a/engine/menus/main_menu.asm +++ b/engine/menus/main_menu.asm @@ -1,4 +1,9 @@ MainMenu: +; Ensure we initialize wRandomSeed if it isn't carrying over from a previous save +IF DEF(_BUGFIX) + ldh a, [rDIV] + ld [wRandomSeed], a +ENDC ; Check save file call InitOptions xor a diff --git a/engine/menus/save.asm b/engine/menus/save.asm index e31417bdd..e5e2b75ce 100644 --- a/engine/menus/save.asm +++ b/engine/menus/save.asm @@ -10,10 +10,8 @@ IF DEF(_BUGFIX) ld a, [sSaveInProgress] cp 1 jr c, .badsum - ld a, [sRandomAdd] - ldh [hRandomAdd], a - ld a, [sRandomSub] - ldh [hRandomSub], a + ld a, [sRandomSeed] + ld [wRandomSeed], a ENDC call LoadSAV0 jr c, .badsum @@ -171,10 +169,8 @@ IF DEF(_BUGFIX) call PrintText ld a, 1 ld [sSaveInProgress], a - ldh a, [hRandomAdd] - ld [sRandomAdd], a - ldh a, [hRandomSub] - ld [sRandomSub], a + ld a, [wRandomSeed] + ld [sRandomSeed], a ENDC call SaveSAVtoSRAM IF DEF(_BUGFIX) diff --git a/ram/sram.asm b/ram/sram.asm index 98f04aff4..043a59c4f 100644 --- a/ram/sram.asm +++ b/ram/sram.asm @@ -25,8 +25,7 @@ sMainDataCheckSum:: db ; adding this variable allows us to track whether the user turned off the power while saving IF DEF(_BUGFIX) sSaveInProgress:: db -sRandomAdd:: db -sRandomSub:: db +sRandomSeed:: db ENDC ; The PC boxes will not fit into one SRAM bank, diff --git a/ram/wram.asm b/ram/wram.asm index dbe20a463..e94c7e6c6 100644 --- a/ram/wram.asm +++ b/ram/wram.asm @@ -1867,7 +1867,11 @@ wPseudoItemID:: db wUnusedD153:: db +IF DEF(_BUGFIX) +wRandomSeed:: db +ELSE ds 2 +ENDC wEvoStoneItemID:: db From 86befaeea7548c076c5d834a206d113ff18bd33f Mon Sep 17 00:00:00 2001 From: Travis Mcgeehan Date: Sat, 4 Nov 2023 19:58:49 -0400 Subject: [PATCH 16/37] Fix power off during save flag --- .vscode/extensions.json | 3 +++ engine/menus/save.asm | 25 ++++++++++++++++++++----- 2 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 .vscode/extensions.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000..0783442f2 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["donaldhays.rgbds-z80"] +} \ No newline at end of file diff --git a/engine/menus/save.asm b/engine/menus/save.asm index e5e2b75ce..bc112ed5e 100644 --- a/engine/menus/save.asm +++ b/engine/menus/save.asm @@ -7,11 +7,17 @@ LoadSAV: ; tell the user the save is corrupt if they turned off the power while saving ; and carry random state through power on/off IF DEF(_BUGFIX) + call EnableSRAMAndLatchClockData + ld a, $1 + ld [MBC1SRamBank], a ld a, [sSaveInProgress] cp 1 - jr c, .badsum - ld a, [sRandomSeed] - ld [wRandomSeed], a + jr z, .badsum + call DisableSRAMAndPrepareClockData + ld a, [sRandomAdd] + ldh [hRandomAdd], a + ld a, [sRandomSub] + ldh [hRandomSub], a ENDC call LoadSAV0 jr c, .badsum @@ -167,15 +173,24 @@ SaveSAV: IF DEF(_BUGFIX) ld hl, SavingText call PrintText + call EnableSRAMAndLatchClockData + ld a, $1 + ld [MBC1SRamBank], a ld a, 1 ld [sSaveInProgress], a - ld a, [wRandomSeed] - ld [sRandomSeed], a + ldh a, [hRandomAdd] + ld [sRandomAdd], a + ldh a, [hRandomSub] + ld [sRandomSub], a ENDC call SaveSAVtoSRAM IF DEF(_BUGFIX) + call EnableSRAMAndLatchClockData + ld a, $1 + ld [MBC1SRamBank], a ld a, 0 ld [sSaveInProgress], a + call DisableSRAMAndPrepareClockData ELSE ld hl, SavingText call PrintText From 600d1ba8b157ea0ac91003d848de01f5afdc1e1c Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Sun, 5 Nov 2023 00:10:19 -0400 Subject: [PATCH 17/37] bugfix the bugfixes --- engine/menus/save.asm | 12 ++++-------- ram/wram.asm | 12 ++++++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/engine/menus/save.asm b/engine/menus/save.asm index bc112ed5e..195cec4f6 100644 --- a/engine/menus/save.asm +++ b/engine/menus/save.asm @@ -13,11 +13,9 @@ IF DEF(_BUGFIX) ld a, [sSaveInProgress] cp 1 jr z, .badsum + ld a, [sRandomSeed] + ld [wRandomSeed], a call DisableSRAMAndPrepareClockData - ld a, [sRandomAdd] - ldh [hRandomAdd], a - ld a, [sRandomSub] - ldh [hRandomSub], a ENDC call LoadSAV0 jr c, .badsum @@ -178,10 +176,8 @@ IF DEF(_BUGFIX) ld [MBC1SRamBank], a ld a, 1 ld [sSaveInProgress], a - ldh a, [hRandomAdd] - ld [sRandomAdd], a - ldh a, [hRandomSub] - ld [sRandomSub], a + ld a, [wRandomSeed] + ld [sRandomSeed], a ENDC call SaveSAVtoSRAM IF DEF(_BUGFIX) diff --git a/ram/wram.asm b/ram/wram.asm index e94c7e6c6..21b808b35 100644 --- a/ram/wram.asm +++ b/ram/wram.asm @@ -1205,9 +1205,17 @@ ENDU wPartyMenuHPBarColors:: ds PARTY_LENGTH wStatusScreenHPBarColor:: db +IF DEF(_BUGFIX) + wRandomSeed:: db + + ds 3 + +ELSE ds 7 +ENDC + wCopyingSGBTileData:: wWhichPartyMenuHPBar:: wPalPacket:: @@ -1867,11 +1875,7 @@ wPseudoItemID:: db wUnusedD153:: db -IF DEF(_BUGFIX) -wRandomSeed:: db -ELSE ds 2 -ENDC wEvoStoneItemID:: db From b4c91dd81596a27a4e82302485867031a551f461 Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Sun, 5 Nov 2023 00:23:26 -0400 Subject: [PATCH 18/37] Adjust unused code removal for trainer fly bugfix space, this line is actually used --- home/trainers.asm | 2 -- home/yes_no.asm | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/home/trainers.asm b/home/trainers.asm index 84a35b4dd..2a95a8270 100644 --- a/home/trainers.asm +++ b/home/trainers.asm @@ -281,9 +281,7 @@ SpritePositionBankswitch:: CheckForEngagingTrainers:: xor a -IF !DEF(_BUGFIX) call ReadTrainerHeaderInfo ; read trainer flag's bit (unused) -ENDC ld d, h ; store trainer header address in de ld e, l .trainerLoop diff --git a/home/yes_no.asm b/home/yes_no.asm index 63b20e93c..1a8c2e3ca 100644 --- a/home/yes_no.asm +++ b/home/yes_no.asm @@ -5,11 +5,14 @@ YesNoChoice:: call InitYesNoTextBoxParameters jr DisplayYesNoChoice +; removed in bugfix patch to make space for trainer fly glitch fixes +IF !DEF(_BUGFIX) TwoOptionMenu:: ; unreferenced ld a, TWO_OPTION_MENU ld [wTextBoxID], a call InitYesNoTextBoxParameters jp DisplayTextBoxID +ENDC InitYesNoTextBoxParameters:: xor a ; YES_NO_MENU From b44d69bfbc037c8b7b4592dab7f5dd4c7af19385 Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Sun, 5 Nov 2023 01:51:09 -0400 Subject: [PATCH 19/37] fixes for pikawalk --- engine/pikachu/pikachu_follow.asm | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/engine/pikachu/pikachu_follow.asm b/engine/pikachu/pikachu_follow.asm index 9575c3415..9862bcfe0 100644 --- a/engine/pikachu/pikachu_follow.asm +++ b/engine/pikachu/pikachu_follow.asm @@ -1164,13 +1164,34 @@ ClearPikachuFollowCommandBuffer: AppendPikachuFollowCommandToBuffer: ld hl, wPikachuFollowCommandBufferSize +; Bugfixes for pikawalk +; The game allocates 1+16 bytes of space for pikachu follow commands +; But the original source has no bounds checking to ensure the buffer size +; stays within the allocated bounds, opening up a buffer overflow exploit +; by walking with pikachu asleep offscreen in the Pewter City Pokemon Center +IF DEF(_BUGFIX) + push af + ld a, 17 + cp [hl] + jp z, .skipAppending +ENDC inc [hl] ld e, [hl] ld d, 0 ld hl, wPikachuFollowCommandBuffer add hl, de +; restore af from the skip check +IF DEF(_BUGFIX) + pop af +ENDC ld [hl], a ret +; restore af from the skip check and return +IF DEF(_BUGFIX) +.skipAppending + pop af + ret +ENDC RefreshPikachuFollow: call ClearPikachuFollowCommandBuffer From 69da0a8ab74c936e1916f0f7d89734af728062e1 Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Sun, 5 Nov 2023 17:09:31 -0500 Subject: [PATCH 20/37] Refine the pikawalk bugfix behavior --- engine/pikachu/pikachu_follow.asm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/engine/pikachu/pikachu_follow.asm b/engine/pikachu/pikachu_follow.asm index 9862bcfe0..374400c05 100644 --- a/engine/pikachu/pikachu_follow.asm +++ b/engine/pikachu/pikachu_follow.asm @@ -1169,13 +1169,13 @@ AppendPikachuFollowCommandToBuffer: ; But the original source has no bounds checking to ensure the buffer size ; stays within the allocated bounds, opening up a buffer overflow exploit ; by walking with pikachu asleep offscreen in the Pewter City Pokemon Center + inc [hl] IF DEF(_BUGFIX) push af - ld a, 17 + ld a, 15 cp [hl] - jp z, .skipAppending + jp c, .skipAppending ENDC - inc [hl] ld e, [hl] ld d, 0 ld hl, wPikachuFollowCommandBuffer From 70d87f594ba21eb50d97f137287d4b2b0cfee499 Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Sun, 5 Nov 2023 17:32:37 -0500 Subject: [PATCH 21/37] Optimizations and documentation improvement --- engine/menus/save.asm | 7 +++++-- engine/pikachu/pikachu_follow.asm | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/engine/menus/save.asm b/engine/menus/save.asm index 195cec4f6..ee0bb3c8c 100644 --- a/engine/menus/save.asm +++ b/engine/menus/save.asm @@ -174,17 +174,19 @@ IF DEF(_BUGFIX) call EnableSRAMAndLatchClockData ld a, $1 ld [MBC1SRamBank], a - ld a, 1 + xor a + inc a ld [sSaveInProgress], a ld a, [wRandomSeed] ld [sRandomSeed], a ENDC call SaveSAVtoSRAM +; reset the saving in progress flag IF DEF(_BUGFIX) call EnableSRAMAndLatchClockData ld a, $1 ld [MBC1SRamBank], a - ld a, 0 + xor a ld [sSaveInProgress], a call DisableSRAMAndPrepareClockData ELSE @@ -314,6 +316,7 @@ SAVCheckSum: .loop ld a, [hli] add d +; make the checksum a little more powerful IF DEF(_BUGFIX) rrca ENDC diff --git a/engine/pikachu/pikachu_follow.asm b/engine/pikachu/pikachu_follow.asm index 374400c05..a35fea830 100644 --- a/engine/pikachu/pikachu_follow.asm +++ b/engine/pikachu/pikachu_follow.asm @@ -1165,7 +1165,7 @@ ClearPikachuFollowCommandBuffer: AppendPikachuFollowCommandToBuffer: ld hl, wPikachuFollowCommandBufferSize ; Bugfixes for pikawalk -; The game allocates 1+16 bytes of space for pikachu follow commands +; The game allocates 16 bytes of space for pikachu follow commands ; But the original source has no bounds checking to ensure the buffer size ; stays within the allocated bounds, opening up a buffer overflow exploit ; by walking with pikachu asleep offscreen in the Pewter City Pokemon Center @@ -1186,7 +1186,7 @@ IF DEF(_BUGFIX) ENDC ld [hl], a ret -; restore af from the skip check and return +; restore af from the skip check and return IF DEF(_BUGFIX) .skipAppending pop af From 9a133158a26be7f9f17038f688fa390c3201fdec Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Sun, 5 Nov 2023 21:57:23 -0500 Subject: [PATCH 22/37] some cleanup --- engine/battle/core.asm | 5 +---- ram/wram.asm | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/engine/battle/core.asm b/engine/battle/core.asm index 59323d44c..d35882822 100644 --- a/engine/battle/core.asm +++ b/engine/battle/core.asm @@ -6802,12 +6802,12 @@ ApplyBadgeStatBoosts: ld a, [wLinkState] cp LINK_STATE_BATTLING ret z ; return if link battle -IF DEF(_BUGFIX) ld a, [wObtainedBadges] ld b, a ld hl, wBattleMonAttack ; loop unrolled to fix badge boosts to match in game text ; and the way it was fixed in FRLG +IF DEF(_BUGFIX) srl b call c, .applyBoostToStat ld hl, wBattleMonSpeed @@ -6824,9 +6824,6 @@ IF DEF(_BUGFIX) call c, .applyBoostToStat ret ELSE - ld a, [wObtainedBadges] - ld b, a - ld hl, wBattleMonAttack ld c, $4 ; the boost is applied for badges whose bit position is even ; the order of boosts matches the order they are laid out in RAM diff --git a/ram/wram.asm b/ram/wram.asm index 21b808b35..398bd4757 100644 --- a/ram/wram.asm +++ b/ram/wram.asm @@ -1208,7 +1208,7 @@ wStatusScreenHPBarColor:: db IF DEF(_BUGFIX) wRandomSeed:: db - ds 3 + ds 6 ELSE From 110a3c927e2fb329c97c9ff262850cf14dc4f6c0 Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Tue, 7 Nov 2023 00:28:49 -0500 Subject: [PATCH 23/37] Actually fix fast options --- engine/menus/options.asm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/engine/menus/options.asm b/engine/menus/options.asm index 49ab5d701..52382db7f 100644 --- a/engine/menus/options.asm +++ b/engine/menus/options.asm @@ -1,9 +1,11 @@ DisplayOptionMenu_: - ; This line fixes the Fast Options glitch + ; This section fixes the Fast Options glitch ; The code as written applies any direction button presses done simultaneous with selecting the menu ; To each option while rendering the menu IF DEF(_BUGFIX) call JoypadLowSensitivity + xor a + ldh [hJoy5], a ENDC call InitOptionsMenu .optionMenuLoop From 8a630674cbc19d2b057c296072c1a07656417fcd Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Tue, 7 Nov 2023 23:12:57 -0500 Subject: [PATCH 24/37] continuing to port fixes from pokered archives --- README.md | 2 ++ data/maps/objects/Route17.asm | 4 +++ engine/battle/animations.asm | 3 ++ engine/battle/core.asm | 41 +++++++++++++++++++++++ engine/battle/init_battle.asm | 38 ++++++++++++++++++++- engine/battle/move_effects/substitute.asm | 5 ++- engine/battle/trainer_ai.asm | 12 +++++++ engine/items/item_effects.asm | 5 +++ 8 files changed, 108 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 571107916..4f71f572a 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,8 @@ This version includes the ability to optionally compile with a set of bugfix pat `make BUGFIX=1` +Many of these patches are sourced from the research done on [pokered](https://github.com/pret/pokered/wiki/%5BARCHIVED%5D-Bugs-and-Glitches) which is now defunct and archived. Some patches were also written specifically for this project (badge boosts, fast options) and some were collaborations with other Pokemon Speedrun community members including CasualPokePlayer and luckytyphlosion (statistically validated PRNG). + ## See also - [**Wiki**][wiki] (includes [tutorials][tutorials]) diff --git a/data/maps/objects/Route17.asm b/data/maps/objects/Route17.asm index 48d889265..0d352708d 100644 --- a/data/maps/objects/Route17.asm +++ b/data/maps/objects/Route17.asm @@ -10,6 +10,10 @@ Route17_Object: bg_event 9, 87, 14 ; Route17Text14 bg_event 9, 111, 15 ; Route17Text15 bg_event 9, 141, 16 ; Route17Text16 +; fix the sign at Route 16 showing Celadon <-> Fuchsia when read from the front +IF DEF(_BUGFIX) + bg_event 5, -1, 17 ; Route17Text17 +ENDC def_object_events object_event 12, 19, SPRITE_BIKER, STAY, LEFT, 1, OPP_CUE_BALL, 4 diff --git a/engine/battle/animations.asm b/engine/battle/animations.asm index 373c9ee33..a3f223fa2 100644 --- a/engine/battle/animations.asm +++ b/engine/battle/animations.asm @@ -1413,7 +1413,10 @@ AdjustOAMBlockYPos2: add b cp 112 jr c, .skipSettingPreviousEntrysAttribute +; fix swag boulder +IF !DEF(_BUGFIX) dec hl +ENDC ld a, 160 ; bug, sets previous OAM entry's attribute ld [hli], a .skipSettingPreviousEntrysAttribute diff --git a/engine/battle/core.asm b/engine/battle/core.asm index d35882822..696402f25 100644 --- a/engine/battle/core.asm +++ b/engine/battle/core.asm @@ -2490,7 +2490,16 @@ PartyMenuOrRockOrRun: ld [wd0b5], a call GetMonHeader ld de, vFrontPic +; ensure we don't identify ghost encounters when reloading battle sprites +IF DEF(_BUGFIX) + call IsGhostBattle + push af + call nz, LoadMonFrontSprite + pop af + call z, LoadGhostPic +ELSE call LoadMonFrontSprite +ENDC jr .enemyMonPicReloaded .doEnemyMonAnimation ld b, BANK(AnimationSubstitute) ; BANK(AnimationMinimizeMon) @@ -2913,6 +2922,12 @@ NoMovesLeftText: text_end SwapMovesInMenu: +; Prevent move swapping while transformed +IF DEF(_BUGFIX) + ld a, [wPlayerBattleStatus3] + bit TRANSFORMED, a + jp nz, MoveSelectionMenu +ENDC IF DEF(_DEBUG) ld a, [wFlags_D733] bit BIT_TEST_BATTLE, a @@ -5478,6 +5493,24 @@ AdjustDamageForMoveType: ld b, a ld a, [hl] ; a = damage multiplier ldh [hMultiplier], a +; fix the reported type effectiveness of moves used on dual type pokemon +IF DEF(_BUGFIX) + and a ; cp NO_EFFECT + jr z, .gotMultiplier + cp NOT_VERY_EFFECTIVE + jr nz, .nothalf + ld a, [wDamageMultipliers] + and $7f + srl a + jr .gotMultiplier +.nothalf + cp SUPER_EFFECTIVE + jr nz, .gotMultiplier + ld a, [wDamageMultipliers] + and $7f + sla a +.gotMultiplier +ENDC add b ld [wDamageMultipliers], a xor a @@ -6473,12 +6506,20 @@ LoadEnemyMonData: ld a, [wEnemyMonSpecies2] ld [wd11e], a predef IndexToPokedex +; avoid marking a pokemon as seen if it's not identified via the silph scope +IF DEF(_BUGFIX) + call IsGhostBattle + jr z, .noMarkSeen +ENDC ld a, [wd11e] dec a ld c, a ld b, FLAG_SET ld hl, wPokedexSeen predef FlagActionPredef ; mark this mon as seen in the pokedex +IF DEF(_BUGFIX) +.noMarkSeen +ENDC ld hl, wEnemyMonLevel ld de, wEnemyMonUnmodifiedLevel ld bc, 1 + NUM_STATS * 2 diff --git a/engine/battle/init_battle.asm b/engine/battle/init_battle.asm index e7be112cd..47b2be27d 100644 --- a/engine/battle/init_battle.asm +++ b/engine/battle/init_battle.asm @@ -56,7 +56,38 @@ InitBattleCommon: jp z, _InitBattleCommon callabd_ModifyPikachuHappiness PIKAHAPPY_GYMLEADER ; useless since already in bank3d jp _InitBattleCommon - +; fixes for identifying ghosts via entering and leaving menus +IF DEF(_BUGFIX) +LoadGhostPic: + ld hl, wMonHSpriteDim + ld a, $66 + ld [hli], a ; write sprite dimensions + ld bc, GhostPic + ld a, c + ld [hli], a ; write front sprite pointer + ld [hl], b + ld hl, wEnemyMonNick ; set name to "GHOST" + ld a, "G" + ld [hli], a + ld a, "H" + ld [hli], a + ld a, "O" + ld [hli], a + ld a, "S" + ld [hli], a + ld a, "T" + ld [hli], a + ld [hl], "@" + ld a, [wcf91] + push af + ld a, MON_GHOST + ld [wcf91], a + ld de, vFrontPic + call LoadMonFrontSprite ; load ghost sprite + pop af + ld [wcf91], a + ret +ENDC InitWildBattle: ld a, $1 ld [wIsInBattle], a @@ -68,6 +99,10 @@ InitWildBattle: callfar IsGhostBattle jr nz, .isNoGhost .isGhost +; fixes for identifying ghosts via entering and leaving menus +IF DEF(_BUGFIX) + call LoadGhostPic +ELSE ld hl, wMonHSpriteDim ld a, $66 ld [hli], a ; write sprite dimensions @@ -95,6 +130,7 @@ InitWildBattle: call LoadMonFrontSprite ; load ghost sprite pop af ld [wcf91], a +ENDC jr .spriteLoaded .isNoGhost ld de, vFrontPic diff --git a/engine/battle/move_effects/substitute.asm b/engine/battle/move_effects/substitute.asm index b1fd8ac28..8966000ee 100644 --- a/engine/battle/move_effects/substitute.asm +++ b/engine/battle/move_effects/substitute.asm @@ -37,7 +37,10 @@ SubstituteEffect_: sbc 0 pop bc jr c, .notEnoughHP ; underflow means user would be left with negative health - ; bug: since it only branches on carry, it will possibly leave user with 0 HP +; Prevent leaving the user at 0 HP by also branching on the zero flag +IF DEF(_BUGFIX) + jr z, .notEnoughHP +ENDC .userHasZeroOrMoreHP ldi [hl], a ; save resulting HP after subtraction into current HP ld [hl], d diff --git a/engine/battle/trainer_ai.asm b/engine/battle/trainer_ai.asm index 41325ce79..9e61b3b3e 100644 --- a/engine/battle/trainer_ai.asm +++ b/engine/battle/trainer_ai.asm @@ -558,6 +558,12 @@ AIPrintItemUseAndUpdateHPBar: xor a ld [wHPBarType], a predef UpdateHPBar2 +; fix to update enemy pokemon status HUD when healing items are used +IF DEF(_BUGFIX) + push af + farcall DrawEnemyHUDAndHPBar + pop af +ENDC jp DecrementAICount AISwitchIfEnoughMons: @@ -642,6 +648,12 @@ AICureStatus: ld [wEnemyMonStatus], a ; clear status of active enemy ld hl, wEnemyBattleStatus3 res 0, [hl] +; fix to update enemy pokemon status HUD when healing items are used +IF DEF(_BUGFIX) + push af + farcall DrawEnemyHUDAndHPBar + pop af +ENDC ret AIUseXAccuracy: ; unused diff --git a/engine/items/item_effects.asm b/engine/items/item_effects.asm index eddb1fa36..30bdc9c21 100644 --- a/engine/items/item_effects.asm +++ b/engine/items/item_effects.asm @@ -488,8 +488,13 @@ ItemUseBall: ld hl, wEnemyBattleStatus3 bit TRANSFORMED, [hl] jr z, .notTransformed +; there's no reason to assume that a transformed pokemon is a ditto +; if a player battles with a ditto with transform against a wild pokemon with mirror move +; it could copy TRANSFORM and then if it uses it be caught as a ditto improperly +IF !DEF(_BUGFIX) ld a, DITTO ld [wEnemyMonSpecies2], a +ENDC jr .skip6 .notTransformed From fe3b98afc614e3790ae6a89784db1f5b01fc5386 Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Tue, 7 Nov 2023 23:16:54 -0500 Subject: [PATCH 25/37] finish fixing route 17 sign text --- scripts/Route17.asm | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/scripts/Route17.asm b/scripts/Route17.asm index 526b25763..05b214dbe 100644 --- a/scripts/Route17.asm +++ b/scripts/Route17.asm @@ -29,6 +29,10 @@ Route17_TextPointers: dw Route17Text14 dw Route17Text15 dw Route17Text16 +; fix the sign at Route 16 showing Celadon <-> Fuchsia when read from the front +IF DEF(_BUGFIX) + dw Route17Text17 +ENDC Route17TrainerHeaders: def_trainers @@ -257,3 +261,9 @@ Route17Text15: Route17Text16: text_far _Route17Text16 text_end +; fix the sign at Route 16 showing Celadon <-> Fuchsia when read from the front +IF DEF(_BUGFIX) +Route17Text17: + text_far _Route16Text9 + text_end +ENDC From 4be47712b10dafb57073f2ea48ad1d1a38d9ff81 Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Wed, 8 Nov 2023 00:57:05 -0500 Subject: [PATCH 26/37] continuing to port fixes from pokered archives --- audio/engine_1.asm | 10 +++++++++- data/battle_anims/subanimations.asm | 7 ++++++- data/maps/dungeon_maps.asm | 21 ++++++++++++++++----- engine/battle/animations.asm | 4 ++++ engine/battle/core.asm | 22 ++++++++++++++++++++++ engine/movie/splash.asm | 7 ++++++- engine/overworld/healing_machine.asm | 7 ++++++- engine/overworld/movement.asm | 10 ++++++++++ engine/overworld/player_animations.asm | 14 ++++++++++++++ engine/slots/slot_machine.asm | 21 ++++++++++++++++++--- home/overworld.asm | 6 ++++++ home/trainers.asm | 4 ++++ home/uncompress.asm | 16 ++++++++++++++++ scripts/Route12Gate2F.asm | 7 +++++++ 14 files changed, 144 insertions(+), 12 deletions(-) diff --git a/audio/engine_1.asm b/audio/engine_1.asm index c155dda63..16821b2cd 100644 --- a/audio/engine_1.asm +++ b/audio/engine_1.asm @@ -1241,13 +1241,21 @@ Audio1_InitPitchSlideVars: ; This means that the result will be 0x200 greater than it should be if the ; low byte of the current frequency is greater than the low byte of the ; target frequency. +IF DEF(_BUGFIX) + push af + ld hl, wChannelPitchSlideTargetFrequencyHighBytes + add hl, bc + pop af + ld a, [hl] + sbc b +ELSE ld a, d sbc b ld d, a - ld hl, wChannelPitchSlideTargetFrequencyHighBytes add hl, bc ld a, [hl] +ENDC sub d ld d, a ld b, 0 diff --git a/data/battle_anims/subanimations.asm b/data/battle_anims/subanimations.asm index 74097e226..9b419ff0a 100644 --- a/data/battle_anims/subanimations.asm +++ b/data/battle_anims/subanimations.asm @@ -547,7 +547,12 @@ Subanim_0Circle_1Square_TossBack: db FRAMEBLOCK_47, BASECOORD_B0, FRAMEBLOCKMODE_00 Subanim_0CirclesCentering: - subanim SUBANIMTYPE_COORDFLIP, 6 ; should be SUBANIMTYPE_HVFLIP +; fix animation when AI uses double edge +IF DEF(_BUGFIX) + subanim SUBANIMTYPE_HVFLIP, 6 +ELSE + subanim SUBANIMTYPE_COORDFLIP, 6 +ENDC db FRAMEBLOCK_44, BASECOORD_64, FRAMEBLOCKMODE_00 db FRAMEBLOCK_45, BASECOORD_65, FRAMEBLOCKMODE_00 db FRAMEBLOCK_46, BASECOORD_66, FRAMEBLOCKMODE_00 diff --git a/data/maps/dungeon_maps.asm b/data/maps/dungeon_maps.asm index d647923cd..fbec3af4e 100644 --- a/data/maps/dungeon_maps.asm +++ b/data/maps/dungeon_maps.asm @@ -1,8 +1,3 @@ -; GetBattleTransitionID_IsDungeonMap fails to recognize -; VICTORY_ROAD_2F, VICTORY_ROAD_3F, all ROCKET_HIDEOUT maps, -; POKEMON_MANSION_1F, SEAFOAM_ISLANDS_[B1F-B4F], POWER_PLANT, -; DIGLETTS_CAVE, and SILPH_CO_[9-11]F as dungeon maps - ; GetBattleTransitionID_IsDungeonMap checks if wCurMap ; is equal to one of these maps DungeonMaps1: @@ -10,6 +5,14 @@ DungeonMaps1: db ROCK_TUNNEL_1F db SEAFOAM_ISLANDS_1F db ROCK_TUNNEL_B1F +; fix missing dungeon maps +IF DEF(_BUGFIX) + db POKEMON_MANSION_1F + db VICTORY_ROAD_2F + db VICTORY_ROAD_3F + db POWER_PLANT + db DIGLETTS_CAVE +ENDC db -1 ; end ; GetBattleTransitionID_IsDungeonMap checks if wCurMap @@ -24,4 +27,12 @@ DungeonMaps2: ; SILPH_CO_[2-8]F, POKEMON_MANSION[2F-B1F], SAFARI_ZONE, and ; CERULEAN_CAVE maps, except for SILPH_CO_1F db SILPH_CO_2F, CERULEAN_CAVE_1F +IF DEF(_BUGFIX) + ; SILPH_CO_[9-11]F + db SILPH_CO_9F, SILPH_CO_11F + ; SEAFOAM_ISLANDS_[B1F-B4F] + db SEAFOAM_ISLANDS_B1F, SEAFOAM_ISLANDS_B4F + ; all ROCKET_HIDEOUT maps + db ROCKET_HIDEOUT_B1F, ROCKET_HIDEOUT_B4F +ENDC db -1 ; end diff --git a/engine/battle/animations.asm b/engine/battle/animations.asm index a3f223fa2..68b591c70 100644 --- a/engine/battle/animations.asm +++ b/engine/battle/animations.asm @@ -1934,7 +1934,11 @@ _AnimationSlideMonOff: sub 7 ; This has the same problem as above, but it has no visible effect because ; the lower right tile is in the first column to slide off the screen. +IF DEF(_BUGFIX) + cp $31 +ELSE cp $30 +ENDC ret c ld a, " " ret diff --git a/engine/battle/core.asm b/engine/battle/core.asm index 696402f25..91f8521c6 100644 --- a/engine/battle/core.asm +++ b/engine/battle/core.asm @@ -1228,6 +1228,11 @@ SlideDownFaintedMonPic: push de push hl ld b, 6 ; number of rows +; fix tearing during sliding animations +IF DEF(_BUGFIX) + xor a + ld [hAutoBGTransferEnabled], a +ENDC .rowLoop push bc push hl @@ -1252,6 +1257,12 @@ SlideDownFaintedMonPic: add hl, bc ld de, SevenSpacesText call PlaceString +; fix tearing during sliding animations +IF DEF(_BUGFIX) + xor a + inc a + ld [hAutoBGTransferEnabled], a +ENDC ld c, 2 call DelayFrames pop hl @@ -1277,6 +1288,11 @@ SlideTrainerPicOffScreen: push bc push hl ld b, 7 ; number of rows +; fix tearing during sliding animations +IF DEF(_BUGFIX) + xor a + ld [hAutoBGTransferEnabled], a +ENDC .rowLoop push hl ldh a, [hSlideAmount] @@ -1302,6 +1318,12 @@ SlideTrainerPicOffScreen: add hl, de dec b jr nz, .rowLoop +; fix tearing during sliding animations +IF DEF(_BUGFIX) + xor a + inc a + ld [hAutoBGTransferEnabled], a +ENDC ld c, 2 call DelayFrames pop hl diff --git a/engine/movie/splash.asm b/engine/movie/splash.asm index b393d3194..e80fe7da9 100644 --- a/engine/movie/splash.asm +++ b/engine/movie/splash.asm @@ -136,7 +136,12 @@ AnimateShootingStar: ld a, [wMoveDownSmallStarsOAMCount] cp 24 jr z, .next2 - add 6 ; should be 4, but the extra 2 aren't visible on screen +; originally 2 extra stars are set up but only offscreen +IF DEF(_BUGFIX) + add 4 +ELSE + add 6 +ENDC ld [wMoveDownSmallStarsOAMCount], a .next2 call MoveDownSmallStars diff --git a/engine/overworld/healing_machine.asm b/engine/overworld/healing_machine.asm index 3bd739b7a..2d7cb2d96 100644 --- a/engine/overworld/healing_machine.asm +++ b/engine/overworld/healing_machine.asm @@ -1,7 +1,12 @@ AnimateHealingMachine: ld de, PokeCenterFlashingMonitorAndHealBall ld hl, vChars0 tile $7c - lb bc, BANK(PokeCenterFlashingMonitorAndHealBall), 3 ; should be 2 +; fix an animation in the healing machine +IF DEF(_BUGFIX) + lb bc, BANK(PokeCenterFlashingMonitorAndHealBall), 2 +ELSE + lb bc, BANK(PokeCenterFlashingMonitorAndHealBall), 3 +ENDC call CopyVideoData ld hl, wUpdateSpritesEnabled ld a, [hl] diff --git a/engine/overworld/movement.asm b/engine/overworld/movement.asm index e6ca87486..818ecfa9f 100644 --- a/engine/overworld/movement.asm +++ b/engine/overworld/movement.asm @@ -580,12 +580,22 @@ CanWalkOntoTile: ld a, [hli] ; x#SPRITESTATEDATA1_YPIXELS add $4 ; align to blocks (Y pos is always 4 pixels off) add d ; add Y delta +; fix the bottom row of the screen being treated as offscreen +IF DEF(_BUGFIX) + cp $81 +ELSE cp $80 ; if value is >$80, the destination is off screen (either $81 or $FF underflow) +ENDC jr nc, .impassable ; don't walk off screen inc l ld a, [hl] ; x#SPRITESTATEDATA1_XPIXELS add e ; add X delta +; fix the rightmost column of the screen being treated as offscreen +IF DEF(_BUGFIX) + cp $91 +ELSE cp $90 ; if value is >$90, the destination is off screen (either $91 or $FF underflow) +ENDC jr nc, .impassable ; don't walk off screen push de push bc diff --git a/engine/overworld/player_animations.asm b/engine/overworld/player_animations.asm index 6f8a5c188..1569da7ba 100644 --- a/engine/overworld/player_animations.asm +++ b/engine/overworld/player_animations.asm @@ -90,6 +90,10 @@ PlayerSpinWhileMovingDown: ld [hli], a ; wPlayerSpinWhileMovingUpOrDownAnimMaxY call GetPlayerTeleportAnimFrameDelay ld [hl], a ; wPlayerSpinWhileMovingUpOrDownAnimFrameDelay +; fix a garbage text character appearing instead of the spinning animation when using escape rope +IF DEF(_BUGFIX) + ld hl, wFacingDirectionList +ENDC jp PlayerSpinWhileMovingUpOrDown @@ -112,6 +116,10 @@ _LeaveMapAnim:: ld [hli], a ; wPlayerSpinWhileMovingUpOrDownAnimMaxY call GetPlayerTeleportAnimFrameDelay ld [hl], a ; wPlayerSpinWhileMovingUpOrDownAnimFrameDelay +; fix a garbage text character appearing instead of the spinning animation when using escape rope +IF DEF(_BUGFIX) + ld hl, wFacingDirectionList +ENDC call PlayerSpinWhileMovingUpOrDown call IsPlayerStandingOnWarpPadOrHole ld a, b @@ -206,6 +214,12 @@ FlyAnimationScreenCoords2: db $F0, $00 LeaveMapThroughHoleAnim: +; reset the music after falling through a hole on a bicycle +IF DEF(_BUGFIX) + ld a, [wLastMusicSoundID] + cp MUSIC_BIKE_RIDING + call z, PlayDefaultMusic +ENDC ld a, $ff ld [wUpdateSpritesEnabled], a ; disable UpdateSprites ; shift upper half of player's sprite down 8 pixels and hide lower half diff --git a/engine/slots/slot_machine.asm b/engine/slots/slot_machine.asm index 3918e8793..fb0e1cd1e 100644 --- a/engine/slots/slot_machine.asm +++ b/engine/slots/slot_machine.asm @@ -305,7 +305,12 @@ SlotMachine_StopWheel1Early: .loop ld a, [hli] cp HIGH(SLOTS7) - jr c, .stopWheel ; condition never true +; the original condition is never true, intended to compare against the zero flag +IF DEF(_BUGFIX) + jr z, .stopWheel +ELSE + jr c, .stopWheel +ENDC dec c jr nz, .loop ret @@ -854,7 +859,12 @@ LoadSlotMachineTiles: call DisableLCD ld hl, SlotMachineTiles2 ld de, vChars0 - ld bc, $1c tiles ; should be SlotMachineTiles2End - SlotMachineTiles2, or $18 tiles +; should be SlotMachineTiles2End - SlotMachineTiles2, or $18 tiles +IF DEF(_BUGFIX) + ld bc, SlotMachineTiles2End - SlotMachineTiles2 +ELSE + ld bc, $1c tiles +ENDC ld a, BANK(SlotMachineTiles2) call FarCopyData ld hl, SlotMachineTiles1 @@ -864,7 +874,12 @@ LoadSlotMachineTiles: call FarCopyData ld hl, SlotMachineTiles2 ld de, vChars2 tile $25 - ld bc, $1c tiles ; should be SlotMachineTiles2End - SlotMachineTiles2, or $18 tiles +; should be SlotMachineTiles2End - SlotMachineTiles2, or $18 tiles +IF DEF(_BUGFIX) + ld bc, SlotMachineTiles2End - SlotMachineTiles2 +ELSE + ld bc, $1c tiles +ENDC ld a, BANK(SlotMachineTiles2) call FarCopyData ld hl, SlotMachineMap diff --git a/home/overworld.asm b/home/overworld.asm index 62d0e3b77..8dfa48e7b 100644 --- a/home/overworld.asm +++ b/home/overworld.asm @@ -1329,7 +1329,13 @@ CheckForTilePairCollisions:: jr .retry .currentTileMatchesFirstInPair inc hl +; fix performance issue in collision detection +; the original code can continue to loop unnecessarily after finding a match in the pair +IF DEF(_BUGFIX) + ld a, [hli] +ELSE ld a, [hl] +ENDC cp c jr z, .foundMatch jr .tilePairCollisionLoop diff --git a/home/trainers.asm b/home/trainers.asm index 2a95a8270..93566cfb3 100644 --- a/home/trainers.asm +++ b/home/trainers.asm @@ -72,10 +72,13 @@ ReadTrainerHeaderInfo:: jr z, .readPointer ; read end battle text cp $a jr nz, .done +; fix the end battle text (2) +IF !DEF(_BUGFIX) ld a, [hli] ; read end battle text (2) but override the result afterwards (XXX why, bug?) ld d, [hl] ld e, a jr .done +ENDC .readPointer ld a, [hli] ld h, [hl] @@ -108,6 +111,7 @@ TalkToTrainer:: call ReadTrainerHeaderInfo ; print before battle text call PrintText ld a, $a +; this is fixed by the bugfix in nonZeroOffset call ReadTrainerHeaderInfo ; (?) does nothing apparently (maybe bug in ReadTrainerHeaderInfo) push de ld a, $8 diff --git a/home/uncompress.asm b/home/uncompress.asm index 27474f2dc..63c50099f 100644 --- a/home/uncompress.asm +++ b/home/uncompress.asm @@ -31,14 +31,30 @@ _UncompressSpriteData:: ld [wSpriteLoadFlags], a call ReadNextInputByte ; first byte of input determines sprite width (high nybble) and height (low nybble) in tiles (8x8 pixels) ld b, a +; fix glitch sprites corrupting SRAM +IF DEF(_BUGFIX) + and $7 + jr nz, .skip1 + inc a +.skip1 +ELSE and $f +ENDC add a add a add a ld [wSpriteHeight], a ld a, b swap a +; fix glitch sprites corrupting SRAM +IF DEF(_BUGFIX) + and $7 + jr nz, .skip2 + inc a +.skip2 +ELSE and $f +ENDC add a add a add a diff --git a/scripts/Route12Gate2F.asm b/scripts/Route12Gate2F.asm index 2174fba8b..3e9cc89e1 100644 --- a/scripts/Route12Gate2F.asm +++ b/scripts/Route12Gate2F.asm @@ -68,6 +68,12 @@ GateUpstairsScript_PrintIfFacingUp: ld a, [wSpritePlayerStateData1FacingDirection] cp SPRITE_FACING_UP jr z, .up +; fix the route 12 gate binoculars +IF DEF(_BUGFIX) + ld hl, TVWrongSideText +.up + call PrintText +ELSE ld a, TRUE jr .done .up @@ -75,4 +81,5 @@ GateUpstairsScript_PrintIfFacingUp: xor a .done ld [wDoNotWaitForButtonPressAfterDisplayingText], a +ENDC jp TextScriptEnd From 59597970e952a654b9b3e720c97b1bb9e02f281a Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Wed, 8 Nov 2023 02:19:07 -0500 Subject: [PATCH 27/37] Port more fixes from pret archives --- engine/battle/core.asm | 3 +++ engine/battle/effects.asm | 5 ++++- engine/battle/trainer_ai.asm | 8 +++++--- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/engine/battle/core.asm b/engine/battle/core.asm index 91f8521c6..b1eb237ad 100644 --- a/engine/battle/core.asm +++ b/engine/battle/core.asm @@ -5648,6 +5648,9 @@ MoveHitTest: jr z, .checkForDigOrFlyStatus ; The fix for Swift broke this code. It's supposed to prevent HP draining moves from working on Substitutes. ; Since CheckTargetSubstitute overwrites a with either $00 or $01, it never works. +IF DEF(_BUGFIX) + ld a, [de] +ENDC cp DRAIN_HP_EFFECT jp z, .moveMissed cp DREAM_EATER_EFFECT diff --git a/engine/battle/effects.asm b/engine/battle/effects.asm index 1d1d2438f..3db757c0e 100644 --- a/engine/battle/effects.asm +++ b/engine/battle/effects.asm @@ -327,7 +327,10 @@ FreezeBurnParalyzeEffect: ld hl, BurnedText jp PrintText .freeze2 -; hyper beam bits aren't reseted for opponent's side +; hyper beam bits aren't reset for the opponent's side +IF DEF(_BUGFIX) + call ClearHyperBeam +ENDC ld a, 1 << FRZ ld [wBattleMonStatus], a ld a, SHAKE_SCREEN_ANIM diff --git a/engine/battle/trainer_ai.asm b/engine/battle/trainer_ai.asm index 9e61b3b3e..0d499f669 100644 --- a/engine/battle/trainer_ai.asm +++ b/engine/battle/trainer_ai.asm @@ -351,10 +351,12 @@ CooltrainerMAI: jp AIUseXAttack CooltrainerFAI: - ; The intended 25% chance to consider switching will not apply. - ; Uncomment the line below to fix this. cp 25 percent + 1 - ; ret nc +; The intended 25% chance to consider switching will not apply. +; Uncomment the line below to fix this. +IF DEF(_BUGFIX) + ret nc +ENDC ld a, 10 call AICheckIfHPBelowFraction jp c, AIUseHyperPotion From 1ca07006a846a9ac8f413337646343405f892640 Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Wed, 8 Nov 2023 03:30:37 -0500 Subject: [PATCH 28/37] fix leaving mr fujis house --- scripts/PokemonTower7F.asm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/PokemonTower7F.asm b/scripts/PokemonTower7F.asm index c9da74f76..218c1e5a2 100644 --- a/scripts/PokemonTower7F.asm +++ b/scripts/PokemonTower7F.asm @@ -246,6 +246,11 @@ PokemonTower7Script11: ld [wDestinationWarpID], a ld a, LAVENDER_TOWN ld [wLastMap], a +; make it possible to leave mr fuji's house directly after warping +IF DEF(_BUGFIX) + ld hl, wd736 + set 2, [hl] +ENDC ld hl, wd72d set 3, [hl] ld a, $0 From a79cabc826846fad04552610083088587f400c36 Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Thu, 9 Nov 2023 01:16:06 -0500 Subject: [PATCH 29/37] fix xorshift rng algorithm --- engine/math/random.asm | 3 ++- engine/menus/main_menu.asm | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/engine/math/random.asm b/engine/math/random.asm index 3292352bb..8549e5d5d 100644 --- a/engine/math/random.asm +++ b/engine/math/random.asm @@ -23,6 +23,7 @@ ENDC IF DEF(_BUGFIX) ; luckytyphlosion implementation of xorshift prng +; ported from https://github.com/edrosten/8bit_rng XorshiftRandom: push bc ldh a, [rDIV] @@ -43,8 +44,8 @@ XorshiftRandom: ld a, c ld c, [hl] ; read in y ld [hld], a ; y = old z + ld [hl], c ; x = y ld c, a - ld [hl], a ; x = y ; hl = y ; vars ; b contains t diff --git a/engine/menus/main_menu.asm b/engine/menus/main_menu.asm index 2d3fe26fd..f68910434 100644 --- a/engine/menus/main_menu.asm +++ b/engine/menus/main_menu.asm @@ -1,8 +1,12 @@ MainMenu: ; Ensure we initialize wRandomSeed if it isn't carrying over from a previous save IF DEF(_BUGFIX) - ldh a, [rDIV] + xor a + ld [wRandomSeed], a ld [wRandomSeed], a + ld [wRandomSeed], a + inc a + ld [wRandomSeed+3], a ENDC ; Check save file call InitOptions From 1e58b16ae7e187fd862f8589b2eef7a4c79ff53b Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Thu, 9 Nov 2023 16:55:08 -0500 Subject: [PATCH 30/37] remove rdiv bit mix and save full 32 bits of rng state --- engine/math/random.asm | 8 +++----- engine/menus/save.asm | 12 ++++++++++++ ram/sram.asm | 3 +++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/engine/math/random.asm b/engine/math/random.asm index 8549e5d5d..17320f873 100644 --- a/engine/math/random.asm +++ b/engine/math/random.asm @@ -26,15 +26,13 @@ IF DEF(_BUGFIX) ; ported from https://github.com/edrosten/8bit_rng XorshiftRandom: push bc - ldh a, [rDIV] - rra ; shift into carry ld hl, wRandomSeed ld a, [hl] ; read in x ; x << 4 add a add a add a - adc a ; this mixes in 1 bit of rDIV into RNG + add a xor [hl] ld b, a ; t = x ^ (x << 4) ld hl, wRandomSeed + 3 @@ -51,9 +49,9 @@ XorshiftRandom: ; b contains t ; a/c contains z xor b ; z ^ t - rr c ; (z >> 1) + srl c ; (z >> 1) xor c ; z ^ t ^ (z >> 1) - rl b ; (t << 1) + sla b ; (t << 1) xor b ; z ^ t ^ (z >> 1) ^ (t << 1) ld [wRandomSeed + 3], a pop bc diff --git a/engine/menus/save.asm b/engine/menus/save.asm index ee0bb3c8c..50579cf0e 100644 --- a/engine/menus/save.asm +++ b/engine/menus/save.asm @@ -15,6 +15,12 @@ IF DEF(_BUGFIX) jr z, .badsum ld a, [sRandomSeed] ld [wRandomSeed], a + ld a, [sRandomSeed+1] + ld [wRandomSeed+1], a + ld a, [sRandomSeed+2] + ld [wRandomSeed+2], a + ld a, [sRandomSeed+3] + ld [wRandomSeed+3], a call DisableSRAMAndPrepareClockData ENDC call LoadSAV0 @@ -179,6 +185,12 @@ IF DEF(_BUGFIX) ld [sSaveInProgress], a ld a, [wRandomSeed] ld [sRandomSeed], a + ld a, [wRandomSeed+1] + ld [sRandomSeed+1], a + ld a, [wRandomSeed+2] + ld [sRandomSeed+2], a + ld a, [wRandomSeed+3] + ld [sRandomSeed+3], a ENDC call SaveSAVtoSRAM ; reset the saving in progress flag diff --git a/ram/sram.asm b/ram/sram.asm index 043a59c4f..583e9cc10 100644 --- a/ram/sram.asm +++ b/ram/sram.asm @@ -26,6 +26,9 @@ sMainDataCheckSum:: db IF DEF(_BUGFIX) sSaveInProgress:: db sRandomSeed:: db + + ds 3 + ENDC ; The PC boxes will not fit into one SRAM bank, From 987bb200350d8470fcdd79c0ac2a7ab47b76031f Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Sat, 11 Nov 2023 00:13:32 -0500 Subject: [PATCH 31/37] Fix accuracy scaling of Rage, Thrash, and Petal Dance --- engine/battle/core.asm | 16 ++++++++++++++++ ram/wram.asm | 6 ++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/engine/battle/core.asm b/engine/battle/core.asm index b1eb237ad..fa9ddbc11 100644 --- a/engine/battle/core.asm +++ b/engine/battle/core.asm @@ -5710,7 +5710,14 @@ ENDC ret nz ; if so, always hit regardless of accuracy/evasion .calcHitChance call CalcHitChance ; scale the move accuracy according to attacker's accuracy and target's evasion +; In the original code, wPlayerMoveAccuracy is not reset each turn before being scaled +; which affects multi turn moves like Rage and Thrash which don't reload the accuracy between turns +; we load explicitly from a separate scaled variable here to fix this +IF DEF(_BUGFIX) + ld a, [wScaledPlayerMoveAccuracy] +ELSE ld a, [wPlayerMoveAccuracy] +ENDC ld b, a ldh a, [hWhoseTurn] and a @@ -5751,7 +5758,16 @@ ENDC ; values for player turn CalcHitChance: +; In the original code, wPlayerMoveAccuracy is not reset each turn before being scaled +; which affects multi turn moves like Rage and Thrash which don't reload the accuracy between turns +; we explicitly reset the scaled accuracy from wPlayerMoveAccuracy each turn here to fix this +IF DEF(_BUGFIX) + ld a, [wPlayerMoveAccuracy] + ld [wScaledPlayerMoveAccuracy], a + ld hl, wScaledPlayerMoveAccuracy +ELSE ld hl, wPlayerMoveAccuracy +ENDC ldh a, [hWhoseTurn] and a ld a, [wPlayerMonAccuracyMod] diff --git a/ram/wram.asm b/ram/wram.asm index 398bd4757..cbb856dbe 100644 --- a/ram/wram.asm +++ b/ram/wram.asm @@ -1206,9 +1206,11 @@ wPartyMenuHPBarColors:: ds PARTY_LENGTH wStatusScreenHPBarColor:: db IF DEF(_BUGFIX) - wRandomSeed:: db +wRandomSeed:: db - ds 6 + ds 5 + +wScaledPlayerMoveAccuracy:: db ELSE From 8fbd7454890c5899395b51defd181e841445d3bd Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Sat, 11 Nov 2023 22:06:17 -0500 Subject: [PATCH 32/37] actually fix XorshiftRandom --- engine/math/random.asm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/engine/math/random.asm b/engine/math/random.asm index 17320f873..3426fb9cb 100644 --- a/engine/math/random.asm +++ b/engine/math/random.asm @@ -39,10 +39,11 @@ XorshiftRandom: ld a, [hld] ; read in a ; hl = +2 ld c, [hl] ; read in z ; hl = +2 ld [hld], a ; z = a ; hl = +1 - ld a, c + ld a, c ; move z to a ld c, [hl] ; read in y ld [hld], a ; y = old z - ld [hl], c ; x = y + ld [hl], c ; x = y + ld a, [wRandomSeed+2] ld c, a ; hl = y ; vars From 7171707ebd3d643c8eec523ba6a17eb3e2f780be Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Sat, 11 Nov 2023 22:06:31 -0500 Subject: [PATCH 33/37] actually fix x item badge boost reapplication --- engine/battle/effects.asm | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/engine/battle/effects.asm b/engine/battle/effects.asm index 3db757c0e..de09453a9 100644 --- a/engine/battle/effects.asm +++ b/engine/battle/effects.asm @@ -531,12 +531,16 @@ UpdateStatDone: pop af call nz, Bankswitch .applyBadgeBoostsAndStatusPenalties - ldh a, [hWhoseTurn] - and a ; Prevent reapplication of badge boosts IF DEF(_BUGFIX) + xor a + ld [wCalculateWhoseStats], a + ldh a, [hWhoseTurn] + and a call z, CalculateModifiedStats ENDC + ldh a, [hWhoseTurn] + and a call z, ApplyBadgeStatBoosts ; whenever the player uses a stat-up move, badge boosts get reapplied again to every stat, ; even to those not affected by the stat-up move (will be boosted further) ld hl, MonsStatsRoseText @@ -730,6 +734,8 @@ UpdateLoweredStatDone: ; Prevent reapplication of badge boosts IF DEF(_BUGFIX) call nz, CalculateModifiedStats + ldh a, [hWhoseTurn] + and a ENDC call nz, ApplyBadgeStatBoosts ; whenever the player uses a stat-down move, badge boosts get reapplied again to every stat, ; even to those not affected by the stat-up move (will be boosted further) From 2188a81f36b2b913533d6c567295c49a7e786a7b Mon Sep 17 00:00:00 2001 From: Travis Mcgeehan Date: Sun, 12 Nov 2023 20:16:03 -0500 Subject: [PATCH 34/37] Fix bugs with healing and switch out text --- engine/battle/common_text.asm | 12 ++++++++++++ engine/battle/move_effects/heal.asm | 11 +++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/engine/battle/common_text.asm b/engine/battle/common_text.asm index 95c06bf5d..1482b247a 100644 --- a/engine/battle/common_text.asm +++ b/engine/battle/common_text.asm @@ -200,6 +200,10 @@ PlayerMon2Text: ld b, [hl] ld a, [de] sbc b +; original code ignores underflow, if we underflow, print default text +IF DEF(_BUGFIX) + jr c, .gainedHP +ENDC ldh [hMultiplicand + 1], a ld a, 25 ldh [hMultiplier], a @@ -234,6 +238,14 @@ PlayerMon2Text: ret c ld hl, GoodText ; HP went down 70% or more ret +; fallback to default text for underflow +IF DEF(_BUGFIX) +.gainedHP + pop bc + pop de + ld hl, EnoughText + ret +ENDC EnoughText: text_far _EnoughText diff --git a/engine/battle/move_effects/heal.asm b/engine/battle/move_effects/heal.asm index c3ffda657..d5f9f0062 100644 --- a/engine/battle/move_effects/heal.asm +++ b/engine/battle/move_effects/heal.asm @@ -11,13 +11,20 @@ HealEffect_: .healEffect ld b, a ld a, [de] - cp [hl] ; most significant bytes comparison is ignored - ; causes the move to miss if max HP is 255 or 511 points higher than the current HP + cp [hl] inc de inc hl +; most significant bytes comparison is ignored from cp [hl] +; causes the move to miss if max HP is 255 or 511 points higher than the current HP +IF DEF(_BUGFIX) + jr z, .passed +ENDC ld a, [de] sbc [hl] jp z, .failed ; no effect if user's HP is already at its maximum +IF DEF(_BUGFIX) +.passed +ENDC ld a, b cp REST jr nz, .healHP From d502a1679a6c3a9b55360bb89285328450599934 Mon Sep 17 00:00:00 2001 From: TiKevin83 <38826675+TiKevin83@users.noreply.github.com> Date: Tue, 14 Nov 2023 18:55:42 -0500 Subject: [PATCH 35/37] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4f71f572a..7bb0c8268 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Pokémon Yellow [![Build Status][ci-badge]][ci] +# Pokémon Yellow Fort Knox Edition [![Build Status][ci-badge]][ci] This is a disassembly of Pokémon Yellow. @@ -10,9 +10,9 @@ It builds the following ROMs: To set up the repository, see [**INSTALL.md**](INSTALL.md). -## Bugfix Patch +## Fort Knox Edition -This version includes the ability to optionally compile with a set of bugfix patches: +This version includes the ability to optionally compile with a set of bugfix patches I'm calling Fort Knox Edition: `make BUGFIX=1` From 473c50c41dac62e62c8d0f5706ac2f69398b428f Mon Sep 17 00:00:00 2001 From: TiKevin83 Date: Sat, 30 Dec 2023 13:39:24 -0500 Subject: [PATCH 36/37] commit v1.0 IPS patch --- pokeyellow-bugfix-romhack.ips | Bin 0 -> 124686 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 pokeyellow-bugfix-romhack.ips diff --git a/pokeyellow-bugfix-romhack.ips b/pokeyellow-bugfix-romhack.ips new file mode 100644 index 0000000000000000000000000000000000000000..2baa8ac3c82052f10762fdac96a7b5ae44405387 GIT binary patch literal 124686 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

8<6*oq$ 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 v0ZQIV=yP(2-=qYm()mAK0#bft{xHe^yo>}n+;Y Date: Sun, 4 Aug 2024 23:22:31 -0400 Subject: [PATCH 37/37] Remove broken substitute change identified in test routing --- engine/battle/core.asm | 3 --- 1 file changed, 3 deletions(-) diff --git a/engine/battle/core.asm b/engine/battle/core.asm index fa9ddbc11..91cb6c42c 100644 --- a/engine/battle/core.asm +++ b/engine/battle/core.asm @@ -5648,9 +5648,6 @@ MoveHitTest: jr z, .checkForDigOrFlyStatus ; The fix for Swift broke this code. It's supposed to prevent HP draining moves from working on Substitutes. ; Since CheckTargetSubstitute overwrites a with either $00 or $01, it never works. -IF DEF(_BUGFIX) - ld a, [de] -ENDC cp DRAIN_HP_EFFECT jp z, .moveMissed cp DREAM_EATER_EFFECT