diff options
| author | luckytyphlosion <alan.rj.huang@gmail.com> | 2015-06-05 17:23:06 -0400 | 
|---|---|---|
| committer | luckytyphlosion <alan.rj.huang@gmail.com> | 2015-06-05 17:23:06 -0400 | 
| commit | 139e117d0717c69ae4c47a8d1a040267ee28d91d (patch) | |
| tree | 103cb36abe028d259066c0a582cf78a01380c21d /engine | |
| parent | 56da1f9b662d0e3db8f8405ffb12060d69d66c86 (diff) | |
Fix EOL to LF to make push requests more doable.
Diffstat (limited to 'engine')
| -rwxr-xr-x | engine/items/items.asm | 5744 | ||||
| -rwxr-xr-x | engine/overworld/map_sprites.asm | 880 | 
2 files changed, 3312 insertions, 3312 deletions
| diff --git a/engine/items/items.asm b/engine/items/items.asm index beb85cde..c6f098dc 100755 --- a/engine/items/items.asm +++ b/engine/items/items.asm @@ -1,2872 +1,2872 @@ -UseItem_: ; d5c7 (3:55c7)
 -	ld a,1
 -	ld [wcd6a],a
 -	ld a,[wcf91]	;contains item_ID
 -	cp a,HM_01
 -	jp nc,ItemUseTMHM
 -	ld hl,ItemUsePtrTable
 -	dec a
 -	add a
 -	ld c,a
 -	ld b,0
 -	add hl,bc
 -	ld a,[hli]
 -	ld h,[hl]
 -	ld l,a
 -	jp [hl]
 -
 -ItemUsePtrTable: ; d5e1 (3:55e1)
 -	dw ItemUseBall       ; MASTER_BALL
 -	dw ItemUseBall       ; ULTRA_BALL
 -	dw ItemUseBall       ; GREAT_BALL
 -	dw ItemUseBall       ; POKE_BALL
 -	dw ItemUseTownMap    ; TOWN_MAP
 -	dw ItemUseBicycle    ; BICYCLE
 -	dw ItemUseSurfboard  ; out-of-battle Surf effect
 -	dw ItemUseBall       ; SAFARI_BALL
 -	dw ItemUsePokedex    ; POKEDEX
 -	dw ItemUseEvoStone   ; MOON_STONE
 -	dw ItemUseMedicine   ; ANTIDOTE
 -	dw ItemUseMedicine   ; BURN_HEAL
 -	dw ItemUseMedicine   ; ICE_HEAL
 -	dw ItemUseMedicine   ; AWAKENING
 -	dw ItemUseMedicine   ; PARLYZ_HEAL
 -	dw ItemUseMedicine   ; FULL_RESTORE
 -	dw ItemUseMedicine   ; MAX_POTION
 -	dw ItemUseMedicine   ; HYPER_POTION
 -	dw ItemUseMedicine   ; SUPER_POTION
 -	dw ItemUseMedicine   ; POTION
 -	dw ItemUseBait       ; BOULDERBADGE
 -	dw ItemUseRock       ; CASCADEBADGE
 -	dw UnusableItem      ; THUNDERBADGE
 -	dw UnusableItem      ; RAINBOWBADGE
 -	dw UnusableItem      ; SOULBADGE
 -	dw UnusableItem      ; MARSHBADGE
 -	dw UnusableItem      ; VOLCANOBADGE
 -	dw UnusableItem      ; EARTHBADGE
 -	dw ItemUseEscapeRope ; ESCAPE_ROPE
 -	dw ItemUseRepel      ; REPEL
 -	dw UnusableItem      ; OLD_AMBER
 -	dw ItemUseEvoStone   ; FIRE_STONE
 -	dw ItemUseEvoStone   ; THUNDER_STONE
 -	dw ItemUseEvoStone   ; WATER_STONE
 -	dw ItemUseVitamin    ; HP_UP
 -	dw ItemUseVitamin    ; PROTEIN
 -	dw ItemUseVitamin    ; IRON
 -	dw ItemUseVitamin    ; CARBOS
 -	dw ItemUseVitamin    ; CALCIUM
 -	dw ItemUseVitamin    ; RARE_CANDY
 -	dw UnusableItem      ; DOME_FOSSIL
 -	dw UnusableItem      ; HELIX_FOSSIL
 -	dw UnusableItem      ; SECRET_KEY
 -	dw UnusableItem
 -	dw UnusableItem      ; BIKE_VOUCHER
 -	dw ItemUseXAccuracy  ; X_ACCURACY
 -	dw ItemUseEvoStone   ; LEAF_STONE
 -	dw ItemUseCardKey    ; CARD_KEY
 -	dw UnusableItem      ; NUGGET
 -	dw UnusableItem      ; ??? PP_UP
 -	dw ItemUsePokedoll   ; POKE_DOLL
 -	dw ItemUseMedicine   ; FULL_HEAL
 -	dw ItemUseMedicine   ; REVIVE
 -	dw ItemUseMedicine   ; MAX_REVIVE
 -	dw ItemUseGuardSpec  ; GUARD_SPEC_
 -	dw ItemUseSuperRepel ; SUPER_REPL
 -	dw ItemUseMaxRepel   ; MAX_REPEL
 -	dw ItemUseDireHit    ; DIRE_HIT
 -	dw UnusableItem      ; COIN
 -	dw ItemUseMedicine   ; FRESH_WATER
 -	dw ItemUseMedicine   ; SODA_POP
 -	dw ItemUseMedicine   ; LEMONADE
 -	dw UnusableItem      ; S_S__TICKET
 -	dw UnusableItem      ; GOLD_TEETH
 -	dw ItemUseXStat      ; X_ATTACK
 -	dw ItemUseXStat      ; X_DEFEND
 -	dw ItemUseXStat      ; X_SPEED
 -	dw ItemUseXStat      ; X_SPECIAL
 -	dw ItemUseCoinCase   ; COIN_CASE
 -	dw ItemUseOaksParcel ; OAKS_PARCEL
 -	dw ItemUseItemfinder ; ITEMFINDER
 -	dw UnusableItem      ; SILPH_SCOPE
 -	dw ItemUsePokeflute  ; POKE_FLUTE
 -	dw UnusableItem      ; LIFT_KEY
 -	dw UnusableItem      ; EXP__ALL
 -	dw OldRodCode        ; OLD_ROD
 -	dw GoodRodCode       ; GOOD_ROD
 -	dw SuperRodCode      ; SUPER_ROD
 -	dw ItemUsePPUp       ; PP_UP (real one)
 -	dw ItemUsePPRestore  ; ETHER
 -	dw ItemUsePPRestore  ; MAX_ETHER
 -	dw ItemUsePPRestore  ; ELIXER
 -	dw ItemUsePPRestore  ; MAX_ELIXER
 -
 -ItemUseBall: ; d687 (3:5687)
 -	ld a,[W_ISINBATTLE]
 -	and a
 -	jp z,ItemUseNotTime ; not in battle
 -	dec a
 -	jp nz,ThrowBallAtTrainerMon
 -	ld a,[W_BATTLETYPE]
 -	dec a
 -	jr z,.UseBall
 -	ld a,[wPartyCount]	;is Party full?
 -	cp a,PARTY_LENGTH
 -	jr nz,.UseBall
 -	ld a,[W_NUMINBOX]	;is Box full?
 -	cp a,MONS_PER_BOX
 -	jp z,BoxFullCannotThrowBall
 -.UseBall	;$56a7
 -;ok, you can use a ball
 -	xor a
 -	ld [wd11c],a
 -	ld a,[W_BATTLETYPE]
 -	cp a,2		;SafariBattle
 -	jr nz,.skipSafariZoneCode
 -.safariZone
 -	; remove a Safari Ball from inventory
 -	ld hl,W_NUMSAFARIBALLS
 -	dec [hl]
 -.skipSafariZoneCode	;$56b6
 -	call GoPAL_SET_CF1C
 -	ld a,$43
 -	ld [wd11e],a
 -	call LoadScreenTilesFromBuffer1	;restore screenBuffer from Backup
 -	ld hl,ItemUseText00
 -	call PrintText
 -	callab IsGhostBattle
 -	ld b,$10
 -	jp z,.next12
 -	ld a,[W_BATTLETYPE]
 -	dec a
 -	jr nz,.notOldManBattle
 -.oldManBattle
 -	ld hl,W_GRASSRATE
 -	ld de,wPlayerName
 -	ld bc,11
 -	call CopyData ; save the player's name in the Wild Monster data (part of the Cinnabar Island Missingno glitch)
 -	jp .BallSuccess	;$578b
 -.notOldManBattle	;$56e9
 -	ld a,[W_CURMAP]
 -	cp a,POKEMONTOWER_6
 -	jr nz,.loop
 -	ld a,[wEnemyMonSpecies2]
 -	cp a,MAROWAK
 -	ld b,$10
 -	jp z,.next12
 -; if not fighting ghost Marowak, loop until a random number in the current
 -; pokeball's allowed range is found
 -.loop	;$56fa
 -	call Random
 -	ld b,a
 -	ld hl,wcf91
 -	ld a,[hl]
 -	cp a,MASTER_BALL
 -	jp z,.BallSuccess	;$578b
 -	cp a,POKE_BALL
 -	jr z,.checkForAilments
 -	ld a,200
 -	cp b
 -	jr c,.loop	;get only numbers <= 200 for Great Ball
 -	ld a,[hl]
 -	cp a,GREAT_BALL
 -	jr z,.checkForAilments
 -	ld a,150	;get only numbers <= 150 for Ultra Ball
 -	cp b
 -	jr c,.loop
 -.checkForAilments	;$571a
 -; pokemon can be caught more easily with any (primary) status ailment
 -; Frozen/Asleep pokemon are relatively even easier to catch
 -; for Frozen/Asleep pokemon, any random number from 0-24 ensures a catch.
 -; for the others, a random number from 0-11 ensures a catch.
 -	ld a,[wEnemyMonStatus]	;status ailments
 -	and a
 -	jr z,.noAilments
 -	and a, 1 << FRZ | SLP	;is frozen and/or asleep?
 -	ld c,12
 -	jr z,.notFrozenOrAsleep
 -	ld c,25
 -.notFrozenOrAsleep	;$5728
 -	ld a,b
 -	sub c
 -	jp c,.BallSuccess	;$578b
 -	ld b,a
 -.noAilments	;$572e
 -	push bc		;save RANDOM number
 -	xor a
 -	ld [H_MULTIPLICAND],a
 -	ld hl,wEnemyMonMaxHP
 -	ld a,[hli]
 -	ld [H_MULTIPLICAND + 1],a
 -	ld a,[hl]
 -	ld [H_MULTIPLICAND + 2],a
 -	ld a,255
 -	ld [H_MULTIPLIER],a
 -	call Multiply	; MaxHP * 255
 -	ld a,[wcf91]
 -	cp a,GREAT_BALL
 -	ld a,12		;any other BallFactor
 -	jr nz,.next7
 -	ld a,8
 -.next7	;$574d
 -	ld [H_DIVISOR],a
 -	ld b,4		; number of bytes in dividend
 -	call Divide
 -	ld hl,wEnemyMonHP
 -	ld a,[hli]
 -	ld b,a
 -	ld a,[hl]
 -
 -; explanation: we have a 16-bit value equal to [b << 8 | a].
 -; This number is divided by 4. The result is 8 bit (reg. a).
 -; Always bigger than zero.
 -	srl b
 -	rr a
 -	srl b
 -	rr a ; a = current HP / 4
 -	and a
 -	jr nz,.next8
 -	inc a
 -.next8	;$5766
 -	ld [H_DIVISOR],a
 -	ld b,4
 -	call Divide	; ((MaxHP * 255) / BallFactor) / (CurHP / 4)
 -	ld a,[H_QUOTIENT + 2]
 -	and a
 -	jr z,.next9
 -	ld a,255
 -	ld [H_QUOTIENT + 3],a
 -.next9	;$5776
 -	pop bc
 -	ld a,[wEnemyMonCatchRate]	;enemy: Catch Rate
 -	cp b
 -	jr c,.next10
 -	ld a,[H_QUOTIENT + 2]
 -	and a
 -	jr nz,.BallSuccess ; if ((MaxHP * 255) / BallFactor) / (CurHP / 4) > 0x255, automatic success
 -	call Random
 -	ld b,a
 -	ld a,[H_QUOTIENT + 3]
 -	cp b
 -	jr c,.next10
 -.BallSuccess	;$578b
 -	jr .BallSuccess2
 -.next10	;$578d
 -	ld a,[H_QUOTIENT + 3]
 -	ld [wd11e],a
 -	xor a
 -	ld [H_MULTIPLICAND],a
 -	ld [H_MULTIPLICAND + 1],a
 -	ld a,[wEnemyMonCatchRate]	;enemy: Catch Rate
 -	ld [H_MULTIPLICAND + 2],a
 -	ld a,100
 -	ld [H_MULTIPLIER],a
 -	call Multiply	; CatchRate * 100
 -	ld a,[wcf91]
 -	ld b,255
 -	cp a,POKE_BALL
 -	jr z,.next11
 -	ld b,200
 -	cp a,GREAT_BALL
 -	jr z,.next11
 -	ld b,150
 -	cp a,ULTRA_BALL
 -	jr z,.next11
 -.next11	;$57b8
 -	ld a,b
 -	ld [H_DIVISOR],a
 -	ld b,4
 -	call Divide
 -	ld a,[H_QUOTIENT + 2]
 -	and a
 -	ld b,$63
 -	jr nz,.next12
 -	ld a,[wd11e]
 -	ld [H_MULTIPLIER],a
 -	call Multiply
 -	ld a,255
 -	ld [H_DIVISOR],a
 -	ld b,4
 -	call Divide
 -	ld a,[wEnemyMonStatus]	;status ailments
 -	and a
 -	jr z,.next13
 -	and a, 1 << FRZ | SLP
 -	ld b,5
 -	jr z,.next14
 -	ld b,10
 -.next14	;$57e6
 -	ld a,[H_QUOTIENT + 3]
 -	add b
 -	ld [H_QUOTIENT + 3],a
 -.next13	;$57eb
 -	ld a,[H_QUOTIENT + 3]
 -	cp a,10
 -	ld b,$20
 -	jr c,.next12
 -	cp a,30
 -	ld b,$61
 -	jr c,.next12
 -	cp a,70
 -	ld b,$62
 -	jr c,.next12
 -	ld b,$63
 -.next12	;$5801
 -	ld a,b
 -	ld [wd11e],a
 -.BallSuccess2	;$5805
 -	ld c,20
 -	call DelayFrames
 -	ld a,TOSS_ANIM
 -	ld [W_ANIMATIONID],a
 -	xor a
 -	ld [$fff3],a
 -	ld [wAnimationType],a
 -	ld [wDamageMultipliers],a
 -	ld a,[wWhichPokemon]
 -	push af
 -	ld a,[wcf91]
 -	push af
 -	predef MoveAnimation
 -	pop af
 -	ld [wcf91],a
 -	pop af
 -	ld [wWhichPokemon],a
 -	ld a,[wd11e]
 -	cp a,$10
 -	ld hl,ItemUseBallText00
 -	jp z,.printText0
 -	cp a,$20
 -	ld hl,ItemUseBallText01
 -	jp z,.printText0
 -	cp a,$61
 -	ld hl,ItemUseBallText02
 -	jp z,.printText0
 -	cp a,$62
 -	ld hl,ItemUseBallText03
 -	jp z,.printText0
 -	cp a,$63
 -	ld hl,ItemUseBallText04
 -	jp z,.printText0
 -	ld hl,wEnemyMonHP	;current HP
 -	ld a,[hli]
 -	push af
 -	ld a,[hli]
 -	push af		;backup currentHP...
 -	inc hl
 -	ld a,[hl]
 -	push af		;...and status ailments
 -	push hl
 -	ld hl,W_ENEMYBATTSTATUS3
 -	bit Transformed,[hl]
 -	jr z,.next15
 -	ld a,$4c
 -	ld [wEnemyMonSpecies2],a
 -	jr .next16
 -.next15	;$5871
 -	set Transformed,[hl]
 -	ld hl,wcceb
 -	ld a,[wEnemyMonDVs]
 -	ld [hli],a
 -	ld a,[wEnemyMonDVs + 1]
 -	ld [hl],a
 -.next16	;$587e
 -	ld a,[wcf91]
 -	push af
 -	ld a,[wEnemyMonSpecies2]
 -	ld [wcf91],a
 -	ld a,[wEnemyMonLevel]
 -	ld [W_CURENEMYLVL],a
 -	callab LoadEnemyMonData
 -	pop af
 -	ld [wcf91],a
 -	pop hl
 -	pop af
 -	ld [hld],a
 -	dec hl
 -	pop af
 -	ld [hld],a
 -	pop af
 -	ld [hl],a
 -	ld a,[wEnemyMonSpecies]	;enemy
 -	ld [wd11c],a
 -	ld [wcf91],a
 -	ld [wd11e],a
 -	ld a,[W_BATTLETYPE]
 -	dec a
 -	jr z,.printText1
 -	ld hl,ItemUseBallText05
 -	call PrintText
 -	predef IndexToPokedex
 -	ld a,[wd11e]
 -	dec a
 -	ld c,a
 -	ld b,2
 -	ld hl,wPokedexOwned	;Dex_own_flags (pokemon)
 -	predef FlagActionPredef
 -	ld a,c
 -	push af
 -	ld a,[wd11e]
 -	dec a
 -	ld c,a
 -	ld b,1
 -	predef FlagActionPredef
 -	pop af
 -	and a
 -	jr nz,.checkParty
 -	ld hl,ItemUseBallText06
 -	call PrintText
 -	call ClearSprites
 -	ld a,[wEnemyMonSpecies]	;caught mon_ID
 -	ld [wd11e],a
 -	predef ShowPokedexData
 -.checkParty	;$58f4
 -	ld a,[wPartyCount]
 -	cp a,PARTY_LENGTH		;is party full?
 -	jr z,.sendToBox
 -	xor a
 -	ld [wcc49],a
 -	call ClearSprites
 -	call AddPartyMon	;add mon to Party
 -	jr .End
 -.sendToBox	;$5907
 -	call ClearSprites
 -	call SendNewMonToBox
 -	ld hl,ItemUseBallText07
 -	ld a,[wd7f1]
 -	bit 0,a		;already met Bill?
 -	jr nz,.sendToBox2
 -	ld hl,ItemUseBallText08
 -.sendToBox2	;$591a
 -	call PrintText
 -	jr .End
 -.printText1	;$591f
 -	ld hl,ItemUseBallText05
 -.printText0	;$5922
 -	call PrintText
 -	call ClearSprites
 -.End	;$5928
 -	ld a,[W_BATTLETYPE]
 -	and a
 -	ret nz
 -	ld hl,wNumBagItems
 -	inc a
 -	ld [wcf96],a
 -	jp RemoveItemFromInventory	;remove ITEM (XXX)
 -ItemUseBallText00: ; d937 (3:5937)
 -;"It dodged the thrown ball!"
 -;"This pokemon can't be caught"
 -	TX_FAR _ItemUseBallText00
 -	db "@"
 -ItemUseBallText01: ; d93c (3:593c)
 -;"You missed the pokemon!"
 -	TX_FAR _ItemUseBallText01
 -	db "@"
 -ItemUseBallText02: ; d941 (3:5941)
 -;"Darn! The pokemon broke free!"
 -	TX_FAR _ItemUseBallText02
 -	db "@"
 -ItemUseBallText03: ; d946 (3:5946)
 -;"Aww! It appeared to be caught!"
 -	TX_FAR _ItemUseBallText03
 -	db "@"
 -ItemUseBallText04: ; d94b (3:594b)
 -;"Shoot! It was so close too!"
 -	TX_FAR _ItemUseBallText04
 -	db "@"
 -ItemUseBallText05: ; d950 (3:5950)
 -;"All right! {MonName} was caught!"
 -;play sound
 -	TX_FAR _ItemUseBallText05
 -	db $12,$06
 -	db "@"
 -ItemUseBallText07: ; d957 (3:5957)
 -;"X was transferred to Bill's PC"
 -	TX_FAR _ItemUseBallText07
 -	db "@"
 -ItemUseBallText08: ; d95c (3:595c)
 -;"X was transferred to someone's PC"
 -	TX_FAR _ItemUseBallText08
 -	db "@"
 -
 -ItemUseBallText06: ; d961 (3:5961)
 -;"New DEX data will be added..."
 -;play sound
 -	TX_FAR _ItemUseBallText06
 -	db $13,$06
 -	db "@"
 -
 -ItemUseTownMap: ; d968 (3:5968)
 -	ld a,[W_ISINBATTLE]
 -	and a
 -	jp nz,ItemUseNotTime
 -	ld b, BANK(DisplayTownMap)
 -	ld hl, DisplayTownMap
 -	jp Bankswitch ; display Town Map
 -
 -ItemUseBicycle: ; d977 (3:5977)
 -	ld a,[W_ISINBATTLE]
 -	and a
 -	jp nz,ItemUseNotTime
 -	ld a,[wWalkBikeSurfState]
 -	ld [wWalkBikeSurfStateCopy],a
 -	cp a,2 ; is the player surfing?
 -	jp z,ItemUseNotTime
 -	dec a ; is player already bicycling?
 -	jr nz,.tryToGetOnBike
 -.getOffBike
 -	call ItemUseReloadOverworldData
 -	xor a
 -	ld [wWalkBikeSurfState],a ; change player state to walking
 -	call PlayDefaultMusic ; play walking music
 -	ld hl,GotOffBicycleText
 -	jr .printText
 -.tryToGetOnBike
 -	call IsBikeRidingAllowed
 -	jp nc,NoCyclingAllowedHere
 -	call ItemUseReloadOverworldData
 -	xor a ; no keys pressed
 -	ld [hJoyHeld],a ; current joypad state
 -	inc a
 -	ld [wWalkBikeSurfState],a ; change player state to bicycling
 -	ld hl,GotOnBicycleText
 -	call PlayDefaultMusic ; play bike riding music
 -.printText
 -	jp PrintText
 -
 -; used for Surf out-of-battle effect
 -ItemUseSurfboard: ; d9b4 (3:59b4)
 -	ld a,[wWalkBikeSurfState]
 -	ld [wWalkBikeSurfStateCopy],a
 -	cp a,2 ; is the player already surfing?
 -	jr z,.tryToStopSurfing
 -.tryToSurf
 -	call IsNextTileShoreOrWater
 -	jp c,SurfingAttemptFailed
 -	ld hl,TilePairCollisionsWater
 -	call CheckForTilePairCollisions
 -	jp c,SurfingAttemptFailed
 -.surf
 -	call .makePlayerMoveForward
 -	ld hl,wd730
 -	set 7,[hl]
 -	ld a,2
 -	ld [wWalkBikeSurfState],a ; change player state to surfing
 -	call PlayDefaultMusic ; play surfing music
 -	ld hl,SurfingGotOnText
 -	jp PrintText
 -.tryToStopSurfing
 -	xor a
 -	ld [$ff8c],a
 -	ld d,16 ; talking range in pixels (normal range)
 -	call IsSpriteInFrontOfPlayer2
 -	res 7,[hl]
 -	ld a,[$ff8c]
 -	and a ; is there a sprite in the way?
 -	jr nz,.cannotStopSurfing
 -	ld hl,TilePairCollisionsWater
 -	call CheckForTilePairCollisions
 -	jr c,.cannotStopSurfing
 -	ld hl,W_TILESETCOLLISIONPTR ; pointer to list of passable tiles
 -	ld a,[hli]
 -	ld h,[hl]
 -	ld l,a ; hl now points to passable tiles
 -	ld a,[wTileInFrontOfPlayer] ; tile in front of the player
 -	ld b,a
 -.passableTileLoop
 -	ld a,[hli]
 -	cp b
 -	jr z,.stopSurfing
 -	cp a,$ff
 -	jr nz,.passableTileLoop
 -.cannotStopSurfing
 -	ld hl,SurfingNoPlaceToGetOffText
 -	jp PrintText
 -.stopSurfing
 -	call .makePlayerMoveForward
 -	ld hl,wd730
 -	set 7,[hl]
 -	xor a
 -	ld [wWalkBikeSurfState],a ; change player state to walking
 -	dec a
 -	ld [wJoyIgnore],a
 -	call PlayDefaultMusic ; play walking music
 -	jp LoadWalkingPlayerSpriteGraphics
 -; uses a simulated button press to make the player move forward
 -.makePlayerMoveForward
 -	ld a,[wd52a] ; direction the player is going
 -	bit 3,a
 -	ld b,D_UP
 -	jr nz,.storeSimulatedButtonPress
 -	bit 2,a
 -	ld b,D_DOWN
 -	jr nz,.storeSimulatedButtonPress
 -	bit 1,a
 -	ld b,D_LEFT
 -	jr nz,.storeSimulatedButtonPress
 -	ld b,D_RIGHT
 -.storeSimulatedButtonPress
 -	ld a,b
 -	ld [wSimulatedJoypadStatesEnd],a
 -	xor a
 -	ld [wWastedByteCD39],a
 -	inc a
 -	ld [wSimulatedJoypadStatesIndex],a
 -	ret
 -
 -SurfingGotOnText: ; da4c (3:5a4c)
 -	TX_FAR _SurfingGotOnText
 -	db "@"
 -
 -SurfingNoPlaceToGetOffText: ; da51 (3:5a51)
 -	TX_FAR _SurfingNoPlaceToGetOffText
 -	db "@"
 -
 -ItemUsePokedex: ; da56 (3:5a56)
 -	predef_jump ShowPokedexMenu
 -
 -ItemUseEvoStone: ; da5b (3:5a5b)
 -	ld a,[W_ISINBATTLE]
 -	and a
 -	jp nz,ItemUseNotTime
 -	ld a,[wWhichPokemon]
 -	push af
 -	ld a,[wcf91]
 -	ld [wd156],a
 -	push af
 -	ld a,$05 ; evolution stone party menu
 -	ld [wd07d],a
 -	ld a,$ff
 -	ld [wUpdateSpritesEnabled],a
 -	call DisplayPartyMenu
 -	pop bc
 -	jr c,.canceledItemUse
 -	ld a,b
 -	ld [wcf91],a
 -	ld a,$01
 -	ld [wccd4],a
 -	ld a,(SFX_02_3e - SFX_Headers_02) / 3
 -	call PlaySoundWaitForCurrent ; play sound
 -	call WaitForSoundToFinish ; wait for sound to end
 -	callab TryEvolvingMon ; try to evolve pokemon
 -	ld a,[wd121]
 -	and a
 -	jr z,.noEffect
 -	pop af
 -	ld [wWhichPokemon],a
 -	ld hl,wNumBagItems
 -	ld a,1 ; remove 1 stone
 -	ld [wcf96],a
 -	jp RemoveItemFromInventory
 -.noEffect
 -	call ItemUseNoEffect
 -.canceledItemUse
 -	xor a
 -	ld [wcd6a],a
 -	pop af
 -	ret
 -
 -ItemUseVitamin: ; dab4 (3:5ab4)
 -	ld a,[W_ISINBATTLE]
 -	and a
 -	jp nz,ItemUseNotTime
 -
 -ItemUseMedicine: ; dabb (3:5abb)
 -	ld a,[wPartyCount]
 -	and a
 -	jp z,.emptyParty
 -	ld a,[wWhichPokemon]
 -	push af
 -	ld a,[wcf91]
 -	push af
 -	ld a,$01
 -	ld [wd07d],a ; item use party menu
 -	ld a,$ff
 -	ld [wUpdateSpritesEnabled],a
 -	ld a,[wd152]
 -	and a ; using Softboiled?
 -	jr z,.notUsingSoftboiled
 -; if using softboiled
 -	call GoBackToPartyMenu
 -	jr .getPartyMonDataAddress
 -.emptyParty
 -	ld hl,.emptyPartyText
 -	xor a
 -	ld [wcd6a],a ; item use failed
 -	jp PrintText
 -.emptyPartyText
 -	text "You don't have"
 -	line "any #MON!"
 -	prompt
 -.notUsingSoftboiled
 -	call DisplayPartyMenu
 -.getPartyMonDataAddress
 -	jp c,.canceledItemUse
 -	ld hl,wPartyMons
 -	ld bc,wPartyMon2 - wPartyMon1
 -	ld a,[wWhichPokemon]
 -	call AddNTimes
 -	ld a,[wWhichPokemon]
 -	ld [wcf06],a
 -	ld d,a
 -	ld a,[wcf91]
 -	ld e,a
 -	ld [wd0b5],a
 -	pop af
 -	ld [wcf91],a
 -	pop af
 -	ld [wWhichPokemon],a
 -	ld a,[wd152]
 -	and a ; using Softboiled?
 -	jr z,.checkItemType
 -; if using softboiled
 -	ld a,[wWhichPokemon]
 -	cp d ; is the pokemon trying to use softboiled on itself?
 -	jr z,ItemUseMedicine ; if so, force another choice
 -.checkItemType
 -	ld a,[wcf91]
 -	cp a,REVIVE
 -	jr nc,.healHP ; if it's a Revive or Max Revive
 -	cp a,FULL_HEAL
 -	jr z,.cureStatusAilment ; if it's a Full Heal
 -	cp a,HP_UP
 -	jp nc,.useVitamin ; if it's a vitamin or Rare Candy
 -	cp a,FULL_RESTORE
 -	jr nc,.healHP ; if it's a Full Restore or one of the potions
 -; fall through if it's one of the status-specifc healing items
 -.cureStatusAilment
 -	ld bc,4
 -	add hl,bc ; hl now points to status
 -	ld a,[wcf91]
 -	ld bc,$f008
 -	cp a,ANTIDOTE
 -	jr z,.checkMonStatus
 -	ld bc,$f110
 -	cp a,BURN_HEAL
 -	jr z,.checkMonStatus
 -	ld bc,$f220
 -	cp a,ICE_HEAL
 -	jr z,.checkMonStatus
 -	ld bc,$f307
 -	cp a,AWAKENING
 -	jr z,.checkMonStatus
 -	ld bc,$f440
 -	cp a,PARLYZ_HEAL
 -	jr z,.checkMonStatus
 -	ld bc,$f6ff ; Full Heal
 -.checkMonStatus
 -	ld a,[hl] ; pokemon's status
 -	and c ; does the pokemon have a status ailment the item can cure?
 -	jp z,.healingItemNoEffect
 -; if the pokemon has a status the item can heal
 -	xor a
 -	ld [hl],a ; remove the status ailment in the party data
 -	ld a,b
 -	ld [wd07d],a ; the message to display for the item used
 -	ld a,[wPlayerMonNumber]
 -	cp d ; is pokemon the item was used on active in battle?
 -	jp nz,.doneHealing
 -; if it is active in battle
 -	xor a
 -	ld [wBattleMonStatus],a ; remove the status ailment in the in-battle pokemon data
 -	push hl
 -	ld hl,W_PLAYERBATTSTATUS3
 -	res BadlyPoisoned,[hl] ; heal Toxic status
 -	pop hl
 -	ld bc,30
 -	add hl,bc ; hl now points to party stats
 -	ld de,wBattleMonMaxHP
 -	ld bc,10
 -	call CopyData ; copy party stats to in-battle stat data
 -	predef DoubleOrHalveSelectedStats
 -	jp .doneHealing
 -.healHP
 -	inc hl ; hl = address of current HP
 -	ld a,[hli]
 -	ld b,a
 -	ld [wHPBarOldHP+1],a
 -	ld a,[hl]
 -	ld c,a
 -	ld [wHPBarOldHP],a ; current HP stored at wHPBarOldHP (2 bytes, big-endian)
 -	or b
 -	jr nz,.notFainted
 -.fainted
 -	ld a,[wcf91]
 -	cp a,REVIVE
 -	jr z,.updateInBattleFaintedData
 -	cp a,MAX_REVIVE
 -	jr z,.updateInBattleFaintedData
 -	jp .healingItemNoEffect
 -.updateInBattleFaintedData
 -	ld a,[W_ISINBATTLE]
 -	and a
 -	jr z,.compareCurrentHPToMaxHP
 -	push hl
 -	push de
 -	push bc
 -	ld a,[wcf06]
 -	ld c,a
 -	ld hl,wPartyFoughtCurrentEnemyFlags
 -	ld b,$02
 -	predef FlagActionPredef
 -	ld a,c
 -	and a
 -	jr z,.next
 -	ld a,[wcf06]
 -	ld c,a
 -	ld hl,wPartyGainExpFlags
 -	ld b,$01
 -	predef FlagActionPredef
 -.next
 -	pop bc
 -	pop de
 -	pop hl
 -	jr .compareCurrentHPToMaxHP
 -.notFainted
 -	ld a,[wcf91]
 -	cp a,REVIVE
 -	jp z,.healingItemNoEffect
 -	cp a,MAX_REVIVE
 -	jp z,.healingItemNoEffect
 -.compareCurrentHPToMaxHP
 -	push hl
 -	push bc
 -	ld bc,32
 -	add hl,bc ; hl now points to max HP
 -	pop bc
 -	ld a,[hli]
 -	cp b
 -	jr nz,.skipComparingLSB ; no need to compare the LSB's if the MSB's don't match
 -	ld a,[hl]
 -	cp c
 -.skipComparingLSB
 -	pop hl
 -	jr nz,.notFullHP
 -.fullHP ; if the pokemon's current HP equals its max HP
 -	ld a,[wcf91]
 -	cp a,FULL_RESTORE
 -	jp nz,.healingItemNoEffect
 -	inc hl
 -	inc hl
 -	ld a,[hld] ; status ailment
 -	and a ; does the pokemon have a status ailment?
 -	jp z,.healingItemNoEffect
 -	ld a,FULL_HEAL
 -	ld [wcf91],a
 -	dec hl
 -	dec hl
 -	dec hl
 -	jp .cureStatusAilment
 -.notFullHP ; if the pokemon's current HP doesn't equal its max HP
 -	xor a
 -	ld [wLowHealthAlarm],a ;disable low health alarm
 -	ld [wc02a],a
 -	push hl
 -	push de
 -	ld bc,32
 -	add hl,bc ; hl now points to max HP
 -	ld a,[hli]
 -	ld [wHPBarMaxHP+1],a
 -	ld a,[hl]
 -	ld [wHPBarMaxHP],a ; max HP stored at wHPBarMaxHP (2 bytes, big-endian)
 -	ld a,[wd152]
 -	and a ; using Softboiled?
 -	jp z,.notUsingSoftboiled2
 -; if using softboiled
 -	ld hl,wHPBarMaxHP
 -	ld a,[hli]
 -	push af
 -	ld a,[hli]
 -	push af
 -	ld a,[hli]
 -	push af
 -	ld a,[hl]
 -	push af
 -	ld hl,wPartyMon1MaxHP
 -	ld a,[wWhichPokemon]
 -	ld bc,wPartyMon2 - wPartyMon1
 -	call AddNTimes
 -	ld a,[hli]
 -	ld [wHPBarMaxHP + 1],a
 -	ld [H_DIVIDEND],a
 -	ld a,[hl]
 -	ld [wHPBarMaxHP],a
 -	ld [H_DIVIDEND + 1],a
 -	ld a,5
 -	ld [H_DIVISOR],a
 -	ld b,2 ; number of bytes
 -	call Divide ; get 1/5 of max HP of pokemon that used Softboiled
 -	ld bc,wPartyMon1HP - wPartyMon1MaxHP
 -	add hl,bc ; hl now points to LSB of current HP of pokemon that used Softboiled
 -; subtract 1/5 of max HP from current HP of pokemon that used Softboiled
 -	ld a,[H_QUOTIENT + 3]
 -	push af
 -	ld b,a
 -	ld a,[hl]
 -	ld [wHPBarOldHP],a
 -	sub b
 -	ld [hld],a
 -	ld [wHPBarNewHP],a
 -	ld a,[H_QUOTIENT + 2]
 -	ld b,a
 -	ld a,[hl]
 -	ld [wHPBarOldHP+1],a
 -	sbc b
 -	ld [hl],a
 -	ld [wHPBarNewHP+1],a
 -	hlCoord 4, 1
 -	ld a,[wWhichPokemon]
 -	ld bc,2 * 20
 -	call AddNTimes ; calculate coordinates of HP bar of pokemon that used Softboiled
 -	ld a,(SFX_02_3d - SFX_Headers_02) / 3
 -	call PlaySoundWaitForCurrent ; play sound
 -	ld a,[hFlags_0xFFF6]
 -	set 0,a
 -	ld [hFlags_0xFFF6],a
 -	ld a,$02
 -	ld [wHPBarType],a
 -	predef UpdateHPBar2 ; animate HP bar decrease of pokemon that used Softboiled
 -	ld a,[hFlags_0xFFF6]
 -	res 0,a
 -	ld [hFlags_0xFFF6],a
 -	pop af
 -	ld b,a ; store heal amount (1/5 of max HP)
 -	ld hl,wHPBarOldHP + 1
 -	pop af
 -	ld [hld],a
 -	pop af
 -	ld [hld],a
 -	pop af
 -	ld [hld],a
 -	pop af
 -	ld [hl],a
 -	jr .addHealAmount
 -.notUsingSoftboiled2
 -	ld a,[wcf91]
 -	cp a,SODA_POP
 -	ld b,60 ; Soda Pop heal amount
 -	jr z,.addHealAmount
 -	ld b,80 ; Lemonade heal amount
 -	jr nc,.addHealAmount
 -	cp a,FRESH_WATER
 -	ld b,50 ; Fresh Water heal amount
 -	jr z,.addHealAmount
 -	cp a,SUPER_POTION
 -	ld b,200 ; Hyper Potion heal amount
 -	jr c,.addHealAmount
 -	ld b,50 ; Super Potion heal amount
 -	jr z,.addHealAmount
 -	ld b,20 ; Potion heal amount
 -.addHealAmount
 -	pop de
 -	pop hl
 -	ld a,[hl]
 -	add b
 -	ld [hld],a
 -	ld [wHPBarNewHP],a
 -	ld a,[hl]
 -	ld [wHPBarNewHP+1],a
 -	jr nc,.noCarry
 -	inc [hl]
 -	ld a,[hl]
 -	ld [wHPBarNewHP + 1],a
 -.noCarry
 -	push de
 -	inc hl
 -	ld d,h
 -	ld e,l ; de now points to current HP
 -	ld hl,33
 -	add hl,de ; hl now points to max HP
 -	ld a,[wcf91]
 -	cp a,REVIVE
 -	jr z,.setCurrentHPToHalfMaxHP
 -	ld a,[hld]
 -	ld b,a
 -	ld a,[de]
 -	sub b
 -	dec de
 -	ld b,[hl]
 -	ld a,[de]
 -	sbc b
 -	jr nc,.setCurrentHPToMaxHp ; if current HP exceeds max HP after healing
 -	ld a,[wcf91]
 -	cp a,HYPER_POTION
 -	jr c,.setCurrentHPToMaxHp ; if using a Full Restore or Max Potion
 -	cp a,MAX_REVIVE
 -	jr z,.setCurrentHPToMaxHp ; if using a Max Revive
 -	jr .updateInBattleData
 -.setCurrentHPToHalfMaxHP
 -	dec hl
 -	dec de
 -	ld a,[hli]
 -	srl a
 -	ld [de],a
 -	ld [wHPBarNewHP+1],a
 -	ld a,[hl]
 -	rr a
 -	inc de
 -	ld [de],a
 -	ld [wHPBarNewHP],a
 -	dec de
 -	jr .doneHealingPartyHP
 -.setCurrentHPToMaxHp
 -	ld a,[hli]
 -	ld [de],a
 -	ld [wHPBarNewHP+1],a
 -	inc de
 -	ld a,[hl]
 -	ld [de],a
 -	ld [wHPBarNewHP],a
 -	dec de
 -.doneHealingPartyHP ; done updating the pokemon's current HP in the party data structure
 -	ld a,[wcf91]
 -	cp a,FULL_RESTORE
 -	jr nz,.updateInBattleData
 -	ld bc,-31
 -	add hl,bc
 -	xor a
 -	ld [hl],a ; remove the status ailment in the party data
 -.updateInBattleData
 -	ld h,d
 -	ld l,e
 -	pop de
 -	ld a,[wPlayerMonNumber]
 -	cp d ; is pokemon the item was used on active in battle?
 -	jr nz,.calculateHPBarCoords
 -; copy party HP to in-battle HP
 -	ld a,[hli]
 -	ld [wBattleMonHP],a
 -	ld a,[hld]
 -	ld [wBattleMonHP + 1],a
 -	ld a,[wcf91]
 -	cp a,FULL_RESTORE
 -	jr nz,.calculateHPBarCoords
 -	xor a
 -	ld [wBattleMonStatus],a ; remove the status ailment in the in-battle pokemon data
 -.calculateHPBarCoords
 -	ld hl,wOAMBuffer + $90
 -	ld bc,2 * 20
 -	inc d
 -.calculateHPBarCoordsLoop
 -	add hl,bc
 -	dec d
 -	jr nz,.calculateHPBarCoordsLoop
 -	jr .doneHealing
 -.healingItemNoEffect
 -	call ItemUseNoEffect
 -	jp .done
 -.doneHealing
 -	ld a,[wd152]
 -	and a ; using Softboiled?
 -	jr nz,.skipRemovingItem ; no item to remove if using Softboiled
 -	push hl
 -	call RemoveUsedItem
 -	pop hl
 -.skipRemovingItem
 -	ld a,[wcf91]
 -	cp a,FULL_RESTORE
 -	jr c,.playStatusAilmentCuringSound
 -	cp a,FULL_HEAL
 -	jr z,.playStatusAilmentCuringSound
 -	ld a,(SFX_02_3d - SFX_Headers_02) / 3 ; HP healing sound
 -	call PlaySoundWaitForCurrent ; play sound
 -	ld a,[hFlags_0xFFF6]
 -	set 0,a
 -	ld [hFlags_0xFFF6],a
 -	ld a,$02
 -	ld [wHPBarType],a
 -	predef UpdateHPBar2 ; animate the HP bar lengthening
 -	ld a,[hFlags_0xFFF6]
 -	res 0,a
 -	ld [hFlags_0xFFF6],a
 -	ld a,$f7 ; revived message
 -	ld [wd07d],a
 -	ld a,[wcf91]
 -	cp a,REVIVE
 -	jr z,.showHealingItemMessage
 -	cp a,MAX_REVIVE
 -	jr z,.showHealingItemMessage
 -	ld a,$f5 ; standard HP healed message
 -	ld [wd07d],a
 -	jr .showHealingItemMessage
 -.playStatusAilmentCuringSound
 -	ld a,(SFX_02_3e - SFX_Headers_02) / 3 ; status ailment curing sound
 -	call PlaySoundWaitForCurrent
 -.showHealingItemMessage
 -	xor a
 -	ld [H_AUTOBGTRANSFERENABLED],a
 -	call ClearScreen
 -	dec a
 -	ld [wUpdateSpritesEnabled],a
 -	call RedrawPartyMenu ; redraws the party menu and displays the message
 -	ld a,1
 -	ld [H_AUTOBGTRANSFERENABLED],a
 -	ld c,50
 -	call DelayFrames
 -	call WaitForTextScrollButtonPress
 -	jr .done
 -.canceledItemUse
 -	xor a
 -	ld [wcd6a],a ; item use failed
 -	pop af
 -	pop af
 -.done
 -	ld a,[wd152]
 -	and a ; using Softboiled?
 -	ret nz ; if so, return
 -	call GBPalWhiteOut
 -	call z,GoPAL_SET_CF1C
 -	ld a,[W_ISINBATTLE]
 -	and a
 -	ret nz
 -	jp ReloadMapData
 -.useVitamin
 -	push hl
 -	ld a,[hl]
 -	ld [wd0b5],a
 -	ld [wd11e],a
 -	ld bc,33
 -	add hl,bc ; hl now points to level
 -	ld a,[hl] ; a = level
 -	ld [W_CURENEMYLVL],a ; store level
 -	call GetMonHeader
 -	push de
 -	ld a,d
 -	ld hl,wPartyMonNicks
 -	call GetPartyMonName
 -	pop de
 -	pop hl
 -	ld a,[wcf91]
 -	cp a,RARE_CANDY
 -	jp z,.useRareCandy
 -	push hl
 -	sub a,HP_UP
 -	add a
 -	ld bc,17
 -	add hl,bc
 -	add l
 -	ld l,a
 -	jr nc,.noCarry2
 -	inc h
 -.noCarry2
 -	ld a,10
 -	ld b,a
 -	ld a,[hl] ; a = MSB of stat experience of the appropriate stat
 -	cp a,100 ; is there already at least 25600 (256 * 100) stat experience?
 -	jr nc,.vitaminNoEffect ; if so, vitamins can't add any more
 -	add b ; add 2560 (256 * 10) stat experience
 -	jr nc,.noCarry3 ; a carry should be impossible here, so this will always jump
 -	ld a,255
 -.noCarry3
 -	ld [hl],a
 -	pop hl
 -	call .recalculateStats
 -	ld hl,VitaminText
 -	ld a,[wcf91]
 -	sub a,HP_UP - 1
 -	ld c,a
 -.statNameLoop ; loop to get the address of the name of the stat the vitamin increases
 -	dec c
 -	jr z,.gotStatName
 -.statNameInnerLoop
 -	ld a,[hli]
 -	ld b,a
 -	ld a,$50
 -	cp b
 -	jr nz,.statNameInnerLoop
 -	jr .statNameLoop
 -.gotStatName
 -	ld de,wcf4b
 -	ld bc,10
 -	call CopyData ; copy the stat's name to wcf4b
 -	ld a,(SFX_02_3e - SFX_Headers_02) / 3
 -	call PlaySound ; play sound
 -	ld hl,VitaminStatRoseText
 -	call PrintText
 -	jp RemoveUsedItem
 -.vitaminNoEffect
 -	pop hl
 -	ld hl,VitaminNoEffectText
 -	call PrintText
 -	jp GBPalWhiteOut
 -.recalculateStats
 -	ld bc,34
 -	add hl,bc
 -	ld d,h
 -	ld e,l ; de now points to stats
 -	ld bc,-18
 -	add hl,bc ; hl now points to byte 3 of experience
 -	ld b,1
 -	jp CalcStats ; recalculate stats
 -.useRareCandy
 -	push hl
 -	ld bc,33
 -	add hl,bc ; hl now points to level
 -	ld a,[hl] ; a = level
 -	cp a, MAX_LEVEL
 -	jr z,.vitaminNoEffect ; can't raise level above 100
 -	inc a
 -	ld [hl],a ; store incremented level
 -	ld [W_CURENEMYLVL],a
 -	push hl
 -	push de
 -	ld d,a
 -	callab CalcExperience ; calculate experience for next level and store it at $ff96
 -	pop de
 -	pop hl
 -	ld bc,-19
 -	add hl,bc ; hl now points to experience
 -; update experience to minimum for new level
 -	ld a,[$ff96]
 -	ld [hli],a
 -	ld a,[$ff97]
 -	ld [hli],a
 -	ld a,[$ff98]
 -	ld [hl],a
 -	pop hl
 -	ld a,[wWhichPokemon]
 -	push af
 -	ld a,[wcf91]
 -	push af
 -	push de
 -	push hl
 -	ld bc,34
 -	add hl,bc ; hl now points to MSB of max HP
 -	ld a,[hli]
 -	ld b,a
 -	ld c,[hl]
 -	pop hl
 -	push bc
 -	push hl
 -	call .recalculateStats
 -	pop hl
 -	ld bc,35 ; hl now points to LSB of max HP
 -	add hl,bc
 -	pop bc
 -	ld a,[hld]
 -	sub c
 -	ld c,a
 -	ld a,[hl]
 -	sbc b
 -	ld b,a ; bc = the amount of max HP gained from leveling up
 -; add the amount gained to the current HP
 -	ld de,-32
 -	add hl,de ; hl now points to MSB of current HP
 -	ld a,[hl]
 -	add c
 -	ld [hld],a
 -	ld a,[hl]
 -	adc b
 -	ld [hl],a
 -	ld a,$f8 ; level up message
 -	ld [wd07d],a
 -	call RedrawPartyMenu
 -	pop de
 -	ld a,d
 -	ld [wWhichPokemon],a
 -	ld a,e
 -	ld [wd11e],a
 -	xor a
 -	ld [wcc49],a ; load from player's party
 -	call LoadMonData
 -	ld d,$01
 -	callab PrintStatsBox ; display new stats text box
 -	call WaitForTextScrollButtonPress ; wait for button press
 -	xor a
 -	ld [wcc49],a
 -	predef LearnMoveFromLevelUp ; learn level up move, if any
 -	xor a
 -	ld [wccd4],a
 -	callab TryEvolvingMon ; evolve pokemon, if appropriate
 -	ld a,$01
 -	ld [wUpdateSpritesEnabled],a
 -	pop af
 -	ld [wcf91],a
 -	pop af
 -	ld [wWhichPokemon],a
 -	jp RemoveUsedItem
 -
 -VitaminStatRoseText: ; df24 (3:5f24)
 -	TX_FAR _VitaminStatRoseText
 -	db "@"
 -
 -VitaminNoEffectText: ; df29 (3:5f29)
 -	TX_FAR _VitaminNoEffectText
 -	db "@"
 -
 -VitaminText: ; df2e (3:5f2e)
 -	db "HEALTH@"
 -	db "ATTACK@"
 -	db "DEFENSE@"
 -	db "SPEED@"
 -	db "SPECIAL@"
 -
 -ItemUseBait: ; df52 (3:5f52)
 -	ld hl,ThrewBaitText
 -	call PrintText
 -	ld hl,wEnemyMonCatchRate ; catch rate
 -	srl [hl] ; halve catch rate
 -	ld a,BAIT_ANIM
 -	ld hl,wSafariBaitFactor ; bait factor
 -	ld de,wSafariEscapeFactor ; escape factor
 -	jr BaitRockCommon
 -
 -ItemUseRock: ; df67 (3:5f67)
 -	ld hl,ThrewRockText
 -	call PrintText
 -	ld hl,wEnemyMonCatchRate ; catch rate
 -	ld a,[hl]
 -	add a ; double catch rate
 -	jr nc,.noCarry
 -	ld a,$ff
 -.noCarry
 -	ld [hl],a
 -	ld a,ROCK_ANIM
 -	ld hl,wSafariEscapeFactor ; escape factor
 -	ld de,wSafariBaitFactor ; bait factor
 -
 -BaitRockCommon: ; df7f (3:5f7f)
 -	ld [W_ANIMATIONID],a
 -	xor a
 -	ld [wcc5b],a
 -	ld [H_WHOSETURN],a
 -	ld [de],a ; zero escape factor (for bait), zero bait factor (for rock)
 -.randomLoop ; loop until a random number less than 5 is generated
 -	call Random
 -	and a,7
 -	cp a,5
 -	jr nc,.randomLoop
 -	inc a ; increment the random number, giving a range from 1 to 5 inclusive
 -	ld b,a
 -	ld a,[hl]
 -	add b ; increase bait factor (for bait), increase escape factor (for rock)
 -	jr nc,.noCarry
 -	ld a,$ff
 -.noCarry
 -	ld [hl],a
 -	predef MoveAnimation ; do animation
 -	ld c,70
 -	jp DelayFrames
 -
 -ThrewBaitText: ; dfa5 (3:5fa5)
 -	TX_FAR _ThrewBaitText
 -	db "@"
 -
 -ThrewRockText: ; dfaa (3:5faa)
 -	TX_FAR _ThrewRockText
 -	db "@"
 -
 -; also used for Dig out-of-battle effect
 -ItemUseEscapeRope: ; dfaf (3:5faf)
 -	ld a,[W_ISINBATTLE]
 -	and a
 -	jr nz,.notUsable
 -	ld a,[W_CURMAP]
 -	cp a,AGATHAS_ROOM
 -	jr z,.notUsable
 -	ld a,[W_CURMAPTILESET]
 -	ld b,a
 -	ld hl,EscapeRopeTilesets
 -.loop
 -	ld a,[hli]
 -	cp a,$ff
 -	jr z,.notUsable
 -	cp b
 -	jr nz,.loop
 -	ld hl,wd732
 -	set 3,[hl]
 -	set 6,[hl]
 -	ld hl,wd72e
 -	res 4,[hl]
 -	ld hl,wd790
 -	res 7,[hl] ; unset Safari Zone bit
 -	xor a
 -	ld [W_NUMSAFARIBALLS],a
 -	ld [W_SAFARIZONEENTRANCECURSCRIPT],a
 -	inc a
 -	ld [wEscapedFromBattle],a
 -	ld [wcd6a],a ; item used
 -	ld a,[wd152]
 -	and a ; using Dig?
 -	ret nz ; if so, return
 -	call ItemUseReloadOverworldData
 -	ld c,30
 -	call DelayFrames
 -	jp RemoveUsedItem
 -.notUsable
 -	jp ItemUseNotTime
 -
 -EscapeRopeTilesets: ; dffd (3:5ffd)
 -	db FOREST, CEMETERY, CAVERN, FACILITY, INTERIOR
 -	db $ff ; terminator
 -
 -ItemUseRepel: ; e003 (3:6003)
 -	ld b,100
 -
 -ItemUseRepelCommon: ; e005 (3:6005)
 -	ld a,[W_ISINBATTLE]
 -	and a
 -	jp nz,ItemUseNotTime
 -	ld a,b
 -	ld [wRepelRemainingSteps],a
 -	jp PrintItemUseTextAndRemoveItem
 -
 -; handles X Accuracy item
 -ItemUseXAccuracy: ; e013 (3:6013)
 -	ld a,[W_ISINBATTLE]
 -	and a
 -	jp z,ItemUseNotTime
 -	ld hl,W_PLAYERBATTSTATUS2
 -	set UsingXAccuracy,[hl] ; X Accuracy bit
 -	jp PrintItemUseTextAndRemoveItem
 -
 -; This function is bugged and never works. It always jumps to ItemUseNotTime.
 -; The Card Key is handled in a different way.
 -ItemUseCardKey: ; e022 (3:6022)
 -	xor a
 -	ld [wd71f],a
 -	call GetTileAndCoordsInFrontOfPlayer
 -	ld a,[GetTileAndCoordsInFrontOfPlayer] ; $4586
 -	cp a,$18
 -	jr nz,.next0
 -	ld hl,CardKeyTable1
 -	jr .next1
 -.next0
 -	cp a,$24
 -	jr nz,.next2
 -	ld hl,CardKeyTable2
 -	jr .next1
 -.next2
 -	cp a,$5e
 -	jp nz,ItemUseNotTime
 -	ld hl,CardKeyTable3
 -.next1
 -	ld a,[W_CURMAP]
 -	ld b,a
 -.loop
 -	ld a,[hli]
 -	cp a,$ff
 -	jp z,ItemUseNotTime
 -	cp b
 -	jr nz,.nextEntry1
 -	ld a,[hli]
 -	cp d
 -	jr nz,.nextEntry2
 -	ld a,[hli]
 -	cp e
 -	jr nz,.nextEntry3
 -	ld a,[hl]
 -	ld [wd71f],a
 -	jr .done
 -.nextEntry1
 -	inc hl
 -.nextEntry2
 -	inc hl
 -.nextEntry3
 -	inc hl
 -	jr .loop
 -.done
 -	ld hl,ItemUseText00
 -	call PrintText
 -	ld hl,wd728
 -	set 7,[hl]
 -	ret
 -
 -; These tables are probably supposed to be door locations in Silph Co.,
 -; but they are unused.
 -; The reason there are 3 tables is unknown.
 -
 -; Format:
 -; 00: Map ID
 -; 01: Y
 -; 02: X
 -; 03: ID?
 -
 -CardKeyTable1: ; e072 (3:6072)
 -	db  SILPH_CO_2F,$04,$04,$00
 -	db  SILPH_CO_2F,$04,$05,$01
 -	db  SILPH_CO_4F,$0C,$04,$02
 -	db  SILPH_CO_4F,$0C,$05,$03
 -	db  SILPH_CO_7F,$06,$0A,$04
 -	db  SILPH_CO_7F,$06,$0B,$05
 -	db  SILPH_CO_9F,$04,$12,$06
 -	db  SILPH_CO_9F,$04,$13,$07
 -	db SILPH_CO_10F,$08,$0A,$08
 -	db SILPH_CO_10F,$08,$0B,$09
 -	db $ff
 -
 -CardKeyTable2: ; e09b (3:609b)
 -	db SILPH_CO_3F,$08,$09,$0A
 -	db SILPH_CO_3F,$09,$09,$0B
 -	db SILPH_CO_5F,$04,$07,$0C
 -	db SILPH_CO_5F,$05,$07,$0D
 -	db SILPH_CO_6F,$0C,$05,$0E
 -	db SILPH_CO_6F,$0D,$05,$0F
 -	db SILPH_CO_8F,$08,$07,$10
 -	db SILPH_CO_8F,$09,$07,$11
 -	db SILPH_CO_9F,$08,$03,$12
 -	db SILPH_CO_9F,$09,$03,$13
 -	db $ff
 -
 -CardKeyTable3: ; e0c4 (3:60c4)
 -	db SILPH_CO_11F,$08,$09,$14
 -	db SILPH_CO_11F,$09,$09,$15
 -	db $ff
 -
 -ItemUsePokedoll: ; e0cd (3:60cd)
 -	ld a,[W_ISINBATTLE]
 -	dec a
 -	jp nz,ItemUseNotTime
 -	ld a,$01
 -	ld [wEscapedFromBattle],a
 -	jp PrintItemUseTextAndRemoveItem
 -
 -ItemUseGuardSpec: ; e0dc (3:60dc)
 -	ld a,[W_ISINBATTLE]
 -	and a
 -	jp z,ItemUseNotTime
 -	ld hl,W_PLAYERBATTSTATUS2
 -	set ProtectedByMist,[hl] ; Mist bit
 -	jp PrintItemUseTextAndRemoveItem
 -
 -ItemUseSuperRepel: ; e0eb (3:60eb)
 -	ld b,200
 -	jp ItemUseRepelCommon
 -
 -ItemUseMaxRepel: ; e0f0 (3:60f0)
 -	ld b,250
 -	jp ItemUseRepelCommon
 -
 -ItemUseDireHit: ; e0f5 (3:60f5)
 -	ld a,[W_ISINBATTLE]
 -	and a
 -	jp z,ItemUseNotTime
 -	ld hl,W_PLAYERBATTSTATUS2
 -	set GettingPumped,[hl] ; Focus Energy bit
 -	jp PrintItemUseTextAndRemoveItem
 -
 -ItemUseXStat: ; e104 (3:6104)
 -	ld a,[W_ISINBATTLE]
 -	and a
 -	jr nz,.inBattle
 -	call ItemUseNotTime
 -	ld a,2
 -	ld [wcd6a],a ; item not used
 -	ret
 -.inBattle
 -	ld hl,W_PLAYERMOVENUM
 -	ld a,[hli]
 -	push af ; save [W_PLAYERMOVENUM]
 -	ld a,[hl]
 -	push af ; save [W_PLAYERMOVEEFFECT]
 -	push hl
 -	ld a,[wcf91]
 -	sub a,X_ATTACK - ATTACK_UP1_EFFECT
 -	ld [hl],a ; store player move effect
 -	call PrintItemUseTextAndRemoveItem
 -	ld a,XSTATITEM_ANIM ; X stat item animation ID
 -	ld [W_PLAYERMOVENUM],a
 -	call LoadScreenTilesFromBuffer1 ; restore saved screen
 -	call Delay3
 -	xor a
 -	ld [H_WHOSETURN],a ; set turn to player's turn
 -	callba StatModifierUpEffect ; do stat increase move
 -	pop hl
 -	pop af
 -	ld [hld],a ; restore [W_PLAYERMOVEEFFECT]
 -	pop af
 -	ld [hl],a ; restore [W_PLAYERMOVENUM]
 -	ret
 -
 -ItemUsePokeflute: ; e140 (3:6140)
 -	ld a,[W_ISINBATTLE]
 -	and a
 -	jr nz,.inBattle
 -; if not in battle
 -	call ItemUseReloadOverworldData
 -	ld a,[W_CURMAP]
 -	cp a,ROUTE_12
 -	jr nz,.notRoute12
 -	ld a,[wd7d8]
 -	bit 7,a ; has the player beaten Route 12 Snorlax yet?
 -	jr nz,.noSnorlaxToWakeUp
 -; if the player hasn't beaten Route 12 Snorlax
 -	ld hl,Route12SnorlaxFluteCoords
 -	call ArePlayerCoordsInArray
 -	jr nc,.noSnorlaxToWakeUp
 -	ld hl,PlayedFluteHadEffectText
 -	call PrintText
 -	ld hl,wd7d8
 -	set 6,[hl] ; trigger Snorlax fight (handled by map script)
 -	ret
 -.notRoute12
 -	cp a,ROUTE_16
 -	jr nz,.noSnorlaxToWakeUp
 -	ld a,[wd7e0]
 -	bit 1,a ; has the player beaten Route 16 Snorlax yet?
 -	jr nz,.noSnorlaxToWakeUp
 -; if the player hasn't beaten Route 16 Snorlax
 -	ld hl,Route16SnorlaxFluteCoords
 -	call ArePlayerCoordsInArray
 -	jr nc,.noSnorlaxToWakeUp
 -	ld hl,PlayedFluteHadEffectText
 -	call PrintText
 -	ld hl,wd7e0
 -	set 0,[hl] ; trigger Snorlax fight (handled by map script)
 -	ret
 -.noSnorlaxToWakeUp
 -	ld hl,PlayedFluteNoEffectText
 -	jp PrintText
 -.inBattle
 -	xor a
 -	ld [wWhichTrade],a ; initialize variable that indicates if any pokemon were woken up to zero
 -	ld b,~SLP & $FF
 -	ld hl,wPartyMon1Status
 -	call WakeUpEntireParty
 -	ld a,[W_ISINBATTLE]
 -	dec a ; is it a trainer battle?
 -	jr z,.skipWakingUpEnemyParty
 -; if it's a trainer battle
 -	ld hl,wEnemyMon1Status
 -	call WakeUpEntireParty
 -.skipWakingUpEnemyParty
 -	ld hl,wBattleMonStatus
 -	ld a,[hl]
 -	and b ; remove Sleep status
 -	ld [hl],a
 -	ld hl,wEnemyMonStatus
 -	ld a,[hl]
 -	and b ; remove Sleep status
 -	ld [hl],a
 -	call LoadScreenTilesFromBuffer2 ; restore saved screen
 -	ld a,[wWhichTrade]
 -	and a ; were any pokemon asleep before playing the flute?
 -	ld hl,PlayedFluteNoEffectText
 -	jp z,PrintText ; if no pokemon were asleep
 -; if some pokemon were asleep
 -	ld hl,PlayedFluteHadEffectText
 -	call PrintText
 -	ld a,[wLowHealthAlarm]
 -	and a,$80
 -	jr nz,.skipMusic
 -	call WaitForSoundToFinish ; wait for sound to end
 -	callba Music_PokeFluteInBattle ; play in-battle pokeflute music
 -.musicWaitLoop ; wait for music to finish playing
 -	ld a,[wc02c]
 -	and a ; music off?
 -	jr nz,.musicWaitLoop
 -.skipMusic
 -	ld hl,FluteWokeUpText
 -	jp PrintText
 -
 -; wakes up all party pokemon
 -; INPUT:
 -; hl must point to status of first pokemon in party (player's or enemy's)
 -; b must equal ~SLP
 -; [wWhichTrade] should be initialized to 0
 -; OUTPUT:
 -; [wWhichTrade]: set to 1 if any pokemon were asleep
 -WakeUpEntireParty: ; e1e5 (3:61e5)
 -	ld de,44
 -	ld c,6
 -.loop
 -	ld a,[hl]
 -	push af
 -	and a,SLP ; is pokemon asleep?
 -	jr z,.notAsleep
 -	ld a,1
 -	ld [wWhichTrade],a ; indicate that a pokemon had to be woken up
 -.notAsleep
 -	pop af
 -	and b ; remove Sleep status
 -	ld [hl],a
 -	add hl,de
 -	dec c
 -	jr nz,.loop
 -	ret
 -
 -; Format:
 -; 00: Y
 -; 01: X
 -Route12SnorlaxFluteCoords: ; e1fd (3:61fd)
 -	db 62,9  ; one space West of Snorlax
 -	db 61,10 ; one space North of Snorlax
 -	db 63,10 ; one space South of Snorlax
 -	db 62,11 ; one space East of Snorlax
 -	db $ff ; terminator
 -
 -; Format:
 -; 00: Y
 -; 01: X
 -Route16SnorlaxFluteCoords: ; e206 (3:6206)
 -	db 10,27 ; one space East of Snorlax
 -	db 10,25 ; one space West of Snorlax
 -	db $ff ; terminator
 -
 -PlayedFluteNoEffectText: ; e20b (3:620b)
 -	TX_FAR _PlayedFluteNoEffectText
 -	db "@"
 -
 -FluteWokeUpText: ; e210 (3:6210)
 -	TX_FAR _FluteWokeUpText
 -	db "@"
 -
 -PlayedFluteHadEffectText: ; e215 (3:6215)
 -	TX_FAR _PlayedFluteHadEffectText
 -	db $06
 -	db $08
 -	ld a,[W_ISINBATTLE]
 -	and a
 -	jr nz,.done
 -; play out-of-battle pokeflute music
 -	ld a,$ff
 -	call PlaySound ; turn off music
 -	ld a, (SFX_02_5e - SFX_Headers_02) / 3
 -	ld c, BANK(SFX_02_5e)
 -	call PlayMusic ; play music
 -.musicWaitLoop ; wait for music to finish playing
 -	ld a,[wc028]
 -	cp a,$b8
 -	jr z,.musicWaitLoop
 -	call PlayDefaultMusic ; start playing normal music again
 -.done
 -	jp TextScriptEnd ; end text
 -
 -ItemUseCoinCase: ; e23a (3:623a)
 -	ld a,[W_ISINBATTLE]
 -	and a
 -	jp nz,ItemUseNotTime
 -	ld hl,CoinCaseNumCoinsText
 -	jp PrintText
 -
 -CoinCaseNumCoinsText: ; e247 (3:6247)
 -	TX_FAR _CoinCaseNumCoinsText
 -	db "@"
 -
 -OldRodCode: ; e24c (3:624c)
 -	call FishingInit
 -	jp c, ItemUseNotTime
 -	ld bc, (5 << 8) | MAGIKARP
 -	ld a, $1 ; set bite
 -	jr RodResponse ; 0xe257 $34
 -
 -GoodRodCode: ; e259 (3:6259)
 -	call FishingInit
 -	jp c,ItemUseNotTime
 -.RandomLoop
 -	call Random
 -	srl a
 -	jr c, .SetBite
 -	and %11
 -	cp 2
 -	jr nc, .RandomLoop
 -	; choose which monster appears
 -	ld hl,GoodRodMons
 -	add a,a
 -	ld c,a
 -	ld b,0
 -	add hl,bc
 -	ld b,[hl]
 -	inc hl
 -	ld c,[hl]
 -	and a
 -.SetBite
 -	ld a,0
 -	rla
 -	xor 1
 -	jr RodResponse
 -
 -INCLUDE "data/good_rod.asm"
 -
 -SuperRodCode: ; e283 (3:6283)
 -	call FishingInit
 -	jp c, ItemUseNotTime
 -	call ReadSuperRodData ; 0xe8ea
 -	ld a, e
 -RodResponse: ; e28d (3:628d)
 -	ld [wWhichTrade], a
 -
 -	dec a ; is there a bite?
 -	jr nz, .next
 -	; if yes, store level and species data
 -	ld a, 1
 -	ld [W_MOVEMISSED], a
 -	ld a, b ; level
 -	ld [W_CURENEMYLVL], a
 -	ld a, c ; species
 -	ld [W_CUROPPONENT], a
 -
 -.next
 -	ld hl, wWalkBikeSurfState
 -	ld a, [hl] ; store the value in a
 -	push af
 -	push hl
 -	ld [hl], 0
 -	callba Func_707b6
 -	pop hl
 -	pop af
 -	ld [hl], a
 -	ret
 -
 -; checks if fishing is possible and if so, runs initialization code common to all rods
 -; unsets carry if fishing is possible, sets carry if not
 -FishingInit: ; e2b4 (3:62b4)
 -	ld a,[W_ISINBATTLE]
 -	and a
 -	jr z,.notInBattle
 -	scf ; can't fish during battle
 -	ret
 -.notInBattle
 -	call IsNextTileShoreOrWater
 -	ret c
 -	ld a,[wWalkBikeSurfState]
 -	cp a,2 ; Surfing?
 -	jr z,.surfing
 -	call ItemUseReloadOverworldData
 -	ld hl,ItemUseText00
 -	call PrintText
 -	ld a,(SFX_02_3e - SFX_Headers_02) / 3
 -	call PlaySound ; play sound
 -	ld c,80
 -	call DelayFrames
 -	and a
 -	ret
 -.surfing
 -	scf ; can't fish when surfing
 -	ret
 -
 -ItemUseOaksParcel: ; e2de (3:62de)
 -	jp ItemUseNotYoursToUse
 -
 -ItemUseItemfinder: ; e2e1 (3:62e1)
 -	ld a,[W_ISINBATTLE]
 -	and a
 -	jp nz,ItemUseNotTime
 -	call ItemUseReloadOverworldData
 -	callba HiddenItemNear ; check for hidden items
 -	ld hl,ItemfinderFoundNothingText
 -	jr nc,.printText ; if no hidden items
 -	ld c,4
 -.loop
 -	ld a,(SFX_02_4a - SFX_Headers_02) / 3
 -	call PlaySoundWaitForCurrent ; play sound
 -	ld a,(SFX_02_5a - SFX_Headers_02) / 3
 -	call PlaySoundWaitForCurrent ; play sound
 -	dec c
 -	jr nz,.loop
 -	ld hl,ItemfinderFoundItemText
 -.printText
 -	jp PrintText
 -
 -ItemfinderFoundItemText: ; e30d (3:630d)
 -	TX_FAR _ItemfinderFoundItemText
 -	db "@"
 -
 -ItemfinderFoundNothingText: ; e312 (3:6312)
 -	TX_FAR _ItemfinderFoundNothingText
 -	db "@"
 -
 -ItemUsePPUp: ; e317 (3:6317)
 -	ld a,[W_ISINBATTLE]
 -	and a
 -	jp nz,ItemUseNotTime
 -
 -ItemUsePPRestore: ; e31e (3:631e)
 -	ld a,[wWhichPokemon]
 -	push af
 -	ld a,[wcf91]
 -	ld [wWhichTrade],a
 -.chooseMon
 -	xor a
 -	ld [wUpdateSpritesEnabled],a
 -	ld a,$01 ; item use party menu
 -	ld [wd07d],a
 -	call DisplayPartyMenu
 -	jr nc,.chooseMove
 -	jp .itemNotUsed
 -.chooseMove
 -	ld a,[wWhichTrade]
 -	cp a,ELIXER
 -	jp nc,.useElixir ; if Elixir or Max Elixir
 -	ld a,$02
 -	ld [wMoveMenuType],a
 -	ld hl,RaisePPWhichTechniqueText
 -	ld a,[wWhichTrade]
 -	cp a,ETHER ; is it a PP Up?
 -	jr c,.printWhichTechniqueMessage ; if so, print the raise PP message
 -	ld hl,RestorePPWhichTechniqueText ; otherwise, print the restore PP message
 -.printWhichTechniqueMessage
 -	call PrintText
 -	xor a
 -	ld [wPlayerMoveListIndex],a
 -	callab MoveSelectionMenu ; move selection menu
 -	ld a,0
 -	ld [wPlayerMoveListIndex],a
 -	jr nz,.chooseMon
 -	ld hl,wPartyMon1Moves
 -	ld bc,44
 -	call GetSelectedMoveOffset
 -	push hl
 -	ld a,[hl]
 -	ld [wd11e],a
 -	call GetMoveName
 -	call CopyStringToCF4B ; copy name to wcf4b
 -	pop hl
 -	ld a,[wWhichTrade]
 -	cp a,ETHER
 -	jr nc,.useEther ; if Ether or Max Ether
 -.usePPUp
 -	ld bc,21
 -	add hl,bc
 -	ld a,[hl] ; move PP
 -	cp a,3 << 6 ; have 3 PP Ups already been used?
 -	jr c,.PPNotMaxedOut
 -	ld hl,PPMaxedOutText
 -	call PrintText
 -	jr .chooseMove
 -.PPNotMaxedOut
 -	ld a,[hl]
 -	add a,1 << 6 ; increase PP Up count by 1
 -	ld [hl],a
 -	ld a,1 ; 1 PP Up used
 -	ld [wd11e],a
 -	call RestoreBonusPP ; add the bonus PP to current PP
 -	ld hl,PPIncreasedText
 -	call PrintText
 -.done
 -	pop af
 -	ld [wWhichPokemon],a
 -	call GBPalWhiteOut
 -	call GoPAL_SET_CF1C
 -	jp RemoveUsedItem
 -.afterRestoringPP ; after using a (Max) Ether/Elixir
 -	ld a,[wWhichPokemon]
 -	ld b,a
 -	ld a,[wPlayerMonNumber]
 -	cp b ; is the pokemon whose PP was restored active in battle?
 -	jr nz,.skipUpdatingInBattleData
 -	ld hl,wPartyMon1PP
 -	ld bc,44
 -	call AddNTimes
 -	ld de,wBattleMonPP
 -	ld bc,4
 -	call CopyData ; copy party data to in-battle data
 -.skipUpdatingInBattleData
 -	ld a,(SFX_02_3e - SFX_Headers_02) / 3
 -	call PlaySound
 -	ld hl,PPRestoredText
 -	call PrintText
 -	jr .done
 -.useEther
 -	call .restorePP
 -	jr nz,.afterRestoringPP
 -	jp .noEffect
 -; unsets zero flag if PP was restored, sets zero flag if not
 -; however, this is bugged for Max Ethers and Max Elixirs (see below)
 -.restorePP
 -	xor a
 -	ld [wcc49],a ; party pokemon
 -	call GetMaxPP
 -	ld hl,wPartyMon1Moves
 -	ld bc,44
 -	call GetSelectedMoveOffset
 -	ld bc,21
 -	add hl,bc ; hl now points to move's PP
 -	ld a,[wd11e]
 -	ld b,a ; b = max PP
 -	ld a,[wWhichTrade]
 -	cp a,MAX_ETHER
 -	jr z,.fullyRestorePP
 -	ld a,[hl] ; move PP
 -	and a,%00111111 ; lower 6 bit bits store current PP
 -	cp b ; does current PP equal max PP?
 -	ret z ; if so, return
 -	add a,10 ; increase current PP by 10
 -; b holds the max PP amount and b will hold the new PP amount.
 -; So, if the new amount meets or exceeds the max amount,
 -; cap the amount to the max amount by leaving b unchanged.
 -; Otherwise, store the new amount in b.
 -	cp b ; does the new amount meet or exceed the maximum?
 -	jr nc,.storeNewAmount
 -	ld b,a
 -.storeNewAmount
 -	ld a,[hl] ; move PP
 -	and a,%11000000 ; PP Up counter bits
 -	add b
 -	ld [hl],a
 -	ret
 -.fullyRestorePP
 -	ld a,[hl] ; move PP
 -; Note that this code has a bug. It doesn't mask out the upper two bits, which
 -; are used to count how many PP Ups have been used on the move. So, Max Ethers
 -; and Max Elixirs will not be detected as having no effect on a move with full
 -; PP if the move has had any PP Ups used on it.
 -	cp b ; does current PP equal max PP?
 -	ret z
 -	jr .storeNewAmount
 -.useElixir
 -; decrement the item ID so that ELIXER becomes ETHER and MAX_ELIXER becomes MAX_ETHER
 -	ld hl,wWhichTrade
 -	dec [hl]
 -	dec [hl]
 -	xor a
 -	ld hl,wCurrentMenuItem
 -	ld [hli],a
 -	ld [hl],a ; zero the counter for number of moves that had their PP restored
 -	ld b,4
 -; loop through each move and restore PP
 -.elixirLoop
 -	push bc
 -	ld hl,wPartyMon1Moves
 -	ld bc,44
 -	call GetSelectedMoveOffset
 -	ld a,[hl]
 -	and a ; does the current slot have a move?
 -	jr z,.nextMove
 -	call .restorePP
 -	jr z,.nextMove
 -; if some PP was restored
 -	ld hl,wTileBehindCursor ; counter for number of moves that had their PP restored
 -	inc [hl]
 -.nextMove
 -	ld hl,wCurrentMenuItem
 -	inc [hl]
 -	pop bc
 -	dec b
 -	jr nz,.elixirLoop
 -	ld a,[wTileBehindCursor]
 -	and a ; did any moves have their PP restored?
 -	jp nz,.afterRestoringPP
 -.noEffect
 -	call ItemUseNoEffect
 -.itemNotUsed
 -	call GBPalWhiteOut
 -	call GoPAL_SET_CF1C
 -	pop af
 -	xor a
 -	ld [wcd6a],a ; item use failed
 -	ret
 -
 -RaisePPWhichTechniqueText: ; e45d (3:645d)
 -	TX_FAR _RaisePPWhichTechniqueText
 -	db "@"
 -
 -RestorePPWhichTechniqueText: ; e462 (3:6462)
 -	TX_FAR _RestorePPWhichTechniqueText
 -	db "@"
 -
 -PPMaxedOutText: ; e467 (3:6467)
 -	TX_FAR _PPMaxedOutText
 -	db "@"
 -
 -PPIncreasedText: ; e46c (3:646c)
 -	TX_FAR _PPIncreasedText
 -	db "@"
 -
 -PPRestoredText: ; e471 (3:6471)
 -	TX_FAR _PPRestoredText
 -	db "@"
 -
 -; for items that can't be used from the Item menu
 -UnusableItem: ; e476 (3:6476)
 -	jp ItemUseNotTime
 -
 -ItemUseTMHM: ; e479 (3:6479)
 -	ld a,[W_ISINBATTLE]
 -	and a
 -	jp nz,ItemUseNotTime
 -	ld a,[wcf91]
 -	sub a,TM_01
 -	push af
 -	jr nc,.skipAdding
 -	add a,55 ; if item is an HM, add 55
 -.skipAdding
 -	inc a
 -	ld [wd11e],a
 -	predef TMToMove ; get move ID from TM/HM ID
 -	ld a,[wd11e]
 -	ld [wMoveNum],a
 -	call GetMoveName
 -	call CopyStringToCF4B ; copy name to wcf4b
 -	pop af
 -	ld hl,BootedUpTMText
 -	jr nc,.printBootedUpMachineText
 -	ld hl,BootedUpHMText
 -.printBootedUpMachineText
 -	call PrintText
 -	ld hl,TeachMachineMoveText
 -	call PrintText
 -	hlCoord 14, 7
 -	ld bc,$080f
 -	ld a,TWO_OPTION_MENU
 -	ld [wTextBoxID],a
 -	call DisplayTextBoxID ; yes/no menu
 -	ld a,[wCurrentMenuItem]
 -	and a
 -	jr z,.useMachine
 -	ld a,2
 -	ld [wcd6a],a ; item not used
 -	ret
 -.useMachine
 -	ld a,[wWhichPokemon]
 -	push af
 -	ld a,[wcf91]
 -	push af
 -.chooseMon
 -	ld hl,wcf4b
 -	ld de,wd036
 -	ld bc,14
 -	call CopyData
 -	ld a,$ff
 -	ld [wUpdateSpritesEnabled],a
 -	ld a,$03 ; teach TM/HM party menu
 -	ld [wd07d],a
 -	call DisplayPartyMenu
 -	push af
 -	ld hl,wd036
 -	ld de,wcf4b
 -	ld bc,14
 -	call CopyData
 -	pop af
 -	jr nc,.checkIfAbleToLearnMove
 -; if the player canceled teaching the move
 -	pop af
 -	pop af
 -	call GBPalWhiteOutWithDelay3
 -	call ClearSprites
 -	call GoPAL_SET_CF1C
 -	jp LoadScreenTilesFromBuffer1 ; restore saved screen
 -.checkIfAbleToLearnMove
 -	predef CanLearnTM ; check if the pokemon can learn the move
 -	push bc
 -	ld a,[wWhichPokemon]
 -	ld hl,wPartyMonNicks
 -	call GetPartyMonName
 -	pop bc
 -	ld a,c
 -	and a ; can the pokemon learn the move?
 -	jr nz,.checkIfAlreadyLearnedMove
 -; if the pokemon can't learn the move
 -	ld a,(SFX_02_51 - SFX_Headers_02) / 3
 -	call PlaySoundWaitForCurrent ; play sound
 -	ld hl,MonCannotLearnMachineMoveText
 -	call PrintText
 -	jr .chooseMon
 -.checkIfAlreadyLearnedMove
 -	callab CheckIfMoveIsKnown ; check if the pokemon already knows the move
 -	jr c,.chooseMon
 -	predef LearnMove ; teach move
 -	pop af
 -	ld [wcf91],a
 -	pop af
 -	ld [wWhichPokemon],a
 -	ld a,b
 -	and a
 -	ret z
 -	ld a,[wcf91]
 -	call IsItemHM
 -	ret c
 -	jp RemoveUsedItem
 -
 -BootedUpTMText: ; e54f (3:654f)
 -	TX_FAR _BootedUpTMText
 -	db "@"
 -
 -BootedUpHMText: ; e554 (3:6554)
 -	TX_FAR _BootedUpHMText
 -	db "@"
 -
 -TeachMachineMoveText: ; e559 (3:6559)
 -	TX_FAR _TeachMachineMoveText
 -	db "@"
 -
 -MonCannotLearnMachineMoveText: ; e55e (3:655e)
 -	TX_FAR _MonCannotLearnMachineMoveText
 -	db "@"
 -
 -PrintItemUseTextAndRemoveItem: ; e563 (3:6563)
 -	ld hl,ItemUseText00
 -	call PrintText
 -	ld a,(SFX_02_3e - SFX_Headers_02) / 3
 -	call PlaySound ; play sound
 -	call WaitForTextScrollButtonPress ; wait for button press
 -
 -RemoveUsedItem: ; e571 (3:6571)
 -	ld hl,wNumBagItems
 -	ld a,1 ; one item
 -	ld [wcf96],a ; store quantity
 -	jp RemoveItemFromInventory
 -
 -ItemUseNoEffect: ; e57c (3:657c)
 -	ld hl,ItemUseNoEffectText
 -	jr ItemUseFailed
 -
 -ItemUseNotTime: ; e581 (3:6581)
 -	ld hl,ItemUseNotTimeText
 -	jr ItemUseFailed
 -
 -ItemUseNotYoursToUse: ; e586 (3:6586)
 -	ld hl,ItemUseNotYoursToUseText
 -	jr ItemUseFailed
 -
 -ThrowBallAtTrainerMon: ; e58b (3:658b)
 -	call GoPAL_SET_CF1C
 -	call LoadScreenTilesFromBuffer1 ; restore saved screen
 -	call Delay3
 -	ld a,TOSS_ANIM
 -	ld [W_ANIMATIONID],a
 -	predef MoveAnimation ; do animation
 -	ld hl,ThrowBallAtTrainerMonText1
 -	call PrintText
 -	ld hl,ThrowBallAtTrainerMonText2
 -	call PrintText
 -	jr RemoveUsedItem
 -
 -NoCyclingAllowedHere: ; e5ac (3:65ac)
 -	ld hl,NoCyclingAllowedHereText
 -	jr ItemUseFailed
 -
 -BoxFullCannotThrowBall: ; e5b1 (3:65b1)
 -	ld hl,BoxFullCannotThrowBallText
 -	jr ItemUseFailed
 -
 -SurfingAttemptFailed: ; e5b6 (3:65b6)
 -	ld hl,NoSurfingHereText
 -
 -ItemUseFailed: ; e5b9 (3:65b9)
 -	xor a
 -	ld [wcd6a],a ; item use failed
 -	jp PrintText
 -
 -ItemUseNotTimeText: ; e5c0 (3:65c0)
 -	TX_FAR _ItemUseNotTimeText
 -	db "@"
 -
 -ItemUseNotYoursToUseText: ; e5c5 (3:65c5)
 -	TX_FAR _ItemUseNotYoursToUseText
 -	db "@"
 -
 -ItemUseNoEffectText: ; e5ca (3:65ca)
 -	TX_FAR _ItemUseNoEffectText
 -	db "@"
 -
 -ThrowBallAtTrainerMonText1: ; e5cf (3:65cf)
 -	TX_FAR _ThrowBallAtTrainerMonText1
 -	db "@"
 -
 -ThrowBallAtTrainerMonText2: ; e5d4 (3:65d4)
 -	TX_FAR _ThrowBallAtTrainerMonText2
 -	db "@"
 -
 -NoCyclingAllowedHereText: ; e5d9 (3:65d9)
 -	TX_FAR _NoCyclingAllowedHereText
 -	db "@"
 -
 -NoSurfingHereText: ; e5de (3:65de)
 -	TX_FAR _NoSurfingHereText
 -	db "@"
 -
 -BoxFullCannotThrowBallText: ; e5e3 (3:65e3)
 -	TX_FAR _BoxFullCannotThrowBallText
 -	db "@"
 -
 -ItemUseText00: ; e5e8 (3:65e8)
 -	TX_FAR _ItemUseText001
 -	db $05
 -	TX_FAR _ItemUseText002
 -	db "@"
 -
 -GotOnBicycleText: ; e5f2 (3:65f2)
 -	TX_FAR _GotOnBicycleText1
 -	db $05
 -	TX_FAR _GotOnBicycleText2
 -	db "@"
 -
 -GotOffBicycleText: ; e5fc (3:65fc)
 -	TX_FAR _GotOffBicycleText1
 -	db $05
 -	TX_FAR _GotOffBicycleText2
 -	db "@"
 -
 -; restores bonus PP (from PP Ups) when healing at a pokemon center
 -; also, when a PP Up is used, it increases the current PP by one PP Up bonus
 -; INPUT:
 -; [wWhichPokemon] = index of pokemon in party
 -; [wd11e] = mode
 -; 0: Pokemon Center healing
 -; 1: using a PP Up
 -; [wCurrentMenuItem] = index of move (when using a PP Up)
 -RestoreBonusPP: ; e606 (3:6606)
 -	ld hl,wPartyMon1Moves
 -	ld bc,44
 -	ld a,[wWhichPokemon]
 -	call AddNTimes
 -	push hl
 -	ld de,wcd78 - 1
 -	predef LoadMovePPs ; loads the normal max PP of each of the pokemon's moves to wcd78
 -	pop hl
 -	ld c,21
 -	ld b,0
 -	add hl,bc ; hl now points to move 1 PP
 -	ld de,wcd78
 -	ld b,0 ; initialize move counter to zero
 -; loop through the pokemon's moves
 -.loop
 -	inc b
 -	ld a,b
 -	cp a,5 ; reached the end of the pokemon's moves?
 -	ret z ; if so, return
 -	ld a,[wd11e]
 -	dec a ; using a PP Up?
 -	jr nz,.skipMenuItemIDCheck
 -; if using a PP Up, check if this is the move it's being used on
 -	ld a,[wCurrentMenuItem]
 -	inc a
 -	cp b
 -	jr nz,.nextMove
 -.skipMenuItemIDCheck
 -	ld a,[hl]
 -	and a,%11000000 ; have any PP Ups been used?
 -	call nz,AddBonusPP ; if so, add bonus PP
 -.nextMove
 -	inc hl
 -	inc de
 -	jr .loop
 -
 -; adds bonus PP from PP Ups to current PP
 -; 1/5 of normal max PP (capped at 7) is added for each PP Up
 -; INPUT:
 -; [de] = normal max PP
 -; [hl] = move PP
 -; [wd11e] = max number of times to add bonus
 -; set to 1 when using a PP Up, set to 255 otherwise
 -AddBonusPP: ; e642 (3:6642)
 -	push bc
 -	ld a,[de] ; normal max PP of move
 -	ld [H_DIVIDEND + 3],a
 -	xor a
 -	ld [H_DIVIDEND],a
 -	ld [H_DIVIDEND + 1],a
 -	ld [H_DIVIDEND + 2],a
 -	ld a,5
 -	ld [H_DIVISOR],a
 -	ld b,4
 -	call Divide
 -	ld a,[hl] ; move PP
 -	ld b,a
 -	swap a
 -	and a,%00001111
 -	srl a
 -	srl a
 -	ld c,a ; c = number of PP Ups used
 -.loop
 -	ld a,[H_QUOTIENT + 3]
 -	cp a,8 ; is the amount greater than or equal to 8?
 -	jr c,.addAmount
 -	ld a,7 ; cap the amount at 7
 -.addAmount
 -	add b
 -	ld b,a
 -	ld a,[wd11e]
 -	dec a
 -	jr z,.done
 -	dec c
 -	jr nz,.loop
 -.done
 -	ld [hl],b
 -	pop bc
 -	ret
 -
 -; gets max PP of a pokemon's move (including PP from PP Ups)
 -; INPUT:
 -; [wWhichPokemon] = index of pokemon within party/box
 -; [wcc49] = pokemon source
 -; 00: player's party
 -; 01: enemy's party
 -; 02: current box
 -; 03: daycare
 -; 04: player's in-battle pokemon
 -; [wCurrentMenuItem] = move index
 -; OUTPUT:
 -; [wd11e] = max PP
 -GetMaxPP: ; e677 (3:6677)
 -	ld a,[wcc49]
 -	and a
 -	ld hl,wPartyMon1Moves
 -	ld bc,wPartyMon2 - wPartyMon1
 -	jr z,.sourceWithMultipleMon
 -	ld hl,wEnemyMon1Moves
 -	dec a
 -	jr z,.sourceWithMultipleMon
 -	ld hl,wBoxMon1Moves
 -	ld bc,wBoxMon2 - wBoxMon1
 -	dec a
 -	jr z,.sourceWithMultipleMon
 -	ld hl,wDayCareMonMoves
 -	dec a
 -	jr z,.sourceWithOneMon
 -	ld hl,wBattleMonMoves ; player's in-battle pokemon
 -.sourceWithOneMon
 -	call GetSelectedMoveOffset2
 -	jr .next
 -.sourceWithMultipleMon
 -	call GetSelectedMoveOffset
 -.next
 -	ld a,[hl]
 -	dec a
 -	push hl
 -	ld hl,Moves
 -	ld bc,6
 -	call AddNTimes
 -	ld de,wcd6d
 -	ld a,BANK(Moves)
 -	call FarCopyData
 -	ld de,wcd72
 -	ld a,[de]
 -	ld b,a ; b = normal max PP
 -	pop hl
 -	push bc
 -	ld bc,21 ; PP offset if not player's in-battle pokemon data
 -	ld a,[wcc49]
 -	cp a,4 ; player's in-battle pokemon?
 -	jr nz,.addPPOffset
 -	ld bc,17 ; PP offset if player's in-battle pokemon data
 -.addPPOffset
 -	add hl,bc
 -	ld a,[hl] ; a = current PP
 -	and a,%11000000 ; get PP Up count
 -	pop bc
 -	or b ; place normal max PP in 6 lower bits of a
 -	ld h,d
 -	ld l,e
 -	inc hl ; hl = wcd73
 -	ld [hl],a
 -	xor a
 -	ld [wd11e],a ; no limit on PP Up amount
 -	call AddBonusPP ; add bonus PP from PP Ups
 -	ld a,[hl]
 -	and a,%00111111 ; mask out the PP Up count
 -	ld [wd11e],a ; store max PP
 -	ret
 -
 -GetSelectedMoveOffset: ; e6e3 (3:66e3)
 -	ld a,[wWhichPokemon]
 -	call AddNTimes
 -
 -GetSelectedMoveOffset2: ; e6e9 (3:66e9)
 -	ld a,[wCurrentMenuItem]
 -	ld c,a
 -	ld b,0
 -	add hl,bc
 -	ret
 -
 -; confirms the item toss and then tosses the item
 -; INPUT:
 -; hl = address of inventory (either wNumBagItems or wNumBoxItems)
 -; [wcf91] = item ID
 -; [wWhichPokemon] = index of item within inventory
 -; [wcf96] = quantity to toss
 -; OUTPUT:
 -; clears carry flag if the item is tossed, sets carry flag if not
 -TossItem_: ; e6f1 (3:66f1)
 -	push hl
 -	ld a,[wcf91]
 -	call IsItemHM
 -	pop hl
 -	jr c,.tooImportantToToss
 -	push hl
 -	call IsKeyItem_
 -	ld a,[wd124]
 -	pop hl
 -	and a
 -	jr nz,.tooImportantToToss
 -	push hl
 -	ld a,[wcf91]
 -	ld [wd11e],a
 -	call GetItemName
 -	call CopyStringToCF4B ; copy name to wcf4b
 -	ld hl,IsItOKToTossItemText
 -	call PrintText
 -	hlCoord 14, 7
 -	ld bc,$080f
 -	ld a,TWO_OPTION_MENU
 -	ld [wTextBoxID],a
 -	call DisplayTextBoxID ; yes/no menu
 -	ld a,[wd12e]
 -	cp a,2
 -	pop hl
 -	scf
 -	ret z
 -; if the player chose Yes
 -	push hl
 -	ld a,[wWhichPokemon]
 -	call RemoveItemFromInventory
 -	ld a,[wcf91]
 -	ld [wd11e],a
 -	call GetItemName
 -	call CopyStringToCF4B ; copy name to wcf4b
 -	ld hl,ThrewAwayItemText
 -	call PrintText
 -	pop hl
 -	and a
 -	ret
 -.tooImportantToToss
 -	push hl
 -	ld hl,TooImportantToTossText
 -	call PrintText
 -	pop hl
 -	scf
 -	ret
 -
 -ThrewAwayItemText: ; e755 (3:6755)
 -	TX_FAR _ThrewAwayItemText
 -	db "@"
 -
 -IsItOKToTossItemText: ; e75a (3:675a)
 -	TX_FAR _IsItOKToTossItemText
 -	db "@"
 -
 -TooImportantToTossText: ; e75f (3:675f)
 -	TX_FAR _TooImportantToTossText
 -	db "@"
 -
 -; checks if an item is a key item
 -; INPUT:
 -; [wcf91] = item ID
 -; OUTPUT:
 -; [wd124] = result
 -; 00: item is not key item
 -; 01: item is key item
 -IsKeyItem_: ; e764 (3:6764)
 -	ld a,$01
 -	ld [wd124],a
 -	ld a,[wcf91]
 -	cp a,HM_01 ; is the item an HM or TM?
 -	jr nc,.checkIfItemIsHM
 -; if the item is not an HM or TM
 -	push af
 -	ld hl,KeyItemBitfield
 -	ld de,wHPBarMaxHP
 -	ld bc,15 ; only 11 bytes are actually used
 -	call CopyData
 -	pop af
 -	dec a
 -	ld c,a
 -	ld hl,wHPBarMaxHP
 -	ld b,$02 ; test bit
 -	predef FlagActionPredef ; bitfield operation function
 -	ld a,c
 -	and a
 -	ret nz
 -.checkIfItemIsHM
 -	ld a,[wcf91]
 -	call IsItemHM
 -	ret c
 -	xor a
 -	ld [wd124],a
 -	ret
 -
 -INCLUDE "data/key_items.asm"
 -
 -SendNewMonToBox: ; e7a4 (3:67a4)
 -	ld de, W_NUMINBOX ; wda80
 -	ld a, [de]
 -	inc a
 -	ld [de], a
 -	ld a, [wcf91]
 -	ld [wd0b5], a
 -	ld c, a
 -.asm_e7b1
 -	inc de
 -	ld a, [de]
 -	ld b, a
 -	ld a, c
 -	ld c, b
 -	ld [de], a
 -	cp $ff
 -	jr nz, .asm_e7b1
 -	call GetMonHeader
 -	ld hl, wBoxMonOT
 -	ld bc, $b
 -	ld a, [W_NUMINBOX] ; wda80
 -	dec a
 -	jr z, .asm_e7ee
 -	dec a
 -	call AddNTimes
 -	push hl
 -	ld bc, $b
 -	add hl, bc
 -	ld d, h
 -	ld e, l
 -	pop hl
 -	ld a, [W_NUMINBOX] ; wda80
 -	dec a
 -	ld b, a
 -.asm_e7db
 -	push bc
 -	push hl
 -	ld bc, $b
 -	call CopyData
 -	pop hl
 -	ld d, h
 -	ld e, l
 -	ld bc, $fff5
 -	add hl, bc
 -	pop bc
 -	dec b
 -	jr nz, .asm_e7db
 -.asm_e7ee
 -	ld hl, wPlayerName ; wd158
 -	ld de, wBoxMonOT
 -	ld bc, $b
 -	call CopyData
 -	ld a, [W_NUMINBOX] ; wda80
 -	dec a
 -	jr z, .asm_e82a
 -	ld hl, wBoxMonNicks
 -	ld bc, $b
 -	dec a
 -	call AddNTimes
 -	push hl
 -	ld bc, $b
 -	add hl, bc
 -	ld d, h
 -	ld e, l
 -	pop hl
 -	ld a, [W_NUMINBOX] ; wda80
 -	dec a
 -	ld b, a
 -.asm_e817
 -	push bc
 -	push hl
 -	ld bc, $b
 -	call CopyData
 -	pop hl
 -	ld d, h
 -	ld e, l
 -	ld bc, $fff5
 -	add hl, bc
 -	pop bc
 -	dec b
 -	jr nz, .asm_e817
 -.asm_e82a
 -	ld hl, wBoxMonNicks
 -	ld a, $2
 -	ld [wd07d], a
 -	predef AskName
 -	ld a, [W_NUMINBOX] ; wda80
 -	dec a
 -	jr z, .asm_e867
 -	ld hl, wBoxMons
 -	ld bc, wBoxMon2 - wBoxMon1
 -	dec a
 -	call AddNTimes
 -	push hl
 -	ld bc, wBoxMon2 - wBoxMon1
 -	add hl, bc
 -	ld d, h
 -	ld e, l
 -	pop hl
 -	ld a, [W_NUMINBOX] ; wda80
 -	dec a
 -	ld b, a
 -.asm_e854
 -	push bc
 -	push hl
 -	ld bc, wBoxMon2 - wBoxMon1
 -	call CopyData
 -	pop hl
 -	ld d, h
 -	ld e, l
 -	ld bc, $ffdf
 -	add hl, bc
 -	pop bc
 -	dec b
 -	jr nz, .asm_e854
 -.asm_e867
 -	ld a, [wEnemyMonLevel] ; wEnemyMonLevel
 -	ld [wEnemyMonBoxLevel], a
 -	ld hl, wEnemyMon
 -	ld de, wBoxMon1
 -	ld bc, $c
 -	call CopyData
 -	ld hl, wPlayerID ; wPlayerID
 -	ld a, [hli]
 -	ld [de], a
 -	inc de
 -	ld a, [hl]
 -	ld [de], a
 -	inc de
 -	push de
 -	ld a, [W_CURENEMYLVL] ; W_CURENEMYLVL
 -	ld d, a
 -	callab CalcExperience
 -	pop de
 -	ld a, [H_NUMTOPRINT] ; $ff96 (aliases: H_MULTIPLICAND)
 -	ld [de], a
 -	inc de
 -	ld a, [$ff97]
 -	ld [de], a
 -	inc de
 -	ld a, [$ff98]
 -	ld [de], a
 -	inc de
 -	xor a
 -	ld b, $a
 -.asm_e89f
 -	ld [de], a
 -	inc de
 -	dec b
 -	jr nz, .asm_e89f
 -	ld hl, wEnemyMonDVs
 -	ld a, [hli]
 -	ld [de], a
 -	inc de
 -	ld a, [hli]
 -	ld [de], a
 -	ld hl, wEnemyMonPP ; wcffe
 -	ld b, $4
 -.asm_e8b1
 -	ld a, [hli]
 -	inc de
 -	ld [de], a
 -	dec b
 -	jr nz, .asm_e8b1
 -	ret
 -
 -; checks if the tile in front of the player is a shore or water tile
 -; used for surfing and fishing
 -; unsets carry if it is, sets carry if not
 -IsNextTileShoreOrWater: ; e8b8 (3:68b8)
 -	ld a, [W_CURMAPTILESET]
 -	ld hl, WaterTilesets
 -	ld de,1
 -	call IsInArray ; does the current map allow surfing?
 -	ret nc ; if not, return
 -	ld hl,WaterTile
 -	ld a, [W_CURMAPTILESET]
 -	cp SHIP_PORT ; Vermilion Dock tileset
 -	jr z, .skipShoreTiles ; if it's the Vermilion Dock tileset
 -	cp GYM ; eastern shore tile in Safari Zone
 -	jr z, .skipShoreTiles
 -	cp DOJO ; usual eastern shore tile
 -	jr z, .skipShoreTiles
 -	ld hl,ShoreTiles
 -.skipShoreTiles
 -	ld a,[wTileInFrontOfPlayer]
 -	ld de,$1
 -	call IsInArray
 -	ret
 -
 -; tilesets with water
 -WaterTilesets: ; e834 (3:6834)
 -	db OVERWORLD, FOREST, DOJO, GYM, SHIP, SHIP_PORT, CAVERN, FACILITY, PLATEAU
 -	db $ff ; terminator
 -
 -; shore tiles
 -ShoreTiles: ; e83e (3:683e)
 -	db $48, $32
 -WaterTile: ; e840 (3:6840)
 -	db $14
 -	db $ff ; terminator
 -
 -ReadSuperRodData: ; e8ea (3:68ea)
 -; return e = 2 if no fish on this map
 -; return e = 1 if a bite, bc = level,species
 -; return e = 0 if no bite
 -	ld a, [W_CURMAP]
 -	ld de, 3 ; each fishing group is three bytes wide
 -	ld hl, SuperRodData
 -	call IsInArray
 -	jr c, .ReadFishingGroup
 -	ld e, $2 ; $2 if no fishing groups found
 -	ret
 -
 -.ReadFishingGroup ; 0xe8f6
 -; hl points to the fishing group entry in the index
 -	inc hl ; skip map id
 -
 -	; read fishing group address
 -	ld a, [hli]
 -	ld h, [hl]
 -	ld l, a
 -
 -	ld b, [hl] ; how many mons in group
 -	inc hl ; point to data
 -	ld e, $0 ; no bite yet
 -
 -.RandomLoop ; 0xe90c
 -	call Random
 -	srl a
 -	ret c ; 50% chance of no battle
 -
 -	and %11 ; 2-bit random number
 -	cp b
 -	jr nc, .RandomLoop ; if a is greater than the number of mons, regenerate
 -
 -	; get the mon
 -	add a
 -	ld c, a
 -	ld b, $0
 -	add hl, bc
 -	ld b, [hl] ; level
 -	inc hl
 -	ld c, [hl] ; species
 -	ld e, $1 ; $1 if there's a bite
 -	ret
 -
 -INCLUDE "data/super_rod.asm"
 -
 -; reloads map view and processes sprite data
 -; for items that cause the overworld to be displayed
 -ItemUseReloadOverworldData: ; e9c5 (3:69c5)
 -	call LoadCurrentMapView
 -	jp UpdateSprites
 -
 -; creates a list at wBuffer of maps where the mon in [wd11e] can be found.
 -; this is used by the pokedex to display locations the mon can be found on the map.
 -FindWildLocationsOfMon: ; e9cb (3:69cb)
 -	ld hl, WildDataPointers
 -	ld de, wBuffer
 -	ld c, $0
 -.loop
 -	inc hl
 -	ld a, [hld]
 -	inc a
 -	jr z, .done
 -	push hl
 -	ld a, [hli]
 -	ld h, [hl]
 -	ld l, a
 -	ld a, [hli]
 -	and a
 -	call nz, CheckMapForMon ; land
 -	ld a, [hli]
 -	and a
 -	call nz, CheckMapForMon ; water
 -	pop hl
 -	inc hl
 -	inc hl
 -	inc c
 -	jr .loop
 -.done
 -	ld a, $ff ; list terminator
 -	ld [de], a
 -	ret
 -
 -CheckMapForMon: ; e9f0 (3:69f0)
 -	inc hl
 -	ld b, $a
 -.loop
 -	ld a, [wd11e]
 -	cp [hl]
 -	jr nz, .nextEntry
 -	ld a, c
 -	ld [de], a
 -	inc de
 -.nextEntry
 -	inc hl
 -	inc hl
 -	dec b
 -	jr nz, .loop
 -	dec hl
 -	ret
 +UseItem_: ; d5c7 (3:55c7) +	ld a,1 +	ld [wcd6a],a +	ld a,[wcf91]	;contains item_ID +	cp a,HM_01 +	jp nc,ItemUseTMHM +	ld hl,ItemUsePtrTable +	dec a +	add a +	ld c,a +	ld b,0 +	add hl,bc +	ld a,[hli] +	ld h,[hl] +	ld l,a +	jp [hl] + +ItemUsePtrTable: ; d5e1 (3:55e1) +	dw ItemUseBall       ; MASTER_BALL +	dw ItemUseBall       ; ULTRA_BALL +	dw ItemUseBall       ; GREAT_BALL +	dw ItemUseBall       ; POKE_BALL +	dw ItemUseTownMap    ; TOWN_MAP +	dw ItemUseBicycle    ; BICYCLE +	dw ItemUseSurfboard  ; out-of-battle Surf effect +	dw ItemUseBall       ; SAFARI_BALL +	dw ItemUsePokedex    ; POKEDEX +	dw ItemUseEvoStone   ; MOON_STONE +	dw ItemUseMedicine   ; ANTIDOTE +	dw ItemUseMedicine   ; BURN_HEAL +	dw ItemUseMedicine   ; ICE_HEAL +	dw ItemUseMedicine   ; AWAKENING +	dw ItemUseMedicine   ; PARLYZ_HEAL +	dw ItemUseMedicine   ; FULL_RESTORE +	dw ItemUseMedicine   ; MAX_POTION +	dw ItemUseMedicine   ; HYPER_POTION +	dw ItemUseMedicine   ; SUPER_POTION +	dw ItemUseMedicine   ; POTION +	dw ItemUseBait       ; BOULDERBADGE +	dw ItemUseRock       ; CASCADEBADGE +	dw UnusableItem      ; THUNDERBADGE +	dw UnusableItem      ; RAINBOWBADGE +	dw UnusableItem      ; SOULBADGE +	dw UnusableItem      ; MARSHBADGE +	dw UnusableItem      ; VOLCANOBADGE +	dw UnusableItem      ; EARTHBADGE +	dw ItemUseEscapeRope ; ESCAPE_ROPE +	dw ItemUseRepel      ; REPEL +	dw UnusableItem      ; OLD_AMBER +	dw ItemUseEvoStone   ; FIRE_STONE +	dw ItemUseEvoStone   ; THUNDER_STONE +	dw ItemUseEvoStone   ; WATER_STONE +	dw ItemUseVitamin    ; HP_UP +	dw ItemUseVitamin    ; PROTEIN +	dw ItemUseVitamin    ; IRON +	dw ItemUseVitamin    ; CARBOS +	dw ItemUseVitamin    ; CALCIUM +	dw ItemUseVitamin    ; RARE_CANDY +	dw UnusableItem      ; DOME_FOSSIL +	dw UnusableItem      ; HELIX_FOSSIL +	dw UnusableItem      ; SECRET_KEY +	dw UnusableItem +	dw UnusableItem      ; BIKE_VOUCHER +	dw ItemUseXAccuracy  ; X_ACCURACY +	dw ItemUseEvoStone   ; LEAF_STONE +	dw ItemUseCardKey    ; CARD_KEY +	dw UnusableItem      ; NUGGET +	dw UnusableItem      ; ??? PP_UP +	dw ItemUsePokedoll   ; POKE_DOLL +	dw ItemUseMedicine   ; FULL_HEAL +	dw ItemUseMedicine   ; REVIVE +	dw ItemUseMedicine   ; MAX_REVIVE +	dw ItemUseGuardSpec  ; GUARD_SPEC_ +	dw ItemUseSuperRepel ; SUPER_REPL +	dw ItemUseMaxRepel   ; MAX_REPEL +	dw ItemUseDireHit    ; DIRE_HIT +	dw UnusableItem      ; COIN +	dw ItemUseMedicine   ; FRESH_WATER +	dw ItemUseMedicine   ; SODA_POP +	dw ItemUseMedicine   ; LEMONADE +	dw UnusableItem      ; S_S__TICKET +	dw UnusableItem      ; GOLD_TEETH +	dw ItemUseXStat      ; X_ATTACK +	dw ItemUseXStat      ; X_DEFEND +	dw ItemUseXStat      ; X_SPEED +	dw ItemUseXStat      ; X_SPECIAL +	dw ItemUseCoinCase   ; COIN_CASE +	dw ItemUseOaksParcel ; OAKS_PARCEL +	dw ItemUseItemfinder ; ITEMFINDER +	dw UnusableItem      ; SILPH_SCOPE +	dw ItemUsePokeflute  ; POKE_FLUTE +	dw UnusableItem      ; LIFT_KEY +	dw UnusableItem      ; EXP__ALL +	dw OldRodCode        ; OLD_ROD +	dw GoodRodCode       ; GOOD_ROD +	dw SuperRodCode      ; SUPER_ROD +	dw ItemUsePPUp       ; PP_UP (real one) +	dw ItemUsePPRestore  ; ETHER +	dw ItemUsePPRestore  ; MAX_ETHER +	dw ItemUsePPRestore  ; ELIXER +	dw ItemUsePPRestore  ; MAX_ELIXER + +ItemUseBall: ; d687 (3:5687) +	ld a,[W_ISINBATTLE] +	and a +	jp z,ItemUseNotTime ; not in battle +	dec a +	jp nz,ThrowBallAtTrainerMon +	ld a,[W_BATTLETYPE] +	dec a +	jr z,.UseBall +	ld a,[wPartyCount]	;is Party full? +	cp a,PARTY_LENGTH +	jr nz,.UseBall +	ld a,[W_NUMINBOX]	;is Box full? +	cp a,MONS_PER_BOX +	jp z,BoxFullCannotThrowBall +.UseBall	;$56a7 +;ok, you can use a ball +	xor a +	ld [wd11c],a +	ld a,[W_BATTLETYPE] +	cp a,2		;SafariBattle +	jr nz,.skipSafariZoneCode +.safariZone +	; remove a Safari Ball from inventory +	ld hl,W_NUMSAFARIBALLS +	dec [hl] +.skipSafariZoneCode	;$56b6 +	call GoPAL_SET_CF1C +	ld a,$43 +	ld [wd11e],a +	call LoadScreenTilesFromBuffer1	;restore screenBuffer from Backup +	ld hl,ItemUseText00 +	call PrintText +	callab IsGhostBattle +	ld b,$10 +	jp z,.next12 +	ld a,[W_BATTLETYPE] +	dec a +	jr nz,.notOldManBattle +.oldManBattle +	ld hl,W_GRASSRATE +	ld de,wPlayerName +	ld bc,11 +	call CopyData ; save the player's name in the Wild Monster data (part of the Cinnabar Island Missingno glitch) +	jp .BallSuccess	;$578b +.notOldManBattle	;$56e9 +	ld a,[W_CURMAP] +	cp a,POKEMONTOWER_6 +	jr nz,.loop +	ld a,[wEnemyMonSpecies2] +	cp a,MAROWAK +	ld b,$10 +	jp z,.next12 +; if not fighting ghost Marowak, loop until a random number in the current +; pokeball's allowed range is found +.loop	;$56fa +	call Random +	ld b,a +	ld hl,wcf91 +	ld a,[hl] +	cp a,MASTER_BALL +	jp z,.BallSuccess	;$578b +	cp a,POKE_BALL +	jr z,.checkForAilments +	ld a,200 +	cp b +	jr c,.loop	;get only numbers <= 200 for Great Ball +	ld a,[hl] +	cp a,GREAT_BALL +	jr z,.checkForAilments +	ld a,150	;get only numbers <= 150 for Ultra Ball +	cp b +	jr c,.loop +.checkForAilments	;$571a +; pokemon can be caught more easily with any (primary) status ailment +; Frozen/Asleep pokemon are relatively even easier to catch +; for Frozen/Asleep pokemon, any random number from 0-24 ensures a catch. +; for the others, a random number from 0-11 ensures a catch. +	ld a,[wEnemyMonStatus]	;status ailments +	and a +	jr z,.noAilments +	and a, 1 << FRZ | SLP	;is frozen and/or asleep? +	ld c,12 +	jr z,.notFrozenOrAsleep +	ld c,25 +.notFrozenOrAsleep	;$5728 +	ld a,b +	sub c +	jp c,.BallSuccess	;$578b +	ld b,a +.noAilments	;$572e +	push bc		;save RANDOM number +	xor a +	ld [H_MULTIPLICAND],a +	ld hl,wEnemyMonMaxHP +	ld a,[hli] +	ld [H_MULTIPLICAND + 1],a +	ld a,[hl] +	ld [H_MULTIPLICAND + 2],a +	ld a,255 +	ld [H_MULTIPLIER],a +	call Multiply	; MaxHP * 255 +	ld a,[wcf91] +	cp a,GREAT_BALL +	ld a,12		;any other BallFactor +	jr nz,.next7 +	ld a,8 +.next7	;$574d +	ld [H_DIVISOR],a +	ld b,4		; number of bytes in dividend +	call Divide +	ld hl,wEnemyMonHP +	ld a,[hli] +	ld b,a +	ld a,[hl] + +; explanation: we have a 16-bit value equal to [b << 8 | a]. +; This number is divided by 4. The result is 8 bit (reg. a). +; Always bigger than zero. +	srl b +	rr a +	srl b +	rr a ; a = current HP / 4 +	and a +	jr nz,.next8 +	inc a +.next8	;$5766 +	ld [H_DIVISOR],a +	ld b,4 +	call Divide	; ((MaxHP * 255) / BallFactor) / (CurHP / 4) +	ld a,[H_QUOTIENT + 2] +	and a +	jr z,.next9 +	ld a,255 +	ld [H_QUOTIENT + 3],a +.next9	;$5776 +	pop bc +	ld a,[wEnemyMonCatchRate]	;enemy: Catch Rate +	cp b +	jr c,.next10 +	ld a,[H_QUOTIENT + 2] +	and a +	jr nz,.BallSuccess ; if ((MaxHP * 255) / BallFactor) / (CurHP / 4) > 0x255, automatic success +	call Random +	ld b,a +	ld a,[H_QUOTIENT + 3] +	cp b +	jr c,.next10 +.BallSuccess	;$578b +	jr .BallSuccess2 +.next10	;$578d +	ld a,[H_QUOTIENT + 3] +	ld [wd11e],a +	xor a +	ld [H_MULTIPLICAND],a +	ld [H_MULTIPLICAND + 1],a +	ld a,[wEnemyMonCatchRate]	;enemy: Catch Rate +	ld [H_MULTIPLICAND + 2],a +	ld a,100 +	ld [H_MULTIPLIER],a +	call Multiply	; CatchRate * 100 +	ld a,[wcf91] +	ld b,255 +	cp a,POKE_BALL +	jr z,.next11 +	ld b,200 +	cp a,GREAT_BALL +	jr z,.next11 +	ld b,150 +	cp a,ULTRA_BALL +	jr z,.next11 +.next11	;$57b8 +	ld a,b +	ld [H_DIVISOR],a +	ld b,4 +	call Divide +	ld a,[H_QUOTIENT + 2] +	and a +	ld b,$63 +	jr nz,.next12 +	ld a,[wd11e] +	ld [H_MULTIPLIER],a +	call Multiply +	ld a,255 +	ld [H_DIVISOR],a +	ld b,4 +	call Divide +	ld a,[wEnemyMonStatus]	;status ailments +	and a +	jr z,.next13 +	and a, 1 << FRZ | SLP +	ld b,5 +	jr z,.next14 +	ld b,10 +.next14	;$57e6 +	ld a,[H_QUOTIENT + 3] +	add b +	ld [H_QUOTIENT + 3],a +.next13	;$57eb +	ld a,[H_QUOTIENT + 3] +	cp a,10 +	ld b,$20 +	jr c,.next12 +	cp a,30 +	ld b,$61 +	jr c,.next12 +	cp a,70 +	ld b,$62 +	jr c,.next12 +	ld b,$63 +.next12	;$5801 +	ld a,b +	ld [wd11e],a +.BallSuccess2	;$5805 +	ld c,20 +	call DelayFrames +	ld a,TOSS_ANIM +	ld [W_ANIMATIONID],a +	xor a +	ld [$fff3],a +	ld [wAnimationType],a +	ld [wDamageMultipliers],a +	ld a,[wWhichPokemon] +	push af +	ld a,[wcf91] +	push af +	predef MoveAnimation +	pop af +	ld [wcf91],a +	pop af +	ld [wWhichPokemon],a +	ld a,[wd11e] +	cp a,$10 +	ld hl,ItemUseBallText00 +	jp z,.printText0 +	cp a,$20 +	ld hl,ItemUseBallText01 +	jp z,.printText0 +	cp a,$61 +	ld hl,ItemUseBallText02 +	jp z,.printText0 +	cp a,$62 +	ld hl,ItemUseBallText03 +	jp z,.printText0 +	cp a,$63 +	ld hl,ItemUseBallText04 +	jp z,.printText0 +	ld hl,wEnemyMonHP	;current HP +	ld a,[hli] +	push af +	ld a,[hli] +	push af		;backup currentHP... +	inc hl +	ld a,[hl] +	push af		;...and status ailments +	push hl +	ld hl,W_ENEMYBATTSTATUS3 +	bit Transformed,[hl] +	jr z,.next15 +	ld a,$4c +	ld [wEnemyMonSpecies2],a +	jr .next16 +.next15	;$5871 +	set Transformed,[hl] +	ld hl,wcceb +	ld a,[wEnemyMonDVs] +	ld [hli],a +	ld a,[wEnemyMonDVs + 1] +	ld [hl],a +.next16	;$587e +	ld a,[wcf91] +	push af +	ld a,[wEnemyMonSpecies2] +	ld [wcf91],a +	ld a,[wEnemyMonLevel] +	ld [W_CURENEMYLVL],a +	callab LoadEnemyMonData +	pop af +	ld [wcf91],a +	pop hl +	pop af +	ld [hld],a +	dec hl +	pop af +	ld [hld],a +	pop af +	ld [hl],a +	ld a,[wEnemyMonSpecies]	;enemy +	ld [wd11c],a +	ld [wcf91],a +	ld [wd11e],a +	ld a,[W_BATTLETYPE] +	dec a +	jr z,.printText1 +	ld hl,ItemUseBallText05 +	call PrintText +	predef IndexToPokedex +	ld a,[wd11e] +	dec a +	ld c,a +	ld b,2 +	ld hl,wPokedexOwned	;Dex_own_flags (pokemon) +	predef FlagActionPredef +	ld a,c +	push af +	ld a,[wd11e] +	dec a +	ld c,a +	ld b,1 +	predef FlagActionPredef +	pop af +	and a +	jr nz,.checkParty +	ld hl,ItemUseBallText06 +	call PrintText +	call ClearSprites +	ld a,[wEnemyMonSpecies]	;caught mon_ID +	ld [wd11e],a +	predef ShowPokedexData +.checkParty	;$58f4 +	ld a,[wPartyCount] +	cp a,PARTY_LENGTH		;is party full? +	jr z,.sendToBox +	xor a +	ld [wcc49],a +	call ClearSprites +	call AddPartyMon	;add mon to Party +	jr .End +.sendToBox	;$5907 +	call ClearSprites +	call SendNewMonToBox +	ld hl,ItemUseBallText07 +	ld a,[wd7f1] +	bit 0,a		;already met Bill? +	jr nz,.sendToBox2 +	ld hl,ItemUseBallText08 +.sendToBox2	;$591a +	call PrintText +	jr .End +.printText1	;$591f +	ld hl,ItemUseBallText05 +.printText0	;$5922 +	call PrintText +	call ClearSprites +.End	;$5928 +	ld a,[W_BATTLETYPE] +	and a +	ret nz +	ld hl,wNumBagItems +	inc a +	ld [wcf96],a +	jp RemoveItemFromInventory	;remove ITEM (XXX) +ItemUseBallText00: ; d937 (3:5937) +;"It dodged the thrown ball!" +;"This pokemon can't be caught" +	TX_FAR _ItemUseBallText00 +	db "@" +ItemUseBallText01: ; d93c (3:593c) +;"You missed the pokemon!" +	TX_FAR _ItemUseBallText01 +	db "@" +ItemUseBallText02: ; d941 (3:5941) +;"Darn! The pokemon broke free!" +	TX_FAR _ItemUseBallText02 +	db "@" +ItemUseBallText03: ; d946 (3:5946) +;"Aww! It appeared to be caught!" +	TX_FAR _ItemUseBallText03 +	db "@" +ItemUseBallText04: ; d94b (3:594b) +;"Shoot! It was so close too!" +	TX_FAR _ItemUseBallText04 +	db "@" +ItemUseBallText05: ; d950 (3:5950) +;"All right! {MonName} was caught!" +;play sound +	TX_FAR _ItemUseBallText05 +	db $12,$06 +	db "@" +ItemUseBallText07: ; d957 (3:5957) +;"X was transferred to Bill's PC" +	TX_FAR _ItemUseBallText07 +	db "@" +ItemUseBallText08: ; d95c (3:595c) +;"X was transferred to someone's PC" +	TX_FAR _ItemUseBallText08 +	db "@" + +ItemUseBallText06: ; d961 (3:5961) +;"New DEX data will be added..." +;play sound +	TX_FAR _ItemUseBallText06 +	db $13,$06 +	db "@" + +ItemUseTownMap: ; d968 (3:5968) +	ld a,[W_ISINBATTLE] +	and a +	jp nz,ItemUseNotTime +	ld b, BANK(DisplayTownMap) +	ld hl, DisplayTownMap +	jp Bankswitch ; display Town Map + +ItemUseBicycle: ; d977 (3:5977) +	ld a,[W_ISINBATTLE] +	and a +	jp nz,ItemUseNotTime +	ld a,[wWalkBikeSurfState] +	ld [wWalkBikeSurfStateCopy],a +	cp a,2 ; is the player surfing? +	jp z,ItemUseNotTime +	dec a ; is player already bicycling? +	jr nz,.tryToGetOnBike +.getOffBike +	call ItemUseReloadOverworldData +	xor a +	ld [wWalkBikeSurfState],a ; change player state to walking +	call PlayDefaultMusic ; play walking music +	ld hl,GotOffBicycleText +	jr .printText +.tryToGetOnBike +	call IsBikeRidingAllowed +	jp nc,NoCyclingAllowedHere +	call ItemUseReloadOverworldData +	xor a ; no keys pressed +	ld [hJoyHeld],a ; current joypad state +	inc a +	ld [wWalkBikeSurfState],a ; change player state to bicycling +	ld hl,GotOnBicycleText +	call PlayDefaultMusic ; play bike riding music +.printText +	jp PrintText + +; used for Surf out-of-battle effect +ItemUseSurfboard: ; d9b4 (3:59b4) +	ld a,[wWalkBikeSurfState] +	ld [wWalkBikeSurfStateCopy],a +	cp a,2 ; is the player already surfing? +	jr z,.tryToStopSurfing +.tryToSurf +	call IsNextTileShoreOrWater +	jp c,SurfingAttemptFailed +	ld hl,TilePairCollisionsWater +	call CheckForTilePairCollisions +	jp c,SurfingAttemptFailed +.surf +	call .makePlayerMoveForward +	ld hl,wd730 +	set 7,[hl] +	ld a,2 +	ld [wWalkBikeSurfState],a ; change player state to surfing +	call PlayDefaultMusic ; play surfing music +	ld hl,SurfingGotOnText +	jp PrintText +.tryToStopSurfing +	xor a +	ld [$ff8c],a +	ld d,16 ; talking range in pixels (normal range) +	call IsSpriteInFrontOfPlayer2 +	res 7,[hl] +	ld a,[$ff8c] +	and a ; is there a sprite in the way? +	jr nz,.cannotStopSurfing +	ld hl,TilePairCollisionsWater +	call CheckForTilePairCollisions +	jr c,.cannotStopSurfing +	ld hl,W_TILESETCOLLISIONPTR ; pointer to list of passable tiles +	ld a,[hli] +	ld h,[hl] +	ld l,a ; hl now points to passable tiles +	ld a,[wTileInFrontOfPlayer] ; tile in front of the player +	ld b,a +.passableTileLoop +	ld a,[hli] +	cp b +	jr z,.stopSurfing +	cp a,$ff +	jr nz,.passableTileLoop +.cannotStopSurfing +	ld hl,SurfingNoPlaceToGetOffText +	jp PrintText +.stopSurfing +	call .makePlayerMoveForward +	ld hl,wd730 +	set 7,[hl] +	xor a +	ld [wWalkBikeSurfState],a ; change player state to walking +	dec a +	ld [wJoyIgnore],a +	call PlayDefaultMusic ; play walking music +	jp LoadWalkingPlayerSpriteGraphics +; uses a simulated button press to make the player move forward +.makePlayerMoveForward +	ld a,[wd52a] ; direction the player is going +	bit 3,a +	ld b,D_UP +	jr nz,.storeSimulatedButtonPress +	bit 2,a +	ld b,D_DOWN +	jr nz,.storeSimulatedButtonPress +	bit 1,a +	ld b,D_LEFT +	jr nz,.storeSimulatedButtonPress +	ld b,D_RIGHT +.storeSimulatedButtonPress +	ld a,b +	ld [wSimulatedJoypadStatesEnd],a +	xor a +	ld [wWastedByteCD39],a +	inc a +	ld [wSimulatedJoypadStatesIndex],a +	ret + +SurfingGotOnText: ; da4c (3:5a4c) +	TX_FAR _SurfingGotOnText +	db "@" + +SurfingNoPlaceToGetOffText: ; da51 (3:5a51) +	TX_FAR _SurfingNoPlaceToGetOffText +	db "@" + +ItemUsePokedex: ; da56 (3:5a56) +	predef_jump ShowPokedexMenu + +ItemUseEvoStone: ; da5b (3:5a5b) +	ld a,[W_ISINBATTLE] +	and a +	jp nz,ItemUseNotTime +	ld a,[wWhichPokemon] +	push af +	ld a,[wcf91] +	ld [wd156],a +	push af +	ld a,$05 ; evolution stone party menu +	ld [wd07d],a +	ld a,$ff +	ld [wUpdateSpritesEnabled],a +	call DisplayPartyMenu +	pop bc +	jr c,.canceledItemUse +	ld a,b +	ld [wcf91],a +	ld a,$01 +	ld [wccd4],a +	ld a,(SFX_02_3e - SFX_Headers_02) / 3 +	call PlaySoundWaitForCurrent ; play sound +	call WaitForSoundToFinish ; wait for sound to end +	callab TryEvolvingMon ; try to evolve pokemon +	ld a,[wd121] +	and a +	jr z,.noEffect +	pop af +	ld [wWhichPokemon],a +	ld hl,wNumBagItems +	ld a,1 ; remove 1 stone +	ld [wcf96],a +	jp RemoveItemFromInventory +.noEffect +	call ItemUseNoEffect +.canceledItemUse +	xor a +	ld [wcd6a],a +	pop af +	ret + +ItemUseVitamin: ; dab4 (3:5ab4) +	ld a,[W_ISINBATTLE] +	and a +	jp nz,ItemUseNotTime + +ItemUseMedicine: ; dabb (3:5abb) +	ld a,[wPartyCount] +	and a +	jp z,.emptyParty +	ld a,[wWhichPokemon] +	push af +	ld a,[wcf91] +	push af +	ld a,$01 +	ld [wd07d],a ; item use party menu +	ld a,$ff +	ld [wUpdateSpritesEnabled],a +	ld a,[wd152] +	and a ; using Softboiled? +	jr z,.notUsingSoftboiled +; if using softboiled +	call GoBackToPartyMenu +	jr .getPartyMonDataAddress +.emptyParty +	ld hl,.emptyPartyText +	xor a +	ld [wcd6a],a ; item use failed +	jp PrintText +.emptyPartyText +	text "You don't have" +	line "any #MON!" +	prompt +.notUsingSoftboiled +	call DisplayPartyMenu +.getPartyMonDataAddress +	jp c,.canceledItemUse +	ld hl,wPartyMons +	ld bc,wPartyMon2 - wPartyMon1 +	ld a,[wWhichPokemon] +	call AddNTimes +	ld a,[wWhichPokemon] +	ld [wcf06],a +	ld d,a +	ld a,[wcf91] +	ld e,a +	ld [wd0b5],a +	pop af +	ld [wcf91],a +	pop af +	ld [wWhichPokemon],a +	ld a,[wd152] +	and a ; using Softboiled? +	jr z,.checkItemType +; if using softboiled +	ld a,[wWhichPokemon] +	cp d ; is the pokemon trying to use softboiled on itself? +	jr z,ItemUseMedicine ; if so, force another choice +.checkItemType +	ld a,[wcf91] +	cp a,REVIVE +	jr nc,.healHP ; if it's a Revive or Max Revive +	cp a,FULL_HEAL +	jr z,.cureStatusAilment ; if it's a Full Heal +	cp a,HP_UP +	jp nc,.useVitamin ; if it's a vitamin or Rare Candy +	cp a,FULL_RESTORE +	jr nc,.healHP ; if it's a Full Restore or one of the potions +; fall through if it's one of the status-specifc healing items +.cureStatusAilment +	ld bc,4 +	add hl,bc ; hl now points to status +	ld a,[wcf91] +	ld bc,$f008 +	cp a,ANTIDOTE +	jr z,.checkMonStatus +	ld bc,$f110 +	cp a,BURN_HEAL +	jr z,.checkMonStatus +	ld bc,$f220 +	cp a,ICE_HEAL +	jr z,.checkMonStatus +	ld bc,$f307 +	cp a,AWAKENING +	jr z,.checkMonStatus +	ld bc,$f440 +	cp a,PARLYZ_HEAL +	jr z,.checkMonStatus +	ld bc,$f6ff ; Full Heal +.checkMonStatus +	ld a,[hl] ; pokemon's status +	and c ; does the pokemon have a status ailment the item can cure? +	jp z,.healingItemNoEffect +; if the pokemon has a status the item can heal +	xor a +	ld [hl],a ; remove the status ailment in the party data +	ld a,b +	ld [wd07d],a ; the message to display for the item used +	ld a,[wPlayerMonNumber] +	cp d ; is pokemon the item was used on active in battle? +	jp nz,.doneHealing +; if it is active in battle +	xor a +	ld [wBattleMonStatus],a ; remove the status ailment in the in-battle pokemon data +	push hl +	ld hl,W_PLAYERBATTSTATUS3 +	res BadlyPoisoned,[hl] ; heal Toxic status +	pop hl +	ld bc,30 +	add hl,bc ; hl now points to party stats +	ld de,wBattleMonMaxHP +	ld bc,10 +	call CopyData ; copy party stats to in-battle stat data +	predef DoubleOrHalveSelectedStats +	jp .doneHealing +.healHP +	inc hl ; hl = address of current HP +	ld a,[hli] +	ld b,a +	ld [wHPBarOldHP+1],a +	ld a,[hl] +	ld c,a +	ld [wHPBarOldHP],a ; current HP stored at wHPBarOldHP (2 bytes, big-endian) +	or b +	jr nz,.notFainted +.fainted +	ld a,[wcf91] +	cp a,REVIVE +	jr z,.updateInBattleFaintedData +	cp a,MAX_REVIVE +	jr z,.updateInBattleFaintedData +	jp .healingItemNoEffect +.updateInBattleFaintedData +	ld a,[W_ISINBATTLE] +	and a +	jr z,.compareCurrentHPToMaxHP +	push hl +	push de +	push bc +	ld a,[wcf06] +	ld c,a +	ld hl,wPartyFoughtCurrentEnemyFlags +	ld b,$02 +	predef FlagActionPredef +	ld a,c +	and a +	jr z,.next +	ld a,[wcf06] +	ld c,a +	ld hl,wPartyGainExpFlags +	ld b,$01 +	predef FlagActionPredef +.next +	pop bc +	pop de +	pop hl +	jr .compareCurrentHPToMaxHP +.notFainted +	ld a,[wcf91] +	cp a,REVIVE +	jp z,.healingItemNoEffect +	cp a,MAX_REVIVE +	jp z,.healingItemNoEffect +.compareCurrentHPToMaxHP +	push hl +	push bc +	ld bc,32 +	add hl,bc ; hl now points to max HP +	pop bc +	ld a,[hli] +	cp b +	jr nz,.skipComparingLSB ; no need to compare the LSB's if the MSB's don't match +	ld a,[hl] +	cp c +.skipComparingLSB +	pop hl +	jr nz,.notFullHP +.fullHP ; if the pokemon's current HP equals its max HP +	ld a,[wcf91] +	cp a,FULL_RESTORE +	jp nz,.healingItemNoEffect +	inc hl +	inc hl +	ld a,[hld] ; status ailment +	and a ; does the pokemon have a status ailment? +	jp z,.healingItemNoEffect +	ld a,FULL_HEAL +	ld [wcf91],a +	dec hl +	dec hl +	dec hl +	jp .cureStatusAilment +.notFullHP ; if the pokemon's current HP doesn't equal its max HP +	xor a +	ld [wLowHealthAlarm],a ;disable low health alarm +	ld [wc02a],a +	push hl +	push de +	ld bc,32 +	add hl,bc ; hl now points to max HP +	ld a,[hli] +	ld [wHPBarMaxHP+1],a +	ld a,[hl] +	ld [wHPBarMaxHP],a ; max HP stored at wHPBarMaxHP (2 bytes, big-endian) +	ld a,[wd152] +	and a ; using Softboiled? +	jp z,.notUsingSoftboiled2 +; if using softboiled +	ld hl,wHPBarMaxHP +	ld a,[hli] +	push af +	ld a,[hli] +	push af +	ld a,[hli] +	push af +	ld a,[hl] +	push af +	ld hl,wPartyMon1MaxHP +	ld a,[wWhichPokemon] +	ld bc,wPartyMon2 - wPartyMon1 +	call AddNTimes +	ld a,[hli] +	ld [wHPBarMaxHP + 1],a +	ld [H_DIVIDEND],a +	ld a,[hl] +	ld [wHPBarMaxHP],a +	ld [H_DIVIDEND + 1],a +	ld a,5 +	ld [H_DIVISOR],a +	ld b,2 ; number of bytes +	call Divide ; get 1/5 of max HP of pokemon that used Softboiled +	ld bc,wPartyMon1HP - wPartyMon1MaxHP +	add hl,bc ; hl now points to LSB of current HP of pokemon that used Softboiled +; subtract 1/5 of max HP from current HP of pokemon that used Softboiled +	ld a,[H_QUOTIENT + 3] +	push af +	ld b,a +	ld a,[hl] +	ld [wHPBarOldHP],a +	sub b +	ld [hld],a +	ld [wHPBarNewHP],a +	ld a,[H_QUOTIENT + 2] +	ld b,a +	ld a,[hl] +	ld [wHPBarOldHP+1],a +	sbc b +	ld [hl],a +	ld [wHPBarNewHP+1],a +	hlCoord 4, 1 +	ld a,[wWhichPokemon] +	ld bc,2 * 20 +	call AddNTimes ; calculate coordinates of HP bar of pokemon that used Softboiled +	ld a,(SFX_02_3d - SFX_Headers_02) / 3 +	call PlaySoundWaitForCurrent ; play sound +	ld a,[hFlags_0xFFF6] +	set 0,a +	ld [hFlags_0xFFF6],a +	ld a,$02 +	ld [wHPBarType],a +	predef UpdateHPBar2 ; animate HP bar decrease of pokemon that used Softboiled +	ld a,[hFlags_0xFFF6] +	res 0,a +	ld [hFlags_0xFFF6],a +	pop af +	ld b,a ; store heal amount (1/5 of max HP) +	ld hl,wHPBarOldHP + 1 +	pop af +	ld [hld],a +	pop af +	ld [hld],a +	pop af +	ld [hld],a +	pop af +	ld [hl],a +	jr .addHealAmount +.notUsingSoftboiled2 +	ld a,[wcf91] +	cp a,SODA_POP +	ld b,60 ; Soda Pop heal amount +	jr z,.addHealAmount +	ld b,80 ; Lemonade heal amount +	jr nc,.addHealAmount +	cp a,FRESH_WATER +	ld b,50 ; Fresh Water heal amount +	jr z,.addHealAmount +	cp a,SUPER_POTION +	ld b,200 ; Hyper Potion heal amount +	jr c,.addHealAmount +	ld b,50 ; Super Potion heal amount +	jr z,.addHealAmount +	ld b,20 ; Potion heal amount +.addHealAmount +	pop de +	pop hl +	ld a,[hl] +	add b +	ld [hld],a +	ld [wHPBarNewHP],a +	ld a,[hl] +	ld [wHPBarNewHP+1],a +	jr nc,.noCarry +	inc [hl] +	ld a,[hl] +	ld [wHPBarNewHP + 1],a +.noCarry +	push de +	inc hl +	ld d,h +	ld e,l ; de now points to current HP +	ld hl,33 +	add hl,de ; hl now points to max HP +	ld a,[wcf91] +	cp a,REVIVE +	jr z,.setCurrentHPToHalfMaxHP +	ld a,[hld] +	ld b,a +	ld a,[de] +	sub b +	dec de +	ld b,[hl] +	ld a,[de] +	sbc b +	jr nc,.setCurrentHPToMaxHp ; if current HP exceeds max HP after healing +	ld a,[wcf91] +	cp a,HYPER_POTION +	jr c,.setCurrentHPToMaxHp ; if using a Full Restore or Max Potion +	cp a,MAX_REVIVE +	jr z,.setCurrentHPToMaxHp ; if using a Max Revive +	jr .updateInBattleData +.setCurrentHPToHalfMaxHP +	dec hl +	dec de +	ld a,[hli] +	srl a +	ld [de],a +	ld [wHPBarNewHP+1],a +	ld a,[hl] +	rr a +	inc de +	ld [de],a +	ld [wHPBarNewHP],a +	dec de +	jr .doneHealingPartyHP +.setCurrentHPToMaxHp +	ld a,[hli] +	ld [de],a +	ld [wHPBarNewHP+1],a +	inc de +	ld a,[hl] +	ld [de],a +	ld [wHPBarNewHP],a +	dec de +.doneHealingPartyHP ; done updating the pokemon's current HP in the party data structure +	ld a,[wcf91] +	cp a,FULL_RESTORE +	jr nz,.updateInBattleData +	ld bc,-31 +	add hl,bc +	xor a +	ld [hl],a ; remove the status ailment in the party data +.updateInBattleData +	ld h,d +	ld l,e +	pop de +	ld a,[wPlayerMonNumber] +	cp d ; is pokemon the item was used on active in battle? +	jr nz,.calculateHPBarCoords +; copy party HP to in-battle HP +	ld a,[hli] +	ld [wBattleMonHP],a +	ld a,[hld] +	ld [wBattleMonHP + 1],a +	ld a,[wcf91] +	cp a,FULL_RESTORE +	jr nz,.calculateHPBarCoords +	xor a +	ld [wBattleMonStatus],a ; remove the status ailment in the in-battle pokemon data +.calculateHPBarCoords +	ld hl,wOAMBuffer + $90 +	ld bc,2 * 20 +	inc d +.calculateHPBarCoordsLoop +	add hl,bc +	dec d +	jr nz,.calculateHPBarCoordsLoop +	jr .doneHealing +.healingItemNoEffect +	call ItemUseNoEffect +	jp .done +.doneHealing +	ld a,[wd152] +	and a ; using Softboiled? +	jr nz,.skipRemovingItem ; no item to remove if using Softboiled +	push hl +	call RemoveUsedItem +	pop hl +.skipRemovingItem +	ld a,[wcf91] +	cp a,FULL_RESTORE +	jr c,.playStatusAilmentCuringSound +	cp a,FULL_HEAL +	jr z,.playStatusAilmentCuringSound +	ld a,(SFX_02_3d - SFX_Headers_02) / 3 ; HP healing sound +	call PlaySoundWaitForCurrent ; play sound +	ld a,[hFlags_0xFFF6] +	set 0,a +	ld [hFlags_0xFFF6],a +	ld a,$02 +	ld [wHPBarType],a +	predef UpdateHPBar2 ; animate the HP bar lengthening +	ld a,[hFlags_0xFFF6] +	res 0,a +	ld [hFlags_0xFFF6],a +	ld a,$f7 ; revived message +	ld [wd07d],a +	ld a,[wcf91] +	cp a,REVIVE +	jr z,.showHealingItemMessage +	cp a,MAX_REVIVE +	jr z,.showHealingItemMessage +	ld a,$f5 ; standard HP healed message +	ld [wd07d],a +	jr .showHealingItemMessage +.playStatusAilmentCuringSound +	ld a,(SFX_02_3e - SFX_Headers_02) / 3 ; status ailment curing sound +	call PlaySoundWaitForCurrent +.showHealingItemMessage +	xor a +	ld [H_AUTOBGTRANSFERENABLED],a +	call ClearScreen +	dec a +	ld [wUpdateSpritesEnabled],a +	call RedrawPartyMenu ; redraws the party menu and displays the message +	ld a,1 +	ld [H_AUTOBGTRANSFERENABLED],a +	ld c,50 +	call DelayFrames +	call WaitForTextScrollButtonPress +	jr .done +.canceledItemUse +	xor a +	ld [wcd6a],a ; item use failed +	pop af +	pop af +.done +	ld a,[wd152] +	and a ; using Softboiled? +	ret nz ; if so, return +	call GBPalWhiteOut +	call z,GoPAL_SET_CF1C +	ld a,[W_ISINBATTLE] +	and a +	ret nz +	jp ReloadMapData +.useVitamin +	push hl +	ld a,[hl] +	ld [wd0b5],a +	ld [wd11e],a +	ld bc,33 +	add hl,bc ; hl now points to level +	ld a,[hl] ; a = level +	ld [W_CURENEMYLVL],a ; store level +	call GetMonHeader +	push de +	ld a,d +	ld hl,wPartyMonNicks +	call GetPartyMonName +	pop de +	pop hl +	ld a,[wcf91] +	cp a,RARE_CANDY +	jp z,.useRareCandy +	push hl +	sub a,HP_UP +	add a +	ld bc,17 +	add hl,bc +	add l +	ld l,a +	jr nc,.noCarry2 +	inc h +.noCarry2 +	ld a,10 +	ld b,a +	ld a,[hl] ; a = MSB of stat experience of the appropriate stat +	cp a,100 ; is there already at least 25600 (256 * 100) stat experience? +	jr nc,.vitaminNoEffect ; if so, vitamins can't add any more +	add b ; add 2560 (256 * 10) stat experience +	jr nc,.noCarry3 ; a carry should be impossible here, so this will always jump +	ld a,255 +.noCarry3 +	ld [hl],a +	pop hl +	call .recalculateStats +	ld hl,VitaminText +	ld a,[wcf91] +	sub a,HP_UP - 1 +	ld c,a +.statNameLoop ; loop to get the address of the name of the stat the vitamin increases +	dec c +	jr z,.gotStatName +.statNameInnerLoop +	ld a,[hli] +	ld b,a +	ld a,$50 +	cp b +	jr nz,.statNameInnerLoop +	jr .statNameLoop +.gotStatName +	ld de,wcf4b +	ld bc,10 +	call CopyData ; copy the stat's name to wcf4b +	ld a,(SFX_02_3e - SFX_Headers_02) / 3 +	call PlaySound ; play sound +	ld hl,VitaminStatRoseText +	call PrintText +	jp RemoveUsedItem +.vitaminNoEffect +	pop hl +	ld hl,VitaminNoEffectText +	call PrintText +	jp GBPalWhiteOut +.recalculateStats +	ld bc,34 +	add hl,bc +	ld d,h +	ld e,l ; de now points to stats +	ld bc,-18 +	add hl,bc ; hl now points to byte 3 of experience +	ld b,1 +	jp CalcStats ; recalculate stats +.useRareCandy +	push hl +	ld bc,33 +	add hl,bc ; hl now points to level +	ld a,[hl] ; a = level +	cp a, MAX_LEVEL +	jr z,.vitaminNoEffect ; can't raise level above 100 +	inc a +	ld [hl],a ; store incremented level +	ld [W_CURENEMYLVL],a +	push hl +	push de +	ld d,a +	callab CalcExperience ; calculate experience for next level and store it at $ff96 +	pop de +	pop hl +	ld bc,-19 +	add hl,bc ; hl now points to experience +; update experience to minimum for new level +	ld a,[$ff96] +	ld [hli],a +	ld a,[$ff97] +	ld [hli],a +	ld a,[$ff98] +	ld [hl],a +	pop hl +	ld a,[wWhichPokemon] +	push af +	ld a,[wcf91] +	push af +	push de +	push hl +	ld bc,34 +	add hl,bc ; hl now points to MSB of max HP +	ld a,[hli] +	ld b,a +	ld c,[hl] +	pop hl +	push bc +	push hl +	call .recalculateStats +	pop hl +	ld bc,35 ; hl now points to LSB of max HP +	add hl,bc +	pop bc +	ld a,[hld] +	sub c +	ld c,a +	ld a,[hl] +	sbc b +	ld b,a ; bc = the amount of max HP gained from leveling up +; add the amount gained to the current HP +	ld de,-32 +	add hl,de ; hl now points to MSB of current HP +	ld a,[hl] +	add c +	ld [hld],a +	ld a,[hl] +	adc b +	ld [hl],a +	ld a,$f8 ; level up message +	ld [wd07d],a +	call RedrawPartyMenu +	pop de +	ld a,d +	ld [wWhichPokemon],a +	ld a,e +	ld [wd11e],a +	xor a +	ld [wcc49],a ; load from player's party +	call LoadMonData +	ld d,$01 +	callab PrintStatsBox ; display new stats text box +	call WaitForTextScrollButtonPress ; wait for button press +	xor a +	ld [wcc49],a +	predef LearnMoveFromLevelUp ; learn level up move, if any +	xor a +	ld [wccd4],a +	callab TryEvolvingMon ; evolve pokemon, if appropriate +	ld a,$01 +	ld [wUpdateSpritesEnabled],a +	pop af +	ld [wcf91],a +	pop af +	ld [wWhichPokemon],a +	jp RemoveUsedItem + +VitaminStatRoseText: ; df24 (3:5f24) +	TX_FAR _VitaminStatRoseText +	db "@" + +VitaminNoEffectText: ; df29 (3:5f29) +	TX_FAR _VitaminNoEffectText +	db "@" + +VitaminText: ; df2e (3:5f2e) +	db "HEALTH@" +	db "ATTACK@" +	db "DEFENSE@" +	db "SPEED@" +	db "SPECIAL@" + +ItemUseBait: ; df52 (3:5f52) +	ld hl,ThrewBaitText +	call PrintText +	ld hl,wEnemyMonCatchRate ; catch rate +	srl [hl] ; halve catch rate +	ld a,BAIT_ANIM +	ld hl,wSafariBaitFactor ; bait factor +	ld de,wSafariEscapeFactor ; escape factor +	jr BaitRockCommon + +ItemUseRock: ; df67 (3:5f67) +	ld hl,ThrewRockText +	call PrintText +	ld hl,wEnemyMonCatchRate ; catch rate +	ld a,[hl] +	add a ; double catch rate +	jr nc,.noCarry +	ld a,$ff +.noCarry +	ld [hl],a +	ld a,ROCK_ANIM +	ld hl,wSafariEscapeFactor ; escape factor +	ld de,wSafariBaitFactor ; bait factor + +BaitRockCommon: ; df7f (3:5f7f) +	ld [W_ANIMATIONID],a +	xor a +	ld [wcc5b],a +	ld [H_WHOSETURN],a +	ld [de],a ; zero escape factor (for bait), zero bait factor (for rock) +.randomLoop ; loop until a random number less than 5 is generated +	call Random +	and a,7 +	cp a,5 +	jr nc,.randomLoop +	inc a ; increment the random number, giving a range from 1 to 5 inclusive +	ld b,a +	ld a,[hl] +	add b ; increase bait factor (for bait), increase escape factor (for rock) +	jr nc,.noCarry +	ld a,$ff +.noCarry +	ld [hl],a +	predef MoveAnimation ; do animation +	ld c,70 +	jp DelayFrames + +ThrewBaitText: ; dfa5 (3:5fa5) +	TX_FAR _ThrewBaitText +	db "@" + +ThrewRockText: ; dfaa (3:5faa) +	TX_FAR _ThrewRockText +	db "@" + +; also used for Dig out-of-battle effect +ItemUseEscapeRope: ; dfaf (3:5faf) +	ld a,[W_ISINBATTLE] +	and a +	jr nz,.notUsable +	ld a,[W_CURMAP] +	cp a,AGATHAS_ROOM +	jr z,.notUsable +	ld a,[W_CURMAPTILESET] +	ld b,a +	ld hl,EscapeRopeTilesets +.loop +	ld a,[hli] +	cp a,$ff +	jr z,.notUsable +	cp b +	jr nz,.loop +	ld hl,wd732 +	set 3,[hl] +	set 6,[hl] +	ld hl,wd72e +	res 4,[hl] +	ld hl,wd790 +	res 7,[hl] ; unset Safari Zone bit +	xor a +	ld [W_NUMSAFARIBALLS],a +	ld [W_SAFARIZONEENTRANCECURSCRIPT],a +	inc a +	ld [wEscapedFromBattle],a +	ld [wcd6a],a ; item used +	ld a,[wd152] +	and a ; using Dig? +	ret nz ; if so, return +	call ItemUseReloadOverworldData +	ld c,30 +	call DelayFrames +	jp RemoveUsedItem +.notUsable +	jp ItemUseNotTime + +EscapeRopeTilesets: ; dffd (3:5ffd) +	db FOREST, CEMETERY, CAVERN, FACILITY, INTERIOR +	db $ff ; terminator + +ItemUseRepel: ; e003 (3:6003) +	ld b,100 + +ItemUseRepelCommon: ; e005 (3:6005) +	ld a,[W_ISINBATTLE] +	and a +	jp nz,ItemUseNotTime +	ld a,b +	ld [wRepelRemainingSteps],a +	jp PrintItemUseTextAndRemoveItem + +; handles X Accuracy item +ItemUseXAccuracy: ; e013 (3:6013) +	ld a,[W_ISINBATTLE] +	and a +	jp z,ItemUseNotTime +	ld hl,W_PLAYERBATTSTATUS2 +	set UsingXAccuracy,[hl] ; X Accuracy bit +	jp PrintItemUseTextAndRemoveItem + +; This function is bugged and never works. It always jumps to ItemUseNotTime. +; The Card Key is handled in a different way. +ItemUseCardKey: ; e022 (3:6022) +	xor a +	ld [wd71f],a +	call GetTileAndCoordsInFrontOfPlayer +	ld a,[GetTileAndCoordsInFrontOfPlayer] ; $4586 +	cp a,$18 +	jr nz,.next0 +	ld hl,CardKeyTable1 +	jr .next1 +.next0 +	cp a,$24 +	jr nz,.next2 +	ld hl,CardKeyTable2 +	jr .next1 +.next2 +	cp a,$5e +	jp nz,ItemUseNotTime +	ld hl,CardKeyTable3 +.next1 +	ld a,[W_CURMAP] +	ld b,a +.loop +	ld a,[hli] +	cp a,$ff +	jp z,ItemUseNotTime +	cp b +	jr nz,.nextEntry1 +	ld a,[hli] +	cp d +	jr nz,.nextEntry2 +	ld a,[hli] +	cp e +	jr nz,.nextEntry3 +	ld a,[hl] +	ld [wd71f],a +	jr .done +.nextEntry1 +	inc hl +.nextEntry2 +	inc hl +.nextEntry3 +	inc hl +	jr .loop +.done +	ld hl,ItemUseText00 +	call PrintText +	ld hl,wd728 +	set 7,[hl] +	ret + +; These tables are probably supposed to be door locations in Silph Co., +; but they are unused. +; The reason there are 3 tables is unknown. + +; Format: +; 00: Map ID +; 01: Y +; 02: X +; 03: ID? + +CardKeyTable1: ; e072 (3:6072) +	db  SILPH_CO_2F,$04,$04,$00 +	db  SILPH_CO_2F,$04,$05,$01 +	db  SILPH_CO_4F,$0C,$04,$02 +	db  SILPH_CO_4F,$0C,$05,$03 +	db  SILPH_CO_7F,$06,$0A,$04 +	db  SILPH_CO_7F,$06,$0B,$05 +	db  SILPH_CO_9F,$04,$12,$06 +	db  SILPH_CO_9F,$04,$13,$07 +	db SILPH_CO_10F,$08,$0A,$08 +	db SILPH_CO_10F,$08,$0B,$09 +	db $ff + +CardKeyTable2: ; e09b (3:609b) +	db SILPH_CO_3F,$08,$09,$0A +	db SILPH_CO_3F,$09,$09,$0B +	db SILPH_CO_5F,$04,$07,$0C +	db SILPH_CO_5F,$05,$07,$0D +	db SILPH_CO_6F,$0C,$05,$0E +	db SILPH_CO_6F,$0D,$05,$0F +	db SILPH_CO_8F,$08,$07,$10 +	db SILPH_CO_8F,$09,$07,$11 +	db SILPH_CO_9F,$08,$03,$12 +	db SILPH_CO_9F,$09,$03,$13 +	db $ff + +CardKeyTable3: ; e0c4 (3:60c4) +	db SILPH_CO_11F,$08,$09,$14 +	db SILPH_CO_11F,$09,$09,$15 +	db $ff + +ItemUsePokedoll: ; e0cd (3:60cd) +	ld a,[W_ISINBATTLE] +	dec a +	jp nz,ItemUseNotTime +	ld a,$01 +	ld [wEscapedFromBattle],a +	jp PrintItemUseTextAndRemoveItem + +ItemUseGuardSpec: ; e0dc (3:60dc) +	ld a,[W_ISINBATTLE] +	and a +	jp z,ItemUseNotTime +	ld hl,W_PLAYERBATTSTATUS2 +	set ProtectedByMist,[hl] ; Mist bit +	jp PrintItemUseTextAndRemoveItem + +ItemUseSuperRepel: ; e0eb (3:60eb) +	ld b,200 +	jp ItemUseRepelCommon + +ItemUseMaxRepel: ; e0f0 (3:60f0) +	ld b,250 +	jp ItemUseRepelCommon + +ItemUseDireHit: ; e0f5 (3:60f5) +	ld a,[W_ISINBATTLE] +	and a +	jp z,ItemUseNotTime +	ld hl,W_PLAYERBATTSTATUS2 +	set GettingPumped,[hl] ; Focus Energy bit +	jp PrintItemUseTextAndRemoveItem + +ItemUseXStat: ; e104 (3:6104) +	ld a,[W_ISINBATTLE] +	and a +	jr nz,.inBattle +	call ItemUseNotTime +	ld a,2 +	ld [wcd6a],a ; item not used +	ret +.inBattle +	ld hl,W_PLAYERMOVENUM +	ld a,[hli] +	push af ; save [W_PLAYERMOVENUM] +	ld a,[hl] +	push af ; save [W_PLAYERMOVEEFFECT] +	push hl +	ld a,[wcf91] +	sub a,X_ATTACK - ATTACK_UP1_EFFECT +	ld [hl],a ; store player move effect +	call PrintItemUseTextAndRemoveItem +	ld a,XSTATITEM_ANIM ; X stat item animation ID +	ld [W_PLAYERMOVENUM],a +	call LoadScreenTilesFromBuffer1 ; restore saved screen +	call Delay3 +	xor a +	ld [H_WHOSETURN],a ; set turn to player's turn +	callba StatModifierUpEffect ; do stat increase move +	pop hl +	pop af +	ld [hld],a ; restore [W_PLAYERMOVEEFFECT] +	pop af +	ld [hl],a ; restore [W_PLAYERMOVENUM] +	ret + +ItemUsePokeflute: ; e140 (3:6140) +	ld a,[W_ISINBATTLE] +	and a +	jr nz,.inBattle +; if not in battle +	call ItemUseReloadOverworldData +	ld a,[W_CURMAP] +	cp a,ROUTE_12 +	jr nz,.notRoute12 +	ld a,[wd7d8] +	bit 7,a ; has the player beaten Route 12 Snorlax yet? +	jr nz,.noSnorlaxToWakeUp +; if the player hasn't beaten Route 12 Snorlax +	ld hl,Route12SnorlaxFluteCoords +	call ArePlayerCoordsInArray +	jr nc,.noSnorlaxToWakeUp +	ld hl,PlayedFluteHadEffectText +	call PrintText +	ld hl,wd7d8 +	set 6,[hl] ; trigger Snorlax fight (handled by map script) +	ret +.notRoute12 +	cp a,ROUTE_16 +	jr nz,.noSnorlaxToWakeUp +	ld a,[wd7e0] +	bit 1,a ; has the player beaten Route 16 Snorlax yet? +	jr nz,.noSnorlaxToWakeUp +; if the player hasn't beaten Route 16 Snorlax +	ld hl,Route16SnorlaxFluteCoords +	call ArePlayerCoordsInArray +	jr nc,.noSnorlaxToWakeUp +	ld hl,PlayedFluteHadEffectText +	call PrintText +	ld hl,wd7e0 +	set 0,[hl] ; trigger Snorlax fight (handled by map script) +	ret +.noSnorlaxToWakeUp +	ld hl,PlayedFluteNoEffectText +	jp PrintText +.inBattle +	xor a +	ld [wWhichTrade],a ; initialize variable that indicates if any pokemon were woken up to zero +	ld b,~SLP & $FF +	ld hl,wPartyMon1Status +	call WakeUpEntireParty +	ld a,[W_ISINBATTLE] +	dec a ; is it a trainer battle? +	jr z,.skipWakingUpEnemyParty +; if it's a trainer battle +	ld hl,wEnemyMon1Status +	call WakeUpEntireParty +.skipWakingUpEnemyParty +	ld hl,wBattleMonStatus +	ld a,[hl] +	and b ; remove Sleep status +	ld [hl],a +	ld hl,wEnemyMonStatus +	ld a,[hl] +	and b ; remove Sleep status +	ld [hl],a +	call LoadScreenTilesFromBuffer2 ; restore saved screen +	ld a,[wWhichTrade] +	and a ; were any pokemon asleep before playing the flute? +	ld hl,PlayedFluteNoEffectText +	jp z,PrintText ; if no pokemon were asleep +; if some pokemon were asleep +	ld hl,PlayedFluteHadEffectText +	call PrintText +	ld a,[wLowHealthAlarm] +	and a,$80 +	jr nz,.skipMusic +	call WaitForSoundToFinish ; wait for sound to end +	callba Music_PokeFluteInBattle ; play in-battle pokeflute music +.musicWaitLoop ; wait for music to finish playing +	ld a,[wc02c] +	and a ; music off? +	jr nz,.musicWaitLoop +.skipMusic +	ld hl,FluteWokeUpText +	jp PrintText + +; wakes up all party pokemon +; INPUT: +; hl must point to status of first pokemon in party (player's or enemy's) +; b must equal ~SLP +; [wWhichTrade] should be initialized to 0 +; OUTPUT: +; [wWhichTrade]: set to 1 if any pokemon were asleep +WakeUpEntireParty: ; e1e5 (3:61e5) +	ld de,44 +	ld c,6 +.loop +	ld a,[hl] +	push af +	and a,SLP ; is pokemon asleep? +	jr z,.notAsleep +	ld a,1 +	ld [wWhichTrade],a ; indicate that a pokemon had to be woken up +.notAsleep +	pop af +	and b ; remove Sleep status +	ld [hl],a +	add hl,de +	dec c +	jr nz,.loop +	ret + +; Format: +; 00: Y +; 01: X +Route12SnorlaxFluteCoords: ; e1fd (3:61fd) +	db 62,9  ; one space West of Snorlax +	db 61,10 ; one space North of Snorlax +	db 63,10 ; one space South of Snorlax +	db 62,11 ; one space East of Snorlax +	db $ff ; terminator + +; Format: +; 00: Y +; 01: X +Route16SnorlaxFluteCoords: ; e206 (3:6206) +	db 10,27 ; one space East of Snorlax +	db 10,25 ; one space West of Snorlax +	db $ff ; terminator + +PlayedFluteNoEffectText: ; e20b (3:620b) +	TX_FAR _PlayedFluteNoEffectText +	db "@" + +FluteWokeUpText: ; e210 (3:6210) +	TX_FAR _FluteWokeUpText +	db "@" + +PlayedFluteHadEffectText: ; e215 (3:6215) +	TX_FAR _PlayedFluteHadEffectText +	db $06 +	db $08 +	ld a,[W_ISINBATTLE] +	and a +	jr nz,.done +; play out-of-battle pokeflute music +	ld a,$ff +	call PlaySound ; turn off music +	ld a, (SFX_02_5e - SFX_Headers_02) / 3 +	ld c, BANK(SFX_02_5e) +	call PlayMusic ; play music +.musicWaitLoop ; wait for music to finish playing +	ld a,[wc028] +	cp a,$b8 +	jr z,.musicWaitLoop +	call PlayDefaultMusic ; start playing normal music again +.done +	jp TextScriptEnd ; end text + +ItemUseCoinCase: ; e23a (3:623a) +	ld a,[W_ISINBATTLE] +	and a +	jp nz,ItemUseNotTime +	ld hl,CoinCaseNumCoinsText +	jp PrintText + +CoinCaseNumCoinsText: ; e247 (3:6247) +	TX_FAR _CoinCaseNumCoinsText +	db "@" + +OldRodCode: ; e24c (3:624c) +	call FishingInit +	jp c, ItemUseNotTime +	ld bc, (5 << 8) | MAGIKARP +	ld a, $1 ; set bite +	jr RodResponse ; 0xe257 $34 + +GoodRodCode: ; e259 (3:6259) +	call FishingInit +	jp c,ItemUseNotTime +.RandomLoop +	call Random +	srl a +	jr c, .SetBite +	and %11 +	cp 2 +	jr nc, .RandomLoop +	; choose which monster appears +	ld hl,GoodRodMons +	add a,a +	ld c,a +	ld b,0 +	add hl,bc +	ld b,[hl] +	inc hl +	ld c,[hl] +	and a +.SetBite +	ld a,0 +	rla +	xor 1 +	jr RodResponse + +INCLUDE "data/good_rod.asm" + +SuperRodCode: ; e283 (3:6283) +	call FishingInit +	jp c, ItemUseNotTime +	call ReadSuperRodData ; 0xe8ea +	ld a, e +RodResponse: ; e28d (3:628d) +	ld [wWhichTrade], a + +	dec a ; is there a bite? +	jr nz, .next +	; if yes, store level and species data +	ld a, 1 +	ld [W_MOVEMISSED], a +	ld a, b ; level +	ld [W_CURENEMYLVL], a +	ld a, c ; species +	ld [W_CUROPPONENT], a + +.next +	ld hl, wWalkBikeSurfState +	ld a, [hl] ; store the value in a +	push af +	push hl +	ld [hl], 0 +	callba Func_707b6 +	pop hl +	pop af +	ld [hl], a +	ret + +; checks if fishing is possible and if so, runs initialization code common to all rods +; unsets carry if fishing is possible, sets carry if not +FishingInit: ; e2b4 (3:62b4) +	ld a,[W_ISINBATTLE] +	and a +	jr z,.notInBattle +	scf ; can't fish during battle +	ret +.notInBattle +	call IsNextTileShoreOrWater +	ret c +	ld a,[wWalkBikeSurfState] +	cp a,2 ; Surfing? +	jr z,.surfing +	call ItemUseReloadOverworldData +	ld hl,ItemUseText00 +	call PrintText +	ld a,(SFX_02_3e - SFX_Headers_02) / 3 +	call PlaySound ; play sound +	ld c,80 +	call DelayFrames +	and a +	ret +.surfing +	scf ; can't fish when surfing +	ret + +ItemUseOaksParcel: ; e2de (3:62de) +	jp ItemUseNotYoursToUse + +ItemUseItemfinder: ; e2e1 (3:62e1) +	ld a,[W_ISINBATTLE] +	and a +	jp nz,ItemUseNotTime +	call ItemUseReloadOverworldData +	callba HiddenItemNear ; check for hidden items +	ld hl,ItemfinderFoundNothingText +	jr nc,.printText ; if no hidden items +	ld c,4 +.loop +	ld a,(SFX_02_4a - SFX_Headers_02) / 3 +	call PlaySoundWaitForCurrent ; play sound +	ld a,(SFX_02_5a - SFX_Headers_02) / 3 +	call PlaySoundWaitForCurrent ; play sound +	dec c +	jr nz,.loop +	ld hl,ItemfinderFoundItemText +.printText +	jp PrintText + +ItemfinderFoundItemText: ; e30d (3:630d) +	TX_FAR _ItemfinderFoundItemText +	db "@" + +ItemfinderFoundNothingText: ; e312 (3:6312) +	TX_FAR _ItemfinderFoundNothingText +	db "@" + +ItemUsePPUp: ; e317 (3:6317) +	ld a,[W_ISINBATTLE] +	and a +	jp nz,ItemUseNotTime + +ItemUsePPRestore: ; e31e (3:631e) +	ld a,[wWhichPokemon] +	push af +	ld a,[wcf91] +	ld [wWhichTrade],a +.chooseMon +	xor a +	ld [wUpdateSpritesEnabled],a +	ld a,$01 ; item use party menu +	ld [wd07d],a +	call DisplayPartyMenu +	jr nc,.chooseMove +	jp .itemNotUsed +.chooseMove +	ld a,[wWhichTrade] +	cp a,ELIXER +	jp nc,.useElixir ; if Elixir or Max Elixir +	ld a,$02 +	ld [wMoveMenuType],a +	ld hl,RaisePPWhichTechniqueText +	ld a,[wWhichTrade] +	cp a,ETHER ; is it a PP Up? +	jr c,.printWhichTechniqueMessage ; if so, print the raise PP message +	ld hl,RestorePPWhichTechniqueText ; otherwise, print the restore PP message +.printWhichTechniqueMessage +	call PrintText +	xor a +	ld [wPlayerMoveListIndex],a +	callab MoveSelectionMenu ; move selection menu +	ld a,0 +	ld [wPlayerMoveListIndex],a +	jr nz,.chooseMon +	ld hl,wPartyMon1Moves +	ld bc,44 +	call GetSelectedMoveOffset +	push hl +	ld a,[hl] +	ld [wd11e],a +	call GetMoveName +	call CopyStringToCF4B ; copy name to wcf4b +	pop hl +	ld a,[wWhichTrade] +	cp a,ETHER +	jr nc,.useEther ; if Ether or Max Ether +.usePPUp +	ld bc,21 +	add hl,bc +	ld a,[hl] ; move PP +	cp a,3 << 6 ; have 3 PP Ups already been used? +	jr c,.PPNotMaxedOut +	ld hl,PPMaxedOutText +	call PrintText +	jr .chooseMove +.PPNotMaxedOut +	ld a,[hl] +	add a,1 << 6 ; increase PP Up count by 1 +	ld [hl],a +	ld a,1 ; 1 PP Up used +	ld [wd11e],a +	call RestoreBonusPP ; add the bonus PP to current PP +	ld hl,PPIncreasedText +	call PrintText +.done +	pop af +	ld [wWhichPokemon],a +	call GBPalWhiteOut +	call GoPAL_SET_CF1C +	jp RemoveUsedItem +.afterRestoringPP ; after using a (Max) Ether/Elixir +	ld a,[wWhichPokemon] +	ld b,a +	ld a,[wPlayerMonNumber] +	cp b ; is the pokemon whose PP was restored active in battle? +	jr nz,.skipUpdatingInBattleData +	ld hl,wPartyMon1PP +	ld bc,44 +	call AddNTimes +	ld de,wBattleMonPP +	ld bc,4 +	call CopyData ; copy party data to in-battle data +.skipUpdatingInBattleData +	ld a,(SFX_02_3e - SFX_Headers_02) / 3 +	call PlaySound +	ld hl,PPRestoredText +	call PrintText +	jr .done +.useEther +	call .restorePP +	jr nz,.afterRestoringPP +	jp .noEffect +; unsets zero flag if PP was restored, sets zero flag if not +; however, this is bugged for Max Ethers and Max Elixirs (see below) +.restorePP +	xor a +	ld [wcc49],a ; party pokemon +	call GetMaxPP +	ld hl,wPartyMon1Moves +	ld bc,44 +	call GetSelectedMoveOffset +	ld bc,21 +	add hl,bc ; hl now points to move's PP +	ld a,[wd11e] +	ld b,a ; b = max PP +	ld a,[wWhichTrade] +	cp a,MAX_ETHER +	jr z,.fullyRestorePP +	ld a,[hl] ; move PP +	and a,%00111111 ; lower 6 bit bits store current PP +	cp b ; does current PP equal max PP? +	ret z ; if so, return +	add a,10 ; increase current PP by 10 +; b holds the max PP amount and b will hold the new PP amount. +; So, if the new amount meets or exceeds the max amount, +; cap the amount to the max amount by leaving b unchanged. +; Otherwise, store the new amount in b. +	cp b ; does the new amount meet or exceed the maximum? +	jr nc,.storeNewAmount +	ld b,a +.storeNewAmount +	ld a,[hl] ; move PP +	and a,%11000000 ; PP Up counter bits +	add b +	ld [hl],a +	ret +.fullyRestorePP +	ld a,[hl] ; move PP +; Note that this code has a bug. It doesn't mask out the upper two bits, which +; are used to count how many PP Ups have been used on the move. So, Max Ethers +; and Max Elixirs will not be detected as having no effect on a move with full +; PP if the move has had any PP Ups used on it. +	cp b ; does current PP equal max PP? +	ret z +	jr .storeNewAmount +.useElixir +; decrement the item ID so that ELIXER becomes ETHER and MAX_ELIXER becomes MAX_ETHER +	ld hl,wWhichTrade +	dec [hl] +	dec [hl] +	xor a +	ld hl,wCurrentMenuItem +	ld [hli],a +	ld [hl],a ; zero the counter for number of moves that had their PP restored +	ld b,4 +; loop through each move and restore PP +.elixirLoop +	push bc +	ld hl,wPartyMon1Moves +	ld bc,44 +	call GetSelectedMoveOffset +	ld a,[hl] +	and a ; does the current slot have a move? +	jr z,.nextMove +	call .restorePP +	jr z,.nextMove +; if some PP was restored +	ld hl,wTileBehindCursor ; counter for number of moves that had their PP restored +	inc [hl] +.nextMove +	ld hl,wCurrentMenuItem +	inc [hl] +	pop bc +	dec b +	jr nz,.elixirLoop +	ld a,[wTileBehindCursor] +	and a ; did any moves have their PP restored? +	jp nz,.afterRestoringPP +.noEffect +	call ItemUseNoEffect +.itemNotUsed +	call GBPalWhiteOut +	call GoPAL_SET_CF1C +	pop af +	xor a +	ld [wcd6a],a ; item use failed +	ret + +RaisePPWhichTechniqueText: ; e45d (3:645d) +	TX_FAR _RaisePPWhichTechniqueText +	db "@" + +RestorePPWhichTechniqueText: ; e462 (3:6462) +	TX_FAR _RestorePPWhichTechniqueText +	db "@" + +PPMaxedOutText: ; e467 (3:6467) +	TX_FAR _PPMaxedOutText +	db "@" + +PPIncreasedText: ; e46c (3:646c) +	TX_FAR _PPIncreasedText +	db "@" + +PPRestoredText: ; e471 (3:6471) +	TX_FAR _PPRestoredText +	db "@" + +; for items that can't be used from the Item menu +UnusableItem: ; e476 (3:6476) +	jp ItemUseNotTime + +ItemUseTMHM: ; e479 (3:6479) +	ld a,[W_ISINBATTLE] +	and a +	jp nz,ItemUseNotTime +	ld a,[wcf91] +	sub a,TM_01 +	push af +	jr nc,.skipAdding +	add a,55 ; if item is an HM, add 55 +.skipAdding +	inc a +	ld [wd11e],a +	predef TMToMove ; get move ID from TM/HM ID +	ld a,[wd11e] +	ld [wMoveNum],a +	call GetMoveName +	call CopyStringToCF4B ; copy name to wcf4b +	pop af +	ld hl,BootedUpTMText +	jr nc,.printBootedUpMachineText +	ld hl,BootedUpHMText +.printBootedUpMachineText +	call PrintText +	ld hl,TeachMachineMoveText +	call PrintText +	hlCoord 14, 7 +	ld bc,$080f +	ld a,TWO_OPTION_MENU +	ld [wTextBoxID],a +	call DisplayTextBoxID ; yes/no menu +	ld a,[wCurrentMenuItem] +	and a +	jr z,.useMachine +	ld a,2 +	ld [wcd6a],a ; item not used +	ret +.useMachine +	ld a,[wWhichPokemon] +	push af +	ld a,[wcf91] +	push af +.chooseMon +	ld hl,wcf4b +	ld de,wd036 +	ld bc,14 +	call CopyData +	ld a,$ff +	ld [wUpdateSpritesEnabled],a +	ld a,$03 ; teach TM/HM party menu +	ld [wd07d],a +	call DisplayPartyMenu +	push af +	ld hl,wd036 +	ld de,wcf4b +	ld bc,14 +	call CopyData +	pop af +	jr nc,.checkIfAbleToLearnMove +; if the player canceled teaching the move +	pop af +	pop af +	call GBPalWhiteOutWithDelay3 +	call ClearSprites +	call GoPAL_SET_CF1C +	jp LoadScreenTilesFromBuffer1 ; restore saved screen +.checkIfAbleToLearnMove +	predef CanLearnTM ; check if the pokemon can learn the move +	push bc +	ld a,[wWhichPokemon] +	ld hl,wPartyMonNicks +	call GetPartyMonName +	pop bc +	ld a,c +	and a ; can the pokemon learn the move? +	jr nz,.checkIfAlreadyLearnedMove +; if the pokemon can't learn the move +	ld a,(SFX_02_51 - SFX_Headers_02) / 3 +	call PlaySoundWaitForCurrent ; play sound +	ld hl,MonCannotLearnMachineMoveText +	call PrintText +	jr .chooseMon +.checkIfAlreadyLearnedMove +	callab CheckIfMoveIsKnown ; check if the pokemon already knows the move +	jr c,.chooseMon +	predef LearnMove ; teach move +	pop af +	ld [wcf91],a +	pop af +	ld [wWhichPokemon],a +	ld a,b +	and a +	ret z +	ld a,[wcf91] +	call IsItemHM +	ret c +	jp RemoveUsedItem + +BootedUpTMText: ; e54f (3:654f) +	TX_FAR _BootedUpTMText +	db "@" + +BootedUpHMText: ; e554 (3:6554) +	TX_FAR _BootedUpHMText +	db "@" + +TeachMachineMoveText: ; e559 (3:6559) +	TX_FAR _TeachMachineMoveText +	db "@" + +MonCannotLearnMachineMoveText: ; e55e (3:655e) +	TX_FAR _MonCannotLearnMachineMoveText +	db "@" + +PrintItemUseTextAndRemoveItem: ; e563 (3:6563) +	ld hl,ItemUseText00 +	call PrintText +	ld a,(SFX_02_3e - SFX_Headers_02) / 3 +	call PlaySound ; play sound +	call WaitForTextScrollButtonPress ; wait for button press + +RemoveUsedItem: ; e571 (3:6571) +	ld hl,wNumBagItems +	ld a,1 ; one item +	ld [wcf96],a ; store quantity +	jp RemoveItemFromInventory + +ItemUseNoEffect: ; e57c (3:657c) +	ld hl,ItemUseNoEffectText +	jr ItemUseFailed + +ItemUseNotTime: ; e581 (3:6581) +	ld hl,ItemUseNotTimeText +	jr ItemUseFailed + +ItemUseNotYoursToUse: ; e586 (3:6586) +	ld hl,ItemUseNotYoursToUseText +	jr ItemUseFailed + +ThrowBallAtTrainerMon: ; e58b (3:658b) +	call GoPAL_SET_CF1C +	call LoadScreenTilesFromBuffer1 ; restore saved screen +	call Delay3 +	ld a,TOSS_ANIM +	ld [W_ANIMATIONID],a +	predef MoveAnimation ; do animation +	ld hl,ThrowBallAtTrainerMonText1 +	call PrintText +	ld hl,ThrowBallAtTrainerMonText2 +	call PrintText +	jr RemoveUsedItem + +NoCyclingAllowedHere: ; e5ac (3:65ac) +	ld hl,NoCyclingAllowedHereText +	jr ItemUseFailed + +BoxFullCannotThrowBall: ; e5b1 (3:65b1) +	ld hl,BoxFullCannotThrowBallText +	jr ItemUseFailed + +SurfingAttemptFailed: ; e5b6 (3:65b6) +	ld hl,NoSurfingHereText + +ItemUseFailed: ; e5b9 (3:65b9) +	xor a +	ld [wcd6a],a ; item use failed +	jp PrintText + +ItemUseNotTimeText: ; e5c0 (3:65c0) +	TX_FAR _ItemUseNotTimeText +	db "@" + +ItemUseNotYoursToUseText: ; e5c5 (3:65c5) +	TX_FAR _ItemUseNotYoursToUseText +	db "@" + +ItemUseNoEffectText: ; e5ca (3:65ca) +	TX_FAR _ItemUseNoEffectText +	db "@" + +ThrowBallAtTrainerMonText1: ; e5cf (3:65cf) +	TX_FAR _ThrowBallAtTrainerMonText1 +	db "@" + +ThrowBallAtTrainerMonText2: ; e5d4 (3:65d4) +	TX_FAR _ThrowBallAtTrainerMonText2 +	db "@" + +NoCyclingAllowedHereText: ; e5d9 (3:65d9) +	TX_FAR _NoCyclingAllowedHereText +	db "@" + +NoSurfingHereText: ; e5de (3:65de) +	TX_FAR _NoSurfingHereText +	db "@" + +BoxFullCannotThrowBallText: ; e5e3 (3:65e3) +	TX_FAR _BoxFullCannotThrowBallText +	db "@" + +ItemUseText00: ; e5e8 (3:65e8) +	TX_FAR _ItemUseText001 +	db $05 +	TX_FAR _ItemUseText002 +	db "@" + +GotOnBicycleText: ; e5f2 (3:65f2) +	TX_FAR _GotOnBicycleText1 +	db $05 +	TX_FAR _GotOnBicycleText2 +	db "@" + +GotOffBicycleText: ; e5fc (3:65fc) +	TX_FAR _GotOffBicycleText1 +	db $05 +	TX_FAR _GotOffBicycleText2 +	db "@" + +; restores bonus PP (from PP Ups) when healing at a pokemon center +; also, when a PP Up is used, it increases the current PP by one PP Up bonus +; INPUT: +; [wWhichPokemon] = index of pokemon in party +; [wd11e] = mode +; 0: Pokemon Center healing +; 1: using a PP Up +; [wCurrentMenuItem] = index of move (when using a PP Up) +RestoreBonusPP: ; e606 (3:6606) +	ld hl,wPartyMon1Moves +	ld bc,44 +	ld a,[wWhichPokemon] +	call AddNTimes +	push hl +	ld de,wcd78 - 1 +	predef LoadMovePPs ; loads the normal max PP of each of the pokemon's moves to wcd78 +	pop hl +	ld c,21 +	ld b,0 +	add hl,bc ; hl now points to move 1 PP +	ld de,wcd78 +	ld b,0 ; initialize move counter to zero +; loop through the pokemon's moves +.loop +	inc b +	ld a,b +	cp a,5 ; reached the end of the pokemon's moves? +	ret z ; if so, return +	ld a,[wd11e] +	dec a ; using a PP Up? +	jr nz,.skipMenuItemIDCheck +; if using a PP Up, check if this is the move it's being used on +	ld a,[wCurrentMenuItem] +	inc a +	cp b +	jr nz,.nextMove +.skipMenuItemIDCheck +	ld a,[hl] +	and a,%11000000 ; have any PP Ups been used? +	call nz,AddBonusPP ; if so, add bonus PP +.nextMove +	inc hl +	inc de +	jr .loop + +; adds bonus PP from PP Ups to current PP +; 1/5 of normal max PP (capped at 7) is added for each PP Up +; INPUT: +; [de] = normal max PP +; [hl] = move PP +; [wd11e] = max number of times to add bonus +; set to 1 when using a PP Up, set to 255 otherwise +AddBonusPP: ; e642 (3:6642) +	push bc +	ld a,[de] ; normal max PP of move +	ld [H_DIVIDEND + 3],a +	xor a +	ld [H_DIVIDEND],a +	ld [H_DIVIDEND + 1],a +	ld [H_DIVIDEND + 2],a +	ld a,5 +	ld [H_DIVISOR],a +	ld b,4 +	call Divide +	ld a,[hl] ; move PP +	ld b,a +	swap a +	and a,%00001111 +	srl a +	srl a +	ld c,a ; c = number of PP Ups used +.loop +	ld a,[H_QUOTIENT + 3] +	cp a,8 ; is the amount greater than or equal to 8? +	jr c,.addAmount +	ld a,7 ; cap the amount at 7 +.addAmount +	add b +	ld b,a +	ld a,[wd11e] +	dec a +	jr z,.done +	dec c +	jr nz,.loop +.done +	ld [hl],b +	pop bc +	ret + +; gets max PP of a pokemon's move (including PP from PP Ups) +; INPUT: +; [wWhichPokemon] = index of pokemon within party/box +; [wcc49] = pokemon source +; 00: player's party +; 01: enemy's party +; 02: current box +; 03: daycare +; 04: player's in-battle pokemon +; [wCurrentMenuItem] = move index +; OUTPUT: +; [wd11e] = max PP +GetMaxPP: ; e677 (3:6677) +	ld a,[wcc49] +	and a +	ld hl,wPartyMon1Moves +	ld bc,wPartyMon2 - wPartyMon1 +	jr z,.sourceWithMultipleMon +	ld hl,wEnemyMon1Moves +	dec a +	jr z,.sourceWithMultipleMon +	ld hl,wBoxMon1Moves +	ld bc,wBoxMon2 - wBoxMon1 +	dec a +	jr z,.sourceWithMultipleMon +	ld hl,wDayCareMonMoves +	dec a +	jr z,.sourceWithOneMon +	ld hl,wBattleMonMoves ; player's in-battle pokemon +.sourceWithOneMon +	call GetSelectedMoveOffset2 +	jr .next +.sourceWithMultipleMon +	call GetSelectedMoveOffset +.next +	ld a,[hl] +	dec a +	push hl +	ld hl,Moves +	ld bc,6 +	call AddNTimes +	ld de,wcd6d +	ld a,BANK(Moves) +	call FarCopyData +	ld de,wcd72 +	ld a,[de] +	ld b,a ; b = normal max PP +	pop hl +	push bc +	ld bc,21 ; PP offset if not player's in-battle pokemon data +	ld a,[wcc49] +	cp a,4 ; player's in-battle pokemon? +	jr nz,.addPPOffset +	ld bc,17 ; PP offset if player's in-battle pokemon data +.addPPOffset +	add hl,bc +	ld a,[hl] ; a = current PP +	and a,%11000000 ; get PP Up count +	pop bc +	or b ; place normal max PP in 6 lower bits of a +	ld h,d +	ld l,e +	inc hl ; hl = wcd73 +	ld [hl],a +	xor a +	ld [wd11e],a ; no limit on PP Up amount +	call AddBonusPP ; add bonus PP from PP Ups +	ld a,[hl] +	and a,%00111111 ; mask out the PP Up count +	ld [wd11e],a ; store max PP +	ret + +GetSelectedMoveOffset: ; e6e3 (3:66e3) +	ld a,[wWhichPokemon] +	call AddNTimes + +GetSelectedMoveOffset2: ; e6e9 (3:66e9) +	ld a,[wCurrentMenuItem] +	ld c,a +	ld b,0 +	add hl,bc +	ret + +; confirms the item toss and then tosses the item +; INPUT: +; hl = address of inventory (either wNumBagItems or wNumBoxItems) +; [wcf91] = item ID +; [wWhichPokemon] = index of item within inventory +; [wcf96] = quantity to toss +; OUTPUT: +; clears carry flag if the item is tossed, sets carry flag if not +TossItem_: ; e6f1 (3:66f1) +	push hl +	ld a,[wcf91] +	call IsItemHM +	pop hl +	jr c,.tooImportantToToss +	push hl +	call IsKeyItem_ +	ld a,[wd124] +	pop hl +	and a +	jr nz,.tooImportantToToss +	push hl +	ld a,[wcf91] +	ld [wd11e],a +	call GetItemName +	call CopyStringToCF4B ; copy name to wcf4b +	ld hl,IsItOKToTossItemText +	call PrintText +	hlCoord 14, 7 +	ld bc,$080f +	ld a,TWO_OPTION_MENU +	ld [wTextBoxID],a +	call DisplayTextBoxID ; yes/no menu +	ld a,[wd12e] +	cp a,2 +	pop hl +	scf +	ret z +; if the player chose Yes +	push hl +	ld a,[wWhichPokemon] +	call RemoveItemFromInventory +	ld a,[wcf91] +	ld [wd11e],a +	call GetItemName +	call CopyStringToCF4B ; copy name to wcf4b +	ld hl,ThrewAwayItemText +	call PrintText +	pop hl +	and a +	ret +.tooImportantToToss +	push hl +	ld hl,TooImportantToTossText +	call PrintText +	pop hl +	scf +	ret + +ThrewAwayItemText: ; e755 (3:6755) +	TX_FAR _ThrewAwayItemText +	db "@" + +IsItOKToTossItemText: ; e75a (3:675a) +	TX_FAR _IsItOKToTossItemText +	db "@" + +TooImportantToTossText: ; e75f (3:675f) +	TX_FAR _TooImportantToTossText +	db "@" + +; checks if an item is a key item +; INPUT: +; [wcf91] = item ID +; OUTPUT: +; [wd124] = result +; 00: item is not key item +; 01: item is key item +IsKeyItem_: ; e764 (3:6764) +	ld a,$01 +	ld [wd124],a +	ld a,[wcf91] +	cp a,HM_01 ; is the item an HM or TM? +	jr nc,.checkIfItemIsHM +; if the item is not an HM or TM +	push af +	ld hl,KeyItemBitfield +	ld de,wHPBarMaxHP +	ld bc,15 ; only 11 bytes are actually used +	call CopyData +	pop af +	dec a +	ld c,a +	ld hl,wHPBarMaxHP +	ld b,$02 ; test bit +	predef FlagActionPredef ; bitfield operation function +	ld a,c +	and a +	ret nz +.checkIfItemIsHM +	ld a,[wcf91] +	call IsItemHM +	ret c +	xor a +	ld [wd124],a +	ret + +INCLUDE "data/key_items.asm" + +SendNewMonToBox: ; e7a4 (3:67a4) +	ld de, W_NUMINBOX ; wda80 +	ld a, [de] +	inc a +	ld [de], a +	ld a, [wcf91] +	ld [wd0b5], a +	ld c, a +.asm_e7b1 +	inc de +	ld a, [de] +	ld b, a +	ld a, c +	ld c, b +	ld [de], a +	cp $ff +	jr nz, .asm_e7b1 +	call GetMonHeader +	ld hl, wBoxMonOT +	ld bc, $b +	ld a, [W_NUMINBOX] ; wda80 +	dec a +	jr z, .asm_e7ee +	dec a +	call AddNTimes +	push hl +	ld bc, $b +	add hl, bc +	ld d, h +	ld e, l +	pop hl +	ld a, [W_NUMINBOX] ; wda80 +	dec a +	ld b, a +.asm_e7db +	push bc +	push hl +	ld bc, $b +	call CopyData +	pop hl +	ld d, h +	ld e, l +	ld bc, $fff5 +	add hl, bc +	pop bc +	dec b +	jr nz, .asm_e7db +.asm_e7ee +	ld hl, wPlayerName ; wd158 +	ld de, wBoxMonOT +	ld bc, $b +	call CopyData +	ld a, [W_NUMINBOX] ; wda80 +	dec a +	jr z, .asm_e82a +	ld hl, wBoxMonNicks +	ld bc, $b +	dec a +	call AddNTimes +	push hl +	ld bc, $b +	add hl, bc +	ld d, h +	ld e, l +	pop hl +	ld a, [W_NUMINBOX] ; wda80 +	dec a +	ld b, a +.asm_e817 +	push bc +	push hl +	ld bc, $b +	call CopyData +	pop hl +	ld d, h +	ld e, l +	ld bc, $fff5 +	add hl, bc +	pop bc +	dec b +	jr nz, .asm_e817 +.asm_e82a +	ld hl, wBoxMonNicks +	ld a, $2 +	ld [wd07d], a +	predef AskName +	ld a, [W_NUMINBOX] ; wda80 +	dec a +	jr z, .asm_e867 +	ld hl, wBoxMons +	ld bc, wBoxMon2 - wBoxMon1 +	dec a +	call AddNTimes +	push hl +	ld bc, wBoxMon2 - wBoxMon1 +	add hl, bc +	ld d, h +	ld e, l +	pop hl +	ld a, [W_NUMINBOX] ; wda80 +	dec a +	ld b, a +.asm_e854 +	push bc +	push hl +	ld bc, wBoxMon2 - wBoxMon1 +	call CopyData +	pop hl +	ld d, h +	ld e, l +	ld bc, $ffdf +	add hl, bc +	pop bc +	dec b +	jr nz, .asm_e854 +.asm_e867 +	ld a, [wEnemyMonLevel] ; wEnemyMonLevel +	ld [wEnemyMonBoxLevel], a +	ld hl, wEnemyMon +	ld de, wBoxMon1 +	ld bc, $c +	call CopyData +	ld hl, wPlayerID ; wPlayerID +	ld a, [hli] +	ld [de], a +	inc de +	ld a, [hl] +	ld [de], a +	inc de +	push de +	ld a, [W_CURENEMYLVL] ; W_CURENEMYLVL +	ld d, a +	callab CalcExperience +	pop de +	ld a, [H_NUMTOPRINT] ; $ff96 (aliases: H_MULTIPLICAND) +	ld [de], a +	inc de +	ld a, [$ff97] +	ld [de], a +	inc de +	ld a, [$ff98] +	ld [de], a +	inc de +	xor a +	ld b, $a +.asm_e89f +	ld [de], a +	inc de +	dec b +	jr nz, .asm_e89f +	ld hl, wEnemyMonDVs +	ld a, [hli] +	ld [de], a +	inc de +	ld a, [hli] +	ld [de], a +	ld hl, wEnemyMonPP ; wcffe +	ld b, $4 +.asm_e8b1 +	ld a, [hli] +	inc de +	ld [de], a +	dec b +	jr nz, .asm_e8b1 +	ret + +; checks if the tile in front of the player is a shore or water tile +; used for surfing and fishing +; unsets carry if it is, sets carry if not +IsNextTileShoreOrWater: ; e8b8 (3:68b8) +	ld a, [W_CURMAPTILESET] +	ld hl, WaterTilesets +	ld de,1 +	call IsInArray ; does the current map allow surfing? +	ret nc ; if not, return +	ld hl,WaterTile +	ld a, [W_CURMAPTILESET] +	cp SHIP_PORT ; Vermilion Dock tileset +	jr z, .skipShoreTiles ; if it's the Vermilion Dock tileset +	cp GYM ; eastern shore tile in Safari Zone +	jr z, .skipShoreTiles +	cp DOJO ; usual eastern shore tile +	jr z, .skipShoreTiles +	ld hl,ShoreTiles +.skipShoreTiles +	ld a,[wTileInFrontOfPlayer] +	ld de,$1 +	call IsInArray +	ret + +; tilesets with water +WaterTilesets: ; e834 (3:6834) +	db OVERWORLD, FOREST, DOJO, GYM, SHIP, SHIP_PORT, CAVERN, FACILITY, PLATEAU +	db $ff ; terminator + +; shore tiles +ShoreTiles: ; e83e (3:683e) +	db $48, $32 +WaterTile: ; e840 (3:6840) +	db $14 +	db $ff ; terminator + +ReadSuperRodData: ; e8ea (3:68ea) +; return e = 2 if no fish on this map +; return e = 1 if a bite, bc = level,species +; return e = 0 if no bite +	ld a, [W_CURMAP] +	ld de, 3 ; each fishing group is three bytes wide +	ld hl, SuperRodData +	call IsInArray +	jr c, .ReadFishingGroup +	ld e, $2 ; $2 if no fishing groups found +	ret + +.ReadFishingGroup ; 0xe8f6 +; hl points to the fishing group entry in the index +	inc hl ; skip map id + +	; read fishing group address +	ld a, [hli] +	ld h, [hl] +	ld l, a + +	ld b, [hl] ; how many mons in group +	inc hl ; point to data +	ld e, $0 ; no bite yet + +.RandomLoop ; 0xe90c +	call Random +	srl a +	ret c ; 50% chance of no battle + +	and %11 ; 2-bit random number +	cp b +	jr nc, .RandomLoop ; if a is greater than the number of mons, regenerate + +	; get the mon +	add a +	ld c, a +	ld b, $0 +	add hl, bc +	ld b, [hl] ; level +	inc hl +	ld c, [hl] ; species +	ld e, $1 ; $1 if there's a bite +	ret + +INCLUDE "data/super_rod.asm" + +; reloads map view and processes sprite data +; for items that cause the overworld to be displayed +ItemUseReloadOverworldData: ; e9c5 (3:69c5) +	call LoadCurrentMapView +	jp UpdateSprites + +; creates a list at wBuffer of maps where the mon in [wd11e] can be found. +; this is used by the pokedex to display locations the mon can be found on the map. +FindWildLocationsOfMon: ; e9cb (3:69cb) +	ld hl, WildDataPointers +	ld de, wBuffer +	ld c, $0 +.loop +	inc hl +	ld a, [hld] +	inc a +	jr z, .done +	push hl +	ld a, [hli] +	ld h, [hl] +	ld l, a +	ld a, [hli] +	and a +	call nz, CheckMapForMon ; land +	ld a, [hli] +	and a +	call nz, CheckMapForMon ; water +	pop hl +	inc hl +	inc hl +	inc c +	jr .loop +.done +	ld a, $ff ; list terminator +	ld [de], a +	ret + +CheckMapForMon: ; e9f0 (3:69f0) +	inc hl +	ld b, $a +.loop +	ld a, [wd11e] +	cp [hl] +	jr nz, .nextEntry +	ld a, c +	ld [de], a +	inc de +.nextEntry +	inc hl +	inc hl +	dec b +	jr nz, .loop +	dec hl +	ret diff --git a/engine/overworld/map_sprites.asm b/engine/overworld/map_sprites.asm index 54312c6f..747a0a45 100755 --- a/engine/overworld/map_sprites.asm +++ b/engine/overworld/map_sprites.asm @@ -1,440 +1,440 @@ -; Loads tile patterns for map's sprites.
 -; For outside maps, it loads one of several fixed sets of sprites.
 -; For inside maps, it loads each sprite picture ID used in the map header.
 -; This is also called after displaying text because loading
 -; text tile patterns overwrites half of the sprite tile pattern data.
 -; Note on notation:
 -; $C1X* and $C2X* are used to denote wSpriteStateData1-wSpriteStateData1 + $ff and wSpriteStateData2 + $00-wSpriteStateData2 + $ff sprite slot
 -; fields, respectively, within loops. The X is the loop index.
 -; If there is an inner loop, Y is the inner loop index, i.e. $C1Y* and $C2Y*
 -; denote fields of the sprite slots interated over in the inner loop.
 -_InitMapSprites: ; 1785b (5:785b)
 -	call InitOutsideMapSprites
 -	ret c ; return if the map is an outside map (already handled by above call)
 -; if the map is an inside map (i.e. mapID >= $25)
 -	ld hl,wSpriteStateData1
 -	ld de,wSpriteStateData2 + $0d
 -; Loop to copy picture ID's from $C1X0 to $C2XD for LoadMapSpriteTilePatterns.
 -.copyPictureIDLoop
 -	ld a,[hl] ; $C1X0 (picture ID)
 -	ld [de],a ; $C2XD
 -	ld a,$10
 -	add e
 -	ld e,a
 -	ld a,$10
 -	add l
 -	ld l,a
 -	jr nz,.copyPictureIDLoop
 -
 -; This is used for both inside and outside maps, since it is called by
 -; InitOutsideMapSprites.
 -; Loads tile pattern data for sprites into VRAM.
 -LoadMapSpriteTilePatterns: ; 17871 (5:7871)
 -	ld a,[W_NUMSPRITES]
 -	and a ; are there any sprites?
 -	jr nz,.spritesExist
 -	ret
 -.spritesExist
 -	ld c,a ; c = [W_NUMSPRITES]
 -	ld b,$10 ; number of sprite slots
 -	ld hl,wSpriteStateData2 + $0d
 -	xor a
 -	ld [$ff8e],a ; 4-tile sprite counter
 -.copyPictureIDLoop ; loop to copy picture ID from $C2XD to $C2XE
 -	ld a,[hli] ; $C2XD (sprite picture ID)
 -	ld [hld],a ; $C2XE
 -	ld a,l
 -	add a,$10
 -	ld l,a
 -	dec b
 -	jr nz,.copyPictureIDLoop
 -	ld hl,wSpriteStateData2 + $1e
 -.loadTilePatternLoop
 -	ld de,wSpriteStateData2 + $1d
 -; Check if the current picture ID has already had its tile patterns loaded.
 -; This done by looping through the previous sprite slots and seeing if any of
 -; their picture ID's match that of the current sprite slot.
 -.checkIfAlreadyLoadedLoop
 -	ld a,e
 -	and a,$f0
 -	ld b,a ; b = offset of the wSpriteStateData2 sprite slot being checked against
 -	ld a,l
 -	and a,$f0 ; a = offset of current wSpriteStateData2 sprite slot
 -	cp b ; done checking all previous sprite slots?
 -	jr z,.notAlreadyLoaded
 -	ld a,[de] ; picture ID of the wSpriteStateData2 sprite slot being checked against
 -	cp [hl] ; do the picture ID's match?
 -	jp z,.alreadyLoaded
 -	ld a,e
 -	add a,$10
 -	ld e,a
 -	jr .checkIfAlreadyLoadedLoop
 -.notAlreadyLoaded
 -	ld de,wSpriteStateData2 + $0e
 -	ld b,$01
 -; loop to find the highest tile pattern VRAM slot (among the first 10 slots) used by a previous sprite slot
 -; this is done in order to find the first free VRAM slot available
 -.findNextVRAMSlotLoop
 -	ld a,e
 -	add a,$10
 -	ld e,a
 -	ld a,l
 -	cp e ; reached current slot?
 -	jr z,.foundNextVRAMSlot
 -	ld a,[de] ; $C2YE (VRAM slot)
 -	cp a,11 ; is it one of the first 10 slots?
 -	jr nc,.findNextVRAMSlotLoop
 -	cp b ; compare the slot being checked to the current max
 -	jr c,.findNextVRAMSlotLoop ; if the slot being checked is less than the current max
 -; if the slot being checked is greater than or equal to the current max
 -	ld b,a ; store new max VRAM slot
 -	jr .findNextVRAMSlotLoop
 -.foundNextVRAMSlot
 -	inc b ; increment previous max value to get next VRAM tile pattern slot
 -	ld a,b ; a = next VRAM tile pattern slot
 -	push af
 -	ld a,[hl] ; $C2XE (sprite picture ID)
 -	ld b,a ; b = current sprite picture ID
 -	cp a,SPRITE_BALL ; is it a 4-tile sprite?
 -	jr c,.notFourTileSprite
 -	pop af
 -	ld a,[$ff8e] ; 4-tile sprite counter
 -	add a,11
 -	jr .storeVRAMSlot
 -.notFourTileSprite
 -	pop af
 -.storeVRAMSlot
 -	ld [hl],a ; store VRAM slot at $C2XE
 -	ld [$ff8d],a ; used to determine if it's 4-tile sprite later
 -	ld a,b ; a = current sprite picture ID
 -	dec a
 -	add a
 -	add a
 -	push bc
 -	push hl
 -	ld hl,SpriteSheetPointerTable
 -	jr nc,.noCarry
 -	inc h
 -.noCarry
 -	add l
 -	ld l,a
 -	jr nc,.noCarry2
 -	inc h
 -.noCarry2
 -	push hl
 -	call ReadSpriteSheetData
 -	push af
 -	push de
 -	push bc
 -	ld hl,vNPCSprites ; VRAM base address
 -	ld bc,$c0 ; number of bytes per VRAM slot
 -	ld a,[$ff8d]
 -	cp a,11 ; is it a 4-tile sprite?
 -	jr nc,.fourTileSpriteVRAMAddr
 -	ld d,a
 -	dec d
 -; Equivalent to multiplying $C0 (number of bytes in 12 tiles) times the VRAM
 -; slot and adding the result to $8000 (the VRAM base address).
 -.calculateVRAMAddrLoop
 -	add hl,bc
 -	dec d
 -	jr nz,.calculateVRAMAddrLoop
 -	jr .loadStillTilePattern
 -.fourTileSpriteVRAMAddr
 -	ld hl,vSprites + $7c0 ; address for second 4-tile sprite
 -	ld a,[$ff8e] ; 4-tile sprite counter
 -	and a ; is it the first 4-tile sprite?
 -	jr nz,.loadStillTilePattern
 -; if it's the first 4-tile sprite
 -	ld hl,vSprites + $780 ; address for first 4-tile sprite
 -	inc a
 -	ld [$ff8e],a ; 4-tile sprite counter
 -.loadStillTilePattern
 -	pop bc
 -	pop de
 -	pop af
 -	push hl
 -	push hl
 -	ld h,d
 -	ld l,e
 -	pop de
 -	ld b,a
 -	ld a,[wFontLoaded]
 -	bit 0,a ; reloading upper half of tile patterns after displaying text?
 -	jr nz,.skipFirstLoad ; if so, skip loading data into the lower half
 -	ld a,b
 -	ld b,0
 -	call FarCopyData2 ; load tile pattern data for sprite when standing still
 -.skipFirstLoad
 -	pop de
 -	pop hl
 -	ld a,[$ff8d]
 -	cp a,11 ; is it a 4-tile sprite?
 -	jr nc,.skipSecondLoad ; if so, there is no second block
 -	push de
 -	call ReadSpriteSheetData
 -	push af
 -	ld a,$c0
 -	add e
 -	ld e,a
 -	jr nc,.noCarry3
 -	inc d
 -.noCarry3
 -	ld a,[wFontLoaded]
 -	bit 0,a ; reloading upper half of tile patterns after displaying text?
 -	jr nz,.loadWhileLCDOn
 -	pop af
 -	pop hl
 -	set 3,h ; add $800 to hl
 -	push hl
 -	ld h,d
 -	ld l,e
 -	pop de
 -	call FarCopyData2 ; load tile pattern data for sprite when walking
 -	jr .skipSecondLoad
 -; When reloading the upper half of tile patterns after diplaying text, the LCD
 -; will be on, so CopyVideoData (which writes to VRAM only during V-blank) must
 -; be used instead of FarCopyData2.
 -.loadWhileLCDOn
 -	pop af
 -	pop hl
 -	set 3,h ; add $800 to hl
 -	ld b,a
 -	swap c
 -	call CopyVideoData ; load tile pattern data for sprite when walking
 -.skipSecondLoad
 -	pop hl
 -	pop bc
 -	jr .nextSpriteSlot
 -.alreadyLoaded ; if the current picture ID has already had its tile patterns loaded
 -	inc de
 -	ld a,[de] ; a = VRAM slot for the current picture ID (from $C2YE)
 -	ld [hl],a ; store VRAM slot in current wSpriteStateData2 sprite slot (at $C2XE)
 -.nextSpriteSlot
 -	ld a,l
 -	add a,$10
 -	ld l,a
 -	dec c
 -	jp nz,.loadTilePatternLoop
 -	ld hl,wSpriteStateData2 + $0d
 -	ld b,$10
 -; the pictures ID's stored at $C2XD are no longer needed, so zero them
 -.zeroStoredPictureIDLoop
 -	xor a
 -	ld [hl],a ; $C2XD
 -	ld a,$10
 -	add l
 -	ld l,a
 -	dec b
 -	jr nz,.zeroStoredPictureIDLoop
 -	ret
 -
 -; reads data from SpriteSheetPointerTable
 -; INPUT:
 -; hl = address of sprite sheet entry
 -; OUTPUT:
 -; de = pointer to sprite sheet
 -; bc = length in bytes
 -; a = ROM bank
 -ReadSpriteSheetData: ; 17971 (5:7971)
 -	ld a,[hli]
 -	ld e,a
 -	ld a,[hli]
 -	ld d,a
 -	ld a,[hli]
 -	ld c,a
 -	xor a
 -	ld b,a
 -	ld a,[hli]
 -	ret
 -
 -; Loads sprite set for outside maps (cities and routes) and sets VRAM slots.
 -; sets carry if the map is a city or route, unsets carry if not
 -InitOutsideMapSprites: ; 1797b (5:797b)
 -	ld a,[W_CURMAP]
 -	cp a,REDS_HOUSE_1F ; is the map a city or a route (map ID less than $25)?
 -	ret nc ; if not, return
 -	ld hl,MapSpriteSets
 -	add l
 -	ld l,a
 -	jr nc,.noCarry
 -	inc h
 -.noCarry
 -	ld a,[hl] ; a = spriteSetID
 -	cp a,$f0 ; does the map have 2 sprite sets?
 -	call nc,GetSplitMapSpriteSetID ; if so, choose the appropriate one
 -	ld b,a ; b = spriteSetID
 -	ld a,[wFontLoaded]
 -	bit 0,a ; reloading upper half of tile patterns after displaying text?
 -	jr nz,.loadSpriteSet ; if so, forcibly reload the sprite set
 -	ld a,[W_SPRITESETID]
 -	cp b ; has the sprite set ID changed?
 -	jr z,.skipLoadingSpriteSet ; if not, don't load it again
 -.loadSpriteSet
 -	ld a,b
 -	ld [W_SPRITESETID],a
 -	dec a
 -	ld b,a
 -	sla a
 -	ld c,a
 -	sla a
 -	sla a
 -	add c
 -	add b ; a = (spriteSetID - 1) * 11
 -	ld de,SpriteSets
 -; add a to de to get offset of sprite set
 -	add e
 -	ld e,a
 -	jr nc,.noCarry2
 -	inc d
 -.noCarry2
 -	ld hl,wSpriteStateData2 + $0d
 -	ld a,SPRITE_RED
 -	ld [hl],a
 -	ld bc,W_SPRITESET
 -; Load the sprite set into RAM.
 -; This loop also fills $C2XD (sprite picture ID) where X is from $0 to $A
 -; with picture ID's. This is done so that LoadMapSpriteTilePatterns will
 -; load tile patterns for all sprite pictures in the sprite set.
 -.loadSpriteSetLoop
 -	ld a,$10
 -	add l
 -	ld l,a
 -	ld a,[de] ; sprite picture ID from sprite set
 -	ld [hl],a ; $C2XD (sprite picture ID)
 -	ld [bc],a
 -	inc de
 -	inc bc
 -	ld a,l
 -	cp a,$bd ; reached 11th sprite slot?
 -	jr nz,.loadSpriteSetLoop
 -	ld b,4 ; 4 remaining sprite slots
 -.zeroRemainingSlotsLoop ; loop to zero the picture ID's of the remaining sprite slots
 -	ld a,$10
 -	add l
 -	ld l,a
 -	xor a
 -	ld [hl],a ; $C2XD (sprite picture ID)
 -	dec b
 -	jr nz,.zeroRemainingSlotsLoop
 -	ld a,[W_NUMSPRITES]
 -	push af ; save number of sprites
 -	ld a,11 ; 11 sprites in sprite set
 -	ld [W_NUMSPRITES],a
 -	call LoadMapSpriteTilePatterns
 -	pop af
 -	ld [W_NUMSPRITES],a ; restore number of sprites
 -	ld hl,wSpriteStateData2 + $1e
 -	ld b,$0f
 -; The VRAM tile pattern slots that LoadMapSpriteTilePatterns set are in the
 -; order of the map's sprite set, not the order of the actual sprites loaded
 -; for the current map. So, they are not needed and are zeroed by this loop.
 -.zeroVRAMSlotsLoop
 -	xor a
 -	ld [hl],a ; $C2XE (VRAM slot)
 -	ld a,$10
 -	add l
 -	ld l,a
 -	dec b
 -	jr nz,.zeroVRAMSlotsLoop
 -.skipLoadingSpriteSet
 -	ld hl,wSpriteStateData1 + $10
 -; This loop stores the correct VRAM tile pattern slots according the sprite
 -; data from the map's header. Since the VRAM tile pattern slots are filled in
 -; the order of the sprite set, in order to find the VRAM tile pattern slot
 -; for a sprite slot, the picture ID for the sprite is looked up within the
 -; sprite set. The index of the picture ID within the sprite set plus one
 -; (since the Red sprite always has the first VRAM tile pattern slot) is the
 -; VRAM tile pattern slot.
 -.storeVRAMSlotsLoop
 -	ld c,0
 -	ld a,[hl] ; $C1X0 (picture ID) (zero if sprite slot is not used)
 -	and a ; is the sprite slot used?
 -	jr z,.skipGettingPictureIndex ; if the sprite slot is not used
 -	ld b,a ; b = picture ID
 -	ld de,W_SPRITESET
 -; Loop to find the index of the sprite's picture ID within the sprite set.
 -.getPictureIndexLoop
 -	inc c
 -	ld a,[de]
 -	inc de
 -	cp b ; does the picture ID match?
 -	jr nz,.getPictureIndexLoop
 -	inc c
 -.skipGettingPictureIndex
 -	push hl
 -	inc h
 -	ld a,$0e
 -	add l
 -	ld l,a
 -	ld a,c ; a = VRAM slot (zero if sprite slot is not used)
 -	ld [hl],a ; $C2XE (VRAM slot)
 -	pop hl
 -	ld a,$10
 -	add l
 -	ld l,a
 -	and a
 -	jr nz,.storeVRAMSlotsLoop
 -	scf
 -	ret
 -
 -; Chooses the correct sprite set ID depending on the player's position within
 -; the map for maps with two sprite sets.
 -GetSplitMapSpriteSetID: ; 17a1a (5:7a1a)
 -	cp a,$f8
 -	jr z,.route20
 -	ld hl,SplitMapSpriteSets
 -	and a,$0f
 -	dec a
 -	sla a
 -	sla a
 -	add l
 -	ld l,a
 -	jr nc,.noCarry
 -	inc h
 -.noCarry
 -	ld a,[hli] ; determines whether the map is split East/West or North/South
 -	cp a,$01
 -	ld a,[hli] ; position of dividing line
 -	ld b,a
 -	jr z,.eastWestDivide
 -.northSouthDivide
 -	ld a,[W_YCOORD]
 -	jr .compareCoord
 -.eastWestDivide
 -	ld a,[W_XCOORD]
 -.compareCoord
 -	cp b
 -	jr c,.loadSpriteSetID
 -; if in the East side or South side
 -	inc hl
 -.loadSpriteSetID
 -	ld a,[hl]
 -	ret
 -; Uses sprite set $01 for West side and $0A for East side.
 -; Route 20 is a special case because the two map sections have a more complex
 -; shape instead of the map simply being split horizontally or vertically.
 -.route20
 -	ld hl,W_XCOORD
 -	ld a,[hl]
 -	cp a,$2b
 -	ld a,$01
 -	ret c
 -	ld a,[hl]
 -	cp a,$3e
 -	ld a,$0a
 -	ret nc
 -	ld a,[hl]
 -	cp a,$37
 -	ld b,$08
 -	jr nc,.next
 -	ld b,$0d
 -.next
 -	ld a,[W_YCOORD]
 -	cp b
 -	ld a,$0a
 -	ret c
 -	ld a,$01
 -	ret
 -
 -INCLUDE "data/sprite_sets.asm"
 +; Loads tile patterns for map's sprites. +; For outside maps, it loads one of several fixed sets of sprites. +; For inside maps, it loads each sprite picture ID used in the map header. +; This is also called after displaying text because loading +; text tile patterns overwrites half of the sprite tile pattern data. +; Note on notation: +; $C1X* and $C2X* are used to denote wSpriteStateData1-wSpriteStateData1 + $ff and wSpriteStateData2 + $00-wSpriteStateData2 + $ff sprite slot +; fields, respectively, within loops. The X is the loop index. +; If there is an inner loop, Y is the inner loop index, i.e. $C1Y* and $C2Y* +; denote fields of the sprite slots interated over in the inner loop. +_InitMapSprites: ; 1785b (5:785b) +	call InitOutsideMapSprites +	ret c ; return if the map is an outside map (already handled by above call) +; if the map is an inside map (i.e. mapID >= $25) +	ld hl,wSpriteStateData1 +	ld de,wSpriteStateData2 + $0d +; Loop to copy picture ID's from $C1X0 to $C2XD for LoadMapSpriteTilePatterns. +.copyPictureIDLoop +	ld a,[hl] ; $C1X0 (picture ID) +	ld [de],a ; $C2XD +	ld a,$10 +	add e +	ld e,a +	ld a,$10 +	add l +	ld l,a +	jr nz,.copyPictureIDLoop + +; This is used for both inside and outside maps, since it is called by +; InitOutsideMapSprites. +; Loads tile pattern data for sprites into VRAM. +LoadMapSpriteTilePatterns: ; 17871 (5:7871) +	ld a,[W_NUMSPRITES] +	and a ; are there any sprites? +	jr nz,.spritesExist +	ret +.spritesExist +	ld c,a ; c = [W_NUMSPRITES] +	ld b,$10 ; number of sprite slots +	ld hl,wSpriteStateData2 + $0d +	xor a +	ld [$ff8e],a ; 4-tile sprite counter +.copyPictureIDLoop ; loop to copy picture ID from $C2XD to $C2XE +	ld a,[hli] ; $C2XD (sprite picture ID) +	ld [hld],a ; $C2XE +	ld a,l +	add a,$10 +	ld l,a +	dec b +	jr nz,.copyPictureIDLoop +	ld hl,wSpriteStateData2 + $1e +.loadTilePatternLoop +	ld de,wSpriteStateData2 + $1d +; Check if the current picture ID has already had its tile patterns loaded. +; This done by looping through the previous sprite slots and seeing if any of +; their picture ID's match that of the current sprite slot. +.checkIfAlreadyLoadedLoop +	ld a,e +	and a,$f0 +	ld b,a ; b = offset of the wSpriteStateData2 sprite slot being checked against +	ld a,l +	and a,$f0 ; a = offset of current wSpriteStateData2 sprite slot +	cp b ; done checking all previous sprite slots? +	jr z,.notAlreadyLoaded +	ld a,[de] ; picture ID of the wSpriteStateData2 sprite slot being checked against +	cp [hl] ; do the picture ID's match? +	jp z,.alreadyLoaded +	ld a,e +	add a,$10 +	ld e,a +	jr .checkIfAlreadyLoadedLoop +.notAlreadyLoaded +	ld de,wSpriteStateData2 + $0e +	ld b,$01 +; loop to find the highest tile pattern VRAM slot (among the first 10 slots) used by a previous sprite slot +; this is done in order to find the first free VRAM slot available +.findNextVRAMSlotLoop +	ld a,e +	add a,$10 +	ld e,a +	ld a,l +	cp e ; reached current slot? +	jr z,.foundNextVRAMSlot +	ld a,[de] ; $C2YE (VRAM slot) +	cp a,11 ; is it one of the first 10 slots? +	jr nc,.findNextVRAMSlotLoop +	cp b ; compare the slot being checked to the current max +	jr c,.findNextVRAMSlotLoop ; if the slot being checked is less than the current max +; if the slot being checked is greater than or equal to the current max +	ld b,a ; store new max VRAM slot +	jr .findNextVRAMSlotLoop +.foundNextVRAMSlot +	inc b ; increment previous max value to get next VRAM tile pattern slot +	ld a,b ; a = next VRAM tile pattern slot +	push af +	ld a,[hl] ; $C2XE (sprite picture ID) +	ld b,a ; b = current sprite picture ID +	cp a,SPRITE_BALL ; is it a 4-tile sprite? +	jr c,.notFourTileSprite +	pop af +	ld a,[$ff8e] ; 4-tile sprite counter +	add a,11 +	jr .storeVRAMSlot +.notFourTileSprite +	pop af +.storeVRAMSlot +	ld [hl],a ; store VRAM slot at $C2XE +	ld [$ff8d],a ; used to determine if it's 4-tile sprite later +	ld a,b ; a = current sprite picture ID +	dec a +	add a +	add a +	push bc +	push hl +	ld hl,SpriteSheetPointerTable +	jr nc,.noCarry +	inc h +.noCarry +	add l +	ld l,a +	jr nc,.noCarry2 +	inc h +.noCarry2 +	push hl +	call ReadSpriteSheetData +	push af +	push de +	push bc +	ld hl,vNPCSprites ; VRAM base address +	ld bc,$c0 ; number of bytes per VRAM slot +	ld a,[$ff8d] +	cp a,11 ; is it a 4-tile sprite? +	jr nc,.fourTileSpriteVRAMAddr +	ld d,a +	dec d +; Equivalent to multiplying $C0 (number of bytes in 12 tiles) times the VRAM +; slot and adding the result to $8000 (the VRAM base address). +.calculateVRAMAddrLoop +	add hl,bc +	dec d +	jr nz,.calculateVRAMAddrLoop +	jr .loadStillTilePattern +.fourTileSpriteVRAMAddr +	ld hl,vSprites + $7c0 ; address for second 4-tile sprite +	ld a,[$ff8e] ; 4-tile sprite counter +	and a ; is it the first 4-tile sprite? +	jr nz,.loadStillTilePattern +; if it's the first 4-tile sprite +	ld hl,vSprites + $780 ; address for first 4-tile sprite +	inc a +	ld [$ff8e],a ; 4-tile sprite counter +.loadStillTilePattern +	pop bc +	pop de +	pop af +	push hl +	push hl +	ld h,d +	ld l,e +	pop de +	ld b,a +	ld a,[wFontLoaded] +	bit 0,a ; reloading upper half of tile patterns after displaying text? +	jr nz,.skipFirstLoad ; if so, skip loading data into the lower half +	ld a,b +	ld b,0 +	call FarCopyData2 ; load tile pattern data for sprite when standing still +.skipFirstLoad +	pop de +	pop hl +	ld a,[$ff8d] +	cp a,11 ; is it a 4-tile sprite? +	jr nc,.skipSecondLoad ; if so, there is no second block +	push de +	call ReadSpriteSheetData +	push af +	ld a,$c0 +	add e +	ld e,a +	jr nc,.noCarry3 +	inc d +.noCarry3 +	ld a,[wFontLoaded] +	bit 0,a ; reloading upper half of tile patterns after displaying text? +	jr nz,.loadWhileLCDOn +	pop af +	pop hl +	set 3,h ; add $800 to hl +	push hl +	ld h,d +	ld l,e +	pop de +	call FarCopyData2 ; load tile pattern data for sprite when walking +	jr .skipSecondLoad +; When reloading the upper half of tile patterns after diplaying text, the LCD +; will be on, so CopyVideoData (which writes to VRAM only during V-blank) must +; be used instead of FarCopyData2. +.loadWhileLCDOn +	pop af +	pop hl +	set 3,h ; add $800 to hl +	ld b,a +	swap c +	call CopyVideoData ; load tile pattern data for sprite when walking +.skipSecondLoad +	pop hl +	pop bc +	jr .nextSpriteSlot +.alreadyLoaded ; if the current picture ID has already had its tile patterns loaded +	inc de +	ld a,[de] ; a = VRAM slot for the current picture ID (from $C2YE) +	ld [hl],a ; store VRAM slot in current wSpriteStateData2 sprite slot (at $C2XE) +.nextSpriteSlot +	ld a,l +	add a,$10 +	ld l,a +	dec c +	jp nz,.loadTilePatternLoop +	ld hl,wSpriteStateData2 + $0d +	ld b,$10 +; the pictures ID's stored at $C2XD are no longer needed, so zero them +.zeroStoredPictureIDLoop +	xor a +	ld [hl],a ; $C2XD +	ld a,$10 +	add l +	ld l,a +	dec b +	jr nz,.zeroStoredPictureIDLoop +	ret + +; reads data from SpriteSheetPointerTable +; INPUT: +; hl = address of sprite sheet entry +; OUTPUT: +; de = pointer to sprite sheet +; bc = length in bytes +; a = ROM bank +ReadSpriteSheetData: ; 17971 (5:7971) +	ld a,[hli] +	ld e,a +	ld a,[hli] +	ld d,a +	ld a,[hli] +	ld c,a +	xor a +	ld b,a +	ld a,[hli] +	ret + +; Loads sprite set for outside maps (cities and routes) and sets VRAM slots. +; sets carry if the map is a city or route, unsets carry if not +InitOutsideMapSprites: ; 1797b (5:797b) +	ld a,[W_CURMAP] +	cp a,REDS_HOUSE_1F ; is the map a city or a route (map ID less than $25)? +	ret nc ; if not, return +	ld hl,MapSpriteSets +	add l +	ld l,a +	jr nc,.noCarry +	inc h +.noCarry +	ld a,[hl] ; a = spriteSetID +	cp a,$f0 ; does the map have 2 sprite sets? +	call nc,GetSplitMapSpriteSetID ; if so, choose the appropriate one +	ld b,a ; b = spriteSetID +	ld a,[wFontLoaded] +	bit 0,a ; reloading upper half of tile patterns after displaying text? +	jr nz,.loadSpriteSet ; if so, forcibly reload the sprite set +	ld a,[W_SPRITESETID] +	cp b ; has the sprite set ID changed? +	jr z,.skipLoadingSpriteSet ; if not, don't load it again +.loadSpriteSet +	ld a,b +	ld [W_SPRITESETID],a +	dec a +	ld b,a +	sla a +	ld c,a +	sla a +	sla a +	add c +	add b ; a = (spriteSetID - 1) * 11 +	ld de,SpriteSets +; add a to de to get offset of sprite set +	add e +	ld e,a +	jr nc,.noCarry2 +	inc d +.noCarry2 +	ld hl,wSpriteStateData2 + $0d +	ld a,SPRITE_RED +	ld [hl],a +	ld bc,W_SPRITESET +; Load the sprite set into RAM. +; This loop also fills $C2XD (sprite picture ID) where X is from $0 to $A +; with picture ID's. This is done so that LoadMapSpriteTilePatterns will +; load tile patterns for all sprite pictures in the sprite set. +.loadSpriteSetLoop +	ld a,$10 +	add l +	ld l,a +	ld a,[de] ; sprite picture ID from sprite set +	ld [hl],a ; $C2XD (sprite picture ID) +	ld [bc],a +	inc de +	inc bc +	ld a,l +	cp a,$bd ; reached 11th sprite slot? +	jr nz,.loadSpriteSetLoop +	ld b,4 ; 4 remaining sprite slots +.zeroRemainingSlotsLoop ; loop to zero the picture ID's of the remaining sprite slots +	ld a,$10 +	add l +	ld l,a +	xor a +	ld [hl],a ; $C2XD (sprite picture ID) +	dec b +	jr nz,.zeroRemainingSlotsLoop +	ld a,[W_NUMSPRITES] +	push af ; save number of sprites +	ld a,11 ; 11 sprites in sprite set +	ld [W_NUMSPRITES],a +	call LoadMapSpriteTilePatterns +	pop af +	ld [W_NUMSPRITES],a ; restore number of sprites +	ld hl,wSpriteStateData2 + $1e +	ld b,$0f +; The VRAM tile pattern slots that LoadMapSpriteTilePatterns set are in the +; order of the map's sprite set, not the order of the actual sprites loaded +; for the current map. So, they are not needed and are zeroed by this loop. +.zeroVRAMSlotsLoop +	xor a +	ld [hl],a ; $C2XE (VRAM slot) +	ld a,$10 +	add l +	ld l,a +	dec b +	jr nz,.zeroVRAMSlotsLoop +.skipLoadingSpriteSet +	ld hl,wSpriteStateData1 + $10 +; This loop stores the correct VRAM tile pattern slots according the sprite +; data from the map's header. Since the VRAM tile pattern slots are filled in +; the order of the sprite set, in order to find the VRAM tile pattern slot +; for a sprite slot, the picture ID for the sprite is looked up within the +; sprite set. The index of the picture ID within the sprite set plus one +; (since the Red sprite always has the first VRAM tile pattern slot) is the +; VRAM tile pattern slot. +.storeVRAMSlotsLoop +	ld c,0 +	ld a,[hl] ; $C1X0 (picture ID) (zero if sprite slot is not used) +	and a ; is the sprite slot used? +	jr z,.skipGettingPictureIndex ; if the sprite slot is not used +	ld b,a ; b = picture ID +	ld de,W_SPRITESET +; Loop to find the index of the sprite's picture ID within the sprite set. +.getPictureIndexLoop +	inc c +	ld a,[de] +	inc de +	cp b ; does the picture ID match? +	jr nz,.getPictureIndexLoop +	inc c +.skipGettingPictureIndex +	push hl +	inc h +	ld a,$0e +	add l +	ld l,a +	ld a,c ; a = VRAM slot (zero if sprite slot is not used) +	ld [hl],a ; $C2XE (VRAM slot) +	pop hl +	ld a,$10 +	add l +	ld l,a +	and a +	jr nz,.storeVRAMSlotsLoop +	scf +	ret + +; Chooses the correct sprite set ID depending on the player's position within +; the map for maps with two sprite sets. +GetSplitMapSpriteSetID: ; 17a1a (5:7a1a) +	cp a,$f8 +	jr z,.route20 +	ld hl,SplitMapSpriteSets +	and a,$0f +	dec a +	sla a +	sla a +	add l +	ld l,a +	jr nc,.noCarry +	inc h +.noCarry +	ld a,[hli] ; determines whether the map is split East/West or North/South +	cp a,$01 +	ld a,[hli] ; position of dividing line +	ld b,a +	jr z,.eastWestDivide +.northSouthDivide +	ld a,[W_YCOORD] +	jr .compareCoord +.eastWestDivide +	ld a,[W_XCOORD] +.compareCoord +	cp b +	jr c,.loadSpriteSetID +; if in the East side or South side +	inc hl +.loadSpriteSetID +	ld a,[hl] +	ret +; Uses sprite set $01 for West side and $0A for East side. +; Route 20 is a special case because the two map sections have a more complex +; shape instead of the map simply being split horizontally or vertically. +.route20 +	ld hl,W_XCOORD +	ld a,[hl] +	cp a,$2b +	ld a,$01 +	ret c +	ld a,[hl] +	cp a,$3e +	ld a,$0a +	ret nc +	ld a,[hl] +	cp a,$37 +	ld b,$08 +	jr nc,.next +	ld b,$0d +.next +	ld a,[W_YCOORD] +	cp b +	ld a,$0a +	ret c +	ld a,$01 +	ret + +INCLUDE "data/sprite_sets.asm" | 
