Special Defense badge boost glitch

From Glitch City Wiki
Jump to navigation Jump to search

The Special Defense badge boost glitch is a glitch in Pokémon Gold, Silver and Crystal that causes the Glacier Badge's boost to the Special Defense stat of a Pokémon to not apply if the Special Attack stat of that Pokémon is in certain ranges.

Specifically, if the unboosted Special Attack stat (which may include the Special Attack stage modifier) is either 0 – 205, or 433 – 660, then the glitch will cause the player to lose the Special Defense boost.

After giving the player the Glacier Badge, Pryce mentions that "That BADGE will raise the SPECIAL stats of POKéMON." Presumably, the developer's intention is for the Glacier Badge to boost both the Special Attack and the Special Defence unconditionally. However, the code to apply the Special Defense boost uses register a to determine whether the boost should be applied, but the value in register a is overwritten while applying the Special Attack boost. This results in an unintended extra condition for the boost to apply.

Analysis

The piece of code to apply the badge stat boosts is as follows: (external link)

; The value in register b has been initialized to a bitmask for Johto badges,
; in the following order, starting from the least significant bit:
;   ZEPHYR, HIVE, MINERAL, FOG, PLAIN, STORM, GLACIER, RISING.

; The order of the stats are:
;   Attack, Defense, Speed, SpAtk, SpDef.

	ld hl, wBattleMonAttack
	ld c, 4                 ; The number of times the below loop should execute
.CheckBadge:
	ld a, b                 ; Save the value of b, specifically for use after the loop
	srl b                   ; Shift b to the right, removing the least significant bit
	call c, BoostStat       ; Apply the boost if the bit just removed is 1
	inc hl
	inc hl                  ; Move to the next stat (stats are 2-byte integers)

	srl b                   ; Throw away a bit from b (only check every other badge)
	dec c
	jr nz, .CheckBadge

	srl a                   ; Check Glacier Badge again for Special Defense
	call c, BoostStat
	ret

The last check assumes that the value in register a comes from the ld a, b instruction from the last iteration of the loop. Since the srl b immediately after is a check for the Glacier Badge, the final srl a should be a check for the Glacier Badge, too.

However, this does not take into account that the function BoostStat actually overwrites register a. The code for that function is as follows: (external link)

BoostStat:
; Raise stat at hl by 1/8.

	ld a, [hli]
	ld d, a     ; High byte of the stat
	ld e, [hl]  ; Low byte of the stat
	srl d
	rr e        ; Shift the 16-bit integer de to the right...
	srl d
	rr e        ; ...
	srl d
	rr e        ; ... three times (i.e. divide by 8)
	ld a, [hl]
	add e
	ld [hld], a
	ld a, [hl]
	adc d
	ld [hli], a ; Add de back into the stat at hl

; Cap at 999.
	ld a, [hld]                ; Low byte of boosted stat
	sub LOW(MAX_STAT_VALUE)
	ld a, [hl]                 ; High byte of boosted stat
	sbc HIGH(MAX_STAT_VALUE)
	ret c                      ; If boosted stat is less than 999, return
	ld a, HIGH(MAX_STAT_VALUE)
	ld [hli], a
	ld a, LOW(MAX_STAT_VALUE)
	ld [hld], a                ; Otherwise, set boosted stat to 999
	ret

Here, the value of MAX_STAT_VALUE is 999 = 0x03E7.

There are therefore three cases for the srl a check:

  • If the player does not have the Glacier Badge, then the function BoostStat is not called, and the check works as intended. The Special Defense boost will not be applied.
  • If the player has the Glacier Badge, and the unboosted Special Attack is at least 888, then the boosted Special Attack would be at least 999, and the last few instructions in BoostStat will cap it at 999, setting register a to LOW(MAX_STAT_VALUE) = 0xE7 in the process. The srl a check will see that the least significant bit of 0xE7 is 1, so the Special Defense boost will be applied.
  • If the player has the Glacier Badge, and the unboosted Special Attack is less than 888, then the value left in register a will be the result of sbc HIGH(MAX_STAT_VALUE), i.e. the high byte of (boosted Special Attack - 999). The table below shows the possible values for that high byte:
Unboosted SpAtk Boosted SpAtk Boosted SpAtk - 999 Value left in a SpDef boost?
0 – 205 0 – 230 -999 – -769 (0xFC19 – 0xFCFF) 0xFC No
206 – 432 231 – 486 -768 – -513 (0xFD00 – 0xFDFF) 0xFD Yes
433 – 660 487 – 742 -512 – -257 (0xFE00 – 0xFEFF) 0xFE No
661 – 887 743 – 997 -256 – -2 (0xFF00 – 0xFFFE) 0xFF Yes

In conclusion, this glitch causes an unintended behavior only when the player has the Glacier Badge, and the unboosted Special Attack of the Pokémon in question is either 0 – 205, or 433 – 660. In those cases, the glitch causes the Special Defense boost to not apply.